X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fnew_dynarec%2Fassem_arm64.c;h=6f108bf826265b67ffc37ceb3d2d36ea99a5df6f;hb=aaece50824568f63d6993b6db6a1ea659ac5c7da;hp=3a88f9efc78594b45aed93866d5da9840fc20d95;hpb=104df9d3b15f92d5c73d2d6beb6f01f0cc158e03;p=pcsx_rearmed.git diff --git a/libpcsxcore/new_dynarec/assem_arm64.c b/libpcsxcore/new_dynarec/assem_arm64.c index 3a88f9ef..6f108bf8 100644 --- a/libpcsxcore/new_dynarec/assem_arm64.c +++ b/libpcsxcore/new_dynarec/assem_arm64.c @@ -31,7 +31,7 @@ void do_memhandler_post(); /* Linker */ static void set_jump_target(void *addr, void *target) { - u_int *ptr = addr; + u_int *ptr = NDRC_WRITE_OFFSET(addr); intptr_t offset = (u_char *)target - (u_char *)addr; if ((*ptr&0xFC000000) == 0x14000000) { // b @@ -142,7 +142,7 @@ static unused const char *condname[16] = { static void output_w32(u_int word) { - *((u_int *)out) = word; + *((u_int *)NDRC_WRITE_OFFSET(out)) = word; out += 4; } @@ -399,6 +399,27 @@ static void emit_movimm(u_int imm, u_int rt) } } +static void emit_movimm64(uint64_t imm, u_int rt) +{ + u_int shift, op, imm16, insns = 0; + for (shift = 0; shift < 4; shift++) { + imm16 = (imm >> shift * 16) & 0xffff; + if (!imm16) + continue; + op = insns ? 0xf2800000 : 0xd2800000; + assem_debug("mov%c %s,#%#x", insns ? 'k' : 'z', regname64[rt], imm16); + if (shift) + assem_debug(",lsl #%u", shift * 16); + assem_debug("\n"); + output_w32(op | (shift << 21) | imm16_rd(imm16, rt)); + insns++; + } + if (!insns) { + assem_debug("movz %s,#0\n", regname64[rt]); + output_w32(0xd2800000 | imm16_rd(0, rt)); + } +} + static void emit_readword(void *addr, u_int rt) { uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local; @@ -838,6 +859,12 @@ static void emit_cmp(u_int rs,u_int rt) output_w32(0x6b000000 | rm_rn_rd(rt, rs, WZR)); } +static void emit_cmpcs(u_int rs,u_int rt) +{ + assem_debug("ccmp %s,%s,#0,cs\n",regname[rs],regname[rt]); + output_w32(0x7a400000 | (COND_CS << 12) | rm_rn_rd(rt, rs, 0)); +} + static void emit_set_gz32(u_int rs, u_int rt) { //assem_debug("set_gz32\n"); @@ -1323,16 +1350,7 @@ static void emit_movimm_from64(u_int rs_val, u_int rs, uintptr_t rt_val, u_int r } // just move the whole thing. At least on Linux all addresses // seem to be 48bit, so 3 insns - not great not terrible - assem_debug("movz %s,#%#lx\n", regname64[rt], rt_val & 0xffff); - output_w32(0xd2800000 | imm16_rd(rt_val & 0xffff, rt)); - assem_debug("movk %s,#%#lx,lsl #16\n", regname64[rt], (rt_val >> 16) & 0xffff); - output_w32(0xf2a00000 | imm16_rd((rt_val >> 16) & 0xffff, rt)); - assem_debug("movk %s,#%#lx,lsl #32\n", regname64[rt], (rt_val >> 32) & 0xffff); - output_w32(0xf2c00000 | imm16_rd((rt_val >> 32) & 0xffff, rt)); - if (rt_val >> 48) { - assem_debug("movk %s,#%#lx,lsl #48\n", regname64[rt], (rt_val >> 48) & 0xffff); - output_w32(0xf2e00000 | imm16_rd((rt_val >> 48) & 0xffff, rt)); - } + emit_movimm64(rt_val, rt); } // trashes x2 @@ -1507,8 +1525,13 @@ static void inline_readstub(enum stub_type type, int i, u_int addr, emit_addimm(cc<0?2:cc,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); + intptr_t offset = (l1 & ~0xfffl) - ((intptr_t)out & ~0xfffl); + if (-4294967296l <= offset && offset < 4294967296l) { + emit_adrp((void *)l1, 1); + emit_addimm64(1, l1 & 0xfff, 1); + } + else + emit_movimm64(l1, 1); } else emit_far_call(do_memhandler_pre); @@ -1892,7 +1915,7 @@ 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 clear_cache_arm64(char *start, char *end) +static unused void clear_cache_arm64(char *start, char *end) { // Don't rely on GCC's __clear_cache implementation, as it caches // icache/dcache cache line sizes, that can vary between cores on @@ -1937,7 +1960,7 @@ static void clear_cache_arm64(char *start, char *end) static void arch_init(void) { uintptr_t diff = (u_char *)&ndrc->tramp.f - (u_char *)&ndrc->tramp.ops; - struct tramp_insns *ops = ndrc->tramp.ops; + struct tramp_insns *ops = NDRC_WRITE_OFFSET(ndrc->tramp.ops); size_t i; assert(!(diff & 3)); start_tcache_write(ops, (u_char *)ops + sizeof(ndrc->tramp.ops));