X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fnew_dynarec.c;h=69e829f98565a927fada448f01c9ede2f87f80a1;hp=88c059aba139ab895a85e40508861db83802818e;hb=a64911708df86674a7a64e42782bf467abe9f0aa;hpb=1fd1aceb4382827b39bda6fe6915e38a294534e6 diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 88c059ab..69e829f9 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -179,6 +179,7 @@ struct ll_entry #define COP2 27 // Coprocessor 2 move #define C2LS 28 // Coprocessor 2 load/store #define C2OP 29 // Coprocessor 2 operation +#define INTCALL 30// Call interpreter to handle rare corner cases /* stubs */ #define CC_STUB 1 @@ -220,6 +221,7 @@ void jump_syscall(); void jump_syscall_hle(); void jump_eret(); void jump_hlecall(); +void jump_intcall(); void new_dyna_leave(); // TLB @@ -408,7 +410,7 @@ void *get_addr_32(u_int vaddr,u_int flags) { #ifdef FORCE32 return get_addr(vaddr); -#endif +#else //printf("TRACE: count=%d next=%d (get_addr_32 %x,flags %x)\n",Count,next_interupt,vaddr,flags); int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; if(ht_bin[0]==vaddr) return (void *)ht_bin[1]; @@ -488,6 +490,7 @@ void *get_addr_32(u_int vaddr,u_int flags) Context=(Context&0xFF80000F)|((BadVAddr>>9)&0x007FFFF0); EntryHi=BadVAddr&0xFFFFE000; return get_addr_ht(0x80000000); +#endif } void clear_all_regs(signed char regmap[]) @@ -726,7 +729,7 @@ int needed_again(int r, int i) j++; break; } - if(itype[i+j]==SYSCALL||itype[i+j]==HLECALL||((source[i+j]&0xfc00003f)==0x0d)) + if(itype[i+j]==SYSCALL||itype[i+j]==HLECALL||itype[i+j]==INTCALL||((source[i+j]&0xfc00003f)==0x0d)) { break; } @@ -1083,7 +1086,7 @@ void ll_kill_pointers(struct ll_entry *head,int addr,int shift) if(((ptr>>shift)==(addr>>shift)) || (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift))) { - printf("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr); + inv_debug("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr); u_int host_addr=(u_int)kill_pointer(head->addr); if((host_addr>>12)!=(old_host_addr>>12)) { @@ -2753,17 +2756,17 @@ void load_assemble(int i,struct regstat *i_regs) //if(c) printf("load_assemble: const=%x\n",(int)constmap[i][s]+offset); // FIXME: Even if the load is a NOP, we should check for pagefaults... #ifdef PCSX - if(tl<0) { - if(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80) { + if(tl<0&&(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80) + ||rt1[i]==0) { // could be FIFO, must perform the read + // ||dummy read assem_debug("(forced read)\n"); tl=get_reg(i_regs->regmap,-1); assert(tl>=0); - } } +#endif if(offset||s<0||c) addr=tl; else addr=s; -#endif if(tl>=0) { //assert(tl>=0); //assert(rt1[i]); @@ -3691,7 +3694,7 @@ void mov_assemble(int i,struct regstat *i_regs) { //if(opcode2[i]==0x10||opcode2[i]==0x12) { // MFHI/MFLO //if(opcode2[i]==0x11||opcode2[i]==0x13) { // MTHI/MTLO - assert(rt1[i]>0); + //assert(rt1[i]>0); if(rt1[i]) { signed char sh,sl,th,tl; th=get_reg(i_regs->regmap,rt1[i]|64); @@ -3747,6 +3750,16 @@ void hlecall_assemble(int i,struct regstat *i_regs) emit_jmp((int)jump_hlecall); } +void intcall_assemble(int i,struct regstat *i_regs) +{ + signed char ccreg=get_reg(i_regs->regmap,CCREG); + assert(ccreg==HOST_CCREG); + assert(!is_delayslot); + emit_movimm(start+i*4,0); // Get PC + emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG); + emit_jmp((int)jump_intcall); +} + void ds_assemble(int i,struct regstat *i_regs) { is_delayslot=1; @@ -3791,6 +3804,7 @@ void ds_assemble(int i,struct regstat *i_regs) mov_assemble(i,i_regs);break; case SYSCALL: case HLECALL: + case INTCALL: case SPAN: case UJUMP: case RJUMP: @@ -4644,6 +4658,7 @@ void ds_assemble_entry(int i) mov_assemble(t,®s[t]);break; case SYSCALL: case HLECALL: + case INTCALL: case SPAN: case UJUMP: case RJUMP: @@ -5635,7 +5650,6 @@ void sjump_assemble(int i,struct regstat *i_regs) // First test branch condition, then execute delay slot, then branch ooo=0; } - assert(opcode2[i]<0x10||ooo); // FIXME (BxxZALL) if(ooo) { s1l=get_reg(branch_regs[i].regmap,rs1[i]); @@ -5822,18 +5836,32 @@ void sjump_assemble(int i,struct regstat *i_regs) // In-order execution (branch first) //printf("IOE\n"); int nottaken=0; + if(rt1[i]==31) { + int rt,return_address; + assert(rt1[i+1]!=31); + assert(rt2[i+1]!=31); + rt=get_reg(branch_regs[i].regmap,31); + if(rt>=0) { + // Save the PC even if the branch is not taken + return_address=start+i*4+8; + emit_movimm(return_address,rt); // PC into link register + #ifdef IMM_PREFETCH + emit_prefetch(hash_table[((return_address>>16)^return_address)&0xFFFF]); + #endif + } + } if(!unconditional) { //printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]); if(!only32) { assert(s1h>=0); - if((opcode2[i]&0x1d)==0) // BLTZ/BLTZL + if((opcode2[i]&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL { emit_test(s1h,s1h); nottaken=(int)out; emit_jns(1); } - if((opcode2[i]&0x1d)==1) // BGEZ/BGEZL + if((opcode2[i]&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL { emit_test(s1h,s1h); nottaken=(int)out; @@ -5843,13 +5871,13 @@ void sjump_assemble(int i,struct regstat *i_regs) else { assert(s1l>=0); - if((opcode2[i]&0x1d)==0) // BLTZ/BLTZL + if((opcode2[i]&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL { emit_test(s1l,s1l); nottaken=(int)out; emit_jns(1); } - if((opcode2[i]&0x1d)==1) // BGEZ/BGEZL + if((opcode2[i]&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL { emit_test(s1l,s1l); nottaken=(int)out; @@ -6475,6 +6503,7 @@ static void pagespan_ds() mov_assemble(0,®s[0]);break; case SYSCALL: case HLECALL: + case INTCALL: case SPAN: case UJUMP: case RJUMP: @@ -6698,7 +6727,7 @@ void unneeded_registers(int istart,int iend,int r) } } } - else if(itype[i]==SYSCALL||itype[i]==HLECALL) + else if(itype[i]==SYSCALL||itype[i]==HLECALL||itype[i]==INTCALL) { // SYSCALL instruction (software interrupt) u=1; @@ -7064,7 +7093,7 @@ static void provisional_r32() if((regs[i].was32>>dep2[i+1])&1) r32|=1LL<>16)&0x1f,rs1[i],imm[i]); break; + case INTCALL: + printf (" %x: %s (INTCALL)\n",start+i*4,insn[i]); + break; default: //printf (" %s %8x\n",insn[i],source[i]); printf (" %x: %s\n",start+i*4,insn[i]); @@ -7742,11 +7774,11 @@ int new_recompile_block(int addr) start = (u_int)addr&~3; //assert(((u_int)addr&1)==0); #ifdef PCSX - if (Config.HLE && start == 0x80001000) { + if (Config.HLE && start == 0x80001000) // hlecall + { // XXX: is this enough? Maybe check hleSoftCall? u_int beginning=(u_int)out; u_int page=get_page(start); - ll_add(jump_in+page,start,out); invalid_code[start>>12]=0; emit_movimm(start,0); emit_writeword(0,(int)&pcaddr); @@ -7754,12 +7786,21 @@ int new_recompile_block(int addr) #ifdef __arm__ __clear_cache((void *)beginning,out); #endif + ll_add(jump_in+page,start,(void *)beginning); return 0; } - else if ((u_int)addr < 0x00200000) { + else if ((u_int)addr < 0x00200000 || + (0xa0000000 <= addr && addr < 0xa0200000)) { // used for BIOS calls mostly? - source = (u_int *)((u_int)rdram+start-0); - pagelimit = 0x00200000; + source = (u_int *)((u_int)rdram+(start&0x1fffff)); + pagelimit = (addr&0xa0000000)|0x00200000; + } + else if (!Config.HLE && ( +/* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/ + (0xbfc00000 <= addr && addr < 0xbfc80000))) { + // BIOS + source = (u_int *)((u_int)psxR+(start&0x7ffff)); + pagelimit = (addr&0xfff00000)|0x80000; } else #endif @@ -7794,7 +7835,7 @@ int new_recompile_block(int addr) else { assem_debug("Compile at unmapped memory address: %x \n", (int)addr); //assem_debug("start: %x next: %x\n",memory_map[start>>12],memory_map[(start+4096)>>12]); - return 1; // Caller will invoke exception handler + return -1; // Caller will invoke exception handler } //printf("source= %x\n",(int)source); } @@ -7933,7 +7974,11 @@ int new_recompile_block(int addr) case 0x02: strcpy(insn[i],"TLBWI"); type=COP0; break; case 0x06: strcpy(insn[i],"TLBWR"); type=COP0; break; case 0x08: strcpy(insn[i],"TLBP"); type=COP0; break; +#ifdef PCSX + case 0x10: strcpy(insn[i],"RFE"); type=COP0; break; +#else case 0x18: strcpy(insn[i],"ERET"); type=COP0; break; +#endif } } break; @@ -8052,11 +8097,11 @@ int new_recompile_block(int addr) break; } break; +#ifndef FORCE32 case 0x14: strcpy(insn[i],"BEQL"); type=CJUMP; break; case 0x15: strcpy(insn[i],"BNEL"); type=CJUMP; break; case 0x16: strcpy(insn[i],"BLEZL"); type=CJUMP; break; case 0x17: strcpy(insn[i],"BGTZL"); type=CJUMP; break; -#ifndef FORCE32 case 0x18: strcpy(insn[i],"DADDI"); type=IMM16; break; case 0x19: strcpy(insn[i],"DADDIU"); type=IMM16; break; case 0x1A: strcpy(insn[i],"LDL"); type=LOADLR; break; @@ -8096,19 +8141,20 @@ int new_recompile_block(int addr) #endif #ifdef PCSX case 0x12: strcpy(insn[i],"COP2"); type=NI; + // note: COP MIPS-1 encoding differs from MIPS32 op2=(source[i]>>21)&0x1f; - switch(op2) + if (source[i]&0x3f) { + if (gte_handlers[source[i]&0x3f]!=NULL) { + snprintf(insn[i], sizeof(insn[i]), "COP2 %x", source[i]&0x3f); + type=C2OP; + } + } + else switch(op2) { case 0x00: strcpy(insn[i],"MFC2"); type=COP2; break; case 0x02: strcpy(insn[i],"CFC2"); type=COP2; break; case 0x04: strcpy(insn[i],"MTC2"); type=COP2; break; case 0x06: strcpy(insn[i],"CTC2"); type=COP2; break; - default: - if (gte_handlers[source[i]&0x3f]!=NULL) { - snprintf(insn[i], sizeof(insn[i]), "COP2 %x", source[i]&0x3f); - type=C2OP; - } - break; } break; case 0x32: strcpy(insn[i],"LWC2"); type=C2LS; break; @@ -8119,6 +8165,18 @@ int new_recompile_block(int addr) printf("NI %08x @%08x (%08x)\n", source[i], addr + i*4, addr); break; } +#ifdef PCSX + /* detect branch in delay slot early */ + if(type==RJUMP||type==UJUMP||type==CJUMP||type==SJUMP||type==FJUMP) { + opcode[i+1]=source[i+1]>>26; + opcode2[i+1]=source[i+1]&0x3f; + if((00&&(itype[i-1]==UJUMP||itype[i-1]==RJUMP||(source[i-1]>>16)==0x1000)) { if(rt1[i-1]==0) { // Continue past subroutine call (JAL) - done=1; - // Does the block continue due to a branch? - for(j=i-1;j>=0;j--) - { - if(ba[j]==start+i*4+4) done=j=0; - if(ba[j]==start+i*4+8) done=j=0; - } + done=2; } else { if(stop_after_jal) done=1; @@ -8372,7 +8425,15 @@ int new_recompile_block(int addr) if(i>MAXBLOCK/2) done=1; } if(itype[i]==SYSCALL&&stop_after_jal) done=1; - if(itype[i]==HLECALL) done=1; + if(itype[i]==HLECALL||itype[i]==INTCALL) done=2; + if(done==2) { + // Does the block continue due to a branch? + for(j=i-1;j>=0;j--) + { + if(ba[j]==start+i*4+4) done=j=0; + if(ba[j]==start+i*4+8) done=j=0; + } + } //assert(i=0) f_regmap[hr]=regs[i].regmap[hr]; + else if(regs[i].regmap[hr]>=0) { + if(f_regmap[hr]!=regs[i].regmap[hr]) { + // dealloc old register + int n; + for(n=0;n64) { if(!((branch_regs[i].dirty>>hr)&1)) f_regmap[hr]=branch_regs[i].regmap[hr]; else f_regmap[hr]=-1; } - else if(branch_regs[i].regmap[hr]>=0) f_regmap[hr]=branch_regs[i].regmap[hr]; + else if(branch_regs[i].regmap[hr]>=0) { + if(f_regmap[hr]!=branch_regs[i].regmap[hr]) { + // dealloc old register + int n; + for(n=0;n>hr)&1)) f_regmap[hr]=regs[i].regmap[hr]; } - else if(regs[i].regmap[hr]>=0) f_regmap[hr]=regs[i].regmap[hr]; + else if(regs[i].regmap[hr]>=0) { + if(f_regmap[hr]!=regs[i].regmap[hr]) { + // dealloc old register + int n; + for(n=0;n>dep2[i+1])&1) r32|=1LL<