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

@ -30,6 +30,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_SHIFT 20
#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT)
#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT)
#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT)
#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT)
#define OPCODE_B (0xa0 << OPCODE_SHIFT)
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
@ -45,6 +48,18 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define B_OFFSET(x) (((x) >> 2) & 0xffffff)
#define SHIFT_TYPE_SHIFT 5
#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT)
#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT)
#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT)
#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT)
#define SHIFT_TYPE_IMM (0 << 4)
#define SHIFT_TYPE_REG (1 << 4)
#define SHIFT_IMM_SHIFT 7
#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
static int literal_offset = 0;
void codegen_reset_literal_pool(codeblock_t *block)
{
@ -114,14 +129,49 @@ static inline int in_range(void *addr, void *base)
return 1;
}
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
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_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if (!get_arm_imm(imm, &arm_imm))
fatal("host_arm_ADD_IMM !check_arm_imm %08x\n", imm);
if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_BLX(codeblock_t *block, int addr_reg)
@ -153,15 +203,20 @@ void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm)
{
uint32_t arm_imm;
if (!get_arm_imm(imm, &arm_imm))
fatal("host_arm_MOV_IMM !check_arm_imm %08x\n", imm);
codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm);
if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
host_arm_LDR_IMM(block, dst_reg, REG_LITERAL, offset);
}
}
void host_arm_MOV_REG(codeblock_t *block, int dst_reg, int src_reg)
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg));
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
}
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
@ -204,7 +259,31 @@ void host_arm_call(codeblock_t *block, void *dst_addr)
void host_arm_nop(codeblock_t *block)
{
host_arm_MOV_REG(block, REG_R0, REG_R0);
host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0);
}
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
host_arm_ADD_REG_LSL(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_arm_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_arm_ADD_REG_LSL(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_arm_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)
@ -269,6 +348,13 @@ 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_arm_MOV_REG_LSL(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)
{
uint32_t arm_imm;
@ -332,10 +418,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_range(p, &cpu_state))
host_arm_LDR_IMM(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_range(p, &cpu_state))