sh2 drc: improved RTS call stack cache

This commit is contained in:
kub 2019-09-19 22:14:28 +02:00
parent 58a444a295
commit 36614252d9
6 changed files with 130 additions and 189 deletions

View file

@ -1000,10 +1000,6 @@ static inline void emith_pool_adjust(int pool_index, int move_offs)
emith_read_r_r_offs_c(A_COND_AL, r, rs, offs)
#define emith_read_r_r_r(r, rs, rm) \
EOP_LDR_REG_LSL(A_COND_AL, r, rs, rm, 0)
#define emith_read_r_r_r_wb(r, rs, rm) \
EOP_LDR_REG_LSL_WB(A_COND_AL, r, rs, rm, 0)
#define emith_read_r_r_r_ptr_wb(r, rs, rm) \
emith_read_r_r_r_wb(r, rs, rm)
#define emith_read8_r_r_offs_c(cond, r, rs, offs) \
EOP_LDRB_IMM2(cond, r, rs, offs)
@ -1049,10 +1045,6 @@ static inline void emith_pool_adjust(int pool_index, int move_offs)
emith_write_r_r_offs_c(A_COND_AL, r, rs, offs)
#define emith_write_r_r_offs_ptr(r, rs, offs) \
emith_write_r_r_offs_c(A_COND_AL, r, rs, offs)
#define emith_write_r_r_r_wb(r, rs, rm) \
EOP_STR_REG_LSL_WB(A_COND_AL, r, rs, rm, 0)
#define emith_write_r_r_r_ptr_wb(r, rs, rm) \
emith_write_r_r_r_wb(r, rs, rm)
#define emith_ctx_read_c(cond, r, offs) \
emith_read_r_r_offs_c(cond, r, CONTEXT_REG, offs)
@ -1133,21 +1125,21 @@ static inline void emith_pool_adjust(int pool_index, int move_offs)
#define emith_jump_patchable(target) \
emith_jump(target)
#define emith_jump_patchable_size() 4
#define emith_jump_cond(cond, target) \
emith_xbranch(cond, target, 0)
#define emith_jump_cond_inrange(target) !0
#define emith_jump_cond_patchable(cond, target) \
emith_jump_cond(cond, target)
#define emith_jump_patch(ptr, target) ({ \
#define emith_jump_patch(ptr, target, pos) do { \
u32 *ptr_ = ptr; \
u32 val_ = (u32 *)(target) - ptr_ - 2; \
*ptr_ = (*ptr_ & 0xff000000) | (val_ & 0x00ffffff); \
(u8 *)ptr; \
})
#define emith_jump_cond_inrange(target) !0
if ((void *)(pos) != NULL) *(u8 **)(pos) = (u8 *)ptr; \
} while (0)
#define emith_jump_patch_size() 4
#define emith_jump_at(ptr, target) do { \
@ -1184,11 +1176,6 @@ static inline void emith_pool_adjust(int pool_index, int move_offs)
emith_jump_ctx(offs); \
} while (0)
#define emith_call_link(r, target) do { \
emith_move_r_r(r, PC); \
emith_jump(target); \
} while (0)
#define emith_call_cleanup() /**/
#define emith_ret_c(cond) \
@ -1200,6 +1187,9 @@ static inline void emith_pool_adjust(int pool_index, int move_offs)
#define emith_ret_to_ctx(offs) \
emith_ctx_write(LR, offs)
#define emith_add_r_ret_imm(r, imm) \
emith_add_r_r_ptr_imm(r, LR, imm)
/* pushes r12 for eabi alignment */
#define emith_push_ret(r) do { \
int r_ = (r >= 0 ? r : 12); \

View file

@ -865,15 +865,6 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define emith_read_r_r_r_c(cond, r, rs, rm) \
emith_read_r_r_r(r, rs, rm)
#define emith_read_r_r_r_ptr_wb(r, rs, rm) do { \
emith_read_r_r_r_ptr(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_read_r_r_r_wb(r, rs, rm) do { \
emith_read_r_r_r(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_read8_r_r_offs(r, rs, offs) \
emith_ldst_offs(AM_B, r, rs, offs, LT_LD, AM_IDX)
#define emith_read8_r_r_offs_c(cond, r, rs, offs) \
@ -935,15 +926,6 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define emith_write_r_r_r_c(cond, r, rs, rm) \
emith_write_r_r_r(r, rs, rm)
#define emith_write_r_r_r_ptr_wb(r, rs, rm) do { \
emith_write_r_r_r_ptr(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_write_r_r_r_wb(r, rs, rm) do { \
emith_write_r_r_r(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_ctx_read_ptr(r, offs) \
emith_read_r_r_offs_ptr(r, CONTEXT_REG, offs)
@ -1031,6 +1013,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define emith_jump_patchable(target) \
emith_jump(target)
#define emith_jump_patchable_size() 4
#define emith_jump_cond(cond, target) \
emith_bcond(tcache_ptr, 0, cond, target)
@ -1039,9 +1022,9 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
emith_bcond(tcache_ptr, 1, cond, target)
#define emith_jump_cond_inrange(target) \
!(((u8 *)target - (u8 *)tcache_ptr + 0x100000) >> 22)
!(((u8 *)target - (u8 *)tcache_ptr + 0x100000) >> 21)
#define emith_jump_patch(ptr, target) ({ \
#define emith_jump_patch(ptr, target, pos) do { \
u32 *ptr_ = (u32 *)ptr; \
u32 disp_ = (u8 *)(target) - (u8 *)(ptr_); \
int cond_ = ptr_[0] & 0xf; \
@ -1051,8 +1034,9 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
} else if (ptr_[0] & 0x80000000) \
EMIT_PTR(ptr_, A64_BL((disp_) & 0x0fffffff)); \
else EMIT_PTR(ptr_, A64_B((disp_) & 0x0fffffff)); \
(u8 *)ptr; \
})
if ((void *)(pos) != NULL) *(u8 **)(pos) = (u8 *)ptr; \
} while (0)
#define emith_jump_patch_size() 8
#define emith_jump_reg(r) \
EMIT(A64_BR(r))
@ -1085,11 +1069,6 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
rcache_free_tmp(_t); \
} while (0)
#define emith_call_link(r, target) do { \
EMIT(A64_ADRXLIT_IMM(r, 8)); \
emith_jump(target); \
} while (0)
#define emith_call_cleanup() /**/
#define emith_ret() \
@ -1100,6 +1079,9 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define emith_ret_to_ctx(offs) \
emith_ctx_write_ptr(LR, offs)
#define emith_add_r_ret_imm(r, imm) \
emith_add_r_r_ptr_imm(r, LR, imm)
// NB: pushes r or r18 for SP hardware alignment
#define emith_push_ret(r) do { \
int r_ = (r >= 0 ? r : 18); \
@ -1120,7 +1102,6 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define emith_flush() /**/
#define host_instructions_updated(base, end) __builtin___clear_cache(base, end)
#define emith_update_cache() /**/
#define emith_jump_patch_size() 8
#define emith_rw_offs_max() 0xff

View file

@ -950,13 +950,6 @@ static void emith_lohi_nops(void)
#define emith_read_r_r_r_c(cond, r, rs, rm) \
emith_read_r_r_r(r, rs, rm)
#define emith_read_r_r_r_ptr_wb(r, rs, rm) do { \
emith_add_r_r_r(rs, rs, rm); \
EMIT(MIPS_LW(r, rs, 0)); \
} while (0)
#define emith_read_r_r_r_wb(r, rs, rm) \
emith_read_r_r_r_ptr_wb(r, rs, rm)
#define emith_read8_r_r_offs(r, rs, offs) \
EMIT(MIPS_LBU(r, rs, offs))
#define emith_read8_r_r_offs_c(cond, r, rs, offs) \
@ -1028,13 +1021,6 @@ static void emith_lohi_nops(void)
#define emith_write_r_r_r_c(cond, r, rs, rm) \
emith_write_r_r_r(r, rs, rm)
#define emith_write_r_r_r_ptr_wb(r, rs, rm) do { \
emith_add_r_r_r(rs, rs, rm); \
EMIT(MIPS_SW(r, rs, 0)); \
} while (0)
#define emith_write_r_r_r_wb(r, rs, rm) \
emith_write_r_r_r_ptr_wb(r, rs, rm)
#define emith_ctx_read_ptr(r, offs) \
emith_read_r_r_offs_ptr(r, CONTEXT_REG, offs)
@ -1176,6 +1162,7 @@ static int emith_cond_check(int cond, int *r)
emith_branch(MIPS_J((uintptr_t)target & 0x0fffffff))
#define emith_jump_patchable(target) \
emith_jump(target)
#define emith_jump_patchable_size() 8 /* J+delayslot */
// NB: MIPS conditional branches have only +/- 128KB range
#define emith_jump_cond(cond, target) do { \
@ -1190,6 +1177,8 @@ static int emith_cond_check(int cond, int *r)
EMIT_PTR(bp, MIPS_BCONDZ(mcond_, r_, (u8 *)tcache_ptr-bp-4)); \
} \
} while (0)
#define emith_jump_cond_inrange(target) \
!(((u8 *)target - (u8 *)tcache_ptr + 0x20000) >> 18)
#define emith_jump_cond_patchable(cond, target) do { \
int r_, mcond_ = emith_cond_check(cond, &r_); \
@ -1199,16 +1188,14 @@ static int emith_cond_check(int cond, int *r)
EMIT_PTR(bp, MIPS_BCONDZ(mcond_, r_, (u8 *)tcache_ptr-bp-4)); \
} while (0)
#define emith_jump_cond_inrange(target) \
!(((u8 *)target - (u8 *)tcache_ptr + 0x10000) >> 18)
// NB: returns position of patch for cache maintenance
#define emith_jump_patch(ptr, target) ({ \
#define emith_jump_patch(ptr, target, pos) do { \
u32 *ptr_ = (u32 *)ptr-1; /* must skip condition check code */ \
while ((ptr_[0] & 0xf8000000) != OP_J << 26) ptr_ ++; \
EMIT_PTR(ptr_, MIPS_J((uintptr_t)target & 0x0fffffff)); \
(u8 *)(ptr_-1); \
})
if ((void *)(pos) != NULL) *(u8 **)(pos) = (u8 *)(ptr_-1); \
} while (0)
#define emith_jump_patch_size() 4
#define emith_jump_reg(r) \
emith_branch(MIPS_JR(r))
@ -1235,11 +1222,6 @@ static int emith_cond_check(int cond, int *r)
emith_call_reg(AT); \
} while (0)
#define emith_call_link(r, target) do { \
EMIT(MIPS_BL(4)); EMIT(MIPS_ADD_IMM(r, LR, 8)); emith_flush(); \
emith_branch(MIPS_J((uintptr_t)target & 0x0fffffff)); \
} while (0)
#define emith_call_cleanup() /**/
#define emith_ret() \
@ -1250,6 +1232,9 @@ static int emith_cond_check(int cond, int *r)
#define emith_ret_to_ctx(offs) \
emith_ctx_write_ptr(LR, offs)
#define emith_add_r_ret_imm(r, imm) \
emith_add_r_r_ptr_imm(r, LR, imm)
// NB: ABI SP alignment is 8 for compatibility with MIPS IV
#define emith_push_ret(r) do { \
emith_sub_r_imm(SP, 8+16); /* reserve new arg save area (16) */ \
@ -1271,7 +1256,6 @@ static int emith_cond_check(int cond, int *r)
// NB: mips32r2 has SYNCI
#define host_instructions_updated(base, end) __builtin___clear_cache(base, end)
#define emith_update_cache() /**/
#define emith_jump_patch_size() 4
#define emith_rw_offs_max() 0x7fff
// SH2 drc specific

View file

@ -297,54 +297,61 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
// _r_r_r_shift
#define emith_add_r_r_r_lsl(d, s1, s2, lslimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_add_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
if (lslimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_add_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_add_r_r_r(d, s1, s2); \
} while (0)
#define emith_add_r_r_r_lsl_ptr(d, s1, s2, lslimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_add_r_r_r_ptr(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
if (lslimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_add_r_r_r_ptr(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_add_r_r_r_ptr(d, s1, s2); \
} while (0)
#define emith_add_r_r_r_lsr(d, s1, s2, lsrimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsr(tmp_, s2, lsrimm); \
emith_add_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
if (lsrimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsr(tmp_, s2, lsrimm); \
emith_add_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_add_r_r_r(d, s1, s2); \
} while (0)
#define emith_sub_r_r_r_lsl(d, s1, s2, lslimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_sub_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
if (lslimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_sub_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_sub_r_r_r(d, s1, s2); \
} while (0)
#define emith_or_r_r_r_lsl(d, s1, s2, lslimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_or_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
if (lslimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s2, lslimm); \
emith_or_r_r_r(d, s1, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_or_r_r_r(d, s1, s2); \
} while (0)
// _r_r_shift
#define emith_or_r_r_lsl(d, s, lslimm) do { \
int tmp_ = rcache_get_tmp(); \
emith_lsl(tmp_, s, lslimm); \
emith_or_r_r(d, tmp_); \
rcache_free_tmp(tmp_); \
} while (0)
#define emith_or_r_r_lsl(d, s, lslimm) \
emith_or_r_r_r_lsl(d, d, s, lslimm)
// d != s
#define emith_eor_r_r_lsr(d, s, lsrimm) do { \
emith_push(s); \
emith_lsr(s, s, lsrimm); \
emith_eor_r_r(d, s); \
emith_pop(s); \
if (lsrimm) { \
int tmp_ = rcache_get_tmp(); \
emith_lsr(tmp_, s, lsrimm); \
emith_eor_r_r(d, tmp_); \
rcache_free_tmp(tmp_); \
} else emith_eor_r_r(d, s); \
} while (0)
// _r_imm
@ -792,14 +799,6 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
EMIT_OP_MODRM64(0x8b, 0, r, 4); \
EMIT_SIB64(0, rs, rm); /* mov r, [rm + rs * 1] */ \
} while (0)
#define emith_read_r_r_r_wb(r, rs, rm) do { \
emith_read_r_r_r(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_read_r_r_r_ptr_wb(r, rs, rm) do { \
emith_read_r_r_r_ptr(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_write_r_r_r(r, rs, rm) do { \
EMIT_XREX_IF(0, r, rm, rs); \
@ -811,15 +810,6 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
EMIT_OP_MODRM64(0x89, 0, r, 4); \
EMIT_SIB64(0, rs, rm); /* mov [rm + rs * 1], r */ \
} while (0)
#define emith_write_r_r_r_wb(r, rs, rm) do { \
emith_write_r_r_r(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_write_r_r_r_ptr_wb(r, rs, rm) do { \
emith_write_r_r_r_ptr(r, rs, rm); \
emith_add_r_r_ptr(rs, rm); \
} while (0)
#define emith_ctx_read(r, offs) \
emith_read_r_r_offs(r, CONTEXT_REG, offs)
@ -846,10 +836,11 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
emith_ctx_write(r_, offs_); \
} while (0)
// assumes EBX is free
#define emith_ret_to_ctx(offs) do { \
emith_pop(xBX); \
emith_ctx_write(xBX, offs); \
int tmp_ = rcache_get_tmp(); \
emith_pop(tmp_); \
emith_ctx_write(tmp_, offs); \
rcache_free_tmp(tmp_); \
} while (0)
#define emith_jump(ptr) do { \
@ -860,24 +851,24 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
#define emith_jump_patchable(target) \
emith_jump(target)
#define emith_jump_patchable_size() 5 /* JMP rel32 */
#define emith_jump_cond(cond, ptr) do { \
u32 disp = (u8 *)(ptr) - ((u8 *)tcache_ptr + 6); \
EMIT_OP(0x0f80 | (cond)); \
EMIT(disp, u32); \
} while (0)
#define emith_jump_cond_inrange(ptr) !0
#define emith_jump_cond_patchable(cond, target) \
emith_jump_cond(cond, target)
#define emith_jump_patch(ptr, target) ({ \
#define emith_jump_patch(ptr, target, pos) do { \
u32 disp_ = (u8 *)(target) - ((u8 *)(ptr) + 4); \
u32 offs_ = (*(u8 *)(ptr) == 0x0f) ? 2 : 1; \
EMIT_PTR((u8 *)(ptr) + offs_, disp_ - offs_, u32); \
ptr; \
})
#define emith_jump_cond_inrange(ptr) !0
if ((void *)(pos) != NULL) *(u8 **)(pos) = (u8 *)ptr; \
} while (0)
#define emith_jump_patch_size() 6
#define emith_jump_at(ptr, target) do { \
@ -903,20 +894,17 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
EMIT(offs, u32); \
} while (0)
#define emith_call_link(r, target) do { \
EMIT_OP(0xe8); \
EMIT(0, u32); /* call pc+0 */ \
emith_pop(r); \
emith_add_r_r_ptr_imm(r, r, 13); \
emith_jump(target); \
} while (0)
#define emith_call_cleanup() \
emith_add_r_r_ptr_imm(xSP, xSP, sizeof(void *)); // remove return addr
#define emith_ret() \
EMIT_OP(0xc3)
#define emith_add_r_ret_imm(r, imm) do { \
emith_read_r_r_offs_ptr(r, xSP, 0); \
emith_add_r_r_ptr_imm(r, r, imm); \
} while (0)
#define emith_jump_reg(r) \
EMIT_OP_MODRM(0xff, 3, 4, r)