X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fnew_dynarec.c;h=b9e7c144850ff848c9e21a6508540342c7064d79;hb=9b495f6ec3f28cf5ed1d41f6af16a9967fcf3e64;hp=447023c68ccde3c1de4abf3347d8298152b22246;hpb=d9e2b173fb11fea4976fb0a6c5feda6b654b4b46;p=pcsx_rearmed.git diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 447023c6..b9e7c144 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -41,6 +41,7 @@ static Jit g_jit; #include "emu_if.h" // emulator interface #include "arm_features.h" +#define unused __attribute__((unused)) #ifdef __clang__ #define noinline __attribute__((noinline)) #else @@ -58,6 +59,7 @@ static Jit g_jit; //#define DISASM //#define ASSEM_PRINT +//#define INV_DEBUG_W //#define STAT_PRINT #ifdef ASSEM_PRINT @@ -163,7 +165,7 @@ struct regstat u_int wasconst; // before; for example 'lw r2, (r2)' wasconst is true u_int isconst; // ... but isconst is false when r2 is known u_int loadedconst; // host regs that have constants loaded - u_int waswritten; // MIPS regs that were used as store base before + //u_int waswritten; // MIPS regs that were used as store base before }; struct ht_entry @@ -397,8 +399,9 @@ void new_dyna_leave(); void *ndrc_get_addr_ht_param(u_int vaddr, int can_compile); void *ndrc_get_addr_ht(u_int vaddr); -void ndrc_invalidate_addr(u_int addr); void ndrc_add_jump_out(u_int vaddr, void *src); +void ndrc_write_invalidate_one(u_int addr); +static void ndrc_write_invalidate_many(u_int addr, u_int end); static int new_recompile_block(u_int addr); static void invalidate_block(struct block_info *block); @@ -490,6 +493,8 @@ static void end_tcache_write(void *start, void *end) if (g_jit.type == JitType_CodeMemory) { armDCacheClean(start, len); armICacheInvalidate((char *)start - ndrc_write_ofs, len); + // as of v4.2.1 libnx lacks isb + __asm__ volatile("isb" ::: "memory"); } #elif defined(__aarch64__) // as of 2021, __clear_cache() is still broken on arm64 @@ -685,6 +690,28 @@ static int doesnt_expire_soon(u_char *tcaddr) return diff > EXPIRITY_OFFSET + MAX_OUTPUT_BLOCK_SIZE; } +static unused void check_for_block_changes(u_int start, u_int end) +{ + u_int start_page = get_page_prev(start); + u_int end_page = get_page(end - 1); + u_int page; + + for (page = start_page; page <= end_page; page++) { + struct block_info *block; + for (block = blocks[page]; block != NULL; block = block->next) { + if (block->is_dirty) + continue; + if (memcmp(block->source, block->copy, block->len)) { + printf("bad block %08x-%08x %016llx %016llx @%08x\n", + block->start, block->start + block->len, + *(long long *)block->source, *(long long *)block->copy, psxRegs.pc); + fflush(stdout); + abort(); + } + } + } +} + static void *try_restore_block(u_int vaddr, u_int start_page, u_int end_page) { void *found_clean = NULL; @@ -768,6 +795,7 @@ static void noinline *get_addr(u_int vaddr, int can_compile) // Look up address in hash table first void *ndrc_get_addr_ht_param(u_int vaddr, int can_compile) { + //check_for_block_changes(vaddr, vaddr + MAXBLOCK); const struct ht_entry *ht_bin = hash_table_get(vaddr); stat_inc(stat_ht_lookups); if (ht_bin->vaddr[0] == vaddr) return ht_bin->tcaddr[0]; @@ -1163,7 +1191,8 @@ static const struct { FUNCNAME(jump_handler_write8), FUNCNAME(jump_handler_write16), FUNCNAME(jump_handler_write32), - FUNCNAME(ndrc_invalidate_addr), + FUNCNAME(ndrc_write_invalidate_one), + FUNCNAME(ndrc_write_invalidate_many), FUNCNAME(jump_to_new_pc), FUNCNAME(jump_break), FUNCNAME(jump_break_ds), @@ -1330,7 +1359,7 @@ static int blocks_remove_matching_addrs(struct block_info **head, int hit = 0; while (*head) { if ((((*head)->tc_offs ^ base_offs) >> shift) == 0) { - inv_debug("EXP: rm block %08x (tc_offs %zx)\n", (*head)->start, (*head)->tc_offs); + inv_debug("EXP: rm block %08x (tc_offs %x)\n", (*head)->start, (*head)->tc_offs); invalidate_block(*head); next = (*head)->next; free(*head); @@ -1391,7 +1420,7 @@ static void unlink_jumps_tc_range(struct jump_info *ji, u_int base_offs, int shi continue; } - inv_debug("EXP: rm link to %08x (tc_offs %zx)\n", ji->e[i].target_vaddr, tc_offs); + inv_debug("EXP: rm link to %08x (tc_offs %x)\n", ji->e[i].target_vaddr, tc_offs); stat_dec(stat_links); ji->count--; if (i < ji->count) { @@ -1426,7 +1455,7 @@ static int invalidate_range(u_int start, u_int end, int hit = 0; // additional area without code (to supplement invalid_code[]), [start, end) - // avoids excessive ndrc_invalidate_addr() calls + // avoids excessive ndrc_write_invalidate*() calls inv_start = start_m & ~0xfff; inv_end = end_m | 0xfff; @@ -1485,16 +1514,28 @@ void new_dynarec_invalidate_range(unsigned int start, unsigned int end) invalidate_range(start, end, NULL, NULL); } -void ndrc_invalidate_addr(u_int addr) +static void ndrc_write_invalidate_many(u_int start, u_int end) { // this check is done by the caller //if (inv_code_start<=addr&&addr<=inv_code_end) { rhits++; return; } - int ret = invalidate_range(addr, addr + 4, &inv_code_start, &inv_code_end); + int ret = invalidate_range(start, end, &inv_code_start, &inv_code_end); +#ifdef INV_DEBUG_W + int invc = invalid_code[start >> 12]; + u_int len = end - start; if (ret) - inv_debug("INV ADDR: %08x hit %d blocks\n", addr, ret); + printf("INV ADDR: %08x/%02x hit %d blocks\n", start, len, ret); else - inv_debug("INV ADDR: %08x miss, inv %08x-%08x\n", addr, inv_code_start, inv_code_end); + printf("INV ADDR: %08x/%02x miss, inv %08x-%08x invc %d->%d\n", start, len, + inv_code_start, inv_code_end, invc, invalid_code[start >> 12]); + check_for_block_changes(start, end); +#endif stat_inc(stat_inv_addr_calls); + (void)ret; +} + +void ndrc_write_invalidate_one(u_int addr) +{ + ndrc_write_invalidate_many(addr, addr + 4); } // This is called when loading a save state. @@ -1519,26 +1560,6 @@ void new_dynarec_invalidate_all_pages(void) do_clear_cache(); } -static void do_invstub(int n) -{ - 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_readword(&inv_code_start, 1); - emit_readword(&inv_code_end, 2); - emit_cmp(0, 1); - emit_cmpcs(2, 0); - void *jaddr = out; - emit_jc(0); - emit_far_call(ndrc_invalidate_addr); - set_jump_target(jaddr, out); - restore_regs(reglist); - emit_jmp(stubs[n].retaddr); // return address -} - // Add an entry to jump_out after making a link // src should point to code by emit_extjump() void ndrc_add_jump_out(u_int vaddr, void *src) @@ -3145,6 +3166,89 @@ static void loadlr_assemble(int i, const struct regstat *i_regs, int ccadj_) } #endif +static void do_invstub(int n) +{ + literal_pool(20); + assem_debug("do_invstub\n"); + u_int reglist = stubs[n].a; + u_int addrr = stubs[n].b; + int ofs_start = stubs[n].c; + int ofs_end = stubs[n].d; + int len = ofs_end - ofs_start; + u_int rightr = 0; + + set_jump_target(stubs[n].addr, out); + save_regs(reglist); + emit_readword(&inv_code_start, 2); + emit_readword(&inv_code_end, 3); + if (addrr != 0 || ofs_start != 0) + emit_addimm(addrr, ofs_start, 0); + if (len != 0) + emit_addimm(0, len + 4, (rightr = 1)); + emit_cmp(0, 2); + emit_cmpcs(3, rightr); + void *jaddr = out; + emit_jc(0); + void *func = (len != 0) + ? (void *)ndrc_write_invalidate_many + : (void *)ndrc_write_invalidate_one; + emit_far_call(func); + set_jump_target(jaddr, out); + restore_regs(reglist); + emit_jmp(stubs[n].retaddr); +} + +static void do_store_smc_check(int i, const struct regstat *i_regs, u_int reglist, int addr) +{ + if (HACK_ENABLED(NDHACK_NO_SMC_CHECK)) + return; + // this can't be used any more since we started to check exact + // block boundaries in invalidate_range() + //if (i_regs->waswritten & (1<= 0; j--) { + if (!dops[j].is_store || dops[j].rs1 != dops[i].rs1 + || abs(imm[j] - imm[j+1]) > imm_maxdiff) + break; + count++; + if (imm_min > imm[j]) + imm_min = imm[j]; + if (imm_max < imm[j]) + imm_max = imm[j]; + } +#if defined(HOST_IMM8) + int ir = get_reg(i_regs->regmap, INVCP); + assert(ir >= 0); + host_tempreg_acquire(); + emit_ldrb_indexedsr12_reg(ir, addr, HOST_TEMPREG); +#else + emit_cmpmem_indexedsr12_imm(invalid_code, addr, 1); + #error not handled +#endif +#ifdef INVALIDATE_USE_COND_CALL + if (count == 1) { + emit_cmpimm(HOST_TEMPREG, 1); + emit_callne(invalidate_addr_reg[addr]); + host_tempreg_release(); + return; + } +#endif + void *jaddr = emit_cbz(HOST_TEMPREG, 0); + host_tempreg_release(); + imm_min -= imm[i]; + imm_max -= imm[i]; + add_stub(INVCODE_STUB, jaddr, out, reglist|(1<waswritten&(1<regmap,INVCP); - assert(ir>=0); - emit_cmpmem_indexedsr12_reg(ir,addr,1); - #else - emit_cmpmem_indexedsr12_imm(invalid_code,addr,1); - #endif - #ifdef INVALIDATE_USE_COND_CALL - emit_callne(invalidate_addr_reg[addr]); - #else - void *jaddr2 = out; - emit_jne(0); - add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<waswritten&(1<regmap,INVCP); - assert(ir>=0); - emit_cmpmem_indexedsr12_reg(ir,temp,1); - #else - emit_cmpmem_indexedsr12_imm(invalid_code,temp,1); - #endif - #ifdef INVALIDATE_USE_COND_CALL - emit_callne(invalidate_addr_reg[temp]); - #else - void *jaddr2 = out; - emit_jne(0); - add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<waswritten&(1<regmap,INVCP); - assert(ir>=0); - emit_cmpmem_indexedsr12_reg(ir,ar,1); -#else - emit_cmpmem_indexedsr12_imm(invalid_code,ar,1); -#endif - #ifdef INVALIDATE_USE_COND_CALL - emit_callne(invalidate_addr_reg[ar]); - #else - void *jaddr3 = out; - emit_jne(0); - add_stub(INVCODE_STUB,jaddr3,out,reglist|(1<0&&(dops[i-1].itype==STORE||dops[i-1].itype==STORELR||(dops[i-1].itype==C2LS&&dops[i-1].opcode==0x3a))&&(u_int)imm[i-1]<0x800) current.waswritten|=1<=0x800) current.waswritten&=~(1<0) @@ -7808,7 +7871,7 @@ static noinline void pass3_register_alloc(u_int addr) } } if(current.regmap[HOST_BTREG]==BTREG) current.regmap[HOST_BTREG]=-1; - regs[i].waswritten=current.waswritten; + //regs[i].waswritten=current.waswritten; } } @@ -8861,8 +8924,8 @@ static noinline void pass10_expire_blocks(void) u_int block_i = expirep / step & (PAGE_COUNT - 1); u_int phase = (expirep >> (base_shift - 1)) & 1u; if (!(expirep & (MAX_OUTPUT_BLOCK_SIZE / 2 - 1))) { - inv_debug("EXP: base_offs %x/%x phase %u\n", base_offs, - out - ndrc->translation_cache, phase); + inv_debug("EXP: base_offs %x/%lx phase %u\n", base_offs, + (long)(out - ndrc->translation_cache), phase); } if (!phase) {