Implemented effective address compilation.
This commit is contained in:
parent
ee3f9210dc
commit
94fea237b4
13 changed files with 978 additions and 133 deletions
|
|
@ -87,6 +87,13 @@ static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
|||
}
|
||||
}
|
||||
|
||||
static int is_imm8(uint32_t imm_data)
|
||||
{
|
||||
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void call(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
|
@ -104,6 +111,62 @@ static inline void call(codeblock_t *block, uintptr_t func)
|
|||
}
|
||||
}
|
||||
|
||||
static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
{
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
{
|
||||
codegen_addbyte3(block, 0x83, 0xe0 | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xe0 | (dst_reg & 7)); /*AND dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | (src_reg_b & 7)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_CALL(codeblock_t *block, void *p)
|
||||
{
|
||||
call(block, (uintptr_t)p);
|
||||
|
|
@ -115,13 +178,22 @@ static void host_x86_JNZ(codeblock_t *block, void *p)
|
|||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/
|
||||
(shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7));
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
else
|
||||
|
|
@ -139,7 +211,7 @@ static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_dat
|
|||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
|
|
@ -156,16 +228,19 @@ static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
|||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV8_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/
|
||||
codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
|
@ -173,16 +248,19 @@ static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
|||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV32_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
|
@ -190,26 +268,47 @@ static void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
|||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV64_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x04 | (src_reg << 3), 0x25); /*MOV [p], src_reg*/
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOV32_REG_ABS reg & 8\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("host_x86_MOV32_REG_ABS - out of range\n");
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV32_REG_IMM reg & 8\n");
|
||||
codegen_addbyte(block, 0xb8 | reg); /*MOV reg, imm_data*/
|
||||
codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
|
||||
|
|
@ -217,10 +316,17 @@ static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_dat
|
|||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV64_REG_IMM reg & 8\n");
|
||||
codegen_addbyte2(block, 0x48, 0xb8 | reg); /*MOVQ reg, imm_data*/
|
||||
codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/
|
||||
codegen_addquad(block, imm_data);
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV32_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||
{
|
||||
|
|
@ -244,9 +350,42 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_
|
|||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_TEST32_REG - bad reg\n");
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
|
||||
|
||||
static int codegen_ADD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
if (!uop->imm_data)
|
||||
host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
else if (uop->imm_data < 4)
|
||||
host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data);
|
||||
else
|
||||
fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||
|
|
@ -287,6 +426,11 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MOV(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data);
|
||||
|
|
@ -325,10 +469,21 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
|
||||
|
||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
|
||||
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM
|
||||
};
|
||||
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
|
||||
{
|
||||
host_x86_MOV32_REG_ABS(block, host_reg, p);
|
||||
}
|
||||
|
||||
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
|
||||
{
|
||||
host_x86_MOV8_ABS_REG(block, p, host_reg);
|
||||
|
|
|
|||
Loading…
Reference in a new issue