From 0512a22869c8b9ec7f697cefbdc445e936a3d19b Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 9 Jan 2023 20:45:10 +0000 Subject: [PATCH] sh2 drc, wrap generated function ptrs if called from host --- cpu/drc/emit_arm.c | 5 ++++- cpu/drc/emit_arm64.c | 5 ++++- cpu/drc/emit_mips.c | 5 ++++- cpu/drc/emit_ppc.c | 13 ++++++++++++- cpu/drc/emit_riscv.c | 5 ++++- cpu/drc/emit_x86.c | 5 ++++- cpu/sh2/compiler.c | 16 +++++++++------- cpu/sh2/compiler.h | 4 ++-- 8 files changed, 43 insertions(+), 15 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 07324994..5a62c8bb 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1217,7 +1217,7 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) EOP_C_BX(A_COND_AL, r); \ } while (0) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ emith_move_r_r(LR, PC); \ emith_jump_ctx(offs); \ } while (0) @@ -1261,6 +1261,9 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) #define host_instructions_updated(base, end, force) \ do { if (force) emith_update_add(base, end); } while (0) +#define host_call(addr, args) \ + addr + #define host_arg2reg(rd, arg) \ rd = arg diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index 855e22dd..f97583d2 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -1061,6 +1061,9 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) } \ } while (0) +#define host_call(addr, args) \ + addr + #define host_arg2reg(rd, arg) \ rd = arg @@ -1136,7 +1139,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) #define emith_call_reg(r) \ EMIT(A64_BLR(r)) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ int _t = rcache_get_tmp(); \ emith_ctx_read_ptr(_t, offs); \ emith_call_reg(_t); \ diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index b4100c66..d2964dca 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -1393,6 +1393,9 @@ static void emith_lohi_nops(void) if (_s) emith_add_r_r_ptr_imm(SP, SP, _s); \ } while (0) +#define host_call(addr, args) \ + addr + #define host_arg2reg(rd, arg) \ rd = (arg+4) @@ -1602,7 +1605,7 @@ static int emith_cond_check(int cond, int *r) #define emith_call_reg(r) \ emith_branch(MIPS_JALR(LR, r)) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ emith_ctx_read_ptr(CR, offs); \ emith_call_reg(CR); \ } while (0) diff --git a/cpu/drc/emit_ppc.c b/cpu/drc/emit_ppc.c index 432583e1..f9fe9b49 100644 --- a/cpu/drc/emit_ppc.c +++ b/cpu/drc/emit_ppc.c @@ -1307,6 +1307,17 @@ static void emith_add_imm(int rt, int ra, u32 imm) if (_s) emith_add_r_r_ptr_imm(SP, SP, _s); \ } while (0) +#if defined __PS3__ +// on PS3 a C function pointer points to an array of 2 ptrs containing the start +// address and the TOC pointer for this function. TOC isn't used by the DRC though. +static void *fptr[2]; +#define host_call(addr, args) (fptr[0] = addr, (void (*) args)fptr) +#else +// with ELF we have the PLT which wraps functions needing any ABI register setup, +// hence a function ptr is simply the entry address of the function to execute. +#define host_call(addr, args) addr +#endif + #define host_arg2reg(rt, arg) \ rt = (arg+3) @@ -1500,7 +1511,7 @@ static int emith_cond_check(int cond) EMIT(PPC_BLCTRCOND(BXX)); \ } while(0) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ emith_ctx_read_ptr(CR, offs); \ emith_call_reg(CR); \ } while (0) diff --git a/cpu/drc/emit_riscv.c b/cpu/drc/emit_riscv.c index 840973f2..4c3448f2 100644 --- a/cpu/drc/emit_riscv.c +++ b/cpu/drc/emit_riscv.c @@ -1186,6 +1186,9 @@ static void emith_st_offs(int sz, int rt, int rs, int o12) if (_s) emith_add_r_r_ptr_imm(SP, SP, _s); \ } while (0) +#define host_call(addr, args) \ + addr + #define host_arg2reg(rd, arg) \ rd = (arg+10) @@ -1386,7 +1389,7 @@ static int emith_cond_check(int cond, int *r, int *s) #define emith_call_reg(r) \ EMIT(R5_JALR(LR, r, 0)) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ emith_ctx_read_ptr(AT, offs); \ emith_call_reg(AT); \ } while (0) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index c24370ed..6ba7304f 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -937,7 +937,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common EMIT_OP_MODRM(0xff, 3, 2, (r)&7); \ } while (0) -#define emith_call_ctx(offs) do { \ +#define emith_abicall_ctx(offs) do { \ EMIT_OP_MODRM(0xff, 2, 2, CONTEXT_REG); \ EMIT(offs, u32); \ } while (0) @@ -1043,6 +1043,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common #define emith_rw_offs_max() 0xffffffffU +#define host_call(addr, args) + addr + #ifdef __x86_64__ #define HOST_REGS 16 diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 76f6cd65..53721b7c 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -506,7 +506,14 @@ static signed char reg_map_host[HOST_REGS]; static guest_reg_t guest_regs[SH2_REGS]; +// generated functions called from C, to be called only through host_call() static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2); +#ifdef DRC_SR_REG +void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2); +void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); +#endif + +// generated DRC helper functions, only called from generated code via emith_call*() static void REGPARM(1) (*sh2_drc_dispatcher)(u32 pc); #if CALL_STACK static u32 REGPARM(2) (*sh2_drc_dispatcher_call)(u32 pc); @@ -525,11 +532,6 @@ static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write32)(u32 a, u32 d); -#ifdef DRC_SR_REG -void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2); -void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); -#endif - // flags for memory access #define MF_SIZEMASK 0x03 // size of access #define MF_POSTINCR 0x10 // post increment (for read_rr) @@ -5513,7 +5515,7 @@ static void sh2_generate_utils(void) emith_sub_r_imm(sr, 13 << 12); // at least 13 cycles rcache_flush(); emith_move_r_r_ptr(arg0, CONTEXT_REG); - emith_call_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level); + emith_abicall_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level); // obtain new PC tmp = rcache_get_reg_arg(1, SHR_VBR, &tmp2); emith_add_r_r_r_lsl(arg0, tmp2, RET_REG, 2); @@ -5711,7 +5713,7 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) #endif sh2c->state |= SH2_IN_DRC; - sh2_drc_entry(sh2c); + host_call(sh2_drc_entry, (SH2 *))(sh2c); sh2c->state &= ~SH2_IN_DRC; // TODO: irq cycles diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index 5cb0942b..050be114 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -74,11 +74,11 @@ extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); #define DRC_SAVE_SR(sh2) \ if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \ sh2->sr = (s32)_sh2_sr -// sh2_drc_save_sr(sh2) +// host_call(sh2_drc_save_sr, (SH2 *))(sh2) #define DRC_RESTORE_SR(sh2) \ if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \ _sh2_sr = (s32)sh2->sr -// sh2_drc_restore_sr(sh2) +// host_call(sh2_drc_restore_sr, (SH2 *))(sh2) #else #define DRC_DECLARE_SR #define DRC_SAVE_SR(sh2) -- 2.39.2