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=bbff27589f39e7f0f3f62cb302ba0241ff69512b;hp=6f7c5673785dd63e1638f30794b4a0b26deb752e;hb=fab5d06db8a9cc033af1007f2b10eb9b35535b4c;hpb=2002a1dbd97bc1b94b12ec3e90702a770b040858 diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 6f7c5673..bbff2758 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -135,7 +135,7 @@ struct ll_entry #define CCREG 36 // Cycle count #define INVCP 37 // Pointer to invalid_code #define TEMPREG 38 -#define FTEMP 38 // FPU temporary register +#define FTEMP 38 // FPU/LDL/LDR temporary register #define PTEMP 39 // Prefetch temporary register #define TLREG 40 // TLB mapping offset #define RHASH 41 // Return address hash @@ -175,6 +175,10 @@ struct ll_entry #define OTHER 23 // Other #define SPAN 24 // Branch/delay slot spans 2 pages #define NI 25 // Not implemented +#define HLECALL 26// PCSX fake opcodes for HLE +#define COP2 27 // Coprocessor 2 move +#define C2LS 28 // Coprocessor 2 load/store +#define C2OP 29 // Coprocessor 2 operation /* stubs */ #define CC_STUB 1 @@ -213,7 +217,10 @@ void cc_interrupt(); void fp_exception(); void fp_exception_ds(); void jump_syscall(); +void jump_syscall_hle(); void jump_eret(); +void jump_hlecall(); +void new_dyna_leave(); // TLB void TLBWI_new(); @@ -399,6 +406,9 @@ void *get_addr_ht(u_int vaddr) void *get_addr_32(u_int vaddr,u_int flags) { +#ifdef FORCE32 + return get_addr(vaddr); +#endif //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]; @@ -626,7 +636,7 @@ void lsn(u_char hsn[], int i, int *preferred_reg) } // On some architectures stores need invc_ptr #if defined(HOST_IMM8) - if(itype[i+j]==STORE || itype[i+j]==STORELR || (opcode[i+j]&0x3b)==0x39) { + if(itype[i+j]==STORE || itype[i+j]==STORELR || (opcode[i+j]&0x3b)==0x39 || (opcode[i+j]&0x3b)==0x3a) { hsn[INVCP]=j; } #endif @@ -663,19 +673,19 @@ void lsn(u_char hsn[], int i, int *preferred_reg) hsn[RHTBL]=1; } // Coprocessor load/store needs FTEMP, even if not declared - if(itype[i]==C1LS) { + if(itype[i]==C1LS||itype[i]==C2LS) { hsn[FTEMP]=0; } // Load L/R also uses FTEMP as a temporary register if(itype[i]==LOADLR) { hsn[FTEMP]=0; } - // Also 64-bit SDL/SDR - if(opcode[i]==0x2c||opcode[i]==0x2d) { + // Also SWL/SWR/SDL/SDR + if(opcode[i]==0x2a||opcode[i]==0x2e||opcode[i]==0x2c||opcode[i]==0x2d) { hsn[FTEMP]=0; } // Don't remove the TLB registers either - if(itype[i]==LOAD || itype[i]==LOADLR || itype[i]==STORE || itype[i]==STORELR || itype[i]==C1LS ) { + if(itype[i]==LOAD || itype[i]==LOADLR || itype[i]==STORE || itype[i]==STORELR || itype[i]==C1LS || itype[i]==C2LS) { hsn[TLREG]=0; } // Don't remove the miniht registers @@ -716,7 +726,7 @@ int needed_again(int r, int i) j++; break; } - if(itype[i+j]==SYSCALL||((source[i+j]&0xfc00003f)==0x0d)) + if(itype[i+j]==SYSCALL||itype[i+j]==HLECALL||((source[i+j]&0xfc00003f)==0x0d)) { break; } @@ -962,14 +972,10 @@ void ll_add(struct ll_entry **head,int vaddr,void *addr) // Add virtual address mapping for 32-bit compiled block void ll_add_32(struct ll_entry **head,int vaddr,u_int reg32,void *addr) { - struct ll_entry *new_entry; - new_entry=malloc(sizeof(struct ll_entry)); - assert(new_entry!=NULL); - new_entry->vaddr=vaddr; - new_entry->reg32=reg32; - new_entry->addr=addr; - new_entry->next=*head; - *head=new_entry; + ll_add(head,vaddr,addr); +#ifndef FORCE32 + (*head)->reg32=reg32; +#endif } // Check if an address is already compiled @@ -1070,25 +1076,37 @@ void ll_clear(struct ll_entry **head) // Dereference the pointers and remove if it matches void ll_kill_pointers(struct ll_entry *head,int addr,int shift) { + u_int old_host_addr=0; while(head) { int ptr=get_pointer(head->addr); inv_debug("EXP: Lookup pointer to %x at %x (%x)\n",(int)ptr,(int)head->addr,head->vaddr); if(((ptr>>shift)==(addr>>shift)) || (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift))) { - inv_debug("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr); - kill_pointer(head->addr); + printf("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)) { + #ifdef __arm__ + __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff)); + #endif + old_host_addr=host_addr; + } } head=head->next; } + #ifdef __arm__ + if (old_host_addr) + __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff)); + #endif } // This is called when we write to a compiled block (see do_invstub) -int invalidate_page(u_int page) +void invalidate_page(u_int page) { - int modified=0; struct ll_entry *head; struct ll_entry *next; + u_int old_host_addr=0; head=jump_in[page]; jump_in[page]=0; while(head!=NULL) { @@ -1102,17 +1120,25 @@ int invalidate_page(u_int page) jump_out[page]=0; while(head!=NULL) { inv_debug("INVALIDATE: kill pointer to %x (%x)\n",head->vaddr,(int)head->addr); - kill_pointer(head->addr); - modified=1; + u_int host_addr=(u_int)kill_pointer(head->addr); + + if((host_addr>>12)!=(old_host_addr>>12)) { + #ifdef __arm__ + __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff)); + #endif + old_host_addr=host_addr; + } next=head->next; free(head); head=next; } - return modified; + #ifdef __arm__ + if (old_host_addr) + __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff)); + #endif } void invalidate_block(u_int block) { - int modified; u_int page=get_page(block<<12); u_int vpage=get_vpage(block<<12); inv_debug("INVALIDATE: %x (%d)\n",block<<12,page); @@ -1145,7 +1171,7 @@ void invalidate_block(u_int block) head=head->next; } //printf("first=%d last=%d\n",first,last); - modified=invalidate_page(page); + invalidate_page(page); assert(first+5>page); // NB: this assumes MAXBLOCK<=4096 (4 pages) assert(last=0x80000&&block<0x80800) memory_map[block]=((u_int)rdram-0x80000000)>>2; #endif - #ifdef __arm__ - if(modified) - __clear_cache((void *)BASE_ADDR,(void *)BASE_ADDR+(1<regmap,rt1[i]|64); tl=get_reg(i_regs->regmap,rt1[i]); @@ -2698,11 +2749,21 @@ void load_assemble(int i,struct regstat *i_regs) memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80800000; if(using_tlb&&((signed int)(constmap[i][s]+offset))>=(signed int)0xC0000000) memtarget=1; } - if(offset||s<0||c) addr=tl; - else addr=s; //printf("load_assemble: c=%d\n",c); //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) { + // could be FIFO, must perform the read + assem_debug("(forced read)\n"); + tl=get_reg(i_regs->regmap,-1); + assert(tl>=0); + } + } + if(offset||s<0||c) addr=tl; + else addr=s; +#endif if(tl>=0) { //assert(tl>=0); //assert(rt1[i]); @@ -2948,7 +3009,7 @@ void store_assemble(int i,struct regstat *i_regs) int addr,temp; int offset; int jaddr=0,jaddr2,type; - int memtarget,c=0; + int memtarget=0,c=0; int agr=AGEN1+(i&1); u_int hr,reglist=0; th=get_reg(i_regs->regmap,rs2[i]|64); @@ -3064,6 +3125,9 @@ void store_assemble(int i,struct regstat *i_regs) } type=STORED_STUB; } + if(!using_tlb&&(!c||memtarget)) + // addr could be a temp, make sure it survives STORE*_STUB + reglist|=1<regmap,rs2[i]|64); tl=get_reg(i_regs->regmap,rs2[i]); s=get_reg(i_regs->regmap,rs1[i]); - temp=get_reg(i_regs->regmap,-1); + temp=get_reg(i_regs->regmap,agr); + if(temp<0) temp=get_reg(i_regs->regmap,-1); offset=imm[i]; if(s>=0) { c=(i_regs->isconst>>s)&1; @@ -3315,7 +3381,7 @@ void storelr_assemble(int i,struct regstat *i_regs) set_jump_target(done0,(int)out); } if(!c||!memtarget) - add_stub(STORELR_STUB,jaddr,(int)out,0,(int)i_regs,rs2[i],ccadj[i],reglist); + add_stub(STORELR_STUB,jaddr,(int)out,i,(int)i_regs,temp,ccadj[i],reglist); } if(!using_tlb) { emit_addimm_no_flags((u_int)0x80000000-(u_int)rdram,temp); @@ -3527,6 +3593,87 @@ void c1ls_assemble(int i,struct regstat *i_regs) #endif } +void c2ls_assemble(int i,struct regstat *i_regs) +{ + int s,tl; + int ar; + int offset; + int c=0; + int jaddr,jaddr2=0,jaddr3,type; + int agr=AGEN1+(i&1); + u_int hr,reglist=0; + u_int copr=(source[i]>>16)&0x1f; + s=get_reg(i_regs->regmap,rs1[i]); + tl=get_reg(i_regs->regmap,FTEMP); + offset=imm[i]; + assert(rs1[i]>0); + assert(tl>=0); + assert(!using_tlb); + + for(hr=0;hrregmap[hr]>=0) reglist|=1<regmap[HOST_CCREG]==CCREG) + reglist&=~(1<regmap,agr); + if(ar<0) ar=get_reg(i_regs->regmap,-1); + reglist|=1<=0) ar=s; + assert(ar>=0); + + if (opcode[i]==0x3a) { // SWC2 + cop2_get_dreg(copr,tl,HOST_TEMPREG); + } + if(s>=0) c=(i_regs->wasconst>>s)&1; + if(!c) { + emit_cmpimm(offset||c||s<0?ar:s,0x800000); + jaddr2=(int)out; + emit_jno(0); + } + else if(((signed int)(constmap[i][s]+offset))>=(signed int)0x80800000) { + jaddr2=(int)out; + emit_jmp(0); // inline_readstub/inline_writestub? Very rare case + } + if (opcode[i]==0x32) { // LWC2 + #ifdef HOST_IMM_ADDR32 + if(c) emit_readword_tlb(constmap[i][s]+offset,-1,tl); + else + #endif + emit_readword_indexed(0,ar,tl); + type=LOADW_STUB; + } + if (opcode[i]==0x3a) { // SWC2 +#ifdef DESTRUCTIVE_SHIFT + if(!offset&&!c&&s>=0) emit_mov(s,ar); +#endif + emit_writeword_indexed(tl,0,ar); + type=STOREW_STUB; + } + if(jaddr2) + add_stub(type,jaddr2,(int)out,i,ar,(int)i_regs,ccadj[i],reglist); + if (opcode[i]==0x3a) { // SWC2 +#if defined(HOST_IMM8) + int ir=get_reg(i_regs->regmap,INVCP); + assert(ir>=0); + emit_cmpmem_indexedsr12_reg(ir,ar,1); +#else + emit_cmpmem_indexedsr12_imm((int)invalid_code,ar,1); +#endif + jaddr3=(int)out; + emit_jne(0); + add_stub(INVCODE_STUB,jaddr3,(int)out,reglist|(1<regmap,CCREG); + assert(ccreg==HOST_CCREG); + assert(!is_delayslot); + emit_movimm(start+i*4+4,0); // Get PC + emit_movimm((int)psxHLEt[source[i]&7],1); + emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG); // XXX + emit_jmp((int)jump_hlecall); } void ds_assemble(int i,struct regstat *i_regs) @@ -3610,6 +3768,12 @@ void ds_assemble(int i,struct regstat *i_regs) cop1_assemble(i,i_regs);break; case C1LS: c1ls_assemble(i,i_regs);break; + case COP2: + cop2_assemble(i,i_regs);break; + case C2LS: + c2ls_assemble(i,i_regs);break; + case C2OP: + c2op_assemble(i,i_regs);break; case FCONV: fconv_assemble(i,i_regs);break; case FLOAT: @@ -3621,6 +3785,7 @@ void ds_assemble(int i,struct regstat *i_regs) case MOV: mov_assemble(i,i_regs);break; case SYSCALL: + case HLECALL: case SPAN: case UJUMP: case RJUMP: @@ -3778,9 +3943,10 @@ static void loop_preload(signed char pre[],signed char entry[]) } // Generate address for load/store instruction +// goes to AGEN for writes, FTEMP for LOADLR and cop1/2 loads void address_generation(int i,struct regstat *i_regs,signed char entry[]) { - if(itype[i]==LOAD||itype[i]==LOADLR||itype[i]==STORE||itype[i]==STORELR||itype[i]==C1LS) { + if(itype[i]==LOAD||itype[i]==LOADLR||itype[i]==STORE||itype[i]==STORELR||itype[i]==C1LS||itype[i]==C2LS) { int ra; int agr=AGEN1+(i&1); int mgr=MGEN1+(i&1); @@ -3795,8 +3961,8 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) ra=get_reg(i_regs->regmap,agr); if(ra<0) ra=get_reg(i_regs->regmap,-1); } - if(itype[i]==C1LS) { - if (opcode[i]==0x31||opcode[i]==0x35) // LWC1/LDC1 + if(itype[i]==C1LS||itype[i]==C2LS) { + if ((opcode[i]&0x3b)==0x31||(opcode[i]&0x3b)==0x32) // LWC1/LDC1/LWC2/LDC2 ra=get_reg(i_regs->regmap,FTEMP); else { // SWC1/SDC1 ra=get_reg(i_regs->regmap,agr); @@ -3834,7 +4000,7 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) else if(c) { if(rm>=0) { if(!entry||entry[rm]!=mgr) { - if(itype[i]==STORE||itype[i]==STORELR||opcode[i]==0x39||opcode[i]==0x3D) { + if(itype[i]==STORE||itype[i]==STORELR||(opcode[i]&0x3b)==0x39||(opcode[i]&0x3b)==0x3a) { // Stores to memory go thru the mapper to detect self-modifying // code, loads don't. if((unsigned int)(constmap[i][rs]+offset)>=0xC0000000 || @@ -3854,7 +4020,7 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) emit_movimm((constmap[i][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR }else{ #ifdef HOST_IMM_ADDR32 - if((itype[i]!=LOAD&&opcode[i]!=0x31&&opcode[i]!=0x35) || + if((itype[i]!=LOAD&&(opcode[i]&0x3b)!=0x31&&(opcode[i]&0x3b)!=0x32) || // LWC1/LDC1/LWC2/LDC2 (using_tlb&&((signed int)constmap[i][rs]+offset)>=(signed int)0xC0000000)) #endif emit_movimm(constmap[i][rs]+offset,ra); @@ -3872,7 +4038,7 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) } } // Preload constants for next instruction - if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS) { + if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS||itype[i+1]==C2LS) { int agr,ra; #ifndef HOST_IMM_ADDR32 // Mapper entry @@ -3883,7 +4049,8 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) int offset=imm[i+1]; int c=(regs[i+1].wasconst>>rs)&1; if(c) { - if(itype[i+1]==STORE||itype[i+1]==STORELR||opcode[i+1]==0x39||opcode[i+1]==0x3D) { + if(itype[i+1]==STORE||itype[i+1]==STORELR + ||(opcode[i+1]&0x3b)==0x39||(opcode[i+1]&0x3b)==0x3a) { // SWC1/SDC1, SWC2/SDC2 // Stores to memory go thru the mapper to detect self-modifying // code, loads don't. if((unsigned int)(constmap[i+1][rs]+offset)>=0xC0000000 || @@ -3913,7 +4080,7 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) emit_movimm((constmap[i+1][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR }else{ #ifdef HOST_IMM_ADDR32 - if((itype[i+1]!=LOAD&&opcode[i+1]!=0x31&&opcode[i+1]!=0x35) || + if((itype[i+1]!=LOAD&&(opcode[i+1]&0x3b)!=0x31&&(opcode[i+1]&0x3b)!=0x32) || // LWC1/LDC1/LWC2/LDC2 (using_tlb&&((signed int)constmap[i+1][rs]+offset)>=(signed int)0xC0000000)) #endif emit_movimm(constmap[i+1][rs]+offset,ra); @@ -4427,7 +4594,7 @@ void ds_assemble_entry(int i) wb_register(CCREG,regs[t].regmap_entry,regs[t].wasdirty,regs[t].was32); load_regs(regs[t].regmap_entry,regs[t].regmap,regs[t].was32,rs1[t],rs2[t]); address_generation(t,®s[t],regs[t].regmap_entry); - if(itype[t]==STORE||itype[t]==STORELR||(opcode[t]&0x3b)==0x39) + if(itype[t]==STORE||itype[t]==STORELR||(opcode[t]&0x3b)==0x39||(opcode[t]&0x3b)==0x3a) load_regs(regs[t].regmap_entry,regs[t].regmap,regs[t].was32,INVCP,INVCP); cop1_usable=0; is_delayslot=0; @@ -4454,6 +4621,12 @@ void ds_assemble_entry(int i) cop1_assemble(t,®s[t]);break; case C1LS: c1ls_assemble(t,®s[t]);break; + case COP2: + cop2_assemble(t,®s[t]);break; + case C2LS: + c2ls_assemble(t,®s[t]);break; + case C2OP: + c2op_assemble(t,®s[t]);break; case FCONV: fconv_assemble(t,®s[t]);break; case FLOAT: @@ -4465,6 +4638,7 @@ void ds_assemble_entry(int i) case MOV: mov_assemble(t,®s[t]);break; case SYSCALL: + case HLECALL: case SPAN: case UJUMP: case RJUMP: @@ -4931,11 +5105,11 @@ void rjump_assemble(int i,struct regstat *i_regs) wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32, bc_unneeded,bc_unneeded_upper); load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,rs1[i],CCREG); - if(rt1[i]==31) { + if(rt1[i]!=0) { int rt,return_address; - assert(rt1[i+1]!=31); - assert(rt2[i+1]!=31); - rt=get_reg(branch_regs[i].regmap,31); + assert(rt1[i+1]!=rt1[i]); + assert(rt2[i+1]!=rt1[i]); + rt=get_reg(branch_regs[i].regmap,rt1[i]); assem_debug("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]); assert(rt>=0); return_address=start+i*4+8; @@ -6051,7 +6225,7 @@ static void pagespan_assemble(int i,struct regstat *i_regs) emit_mov(s1l,addr); if(opcode2[i]==9) // JALR { - int rt=get_reg(i_regs->regmap,31); + int rt=get_reg(i_regs->regmap,rt1[i]); emit_movimm(start+i*4+8,rt); } } @@ -6252,7 +6426,7 @@ static void pagespan_ds() emit_writeword(HOST_BTREG,(int)&branch_target); load_regs(regs[0].regmap_entry,regs[0].regmap,regs[0].was32,rs1[0],rs2[0]); address_generation(0,®s[0],regs[0].regmap_entry); - if(itype[0]==STORE||itype[0]==STORELR||(opcode[0]&0x3b)==0x39) + if(itype[0]==STORE||itype[0]==STORELR||(opcode[0]&0x3b)==0x39||(opcode[0]&0x3b)==0x3a) load_regs(regs[0].regmap_entry,regs[0].regmap,regs[0].was32,INVCP,INVCP); cop1_usable=0; is_delayslot=0; @@ -6279,6 +6453,12 @@ static void pagespan_ds() cop1_assemble(0,®s[0]);break; case C1LS: c1ls_assemble(0,®s[0]);break; + case COP2: + cop2_assemble(0,®s[0]);break; + case C2LS: + c2ls_assemble(0,®s[0]);break; + case C2OP: + c2op_assemble(0,®s[0]);break; case FCONV: fconv_assemble(0,®s[0]);break; case FLOAT: @@ -6290,6 +6470,7 @@ static void pagespan_ds() case MOV: mov_assemble(0,®s[0]);break; case SYSCALL: + case HLECALL: case SPAN: case UJUMP: case RJUMP: @@ -6513,7 +6694,7 @@ void unneeded_registers(int istart,int iend,int r) } } } - else if(itype[i]==SYSCALL) + else if(itype[i]==SYSCALL||itype[i]==HLECALL) { // SYSCALL instruction (software interrupt) u=1; @@ -6545,9 +6726,6 @@ void unneeded_registers(int istart,int iend,int r) // Save it unneeded_reg[i]=u; unneeded_reg_upper[i]=uu; -#ifdef FORCE32 - unneeded_reg_upper[i]=-1LL; -#endif /* printf("ur (%d,%d) %x: ",istart,iend,start+i*4); printf("U:"); @@ -6569,6 +6747,12 @@ void unneeded_registers(int istart,int iend,int r) } printf("\n");*/ } +#ifdef FORCE32 + for (i=iend;i>=istart;i--) + { + unneeded_reg_upper[i]=branch_unneeded_reg_upper[i]=-1LL; + } +#endif } // Identify registers which are likely to contain 32-bit values @@ -6759,18 +6943,22 @@ static void provisional_32bit() if(op2==0) is32|=1LL<>dep2[i+1])&1) r32|=1LL<>11)&0x1f); // MTC1 else printf (" %x: %s\n",start+i*4,insn[i]); break; + case COP2: + if(opcode2[i]<3) + printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],rt1[i],(source[i]>>11)&0x1f); // MFC2 + else if(opcode2[i]>3) + printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],rs1[i],(source[i]>>11)&0x1f); // MTC2 + else printf (" %x: %s\n",start+i*4,insn[i]); + break; case C1LS: printf (" %x: %s cpr1[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,rs1[i],imm[i]); break; + case C2LS: + printf (" %x: %s cpr2[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,rs1[i],imm[i]); + break; default: //printf (" %s %8x\n",insn[i],source[i]); printf (" %x: %s\n",start+i*4,insn[i]); @@ -7535,6 +7737,28 @@ int new_recompile_block(int addr) //rlist(); start = (u_int)addr&~3; //assert(((u_int)addr&1)==0); +#ifdef PCSX + if (Config.HLE && start == 0x80001000) { + // 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); + emit_jmp((int)new_dyna_leave); +#ifdef __arm__ + __clear_cache((void *)beginning,out); +#endif + return 0; + } + else if ((u_int)addr < 0x00200000) { + // used for BIOS calls mostly? + source = (u_int *)((u_int)rdram+start-0); + pagelimit = 0x00200000; + } + else +#endif #ifdef MUPEN64 if ((int)addr >= 0xa4000000 && (int)addr < 0xa4001000) { source = (u_int *)((u_int)SP_DMEM+start-0xa4000000); @@ -7858,8 +8082,29 @@ int new_recompile_block(int addr) case 0x3C: strcpy(insn[i],"SCD"); type=NI; break; case 0x3D: strcpy(insn[i],"SDC1"); type=C1LS; break; case 0x3F: strcpy(insn[i],"SD"); type=STORE; break; +#ifdef PCSX + case 0x12: strcpy(insn[i],"COP2"); type=NI; + op2=(source[i]>>21)&0x1f; + 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; + case 0x3A: strcpy(insn[i],"SWC2"); type=C2LS; break; + case 0x3B: strcpy(insn[i],"HLECALL"); type=HLECALL; break; +#endif default: strcpy(insn[i],"???"); type=NI; - assem_debug("NI %08x @%08x\n", source[i], addr + i*4); + printf("NI %08x @%08x\n", source[i], addr + i*4); break; } itype[i]=type; @@ -7929,9 +8174,9 @@ int new_recompile_block(int addr) rs2[i]=0; rt1[i]=0; rt2[i]=0; - // The JALR instruction writes to r31. + // The JALR instruction writes to rd. if (op2&1) { - rt1[i]=31; + rt1[i]=(source[i]>>11)&0x1f; } rs2[i]=CCREG; break; @@ -8033,6 +8278,7 @@ int new_recompile_block(int addr) if(op2==16) if((source[i]&0x3f)==0x18) rs2[i]=CCREG; // ERET break; case COP1: + case COP2: rs1[i]=0; rs2[i]=0; rt1[i]=0; @@ -8049,6 +8295,13 @@ int new_recompile_block(int addr) rt2[i]=0; imm[i]=(short)source[i]; break; + case C2LS: + rs1[i]=(source[i]>>21)&0x1F; + rs2[i]=0; + rt1[i]=0; + rt2[i]=0; + imm[i]=(short)source[i]; + break; case FLOAT: case FCONV: rs1[i]=0; @@ -8063,6 +8316,7 @@ int new_recompile_block(int addr) rt2[i]=0; break; case SYSCALL: + case HLECALL: rs1[i]=CCREG; rs2[i]=0; rt1[i]=0; @@ -8086,7 +8340,7 @@ int new_recompile_block(int addr) else ba[i]=-1; /* Is this the end of the block? */ if(i>0&&(itype[i-1]==UJUMP||itype[i-1]==RJUMP||(source[i-1]>>16)==0x1000)) { - if(rt1[i-1]!=31) { // Continue past subroutine call (JAL) + 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--) @@ -8106,6 +8360,7 @@ int new_recompile_block(int addr) if(i>MAXBLOCK/2) done=1; } if(i>0&&itype[i-1]==SYSCALL&&stop_after_jal) done=1; + if(itype[i-1]==HLECALL) done=1; assert(i0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP||itype[i-1]==FJUMP||itype[i]==SYSCALL)) + if(i>0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP||itype[i-1]==FJUMP||itype[i]==SYSCALL||itype[i]==HLECALL)) { cc=0; } @@ -9162,13 +9425,13 @@ int new_recompile_block(int addr) if(dep1[i+1]==(regs[i].regmap_entry[hr]&63)) nr|=1<>2; if(t>0&&(itype[t-1]!=UJUMP&&itype[t-1]!=RJUMP&&itype[t-1]!=CJUMP&&itype[t-1]!=SJUMP&&itype[t-1]!=FJUMP)) // loop_preload can't handle jumps into delay slots @@ -9401,7 +9667,8 @@ int new_recompile_block(int addr) else if(branch_regs[i].regmap[hr]>=0) f_regmap[hr]=branch_regs[i].regmap[hr]; if(itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS ||itype[i+1]==SHIFT||itype[i+1]==COP1||itype[i+1]==FLOAT - ||itype[i+1]==FCOMP||itype[i+1]==FCONV) + ||itype[i+1]==FCOMP||itype[i+1]==FCONV + ||itype[i+1]==COP2||itype[i+1]==C2LS||itype[i+1]==C2OP) { // Test both in case the delay slot is ooo, // could be done better... @@ -9440,8 +9707,8 @@ int new_recompile_block(int addr) while(k>1&®s[k-1].regmap[hr]==-1) { if(itype[k-1]==STORE||itype[k-1]==STORELR ||itype[k-1]==C1LS||itype[k-1]==SHIFT||itype[k-1]==COP1 - ||itype[k-1]==FLOAT||itype[k-1]==FCONV - ||itype[k-1]==FCOMP) { + ||itype[k-1]==FLOAT||itype[k-1]==FCONV||itype[k-1]==FCOMP + ||itype[k-1]==COP2||itype[k-1]==C2LS||itype[k-1]==C2OP) { if(count_free_regs(regs[k-1].regmap)<2) { //printf("no free regs for store %x\n",start+(k-1)*4); break; @@ -9550,7 +9817,8 @@ int new_recompile_block(int addr) } if(itype[j]==STORE||itype[j]==STORELR||itype[j]==C1LS ||itype[j]==SHIFT||itype[j]==COP1||itype[j]==FLOAT - ||itype[j]==FCOMP||itype[j]==FCONV) { + ||itype[j]==FCOMP||itype[j]==FCONV + ||itype[j]==COP2||itype[j]==C2LS||itype[j]==C2OP) { if(count_free_regs(regs[j].regmap)<2) { //printf("No free regs for store %x\n",start+j*4); break; @@ -9592,7 +9860,8 @@ int new_recompile_block(int addr) if(regs[j].regmap[HOST_CCREG]!=-1) break; if(itype[j]==STORE||itype[j]==STORELR||itype[j]==C1LS ||itype[j]==SHIFT||itype[j]==COP1||itype[j]==FLOAT - ||itype[j]==FCOMP||itype[j]==FCONV) { + ||itype[j]==FCOMP||itype[j]==FCONV + ||itype[j]==COP2||itype[j]==C2LS||itype[j]==C2OP) { if(count_free_regs(regs[j].regmap)<2) { //printf("no free regs for store %x\n",start+j*4); break; @@ -9625,7 +9894,8 @@ int new_recompile_block(int addr) while(regs[k-1].regmap[HOST_CCREG]==-1) { if(itype[k-1]==STORE||itype[k-1]==STORELR||itype[k-1]==C1LS ||itype[k-1]==SHIFT||itype[k-1]==COP1||itype[k-1]==FLOAT - ||itype[k-1]==FCONV||itype[k-1]==FCOMP) { + ||itype[k-1]==FCONV||itype[k-1]==FCOMP + ||itype[k-1]==COP2||itype[k-1]==C2LS||itype[k-1]==C2OP) { if(count_free_regs(regs[k-1].regmap)<2) { //printf("no free regs for store %x\n",start+(k-1)*4); break; @@ -9656,7 +9926,8 @@ int new_recompile_block(int addr) if(itype[i]!=STORE&&itype[i]!=STORELR&&itype[i]!=C1LS&&itype[i]!=SHIFT&& itype[i]!=NOP&&itype[i]!=MOV&&itype[i]!=ALU&&itype[i]!=SHIFTIMM&& itype[i]!=IMM16&&itype[i]!=LOAD&&itype[i]!=COP1&&itype[i]!=FLOAT&& - itype[i]!=FCONV&&itype[i]!=FCOMP) + itype[i]!=FCONV&&itype[i]!=FCOMP&& + itype[i]!=COP2&&itype[i]!=C2LS&&itype[i]!=C2OP) { memcpy(f_regmap,regs[i].regmap,sizeof(f_regmap)); } @@ -9671,7 +9942,8 @@ int new_recompile_block(int addr) { if(!bt[i+1]) { - if(itype[i]==ALU||itype[i]==MOV||itype[i]==LOAD||itype[i]==SHIFTIMM||itype[i]==IMM16||(itype[i]==COP1&&opcode2[i]<3)) + if(itype[i]==ALU||itype[i]==MOV||itype[i]==LOAD||itype[i]==SHIFTIMM||itype[i]==IMM16 + ||((itype[i]==COP1||itype[i]==COP2)&&opcode2[i]<3)) { if(rs1[i+1]) { if((hr=get_reg(regs[i+1].regmap,rs1[i+1]))>=0) @@ -9738,7 +10010,7 @@ int new_recompile_block(int addr) } } #ifndef HOST_IMM_ADDR32 - if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS) { + if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS||itype[i+1]==C2LS) { hr=get_reg(regs[i+1].regmap,TLREG); if(hr>=0) { int sr=get_reg(regs[i+1].regmap,rs1[i+1]); @@ -9776,7 +10048,8 @@ int new_recompile_block(int addr) } } #endif - if(itype[i+1]==STORE||itype[i+1]==STORELR||opcode[i+1]==0x39||opcode[i+1]==0x3D) { // SB/SH/SW/SD/SWC1/SDC1 + if(itype[i+1]==STORE||itype[i+1]==STORELR + ||(opcode[i+1]&0x3b)==0x39||(opcode[i+1]&0x3b)==0x3a) { // SB/SH/SW/SD/SWC1/SDC1/SWC2/SDC2 if(get_reg(regs[i+1].regmap,rs1[i+1])<0) { hr=get_reg2(regs[i].regmap,regs[i+1].regmap,-1); if(hr<0) hr=get_reg(regs[i+1].regmap,-1); @@ -9795,7 +10068,7 @@ int new_recompile_block(int addr) } } } - if(itype[i+1]==LOADLR||opcode[i+1]==0x31||opcode[i+1]==0x35) { // LWC1/LDC1 + if(itype[i+1]==LOADLR||(opcode[i+1]&0x3b)==0x31||(opcode[i+1]&0x3b)==0x32) { // LWC1/LDC1, LWC2/LDC2 if(get_reg(regs[i+1].regmap,rs1[i+1])<0) { int nr; hr=get_reg(regs[i+1].regmap,FTEMP); @@ -9830,12 +10103,12 @@ int new_recompile_block(int addr) } } } - if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR/*||itype[i+1]==C1LS*/) { + if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR/*||itype[i+1]==C1LS||||itype[i+1]==C2LS*/) { if(itype[i+1]==LOAD) hr=get_reg(regs[i+1].regmap,rt1[i+1]); - if(itype[i+1]==LOADLR||opcode[i+1]==0x31||opcode[i+1]==0x35) // LWC1/LDC1 + if(itype[i+1]==LOADLR||(opcode[i+1]&0x3b)==0x31||(opcode[i+1]&0x3b)==0x32) // LWC1/LDC1, LWC2/LDC2 hr=get_reg(regs[i+1].regmap,FTEMP); - if(itype[i+1]==STORE||itype[i+1]==STORELR||opcode[i+1]==0x39||opcode[i+1]==0x3D) { // SWC1/SDC1 + if(itype[i+1]==STORE||itype[i+1]==STORELR||(opcode[i+1]&0x3b)==0x39||(opcode[i+1]&0x3b)==0x3a) { // SWC1/SDC1/SWC2/SDC2 hr=get_reg(regs[i+1].regmap,AGEN1+((i+1)&1)); if(hr<0) hr=get_reg(regs[i+1].regmap,-1); } @@ -9930,7 +10203,7 @@ int new_recompile_block(int addr) if((regs[i].was32>>dep2[i+1])&1) r32|=1LL<