From 76115568f2282d7db9aff21341f380b236481ace Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 21 Nov 2018 17:02:20 +0000 Subject: [PATCH] Added recompiled versions of MOVD and MOVQ. --- src/codegen_backend_arm64_uops.c | 37 ++++++++++- src/codegen_backend_arm_uops.c | 39 ++++++++++- src/codegen_backend_x86-64_uops.c | 42 +++++++++++- src/codegen_backend_x86_uops.c | 33 +++++++++- src/codegen_ir_defs.h | 11 +++- src/codegen_ops.c | 9 +-- src/codegen_ops_mmx_loadstore.c | 106 ++++++++++++++++++++++++++++++ src/codegen_ops_mmx_loadstore.h | 5 ++ src/codegen_reg.c | 27 ++++++++ src/codegen_reg.h | 26 +++++++- 10 files changed, 320 insertions(+), 15 deletions(-) create mode 100644 src/codegen_ops_mmx_loadstore.c create mode 100644 src/codegen_ops_mmx_loadstore.h diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 1d8aec5..5464148 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -699,6 +699,32 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); + + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); + + host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1162,7 +1188,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_arm64_FMOV_D_Q(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_arm64_FMOV_W_S(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); } @@ -1836,6 +1870,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 08ae666..1f132de 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -772,6 +772,33 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1238,7 +1265,16 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_arm_VMOV_32_S(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { host_arm_UXTB(block, dest_reg, src_reg, 0); } @@ -1955,6 +1991,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4fd1768..d27edae 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -641,6 +641,29 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +#if WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +#endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1076,7 +1099,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); } @@ -1640,6 +1671,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, @@ -1757,6 +1789,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); @@ -1766,6 +1802,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos { host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 9ef533e..a61592a 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -649,6 +649,26 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_x86_JMP(block, uop->p); @@ -1073,7 +1093,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); } @@ -1642,7 +1670,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FDIV & UOP_MASK] = codegen_FDIV, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 998017b..5c5d290 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -167,7 +167,7 @@ /*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ #define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) -/*UOP_FP_ENTER - */ +/*UOP_FP_ENTER - must be called before any FPU register accessed*/ #define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) /*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/ #define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) @@ -180,7 +180,10 @@ /*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ #define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) -#define UOP_MAX 0x86 +/*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ +#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) + +#define UOP_MAX 0x91 #define UOP_MASK 0xffff @@ -488,7 +491,8 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; } while (0) +#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0) +#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0) #define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) #define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) @@ -549,6 +553,7 @@ void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_of void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_set_jump_dest(codeblock_t *block, void *p); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a2d6fb1..28dc422 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -11,6 +11,7 @@ #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" +#include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -74,8 +75,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -96,8 +97,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c new file mode 100644 index 0000000..e0ea5f7 --- /dev/null +++ b/src/codegen_ops_mmx_loadstore.c @@ -0,0 +1,106 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_loadstore.h" +#include "codegen_ops_helpers.h" + +uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); + } + + return op_pc + 1; + +} +uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } + + return op_pc + 1; +} + +uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; + +} + +uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); + } + + return op_pc + 1; +} diff --git a/src/codegen_ops_mmx_loadstore.h b/src/codegen_ops_mmx_loadstore.h new file mode 100644 index 0000000..4b473ad --- /dev/null +++ b/src/codegen_ops_mmx_loadstore.h @@ -0,0 +1,5 @@ +uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 6e51f7d..3e801a9 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -123,6 +123,15 @@ struct [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP}, + [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP}, + [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP}, + [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP}, + [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP}, + [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP}, + [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP}, + [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, @@ -204,6 +213,15 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, else codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; + + case REG_QWORD: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_64_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_64(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; case REG_DOUBLE: if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) @@ -282,6 +300,15 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i codegen_direct_write_32(block, p, reg_set->reg_list[c]); break; + case REG_QWORD: + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); + if ((uintptr_t)p < 256) + codegen_direct_write_64_stack(block, (int)p, reg_set->reg_list[c]); + else + codegen_direct_write_64(block, p, reg_set->reg_list[c]); + break; + case REG_POINTER: if (ireg_data[ir_reg].type != REG_INTEGER) fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 4568382..8474ef9 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -104,10 +104,19 @@ enum IREG_ST6_i64 = 62, IREG_ST7_i64 = 63, - IREG_NPXCx = 64, - IREG_NPXSx = 65, + IREG_MM0x = 64, + IREG_MM1x = 65, + IREG_MM2x = 66, + IREG_MM3x = 67, + IREG_MM4x = 68, + IREG_MM5x = 69, + IREG_MM6x = 70, + IREG_MM7x = 71, + + IREG_NPXCx = 72, + IREG_NPXSx = 73, - IREG_COUNT = 66, + IREG_COUNT = 74, IREG_INVALID = 255, @@ -160,6 +169,15 @@ enum IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, + IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, + IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, + IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, + IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, + IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, + IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, + IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, + IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, + IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, IREG_NPXS = IREG_NPXSx + IREG_SIZE_W }; @@ -173,6 +191,8 @@ enum #define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) #define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) +#define IREG_MM(reg) ((reg) + IREG_MM0) + #define IREG_TOP_diff_stack_offset 32 static inline int ireg_seg_base(x86seg *seg)