X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fnew_dynarec.c;h=892d8e946442f8413ec867463bc076181e672aba;hb=f9e9616e4ccc5de395bb548e95785565a42eed14;hp=db751266e4ac46efa63d3c7fedeef622cde2f216;hpb=33a1eda13ebe624fc1233d820c8db7dcd7aba0d8;p=pcsx_rearmed.git diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index db751266..892d8e94 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -81,7 +81,7 @@ static Jit g_jit; #endif #define RAM_SIZE 0x200000 -#define MAXBLOCK 4096 +#define MAXBLOCK 2048 #define MAX_OUTPUT_BLOCK_SIZE 262144 #define EXPIRITY_OFFSET (MAX_OUTPUT_BLOCK_SIZE * 2) #define PAGE_COUNT 1024 @@ -158,14 +158,14 @@ struct regstat { signed char regmap_entry[HOST_REGS]; signed char regmap[HOST_REGS]; - uint64_t wasdirty; - uint64_t dirty; - uint64_t u; + u_int wasdirty; + u_int dirty; u_int wasconst; // before; for example 'lw r2, (r2)' wasconst is true u_int isconst; // ... but isconst is false when r2 is known (hr) u_int loadedconst; // host regs that have constants loaded u_int noevict; // can't evict this hr (alloced by current op) //u_int waswritten; // MIPS regs that were used as store base before + uint64_t u; }; struct ht_entry @@ -242,8 +242,13 @@ static struct decoded_insn u_char is_delay_load:1; // is_load + MFC/CFC u_char is_exception:1; // unconditional, also interp. fallback u_char may_except:1; // might generate an exception + u_char ls_type:2; // load/store type (ls_width_type) } dops[MAXBLOCK]; +enum ls_width_type { + LS_8 = 0, LS_16, LS_32, LS_LR +}; + static struct compile_info { int imm; @@ -409,9 +414,9 @@ static void invalidate_block(struct block_info *block); static void exception_assemble(int i, const struct regstat *i_regs, int ccadj_); // Needed by assembler -static void wb_register(signed char r, const signed char regmap[], uint64_t dirty); -static void wb_dirtys(const signed char i_regmap[], uint64_t i_dirty); -static void wb_needed_dirtys(const signed char i_regmap[], uint64_t i_dirty, int addr); +static void wb_register(signed char r, const signed char regmap[], u_int dirty); +static void wb_dirtys(const signed char i_regmap[], u_int i_dirty); +static void wb_needed_dirtys(const signed char i_regmap[], u_int i_dirty, int addr); static void load_all_regs(const signed char i_regmap[]); static void load_needed_regs(const signed char i_regmap[], const signed char next_regmap[]); static void load_regs_entry(int t); @@ -2288,7 +2293,7 @@ static void add_stub_r(enum stub_type type, void *addr, void *retaddr, } // Write out a single register -static void wb_register(signed char r, const signed char regmap[], uint64_t dirty) +static void wb_register(signed char r, const signed char regmap[], u_int dirty) { int hr; for(hr=0;hr>2; @@ -4738,6 +4746,7 @@ static void wb_needed_dirtys(const signed char i_regmap[], uint64_t i_dirty, int } // Load all registers (except cycle count) +#ifndef load_all_regs static void load_all_regs(const signed char i_regmap[]) { int hr; @@ -4754,48 +4763,31 @@ static void load_all_regs(const signed char i_regmap[]) } } } +#endif // Load all current registers also needed by next instruction static void load_needed_regs(const signed char i_regmap[], const signed char next_regmap[]) { + signed char regmap_sel[HOST_REGS]; int hr; - for(hr=0;hr=0) { - if(i_regmap[hr]==0) { - emit_zeroreg(hr); - } - else - if(i_regmap[hr]>0 && i_regmap[hr]= 0) + regmap_sel[hr] = i_regmap[hr]; } + load_all_regs(regmap_sel); } // Load all regs, storing cycle count if necessary static void load_regs_entry(int t) { - int hr; if(dops[t].is_ds) emit_addimm(HOST_CCREG,CLOCK_ADJUST(1),HOST_CCREG); else if(cinfo[t].ccadj) emit_addimm(HOST_CCREG,-cinfo[t].ccadj,HOST_CCREG); if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) { emit_storereg(CCREG,HOST_CCREG); } - // Load 32-bit regs - for(hr=0;hr=0&®s[t].regmap_entry[hr]> 21) & 0x1f; break; - case 0x20: set_mnemonic(i, "LB"); type=LOAD; break; - case 0x21: set_mnemonic(i, "LH"); type=LOAD; break; - case 0x22: set_mnemonic(i, "LWL"); type=LOADLR; break; - case 0x23: set_mnemonic(i, "LW"); type=LOAD; break; - case 0x24: set_mnemonic(i, "LBU"); type=LOAD; break; - case 0x25: set_mnemonic(i, "LHU"); type=LOAD; break; - case 0x26: set_mnemonic(i, "LWR"); type=LOADLR; break; - case 0x28: set_mnemonic(i, "SB"); type=STORE; break; - case 0x29: set_mnemonic(i, "SH"); type=STORE; break; - case 0x2A: set_mnemonic(i, "SWL"); type=STORELR; break; - case 0x2B: set_mnemonic(i, "SW"); type=STORE; break; - case 0x2E: set_mnemonic(i, "SWR"); type=STORELR; break; - case 0x32: set_mnemonic(i, "LWC2"); type=C2LS; break; - case 0x3A: set_mnemonic(i, "SWC2"); type=C2LS; break; + case 0x20: set_mnemonic(i, "LB"); type=LOAD; ls_type = LS_8; break; + case 0x21: set_mnemonic(i, "LH"); type=LOAD; ls_type = LS_16; break; + case 0x22: set_mnemonic(i, "LWL"); type=LOADLR; ls_type = LS_LR; break; + case 0x23: set_mnemonic(i, "LW"); type=LOAD; ls_type = LS_32; break; + case 0x24: set_mnemonic(i, "LBU"); type=LOAD; ls_type = LS_8; break; + case 0x25: set_mnemonic(i, "LHU"); type=LOAD; ls_type = LS_16; break; + case 0x26: set_mnemonic(i, "LWR"); type=LOADLR; ls_type = LS_LR; break; + case 0x28: set_mnemonic(i, "SB"); type=STORE; ls_type = LS_8; break; + case 0x29: set_mnemonic(i, "SH"); type=STORE; ls_type = LS_16; break; + case 0x2A: set_mnemonic(i, "SWL"); type=STORELR; ls_type = LS_LR; break; + case 0x2B: set_mnemonic(i, "SW"); type=STORE; ls_type = LS_32; break; + case 0x2E: set_mnemonic(i, "SWR"); type=STORELR; ls_type = LS_LR; break; + case 0x32: set_mnemonic(i, "LWC2"); type=C2LS; ls_type = LS_32; break; + case 0x3A: set_mnemonic(i, "SWC2"); type=C2LS; ls_type = LS_32; break; case 0x3B: if (Config.HLE && (src & 0x03ffffff) < ARRAY_SIZE(psxHLEt)) { set_mnemonic(i, "HLECALL"); @@ -6694,8 +6687,9 @@ static void disassemble_one(int i, u_int src) } if (type == INTCALL) SysPrintf("NI %08x @%08x (%08x)\n", src, start + i*4, start); - dops[i].itype=type; - dops[i].opcode2=op2; + dops[i].itype = type; + dops[i].opcode2 = op2; + dops[i].ls_type = ls_type; /* Get registers/immediates */ dops[i].use_lt1=0; gte_rs[i]=gte_rt[i]=0; @@ -6841,6 +6835,7 @@ static void disassemble_one(int i, u_int src) static noinline void pass1_disassemble(u_int pagelimit) { int i, j, done = 0, ni_count = 0; + int ds_next = 0; for (i = 0; !done; i++) { @@ -6848,6 +6843,7 @@ static noinline void pass1_disassemble(u_int pagelimit) unsigned int type, op, op2; disassemble_one(i, source[i]); + dops[i].is_ds = ds_next; ds_next = 0; type = dops[i].itype; op = dops[i].opcode; op2 = dops[i].opcode2; @@ -6880,6 +6876,7 @@ static noinline void pass1_disassemble(u_int pagelimit) dops[i].is_store = type == STORE || type == STORELR || op == 0x3a; // SWC2 dops[i].is_exception = type == SYSCALL || type == HLECALL || type == INTCALL; dops[i].may_except = dops[i].is_exception || (type == ALU && (op2 == 0x20 || op2 == 0x22)) || op == 8; + ds_next = dops[i].is_jump; if (((op & 0x37) == 0x21 || op == 0x25) // LH/SH/LHU && ((cinfo[i].imm & 1) || Config.PreciseExceptions)) @@ -6984,7 +6981,8 @@ static noinline void pass1_disassemble(u_int pagelimit) // Don't recompile stuff that's already compiled if(check_addr(start+i*4+4)) done=1; // Don't get too close to the limit - if(i>MAXBLOCK/2) done=1; + if (i > MAXBLOCK - 64) + done = 1; } if (dops[i].itype == HLECALL) stop = 1; @@ -7004,7 +7002,8 @@ static noinline void pass1_disassemble(u_int pagelimit) //assert(i 8 || dops[i].opcode == 0x11)) { done=stop_after_jal=1; @@ -7167,6 +7166,31 @@ static noinline void pass2_unneeded_regs(int istart,int iend,int r) } } +static noinline void pass2a_unneeded_other(void) +{ + int i, j; + for (i = 0; i < slen; i++) + { + // remove redundant alignment checks + if (dops[i].may_except && (dops[i].is_load || dops[i].is_store) + && dops[i].rt1 != dops[i].rs1 && !dops[i].is_ds) + { + int base = dops[i].rs1, lsb = cinfo[i].imm, ls_type = dops[i].ls_type; + int mask = ls_type == LS_32 ? 3 : 1; + lsb &= mask; + for (j = i + 1; j < slen; j++) { + if (dops[j].bt || dops[j].is_jump) + break; + if ((dops[j].is_load || dops[j].is_store) && dops[j].rs1 == base + && dops[j].ls_type == ls_type && (cinfo[j].imm & mask) == lsb) + dops[j].may_except = 0; + if (dops[j].rt1 == base) + break; + } + } + } +} + static noinline void pass3_register_alloc(u_int addr) { struct regstat current; // Current register allocations/status @@ -7231,7 +7255,7 @@ static noinline void pass3_register_alloc(u_int addr) abort(); } } - dops[i].is_ds=ds; + assert(dops[i].is_ds == ds); if(ds) { ds=0; // Skip delay slot, already allocated as part of branch // ...but we need to alloc it in case something jumps here @@ -8958,6 +8982,8 @@ static int new_recompile_block(u_int addr) pass2_unneeded_regs(0,slen-1,0); + pass2a_unneeded_other(); + /* Pass 3 - Register allocation */ pass3_register_alloc(addr);