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=6d7069d9c8d2e837294cd5484bc3706fff789c3b;hp=6501d26a3fc379ae5a7303de263bf966c57fafd9;hb=a151a8d8331cf743eabeab23ce52e9b7726239e5;hpb=e2b5e7aa45f75cd13ef238fa4ff9516891dabef5 diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 6501d26a..6d7069d9 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -23,7 +23,19 @@ #include #include #include +#ifdef __MACH__ +#include +#endif +#ifdef _3DS +#include <3ds_utils.h> +#endif +#ifdef VITA +#include +static int sceBlock; +#endif +#include "new_dynarec_config.h" +#include "../psxhle.h" //emulator interface #include "emu_if.h" //emulator interface //#define DISASM @@ -42,19 +54,6 @@ #include "assem_arm.h" #endif -#ifdef __BLACKBERRY_QNX__ -#undef __clear_cache -#define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); -#elif defined(__MACH__) -#include -#define __clear_cache mach_clear_cache -static void __clear_cache(void *start, void *end) { - size_t len = (char *)end - (char *)start; - sys_dcache_flush(start, len); - sys_icache_invalidate(start, len); -} -#endif - #define MAXBLOCK 4096 #define MAX_OUTPUT_BLOCK_SIZE 262144 @@ -271,6 +270,66 @@ static void add_to_linker(int addr,int target,int ext); static int tracedebug=0; +static void mprotect_w_x(void *start, void *end, int is_x) +{ +#ifdef NO_WRITE_EXEC + #if defined(VITA) + // *Open* enables write on all memory that was + // allocated by sceKernelAllocMemBlockForVM()? + if (is_x) + sceKernelCloseVMDomain(); + else + sceKernelOpenVMDomain(); + #else + u_long mstart = (u_long)start & ~4095ul; + u_long mend = (u_long)end; + if (mprotect((void *)mstart, mend - mstart, + PROT_READ | (is_x ? PROT_EXEC : PROT_WRITE)) != 0) + SysPrintf("mprotect(%c) failed: %s\n", is_x ? 'x' : 'w', strerror(errno)); + #endif +#endif +} + +static void start_tcache_write(void *start, void *end) +{ + mprotect_w_x(start, end, 0); +} + +static void end_tcache_write(void *start, void *end) +{ +#ifdef __arm__ + size_t len = (char *)end - (char *)start; + #if defined(__BLACKBERRY_QNX__) + msync(start, len, MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); + #elif defined(__MACH__) + sys_cache_control(kCacheFunctionPrepareForExecution, start, len); + #elif defined(VITA) + sceKernelSyncVMDomain(sceBlock, start, len); + #elif defined(_3DS) + ctr_flush_invalidate_cache(); + #else + __clear_cache(start, end); + #endif + (void)len; +#endif + + mprotect_w_x(start, end, 1); +} + +static void *start_block(void) +{ + u_char *end = out + MAX_OUTPUT_BLOCK_SIZE; + if (end > (u_char *)BASE_ADDR + (1<vaddr==vaddr) { //printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr); - int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; ht_bin[3]=ht_bin[1]; ht_bin[2]=ht_bin[0]; - ht_bin[1]=(int)head->addr; + ht_bin[1]=(u_int)head->addr; ht_bin[0]=vaddr; return head->addr; } @@ -334,9 +393,9 @@ void *get_addr(u_int vaddr) restore_candidate[vpage>>3]|=1<<(vpage&7); } else restore_candidate[page>>3]|=1<<(page&7); - int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; if(ht_bin[0]==vaddr) { - ht_bin[1]=(int)head->addr; // Replace existing entry + ht_bin[1]=(u_int)head->addr; // Replace existing entry } else { @@ -366,7 +425,7 @@ void *get_addr(u_int vaddr) void *get_addr_ht(u_int vaddr) { //printf("TRACE: count=%d next=%d (get_addr_ht %x)\n",Count,next_interupt,vaddr); - int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; if(ht_bin[0]==vaddr) return (void *)ht_bin[1]; if(ht_bin[2]==vaddr) return (void *)ht_bin[3]; return get_addr(vaddr); @@ -634,6 +693,7 @@ int needed_again(int r, int i) } }*/ if(rn<10) return 1; + (void)b; return 0; } @@ -781,7 +841,7 @@ void *check_addr(u_int vaddr) void remove_hash(int vaddr) { //printf("remove hash: %x\n",vaddr); - int *ht_bin=hash_table[(((vaddr)>>16)^vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[(((vaddr)>>16)^vaddr)&0xFFFF]; if(ht_bin[2]==vaddr) { ht_bin[2]=ht_bin[3]=-1; } @@ -817,7 +877,7 @@ void ll_clear(struct ll_entry **head) { struct ll_entry *cur; struct ll_entry *next; - if(cur=*head) { + if((cur=*head)) { *head=0; while(cur) { next=cur->next; @@ -828,7 +888,7 @@ 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) +static void ll_kill_pointers(struct ll_entry *head,int addr,int shift) { while(head) { int ptr=get_pointer(head->addr); @@ -837,10 +897,11 @@ void ll_kill_pointers(struct ll_entry *head,int addr,int shift) (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift))) { inv_debug("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr); - u_int host_addr=(u_int)kill_pointer(head->addr); + void *host_addr=find_extjump_insn(head->addr); #ifdef __arm__ - needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31); + mark_clear_cache(host_addr); #endif + set_jump_target((int)host_addr,(int)head->addr); } head=head->next; } @@ -864,10 +925,11 @@ void 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); - u_int host_addr=(u_int)kill_pointer(head->addr); + void *host_addr=find_extjump_insn(head->addr); #ifdef __arm__ - needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31); + mark_clear_cache(host_addr); #endif + set_jump_target((int)host_addr,(int)head->addr); next=head->next; free(head); head=next; @@ -991,7 +1053,7 @@ void invalidate_addr(u_int addr) // Anything could have changed, so invalidate everything. void invalidate_all_pages() { - u_int page,n; + u_int page; for(page=0;page<4096;page++) invalidate_page(page); for(page=0;page<1048576;page++) @@ -999,9 +1061,6 @@ void invalidate_all_pages() restore_candidate[(page&2047)>>3]|=1<<(page&7); restore_candidate[((page&2047)>>3)+256]|=1<<(page&7); } - #ifdef __arm__ - __clear_cache((void *)BASE_ADDR,(void *)BASE_ADDR+(1< %x (%d)\n",(int)src,vaddr,page); int *ptr=(int *)(src+4); assert((*ptr&0x0fff0000)==0x059f0000); + (void)ptr; ll_add(jump_out+page,vaddr,src); //int ptr=get_pointer(src); //inv_debug("add_link: Pointer is to %x\n",(int)ptr); @@ -1033,7 +1093,7 @@ void clean_blocks(u_int page) // Don't restore blocks which are about to expire from the cache if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) { u_int start,end; - if(verify_dirty((int)head->addr)) { + if(verify_dirty(head->addr)) { //printf("Possibly Restore %x (%x)\n",head->vaddr, (int)head->addr); u_int i; u_int inv=0; @@ -1054,12 +1114,12 @@ void clean_blocks(u_int page) //printf("page=%x, addr=%x\n",page,head->vaddr); //assert(head->vaddr>>12==(page|0x80000)); ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr); - int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF]; if(ht_bin[0]==head->vaddr) { - ht_bin[1]=(int)clean_addr; // Replace existing entry + ht_bin[1]=(u_int)clean_addr; // Replace existing entry } if(ht_bin[2]==head->vaddr) { - ht_bin[3]=(int)clean_addr; // Replace existing entry + ht_bin[3]=(u_int)clean_addr; // Replace existing entry } } } @@ -2333,23 +2393,25 @@ void imm16_assemble(int i,struct regstat *i_regs) emit_mov(sh,th); } } - if(opcode[i]==0x0d) //ORI - if(sl<0) { - emit_orimm(tl,imm[i],tl); - }else{ - if(!((i_regs->wasconst>>sl)&1)) - emit_orimm(sl,imm[i],tl); - else - emit_movimm(constmap[i][sl]|imm[i],tl); + if(opcode[i]==0x0d) { // ORI + if(sl<0) { + emit_orimm(tl,imm[i],tl); + }else{ + if(!((i_regs->wasconst>>sl)&1)) + emit_orimm(sl,imm[i],tl); + else + emit_movimm(constmap[i][sl]|imm[i],tl); + } } - if(opcode[i]==0x0e) //XORI - if(sl<0) { - emit_xorimm(tl,imm[i],tl); - }else{ - if(!((i_regs->wasconst>>sl)&1)) - emit_xorimm(sl,imm[i],tl); - else - emit_movimm(constmap[i][sl]^imm[i],tl); + if(opcode[i]==0x0e) { // XORI + if(sl<0) { + emit_xorimm(tl,imm[i],tl); + }else{ + if(!((i_regs->wasconst>>sl)&1)) + emit_xorimm(sl,imm[i],tl); + else + emit_movimm(constmap[i][sl]^imm[i],tl); + } } } else { @@ -2533,7 +2595,7 @@ void load_assemble(int i,struct regstat *i_regs) //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... - if(tl<0&&(!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 @@ -2790,7 +2852,7 @@ void load_assemble(int i,struct regstat *i_regs) emit_call((int)memdebug); //emit_popa(); restore_regs(0x100f); - }/**/ + }*/ } #ifndef loadlr_assemble @@ -2806,7 +2868,7 @@ void store_assemble(int i,struct regstat *i_regs) int s,th,tl,map=-1; int addr,temp; int offset; - int jaddr=0,jaddr2,type; + int jaddr=0,type; int memtarget=0,c=0; int agr=AGEN1+(i&1); int faststore_reg_override=0; @@ -2925,7 +2987,7 @@ void store_assemble(int i,struct regstat *i_regs) #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT) emit_callne(invalidate_addr_reg[addr]); #else - jaddr2=(int)out; + int jaddr2=(int)out; emit_jne(0); add_stub(INVCODE_STUB,jaddr2,(int)out,reglist|(1<regmap,CCREG); assert(ccreg==HOST_CCREG); assert(!is_delayslot); + (void)ccreg; emit_movimm(start+i*4,EAX); // Get PC emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // CHECK: is this right? There should probably be an extra cycle... emit_jmp((int)jump_syscall_hle); // XXX @@ -3378,11 +3441,17 @@ void syscall_assemble(int i,struct regstat *i_regs) void hlecall_assemble(int i,struct regstat *i_regs) { + extern void psxNULL(); signed char ccreg=get_reg(i_regs->regmap,CCREG); assert(ccreg==HOST_CCREG); assert(!is_delayslot); + (void)ccreg; emit_movimm(start+i*4+4,0); // Get PC - emit_movimm((int)psxHLEt[source[i]&7],1); + uint32_t hleCode = source[i] & 0x03ffffff; + if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) + emit_movimm((int)psxNULL,1); + else + emit_movimm((int)psxHLEt[hleCode],1); emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // XXX emit_jmp((int)jump_hlecall); } @@ -3392,6 +3461,7 @@ 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); + (void)ccreg; emit_movimm(start+i*4,0); // Get PC emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); emit_jmp((int)jump_intcall); @@ -4193,6 +4263,28 @@ int match_bt(signed char i_regmap[],uint64_t i_is32,uint64_t i_dirty,int addr) return 1; } +#ifdef DRC_DBG +static void drc_dbg_emit_do_cmp(int i) +{ + extern void do_insn_cmp(); + extern int cycle; + u_int hr,reglist=0; + + for(hr=0;hr=0) reglist|=1<\n"); + drc_dbg_emit_do_cmp(t); if(regs[t].regmap_entry[HOST_CCREG]==CCREG&®s[t].regmap[HOST_CCREG]!=CCREG) 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]); @@ -4636,7 +4729,6 @@ static void ujump_assemble_write_ra(int i) void ujump_assemble(int i,struct regstat *i_regs) { - signed char *i_regmap=i_regs->regmap; int ra_done=0; if(i==(ba[i]-start)>>2) assem_debug("idle loop\n"); address_generation(i+1,i_regs,regs[i].regmap_entry); @@ -4644,6 +4736,7 @@ void ujump_assemble(int i,struct regstat *i_regs) int temp=get_reg(branch_regs[i].regmap,PTEMP); if(rt1[i]==31&&temp>=0) { + signed char *i_regmap=i_regs->regmap; int return_address=start+i*4+8; if(get_reg(branch_regs[i].regmap,31)>0) if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp); @@ -4709,9 +4802,8 @@ static void rjump_assemble_write_ra(int i) void rjump_assemble(int i,struct regstat *i_regs) { - signed char *i_regmap=i_regs->regmap; int temp; - int rs,cc,adj; + int rs,cc; int ra_done=0; rs=get_reg(branch_regs[i].regmap,rs1[i]); assert(rs>=0); @@ -4728,6 +4820,7 @@ void rjump_assemble(int i,struct regstat *i_regs) if(rt1[i]==31) { if((temp=get_reg(branch_regs[i].regmap,PTEMP))>=0) { + signed char *i_regmap=i_regs->regmap; int return_address=start+i*4+8; if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp); } @@ -4756,6 +4849,7 @@ void rjump_assemble(int i,struct regstat *i_regs) rjump_assemble_write_ra(i); cc=get_reg(branch_regs[i].regmap,CCREG); assert(cc==HOST_CCREG); + (void)cc; #ifdef USE_MINI_HT int rh=get_reg(branch_regs[i].regmap,RHASH); int ht=get_reg(branch_regs[i].regmap,RHTBL); @@ -5761,7 +5855,6 @@ static void pagespan_assemble(int i,struct regstat *i_regs) int s1h=get_reg(i_regs->regmap,rs1[i]|64); int s2l=get_reg(i_regs->regmap,rs2[i]); int s2h=get_reg(i_regs->regmap,rs2[i]|64); - void *nt_branch=NULL; int taken=0; int nottaken=0; int unconditional=0; @@ -5778,7 +5871,7 @@ static void pagespan_assemble(int i,struct regstat *i_regs) s1h=s2h=-1; } int hr=0; - int addr,alt,ntaddr; + int addr=-1,alt=-1,ntaddr=-1; if(i_regs->regmap[HOST_BTREG]<0) {addr=HOST_BTREG;} else { while(hr>r)&1));*/} + }else {/*printf("i: %x (%d) mismatch(+2): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/} } } } @@ -6783,7 +6876,7 @@ void clean_registers(int istart,int iend,int wr) if(r!=EXCLUDE_REG) { if(regs[i].regmap[r]==regmap_pre[i+1][r]) { regs[i+1].wasdirty&=wont_dirty_i|~(1<>r)&1));*/} + }else {/*printf("i: %x (%d) mismatch(+1): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/} } } } @@ -6826,7 +6919,7 @@ void clean_registers(int istart,int iend,int wr) wont_dirty_i|=((unneeded_reg[i]>>(regmap_pre[i][r]&63))&1)<>r)&1));*/ + /*printf("i: %x (%d) mismatch: %d\n",start+i*4,i,r);assert(!((will_dirty>>r)&1));*/ } } } @@ -6932,13 +7025,14 @@ static void disassemble_inst(int i) {} static int new_dynarec_test(void) { int (*testfunc)(void) = (void *)out; + void *beginning; int ret; + + beginning = start_block(); emit_movimm(DRC_TEST_VAL,0); // test emit_jmpreg(14); literal_pool(0); -#ifdef __arm__ - __clear_cache((void *)testfunc, out); -#endif + end_block(beginning); SysPrintf("testing if we can run recompiled code..\n"); ret = testfunc(); if (ret == DRC_TEST_VAL) @@ -6975,20 +7069,43 @@ void new_dynarec_clear_full() void new_dynarec_init() { SysPrintf("Init new dynarec\n"); - out=(u_char *)BASE_ADDR; -#if BASE_ADDR_FIXED - if (mmap (out, 1<>12]=0; emit_movimm(start,0); emit_writeword(0,(int)&pcaddr); emit_jmp((int)new_dyna_leave); literal_pool(0); -#ifdef __arm__ - __clear_cache((void *)beginning,out); -#endif + end_block(beginning); ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning); return 0; } @@ -8359,7 +8483,7 @@ int new_recompile_block(int addr) // Create entry (branch target) regmap for(hr=0;hr=0) { if(r!=regmap_pre[i][hr]) { @@ -9878,7 +10002,7 @@ int new_recompile_block(int addr) cop1_usable=0; uint64_t is32_pre=0; u_int dirty_pre=0; - u_int beginning=(u_int)out; + void *beginning=start_block(); if((u_int)addr&1) { ds=1; pagespan_ds(); @@ -9932,6 +10056,8 @@ int new_recompile_block(int addr) // branch target entry point instr_addr[i]=(u_int)out; assem_debug("<->\n"); + drc_dbg_emit_do_cmp(i); + // load regs if(regs[i].regmap_entry[HOST_CCREG]==CCREG&®s[i].regmap[HOST_CCREG]!=CCREG) wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty,regs[i].was32); @@ -10151,7 +10277,7 @@ int new_recompile_block(int addr) // replace it with the new address. // Don't add new entries. We'll insert the // ones that actually get used in check_addr(). - int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; + u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; if(ht_bin[0]==vaddr) { ht_bin[1]=entry_point; } @@ -10168,14 +10294,12 @@ int new_recompile_block(int addr) // Align code if(((u_int)out)&7) emit_addnop(13); #endif - assert((u_int)out-beginning>shift)==(base>>shift) || ((ht_bin[3]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) { inv_debug("EXP: Remove hash %x -> %x\n",ht_bin[2],ht_bin[3]);