Implemented basic register allocation.

Mainly handles 'virtual' registers at the moment (eg current and last PC values, segment override status, etc).
This commit is contained in:
SarahW 2018-06-23 19:04:36 +01:00
commit ee3f9210dc
23 changed files with 776 additions and 76 deletions

View file

@ -115,18 +115,95 @@ 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_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
{
codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
codegen_addlong(block, (uint32_t)p);
codegen_addlong(block, imm_data);
}
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
{
codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/
codegen_addlong(block, (uint32_t)p);
codegen_addbyte(block, 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_addbyte(block, imm_data);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p);
codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/
codegen_addlong(block, (uint32_t)(uintptr_t)p);
codegen_addbyte(block, imm_data);
}
}
static void host_x86_MOV32_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, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/
codegen_addlong(block, imm_data);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p);
codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
codegen_addlong(block, (uint32_t)(uintptr_t)p);
codegen_addlong(block, imm_data);
}
}
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 (offset >= -128 && offset < 127)
{
codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], 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_addlong(block, (uint32_t)(uintptr_t)p);
}
}
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 (offset >= -128 && offset < 127)
{
codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], 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_addlong(block, (uint32_t)(uintptr_t)p);
}
}
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 (offset >= -128 && offset < 127)
{
codegen_addbyte4(block, 0x48, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], 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_addlong(block, (uint32_t)(uintptr_t)p);
}
}
static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data)
{
@ -136,6 +213,15 @@ static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_dat
codegen_addlong(block, imm_data);
}
static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data)
{
if (reg & 8)
fatal("host_x86_MOV64_REG_IMM reg & 8\n");
codegen_addbyte2(block, 0x48, 0xb8 | reg); /*MOVQ reg, imm_data*/
codegen_addquad(block, imm_data);
}
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
{
if (!offset)
@ -201,6 +287,17 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
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);
return 0;
}
static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
{
host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
if (((uintptr_t)uop->p) >> 32)
@ -226,7 +323,25 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM,
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM
};
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOV8_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOV32_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOV64_ABS_REG(block, p, host_reg);
}
#endif