Added recompiled versions of Jcc, JCXZ, LOOP, LOOPE and LOOPNE.
This commit is contained in:
parent
872a2da788
commit
3332897886
18 changed files with 3234 additions and 21 deletions
|
|
@ -31,6 +31,19 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define COND_EQ (0x0)
|
||||
#define COND_NE (0x1)
|
||||
#define COND_CS (0x2)
|
||||
#define COND_CC (0x3)
|
||||
#define COND_MI (0x4)
|
||||
#define COND_PL (0x5)
|
||||
#define COND_VS (0x6)
|
||||
#define COND_VC (0x7)
|
||||
#define COND_HI (0x8)
|
||||
#define COND_LS (0x9)
|
||||
#define COND_GE (0xa)
|
||||
#define COND_LT (0xb)
|
||||
#define COND_GT (0xc)
|
||||
#define COND_LE (0xd)
|
||||
|
||||
|
||||
#define OPCODE_SHIFT 24
|
||||
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
|
||||
|
|
@ -72,6 +85,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_AND_LSL (0x050 << 21)
|
||||
#define OPCODE_AND_ROR (0x056 << 21)
|
||||
#define OPCODE_ANDS_LSL (0x350 << 21)
|
||||
#define OPCODE_CMP_LSL (0x358 << 21)
|
||||
#define OPCODE_EOR_LSL (0x250 << 21)
|
||||
#define OPCODE_ORR_ASR (0x154 << 21)
|
||||
#define OPCODE_ORR_LSL (0x150 << 21)
|
||||
|
|
@ -83,6 +97,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define OPCODE_ASR (0x1ac02800)
|
||||
#define OPCODE_BLR (0xd63f0000)
|
||||
#define OPCODE_BR (0xd61f0000)
|
||||
#define OPCODE_LDR_REG (0xb8606800)
|
||||
#define OPCODE_LDRB_REG (0x38606800)
|
||||
#define OPCODE_LDRH_REG (0x78606800)
|
||||
|
|
@ -290,15 +305,75 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg)
|
|||
codegen_addlong(block, OPCODE_BLR | Rn(addr_reg));
|
||||
}
|
||||
|
||||
uint32_t *host_arm64_BCC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CC);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BCS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_EQ);
|
||||
return &block->data[block_pos-4];
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BGE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GE);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BGT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GT);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BHI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_HI);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LE);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LT);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BMI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_MI);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BNE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_NE);
|
||||
return &block->data[block_pos-4];
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BPL_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_PL);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BVC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VC);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BVS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
|
||||
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest)
|
||||
|
|
@ -307,6 +382,11 @@ void host_arm64_branch_set_offset(uint32_t *opcode, void *dest)
|
|||
*opcode |= OFFSET19(offset);
|
||||
}
|
||||
|
||||
void host_arm64_BR(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BR | Rn(addr_reg));
|
||||
}
|
||||
|
||||
void host_arm64_BEQ(codeblock_t *block, void *dest)
|
||||
{
|
||||
uint32_t *opcode = host_arm64_BEQ_(block);
|
||||
|
|
@ -375,6 +455,11 @@ void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data)
|
|||
fatal("CMPX_IMM %08x\n", imm_data);
|
||||
}
|
||||
|
||||
void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
|
|
@ -649,6 +734,13 @@ void host_arm64_call(codeblock_t *block, void *dst_addr)
|
|||
host_arm64_BLR(block, REG_X16);
|
||||
}
|
||||
|
||||
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr)
|
||||
{
|
||||
int offset = add_literal_q(block, (uintptr_t)dst_addr);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X16, offset);
|
||||
host_arm64_BR(block, REG_X16);
|
||||
}
|
||||
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_is_imm16(imm_data))
|
||||
|
|
|
|||
|
|
@ -17,11 +17,25 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
|||
|
||||
void host_arm64_BEQ(codeblock_t *block, void *dest);
|
||||
|
||||
uint32_t *host_arm64_BCC_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BCS_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BEQ_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BGE_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BGT_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BHI_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BLE_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BLS_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BLT_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BMI_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BNE_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BPL_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BVC_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BVS_(codeblock_t *block);
|
||||
|
||||
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest);
|
||||
|
||||
void host_arm64_BR(codeblock_t *block, int addr_reg);
|
||||
|
||||
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||
|
||||
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||
|
|
@ -30,6 +44,8 @@ void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
|||
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
||||
|
||||
#define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0)
|
||||
void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift);
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
|
||||
|
|
@ -88,6 +104,7 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int
|
|||
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||
|
||||
void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr);
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "codegen_backend_arm64_ops.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
|
||||
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||
|
||||
#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f)
|
||||
|
||||
#define REG_IS_L(size) (size == IREG_SIZE_L)
|
||||
|
|
@ -193,6 +195,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (!REG_IS_L(dest_size))
|
||||
fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real);
|
||||
host_arm64_call(block, uop->p);
|
||||
host_arm64_MOV_REG(block, dest_reg, REG_W0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm64_call(block, uop->p);
|
||||
|
|
@ -217,6 +232,369 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff);
|
||||
host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff);
|
||||
host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BCS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BHI_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BGE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BGT_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BVC_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BCC_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BLS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BLT_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BLE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BVS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm64_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_JMP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm64_jump(block, (uintptr_t)uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_ARG0, uop->imm_data);
|
||||
|
|
@ -918,6 +1296,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 31);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 15);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 7);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 31);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 15);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm64_TST_IMM(block, src_reg, 1 << 7);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm64_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_XOR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -986,7 +1413,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
|
|||
|
||||
const uOpFn uop_handlers[UOP_MAX] =
|
||||
{
|
||||
[UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT,
|
||||
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||
|
||||
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
||||
|
||||
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
||||
|
||||
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||
|
|
@ -1030,7 +1461,26 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SHR & UOP_MASK] = codegen_SHR,
|
||||
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ,
|
||||
|
||||
[UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST,
|
||||
[UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST,
|
||||
[UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST,
|
||||
[UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST,
|
||||
[UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST,
|
||||
[UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST,
|
||||
[UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST,
|
||||
[UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST,
|
||||
[UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST,
|
||||
[UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST,
|
||||
[UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST,
|
||||
[UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST,
|
||||
|
||||
[UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST,
|
||||
[UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST,
|
||||
|
||||
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
|
||||
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
|
||||
};
|
||||
|
||||
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
@ -1108,4 +1558,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos
|
|||
fatal("codegen_direct_write_32_stack - not in range\n");
|
||||
}
|
||||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)&block->data[block_pos] - (uintptr_t)p;
|
||||
|
||||
*(uint32_t *)p |= OFFSET19(offset);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define COND_SHIFT 28
|
||||
#define COND_EQ (0x0 << COND_SHIFT)
|
||||
#define COND_NE (0x1 << COND_SHIFT)
|
||||
#define COND_CS (0x2 << COND_SHIFT)
|
||||
#define COND_CC (0x3 << COND_SHIFT)
|
||||
#define COND_MI (0x4 << COND_SHIFT)
|
||||
#define COND_PL (0x5 << COND_SHIFT)
|
||||
#define COND_VS (0x6 << COND_SHIFT)
|
||||
#define COND_VC (0x7 << COND_SHIFT)
|
||||
#define COND_HI (0x8 << COND_SHIFT)
|
||||
#define COND_LS (0x9 << COND_SHIFT)
|
||||
#define COND_GE (0xa << COND_SHIFT)
|
||||
#define COND_LT (0xb << COND_SHIFT)
|
||||
#define COND_GT (0xc << COND_SHIFT)
|
||||
#define COND_LE (0xd << COND_SHIFT)
|
||||
#define COND_AL (0xe << COND_SHIFT)
|
||||
|
||||
#define OPCODE_SHIFT 20
|
||||
|
|
@ -72,6 +84,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define OPCODE_BFI 0xe7c00010
|
||||
#define OPCODE_BLX 0xe12fff30
|
||||
#define OPCODE_BX 0xe12fff10
|
||||
#define OPCODE_LDRH_IMM 0xe1d000b0
|
||||
#define OPCODE_LDRH_REG 0xe19000b0
|
||||
#define OPCODE_STRH_IMM 0xe1c000b0
|
||||
|
|
@ -227,6 +240,19 @@ void host_arm_AND_REG_LSR(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_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_B(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
{
|
||||
host_arm_MOV_IMM(block, REG_R3, dest_addr);
|
||||
host_arm_BX(block, REG_R3);
|
||||
}
|
||||
else
|
||||
codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset));
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -276,18 +302,90 @@ void host_arm_BLX(codeblock_t *block, int addr_reg)
|
|||
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
|
||||
}
|
||||
|
||||
uint32_t *host_arm_BCC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_CC | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BCS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_CS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_EQ | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BGE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_GE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BGT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_GT | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BHI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_HI | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LT | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BMI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_MI | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BNE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_NE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BPL_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_PL | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BVC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_VC | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BVS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_VS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
|
||||
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
|
|
@ -308,6 +406,11 @@ void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
|
|||
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
|
||||
}
|
||||
|
||||
void host_arm_BX(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
|
||||
}
|
||||
|
||||
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm
|
|||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_B(codeblock_t *block, uintptr_t dest_addr);
|
||||
|
||||
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||
|
||||
void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
|
|
@ -15,15 +17,32 @@ void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr
|
|||
|
||||
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr);
|
||||
void host_arm_BLX(codeblock_t *block, int addr_reg);
|
||||
|
||||
uint32_t *host_arm_BCC_(codeblock_t *block);
|
||||
uint32_t *host_arm_BCS_(codeblock_t *block);
|
||||
uint32_t *host_arm_BEQ_(codeblock_t *block);
|
||||
uint32_t *host_arm_BGE_(codeblock_t *block);
|
||||
uint32_t *host_arm_BGT_(codeblock_t *block);
|
||||
uint32_t *host_arm_BHI_(codeblock_t *block);
|
||||
uint32_t *host_arm_BLE_(codeblock_t *block);
|
||||
uint32_t *host_arm_BLS_(codeblock_t *block);
|
||||
uint32_t *host_arm_BLT_(codeblock_t *block);
|
||||
uint32_t *host_arm_BMI_(codeblock_t *block);
|
||||
uint32_t *host_arm_BNE_(codeblock_t *block);
|
||||
uint32_t *host_arm_BPL_(codeblock_t *block);
|
||||
uint32_t *host_arm_BVC_(codeblock_t *block);
|
||||
uint32_t *host_arm_BVS_(codeblock_t *block);
|
||||
|
||||
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr);
|
||||
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr);
|
||||
|
||||
void host_arm_BX(codeblock_t *block, int addr_reg);
|
||||
|
||||
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||
#define host_arm_CMP_REG(block, src_reg_n, src_reg_m) host_arm_CMP_REG_LSL(block, src_reg_n, src_reg_m, 0)
|
||||
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
|
|
|
|||
|
|
@ -268,6 +268,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (!REG_IS_L(dest_size))
|
||||
fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real);
|
||||
host_arm_call(block, uop->p);
|
||||
host_arm_MOV_REG(block, dest_reg, REG_R0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm_call(block, uop->p);
|
||||
|
|
@ -293,6 +306,369 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_UXTH(block, REG_TEMP, src_reg, 0);
|
||||
host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_UXTH(block, REG_TEMP, src_reg, 0);
|
||||
host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BCS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BHI_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BGE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BGT_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BVC_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BCC_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BLS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BLT_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BLE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BVS_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_arm_CMP_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24);
|
||||
host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_JMP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm_B(block, (uintptr_t)uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data);
|
||||
|
|
@ -1000,6 +1376,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 31);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 15);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 7);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BEQ_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 31);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 15);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm_TST_IMM(block, src_reg, 1 << 7);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_arm_BNE_(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_XOR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -1068,8 +1493,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
|
|||
|
||||
const uOpFn uop_handlers[UOP_MAX] =
|
||||
{
|
||||
[UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT,
|
||||
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||
|
||||
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
||||
|
||||
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
||||
|
||||
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||
|
|
@ -1113,7 +1541,26 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SHR & UOP_MASK] = codegen_SHR,
|
||||
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ,
|
||||
|
||||
[UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST,
|
||||
[UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST,
|
||||
[UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST,
|
||||
[UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST,
|
||||
[UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST,
|
||||
[UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST,
|
||||
[UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST,
|
||||
[UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST,
|
||||
[UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST,
|
||||
[UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST,
|
||||
[UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST,
|
||||
[UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST,
|
||||
|
||||
[UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST,
|
||||
[UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST,
|
||||
|
||||
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
|
||||
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
|
||||
};
|
||||
|
||||
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
@ -1190,4 +1637,8 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos
|
|||
fatal("codegen_direct_write_32 - not in range\n");
|
||||
}
|
||||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -117,6 +117,23 @@ static inline void call(codeblock_t *block, uintptr_t func)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void jmp(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
||||
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||
{
|
||||
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||
codegen_addlong(block, (uint32_t)diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/
|
||||
codegen_addquad(block, func);
|
||||
codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
|
|
@ -268,6 +285,21 @@ void host_x86_CALL(codeblock_t *block, void *p)
|
|||
call(block, (uintptr_t)p);
|
||||
}
|
||||
|
||||
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
|
|
@ -291,6 +323,24 @@ void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data)
|
|||
fatal("CMP64_REG_IMM not 8-bit imm\n");
|
||||
}
|
||||
|
||||
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p)
|
||||
{
|
||||
jmp(block, (uintptr_t)p);
|
||||
}
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
|
|
@ -313,6 +363,91 @@ uint8_t *host_x86_JZ_short(codeblock_t *block)
|
|||
return &block->data[block_pos-1];
|
||||
}
|
||||
|
||||
uint32_t *host_x86_JNB_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNBE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNL_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNLE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNO_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNS_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNZ_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JB_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x82); /*JB*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JBE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JL_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JLE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JO_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x80); /*JO*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JS_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x88); /*JS*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JZ_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||
{
|
||||
if (offset)
|
||||
|
|
@ -1007,6 +1142,14 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
|
|
|
|||
|
|
@ -17,15 +17,37 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
|
||||
void host_x86_CALL(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||
|
||||
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p);
|
||||
void host_x86_JZ(codeblock_t *block, void *p);
|
||||
|
||||
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||
|
||||
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNBE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNL_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNLE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNO_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNS_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNZ_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JB_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JBE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JL_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JLE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
|
||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||
|
|
@ -122,6 +144,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (!REG_IS_L(dest_size))
|
||||
fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_CALL(block, uop->p);
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_CALL(block, uop->p);
|
||||
|
|
@ -174,6 +187,343 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNB_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNBE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNL_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNLE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNO_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JB_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JBE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JL_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JLE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JO_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_JMP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_JMP(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
#if WIN64
|
||||
|
|
@ -759,6 +1109,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_TEST32_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_TEST16_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_TEST8_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNS_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_TEST32_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_TEST16_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_TEST8_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JS_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_XOR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -806,8 +1205,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
|
|||
|
||||
const uOpFn uop_handlers[UOP_MAX] =
|
||||
{
|
||||
[UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT,
|
||||
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||
|
||||
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
||||
|
||||
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
||||
|
||||
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||
|
|
@ -851,7 +1253,26 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SHR & UOP_MASK] = codegen_SHR,
|
||||
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ,
|
||||
|
||||
[UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST,
|
||||
[UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST,
|
||||
[UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST,
|
||||
[UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST,
|
||||
[UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST,
|
||||
[UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST,
|
||||
[UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST,
|
||||
[UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST,
|
||||
[UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST,
|
||||
[UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST,
|
||||
[UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST,
|
||||
[UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST,
|
||||
|
||||
[UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST,
|
||||
[UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST,
|
||||
|
||||
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
|
||||
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
|
||||
};
|
||||
|
||||
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
@ -895,4 +1316,9 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos
|
|||
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg);
|
||||
}
|
||||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -260,6 +260,21 @@ void host_x86_CALL(codeblock_t *block, void *p)
|
|||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
|
|
@ -276,6 +291,25 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
|||
}
|
||||
}
|
||||
|
||||
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
|
|
@ -298,6 +332,91 @@ uint8_t *host_x86_JZ_short(codeblock_t *block)
|
|||
return &block->data[block_pos-1];
|
||||
}
|
||||
|
||||
uint32_t *host_x86_JNB_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNBE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNL_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNLE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNO_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNS_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JNZ_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JB_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x82); /*JB*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JBE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JL_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JLE_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JO_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x80); /*JO*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JS_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x88); /*JS*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_x86_JZ_long(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/
|
||||
codegen_addlong(block, 0);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
}
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||
{
|
||||
if (offset)
|
||||
|
|
@ -856,6 +975,14 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
|
|
|
|||
|
|
@ -18,14 +18,36 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
|
||||
void host_x86_CALL(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p);
|
||||
void host_x86_JZ(codeblock_t *block, void *p);
|
||||
|
||||
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||
|
||||
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNBE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNL_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNLE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNO_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNS_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JNZ_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JB_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JBE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JL_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JLE_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
|
||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||
|
|
@ -121,7 +143,10 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
|
|
|||
|
|
@ -159,6 +159,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (!REG_IS_L(dest_size))
|
||||
fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_CALL(block, uop->p);
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_CALL(block, uop->p);
|
||||
|
|
@ -181,10 +194,347 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
|||
else
|
||||
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
|
||||
host_x86_JZ(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNB_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNBE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNL_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNLE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNO_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JB_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JBE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JL_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JLE_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JO_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int 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(src_size_a) && REG_IS_L(src_size_b))
|
||||
{
|
||||
host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b))
|
||||
{
|
||||
host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b))
|
||||
{
|
||||
host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JZ_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_JMP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_JMP(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data);
|
||||
|
|
@ -752,6 +1102,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_TEST32_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_TEST16_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_TEST8_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JNS_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_TEST32_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_TEST16_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_TEST8_REG(block, src_reg, src_reg);
|
||||
}
|
||||
else
|
||||
fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real);
|
||||
|
||||
uop->p = host_x86_JS_long(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_XOR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -799,8 +1198,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
|
|||
|
||||
const uOpFn uop_handlers[UOP_MAX] =
|
||||
{
|
||||
[UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT,
|
||||
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||
|
||||
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
||||
|
||||
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
||||
|
||||
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||
|
|
@ -844,7 +1246,26 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SHR & UOP_MASK] = codegen_SHR,
|
||||
[UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ,
|
||||
|
||||
[UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST,
|
||||
[UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST,
|
||||
[UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST,
|
||||
[UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST,
|
||||
[UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST,
|
||||
[UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST,
|
||||
[UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST,
|
||||
[UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST,
|
||||
[UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST,
|
||||
[UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST,
|
||||
[UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST,
|
||||
[UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST,
|
||||
|
||||
[UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST,
|
||||
[UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST,
|
||||
|
||||
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
|
||||
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
|
||||
};
|
||||
|
||||
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
@ -888,4 +1309,9 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos
|
|||
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg);
|
||||
}
|
||||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ ir_data_t *codegen_ir_init()
|
|||
|
||||
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
||||
{
|
||||
int jump_target_at_end = -1;
|
||||
int c;
|
||||
|
||||
codegen_backend_prologue(block);
|
||||
|
|
@ -26,12 +27,23 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
uop_t *uop = &ir->uops[c];
|
||||
|
||||
// pclog("uOP %i : %08x\n", c, uop->type);
|
||||
|
||||
|
||||
if (uop->type & UOP_TYPE_BARRIER)
|
||||
codegen_reg_flush_invalidate(ir, block);
|
||||
else if (uop->type & UOP_TYPE_ORDER_BARRIER)
|
||||
codegen_reg_flush(ir, block);
|
||||
|
||||
if (uop->type & UOP_TYPE_JUMP_DEST)
|
||||
{
|
||||
uop_t *uop_dest = uop;
|
||||
|
||||
while (uop_dest->jump_list_next != -1)
|
||||
{
|
||||
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||
codegen_set_jump_dest(block, uop_dest->p);
|
||||
}
|
||||
}
|
||||
|
||||
if (uop->type & UOP_TYPE_PARAMS_REGS)
|
||||
{
|
||||
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
|
||||
|
|
@ -56,10 +68,51 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
if (!uop_handlers[uop->type & UOP_MASK])
|
||||
fatal("!uop_handlers[uop->type & UOP_MASK]\n");
|
||||
uop_handlers[uop->type & UOP_MASK](block, uop);
|
||||
|
||||
if (uop->type & UOP_TYPE_JUMP)
|
||||
{
|
||||
if (uop->jump_dest_uop == ir->wr_pos)
|
||||
{
|
||||
if (jump_target_at_end == -1)
|
||||
jump_target_at_end = c;
|
||||
else
|
||||
{
|
||||
uop_t *uop_dest = &ir->uops[jump_target_at_end];
|
||||
|
||||
while (uop_dest->jump_list_next != -1)
|
||||
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||
|
||||
uop_dest->jump_list_next = c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_t *uop_dest = &ir->uops[uop->jump_dest_uop];
|
||||
|
||||
while (uop_dest->jump_list_next != -1)
|
||||
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||
|
||||
uop_dest->jump_list_next = c;
|
||||
ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codegen_reg_flush_invalidate(ir, block);
|
||||
|
||||
if (jump_target_at_end != -1)
|
||||
{
|
||||
uop_t *uop_dest = &ir->uops[jump_target_at_end];
|
||||
|
||||
while (1)
|
||||
{
|
||||
codegen_set_jump_dest(block, uop_dest->p);
|
||||
if (uop_dest->jump_list_next == -1)
|
||||
break;
|
||||
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||
}
|
||||
}
|
||||
|
||||
codegen_backend_epilogue(block);
|
||||
|
||||
// if (has_ea)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@
|
|||
/*uOP uses immediate data*/
|
||||
#define UOP_TYPE_PARAMS_IMM (1 << 30)
|
||||
|
||||
/*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must
|
||||
set jump_dest in the destination uOP to the address of the branch offset to be
|
||||
written when known.*/
|
||||
#define UOP_TYPE_JUMP (1 << 26)
|
||||
/*uOP is the destination of a jump, and must set the destination offset of the jump
|
||||
at compile time.*/
|
||||
#define UOP_TYPE_JUMP_DEST (1 << 25)
|
||||
|
||||
|
||||
#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00)
|
||||
|
|
@ -41,6 +48,10 @@
|
|||
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
|
||||
/*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/
|
||||
#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER)
|
||||
/*UOP_JMP - jump to ptr*/
|
||||
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
|
||||
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
|
||||
/*UOP_MOV_PTR - dest_reg = p*/
|
||||
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
|
||||
/*UOP_MOV_IMM - dest_reg = imm_data*/
|
||||
|
|
@ -86,7 +97,7 @@
|
|||
#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/
|
||||
#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/
|
||||
/*UOP_CMP_IMM_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)
|
||||
|
||||
/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/
|
||||
|
|
@ -102,7 +113,43 @@
|
|||
/*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
|
||||
/*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/
|
||||
#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/
|
||||
#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
|
||||
/*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/
|
||||
#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
|
||||
|
||||
/*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/
|
||||
#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/
|
||||
#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||
|
||||
#define UOP_MAX 0x72
|
||||
|
||||
#define UOP_MASK 0xffff
|
||||
|
||||
|
|
@ -117,6 +164,9 @@ typedef struct uop_t
|
|||
void *p;
|
||||
ir_host_reg_t dest_reg_a_real;
|
||||
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
|
||||
int jump_dest_uop;
|
||||
int jump_list_next;
|
||||
void *jump_dest;
|
||||
} uop_t;
|
||||
|
||||
#define UOP_NR_MAX 4096
|
||||
|
|
@ -141,15 +191,45 @@ static inline uop_t *uop_alloc(ir_data_t *ir)
|
|||
uop->src_reg_b = invalid_ir_reg;
|
||||
uop->src_reg_c = invalid_ir_reg;
|
||||
|
||||
uop->jump_list_next = -1;
|
||||
|
||||
return uop;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
|
||||
static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
|
||||
{
|
||||
uop_t *uop = &ir->uops[jump_uop];
|
||||
|
||||
uop->jump_dest_uop = ir->wr_pos;
|
||||
}
|
||||
|
||||
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||
|
||||
return ir->wr_pos-1;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||
}
|
||||
|
||||
static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg);
|
||||
uop->imm_data = imm;
|
||||
|
||||
return ir->wr_pos-1;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
|
||||
|
|
@ -220,6 +300,17 @@ static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int
|
|||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||
|
||||
return ir->wr_pos-1;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
|
@ -284,7 +375,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
|||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
|
||||
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1_arg(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
|
||||
|
||||
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
|
||||
|
||||
|
|
@ -307,11 +398,30 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
|||
#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)
|
||||
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
|
||||
#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p)
|
||||
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
|
||||
|
||||
#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm)
|
||||
|
||||
#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm)
|
||||
#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm)
|
||||
|
||||
#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b)
|
||||
#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b)
|
||||
|
||||
#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
|
||||
|
||||
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
|
||||
|
||||
#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm)
|
||||
|
|
@ -330,6 +440,9 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
|||
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
|
||||
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
|
||||
|
||||
#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg)
|
||||
#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg)
|
||||
|
||||
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p);
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
|
||||
|
||||
|
|
@ -343,4 +456,6 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of
|
|||
|
||||
void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg);
|
||||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_arith.h"
|
||||
#include "codegen_ops_branch.h"
|
||||
#include "codegen_ops_jump.h"
|
||||
#include "codegen_ops_logic.h"
|
||||
#include "codegen_ops_misc.h"
|
||||
|
|
@ -22,7 +23,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
|
||||
|
||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W,
|
||||
/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -31,7 +32,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*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,
|
||||
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, 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,
|
||||
|
||||
/*32-bit data*/
|
||||
|
|
@ -44,7 +45,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
|
||||
|
||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L,
|
||||
/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -53,7 +54,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*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,
|
||||
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, 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
|
||||
};
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16,
|
||||
/*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, 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,
|
||||
|
|
@ -94,7 +95,7 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32,
|
||||
/*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, 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,
|
||||
|
|
|
|||
662
src/codegen_ops_branch.c
Normal file
662
src/codegen_ops_branch.c
Normal file
|
|
@ -0,0 +1,662 @@
|
|||
#include "ibm.h"
|
||||
|
||||
#include "x86.h"
|
||||
#include "386_common.h"
|
||||
#include "x86_flags.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
#include "codegen_ops_mov.h"
|
||||
|
||||
static int NF_SET_01()
|
||||
{
|
||||
return NF_SET() ? 1 : 0;
|
||||
}
|
||||
static int VF_SET_01()
|
||||
{
|
||||
return VF_SET() ? 1 : 0;
|
||||
}
|
||||
|
||||
static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Overflow is always zero*/
|
||||
return;
|
||||
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Overflow is always zero*/
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
return;
|
||||
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Carry is always zero*/
|
||||
return;
|
||||
|
||||
case FLAGS_SUB8:
|
||||
jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB16:
|
||||
jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB32:
|
||||
jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Carry is always zero*/
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
return;
|
||||
|
||||
case FLAGS_SUB8:
|
||||
jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB16:
|
||||
jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB32:
|
||||
jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN))
|
||||
{
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0);
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN))
|
||||
{
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0);
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop, jump_uop2 = -1;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Carry is always zero, so test zero only*/
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB8:
|
||||
jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16:
|
||||
jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32:
|
||||
jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
if (jump_uop2 != -1)
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop, jump_uop2 = -1;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32:
|
||||
/*Carry is always zero, so test zero only*/
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB8:
|
||||
jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16:
|
||||
jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32:
|
||||
jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
if (jump_uop2 != -1)
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
}
|
||||
|
||||
static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_DEC8:
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_DEC16:
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC32:
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_DEC8:
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_DEC16:
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC32:
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET);
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
/*V flag is always clear. Condition is true if N is set*/
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B);
|
||||
break;
|
||||
case FLAGS_ZN16:
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W);
|
||||
break;
|
||||
case FLAGS_ZN32:
|
||||
jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01);
|
||||
jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
/*V flag is always clear. Condition is true if N is set*/
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B);
|
||||
break;
|
||||
case FLAGS_ZN16:
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W);
|
||||
break;
|
||||
case FLAGS_ZN32:
|
||||
jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res);
|
||||
break;
|
||||
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01);
|
||||
jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
|
||||
static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop, jump_uop2 = -1;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01);
|
||||
jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1);
|
||||
break;
|
||||
}
|
||||
if (jump_uop2 != -1)
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
}
|
||||
static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset)
|
||||
{
|
||||
int jump_uop, jump_uop2 = -1;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_SUB8: case FLAGS_DEC8:
|
||||
jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B);
|
||||
break;
|
||||
case FLAGS_SUB16: case FLAGS_DEC16:
|
||||
jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W);
|
||||
break;
|
||||
case FLAGS_SUB32: case FLAGS_DEC32:
|
||||
jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
default:
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01);
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01);
|
||||
jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1);
|
||||
break;
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, base_pc + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
if (jump_uop2 != -1)
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
}
|
||||
|
||||
#define ropJ(cond) \
|
||||
uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
{ \
|
||||
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \
|
||||
ropJ ## cond ## _common(block, ir, op_pc+1, offset); \
|
||||
\
|
||||
return op_pc+1; \
|
||||
} \
|
||||
uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
{ \
|
||||
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \
|
||||
ropJ ## cond ## _common(block, ir, op_pc+2, offset); \
|
||||
\
|
||||
return op_pc+2; \
|
||||
} \
|
||||
uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
{ \
|
||||
uint32_t offset = fastreadl(cs + op_pc); \
|
||||
ropJ ## cond ## _common(block, ir, op_pc+4, offset); \
|
||||
\
|
||||
return op_pc+4; \
|
||||
}
|
||||
|
||||
ropJ(O)
|
||||
ropJ(NO)
|
||||
ropJ(B)
|
||||
ropJ(NB)
|
||||
ropJ(E)
|
||||
ropJ(NE)
|
||||
ropJ(BE)
|
||||
ropJ(NBE)
|
||||
ropJ(S)
|
||||
ropJ(NS)
|
||||
ropJ(P)
|
||||
ropJ(NP)
|
||||
ropJ(L)
|
||||
ropJ(NL)
|
||||
ropJ(LE)
|
||||
ropJ(NLE)
|
||||
|
||||
|
||||
uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
|
||||
int jump_uop;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0);
|
||||
else
|
||||
jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0);
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
|
||||
return op_pc+1;
|
||||
}
|
||||
|
||||
uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
|
||||
int jump_uop;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0);
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
|
||||
return op_pc+1;
|
||||
}
|
||||
|
||||
uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
|
||||
int jump_uop, jump_uop2;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0);
|
||||
}
|
||||
if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN))
|
||||
{
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0);
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
|
||||
return op_pc+1;
|
||||
}
|
||||
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
|
||||
int jump_uop, jump_uop2;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1);
|
||||
jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0);
|
||||
}
|
||||
if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN))
|
||||
{
|
||||
uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET);
|
||||
jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0);
|
||||
}
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset);
|
||||
uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
|
||||
return op_pc+1;
|
||||
}
|
||||
69
src/codegen_ops_branch.h
Normal file
69
src/codegen_ops_branch.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
uint32_t ropJB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJNS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropJNS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
|
@ -88,9 +88,13 @@ enum
|
|||
IREG_BH = IREG_EBX + IREG_SIZE_BH,
|
||||
|
||||
IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W,
|
||||
|
||||
IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W,
|
||||
IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W,
|
||||
|
||||
IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B,
|
||||
|
||||
IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B,
|
||||
IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B,
|
||||
|
||||
IREG_temp0_W = IREG_temp0 + IREG_SIZE_W,
|
||||
IREG_temp1_W = IREG_temp1 + IREG_SIZE_W,
|
||||
IREG_temp2_W = IREG_temp2 + IREG_SIZE_W,
|
||||
|
|
|
|||
Loading…
Reference in a new issue