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)
#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
} \
} while (0)
+#define host_call(addr, args) \
+ addr
+
#define host_arg2reg(rd, arg) \
rd = arg
#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); \
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)
#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)
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)
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)
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)
#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)
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)
#define emith_rw_offs_max() 0xffffffffU
+#define host_call(addr, args)
+ addr
+
#ifdef __x86_64__
#define HOST_REGS 16
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);
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)
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);
#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
#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)