From 584e67845beb50ea932f9f8163cf82e74976139b Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 31 Mar 2019 18:21:56 +0100 Subject: [PATCH] Added ROL, ROR and NOP uops to ARM and ARM64 backends. --- src/codegen_backend_arm64_ops.c | 11 ++ src/codegen_backend_arm64_ops.h | 3 + src/codegen_backend_arm64_uops.c | 232 ++++++++++++++++++++++++++++++- src/codegen_backend_arm_ops.c | 29 ++++ src/codegen_backend_arm_ops.h | 4 + src/codegen_backend_arm_uops.c | 227 +++++++++++++++++++++++++++++- 6 files changed, 504 insertions(+), 2 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index eaf5089..1bc49c0 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -91,6 +91,7 @@ #define OPCODE_ORR_ASR (0x154 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSR (0x152 << 21) +#define OPCODE_ORR_ROR (0x156 << 21) #define OPCODE_ORRX_LSL (0x550 << 21) #define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_SUB_LSR (0x25a << 21) @@ -164,6 +165,7 @@ #define OPCODE_NOP (0xd503201f) #define OPCODE_ORR_V (0x0ea01c00) #define OPCODE_RET (0xd65f0000) +#define OPCODE_ROR (0x1ac02c00) #define OPCODE_SADDLP_V2S_4H (0x0e602800) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) @@ -994,6 +996,10 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int { codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) { @@ -1092,6 +1098,11 @@ void host_arm64_RET(codeblock_t *block, int reg) codegen_addlong(block, OPCODE_RET | Rn(reg)); } +void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +{ + codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); +} + void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) { codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 42760dd..904aa6d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -143,6 +143,7 @@ void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data); void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); @@ -162,6 +163,8 @@ void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_RET(codeblock_t *block, int reg); +void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); + void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg); void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 0f56360..d7fe7f6 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1474,6 +1474,11 @@ static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { 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); @@ -2354,6 +2359,225 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(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), shift_reg = HOST_REG_GET(uop->src_reg_b_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_imm(block, REG_TEMP2, 32); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 16); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + cs = cs; + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROL_IMM(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_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else + { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR(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), shift_reg = HOST_REG_GET(uop->src_reg_b_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_ROR(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR_IMM(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_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else + { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_SAR(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), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2847,6 +3071,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, @@ -2945,7 +3173,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index b6a6142..9be45f2 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -49,6 +49,7 @@ #define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) #define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) #define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +#define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) #define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) #define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) @@ -177,10 +178,12 @@ #define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #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 SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) #define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) #define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) +#define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) #define BFI_lsb(lsb) ((lsb) << 7) #define BFI_msb(msb) ((msb) << 16) @@ -695,6 +698,14 @@ void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); } +void host_arm_MOV_REG_ROR(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_ROR_IMM(shift)); +} +void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); +} void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { @@ -730,6 +741,24 @@ void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, i codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} +void host_arm_RSB_REG_LSL(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_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)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 3e930df..7627f51 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -89,6 +89,8 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); +void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); @@ -106,6 +108,8 @@ void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, i #define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) #define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) +void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 402a7d7..12c2eb9 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1595,6 +1595,11 @@ static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { 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); @@ -2503,6 +2508,220 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(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), shift_reg = HOST_REG_GET(uop->src_reg_b_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_RSB_IMM(block, REG_TEMP2, shift_reg, 32); + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROL_IMM(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_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } + else + { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } + else + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR(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), shift_reg = HOST_REG_GET(uop->src_reg_b_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_ROR_REG(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR_IMM(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_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } + else + { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_SAR(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), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2997,6 +3216,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, @@ -3095,7 +3318,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p)