Added recompiled versions of mem->reg, reg->mem and imm->mem versions of ADD, AND, CMP, OR, SUB and XOR.

This commit is contained in:
SarahW 2018-07-27 22:24:34 +01:00
commit e64271f5bb
18 changed files with 1554 additions and 542 deletions

View file

@ -221,7 +221,7 @@ void codegen_backend_prologue(codeblock_t *block)
host_arm_nop(block); host_arm_nop(block);
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ 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); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC);
while (block_pos != BLOCK_START) while (block_pos != BLOCK_START)
host_arm_nop(block); host_arm_nop(block);
@ -229,7 +229,7 @@ void codegen_backend_prologue(codeblock_t *block)
/*Entry code*/ /*Entry code*/
host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR); 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_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET);
host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START);
offset = add_literal(block, (uintptr_t)&cpu_state); 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) 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); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC);
if (block_pos > ARM_LITERAL_POOL_OFFSET) if (block_pos > ARM_LITERAL_POOL_OFFSET)

View file

@ -237,7 +237,7 @@ void codegen_backend_prologue(codeblock_t *block)
host_arm64_NOP(block); host_arm64_NOP(block);
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ 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_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_X23, REG_X24, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, 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_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_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_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); offset = add_literal_q(block, (uintptr_t)&cpu_state);
host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); 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) 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_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_X23, REG_X24, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16);

View file

@ -34,6 +34,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_SHIFT 24 #define OPCODE_SHIFT 24
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT)
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
#define OPCODE_CMN_IMM (0x31 << 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_W (0x18 << OPCODE_SHIFT)
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT)
#define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_AND_IMM (0x024 << 23)
#define OPCODE_ANDS_IMM (0x0e4 << 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_LSL (0x058 << 21)
#define OPCODE_ADD_LSR (0x05a << 21) #define OPCODE_ADD_LSR (0x05a << 21)
#define OPCODE_ADDX_LSL (0x458 << 21)
#define OPCODE_AND_ASR (0x054 << 21) #define OPCODE_AND_ASR (0x054 << 21)
#define OPCODE_AND_LSL (0x050 << 21) #define OPCODE_AND_LSL (0x050 << 21)
#define OPCODE_AND_ROR (0x056 << 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_EOR_LSL (0x250 << 21)
#define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSL (0x150 << 21)
#define OPCODE_ORR_LSR (0x152 << 21) #define OPCODE_ORR_LSR (0x152 << 21)
#define OPCODE_ORRX_LSL (0x550 << 21)
#define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_SUB_LSL (0x258 << 21)
#define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_SUB_LSR (0x25a << 21)
#define OPCODE_SUBX_LSL (0x658 << 21)
#define OPCODE_BLR (0xd63f0000) #define OPCODE_BLR (0xd63f0000)
#define OPCODE_LDR_REG (0xb8606800) #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)); 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) void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
{ {
int hw; int hw;

View file

@ -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(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_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_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); void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);

View file

@ -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); 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_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); 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_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); 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_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8);
host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 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"); 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 #endif

View file

@ -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); 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_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b);
host_arm_UADD16(block, dest_reg, src_reg_a, REG_TEMP); 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_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b);
host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); 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) 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); 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_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data);
host_arm_UADD16(block, dest_reg, src_reg, REG_TEMP); 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_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data);
host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); 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) 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"); 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 #endif

View file

@ -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) 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)) 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*/ 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) 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)) 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*/ 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) 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)) 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*/ 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]*/ 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) void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
{ {
if (reg >= 8) if (reg >= 8)

View file

@ -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_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_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_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_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_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_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_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); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);

View file

@ -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)) 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)) 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)) 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 else
fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); 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)) 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)) 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)) 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 else
fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); 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); 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 #endif

View file

@ -253,18 +253,18 @@ void codegen_backend_prologue(codeblock_t *block)
addbyte(0x55); /*PUSH EBP*/ addbyte(0x55); /*PUSH EBP*/
addbyte(0x56); /*PUSH ESI*/ addbyte(0x56); /*PUSH ESI*/
addbyte(0x57); /*PUSH EDI*/ addbyte(0x57); /*PUSH EDI*/
addbyte(0x83); /*SUBL $16,%esp*/ addbyte(0x83); /*SUBL $32,%esp*/
addbyte(0xEC); addbyte(0xEC);
addbyte(0x10); addbyte(0x20);
addbyte(0xBD); /*MOVL EBP, &cpu_state*/ addbyte(0xBD); /*MOVL EBP, &cpu_state*/
addlong(((uintptr_t)&cpu_state) + 128); addlong(((uintptr_t)&cpu_state) + 128);
} }
void codegen_backend_epilogue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block)
{ {
addbyte(0x83); /*ADDL $16,%esp*/ addbyte(0x83); /*ADDL $32,%esp*/
addbyte(0xC4); addbyte(0xC4);
addbyte(0x10); addbyte(0x20);
addbyte(0x5f); /*POP EDI*/ addbyte(0x5f); /*POP EDI*/
addbyte(0x5e); /*POP ESI*/ addbyte(0x5e); /*POP ESI*/
addbyte(0x5d); /*POP EBP*/ addbyte(0x5d); /*POP EBP*/
@ -287,9 +287,9 @@ void codegen_backend_epilogue(codeblock_t *block)
addbyte(0xe8); /*CALL x86gpf*/ addbyte(0xe8); /*CALL x86gpf*/
addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
addbyte(0x83); /*ADDL $16,%esp*/ addbyte(0x83); /*ADDL $32,%esp*/
addbyte(0xC4); addbyte(0xC4);
addbyte(0x10); addbyte(0x20);
addbyte(0x5f); /*POP EDI*/ addbyte(0x5f); /*POP EDI*/
addbyte(0x5e); /*POP ESI*/ addbyte(0x5e); /*POP ESI*/
addbyte(0x5d); /*POP EBP*/ addbyte(0x5d); /*POP EBP*/

View file

@ -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) 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) 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*/ 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) 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) 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*/ 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) 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) 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*/ 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]*/ 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) 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*/ codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/

View file

@ -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_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_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(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_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_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_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_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); void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);

View file

@ -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)) 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)) 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)) 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 else
fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); 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)) 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)) 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)) 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 else
fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); 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); 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 #endif

View file

@ -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_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_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 #endif

File diff suppressed because it is too large Load diff

View file

@ -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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_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; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_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; codegen_flags_changed = 1;
return op_pc + 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) 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) if ((fetchdat & 0xc0) == 0xc0)
return 0; {
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_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1; codegen_flags_changed = 1;
return op_pc + 1; return op_pc + 1;

View file

@ -67,10 +67,10 @@ struct
/*Temporary registers are stored on the stack, and are not guaranteed to /*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 be preserved across uOPs. They will not be written back if they will
not be read again.*/ not be read again.*/
[IREG_temp0] = {REG_DWORD, NULL}, [IREG_temp0] = {REG_DWORD, (void *)16},
[IREG_temp1] = {REG_DWORD, NULL}, [IREG_temp1] = {REG_DWORD, (void *)20},
[IREG_temp2] = {REG_DWORD, NULL}, [IREG_temp2] = {REG_DWORD, (void *)24},
[IREG_temp3] = {REG_DWORD, NULL}, [IREG_temp3] = {REG_DWORD, (void *)28},
}; };
void codegen_reg_reset() 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) switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size)
{ {
case REG_DWORD: 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; break;
default: 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) static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate)
{ {
int ir_reg = IREG_GET_REG(host_regs[c].reg); int ir_reg = IREG_GET_REG(host_regs[c].reg);
void *p = ireg_data[ir_reg].p;
switch (ireg_data[ir_reg].native_size) switch (ireg_data[ir_reg].native_size)
{ {
case REG_BYTE: 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; break;
case REG_DWORD: 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; break;
case REG_POINTER: 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; break;
default: default:

View file

@ -82,7 +82,13 @@ enum
IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, 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)) #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL))