diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 67711e6..7e46a7b 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -20,6 +20,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -93,7 +94,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); } - else if (size == 8 && is_float) + else if (size == 8) { host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); @@ -117,7 +118,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) fatal("build_load_routine - unknown size %i\n", size); if (size == 4 && is_float) host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); - else if (size == 8 && is_float) + else if (size == 8) host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); @@ -206,6 +207,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 638c65a..be5a474 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -20,6 +20,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -96,7 +97,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); else if (size == 4 && is_float) host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); host_arm64_MOVZ_IMM(block, REG_W1, 0); host_arm64_RET(block, REG_X30); @@ -118,7 +119,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); if (size == 4 && is_float) host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); @@ -205,6 +206,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index f992759..1a91768 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -117,6 +117,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 1c6da2f..9603132 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -124,6 +124,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LSR (0x1ac02400) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) +#define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) @@ -754,6 +755,10 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } +void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); +} void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index fb83b83..ad759ea 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -106,6 +106,7 @@ void host_arm64_RET(codeblock_t *block, int reg); void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); +void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 7ec43dc..b3aa3c6 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -817,8 +817,12 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm64_call(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_arm64_call(block, codegen_mem_load_quad); + } else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); if (REG_IS_B(dest_size)) { @@ -836,6 +840,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); } + else if (REG_IS_Q(dest_size)) + { + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + } return 0; } @@ -1169,6 +1177,11 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); + host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 6473fd5..9901b29 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -69,6 +69,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 22e546d..b60f792 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -888,6 +888,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm_BL(block, (uintptr_t)codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_arm_BL(block, (uintptr_t)codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); @@ -908,6 +912,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm_MOV_REG(block, dest_reg, REG_R0); } + else if (REG_IS_Q(dest_size)) + { + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } return 0; } @@ -1237,6 +1245,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static double int64_to_double(int64_t a) +{ + return (double)a; +} static int codegen_MOV_DOUBLE_INT(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); @@ -1253,6 +1265,14 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + /*ARMv7 has no instructions to convert a 64-bit integer to a double. + For simplicity, call a C function and let the compiler do it.*/ + host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t)int64_to_double); /*Input - R0/R1, Output - D0*/ + host_arm_VMOV_D_D(block, dest_reg, REG_D0); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index dc43a39..6306741 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -19,6 +19,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -92,7 +93,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); else if (size == 4 && is_float) host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else if (size == 8 && is_float) + else if (size == 8) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); else fatal("build_load_routine: size=%i\n", size); @@ -131,7 +132,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); } - else if (size == 8 && is_float) + else if (size == 8) { host_x86_CALL(block, (void *)readmemql); host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); @@ -242,6 +243,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 01c0c26..4f7fe4f 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -50,6 +50,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 38cf727..3c3d6c1 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -348,7 +348,12 @@ void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 6d8a8f0..5286d2b 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -29,6 +29,7 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); @@ -75,6 +76,8 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); + void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); @@ -105,18 +108,17 @@ void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); - -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); @@ -125,8 +127,6 @@ void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg); -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); - void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 367f36e..15060cf 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -765,6 +765,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -781,6 +785,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } return 0; } @@ -1069,6 +1077,11 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); + host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index ab6a3be..71a5d0c 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -19,6 +19,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -90,7 +91,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); else if (size == 4 && is_float) host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else if (size == 8 && is_float) + else if (size == 8/* && is_float*/) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); else fatal("build_load_routine: size=%i\n", size); @@ -123,7 +124,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); } - else if (size == 8 && is_float) + else if (size == 8)// && is_float) { host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); @@ -228,6 +229,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 5a5ea69..e2ca668 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -28,6 +28,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 6d5521a..360c1a3 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1316,4 +1316,20 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 } } +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + else + codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ +} + +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + else + codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ +} + #endif diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 102639a..1ebffeb 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -199,3 +199,6 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index d060bdd..ef9496f 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -755,6 +755,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -771,6 +775,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } return 0; } @@ -1060,6 +1068,15 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + /*There is no SSE instruction to convert a 64-bit integer to a floating point value. + Instead we have to bounce the integer through memory via x87.*/ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FILDq_BASE(block, REG_ESP); + host_x87_FSTPd_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 56fff16..2a4191b 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -444,17 +444,17 @@ RecompOpFn recomp_opcodes_df[512] = /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -466,17 +466,17 @@ RecompOpFn recomp_opcodes_df[512] = /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index cfee360..90682e2 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -132,3 +132,19 @@ uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc+1; } +uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + 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(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_MM(-1)); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); + fpu_PUSH(ir); + + return op_pc+1; +} diff --git a/src/codegen_ops_fpu_loadstore.h b/src/codegen_ops_fpu_loadstore.h index 727f715..58d4121 100644 --- a/src/codegen_ops_fpu_loadstore.h +++ b/src/codegen_ops_fpu_loadstore.h @@ -8,3 +8,4 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);