# HG changeset patch # User Mike Pavone # Date 1393220239 28800 # Node ID 1af6c105299376d01b1c2e57b1f454048356fe9b # Parent 0687b05061dd071a160e91879cbfd8720fa800a1 Added untested code for generating ARM machine code diff -r 0687b05061dd -r 1af6c1052993 Makefile --- a/Makefile Sun Feb 23 11:52:13 2014 -0800 +++ b/Makefile Sun Feb 23 21:37:19 2014 -0800 @@ -88,6 +88,9 @@ test_x86 : test_x86.o gen_x86.o $(CC) -o test_x86 test_x86.o gen_x86.o +test_arm : test_arm.o gen_arm.o mem.o + $(CC) -o test_arm test_arm.o gen_arm.o mem.o + gen_fib : gen_fib.o gen_x86.o mem.o $(CC) -o gen_fib gen_fib.o gen_x86.o mem.o diff -r 0687b05061dd -r 1af6c1052993 gen_arm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen_arm.c Sun Feb 23 21:37:19 2014 -0800 @@ -0,0 +1,565 @@ +/* + Copyright 2014 Michael Pavone + This file is part of BlastEm. + BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. +*/ +#include "gen_arm.h" +#include "mem.h" +#include +#include + +#define OP_FIELD_SHIFT 21u + +//Data processing format instructions +#define OP_AND 0x0u +#define OP_EOR (0x1u << OP_FIELD_SHIFT) +#define OP_SUB (0x2u << OP_FIELD_SHIFT) +#define OP_RSB (0x3u << OP_FIELD_SHIFT) +#define OP_ADD (0x4u << OP_FIELD_SHIFT) +#define OP_ADC (0x5u << OP_FIELD_SHIFT) +#define OP_SBC (0x6u << OP_FIELD_SHIFT) +#define OP_RSC (0x7u << OP_FIELD_SHIFT) +#define OP_TST (0x8u << OP_FIELD_SHIFT) +#define OP_TEQ (0x9u << OP_FIELD_SHIFT) +#define OP_CMP (0xAu << OP_FIELD_SHIFT) +#define OP_CMN (0xBu << OP_FIELD_SHIFT) +#define OP_ORR (0xCu << OP_FIELD_SHIFT) +#define OP_MOV (0xDu << OP_FIELD_SHIFT) +#define OP_BIC (0xEu << OP_FIELD_SHIFT) +#define OP_MVN (0xFu << OP_FIELD_SHIFT) + +//branch instructions +#define OP_B 0xA000000u +#define OP_BL 0xB000000u +#define OP_BX 0x12FFF10u + +//load/store +#define OP_STR 0x4000000u +#define OP_LDR 0x4100000u +#define OP_STM 0x8000000u +#define OP_LDM 0x8100000u +#define POST_IND 0u +#define PRE_IND 0x1000000u +#define DIR_DOWN 0u +#define DIR_UP 0x0800000u +#define SZ_W 0u +#define SZ_B 0x0400000u +#define WRITE_B 0x0200000u +#define OFF_IMM 0u +#define OFF_REG 0x2000000u + +#define PUSH (OP_STR | PRE_IND | OFF_IMM | SZ_W | WRITE_B | DIR_DOWN | sizeof(uint32_t) | (sp << 16)) +#define POP (OP_LDR | POST_IND | OFF_IMM | SZ_W | DIR_UP | sizeof(uint32_t) | (sp << 16)) +#define PUSHM (OP_STM | PRE_IND | SZ_W | WRITE_B | DIR_DOWN | (sp << 16)) +#define POPM (OP_LDM | POST_IND | SZ_W | DIR_UP | (sp << 16)) + +#define IMMED 0x2000000u +#define REG 0u + + + +#define RESERVE_INSTRUCTIONS 4 //1 ldr + 1bx + 1 constant +#define CODE_ALLOC_SIZE (1024*1024) + +uint32_t make_immed(uint32_t val) +{ + uint32_t rot_amount = 0; + for (; rot_amount < 0x20; rot_amount += 2) + { + uint32_t test_mask = ~(0xFF << rot_amount | 0xFF >> (32-rot_amount)); + if (!(test_mask & val)) { + return val << rot_amount | val >> (32-rot_amount) | rot_amount << 7; + } + } + return INVALID_IMMED; +} + +void init_code_info(code_info *code) +{ + size_t size = CODE_ALLOC_SIZE; + code->cur = alloc_code(&size); + if (!code->cur) { + fputs("Failed to allocate memory for generated code\n", stderr); + exit(1); + } + code->last = code->cur + size/sizeof(uint32_t) - RESERVE_INSTRUCTIONS; +} + +void check_alloc_code(code_info *code) +{ + if (code->cur = code->last) { + size_t size = CODE_ALLOC_SIZE; + uint32_t *next_code = alloc_code(&size); + if (!next_code) { + fputs("Failed to allocate memory for generated code\n", stderr); + exit(1); + } + if (next_code = code->last + RESERVE_INSTRUCTIONS) { + //new chunk is contiguous with the current one + code->last = next_code + size/sizeof(uint32_t) - RESERVE_INSTRUCTIONS; + } else { + uint32_t * from = code->cur + 2; + if (next_code - from < 0x400000 || from - next_code <= 0x400000) { + *from = CC_AL | OP_B | ((next_code - from) & 0xFFFFFF); + } else { + //push r0 onto the stack + *(from++) = CC_AL | PUSH; + uint32_t immed = make_immed((uint32_t)next_code); + if (immed == INVALID_IMMED) { + //Load target into r0 from word after next instruction into register 0 + *(from++) = CC_AL | OP_LDR | OFF_IMM | DIR_DOWN | PRE_IND | SZ_W | (pc << 16) | 4; + from[1] = (uint32_t)next_code; + } else { + //Load target into r0 + *(from++) = CC_AL | OP_MOV | IMMED | NO_COND | immed; + } + //branch to address in r0 + *from = CC_AL | OP_BX; + code->last = next_code + size/sizeof(uint32_t) - RESERVE_INSTRUCTIONS; + //pop r0 + *(next_code++) = CC_AL | POP; + code->cur = next_code; + } + } + } +} + +uint32_t data_proc(code_info *code, uint32_t cond, uint32_t op, uint32_t set_cond, uint32_t dst, uint32_t src1, uint32_t src2) +{ + check_alloc_code(code); + *(code->cur++) = cond | op | set_cond | (dst << 16) | (src1 << 12) | src2; + + return CODE_OK; +} + +uint32_t data_proci(code_info *code, uint32_t cond, uint32_t op, uint32_t set_cond, uint32_t dst, uint32_t src1, uint32_t immed) +{ + immed = make_immed(immed); + if (immed = INVALID_IMMED) { + return immed; + } + return data_proc(code, cond, op, set_cond, dst, src1, immed); +} + +//TODO: support shifted register for op2 + +uint32_t and(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_AND, set_cond, dst, src1, src2); +} + +uint32_t andi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_AND, set_cond, dst, src1, immed); +} + +uint32_t and_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_AND, set_cond, dst, src1, src2); +} + +uint32_t andi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_AND, set_cond, dst, src1, immed); +} + +uint32_t eor(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_EOR, set_cond, dst, src1, src2); +} + +uint32_t eori(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_EOR, set_cond, dst, src1, immed); +} + +uint32_t eor_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_EOR, set_cond, dst, src1, src2); +} + +uint32_t eori_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_EOR, set_cond, dst, src1, immed); +} + +uint32_t sub(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_SUB, set_cond, dst, src1, src2); +} + +uint32_t subi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_SUB, set_cond, dst, src1, immed); +} + +uint32_t sub_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_SUB, set_cond, dst, src1, src2); +} + +uint32_t subi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_SUB, set_cond, dst, src1, immed); +} + +uint32_t rsb(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_RSB, set_cond, dst, src1, src2); +} + +uint32_t rsbi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_RSB, set_cond, dst, src1, immed); +} + +uint32_t rsb_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_RSB, set_cond, dst, src1, src2); +} + +uint32_t rsbi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_RSB, set_cond, dst, src1, immed); +} + +uint32_t add(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_ADD, set_cond, dst, src1, src2); +} + +uint32_t addi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_ADD, set_cond, dst, src1, immed); +} + +uint32_t add_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_ADD, set_cond, dst, src1, src2); +} + +uint32_t addi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_ADD, set_cond, dst, src1, immed); +} + +uint32_t adc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_ADC, set_cond, dst, src1, src2); +} + +uint32_t adci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_ADC, set_cond, dst, src1, immed); +} + +uint32_t adc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_ADC, set_cond, dst, src1, src2); +} + +uint32_t adci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_ADC, set_cond, dst, src1, immed); +} + +uint32_t sbc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_SBC, set_cond, dst, src1, src2); +} + +uint32_t sbci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_SBC, set_cond, dst, src1, immed); +} + +uint32_t sbc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_SBC, set_cond, dst, src1, src2); +} + +uint32_t sbci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_SBC, set_cond, dst, src1, immed); +} + +uint32_t rsc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_RSC, set_cond, dst, src1, src2); +} + +uint32_t rsci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_RSC, set_cond, dst, src1, immed); +} + +uint32_t rsc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_RSC, set_cond, dst, src1, src2); +} + +uint32_t rsci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_RSC, set_cond, dst, src1, immed); +} + +uint32_t tst(code_info *code, uint32_t src1, uint32_t src2) +{ + return data_proc(code, CC_AL, OP_TST, SET_COND, r0, src1, src2); +} + +uint32_t tsti(code_info *code, uint32_t src1, uint32_t immed) +{ + return data_proci(code, CC_AL, OP_TST, SET_COND, r0, src1, immed); +} + +uint32_t tst_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc) +{ + return data_proc(code, cc, OP_TST, SET_COND, r0, src1, src2); +} + +uint32_t tsti_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc) +{ + return data_proci(code, cc, OP_TST, SET_COND, r0, src1, immed); +} + +uint32_t teq(code_info *code, uint32_t src1, uint32_t src2) +{ + return data_proc(code, CC_AL, OP_TEQ, SET_COND, r0, src1, src2); +} + +uint32_t teqi(code_info *code, uint32_t src1, uint32_t immed) +{ + return data_proci(code, CC_AL, OP_TEQ, SET_COND, r0, src1, immed); +} + +uint32_t teq_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc) +{ + return data_proc(code, cc, OP_TEQ, SET_COND, r0, src1, src2); +} + +uint32_t teqi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc) +{ + return data_proci(code, cc, OP_TEQ, SET_COND, r0, src1, immed); +} + +uint32_t cmp(code_info *code, uint32_t src1, uint32_t src2) +{ + return data_proc(code, CC_AL, OP_CMP, SET_COND, r0, src1, src2); +} + +uint32_t cmpi(code_info *code, uint32_t src1, uint32_t immed) +{ + return data_proci(code, CC_AL, OP_CMP, SET_COND, r0, src1, immed); +} + +uint32_t cmp_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc) +{ + return data_proc(code, cc, OP_CMP, SET_COND, r0, src1, src2); +} + +uint32_t cmpi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc) +{ + return data_proci(code, cc, OP_CMP, SET_COND, r0, src1, immed); +} + +uint32_t cmn(code_info *code, uint32_t src1, uint32_t src2) +{ + return data_proc(code, CC_AL, OP_CMN, SET_COND, r0, src1, src2); +} + +uint32_t cmni(code_info *code, uint32_t src1, uint32_t immed) +{ + return data_proci(code, CC_AL, OP_CMN, SET_COND, r0, src1, immed); +} + +uint32_t cmn_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc) +{ + return data_proc(code, cc, OP_CMN, SET_COND, r0, src1, src2); +} + +uint32_t cmni_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc) +{ + return data_proci(code, cc, OP_CMN, SET_COND, r0, src1, immed); +} + +uint32_t orr(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_ORR, set_cond, dst, src1, src2); +} + +uint32_t orri(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_ORR, set_cond, dst, src1, immed); +} + +uint32_t orr_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_ORR, set_cond, dst, src1, src2); +} + +uint32_t orri_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_ORR, set_cond, dst, src1, immed); +} + +uint32_t mov(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_MOV, set_cond, dst, 0, src2); +} + +uint32_t movi(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_MOV, set_cond, dst, 0, immed); +} + +uint32_t mov_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_MOV, set_cond, dst, 0, src2); +} + +uint32_t movi_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_MOV, set_cond, dst, 0, immed); +} + +uint32_t bic(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_BIC, set_cond, dst, src1, src2); +} + +uint32_t bici(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_BIC, set_cond, dst, src1, immed); +} + +uint32_t bic_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_BIC, set_cond, dst, src1, src2); +} + +uint32_t bici_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_BIC, set_cond, dst, src1, immed); +} + +uint32_t mvn(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond) +{ + return data_proc(code, CC_AL, OP_MVN, set_cond, dst, 0, src2); +} + +uint32_t mvni(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond) +{ + return data_proci(code, CC_AL, OP_MVN, set_cond, dst, 0, immed); +} + +uint32_t mvn_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond) +{ + return data_proc(code, cc, OP_MVN, set_cond, dst, 0, src2); +} + +uint32_t mvni_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond) +{ + return data_proci(code, cc, OP_MVN, set_cond, dst, 0, immed); +} + +uint32_t branchi(code_info *code, uint32_t cc, uint32_t op, uint32_t *dst) +{ + uint32_t * from = code->cur + 2; + if (dst - from >= 0x400000 && from - dst > 0x400000) { + return INVALID_IMMED; + } + check_alloc_code(code); + *(code->cur++) = cc | op | ((dst - from) & 0xFFFFFF); + return CODE_OK; +} + +uint32_t b(code_info *code, uint32_t *dst) +{ + return branchi(code, CC_AL, OP_B, dst); +} + +uint32_t b_cc(code_info *code, uint32_t *dst, uint32_t cc) +{ + return branchi(code, cc, OP_B, dst); +} + +uint32_t bl(code_info *code, uint32_t *dst) +{ + return branchi(code, CC_AL, OP_BL, dst); +} + +uint32_t bl_cc(code_info *code, uint32_t *dst, uint32_t cc) +{ + return branchi(code, cc, OP_BL, dst); +} + +uint32_t bx(code_info *code, uint32_t dst) +{ + check_alloc_code(code); + *(code->cur++) = CC_AL | OP_BX | dst; + return CODE_OK; +} + +uint32_t bx_cc(code_info *code, uint32_t dst, uint32_t cc) +{ + check_alloc_code(code); + *(code->cur++) = cc | OP_BX | dst; + return CODE_OK; +} + +uint32_t push(code_info *code, uint32_t reg) +{ + check_alloc_code(code); + *(code->cur++) = CC_AL | PUSH | reg << 12; + return CODE_OK; +} + +uint32_t push_cc(code_info *code, uint32_t reg, uint32_t cc) +{ + check_alloc_code(code); + *(code->cur++) = cc | PUSH | reg << 12; + return CODE_OK; +} + +uint32_t pushm(code_info *code, uint32_t reglist) +{ + check_alloc_code(code); + *(code->cur++) = CC_AL | PUSHM | reglist; + return CODE_OK; +} + +uint32_t pushm_cc(code_info *code, uint32_t reglist, uint32_t cc) +{ + check_alloc_code(code); + *(code->cur++) = cc | PUSHM | reglist; + return CODE_OK; +} + +uint32_t pop(code_info *code, uint32_t reg) +{ + check_alloc_code(code); + *(code->cur++) = CC_AL | POP | reg << 12; + return CODE_OK; +} + +uint32_t pop_cc(code_info *code, uint32_t reg, uint32_t cc) +{ + check_alloc_code(code); + *(code->cur++) = cc | POP | reg << 12; + return CODE_OK; +} + +uint32_t popm(code_info *code, uint32_t reglist) +{ + check_alloc_code(code); + *(code->cur++) = CC_AL | POPM | reglist; + return CODE_OK; +} + +uint32_t popm_cc(code_info *code, uint32_t reglist, uint32_t cc) +{ + check_alloc_code(code); + *(code->cur++) = cc | POPM | reglist; + return CODE_OK; +} diff -r 0687b05061dd -r 1af6c1052993 gen_arm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen_arm.h Sun Feb 23 21:37:19 2014 -0800 @@ -0,0 +1,159 @@ +/* + Copyright 2014 Michael Pavone + This file is part of BlastEm. + BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. +*/ +#ifndef GEN_ARM_H_ +#define GEN_ARM_H_ + +#include + +typedef struct { + uint32_t *cur; + uint32_t *last; +} code_info; + +#define SET_COND 0x100000u +#define NO_COND 0u + +#define CC_FIELD_SHIFT 28 + +#define CC_EQ 0x0u +#define CC_NE (0x1u << CC_FIELD_SHIFT) +#define CC_CS (0x2u << CC_FIELD_SHIFT) +#define CC_CC (0x3u << CC_FIELD_SHIFT) +#define CC_MI (0x4u << CC_FIELD_SHIFT) +#define CC_PL (0x5u << CC_FIELD_SHIFT) +#define CC_VS (0x6u << CC_FIELD_SHIFT) +#define CC_VC (0x7u << CC_FIELD_SHIFT) +#define CC_HI (0x8u << CC_FIELD_SHIFT) +#define CC_LS (0x9u << CC_FIELD_SHIFT) +#define CC_GE (0xAu << CC_FIELD_SHIFT) +#define CC_LT (0xBu << CC_FIELD_SHIFT) +#define CC_GT (0xCu << CC_FIELD_SHIFT) +#define CC_LE (0xDu << CC_FIELD_SHIFT) +#define CC_AL (0xEu << CC_FIELD_SHIFT) + +#define INVALID_IMMED 0xFFFFFFFFu +#define CODE_OK 0u + +enum { + r0, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + r8, + r9, + r10, + r11, + r12, + sp, + lr, + pc +}; + +#define R0 0x1 +#define R1 0x2 +#define R2 0x4 +#define R3 0x8 +#define R4 0x10 +#define R5 0x20 +#define R6 0x40 +#define R7 0x80 +#define R8 0x100 +#define R9 0x200 +#define R10 0x400 +#define R11 0x800 +#define R12 0x1000 +#define SP 0x2000 +#define LR 0x4000 +#define PC 0x8000 + +void init_code_info(code_info *code); + +uint32_t and(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t andi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t and_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t andi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t eor(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t eori(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t eor_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t eori_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t sub(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t subi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t sub_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t subi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t rsb(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t rsbi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t rsb_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t rsbi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t add(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t addi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t add_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t addi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t adc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t adci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t adc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t adci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t sbc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t sbci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t sbc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t sbci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t rsc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t rsci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t rsc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t rsci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t tst(code_info *code, uint32_t src1, uint32_t src2); +uint32_t tsti(code_info *code, uint32_t src1, uint32_t immed); +uint32_t tst_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc); +uint32_t tsti_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc); +uint32_t teq(code_info *code, uint32_t src1, uint32_t src2); +uint32_t teqi(code_info *code, uint32_t src1, uint32_t immed); +uint32_t teq_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc); +uint32_t teqi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc); +uint32_t cmp(code_info *code, uint32_t src1, uint32_t src2); +uint32_t cmpi(code_info *code, uint32_t src1, uint32_t immed); +uint32_t cmp_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc); +uint32_t cmpi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc); +uint32_t cmn(code_info *code, uint32_t src1, uint32_t src2); +uint32_t cmni(code_info *code, uint32_t src1, uint32_t immed); +uint32_t cmn_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc); +uint32_t cmni_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc); +uint32_t orr(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t orri(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t orr_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t orri_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t mov(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond); +uint32_t movi(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond); +uint32_t mov_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t movi_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t bic(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond); +uint32_t bici(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond); +uint32_t bic_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t bici_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond); +uint32_t mvn(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond); +uint32_t mvni(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond); +uint32_t mvn_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond); +uint32_t mvni_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond); + +uint32_t b(code_info *code, uint32_t *dst); +uint32_t b_cc(code_info *code, uint32_t *dst, uint32_t cc); +uint32_t bl(code_info *code, uint32_t *dst); +uint32_t bl_cc(code_info *code, uint32_t *dst, uint32_t cc); +uint32_t bx(code_info *code, uint32_t dst); +uint32_t bx_cc(code_info *code, uint32_t dst, uint32_t cc); + +uint32_t push(code_info *code, uint32_t reg); +uint32_t push_cc(code_info *code, uint32_t reg, uint32_t cc); +uint32_t pushm(code_info *code, uint32_t reglist); +uint32_t pushm_cc(code_info *code, uint32_t reglist, uint32_t cc); +uint32_t pop(code_info *code, uint32_t reg); +uint32_t pop_cc(code_info *code, uint32_t reg, uint32_t cc); +uint32_t popm(code_info *code, uint32_t reglist); +uint32_t popm_cc(code_info *code, uint32_t reglist, uint32_t cc); + +#endif //GEN_ARM_H_ diff -r 0687b05061dd -r 1af6c1052993 test_arm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_arm.c Sun Feb 23 21:37:19 2014 -0800 @@ -0,0 +1,29 @@ +#include +#include "gen_arm.h" + +typedef int32_t (*fib_fun)(int32_t); + +int main(int arc, char **argv) +{ + code_info code; + init_code_info(&code); + uint32_t *fib = code.cur; + subi(&code, r0, r0, 2, SET_COND); + movi_cc(&code, r0, 1, NO_COND, CC_LT); + bx_cc(&code, lr, CC_LT); + pushm(&code, LR | R4); + mov(&code, r4, r0, NO_COND); + bl(&code, fib); + mov(&code, r1, r0, NO_COND); + addi(&code, r0, r4, 1, NO_COND); + mov(&code, r4, r1, NO_COND); + bl(&code, fib); + add(&code, r0, r4, r0, NO_COND); + popm(&code, LR | R4); + bx(&code, LR); + + fib_fun fibc = (fib_fun)fib; + printf("fib(10): %d\n", fibc(10)); + + return 0; +}