From fda2f31020bf0d6cf7b5dd70ec01cf390b7e1483 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 7 Jan 2018 01:20:00 +0200 Subject: [PATCH] drc: support ms ABI --- cpu/drc/emit_arm.c | 3 ++ cpu/drc/emit_x86.c | 103 +++++++++++++++++++++++++++++++++++---------- cpu/sh2/compiler.c | 21 ++++++--- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 7b5566d..91b4740 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -436,6 +436,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_tst_r_r(d, s) \ EOP_TST_REG(A_COND_AL,d,s,A_AM1_LSL,0) +#define emith_tst_r_r_ptr(d, s) \ + emith_tst_r_r(d, s) + #define emith_teq_r_r(d, s) \ EOP_TEQ_REG(A_COND_AL,d,s,A_AM1_LSL,0) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 5362d9b..865aab4 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -64,20 +64,35 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT(op, u8); \ } while (0) -#define EMIT_MODRM(mod,r,rm) \ - EMIT(((mod)<<6) | ((r)<<3) | (rm), u8) +#define EMIT_MODRM(mod, r, rm) do { \ + assert((mod) < 4u); \ + assert((r) < 8u); \ + assert((rm) < 8u); \ + EMIT(((mod)<<6) | ((r)<<3) | (rm), u8); \ +} while (0) + +#define EMIT_SIB(scale, index, base) do { \ + assert((scale) < 4u); \ + assert((index) < 8u); \ + assert((base) < 8u); \ + EMIT(((scale)<<6) | ((index)<<3) | (base), u8); \ +} while (0) -#define EMIT_SIB(scale,index,base) \ - EMIT(((scale)<<6) | ((index)<<3) | (base), u8) +#define EMIT_SIB64(scale, index, base) \ + EMIT_SIB(scale, (index) & ~8u, (base) & ~8u) #define EMIT_REX(w,r,x,b) \ EMIT(0x40 | ((w)<<3) | ((r)<<2) | ((x)<<1) | (b), u8) #define EMIT_OP_MODRM(op,mod,r,rm) do { \ EMIT_OP(op); \ - EMIT_MODRM(mod, r, rm); \ + EMIT_MODRM(mod, (r), rm); \ } while (0) +// 64bit friendly, rm when everything is converted +#define EMIT_OP_MODRM64(op, mod, r, rm) \ + EMIT_OP_MODRM(op, mod, (r) & ~8u, (rm) & ~8u) + #define JMP8_POS(ptr) \ ptr = tcache_ptr; \ tcache_ptr += 2 @@ -95,8 +110,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT_OP_MODRM(0x8b, 3, dst, src) #define emith_move_r_r_ptr(dst, src) do { \ - EMIT_REX_FOR_PTR(); \ - EMIT_OP_MODRM(0x8b, 3, dst, src); \ + EMIT_REX_IF(1, dst, src); \ + EMIT_OP_MODRM64(0x8b, 3, dst, src); \ } while (0) #define emith_add_r_r(d, s) \ @@ -123,6 +138,11 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_tst_r_r(d, s) \ EMIT_OP_MODRM(0x85, 3, s, d) /* TEST */ +#define emith_tst_r_r_ptr(d, s) do { \ + EMIT_REX_IF(1, s, d); \ + EMIT_OP_MODRM64(0x85, 3, s, d); /* TEST */ \ +} while (0) + #define emith_cmp_r_r(d, s) \ EMIT_OP_MODRM(0x39, 3, s, d) @@ -298,15 +318,15 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; } while (0) #define emith_add_r_r_ptr_imm(d, s, imm) do { \ - if (s != xSP) { \ - EMIT_REX_FOR_PTR(); \ - EMIT_OP_MODRM(0x8d, 2, d, s); /* lea */ \ + if ((s) != xSP) { \ + EMIT_REX_IF(1, d, s); \ + EMIT_OP_MODRM64(0x8d, 2, d, s); /* lea */ \ } \ else { \ if (d != s) \ emith_move_r_r_ptr(d, s); \ - EMIT_REX_FOR_PTR(); \ - EMIT_OP_MODRM(0x81, 3, 0, d); /* add */ \ + EMIT_REX_IF(1, 0, d); \ + EMIT_OP_MODRM64(0x81, 3, 0, d); /* add */ \ } \ EMIT(imm, s32); \ } while (0) @@ -455,10 +475,10 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_deref_op(op, r, rs, offs) do { \ /* mov r <-> [ebp+#offs] */ \ if ((offs) >= 0x80) { \ - EMIT_OP_MODRM(op, 2, r, rs); \ + EMIT_OP_MODRM64(op, 2, r, rs); \ EMIT(offs, u32); \ } else { \ - EMIT_OP_MODRM(op, 1, r, rs); \ + EMIT_OP_MODRM64(op, 1, r, rs); \ EMIT(offs, u8); \ } \ } while (0) @@ -508,7 +528,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_read_r_r_offs(r, CONTEXT_REG, offs) #define emith_ctx_read_ptr(r, offs) do { \ - EMIT_REX_FOR_PTR(); \ + EMIT_REX_IF(1, r, CONTEXT_REG); \ emith_deref_op(0x8b, r, CONTEXT_REG, offs); \ } while (0) @@ -652,10 +672,16 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #ifdef __x86_64__ #define PTR_SCALE 3 -#define NA_TMP_REG xCX // non-arg tmp from reg_temp[] +#define NA_TMP_REG xAX // non-arg tmp from reg_temp[] + +#define EMIT_REX_IF(w, r, rm) do { \ + int r_ = (r) > 7 ? 1 : 0; \ + int rm_ = (rm) > 7 ? 1 : 0; \ + if ((w) | r_ | rm_) \ + EMIT_REX(1, r_, 0, rm_); \ +} while (0) -#define EMIT_REX_FOR_PTR() \ - EMIT_REX(1,0,0,0) +#ifndef _WIN32 #define host_arg2reg(rd, arg) \ switch (arg) { \ @@ -677,12 +703,43 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_ret(); \ } -#else +#else // _WIN32 + +#define host_arg2reg(rd, arg) \ + switch (arg) { \ + case 0: rd = xCX; break; \ + case 1: rd = xDX; break; \ + case 2: rd = 8; break; \ + } + +#define emith_sh2_drc_entry() { \ + emith_push(xBX); \ + emith_push(xBP); \ + emith_push(xSI); \ + emith_push(xDI); \ + emith_add_r_r_ptr_imm(xSP, xSP, -8*5); \ +} + +#define emith_sh2_drc_exit() { \ + emith_add_r_r_ptr_imm(xSP, xSP, 8*5); \ + emith_pop(xDI); \ + emith_pop(xSI); \ + emith_pop(xBP); \ + emith_pop(xBX); \ + emith_ret(); \ +} + +#endif // _WIN32 + +#else // !__x86_64__ #define PTR_SCALE 2 #define NA_TMP_REG xBX // non-arg tmp from reg_temp[] -#define EMIT_REX_FOR_PTR() +#define EMIT_REX_IF(w, r, rm) do { \ + assert((u32)(r) < 8u); \ + assert((u32)(rm) < 8u); \ +} while (0) #define host_arg2reg(rd, arg) \ switch (arg) { \ @@ -728,9 +785,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; int arg2_; \ host_arg2reg(arg2_, 2); \ emith_lsr(NA_TMP_REG, a, SH2_WRITE_SHIFT); \ - EMIT_REX_FOR_PTR(); \ - EMIT_OP_MODRM(0x8b, 0, NA_TMP_REG, 4); \ - EMIT_SIB(PTR_SCALE, NA_TMP_REG, tab); /* mov tmp, [tab + tmp * {4,8}] */ \ + EMIT_REX_IF(1, NA_TMP_REG, tab); \ + EMIT_OP_MODRM64(0x8b, 0, NA_TMP_REG, 4); \ + EMIT_SIB64(PTR_SCALE, NA_TMP_REG, tab); /* mov tmp, [tab + tmp * {4,8}] */ \ emith_move_r_r_ptr(arg2_, CONTEXT_REG); \ emith_jump_reg(NA_TMP_REG); \ } diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 3b6b45a..089f3ef 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -313,9 +313,9 @@ static const int reg_map_g2h[] = { xSI,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, xDI, - -1, -1, -1, -1, + -1, -1, -1, -1, // r12 .. sp + -1, -1, -1, xDI, // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, + -1, -1, -1, -1, // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, }; // ax, cx, dx are usually temporaries by convention @@ -330,12 +330,21 @@ static temp_reg_t reg_temp[] = { #include "../drc/emit_x86.c" static const int reg_map_g2h[] = { +#ifndef _WIN32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, // r12 .. sp + -1, -1, -1, xBX, // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, + -1, -1, -1, -1, // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, +#else + xDI,-1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, xBX, -1, -1, -1, -1, + -1, -1, -1, -1, // r12 .. sp + -1, -1, -1, xBX, // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, + -1, -1, -1, -1, // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, +#endif }; // ax, cx, dx are usually temporaries by convention @@ -344,7 +353,9 @@ static temp_reg_t reg_temp[] = { { xCX, }, { xDX, }, { xSI, }, +#ifndef _WIN32 { xDI, }, +#endif }; #else @@ -1400,7 +1411,7 @@ static void emit_block_entry(void) emith_call(sh2_drc_log_entry); rcache_invalidate(); #endif - emith_tst_r_r(RET_REG, RET_REG); + emith_tst_r_r_ptr(RET_REG, RET_REG); EMITH_SJMP_START(DCOND_EQ); emith_jump_reg_c(DCOND_NE, RET_REG); EMITH_SJMP_END(DCOND_EQ); -- 2.39.2