X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fassem_arm.c;h=95007dfafd43e416be31480f0feb2a29effb51a0;hb=9b495f6ec3f28cf5ed1d41f6af16a9967fcf3e64;hp=c5c2c66e30c834ba50b8a2f371ebcb584da29be3;hpb=2330734fa3064bf3a159c3c56f9a2e005598360e;p=pcsx_rearmed.git diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index c5c2c66e..95007dfa 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -27,8 +27,6 @@ #include "pcnt.h" #include "arm_features.h" -#define unused __attribute__((unused)) - #ifdef DRC_DBG #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-variable" @@ -101,8 +99,6 @@ const u_int invalidate_addr_reg[16] = { 0, 0}; -static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)]; - /* Linker */ static void set_jump_target(void *addr, void *target_) @@ -196,6 +192,7 @@ static void *find_extjump_insn(void *stub) // get address that insn one after stub loads (dyna_linker arg1), // treat it as a pointer to branch insn, // return addr where that branch jumps to +#if 0 static void *get_pointer(void *stub) { //printf("get_pointer(%x)\n",(int)stub); @@ -203,107 +200,7 @@ static void *get_pointer(void *stub) assert((*i_ptr&0x0f000000)==0x0a000000); // b return (u_char *)i_ptr+((*i_ptr<<8)>>6)+8; } - -// Find the "clean" entry point from a "dirty" entry point -// by skipping past the call to verify_code -static void *get_clean_addr(void *addr) -{ - signed int *ptr = addr; - #ifndef HAVE_ARMV7 - ptr+=4; - #else - ptr+=6; - #endif - if((*ptr&0xFF000000)!=0xeb000000) ptr++; - assert((*ptr&0xFF000000)==0xeb000000); // bl instruction - ptr++; - if((*ptr&0xFF000000)==0xea000000) { - return (char *)ptr+((*ptr<<8)>>6)+8; // follow jump - } - return ptr; -} - -static int verify_dirty(const u_int *ptr) -{ - #ifndef HAVE_ARMV7 - u_int offset; - // get from literal pool - assert((*ptr&0xFFFF0000)==0xe59f0000); - offset=*ptr&0xfff; - u_int source=*(u_int*)((void *)ptr+offset+8); - ptr++; - assert((*ptr&0xFFFF0000)==0xe59f0000); - offset=*ptr&0xfff; - u_int copy=*(u_int*)((void *)ptr+offset+8); - ptr++; - assert((*ptr&0xFFFF0000)==0xe59f0000); - offset=*ptr&0xfff; - u_int len=*(u_int*)((void *)ptr+offset+8); - ptr++; - ptr++; - #else - // ARMv7 movw/movt - assert((*ptr&0xFFF00000)==0xe3000000); - u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000); - u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000); - u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000); - ptr+=6; - #endif - if((*ptr&0xFF000000)!=0xeb000000) ptr++; - assert((*ptr&0xFF000000)==0xeb000000); // bl instruction - //printf("verify_dirty: %x %x %x\n",source,copy,len); - return !memcmp((void *)source,(void *)copy,len); -} - -// This doesn't necessarily find all clean entry points, just -// guarantees that it's not dirty -static int isclean(void *addr) -{ - #ifndef HAVE_ARMV7 - u_int *ptr=((u_int *)addr)+4; - #else - u_int *ptr=((u_int *)addr)+6; - #endif - if((*ptr&0xFF000000)!=0xeb000000) ptr++; - if((*ptr&0xFF000000)!=0xeb000000) return 1; // bl instruction - if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code) return 0; - if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0; - return 1; -} - -// get source that block at addr was compiled from (host pointers) -static void get_bounds(void *addr, u_char **start, u_char **end) -{ - u_int *ptr = addr; - #ifndef HAVE_ARMV7 - u_int offset; - // get from literal pool - assert((*ptr&0xFFFF0000)==0xe59f0000); - offset=*ptr&0xfff; - u_int source=*(u_int*)((void *)ptr+offset+8); - ptr++; - //assert((*ptr&0xFFFF0000)==0xe59f0000); - //offset=*ptr&0xfff; - //u_int copy=*(u_int*)((void *)ptr+offset+8); - ptr++; - assert((*ptr&0xFFFF0000)==0xe59f0000); - offset=*ptr&0xfff; - u_int len=*(u_int*)((void *)ptr+offset+8); - ptr++; - ptr++; - #else - // ARMv7 movw/movt - assert((*ptr&0xFFF00000)==0xe3000000); - u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000); - //u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000); - u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000); - ptr+=6; - #endif - if((*ptr&0xFF000000)!=0xeb000000) ptr++; - assert((*ptr&0xFF000000)==0xeb000000); // bl instruction - *start=(u_char *)source; - *end=(u_char *)source+len; -} +#endif // Allocate a specific ARM register. static void alloc_arm_reg(struct regstat *cur,int i,signed char reg,int hr) @@ -473,6 +370,7 @@ static void emit_loadlp(u_int imm,u_int rt) output_w32(0xe5900000|rd_rn_rm(rt,15,0)); } +#ifdef HAVE_ARMV7 static void emit_movw(u_int imm,u_int rt) { assert(imm<65536); @@ -485,6 +383,7 @@ static void emit_movt(u_int imm,u_int rt) assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000); output_w32(0xe3400000|rd_rn_rm(rt,0,0)|((imm>>16)&0xfff)|((imm>>12)&0xf0000)); } +#endif static void emit_movimm(u_int imm,u_int rt) { @@ -522,38 +421,33 @@ static void emit_pcreladdr(u_int rt) static void emit_loadreg(int r, int hr) { - if(r&64) { - SysPrintf("64bit load in 32bit mode!\n"); - assert(0); - return; - } - if((r&63)==0) + assert(hr != EXCLUDE_REG); + if (r == 0) emit_zeroreg(hr); else { - int addr = (int)&psxRegs.GPR.r[r]; + void *addr; switch (r) { //case HIREG: addr = &hi; break; //case LOREG: addr = &lo; break; - case CCREG: addr = (int)&cycle_count; break; - case CSREG: addr = (int)&Status; break; - case INVCP: addr = (int)&invc_ptr; break; - case ROREG: addr = (int)&ram_offset; break; - default: assert(r < 34); break; + case CCREG: addr = &cycle_count; break; + case CSREG: addr = &Status; break; + case INVCP: addr = &invc_ptr; break; + case ROREG: addr = &ram_offset; break; + default: + assert(r < 34); + addr = &psxRegs.GPR.r[r]; + break; } - u_int offset = addr-(u_int)&dynarec_local; + u_int offset = (u_char *)addr - (u_char *)&dynarec_local; assert(offset<4096); - assem_debug("ldr %s,fp+%d\n",regname[hr],offset); + assem_debug("ldr %s,fp+%d # r%d\n",regname[hr],offset,r); output_w32(0xe5900000|rd_rn_rm(hr,FP,0)|offset); } } static void emit_storereg(int r, int hr) { - if(r&64) { - SysPrintf("64bit store in 32bit mode!\n"); - assert(0); - return; - } + assert(hr != EXCLUDE_REG); int addr = (int)&psxRegs.GPR.r[r]; switch (r) { //case HIREG: addr = &hi; break; @@ -563,7 +457,7 @@ static void emit_storereg(int r, int hr) } u_int offset = addr-(u_int)&dynarec_local; assert(offset<4096); - assem_debug("str %s,fp+%d\n",regname[hr],offset); + assem_debug("str %s,fp+%d # r%d\n",regname[hr],offset,r); output_w32(0xe5800000|rd_rn_rm(hr,FP,0)|offset); } @@ -949,6 +843,14 @@ static void emit_cmovae_imm(int imm,int rt) output_w32(0x23a00000|rd_rn_rm(rt,0,0)|armval); } +static void emit_cmovs_imm(int imm,int rt) +{ + assem_debug("movmi %s,#%d\n",regname[rt],imm); + u_int armval; + genimm_checked(imm,&armval); + output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval); +} + static void emit_cmovne_reg(int rs,int rt) { assem_debug("movne %s,%s\n",regname[rt],regname[rs]); @@ -995,6 +897,12 @@ static void emit_cmp(int rs,int rt) output_w32(0xe1500000|rd_rn_rm(0,rs,rt)); } +static void emit_cmpcs(int rs,int rt) +{ + assem_debug("cmpcs %s,%s\n",regname[rs],regname[rt]); + output_w32(0x21500000|rd_rn_rm(0,rs,rt)); +} + static void emit_set_gz32(int rs, int rt) { //assem_debug("set_gz32\n"); @@ -1123,6 +1031,15 @@ static void emit_jcc(const void *a_) output_w32(0x3a000000|offset); } +static void *emit_cbz(int rs, const void *a) +{ + void *ret; + emit_test(rs, rs); + ret = out; + emit_jeq(a); + return ret; +} + static unused void emit_callreg(u_int r) { assert(r<15); @@ -1482,13 +1399,10 @@ static void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt) } // special case for checking invalid_code -static void emit_cmpmem_indexedsr12_reg(int base,int r,int imm) +static void emit_ldrb_indexedsr12_reg(int base, int r, int rt) { - assert(imm<128&&imm>=0); - assert(r>=0&&r<16); - assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]); - output_w32(0xe7d00000|rd_rn_rm(HOST_TEMPREG,base,r)|0x620); - emit_cmpimm(HOST_TEMPREG,imm); + assem_debug("ldrb %s,%s,%s lsr #12\n",regname[rt],regname[base],regname[r]); + output_w32(0xe7d00000|rd_rn_rm(rt,base,r)|0x620); } static void emit_callne(int a) @@ -1521,14 +1435,6 @@ static void emit_orrne_imm(int rs,int imm,int rt) output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval); } -static void emit_andne_imm(int rs,int imm,int rt) -{ - u_int armval; - genimm_checked(imm,&armval); - assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm); - output_w32(0x12000000|rd_rn_rm(rt,rs,0)|armval); -} - static unused void emit_addpl_imm(int rs,int imm,int rt) { u_int armval; @@ -1629,7 +1535,7 @@ static void literal_pool_jumpover(int n) } // parsed by get_pointer, find_extjump_insn -static void emit_extjump2(u_char *addr, u_int target, void *linker) +static void emit_extjump(u_char *addr, u_int target) { u_char *ptr=(u_char *)addr; assert((ptr[3]&0x0e)==0xa); @@ -1637,19 +1543,9 @@ static void emit_extjump2(u_char *addr, u_int target, void *linker) emit_loadlp(target,0); emit_loadlp((u_int)addr,1); - assert(addr>=ndrc->translation_cache&&addr<(ndrc->translation_cache+(1<=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000)); -//DEBUG > -#ifdef DEBUG_CYCLE_COUNT - emit_readword(&last_count,ECX); - emit_add(HOST_CCREG,ECX,HOST_CCREG); - emit_readword(&next_interupt,ECX); - emit_writeword(HOST_CCREG,&Count); - emit_sub(HOST_CCREG,ECX,HOST_CCREG); - emit_writeword(ECX,&last_count); -#endif -//DEBUG < - emit_far_jump(linker); + assert(ndrc->translation_cache <= addr && + addr < ndrc->translation_cache + sizeof(ndrc->translation_cache)); + emit_far_jump(dyna_linker); } static void check_extjump2(void *src) @@ -1804,7 +1700,7 @@ static void inline_readstub(enum stub_type type, int i, u_int addr, { int rs=get_reg(regmap,target); int rt=get_reg(regmap,target); - if(rs<0) rs=get_reg(regmap,-1); + if(rs<0) rs=get_reg_temp(regmap); assert(rs>=0); u_int is_dynamic; uintptr_t host_addr = 0; @@ -1958,7 +1854,7 @@ static void do_writestub(int n) static void inline_writestub(enum stub_type type, int i, u_int addr, const signed char regmap[], int target, int adj, u_int reglist) { - int rs=get_reg(regmap,-1); + int rs=get_reg_temp(regmap); int rt=get_reg(regmap,target); assert(rs>=0); assert(rt>=0); @@ -1992,42 +1888,6 @@ static void inline_writestub(enum stub_type type, int i, u_int addr, restore_regs(reglist); } -// this output is parsed by verify_dirty, get_bounds, isclean, get_clean_addr -static void do_dirty_stub_emit_args(u_int arg0, u_int source_len) -{ - #ifndef HAVE_ARMV7 - emit_loadlp((int)source, 1); - emit_loadlp((int)copy, 2); - emit_loadlp(source_len, 3); - #else - emit_movw(((u_int)source)&0x0000FFFF, 1); - emit_movw(((u_int)copy)&0x0000FFFF, 2); - emit_movt(((u_int)source)&0xFFFF0000, 1); - emit_movt(((u_int)copy)&0xFFFF0000, 2); - emit_movw(source_len, 3); - #endif - emit_movimm(arg0, 0); -} - -static void *do_dirty_stub(int i, u_int source_len) -{ - assem_debug("do_dirty_stub %x\n",start+i*4); - do_dirty_stub_emit_args(start + i*4, source_len); - emit_far_call(verify_code); - void *entry = out; - load_regs_entry(i); - if (entry == out) - entry = instr_addr[i]; - emit_jmp(instr_addr[i]); - return entry; -} - -static void do_dirty_stub_ds(u_int source_len) -{ - do_dirty_stub_emit_args(start + 1, source_len); - emit_far_call(verify_code_ds); -} - /* Special assem */ static void c2op_prologue(u_int op, int i, const struct regstat *i_regs, u_int reglist) @@ -2119,10 +1979,10 @@ static void c2op_assemble(int i, const struct regstat *i_regs) } #else if(cv==3&&shift) - emit_far_call((int)gteMVMVA_part_cv3sh12_arm); + emit_far_call(gteMVMVA_part_cv3sh12_arm); else { emit_movimm(shift,1); - emit_far_call((int)(need_flags?gteMVMVA_part_arm:gteMVMVA_part_nf_arm)); + emit_far_call(need_flags?gteMVMVA_part_arm:gteMVMVA_part_nf_arm); } if(need_flags||need_ir) c2op_call_MACtoIR(lm,need_flags); @@ -2200,11 +2060,11 @@ static void c2op_ctc2_31_assemble(signed char sl, signed char temp) static void do_mfc2_31_one(u_int copr,signed char temp) { emit_readword(®_cop2d[copr],temp); - emit_testimm(temp,0x8000); // do we need this? - emit_andne_imm(temp,0,temp); - emit_cmpimm(temp,0xf80); - emit_andimm(temp,0xf80,temp); - emit_cmovae_imm(0xf80,temp); + emit_lsls_imm(temp,16,temp); + emit_cmovs_imm(0,temp); + emit_cmpimm(temp,0xf80<<16); + emit_andimm(temp,0xf80<<16,temp); + emit_cmovae_imm(0xf80<<16,temp); } static void c2op_mfc2_29_assemble(signed char tl, signed char temp) @@ -2214,11 +2074,11 @@ static void c2op_mfc2_29_assemble(signed char tl, signed char temp) temp = HOST_TEMPREG; } do_mfc2_31_one(9,temp); - emit_shrimm(temp,7,tl); + emit_shrimm(temp,7+16,tl); do_mfc2_31_one(10,temp); - emit_orrshr_imm(temp,2,tl); + emit_orrshr_imm(temp,2+16,tl); do_mfc2_31_one(11,temp); - emit_orrshl_imm(temp,3,tl); + emit_orrshr_imm(temp,-3+16,tl); emit_writeword(tl,®_cop2d[29]); if (temp == HOST_TEMPREG) host_tempreg_release();