Implemented effective address compilation.

This commit is contained in:
SarahW 2018-06-28 22:06:42 +01:00
commit 94fea237b4
13 changed files with 978 additions and 133 deletions

View file

@ -8,7 +8,7 @@
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
{
*(uint32_t *)&block->data[block_pos] = val;
*(uint32_t *)&block->data[block_pos] = val;
block_pos += 4;
if (block_pos >= BLOCK_MAX)
{
@ -21,6 +21,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define Rd(x) (x)
#define Rn(x) ((x) << 5)
#define Rt2(x) ((x) << 10)
#define Rm(x) ((x) << 16)
#define shift_imm6(x) ((x) << 10)
#define DATA_OFFSET_UP (1 << 23)
#define DATA_OFFSET_DOWN (0 << 23)
@ -30,6 +33,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define COND_AL (0xe << COND_SHIFT)
#define OPCODE_SHIFT 24
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
#define OPCODE_AND_IMM (0x11 << OPCODE_SHIFT)
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT)
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
@ -37,20 +42,28 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_MOVK_W (0x0e5 << 23)
#define OPCODE_MOVZ_W (0x0a5 << 23)
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
#define OPCODE_STP_PREIDX_X (0x2a6 << 22)
#define OPCODE_STR_IMM_W (0x2e4 << 22)
#define OPCODE_STR_IMM_Q (0x3e4 << 22)
#define OPCODE_STRB_IMM (0x0e4 << 22)
#define OPCODE_ADD_LSL (0x058 << 21)
#define OPCODE_AND_LSL (0x050 << 21)
#define OPCODE_ORR_LSL (0x150 << 21)
#define OPCODE_BLR (0xd63f0000)
#define OPCODE_NOP (0xd503201f)
#define OPCODE_RET (0xd65f0000)
#define DATPROC_SHIFT(sh) (sh << 10)
#define DATPROC_IMM_SHIFT(sh) (sh << 22)
#define MOV_WIDE_HW(hw) (hw << 21)
#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15)
#define IMM16(imm_data) (imm_data << 5)
#define IMM12(imm_data) ((imm_data) << 10)
#define IMM16(imm_data) ((imm_data) << 5)
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
@ -112,7 +125,39 @@ static inline int imm_is_imm16(uint32_t imm_data)
return 1;
return 0;
}
static inline int imm_is_imm12(uint32_t imm_data)
{
if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff))
return 1;
return 0;
}
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if (!(imm_data & 0xff000000))
{
if (imm_data & 0xfff)
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
if (imm_data & 0xfff000)
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
}
else
{
host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff);
host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000);
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
}
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
host_arm64_mov_imm(block, REG_W16, imm_data);
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
void host_arm64_BLR(codeblock_t *block, int addr_reg)
{
@ -134,6 +179,13 @@ void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, in
codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
}
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
{
if (!in_range12_w(offset))
fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset);
codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
}
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
{
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
@ -153,6 +205,11 @@ void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offs
codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg));
}
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
{
int hw;
@ -237,6 +294,30 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data)
}
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_ADD_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)
{
host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data);
return 0;
}
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_AND_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)
{
host_arm64_call(block, uop->p);
@ -270,6 +351,12 @@ 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_arm64_MOV_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0);
return 0;
}
static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_mov_imm(block, uop->dest_reg_a_real, uop->imm_data);
@ -319,10 +406,24 @@ 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)
{
if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state))
host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
else
fatal("codegen_direct_read_32 - not in range\n");
}
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state))