Added recompiled versions of 8 and 16 bit immediate->reg and reg->reg versions of MOV, ADD, SUB, CMP, AND, OR and XOR.
This commit is contained in:
parent
e4e0f76d5c
commit
648aa0e3e8
17 changed files with 3006 additions and 231 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue