X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fassem_arm64.c;h=6380b27231de31650aa8c4fd591ef372a81ae08c;hp=27f9141d3a35eb198e1016d773edc61e20b5c8ab;hb=a3203cf4f2f21b0f2f74c5e494e3f5ba58225eae;hpb=3968e69e7fa8f9cb0d44ac79477d5929b9649271 diff --git a/libpcsxcore/new_dynarec/assem_arm64.c b/libpcsxcore/new_dynarec/assem_arm64.c index 27f9141d..6380b272 100644 --- a/libpcsxcore/new_dynarec/assem_arm64.c +++ b/libpcsxcore/new_dynarec/assem_arm64.c @@ -23,14 +23,6 @@ #include "pcnt.h" #include "arm_features.h" -#if defined(BASE_ADDR_FIXED) -#elif defined(BASE_ADDR_DYNAMIC) -u_char *translation_cache; -#else -u_char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096))); -#endif -static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)]; - #define CALLER_SAVE_REGS 0x0007ffff #define unused __attribute__((unused)) @@ -889,6 +881,12 @@ static void emit_set_if_carry32(u_int rs1, u_int rs2, u_int rt) emit_cmovb_imm(1,rt); } +static int can_jump_or_call(const void *a) +{ + intptr_t diff = (u_char *)a - out; + return (-134217728 <= diff && diff <= 134217727); +} + static void emit_call(const void *a) { intptr_t diff = (u_char *)a - out; @@ -1295,7 +1293,7 @@ static void emit_extjump2(u_char *addr, u_int target, void *linker) // addr is in the current recompiled block (max 256k) // offset shouldn't exceed +/-1MB emit_adr(addr, 1); - emit_jmp(linker); + emit_far_jump(linker); } static void check_extjump2(void *src) @@ -1438,8 +1436,8 @@ static void do_readstub(int n) int cc=get_reg(i_regmap,CCREG); if(cc<0) emit_loadreg(CCREG,2); - emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d+1),2); - emit_call(handler); + emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d),2); + emit_far_call(handler); // (no cycle reload after read) if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) { loadstore_extend(type,0,rt); @@ -1460,7 +1458,7 @@ static void inline_readstub(enum stub_type type, int i, u_int addr, signed char 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)) + //if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj),cc,target?rs:-1,rt)) // return; handler = get_direct_memhandler(mem_rtab, addr, type, &host_addr); if (handler == NULL) { @@ -1501,16 +1499,16 @@ static void inline_readstub(enum stub_type type, int i, u_int addr, signed char emit_mov(rs,0); if(cc<0) emit_loadreg(CCREG,2); - emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2); + emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj),2); if(is_dynamic) { uintptr_t l1 = ((uintptr_t *)mem_rtab)[addr>>12] << 1; emit_adrp((void *)l1, 1); emit_addimm64(1, l1 & 0xfff, 1); } else - emit_call(do_memhandler_pre); + emit_far_call(do_memhandler_pre); - emit_call(handler); + emit_far_call(handler); // (no cycle reload after read) if(rt>=0&&rt1[i]!=0) @@ -1597,10 +1595,10 @@ static void do_writestub(int n) int cc=get_reg(i_regmap,CCREG); if(cc<0) emit_loadreg(CCREG,2); - emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d+1),2); + emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d),2); // returns new cycle_count - emit_call(handler); - emit_addimm(0,-CLOCK_ADJUST((int)stubs[n].d+1),cc<0?2:cc); + emit_far_call(handler); + emit_addimm(0,-CLOCK_ADJUST((int)stubs[n].d),cc<0?2:cc); if(cc<0) emit_storereg(CCREG,2); if(restore_jump) @@ -1640,12 +1638,12 @@ static void inline_writestub(enum stub_type type, int i, u_int addr, signed char cc = cc_use = get_reg(regmap, CCREG); if (cc < 0) emit_loadreg(CCREG, (cc_use = 2)); - emit_addimm(cc_use, CLOCK_ADJUST(adj+1), 2); + emit_addimm(cc_use, CLOCK_ADJUST(adj), 2); - emit_call(do_memhandler_pre); - emit_call(handler); - emit_call(do_memhandler_post); - emit_addimm(0, -CLOCK_ADJUST(adj+1), cc_use); + emit_far_call(do_memhandler_pre); + emit_far_call(handler); + emit_far_call(do_memhandler_post); + emit_addimm(0, -CLOCK_ADJUST(adj), cc_use); if (cc < 0) emit_storereg(CCREG, cc_use); restore_regs(reglist); @@ -1665,12 +1663,12 @@ static void do_dirty_stub_base(u_int vaddr) emit_loadlp_ofs(0, 0); // ldr x1, source emit_loadlp_ofs(0, 1); // ldr x2, copy emit_movz(slen*4, 2); - emit_call(verify_code_arm64); + emit_far_call(verify_code_arm64); void *jmp = out; emit_cbz(0, 0); emit_movz(vaddr & 0xffff, 0); emit_movk_lsl16(vaddr >> 16, 0); - emit_call(get_addr); + emit_far_call(get_addr); emit_jmpreg(0); set_jump_target(jmp, out); } @@ -1784,7 +1782,7 @@ static void c2op_prologue(u_int op,u_int reglist) save_load_regs_all(1, reglist); #ifdef PCNT emit_movimm(op, 0); - emit_call(pcnt_gte_start); + emit_far_call(pcnt_gte_start); #endif // pointer to cop2 regs emit_addimm64(FP, (u_char *)&psxRegs.CP2D.r[0] - (u_char *)&dynarec_local, 0); @@ -1794,7 +1792,7 @@ static void c2op_epilogue(u_int op,u_int reglist) { #ifdef PCNT emit_movimm(op, 0); - emit_call(pcnt_gte_end); + emit_far_call(pcnt_gte_end); #endif save_load_regs_all(0, reglist); } @@ -1824,7 +1822,7 @@ static void c2op_assemble(int i,struct regstat *i_regs) c2op_prologue(c2op,reglist); emit_movimm(source[i],1); // opcode emit_writeword(1,&psxRegs.code); - emit_call(need_flags?gte_handlers[c2op]:gte_handlers_nf[c2op]); + emit_far_call(need_flags?gte_handlers[c2op]:gte_handlers_nf[c2op]); break; } c2op_epilogue(c2op,reglist); @@ -1973,7 +1971,7 @@ static void do_jump_vaddr(u_int rs) { if (rs != 0) emit_mov(rs, 0); - emit_call(get_addr_ht); + emit_far_call(get_addr_ht); emit_jmpreg(0); } @@ -2017,51 +2015,60 @@ static void do_miniht_insert(u_int return_address,u_int rt,int temp) { emit_writeword(rt,&mini_ht[(return_address&0xFF)>>3][0]); } -static void mark_clear_cache(void *target) +static void clear_cache_arm64(char *start, char *end) { - u_long offset = (u_char *)target - translation_cache; - u_int mask = 1u << ((offset >> 12) & 31); - if (!(needs_clear_cache[offset >> 17] & mask)) { - char *start = (char *)((u_long)target & ~4095ul); - start_tcache_write(start, start + 4096); - needs_clear_cache[offset >> 17] |= mask; + // Don't rely on GCC's __clear_cache implementation, as it caches + // icache/dcache cache line sizes, that can vary between cores on + // big.LITTLE architectures. + uint64_t addr, ctr_el0; + static size_t icache_line_size = 0xffff, dcache_line_size = 0xffff; + size_t isize, dsize; + + __asm__ volatile("mrs %0, ctr_el0" : "=r"(ctr_el0)); + isize = 4 << ((ctr_el0 >> 0) & 0xf); + dsize = 4 << ((ctr_el0 >> 16) & 0xf); + + // use the global minimum cache line size + icache_line_size = isize = icache_line_size < isize ? icache_line_size : isize; + dcache_line_size = dsize = dcache_line_size < dsize ? dcache_line_size : dsize; + + /* If CTR_EL0.IDC is enabled, Data cache clean to the Point of Unification is + not required for instruction to data coherence. */ + if ((ctr_el0 & (1 << 28)) == 0x0) { + addr = (uint64_t)start & ~(uint64_t)(dsize - 1); + for (; addr < (uint64_t)end; addr += dsize) + // use "civac" instead of "cvau", as this is the suggested workaround for + // Cortex-A53 errata 819472, 826319, 827319 and 824069. + __asm__ volatile("dc civac, %0" : : "r"(addr) : "memory"); } -} + __asm__ volatile("dsb ish" : : : "memory"); -// Clearing the cache is rather slow on ARM Linux, so mark the areas -// that need to be cleared, and then only clear these areas once. -static void do_clear_cache() -{ - int i,j; - for (i=0;i<(1<<(TARGET_SIZE_2-17));i++) - { - u_int bitmap=needs_clear_cache[i]; - if(bitmap) { - u_char *start, *end; - for(j=0;j<32;j++) - { - if(bitmap&(1<tramp.f - (u_char *)&ndrc->tramp.ops; + struct tramp_insns *ops = ndrc->tramp.ops; + size_t i; + assert(!(diff & 3)); + start_tcache_write(ops, (u_char *)ops + sizeof(ndrc->tramp.ops)); + for (i = 0; i < ARRAY_SIZE(ndrc->tramp.ops); i++) { + ops[i].ldr = 0x58000000 | imm19_rt(diff >> 2, 17); // ldr x17, [=val] + ops[i].br = 0xd61f0000 | rm_rn_rd(0, 17, 0); // br x17 + } + end_tcache_write(ops, (u_char *)ops + sizeof(ndrc->tramp.ops)); } // vim:shiftwidth=2:expandtab