From e64271f5bb5ed718d7f763838b9ba3a66b0283fe Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 27 Jul 2018 22:24:34 +0100 Subject: [PATCH] Added recompiled versions of mem->reg, reg->mem and imm->mem versions of ADD, AND, CMP, OR, SUB and XOR. --- src/codegen_backend_arm.c | 6 +- src/codegen_backend_arm64.c | 6 +- src/codegen_backend_arm64_ops.c | 11 + src/codegen_backend_arm64_ops.h | 2 + src/codegen_backend_arm64_uops.c | 22 +- src/codegen_backend_arm_uops.c | 40 +- src/codegen_backend_x86-64_ops.c | 42 +- src/codegen_backend_x86-64_ops.h | 4 + src/codegen_backend_x86-64_uops.c | 36 +- src/codegen_backend_x86.c | 12 +- src/codegen_backend_x86_ops.c | 36 +- src/codegen_backend_x86_ops.h | 4 + src/codegen_backend_x86_uops.c | 36 +- src/codegen_ir_defs.h | 4 + src/codegen_ops_arith.c | 1313 +++++++++++++++++++++-------- src/codegen_ops_logic.c | 427 ++++++++-- src/codegen_reg.c | 27 +- src/codegen_reg.h | 8 +- 18 files changed, 1524 insertions(+), 512 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 09630ed..908c5e1 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -221,7 +221,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm_nop(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); while (block_pos != BLOCK_START) host_arm_nop(block); @@ -229,7 +229,7 @@ void codegen_backend_prologue(codeblock_t *block) /*Entry code*/ host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x20); host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET); host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); offset = add_literal(block, (uintptr_t)&cpu_state); @@ -238,7 +238,7 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); if (block_pos > ARM_LITERAL_POOL_OFFSET) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 99e1c23..4ae98f0 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -237,7 +237,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_NOP(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); @@ -255,7 +255,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -48); offset = add_literal_q(block, (uintptr_t)&cpu_state); host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); @@ -263,7 +263,7 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 4effa1a..0a6b8f8 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -34,6 +34,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) @@ -43,6 +44,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) +#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_ANDS_IMM (0x0e4 << 23) @@ -63,6 +65,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ADD_LSL (0x058 << 21) #define OPCODE_ADD_LSR (0x05a << 21) +#define OPCODE_ADDX_LSL (0x458 << 21) #define OPCODE_AND_ASR (0x054 << 21) #define OPCODE_AND_LSL (0x050 << 21) #define OPCODE_AND_ROR (0x056 << 21) @@ -70,8 +73,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSR (0x152 << 21) +#define OPCODE_ORRX_LSL (0x550 << 21) #define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_SUB_LSR (0x25a << 21) +#define OPCODE_SUBX_LSL (0x658 << 21) #define OPCODE_BLR (0xd63f0000) #define OPCODE_LDR_REG (0xb8606800) @@ -444,6 +449,12 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { int hw; diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 6178c6b..9fc993d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -48,6 +48,8 @@ void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, in void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 8b5aad0..cd9f180 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -65,17 +65,17 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); @@ -809,4 +809,20 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (in_range12_w(stack_offset)) + host_arm64_LDR_IMM_W(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + if (in_range12_w(stack_offset)) + host_arm64_STR_IMM_W(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_write_32_stack - not in range\n"); +} + #endif diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index b6f5f41..0ec4c75 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -75,15 +75,15 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) { host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); - host_arm_UADD16(block, dest_reg, src_reg_a, REG_TEMP); + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { @@ -118,15 +118,15 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && src_reg == dest_reg) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_UADD16(block, dest_reg, src_reg, REG_TEMP); + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && src_reg == dest_reg) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) { @@ -905,4 +905,20 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_LDR_IMM(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_STR_IMM(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_write_32 - not in range\n"); +} + #endif diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index f508e8a..9262541 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -174,21 +174,21 @@ void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } @@ -501,6 +501,42 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ } +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg >= 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 6070054..4b67841 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -62,11 +62,15 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d 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_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); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 3e56105..d0efa31 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -26,15 +26,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -49,15 +56,22 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + else + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -638,4 +652,14 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV64_ABS_REG(block, p, host_reg); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); +} + #endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index b81bfce..17f588f 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -253,18 +253,18 @@ void codegen_backend_prologue(codeblock_t *block) addbyte(0x55); /*PUSH EBP*/ addbyte(0x56); /*PUSH ESI*/ addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $16,%esp*/ + addbyte(0x83); /*SUBL $32,%esp*/ addbyte(0xEC); - addbyte(0x10); + addbyte(0x20); addbyte(0xBD); /*MOVL EBP, &cpu_state*/ addlong(((uintptr_t)&cpu_state) + 128); } void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0x83); /*ADDL $32,%esp*/ addbyte(0xC4); - addbyte(0x10); + addbyte(0x20); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ @@ -287,9 +287,9 @@ void codegen_backend_epilogue(codeblock_t *block) addbyte(0xe8); /*CALL x86gpf*/ addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0x83); /*ADDL $32,%esp*/ addbyte(0xC4); - addbyte(0x10); + addbyte(0x20); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 1447338..bcc16ef 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -164,21 +164,21 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } @@ -420,6 +420,36 @@ void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index cf4a793..8d3df16 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -40,12 +40,16 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); + void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift); void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e043cc9..c5f3f80 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -36,15 +36,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -59,15 +66,22 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + else + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -636,4 +650,14 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); +} + #endif diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 7a1d947..a864468 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -304,4 +304,8 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); +void codegen_direct_read_32_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); + #endif diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 1e3f226..9e7fb43 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -49,14 +49,29 @@ uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropADD_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -65,30 +80,61 @@ uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropADD_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -97,30 +143,60 @@ uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropADD_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -129,16 +205,32 @@ uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -184,14 +276,29 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropCMP_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); @@ -200,14 +307,29 @@ uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); @@ -216,14 +338,29 @@ uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } uint32_t ropCMP_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); @@ -232,14 +369,29 @@ uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); @@ -248,14 +400,29 @@ uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } uint32_t ropCMP_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; @@ -263,14 +430,29 @@ uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; @@ -318,14 +500,29 @@ uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropSUB_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -334,30 +531,61 @@ uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropSUB_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -366,30 +594,60 @@ uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropSUB_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -398,16 +656,32 @@ uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -415,70 +689,128 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t rop80(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 & 7; - uint8_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint8_t imm = fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint8_t imm; + + 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); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; - case 0x08: /*OR*/ - imm = fastreadb(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - case 0x20: /*AND*/ - imm = fastreadb(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - case 0x28: /*SUB*/ - imm = fastreadb(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadb(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -486,70 +818,128 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } uint32_t rop81_w(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 & 7; - uint16_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint16_t imm = fastreadw(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint16_t imm; + + 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); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadw(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - case 0x08: /*OR*/ - imm = fastreadw(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x20: /*AND*/ - imm = fastreadw(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x28: /*SUB*/ - imm = fastreadw(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadw(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadw(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -557,69 +947,126 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop81_l(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 & 7; - uint32_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint32_t imm = fastreadl(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint32_t imm; + + 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); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadl(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - case 0x08: /*OR*/ - imm = fastreadl(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x20: /*AND*/ - imm = fastreadl(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x28: /*SUB*/ - imm = fastreadl(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadl(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadl(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -628,70 +1075,128 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop83_w(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 & 7; - uint16_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint16_t imm; + + 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); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - case 0x08: /*OR*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x20: /*AND*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x28: /*SUB*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -699,69 +1204,127 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop83_l(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 & 7; uint32_t imm; - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - case 0x38: /*CMP*/ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + 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); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - default: - return 0; + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } } codegen_flags_changed = 1; diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index ad74d7e..df4a3de 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -43,12 +43,25 @@ uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropAND_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -57,26 +70,55 @@ uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropAND_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -85,26 +127,55 @@ uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropAND_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -113,14 +184,30 @@ uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -161,12 +248,25 @@ uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 } uint32_t ropOR_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -175,26 +275,55 @@ uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropOR_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -203,42 +332,87 @@ uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropOR_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_res, dest_reg); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -279,12 +453,25 @@ uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropXOR_b_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -293,26 +480,55 @@ uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropXOR_b_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_w_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -321,42 +537,87 @@ uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropXOR_w_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_l_rm(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 & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(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); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_res, dest_reg); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_l_rmw(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, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_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); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 28a08be..8bbf3ca 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -67,10 +67,10 @@ struct /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - [IREG_temp0] = {REG_DWORD, NULL}, - [IREG_temp1] = {REG_DWORD, NULL}, - [IREG_temp2] = {REG_DWORD, NULL}, - [IREG_temp3] = {REG_DWORD, NULL}, + [IREG_temp0] = {REG_DWORD, (void *)16}, + [IREG_temp1] = {REG_DWORD, (void *)20}, + [IREG_temp2] = {REG_DWORD, (void *)24}, + [IREG_temp3] = {REG_DWORD, (void *)28}, }; void codegen_reg_reset() @@ -99,7 +99,10 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { case REG_DWORD: - codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_32_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; default: @@ -113,19 +116,27 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) { int ir_reg = IREG_GET_REG(host_regs[c].reg); + void *p = ireg_data[ir_reg].p; switch (ireg_data[ir_reg].native_size) { case REG_BYTE: - codegen_direct_write_8(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_BYTE %p\n", p); + codegen_direct_write_8(block, p, codegen_host_reg_list[c]); break; case REG_DWORD: - codegen_direct_write_32(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + codegen_direct_write_32_stack(block, (int)p, codegen_host_reg_list[c]); + else + codegen_direct_write_32(block, p, codegen_host_reg_list[c]); break; case REG_POINTER: - codegen_direct_write_ptr(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_POINTER %p\n", p); + codegen_direct_write_ptr(block, p, codegen_host_reg_list[c]); break; default: diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 4fd0dd8..c57a0e5 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -82,7 +82,13 @@ enum IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, - IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, + + IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, + IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, + + IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, + IREG_temp1_B = IREG_temp1 + IREG_SIZE_B }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL))