sh2 drc, wrap generated function ptrs if called from host
authorkub <derkub@gmail.com>
Mon, 9 Jan 2023 20:45:10 +0000 (20:45 +0000)
committerkub <derkub@gmail.com>
Mon, 9 Jan 2023 20:45:10 +0000 (20:45 +0000)
cpu/drc/emit_arm.c
cpu/drc/emit_arm64.c
cpu/drc/emit_mips.c
cpu/drc/emit_ppc.c
cpu/drc/emit_riscv.c
cpu/drc/emit_x86.c
cpu/sh2/compiler.c
cpu/sh2/compiler.h

index 0732499..5a62c8b 100644 (file)
@@ -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
 
index 855e22d..f97583d 100644 (file)
@@ -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); \
index b4100c6..d2964dc 100644 (file)
@@ -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)
index 432583e..f9fe9b4 100644 (file)
@@ -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)
index 840973f..4c3448f 100644 (file)
@@ -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)
index c24370e..6ba7304 100644 (file)
@@ -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
index 76f6cd6..53721b7 100644 (file)
@@ -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
index 5cb0942..050be11 100644 (file)
@@ -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)