X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=libpcsxcore%2Fnew_dynarec%2Fassem_arm.c;h=ed00103fd192701fa960905858719c6064440713;hb=d1e4ebd9988a9a5d9fb38b89f19e24b9ab6029d7;hp=d0b1bd7941ee5fd10a7644ffc90f0f321bac1d68;hpb=be516ebe45e48044b599e9d9f9f2d296c3f3ee62;p=pcsx_rearmed.git diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index d0b1bd79..ed00103f 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -49,14 +49,6 @@ u_char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096))); #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif -extern int cycle_count; -extern int last_count; -extern int pcaddr; -extern int pending_exception; -extern int branch_target; -extern uint64_t readmem_dword; -extern u_int mini_ht[32][2]; - void indirect_jump_indexed(); void indirect_jump(); void do_interrupt(); @@ -289,7 +281,6 @@ static int isclean(void *addr) 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_vm) return 0; if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0; return 1; } @@ -423,17 +414,23 @@ static void genimm_checked(u_int imm,u_int *encoded) static u_int genjmp(u_int addr) { - int offset=addr-(int)out-8; - if(offset<-33554432||offset>=33554432) { - if (addr>2) { - SysPrintf("genjmp: out of range: %08x\n", offset); - exit(1); - } + if (addr < 3) return 0; // a branch that will be patched later + int offset = addr-(int)out-8; + if (offset < -33554432 || offset >= 33554432) { + SysPrintf("genjmp: out of range: %08x\n", offset); + abort(); return 0; } return ((u_int)offset>>2)&0xffffff; } +static unused void emit_breakpoint(void) +{ + assem_debug("bkpt #0\n"); + //output_w32(0xe1200070); + output_w32(0xe7f001f0); +} + static void emit_mov(int rs,int rt) { assem_debug("mov %s,%s\n",regname[rt],regname[rs]); @@ -452,12 +449,6 @@ static void emit_add(int rs1,int rs2,int rt) output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2)); } -static void emit_adds(int rs1,int rs2,int rt) -{ - assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]); - output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2)); -} - static void emit_adcs(int rs1,int rs2,int rt) { assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]); @@ -546,12 +537,15 @@ static void emit_loadreg(int r, int hr) if((r&63)==0) emit_zeroreg(hr); else { - int addr=((int)reg)+((r&63)<>4); - if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4); - if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4); - if(r==CCREG) addr=(int)&cycle_count; - if(r==CSREG) addr=(int)&Status; - if(r==INVCP) addr=(int)&invc_ptr; + int addr = (int)&psxRegs.GPR.r[r]; + 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; + default: assert(r < 34); break; + } u_int offset = addr-(u_int)&dynarec_local; assert(offset<4096); assem_debug("ldr %s,fp+%d\n",regname[hr],offset); @@ -566,10 +560,13 @@ static void emit_storereg(int r, int hr) assert(0); return; } - int addr=((int)reg)+((r&63)<>4); - if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4); - if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4); - if(r==CCREG) addr=(int)&cycle_count; + int addr = (int)&psxRegs.GPR.r[r]; + switch (r) { + //case HIREG: addr = &hi; break; + //case LOREG: addr = &lo; break; + case CCREG: addr = (int)&cycle_count; break; + default: assert(r < 34); break; + } u_int offset = addr-(u_int)&dynarec_local; assert(offset<4096); assem_debug("str %s,fp+%d\n",regname[hr],offset); @@ -722,23 +719,6 @@ static void emit_addnop(u_int r) output_w32(0xe2800000|rd_rn_rm(r,r,0)); } -static void emit_adcimm(u_int rs,int imm,u_int rt) -{ - u_int armval; - genimm_checked(imm,&armval); - assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm); - output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval); -} - -static void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl) -{ - // TODO: if(genimm(imm,&armval)) ... - // else - emit_movimm(imm,HOST_TEMPREG); - emit_adds(HOST_TEMPREG,rsl,rtl); - emit_adcimm(rsh,0,rth); -} - static void emit_andimm(int rs,int imm,int rt) { u_int armval; @@ -1049,7 +1029,7 @@ static void emit_set_if_carry32(int rs1, int rs2, int rt) static void emit_call(const void *a_) { int a = (int)a_; - assem_debug("bl %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a)); + assem_debug("bl %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a_)); u_int offset=genjmp(a); output_w32(0xeb000000|offset); } @@ -1057,7 +1037,7 @@ static void emit_call(const void *a_) static void emit_jmp(const void *a_) { int a = (int)a_; - assem_debug("b %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a)); + assem_debug("b %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a_)); u_int offset=genjmp(a); output_w32(0xea000000|offset); } @@ -1070,56 +1050,63 @@ static void emit_jne(const void *a_) output_w32(0x1a000000|offset); } -static void emit_jeq(int a) +static void emit_jeq(const void *a_) { + int a = (int)a_; assem_debug("beq %x\n",a); u_int offset=genjmp(a); output_w32(0x0a000000|offset); } -static void emit_js(int a) +static void emit_js(const void *a_) { + int a = (int)a_; assem_debug("bmi %x\n",a); u_int offset=genjmp(a); output_w32(0x4a000000|offset); } -static void emit_jns(int a) +static void emit_jns(const void *a_) { + int a = (int)a_; assem_debug("bpl %x\n",a); u_int offset=genjmp(a); output_w32(0x5a000000|offset); } -static void emit_jl(int a) +static void emit_jl(const void *a_) { + int a = (int)a_; assem_debug("blt %x\n",a); u_int offset=genjmp(a); output_w32(0xba000000|offset); } -static void emit_jge(int a) +static void emit_jge(const void *a_) { + int a = (int)a_; assem_debug("bge %x\n",a); u_int offset=genjmp(a); output_w32(0xaa000000|offset); } -static void emit_jno(int a) +static void emit_jno(const void *a_) { + int a = (int)a_; assem_debug("bvc %x\n",a); u_int offset=genjmp(a); output_w32(0x7a000000|offset); } -static void emit_jc(int a) +static void emit_jc(const void *a_) { + int a = (int)a_; assem_debug("bcs %x\n",a); u_int offset=genjmp(a); output_w32(0x2a000000|offset); } -static void emit_jcc(void *a_) +static void emit_jcc(const void *a_) { int a = (int)a_; assem_debug("bcc %x\n",a); @@ -1400,21 +1387,6 @@ static void emit_rsbimm(int rs, int imm, int rt) output_w32(0xe2600000|rd_rn_rm(rt,rs,0)|armval); } -// Load 2 immediates optimizing for small code size -static void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2) -{ - emit_movimm(imm1,rt1); - u_int armval; - if(genimm(imm2-imm1,&armval)) { - assem_debug("add %s,%s,#%d\n",regname[rt2],regname[rt1],imm2-imm1); - output_w32(0xe2800000|rd_rn_rm(rt2,rt1,0)|armval); - }else if(genimm(imm1-imm2,&armval)) { - assem_debug("sub %s,%s,#%d\n",regname[rt2],regname[rt1],imm1-imm2); - output_w32(0xe2400000|rd_rn_rm(rt2,rt1,0)|armval); - } - else emit_movimm(imm2,rt2); -} - // Conditionally select one of two immediates, optimizing for small code size // This will only be called if HAVE_CMOV_IMM is defined static void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt) @@ -1597,7 +1569,8 @@ static void literal_pool_jumpover(int n) set_jump_target(jaddr, out); } -static void emit_extjump2(u_char *addr, int target, void *linker) +// parsed by get_pointer, find_extjump_insn +static void emit_extjump2(u_char *addr, u_int target, void *linker) { u_char *ptr=(u_char *)addr; assert((ptr[3]&0x0e)==0xa); @@ -1620,14 +1593,11 @@ static void emit_extjump2(u_char *addr, int target, void *linker) emit_jmp(linker); } -static void emit_extjump(void *addr, int target) -{ - emit_extjump2(addr, target, dyna_linker); -} - -static void emit_extjump_ds(void *addr, int target) +static void check_extjump2(void *src) { - emit_extjump2(addr, target, dyna_linker_ds); + u_int *ptr = src; + assert((ptr[1] & 0x0fff0000) == 0x059f0000); // ldr rx, [pc, #ofs] + (void)ptr; } // put rt_val into rt, potentially making use of rs with value rs_val @@ -1674,23 +1644,6 @@ static int is_similar_value(u_int v1,u_int v2) return 0; } -// trashes r2 -static void pass_args(int a0, int a1) -{ - if(a0==1&&a1==0) { - // must swap - emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0); - } - else if(a0!=0&&a1==0) { - emit_mov(a1,1); - if (a0>=0) emit_mov(a0,0); - } - else { - if(a0>=0&&a0!=0) emit_mov(a0,0); - if(a1>=0&&a1!=1) emit_mov(a1,1); - } -} - static void mov_loadtype_adj(enum stub_type type,int rs,int rt) { switch(type) { @@ -1787,40 +1740,14 @@ static void do_readstub(int n) emit_jmp(stubs[n].retaddr); // return address } -// return memhandler, or get directly accessable address and return 0 -static void *get_direct_memhandler(void *table,u_int addr,enum stub_type type,u_int *addr_host) -{ - u_int l1,l2=0; - l1=((u_int *)table)[addr>>12]; - if((l1&(1<<31))==0) { - u_int v=l1<<1; - *addr_host=v+addr; - return NULL; - } - else { - l1<<=1; - if(type==LOADB_STUB||type==LOADBU_STUB||type==STOREB_STUB) - l2=((u_int *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)]; - else if(type==LOADH_STUB||type==LOADHU_STUB||type==STOREH_STUB) - l2=((u_int *)l1)[0x1000/4 + (addr&0xfff)/2]; - else - l2=((u_int *)l1)[(addr&0xfff)/4]; - if((l2&(1<<31))==0) { - u_int v=l2<<1; - *addr_host=v+(addr&0xfff); - return NULL; - } - return (void *)(l2<<1); - } -} - static void inline_readstub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist) { int rs=get_reg(regmap,target); int rt=get_reg(regmap,target); if(rs<0) rs=get_reg(regmap,-1); assert(rs>=0); - u_int host_addr=0,is_dynamic,far_call=0; + u_int is_dynamic,far_call=0; + uintptr_t host_addr = 0; void *handler; int cc=get_reg(regmap,CCREG); if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj+1),cc,target?rs:-1,rt)) @@ -1983,7 +1910,7 @@ static void inline_writestub(enum stub_type type, int i, u_int addr, signed char int rt=get_reg(regmap,target); assert(rs>=0); assert(rt>=0); - u_int host_addr=0; + uintptr_t host_addr = 0; void *handler = get_direct_memhandler(mem_wtab, addr, type, &host_addr); if (handler == NULL) { if(addr!=host_addr) @@ -2101,36 +2028,28 @@ static void do_unalignedwritestub(int n) #endif } -static void do_invstub(int n) +// this output is parsed by verify_dirty, get_bounds, isclean, get_clean_addr +static void do_dirty_stub_emit_args(u_int arg0) { - literal_pool(20); - u_int reglist=stubs[n].a; - set_jump_target(stubs[n].addr, out); - save_regs(reglist); - if(stubs[n].b!=0) emit_mov(stubs[n].b,0); - emit_call(&invalidate_addr); - restore_regs(reglist); - emit_jmp(stubs[n].retaddr); // return address + #ifndef HAVE_ARMV7 + emit_loadlp((int)source, 1); + emit_loadlp((int)copy, 2); + emit_loadlp(slen*4, 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(slen*4, 3); + #endif + emit_movimm(arg0, 0); } -void *do_dirty_stub(int i) +static void *do_dirty_stub(int i) { assem_debug("do_dirty_stub %x\n",start+i*4); - u_int addr=(u_int)source; - // Careful about the code output here, verify_dirty needs to parse it. - #ifndef HAVE_ARMV7 - emit_loadlp(addr,1); - emit_loadlp((int)copy,2); - emit_loadlp(slen*4,3); - #else - emit_movw(addr&0x0000FFFF,1); - emit_movw(((u_int)copy)&0x0000FFFF,2); - emit_movt(addr&0xFFFF0000,1); - emit_movt(((u_int)copy)&0xFFFF0000,2); - emit_movw(slen*4,3); - #endif - emit_movimm(start+i*4,0); - emit_call((int)start<(int)0xC0000000?&verify_code:&verify_code_vm); + do_dirty_stub_emit_args(start + i*4); + emit_call(verify_code); void *entry = out; load_regs_entry(i); if (entry == out) @@ -2141,20 +2060,8 @@ void *do_dirty_stub(int i) static void do_dirty_stub_ds() { - // Careful about the code output here, verify_dirty needs to parse it. - #ifndef HAVE_ARMV7 - emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1); - emit_loadlp((int)copy,2); - emit_loadlp(slen*4,3); - #else - emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1); - emit_movw(((u_int)copy)&0x0000FFFF,2); - emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1); - emit_movt(((u_int)copy)&0xFFFF0000,2); - emit_movw(slen*4,3); - #endif - emit_movimm(start+1,0); - emit_call(&verify_code_ds); + do_dirty_stub_emit_args(start + 1); + emit_call(verify_code_ds); } /* Special assem */ @@ -2276,7 +2183,7 @@ static void loadlr_assemble_arm(int i,struct regstat *i_regs) int offset; void *jaddr=0; int memtarget=0,c=0; - int fastload_reg_override=0; + int fastio_reg_override=-1; u_int hr,reglist=0; tl=get_reg(i_regs->regmap,rt1[i]); s=get_reg(i_regs->regmap,rs1[i]); @@ -2304,12 +2211,13 @@ static void loadlr_assemble_arm(int i,struct regstat *i_regs) }else{ emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR } - jaddr=emit_fastpath_cmp_jump(i,temp2,&fastload_reg_override); + jaddr=emit_fastpath_cmp_jump(i,temp2,&fastio_reg_override); } else { if(ram_offset&&memtarget) { + host_tempreg_acquire(); emit_addimm(temp2,ram_offset,HOST_TEMPREG); - fastload_reg_override=HOST_TEMPREG; + fastio_reg_override=HOST_TEMPREG; } if (opcode[i]==0x22||opcode[i]==0x26) { emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR @@ -2320,8 +2228,9 @@ static void loadlr_assemble_arm(int i,struct regstat *i_regs) if (opcode[i]==0x22||opcode[i]==0x26) { // LWL/LWR if(!c||memtarget) { int a=temp2; - if(fastload_reg_override) a=fastload_reg_override; + if(fastio_reg_override>=0) a=fastio_reg_override; emit_readword_indexed(0,a,temp2); + if(fastio_reg_override==HOST_TEMPREG) host_tempreg_release(); if(jaddr) add_stub_r(LOADW_STUB,jaddr,out,i,temp2,i_regs,ccadj[i],reglist); } else @@ -2563,7 +2472,7 @@ static void multdiv_assemble_arm(int i,struct regstat *i_regs) emit_negmi(quotient,quotient); // .. quotient and .. emit_negmi(remainder,remainder); // .. remainder for div0 case (will be negated back after jump) emit_movs(d2,HOST_TEMPREG); - emit_jeq((int)out+52); // Division by zero + emit_jeq(out+52); // Division by zero emit_negsmi(HOST_TEMPREG,HOST_TEMPREG); #ifdef HAVE_ARMV5 emit_clz(HOST_TEMPREG,quotient); @@ -2572,7 +2481,7 @@ static void multdiv_assemble_arm(int i,struct regstat *i_regs) emit_movimm(0,quotient); emit_addpl_imm(quotient,1,quotient); emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG); - emit_jns((int)out-2*4); + emit_jns(out-2*4); #endif emit_orimm(quotient,1<<31,quotient); emit_shr(quotient,quotient,quotient); @@ -2599,7 +2508,7 @@ static void multdiv_assemble_arm(int i,struct regstat *i_regs) emit_mov(d1,remainder); emit_movimm(0xffffffff,quotient); // div0 case emit_test(d2,d2); - emit_jeq((int)out+40); // Division by zero + emit_jeq(out+40); // Division by zero #ifdef HAVE_ARMV5 emit_clz(d2,HOST_TEMPREG); emit_movimm(1<<31,quotient); @@ -2608,7 +2517,7 @@ static void multdiv_assemble_arm(int i,struct regstat *i_regs) emit_movimm(0,HOST_TEMPREG); emit_addpl_imm(HOST_TEMPREG,1,HOST_TEMPREG); emit_lslpls_imm(d2,1,d2); - emit_jns((int)out-2*4); + emit_jns(out-2*4); emit_movimm(1<<31,quotient); #endif emit_shr(quotient,HOST_TEMPREG,quotient); @@ -2635,6 +2544,11 @@ static void multdiv_assemble_arm(int i,struct regstat *i_regs) } #define multdiv_assemble multdiv_assemble_arm +static void do_jump_vaddr(int rs) +{ + emit_jmp(jump_vaddr_reg[rs]); +} + static void do_preload_rhash(int r) { // Don't need this for ARM. On x86, this puts the value 0xf8 into the // register. On ARM the hash can be done with a single instruction (below) @@ -2657,11 +2571,11 @@ static void do_miniht_jump(int rs,int rh,int ht) { emit_cmp(rh,rs); emit_ldreq_indexed(ht,4,15); #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK - emit_mov(rs,7); - emit_jmp(jump_vaddr_reg[7]); - #else - emit_jmp(jump_vaddr_reg[rs]); + if(rs!=7) + emit_mov(rs,7); + rs=7; #endif + do_jump_vaddr(rs); } static void do_miniht_insert(u_int return_address,int rt,int temp) {