Added recompiled versions of SHL, SHR, SAR, SHLD and SHRD.

This commit is contained in:
SarahW 2018-08-16 21:44:41 +01:00
commit 872a2da788
18 changed files with 1923 additions and 20 deletions

View file

@ -244,6 +244,8 @@ x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat,
cpu_reg = (fetchdat >> 3) & 7;
cpu_rm = fetchdat & 7;
if ((fetchdat & 0xc0) == 0xc0)
return NULL;
if (op_32 & 0x200)
return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset);

View file

@ -73,6 +73,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_AND_ROR (0x056 << 21)
#define OPCODE_ANDS_LSL (0x350 << 21)
#define OPCODE_EOR_LSL (0x250 << 21)
#define OPCODE_ORR_ASR (0x154 << 21)
#define OPCODE_ORR_LSL (0x150 << 21)
#define OPCODE_ORR_LSR (0x152 << 21)
#define OPCODE_ORRX_LSL (0x550 << 21)
@ -80,11 +81,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_SUB_LSR (0x25a << 21)
#define OPCODE_SUBX_LSL (0x658 << 21)
#define OPCODE_ASR (0x1ac02800)
#define OPCODE_BLR (0xd63f0000)
#define OPCODE_LDR_REG (0xb8606800)
#define OPCODE_LDRB_REG (0x38606800)
#define OPCODE_LDRH_REG (0x78606800)
#define OPCODE_LDRX_REG_LSL3 (0xf8607800)
#define OPCODE_LSL (0x1ac02000)
#define OPCODE_LSR (0x1ac02400)
#define OPCODE_NOP (0xd503201f)
#define OPCODE_RET (0xd65f0000)
#define OPCODE_STR_REG (0xb8206800)
@ -271,6 +275,11 @@ void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_
}
}
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg)
{
codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg));
}
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));
@ -447,9 +456,24 @@ void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, in
codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
}
void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg)
{
codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg));
}
void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg)
{
codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg));
}
void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
{
if (dst_reg != src_m_reg)
if (dst_reg != src_m_reg || shift)
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}

View file

@ -9,6 +9,8 @@ void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int
void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_BLR(codeblock_t *block, int addr_reg);
@ -46,6 +48,10 @@ void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int off
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
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);

View file

@ -553,10 +553,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop)
{
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)
else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
{
host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff);
host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0);
host_arm64_ORR_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) && dest_reg == src_reg_a)
{
@ -610,6 +610,201 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
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);
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_ASR(block, dest_reg, src_reg, shift_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16);
host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24);
host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 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_MOV_REG(block, REG_TEMP, src_reg, 16);
host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SAR_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))
{
host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16);
host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24);
host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 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_MOV_REG(block, REG_TEMP, src_reg, 16);
host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL(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_LSL(block, dest_reg, src_reg, shift_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg);
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_LSL(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL_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))
{
host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm64_MOV_REG(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_MOV_REG(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))
{
host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8);
host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR(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_LSR(block, dest_reg, src_reg, shift_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff);
host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff);
host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg);
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_LSR(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR_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))
{
host_arm64_MOV_REG_LSR(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, REG_TEMP, src_reg, 0xffff);
host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 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_AND_IMM(block, REG_TEMP, src_reg, 0xff);
host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 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))
{
host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8);
host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_mov_imm(block, REG_W16, uop->imm_data);
@ -828,6 +1023,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
[UOP_SAR & UOP_MASK] = codegen_SAR,
[UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM,
[UOP_SHL & UOP_MASK] = codegen_SHL,
[UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM,
[UOP_SHR & UOP_MASK] = codegen_SHR,
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
};

View file

@ -18,6 +18,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
}
#define Rm(x) (x)
#define Rs(x) ((x) << 8)
#define Rd(x) ((x) << 12)
#define Rn(x) ((x) << 16)
@ -94,9 +95,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define SHIFT_TYPE_REG (1 << 4)
#define SHIFT_IMM_SHIFT 7
#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_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 BFI_lsb(lsb) ((lsb) << 7)
#define BFI_msb(msb) ((msb) << 16)
@ -427,14 +433,30 @@ void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm)
}
}
void host_arm_MOV_REG_ASR(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_ASR_IMM(shift));
}
void host_arm_MOV_REG_ASR_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_ASR_REG(shift_reg));
}
void host_arm_MOV_REG_LSL(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_LSL_IMM(shift));
}
void host_arm_MOV_REG_LSL_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_LSL_REG(shift_reg));
}
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_MOV_REG_LSR_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_LSR_REG(shift_reg));
}
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm)
{

View file

@ -46,8 +46,12 @@ void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0)
void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
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_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);

View file

@ -635,10 +635,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop)
{
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)
else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
{
host_arm_UXTH(block, REG_TEMP, src_reg_b, 0);
host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0);
host_arm_ORR_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) && dest_reg == src_reg_a)
{
@ -692,6 +692,201 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
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);
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_ASR_REG(block, dest_reg, src_reg, shift_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16);
host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16);
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24);
host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24);
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_LSL(block, REG_TEMP, src_reg, 16);
host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SAR_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))
{
host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16);
host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16);
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24);
host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24);
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_LSL(block, REG_TEMP, src_reg, 16);
host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL(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_LSL_REG(block, dest_reg, src_reg, shift_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg);
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg);
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_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL_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))
{
host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm_MOV_REG_LSL(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_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data);
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8);
}
else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size))
{
host_arm_UXTB(block, REG_TEMP, src_reg, 8);
host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR(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_LSR_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_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
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_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
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_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR_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))
{
host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
host_arm_UXTH(block, REG_TEMP, src_reg, 0);
host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 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_UXTB(block, REG_TEMP, src_reg, 0);
host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8);
}
else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size))
{
host_arm_UXTB(block, REG_TEMP, src_reg, 8);
host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data);
host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8);
}
else
fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_MOV_IMM(block, REG_R0, uop->imm_data);
@ -911,6 +1106,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
[UOP_SAR & UOP_MASK] = codegen_SAR,
[UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM,
[UOP_SHL & UOP_MASK] = codegen_SHL,
[UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM,
[UOP_SHR & UOP_MASK] = codegen_SHR,
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
};

View file

@ -13,7 +13,9 @@
#define RM_OP_XOR 0x30
#define RM_OP_CMP 0x38
#define RM_OP_SHL 0x20
#define RM_OP_SHR 0x28
#define RM_OP_SAR 0x38
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
@ -811,10 +813,117 @@ void host_x86_RET(codeblock_t *block)
codegen_addbyte(block, 0xc3); /*RET*/
}
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SAR8 CL & 8\n");
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SAR16 CL & 8\n");
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SAR32 CL & 8\n");
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SAR8 imm & 8\n");
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SAR16 imm & 8\n");
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SAR32 imm & 8\n");
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHL8 CL & 8\n");
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHL16 CL & 8\n");
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHL32 CL & 8\n");
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHL8 imm & 8\n");
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHL16 imm & 8\n");
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHL32 imm & 8\n");
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHR8 CL & 8\n");
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHR16 CL & 8\n");
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg)
{
if (dst_reg & 8)
fatal("SHR32 CL & 8\n");
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHR8 imm & 8\n");
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
}
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHR16 imm & 8\n");
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
}
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift)
{
if (dst_reg & 8)
fatal("SHR32_IMM reg & 8\n");
fatal("SHR32 imm & 8\n");
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
}

View file

@ -89,6 +89,28 @@ void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);

View file

@ -473,11 +473,15 @@ static int codegen_OR(codeblock_t *block, uop_t *uop)
if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b))
{
host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b);
if (dest_reg != src_reg_a)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a);
host_x86_OR32_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))
{
host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b);
if (dest_reg != src_reg_a)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a);
host_x86_OR16_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))
{
@ -511,6 +515,178 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
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);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SAR32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SAR16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SAR8_CL(block, dest_reg);
}
else
fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SAR_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SAR32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SAR16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SAR8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL(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);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHL32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHL16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHL8_CL(block, dest_reg);
}
else
fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHL32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHL16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHL8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR(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);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHR32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHR16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHR8_CL(block, dest_reg);
}
else
fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHR32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHR16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHR8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
if (((uintptr_t)uop->p) >> 32)
@ -668,6 +844,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
[UOP_SAR & UOP_MASK] = codegen_SAR,
[UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM,
[UOP_SHL & UOP_MASK] = codegen_SHL,
[UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM,
[UOP_SHR & UOP_MASK] = codegen_SHR,
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
};

View file

@ -13,7 +13,9 @@
#define RM_OP_XOR 0x30
#define RM_OP_CMP 0x38
#define RM_OP_SHL 0x20
#define RM_OP_SHR 0x28
#define RM_OP_SAR 0x38
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
@ -707,6 +709,79 @@ void host_x86_RET(codeblock_t *block)
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/
}
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/
}
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/
}
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/
}
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg)
{
codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/
}
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
}
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
}
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/

View file

@ -89,6 +89,28 @@ void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);

View file

@ -470,11 +470,15 @@ static int codegen_OR(codeblock_t *block, uop_t *uop)
if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b))
{
host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_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_OR32_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))
{
host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b);
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a);
host_x86_OR16_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))
{
@ -508,6 +512,178 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
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);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SAR32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SAR16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SAR8_CL(block, dest_reg);
}
else
fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SAR_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SAR32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SAR16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SAR8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL(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);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHL32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHL16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHL8_CL(block, dest_reg);
}
else
fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHL_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHL32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHL16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHL8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR(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);
host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHR32_CL(block, dest_reg);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHR16_CL(block, dest_reg);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHR8_CL(block, dest_reg);
}
else
fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_SHR_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->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, dest_reg, src_reg);
host_x86_SHR32_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_W(dest_size) && REG_IS_W(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV16_REG_REG(block, dest_reg, src_reg);
host_x86_SHR16_IMM(block, dest_reg, uop->imm_data);
}
else if (REG_IS_B(dest_size) && REG_IS_B(src_size))
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV8_REG_REG(block, dest_reg, src_reg);
host_x86_SHR8_IMM(block, dest_reg, uop->imm_data);
}
else
fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data);
@ -660,7 +836,14 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
[UOP_SAR & UOP_MASK] = codegen_SAR,
[UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM,
[UOP_SHL & UOP_MASK] = codegen_SHL,
[UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM,
[UOP_SHR & UOP_MASK] = codegen_SHR,
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
};

View file

@ -89,7 +89,20 @@
/*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER)
#define UOP_MAX 0x49
/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50)
/*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51)
/*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/
#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52)
/*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/
#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53)
/*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54)
/*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55)
#define UOP_MAX 0x56
#define UOP_MASK 0xffff
@ -287,6 +300,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg)
#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg)
#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg)
#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm)
#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)

View file

@ -7,6 +7,7 @@
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
#include "codegen_ops_mov.h"
#include "codegen_ops_shift.h"
#include "codegen_ops_stack.h"
RecompOpFn recomp_opcodes[512] =
@ -28,8 +29,8 @@ RecompOpFn recomp_opcodes[512] =
/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, 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, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, 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,
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16,
@ -50,8 +51,8 @@ RecompOpFn recomp_opcodes[512] =
/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,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_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, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, 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,
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32
};
@ -73,7 +74,7 @@ RecompOpFn recomp_opcodes_0f[512] =
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@ -95,7 +96,7 @@ RecompOpFn recomp_opcodes_0f[512] =
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

809
src/codegen_ops_shift.c Normal file
View file

@ -0,0 +1,809 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_shift.h"
static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
default:
return 0;
}
}
else
{
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
case 0x28: /*SHR*/
uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
case 0x38: /*SAR*/
uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
default:
return 0;
}
}
else
{
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
case 0x28: /*SHR*/
uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
case 0x38: /*SAR*/
uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
default:
return 0;
}
}
else
{
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
case 0x28: /*SHR*/
uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
case 0x38: /*SAR*/
uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV_IMM(ir, IREG_flags_op2, count);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint8_t imm;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (imm)
return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1;
return op_pc+1;
}
uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint8_t imm;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (imm)
return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1;
return op_pc+1;
}
uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint8_t imm;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (imm)
return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1;
return op_pc+1;
}
uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
}
return shift_common_8(ir, fetchdat, op_pc, target_seg, 1);
}
uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
}
return shift_common_16(ir, fetchdat, op_pc, target_seg, 1);
}
uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
}
return shift_common_32(ir, fetchdat, op_pc, target_seg, 1);
}
uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if (!(CL & 0x1f) || !block->ins)
return 0;
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg));
uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
break;
default:
return 0;
}
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
case 0x28: /*SHR*/
uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
case 0x38: /*SAR*/
uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if (!(CL & 0x1f) || !block->ins)
return 0;
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
break;
default:
return 0;
}
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
case 0x28: /*SHR*/
uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
case 0x38: /*SAR*/
uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
return 0;
if (!(CL & 0x1f) || !block->ins)
return 0;
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x28: /*SHR*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x38: /*SAR*/
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
default:
return 0;
}
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
switch (fetchdat & 0x38)
{
case 0x20: case 0x30: /*SHL*/
uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
case 0x28: /*SHR*/
uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
case 0x38: /*SAR*/
uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
uop_MOV(ir, IREG_flags_op2, IREG_temp2);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
break;
default:
return 0;
}
}
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg = (fetchdat >> 3) & 7;
uint8_t imm;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (!imm)
return op_pc+2;
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm);
uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm);
uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm);
uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm);
uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
}
return op_pc+2;
}
uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg = (fetchdat >> 3) & 7;
uint8_t imm;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (!imm)
return op_pc+2;
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm);
uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm);
uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr);
uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm);
uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm);
uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_op1, IREG_temp2);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
}
return op_pc+2;
}
uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg = (fetchdat >> 3) & 7;
uint8_t imm;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (!imm)
return op_pc+2;
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg));
uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm);
uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm);
uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm);
uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm);
uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
}
return op_pc+2;
}
uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg = (fetchdat >> 3) & 7;
uint8_t imm;
if ((fetchdat & 0xc0) != 0xc0)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
}
imm = fastreadb(cs + op_pc + 1) & 0x1f;
if (!imm)
return op_pc+2;
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm);
uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm);
uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr);
uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm);
uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm);
uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_op1, IREG_temp2);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
}
return op_pc+2;
}

16
src/codegen_ops_shift.h Normal file
View file

@ -0,0 +1,16 @@
uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -93,6 +93,7 @@ enum
IREG_temp0_W = IREG_temp0 + IREG_SIZE_W,
IREG_temp1_W = IREG_temp1 + IREG_SIZE_W,
IREG_temp2_W = IREG_temp2 + IREG_SIZE_W,
IREG_temp0_B = IREG_temp0 + IREG_SIZE_B,
IREG_temp1_B = IREG_temp1 + IREG_SIZE_B,