summaryrefslogtreecommitdiff
path: root/py/asmarm.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/asmarm.c')
-rw-r--r--py/asmarm.c112
1 files changed, 8 insertions, 104 deletions
diff --git a/py/asmarm.c b/py/asmarm.c
index 2c389ac8c..da07680e3 100644
--- a/py/asmarm.c
+++ b/py/asmarm.c
@@ -38,52 +38,8 @@
#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)
-struct _asm_arm_t {
- uint pass;
- mp_uint_t code_offset;
- mp_uint_t code_size;
- byte *code_base;
- byte dummy_data[4];
-
- mp_uint_t max_num_labels;
- mp_uint_t *label_offsets;
- uint push_reglist;
- uint stack_adjust;
-};
-
-asm_arm_t *asm_arm_new(uint max_num_labels) {
- asm_arm_t *as;
-
- as = m_new0(asm_arm_t, 1);
- as->max_num_labels = max_num_labels;
- as->label_offsets = m_new(mp_uint_t, max_num_labels);
-
- return as;
-}
-
-void asm_arm_free(asm_arm_t *as, bool free_code) {
- if (free_code) {
- MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
- }
- m_del(mp_uint_t, as->label_offsets, as->max_num_labels);
- m_del_obj(asm_arm_t, as);
-}
-
-void asm_arm_start_pass(asm_arm_t *as, uint pass) {
- if (pass == ASM_ARM_PASS_COMPUTE) {
- memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
- } else if (pass == ASM_ARM_PASS_EMIT) {
- MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
- if (as->code_base == NULL) {
- assert(0);
- }
- }
- as->pass = pass;
- as->code_offset = 0;
-}
-
void asm_arm_end_pass(asm_arm_t *as) {
- if (as->pass == ASM_ARM_PASS_EMIT) {
+ if (as->base.pass == MP_ASM_PASS_EMIT) {
#ifdef __arm__
// flush I- and D-cache
asm volatile(
@@ -97,35 +53,12 @@ void asm_arm_end_pass(asm_arm_t *as) {
}
}
-// all functions must go through this one to emit bytes
-// if as->pass < ASM_ARM_PASS_EMIT, then this function only returns a buffer of 4 bytes length
-STATIC byte *asm_arm_get_cur_to_write_bytes(asm_arm_t *as, int num_bytes_to_write) {
- if (as->pass < ASM_ARM_PASS_EMIT) {
- as->code_offset += num_bytes_to_write;
- return as->dummy_data;
- } else {
- assert(as->code_offset + num_bytes_to_write <= as->code_size);
- byte *c = as->code_base + as->code_offset;
- as->code_offset += num_bytes_to_write;
- return c;
- }
-}
-
-uint asm_arm_get_code_pos(asm_arm_t *as) {
- return as->code_offset;
-}
-
-uint asm_arm_get_code_size(asm_arm_t *as) {
- return as->code_size;
-}
-
-void *asm_arm_get_code(asm_arm_t *as) {
- return as->code_base;
-}
-
// Insert word into instruction flow
STATIC void emit(asm_arm_t *as, uint op) {
- *(uint*)asm_arm_get_cur_to_write_bytes(as, 4) = op;
+ uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
+ if (c != NULL) {
+ *(uint32_t*)c = op;
+ }
}
// Insert word into instruction flow, add "ALWAYS" condition code
@@ -263,35 +196,6 @@ void asm_arm_pop(asm_arm_t *as, uint reglist) {
emit_al(as, asm_arm_op_pop(reglist));
}
-void asm_arm_label_assign(asm_arm_t *as, uint label) {
- assert(label < as->max_num_labels);
- if (as->pass < ASM_ARM_PASS_EMIT) {
- // assign label offset
- assert(as->label_offsets[label] == -1);
- as->label_offsets[label] = as->code_offset;
- } else {
- // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
- assert(as->label_offsets[label] == as->code_offset);
- }
-}
-
-void asm_arm_align(asm_arm_t* as, uint align) {
- // TODO fill unused data with NOPs?
- as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
-}
-
-void asm_arm_data(asm_arm_t* as, uint bytesize, uint val) {
- byte *c = asm_arm_get_cur_to_write_bytes(as, bytesize);
- // only write to the buffer in the emit pass (otherwise we overflow dummy_data)
- if (as->pass == ASM_ARM_PASS_EMIT) {
- // little endian
- for (uint i = 0; i < bytesize; i++) {
- *c++ = val;
- val >>= 8;
- }
- }
-}
-
void asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src) {
emit_al(as, asm_arm_op_mov_reg(reg_dest, reg_src));
}
@@ -429,9 +333,9 @@ void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {
}
void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) {
- assert(label < as->max_num_labels);
- mp_uint_t dest = as->label_offsets[label];
- mp_int_t rel = dest - as->code_offset;
+ assert(label < as->base.max_num_labels);
+ mp_uint_t dest = as->base.label_offsets[label];
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction
rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted