From 648aa0e3e83d2b2f081d13a61b4d4aefd5473369 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 17 Jul 2018 22:08:25 +0100 Subject: [PATCH] Added recompiled versions of 8 and 16 bit immediate->reg and reg->reg versions of MOV, ADD, SUB, CMP, AND, OR and XOR. --- src/codegen.c | 2 +- src/codegen_backend_arm64_defs.h | 2 + src/codegen_backend_arm64_uops.c | 483 +++++++++++++++++++++++- src/codegen_backend_arm_uops.c | 514 ++++++++++++++++++++++++- src/codegen_backend_x86-64_uops.c | 605 ++++++++++++++++++++++++++---- src/codegen_backend_x86_uops.c | 604 +++++++++++++++++++++++++---- src/codegen_ir.c | 4 +- src/codegen_ir_defs.h | 36 +- src/codegen_ops.c | 20 +- src/codegen_ops_arith.c | 484 ++++++++++++++++++++++++ src/codegen_ops_arith.h | 21 ++ src/codegen_ops_logic.c | 234 ++++++++++++ src/codegen_ops_logic.h | 18 + src/codegen_ops_mov.c | 72 ++++ src/codegen_ops_mov.h | 6 + src/codegen_reg.c | 70 ++-- src/codegen_reg.h | 62 ++- 17 files changed, 3006 insertions(+), 231 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 2255d85..512b4b3 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -58,7 +58,7 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin { int base_reg, index_reg, offset; - switch (cpu_rm) + switch (cpu_rm & 7) { case 0: case 1: case 7: base_reg = IREG_EBX; diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 1c4de84..7de61f0 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -73,4 +73,6 @@ #define REG_CPUSTATE REG_X29 +#define REG_TEMP REG_X7 + #define CODEGEN_HOST_REGS 5 \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index e838e4f..b641a4b 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -45,18 +45,25 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_MOVZ_W (0x0a5 << 23) #define OPCODE_ORR_IMM (0x064 << 23) +#define OPCODE_BFI (0x0cc << 22) #define OPCODE_LDR_IMM_W (0x2e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_UBFX (0x14c << 22) #define OPCODE_ADD_LSL (0x058 << 21) +#define OPCODE_ADD_LSR (0x05a << 21) +#define OPCODE_AND_ASR (0x054 << 21) #define OPCODE_AND_LSL (0x050 << 21) +#define OPCODE_AND_ROR (0x056 << 21) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_LSL (0x150 << 21) +#define OPCODE_ORR_LSR (0x152 << 21) #define OPCODE_SUB_LSL (0x258 << 21) +#define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_BLR (0xd63f0000) #define OPCODE_NOP (0xd503201f) @@ -174,13 +181,33 @@ void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } - +void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +//12001c00 S=0 R=7 void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); + } + else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ { codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } + else if (imm_data == 0x0000ff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + } else { host_arm64_mov_imm(block, REG_W16, imm_data); @@ -191,6 +218,19 @@ void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); +} void host_arm64_BLR(codeblock_t *block, int addr_reg) { @@ -261,6 +301,11 @@ void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shif codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { int hw; @@ -300,6 +345,18 @@ void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t { codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); } + else if (imm_data == 0xffff0000) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f)); + } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } else { host_arm64_mov_imm(block, REG_W16, imm_data); @@ -372,6 +429,15 @@ void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); +} void host_arm64_call(codeblock_t *block, void *dst_addr) { @@ -391,16 +457,83 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) } } +#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_ADD_REG(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)) + { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_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)) + { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_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)) + { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); + host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + 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) + { + 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) + { + 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) + { + 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_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -412,12 +545,67 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_arm64_AND_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_AND_REG(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) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } + else + fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -456,13 +644,65 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_arm64_MOV_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_arm64_mov_imm(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV_IMM %x\n", uop->dest_reg_a_real); return 0; } @@ -474,14 +714,92 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_arm64_ORR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_ORR_REG(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) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_ORR_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) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -510,23 +828,157 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - host_arm64_SUB_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_SUB_REG(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)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_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)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_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)) + { + host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_SUB_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)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_arm64_EOR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_EOR_REG(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) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_EOR_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) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -545,7 +997,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 372044b..17fd823 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -41,9 +41,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) #define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) #define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) #define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) #define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) #define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) #define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) @@ -51,7 +54,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) #define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) -#define OPCODE_BLX 0xe12fff30 +#define OPCODE_BFI 0xe7c00010 +#define OPCODE_BLX 0xe12fff30 +#define OPCODE_UADD8 0xe6500f90 +#define OPCODE_UADD16 0xe6500f10 +#define OPCODE_USUB8 0xe6500ff0 +#define OPCODE_USUB16 0xe6500f70 +#define OPCODE_UXTB 0xe6ef0070 +#define OPCODE_UXTH 0xe6ff0070 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -66,6 +76,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define SHIFT_IMM_SHIFT 7 #define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) + +#define BFI_lsb(lsb) ((lsb) << 7) +#define BFI_msb(msb) ((msb) << 16) + +#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) + +#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) @@ -201,6 +219,20 @@ void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); +} + +void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} +void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + void host_arm_BLX(codeblock_t *block, int addr_reg) { codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); @@ -266,6 +298,20 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +{ + codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); +} + +void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); +} void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { @@ -288,6 +334,11 @@ void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); @@ -327,12 +378,45 @@ void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr { codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) { codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); } +void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} + +void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} void host_arm_call(codeblock_t *block, void *dst_addr) { @@ -346,15 +430,85 @@ void host_arm_nop(codeblock_t *block) host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); } +#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) + static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + 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) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_UADD16(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); +// host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); +// return 0; + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + 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) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_UADD16(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && src_reg == dest_reg) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; + } static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { @@ -364,12 +518,69 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_arm_AND_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_AND_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) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 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) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_arm_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_AND_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) + { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -437,22 +648,75 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_arm_MOV_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, uop->dest_reg_a_real, uop->imm_data); - else + if (REG_IS_L(dest_size)) { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, uop->dest_reg_a_real, REG_LITERAL, offset); + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, dest_reg, REG_LITERAL, offset); + } } + else if (REG_IS_W(dest_size)) + { + host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size)) + { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size)) + { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); return 0; } @@ -464,14 +728,92 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, dest_reg, src_reg, 0); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, dest_reg, src_reg, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, dest_reg, src_reg, 0); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_arm_ORR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_ORR_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) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_ORR_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) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -506,23 +848,158 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_SUB_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)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + 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)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + 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)) + { + host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; + +// host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); +// return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - host_arm_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_SUB_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)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_arm_EOR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_EOR_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) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_EOR_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) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -541,6 +1018,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4e0d50c..ff1f31f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -117,29 +117,66 @@ static inline void call(codeblock_t *block, uintptr_t func) } } +static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ +} +static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static 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"); + + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} +static 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"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} static 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)) @@ -148,29 +185,66 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } +static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ +} +static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_AND8_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_AND8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} +static void host_x86_AND16_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_AND16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} static void host_x86_AND32_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)) @@ -316,6 +390,19 @@ static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) } } +static void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg >= 8) + fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ +} +static void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { if (reg & 8) @@ -332,6 +419,20 @@ static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_dat codegen_addquad(block, imm_data); } +static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV8_REG_REG - bad reg\n"); + + codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV16_REG_REG - bad reg\n"); + + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) @@ -360,29 +461,79 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ +} +static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_OR8_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_OR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} +static void host_x86_OR16_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_OR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} static void host_x86_OR32_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)) @@ -391,33 +542,70 @@ static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } +static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ +} +static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_SUB8_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_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} +static void host_x86_SUB16_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_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} static void host_x86_SUB32_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_SUB32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } @@ -431,29 +619,66 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ +} +static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_XOR8_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_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} +static void host_x86_XOR16_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_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} static void host_x86_XOR32_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)) @@ -462,16 +687,56 @@ static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } +#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + 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); + } + 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); + } + 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); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + 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); + } + 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); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -489,13 +754,47 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_AND32_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_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -539,12 +838,46 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); + return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -552,15 +885,66 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_OR32_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_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -581,29 +965,103 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_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)) + { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_XOR32_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_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -622,7 +1080,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 9dac085..0f68a25 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -100,30 +100,67 @@ static int is_imm8(uint32_t imm_data) return 0; } +static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ +} +static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static 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"); + + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} +static 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"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} static 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) @@ -132,30 +169,67 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } +static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ +} +static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_AND8_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_AND8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} +static void host_x86_AND16_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_AND16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -260,6 +334,23 @@ static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addlong(block, (uint32_t)p); } } + +static 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*/ +} +static void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (!imm_data) + { + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } + else + { + codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (!imm_data) @@ -273,6 +364,14 @@ static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm } } +static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); +} +static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); +} static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); @@ -298,6 +397,29 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +static void host_x86_OR8_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_OR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} +static void host_x86_OR16_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_OR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -305,60 +427,121 @@ static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } + +static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ +} +static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ +} +static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_SUB8_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_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} +static void host_x86_SUB16_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_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} static void host_x86_SUB32_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_SUB32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } @@ -368,6 +551,20 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_ho codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR8_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_XOR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} +static void host_x86_XOR16_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_XOR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -376,27 +573,50 @@ static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } +static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ +} +static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } @@ -406,15 +626,61 @@ static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); }*/ +#define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) +#define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) +#define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) +#define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) + +#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) + static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + 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); + } + 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); + } + 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); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + 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); + } + 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); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -432,13 +698,47 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_AND32_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_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -475,12 +775,46 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); + return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -488,15 +822,66 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_OR32_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_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -513,29 +898,103 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_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_SUB16_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)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_XOR32_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_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -554,6 +1013,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 36bea69..1d89807 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -32,11 +32,11 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b); if (uop->src_reg_a.reg != IREG_INVALID) { - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a); + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); } if (uop->src_reg_b.reg != IREG_INVALID) { - uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b); + uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); } if (uop->dest_reg_a.reg != IREG_INVALID) { diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index bac0ab6..04ee628 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -27,22 +27,40 @@ #define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a) #define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b) #define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) +/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) #define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +/*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) +/*UOP_MOV_IMM - dest_reg = imm_data*/ #define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) +/*UOP_MOV - dest_reg = src_reg_a*/ #define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) +/*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/ +#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) +/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) +/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ #define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) +/*UOP_AND - dest_reg = src_reg_a & src_reg_b*/ #define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +/*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/ #define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +/*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data) + Intended for EA calcluations, imm_data must be between 0 and 3*/ #define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) +/*UOP_OR - dest_reg = src_reg_a | src_reg_b*/ #define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) +/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/ #define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) +/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/ #define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/ #define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) +/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/ #define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) +/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ #define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) #define UOP_MAX 0x3b @@ -81,7 +99,6 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->dest_reg_a = invalid_ir_reg; uop->src_reg_a = invalid_ir_reg; uop->src_reg_b = invalid_ir_reg; -// uop->src_reg_c = invalid_ir_reg; return uop; } @@ -121,6 +138,16 @@ static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int de uop->dest_reg_a = codegen_reg_write(dest_reg); } +static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->imm_data = imm; +} + static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) { uop_t *uop = uop_alloc(ir); @@ -196,9 +223,10 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) -#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) -#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) -#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 728c659..caaf3ff 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -10,20 +10,20 @@ RecompOpFn recomp_opcodes[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, NULL, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, +/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -32,20 +32,20 @@ RecompOpFn recomp_opcodes[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, ropADD_l_rmw, NULL, ropADD_l_rm, NULL, ropADD_EAX_imm, NULL, NULL, NULL, ropOR_l_rmw, NULL, ropOR_l_rm, NULL, ropOR_EAX_imm, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, NULL, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, ropAND_l_rmw, NULL, ropAND_l_rm, NULL, ropAND_EAX_imm, NULL, NULL, NULL, ropSUB_l_rmw, NULL, ropSUB_l_rm, NULL, ropSUB_EAX_imm, NULL, NULL, -/*30*/ NULL, ropXOR_l_rmw, NULL, ropXOR_l_rm, NULL, ropXOR_EAX_imm, NULL, NULL, NULL, ropCMP_l_rmw, NULL, ropCMP_l_rm, NULL, ropCMP_EAX_imm, NULL, NULL, +/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, +/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, rop81_l, NULL, rop83_l, NULL, NULL, NULL, NULL, NULL, ropMOV_l_r, NULL, ropMOV_r_l, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index d516152..1e3f226 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -8,6 +8,32 @@ #include "codegen_ops.h" #include "codegen_ops_arith.h" +uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -21,6 +47,70 @@ uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + 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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + 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; @@ -54,6 +144,32 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -66,6 +182,70 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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); + + codegen_flags_changed = 1; + return op_pc + 1; +} 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; @@ -97,6 +277,32 @@ uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -110,6 +316,70 @@ uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + 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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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)); + + 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; @@ -143,6 +413,148 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +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) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = fastreadb(cs + op_pc + 1); + + 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*/ + imm = fastreadb(cs + op_pc + 1); + + 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*/ + imm = fastreadb(cs + op_pc + 1); + + 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*/ + imm = fastreadb(cs + op_pc + 1); + + 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; + } + + codegen_flags_changed = 1; + return op_pc + 2; +} +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) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = fastreadw(cs + op_pc + 1); + + 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*/ + imm = fastreadw(cs + op_pc + 1); + + 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*/ + imm = fastreadw(cs + op_pc + 1); + + 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*/ + imm = fastreadw(cs + op_pc + 1); + + 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; + } + + codegen_flags_changed = 1; + return op_pc + 3; +} 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; @@ -213,6 +625,78 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_flags_changed = 1; return op_pc + 5; } + +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) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + 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*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + 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*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + 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*/ + 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_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; + } + + codegen_flags_changed = 1; + return op_pc + 2; +} 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; diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index f219318..2faa55d 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -1,14 +1,35 @@ +uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +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); +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); +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); +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); 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); 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); +uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +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); +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); +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); +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); 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); 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); +uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +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); +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); +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); +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); 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); 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); +uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +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); 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); +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); 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); diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index c4aca26..ad74d7e 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -8,6 +8,28 @@ #include "codegen_ops.h" #include "codegen_ops_logic.h" +uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -19,6 +41,62 @@ uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; @@ -48,6 +126,28 @@ uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -59,6 +159,62 @@ uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; @@ -88,6 +244,28 @@ uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } +uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -99,6 +277,62 @@ uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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_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; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + 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; diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h index 127f4c1..cfb7af3 100644 --- a/src/codegen_ops_logic.h +++ b/src/codegen_ops_logic.h @@ -1,11 +1,29 @@ +uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropAND_EAX_imm(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); +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_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_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_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_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_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropOR_EAX_imm(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); +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_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_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_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_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_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_EAX_imm(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); +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_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_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_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_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 2266602..b8bb8aa 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -7,6 +7,22 @@ #include "codegen_ops.h" #include "codegen_ops_mov.h" +uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm = fastreadb(cs + op_pc); + + uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); + + return op_pc + 1; +} +uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); + + return op_pc + 2; +} uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -18,6 +34,34 @@ uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 +uint32_t ropMOV_b_r(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; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = (fetchdat >> 3) & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + return 0; + + return op_pc + 1; +} +uint32_t ropMOV_w_r(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; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = (fetchdat >> 3) & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + return 0; + + return op_pc + 1; +} uint32_t ropMOV_l_r(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; @@ -32,6 +76,34 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } +uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + return 0; + + return op_pc + 1; +} +uint32_t ropMOV_r_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 >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + return 0; + + return op_pc + 1; +} uint32_t ropMOV_r_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 >> 3) & 7; diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index c9bafdc..cf8b31f 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -1,3 +1,9 @@ +uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 164a190..43027f3 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -84,27 +84,28 @@ void codegen_reg_reset() static inline int ir_reg_is_invalid(ir_reg_t ir_reg) { - return (ir_reg.reg == IREG_INVALID); + return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) { - switch (ireg_data[ir_reg.reg].native_size) + 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[ir_reg.reg].p); + codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; default: - fatal("codegen_reg_load - native_size=%i\n", ireg_data[ir_reg.reg].native_size); + fatal("codegen_reg_load - native_size=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size); } host_regs[c] = ir_reg; +//pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version); } static void codegen_reg_writeback(codeblock_t *block, int c) { - int ir_reg = host_regs[c].reg; + int ir_reg = IREG_GET_REG(host_regs[c].reg); switch (ireg_data[ir_reg].native_size) { @@ -141,28 +142,28 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ if (!ir_reg_is_invalid(dest_reg_a)) { - if (!ir_reg_is_invalid(src_reg_a) && src_reg_a.reg == dest_reg_a.reg && src_reg_a.version == dest_reg_a.version-1) + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version-1) dest_reference++; - if (!ir_reg_is_invalid(src_reg_b) && src_reg_b.reg == dest_reg_a.reg && src_reg_b.version == dest_reg_a.version-1) + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1) dest_reference++; } for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(src_reg_a) && host_regs[c].reg == src_reg_a.reg) + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_a.reg)) { if (host_regs[c].version != src_reg_a.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n"); host_regs_locked |= (1 << c); } - if (!ir_reg_is_invalid(src_reg_b) && host_regs[c].reg == src_reg_b.reg) + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_b.reg)) { if (host_regs[c].version != src_reg_b.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); host_regs_locked |= (1 << c); } - if (!ir_reg_is_invalid(dest_reg_a) && host_regs[c].reg == dest_reg_a.reg) + if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) { - if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[host_regs[c].reg][host_regs[c].version] == dest_reference)) + if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference)) host_regs_locked |= (1 << c); else fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", host_regs[c].version, dest_reg_a.version, dest_reference); @@ -170,17 +171,17 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ } } -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) { int c; /*Search for required register*/ for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && host_regs[c].version == ir_reg.version) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && host_regs[c].version == ir_reg.version) break; - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && reg_version_refcount[host_regs[c].reg][host_regs[c].version]) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]) fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); } @@ -196,33 +197,60 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) fatal("codegen_reg_alloc_read_reg - out of registers\n"); if (host_reg_dirty[c]) codegen_reg_writeback(block, c); +// pclog(" load %i\n", c); codegen_reg_load(block, c, ir_reg); host_regs_locked |= (1 << c); // fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); // codegen_reg_writeback(block, c); host_reg_dirty[c] = 0; } +// else +// pclog(" already loaded %i\n", c); - reg_version_refcount[host_regs[c].reg][host_regs[c].version]--; - if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] < 0) + reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]--; + if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] < 0) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); -// pclog(" codegen_reg_alloc_read_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c]; + if (host_reg_idx) + *host_reg_idx = c; +// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c); + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { int c; + if (IREG_GET_SIZE(ir_reg.reg) != IREG_SIZE_L) + { + /*Read in parent register so we can do partial accesses to it*/ + ir_reg_t parent_reg; + + parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; + parent_reg.version = ir_reg.version - 1; + + codegen_reg_alloc_read_reg(block, parent_reg, &c); + + if (IREG_GET_REG(host_regs[c].reg) != IREG_GET_REG(ir_reg.reg) || host_regs[c].version != ir_reg.version-1) + fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, + host_regs[c].reg,host_regs[c].version, + ir_reg.reg,ir_reg.version); + + host_regs[c].reg = ir_reg.reg; + host_regs[c].version = ir_reg.version; + host_reg_dirty[c] = 1; +// pclog(" codegen_reg_alloc_write_reg: partial %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + } + /*Search for previous version in host register*/ for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { if (host_regs[c].version == ir_reg.version-1) { - if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] != 0) + if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] != 0) fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); break; } @@ -257,7 +285,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) host_regs[c].version = ir_reg.version; host_reg_dirty[c] = 1; // pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c]; + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index e1b4965..b8f4de5 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -1,10 +1,17 @@ #ifndef _CODEGEN_REG_H_ #define _CODEGEN_REG_H_ -#define IREG_SIZE_L (0 << 6) -#define IREG_SIZE_W (1 << 6) -#define IREG_SIZE_B (2 << 6) -#define IREG_SIZE_BH (3 << 6) +#define IREG_REG_MASK 0x3f +#define IREG_SIZE_SHIFT 6 +#define IREG_SIZE_MASK (3 << IREG_SIZE_SHIFT) + +#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK) +#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK) + +#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) +#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) +#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) +#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) enum { @@ -45,9 +52,34 @@ enum IREG_COUNT, - IREG_INVALID = 255 + IREG_INVALID = 63, + + IREG_AX = IREG_EAX + IREG_SIZE_W, + IREG_CX = IREG_ECX + IREG_SIZE_W, + IREG_DX = IREG_EDX + IREG_SIZE_W, + IREG_BX = IREG_EBX + IREG_SIZE_W, + IREG_SP = IREG_ESP + IREG_SIZE_W, + IREG_BP = IREG_EBP + IREG_SIZE_W, + IREG_SI = IREG_ESI + IREG_SIZE_W, + IREG_DI = IREG_EDI + IREG_SIZE_W, + + IREG_AL = IREG_EAX + IREG_SIZE_B, + IREG_CL = IREG_ECX + IREG_SIZE_B, + IREG_DL = IREG_EDX + IREG_SIZE_B, + IREG_BL = IREG_EBX + IREG_SIZE_B, + + IREG_AH = IREG_EAX + IREG_SIZE_BH, + IREG_CH = IREG_ECX + IREG_SIZE_BH, + IREG_DH = IREG_EDX + IREG_SIZE_BH, + IREG_BH = IREG_EBX + IREG_SIZE_BH, + + IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, + + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B }; +#define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) +#define IREG_16(reg) ((reg) + IREG_AX) #define IREG_32(reg) ((reg) + IREG_EAX) extern uint8_t reg_last_version[IREG_COUNT]; @@ -67,13 +99,13 @@ static inline ir_reg_t codegen_reg_read(int reg) { ir_reg_t ireg; - if (reg == IREG_INVALID) + if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_read - IREG_INVALID\n"); ireg.reg = reg; - ireg.version = reg_last_version[reg]; - reg_version_refcount[ireg.reg][ireg.version]++; - if (!reg_version_refcount[ireg.reg][ireg.version]) + ireg.version = reg_last_version[IREG_GET_REG(reg)]; + reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]++; + if (!reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]) fatal("codegen_reg_read - refcount overflow\n"); return ireg; @@ -83,15 +115,15 @@ static inline ir_reg_t codegen_reg_write(int reg) { ir_reg_t ireg; - if (reg == IREG_INVALID) + if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_write - IREG_INVALID\n"); ireg.reg = reg; - ireg.version = reg_last_version[reg] + 1; - reg_last_version[reg]++; - if (!reg_last_version[reg]) + ireg.version = reg_last_version[IREG_GET_REG(reg)] + 1; + reg_last_version[IREG_GET_REG(reg)]++; + if (!reg_last_version[IREG_GET_REG(reg)]) fatal("codegen_reg_write - version overflow\n"); - reg_version_refcount[reg][ireg.version] = 0; + reg_version_refcount[IREG_GET_REG(reg)][ireg.version] = 0; return ireg; } @@ -104,7 +136,7 @@ void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); /*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b); -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg); +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx); ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); #endif