Add recompiled versions of mem->reg, reg->mem and imm->mem versions of MOV.

This commit is contained in:
SarahW 2018-07-25 20:16:58 +01:00
commit f27b7f757a
30 changed files with 5225 additions and 2160 deletions

View file

@ -4,125 +4,9 @@
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_backend_arm_defs.h"
#include "codegen_backend_arm_ops.h"
#include "codegen_ir_defs.h"
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
{
*(uint32_t *)&block->data[block_pos] = val;
block_pos += 4;
if (block_pos >= BLOCK_MAX)
{
fatal("codegen_addlong over! %i\n", block_pos);
CPU_BLOCK_END();
}
}
#define Rm(x) (x)
#define Rd(x) ((x) << 12)
#define Rn(x) ((x) << 16)
#define DATA_OFFSET_UP (1 << 23)
#define DATA_OFFSET_DOWN (0 << 23)
#define COND_SHIFT 28
#define COND_NE (0x1 << COND_SHIFT)
#define COND_AL (0xe << COND_SHIFT)
#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_BIC_IMM (0x3c << OPCODE_SHIFT)
#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT)
#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT)
#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT)
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT)
#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT)
#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT)
#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT)
#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT)
#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT)
#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT)
#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT)
#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT)
#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT)
#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT)
#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT)
#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT)
#define OPCODE_BFI 0xe7c00010
#define OPCODE_BLX 0xe12fff30
#define OPCODE_UADD8 0xe6500f90
#define OPCODE_UADD16 0xe6500f10
#define OPCODE_USUB8 0xe6500ff0
#define OPCODE_USUB16 0xe6500f70
#define OPCODE_UXTB 0xe6ef0070
#define OPCODE_UXTH 0xe6ff0070
#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))
#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
#define BFI_lsb(lsb) ((lsb) << 7)
#define BFI_msb(msb) ((msb) << 16)
#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10)
#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4))
static int literal_offset = 0;
void codegen_reset_literal_pool(codeblock_t *block)
{
literal_offset = 0;
}
int add_literal(codeblock_t *block, uint32_t data)
{
int c;
if (literal_offset >= 4096)
fatal("add_literal - literal pool full\n");
/*Search for pre-existing value*/
for (c = 0; c < literal_offset; c += 4)
{
if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data)
return c;
}
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
literal_offset += 4;
return literal_offset - 4;
}
static inline uint32_t arm_data_offset(int offset)
{
if (offset < -0xffc || offset > 0xffc)
fatal("arm_data_offset out of range - %i\n", offset);
if (offset >= 0)
return offset | DATA_OFFSET_UP;
return (-offset) | DATA_OFFSET_DOWN;
}
static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm)
{
int shift = 0;
@ -163,261 +47,6 @@ 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_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SUB_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 ((int32_t)imm < 0 && imm != 0x80000000)
{
host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm);
}
else 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);
}
}
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 if (get_arm_imm(~imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_BIC_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_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));
}
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
}
void host_arm_BLX(codeblock_t *block, int addr_reg)
{
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
}
void host_arm_BNE(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)
fatal("host_arm_BNE - out of range %08x %i\n", offset, offset);
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
}
void host_arm_EOR_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_EOR_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_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
{
codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask);
}
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset)
{
codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
}
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))
{
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_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) | SHIFT_LSL_IMM(shift));
}
void host_arm_MOV_REG_LSR(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) | SHIFT_LSR_IMM(shift));
}
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm)
{
codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm));
}
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
}
void host_arm_ORR_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_ORR_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_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
}
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
{
codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask);
}
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
{
codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
}
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
{
codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
}
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if ((int32_t)imm < 0 && imm != 0x80000000)
{
host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm);
}
else if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_SUB_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_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
}
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2)
{
codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2));
}
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
}
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
}
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
}
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
}
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate)
{
codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
}
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate)
{
codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
}
void host_arm_call(codeblock_t *block, void *dst_addr)
{
int offset = add_literal(block, (uintptr_t)dst_addr);
@ -593,6 +222,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_CMP_IMM_JZ(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
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
host_arm_BEQ(block, uop->p);
return 0;
}
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
{
uint32_t arm_imm;
@ -646,6 +291,190 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data);
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
{
host_arm_BL(block, codegen_mem_load_byte);
}
else if (REG_IS_W(dest_size))
{
host_arm_BL(block, codegen_mem_load_word);
}
else if (REG_IS_L(dest_size))
{
host_arm_BL(block, codegen_mem_load_long);
}
else
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
if (REG_IS_B(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 0, 8);
}
else if (REG_IS_BH(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 8, 8);
}
else if (REG_IS_W(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 0, 16);
}
else if (REG_IS_L(dest_size))
{
host_arm_MOV_REG(block, dest_reg, REG_R0);
}
return 0;
}
static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
{
host_arm_BL(block, codegen_mem_load_byte);
}
else if (REG_IS_W(dest_size))
{
host_arm_BL(block, codegen_mem_load_word);
}
else if (REG_IS_L(dest_size))
{
host_arm_BL(block, codegen_mem_load_long);
}
else
fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
if (REG_IS_B(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 0, 8);
}
else if (REG_IS_BH(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 8, 8);
}
else if (REG_IS_W(dest_size))
{
host_arm_BFI(block, dest_reg, REG_R0, 0, 16);
}
else if (REG_IS_L(dest_size))
{
host_arm_MOV_REG(block, dest_reg, REG_R0);
}
return 0;
}
static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real);
int src_size = IREG_GET_SIZE(uop->src_reg_b_real);
host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data);
if (REG_IS_B(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_byte);
}
else if (REG_IS_W(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_word);
}
else if (REG_IS_L(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_long);
}
else
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
return 0;
}
static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
if (REG_IS_B(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_byte);
}
else if (REG_IS_BH(src_size))
{
host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8);
host_arm_BL(block, codegen_mem_store_byte);
}
else if (REG_IS_W(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_word);
}
else if (REG_IS_L(src_size))
{
host_arm_MOV_REG(block, REG_R1, src_reg);
host_arm_BL(block, codegen_mem_store_long);
}
else
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
return 0;
}
static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
host_arm_BL(block, codegen_mem_store_byte);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
return 0;
}
static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
host_arm_BL(block, codegen_mem_store_word);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
return 0;
}
static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
host_arm_BL(block, codegen_mem_store_long);
host_arm_TST_REG(block, REG_R1, REG_R1);
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
return 0;
}
static int codegen_MOV(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
@ -1015,11 +844,20 @@ 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_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
[UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS,
[UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG,
[UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8,
[UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16,
[UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32,
[UOP_MOV & UOP_MASK] = codegen_MOV,
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
[UOP_ADD & UOP_MASK] = codegen_ADD,
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
@ -1030,7 +868,9 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_SUB & UOP_MASK] = codegen_SUB,
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
};
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)