summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/asmarm.c99
-rw-r--r--py/asmarm.h20
-rw-r--r--py/asmbase.c104
-rw-r--r--py/asmbase.h68
-rw-r--r--py/asmthumb.c134
-rw-r--r--py/asmthumb.h21
-rw-r--r--py/asmx64.c114
-rw-r--r--py/asmx64.h24
-rw-r--r--py/asmx86.c102
-rw-r--r--py/asmx86.h24
-rw-r--r--py/emitinlinethumb.c18
-rw-r--r--py/emitnative.c98
-rw-r--r--py/py.mk1
13 files changed, 262 insertions, 565 deletions
diff --git a/py/asmarm.c b/py/asmarm.c
index 2c389ac8ce..663f861563 100644
--- a/py/asmarm.c
+++ b/py/asmarm.c
@@ -38,50 +38,6 @@
#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) {
#ifdef __arm__
@@ -97,32 +53,6 @@ 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;
@@ -263,35 +193,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));
}
diff --git a/py/asmarm.h b/py/asmarm.h
index 15e7a047b5..263721057c 100644
--- a/py/asmarm.h
+++ b/py/asmarm.h
@@ -28,9 +28,7 @@
#define __MICROPY_INCLUDED_PY_ASMARM_H__
#include "py/misc.h"
-
-#define ASM_ARM_PASS_COMPUTE (1)
-#define ASM_ARM_PASS_EMIT (2)
+#include "py/asmbase.h"
#define ASM_ARM_REG_R0 (0)
#define ASM_ARM_REG_R1 (1)
@@ -68,22 +66,16 @@
#define ASM_ARM_CC_LE (0xd << 28)
#define ASM_ARM_CC_AL (0xe << 28)
-typedef struct _asm_arm_t asm_arm_t;
+typedef struct _asm_arm_t {
+ mp_asm_base_t base;
+ uint push_reglist;
+ uint stack_adjust;
+} asm_arm_t;
-asm_arm_t *asm_arm_new(uint max_num_labels);
-void asm_arm_free(asm_arm_t *as, bool free_code);
-void asm_arm_start_pass(asm_arm_t *as, uint pass);
void asm_arm_end_pass(asm_arm_t *as);
-uint asm_arm_get_code_pos(asm_arm_t *as);
-uint asm_arm_get_code_size(asm_arm_t *as);
-void *asm_arm_get_code(asm_arm_t *as);
void asm_arm_entry(asm_arm_t *as, int num_locals);
void asm_arm_exit(asm_arm_t *as);
-void asm_arm_label_assign(asm_arm_t *as, uint label);
-
-void asm_arm_align(asm_arm_t* as, uint align);
-void asm_arm_data(asm_arm_t* as, uint bytesize, uint val);
void asm_arm_bkpt(asm_arm_t *as);
diff --git a/py/asmbase.c b/py/asmbase.c
new file mode 100644
index 0000000000..916f7c5ec8
--- /dev/null
+++ b/py/asmbase.c
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "py/obj.h"
+#include "py/misc.h"
+#include "py/asmbase.h"
+
+#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
+
+void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels) {
+ as->max_num_labels = max_num_labels;
+ as->label_offsets = m_new(size_t, max_num_labels);
+}
+
+void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code) {
+ if (free_code) {
+ MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
+ }
+ m_del(size_t, as->label_offsets, as->max_num_labels);
+}
+
+void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {
+ if (pass == MP_ASM_PASS_COMPUTE) {
+ // reset all labels
+ memset(as->label_offsets, -1, as->max_num_labels * sizeof(size_t));
+ } else if (pass == MP_ASM_PASS_EMIT) {
+ // allocating executable RAM is platform specific
+ MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
+ assert(as->code_base != NULL);
+ }
+ as->pass = pass;
+ as->code_offset = 0;
+}
+
+// all functions must go through this one to emit bytes
+// if as->pass < MP_ASM_PASS_EMIT, then this function returns dummy_data
+uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) {
+ if (as->pass < MP_ASM_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);
+ uint8_t *c = as->code_base + as->code_offset;
+ as->code_offset += num_bytes_to_write;
+ return c;
+ }
+}
+
+void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
+ assert(label < as->max_num_labels);
+ if (as->pass < MP_ASM_PASS_EMIT) {
+ // assign label offset
+ assert(as->label_offsets[label] == (size_t)-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);
+ }
+}
+
+// align must be a multiple of 2
+void mp_asm_base_align(mp_asm_base_t* as, unsigned int align) {
+ as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
+}
+
+// this function assumes a little endian machine
+void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) {
+ uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize);
+ // only write to the buffer in the emit pass (otherwise we may overflow dummy_data)
+ if (as->pass == MP_ASM_PASS_EMIT) {
+ for (unsigned int i = 0; i < bytesize; i++) {
+ *c++ = val;
+ val >>= 8;
+ }
+ }
+}
+
+#endif // MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
diff --git a/py/asmbase.h b/py/asmbase.h
new file mode 100644
index 0000000000..bfc8ac7ff2
--- /dev/null
+++ b/py/asmbase.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_PY_ASMBASE_H
+#define MICROPY_INCLUDED_PY_ASMBASE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define MP_ASM_PASS_COMPUTE (1)
+#define MP_ASM_PASS_EMIT (2)
+
+typedef struct _mp_asm_base_t {
+ int pass;
+ size_t code_offset;
+ size_t code_size;
+ uint8_t *code_base;
+
+ size_t max_num_labels;
+ size_t *label_offsets;
+
+ // must be last in struct
+ uint8_t dummy_data[4];
+} mp_asm_base_t;
+
+void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels);
+void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code);
+void mp_asm_base_start_pass(mp_asm_base_t *as, int pass);
+uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write);
+void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label);
+void mp_asm_base_align(mp_asm_base_t* as, unsigned int align);
+void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val);
+
+static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) {
+ return as->code_offset;
+}
+
+static inline size_t mp_asm_base_get_code_size(mp_asm_base_t *as) {
+ return as->code_size;
+}
+
+static inline void *mp_asm_base_get_code(mp_asm_base_t *as) {
+ return as->code_base;
+}
+
+#endif // MICROPY_INCLUDED_PY_ASMBASE_H
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 1aae3d38eb..705c15a189 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -42,49 +42,8 @@
#define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
#define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000)
-struct _asm_thumb_t {
- mp_uint_t 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;
- mp_uint_t push_reglist;
- mp_uint_t stack_adjust;
-};
-
-asm_thumb_t *asm_thumb_new(uint max_num_labels) {
- asm_thumb_t *as;
-
- as = m_new0(asm_thumb_t, 1);
- as->max_num_labels = max_num_labels;
- as->label_offsets = m_new(mp_uint_t, max_num_labels);
-
- return as;
-}
-
-void asm_thumb_free(asm_thumb_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_thumb_t, as);
-}
-
-void asm_thumb_start_pass(asm_thumb_t *as, uint pass) {
- if (pass == ASM_THUMB_PASS_COMPUTE) {
- memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
- } else if (pass == ASM_THUMB_PASS_EMIT) {
- MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
- if (as->code_base == NULL) {
- assert(0);
- }
- //printf("code_size: %u\n", as->code_size);
- }
- as->pass = pass;
- as->code_offset = 0;
+static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
+ return mp_asm_base_get_cur_to_write_bytes(&as->base, n);
}
void asm_thumb_end_pass(asm_thumb_t *as) {
@@ -92,7 +51,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
// could check labels are resolved...
#if defined(MCU_SERIES_F7)
- if (as->pass == ASM_THUMB_PASS_EMIT) {
+ if (as->base.pass == MP_ASM_PASS_EMIT) {
// flush D-cache, so the code emited is stored in memory
SCB_CleanDCache_by_Addr((uint32_t*)as->code_base, as->code_size);
// invalidate I-cache
@@ -101,33 +60,6 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
#endif
}
-// all functions must go through this one to emit bytes
-// if as->pass < ASM_THUMB_PASS_EMIT, then this function only returns a buffer of 4 bytes length
-STATIC byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int num_bytes_to_write) {
- //printf("emit %d\n", num_bytes_to_write);
- if (as->pass < ASM_THUMB_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_thumb_get_code_pos(asm_thumb_t *as) {
- return as->code_offset;
-}
-
-uint asm_thumb_get_code_size(asm_thumb_t *as) {
- return as->code_size;
-}
-
-void *asm_thumb_get_code(asm_thumb_t *as) {
- return as->code_base;
-}
-
/*
STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {
byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);
@@ -223,39 +155,9 @@ void asm_thumb_exit(asm_thumb_t *as) {
asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist));
}
-void asm_thumb_label_assign(asm_thumb_t *as, uint label) {
- assert(label < as->max_num_labels);
- if (as->pass < ASM_THUMB_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
- //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
- assert(as->label_offsets[label] == as->code_offset);
- }
-}
-
-void asm_thumb_align(asm_thumb_t* as, uint align) {
- // TODO fill unused data with NOPs?
- as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
-}
-
-void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val) {
- byte *c = asm_thumb_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_THUMB_PASS_EMIT) {
- // little endian
- for (uint i = 0; i < bytesize; i++) {
- *c++ = val;
- val >>= 8;
- }
- }
-}
-
STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) {
- assert(label < as->max_num_labels);
- return as->label_offsets[label];
+ assert(label < as->base.max_num_labels);
+ return as->base.label_offsets[label];
}
void asm_thumb_op16(asm_thumb_t *as, uint op) {
@@ -309,10 +211,10 @@ void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_
bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
asm_thumb_op16(as, OP_B_N(rel));
- return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT12(rel);
+ return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT12(rel);
}
#define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff))
@@ -323,11 +225,11 @@ bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) {
bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
if (!wide) {
asm_thumb_op16(as, OP_BCC_N(cond, rel));
- return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT9(rel);
+ return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT9(rel);
} else {
asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel));
return true;
@@ -339,10 +241,10 @@ bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) {
bool asm_thumb_bl_label(asm_thumb_t *as, uint label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel));
- return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT23(rel);
+ return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT23(rel);
}
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) {
@@ -367,13 +269,13 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
// TODO this is very inefficient, improve it!
void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
// align on machine-word + 2
- if ((as->code_offset & 3) == 0) {
+ if ((as->base.code_offset & 3) == 0) {
asm_thumb_op16(as, ASM_THUMB_OP_NOP);
}
// jump over the i32 value (instruction prefetch adds 2 to PC)
asm_thumb_op16(as, OP_B_N(2));
// store i32 on machine-word aligned boundary
- asm_thumb_data(as, 4, i32);
+ mp_asm_base_data(&as->base, 4, i32);
// do the actual load of the i32 value
asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32);
}
@@ -384,14 +286,14 @@ void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) {
assert(rlo_src < ASM_THUMB_REG_R8);
int word_offset = local_num;
- assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
+ assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset));
}
void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < ASM_THUMB_REG_R8);
int word_offset = local_num;
- assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
+ assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset));
}
@@ -400,7 +302,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < ASM_THUMB_REG_R8);
int word_offset = local_num;
- assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
+ assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
}
@@ -410,7 +312,7 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
void asm_thumb_b_label(asm_thumb_t *as, uint label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
if (dest != (mp_uint_t)-1 && rel <= -4) {
// is a backwards jump, so we know the size of the jump on the first pass
@@ -429,7 +331,7 @@ void asm_thumb_b_label(asm_thumb_t *as, uint label) {
void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
if (dest != (mp_uint_t)-1 && rel <= -4) {
// is a backwards jump, so we know the size of the jump on the first pass
diff --git a/py/asmthumb.h b/py/asmthumb.h
index 43d6c4286f..c03b00da3e 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -27,9 +27,7 @@
#define __MICROPY_INCLUDED_PY_ASMTHUMB_H__
#include "py/misc.h"
-
-#define ASM_THUMB_PASS_COMPUTE (1)
-#define ASM_THUMB_PASS_EMIT (2)
+#include "py/asmbase.h"
#define ASM_THUMB_REG_R0 (0)
#define ASM_THUMB_REG_R1 (1)
@@ -64,24 +62,17 @@
#define ASM_THUMB_CC_GT (0xc)
#define ASM_THUMB_CC_LE (0xd)
-typedef struct _asm_thumb_t asm_thumb_t;
+typedef struct _asm_thumb_t {
+ mp_asm_base_t base;
+ uint32_t push_reglist;
+ uint32_t stack_adjust;
+} asm_thumb_t;
-asm_thumb_t *asm_thumb_new(uint max_num_labels);
-void asm_thumb_free(asm_thumb_t *as, bool free_code);
-void asm_thumb_start_pass(asm_thumb_t *as, uint pass);
void asm_thumb_end_pass(asm_thumb_t *as);
-uint asm_thumb_get_code_pos(asm_thumb_t *as);
-uint asm_thumb_get_code_size(asm_thumb_t *as);
-void *asm_thumb_get_code(asm_thumb_t *as);
void asm_thumb_entry(asm_thumb_t *as, int num_locals);
void asm_thumb_exit(asm_thumb_t *as);
-void asm_thumb_label_assign(asm_thumb_t *as, uint label);
-
-void asm_thumb_align(asm_thumb_t* as, uint align);
-void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val);
-
// argument order follows ARM, in general dest is first
// note there is a difference between movw and mov.w, and many others!
diff --git a/py/asmx64.c b/py/asmx64.c
index 5e23a594ed..c9dad2a669 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -116,80 +116,8 @@
#define UNSIGNED_FIT32(x) (((x) & 0xffffffff00000000) == 0)
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
-struct _asm_x64_t {
- uint pass;
- mp_uint_t code_offset;
- mp_uint_t code_size;
- byte *code_base;
- byte dummy_data[8];
-
- mp_uint_t max_num_labels;
- mp_uint_t *label_offsets;
- int num_locals;
-};
-
-asm_x64_t *asm_x64_new(mp_uint_t max_num_labels) {
- asm_x64_t *as;
-
- as = m_new0(asm_x64_t, 1);
- as->max_num_labels = max_num_labels;
- as->label_offsets = m_new(mp_uint_t, max_num_labels);
-
- return as;
-}
-
-void asm_x64_free(asm_x64_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_x64_t, as);
-}
-
-void asm_x64_start_pass(asm_x64_t *as, uint pass) {
- if (pass == ASM_X64_PASS_COMPUTE) {
- // reset all labels
- memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
- } if (pass == ASM_X64_PASS_EMIT) {
- MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
- if (as->code_base == NULL) {
- assert(0);
- }
- //printf("code_size: %u\n", as->code_size);
- }
- as->pass = pass;
- as->code_offset = 0;
-}
-
-void asm_x64_end_pass(asm_x64_t *as) {
- // could check labels are resolved...
- (void)as;
-}
-
-// all functions must go through this one to emit bytes
-STATIC byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int num_bytes_to_write) {
- //printf("emit %d\n", num_bytes_to_write);
- if (as->pass < ASM_X64_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;
- }
-}
-
-mp_uint_t asm_x64_get_code_pos(asm_x64_t *as) {
- return as->code_offset;
-}
-
-mp_uint_t asm_x64_get_code_size(asm_x64_t *as) {
- return as->code_size;
-}
-
-void *asm_x64_get_code(asm_x64_t *as) {
- return as->code_base;
+static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) {
+ return mp_asm_base_get_cur_to_write_bytes(&as->base, n);
}
STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) {
@@ -230,21 +158,6 @@ STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {
c[7] = IMM64_L7(w64);
}
-// align must be a multiple of 2
-void asm_x64_align(asm_x64_t* as, mp_uint_t align) {
- // TODO fill unused data with NOPs?
- as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
-}
-
-void asm_x64_data(asm_x64_t* as, mp_uint_t bytesize, mp_uint_t val) {
- byte *c = asm_x64_get_cur_to_write_bytes(as, bytesize);
- // machine is little endian
- for (uint i = 0; i < bytesize; i++) {
- *c++ = val;
- val >>= 8;
- }
-}
-
/* unused
STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
byte* c;
@@ -440,7 +353,7 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r
// src_i64 is stored as a full word in the code, and aligned to machine-word boundary
void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64) {
// mov instruction uses 2 bytes for the instruction, before the i64
- while (((as->code_offset + 2) & (WORD_SIZE - 1)) != 0) {
+ while (((as->base.code_offset + 2) & (WORD_SIZE - 1)) != 0) {
asm_x64_nop(as);
}
asm_x64_mov_i64_to_r64(as, src_i64, dest_r64);
@@ -552,27 +465,14 @@ void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) {
asm_x64_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r8));
}
-void asm_x64_label_assign(asm_x64_t *as, mp_uint_t label) {
- assert(label < as->max_num_labels);
- if (as->pass < ASM_X64_PASS_EMIT) {
- // assign label offset
- assert(as->label_offsets[label] == (mp_uint_t)-1);
- as->label_offsets[label] = as->code_offset;
- } else {
- // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
- //printf("l%d: (at %ld=%ld)\n", label, as->label_offsets[label], as->code_offset);
- assert(as->label_offsets[label] == as->code_offset);
- }
-}
-
STATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) {
- assert(label < as->max_num_labels);
- return as->label_offsets[label];
+ assert(label < as->base.max_num_labels);
+ return as->base.label_offsets[label];
}
void asm_x64_jmp_label(asm_x64_t *as, mp_uint_t label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
if (dest != (mp_uint_t)-1 && rel < 0) {
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 8 bit relative jump
@@ -594,7 +494,7 @@ void asm_x64_jmp_label(asm_x64_t *as, mp_uint_t label) {
void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
mp_uint_t dest = get_label_dest(as, label);
- mp_int_t rel = dest - as->code_offset;
+ mp_int_t rel = dest - as->base.code_offset;
if (dest != (mp_uint_t)-1 && rel < 0) {
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 8 bit relative jump
diff --git a/py/asmx64.h b/py/asmx64.h
index 6fbc2c9069..daf5b3d0b1 100644
--- a/py/asmx64.h
+++ b/py/asmx64.h
@@ -28,6 +28,7 @@
#include "py/mpconfig.h"
#include "py/misc.h"
+#include "py/asmbase.h"
// AMD64 calling convention is:
// - args pass in: RDI, RSI, RDX, RCX, R08, R09
@@ -41,9 +42,6 @@
// NOTE: this is a change from the old convention used in this file and
// some functions still use the old (reverse) convention.
-#define ASM_X64_PASS_COMPUTE (1)
-#define ASM_X64_PASS_EMIT (2)
-
#define ASM_X64_REG_RAX (0)
#define ASM_X64_REG_RCX (1)
#define ASM_X64_REG_RDX (2)
@@ -72,18 +70,15 @@
#define ASM_X64_CC_JLE (0xe) // less or equal, signed
#define ASM_X64_CC_JG (0xf) // greater, signed
-typedef struct _asm_x64_t asm_x64_t;
-
-asm_x64_t* asm_x64_new(mp_uint_t max_num_labels);
-void asm_x64_free(asm_x64_t* as, bool free_code);
-void asm_x64_start_pass(asm_x64_t *as, uint pass);
-void asm_x64_end_pass(asm_x64_t *as);
-mp_uint_t asm_x64_get_code_pos(asm_x64_t *as);
-mp_uint_t asm_x64_get_code_size(asm_x64_t* as);
-void* asm_x64_get_code(asm_x64_t* as);
+typedef struct _asm_x64_t {
+ mp_asm_base_t base;
+ byte dummy_data[4]; // in addition to dummy_data in base
+ int num_locals;
+} asm_x64_t;
-void asm_x64_align(asm_x64_t *as, mp_uint_t align);
-void asm_x64_data(asm_x64_t *as, mp_uint_t bytesize, mp_uint_t val);
+static inline void asm_x64_end_pass(asm_x64_t *as) {
+ (void)as;
+}
void asm_x64_nop(asm_x64_t* as);
void asm_x64_push_r64(asm_x64_t* as, int src_r64);
@@ -111,7 +106,6 @@ void asm_x64_mul_r64_r64(asm_x64_t* as, int dest_r64, int src_r64);
void asm_x64_cmp_r64_with_r64(asm_x64_t* as, int src_r64_a, int src_r64_b);
void asm_x64_test_r8_with_r8(asm_x64_t* as, int src_r64_a, int src_r64_b);
void asm_x64_setcc_r8(asm_x64_t* as, int jcc_type, int dest_r8);
-void asm_x64_label_assign(asm_x64_t* as, mp_uint_t label);
void asm_x64_jmp_label(asm_x64_t* as, mp_uint_t label);
void asm_x64_jcc_label(asm_x64_t* as, int jcc_type, mp_uint_t label);
void asm_x64_entry(asm_x64_t* as, int num_locals);
diff --git a/py/asmx86.c b/py/asmx86.c
index 40958826fa..cb9b30d402 100644
--- a/py/asmx86.c
+++ b/py/asmx86.c
@@ -100,80 +100,6 @@
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
-struct _asm_x86_t {
- uint pass;
- mp_uint_t code_offset;
- mp_uint_t code_size;
- byte *code_base;
- byte dummy_data[8];
-
- mp_uint_t max_num_labels;
- mp_uint_t *label_offsets;
- int num_locals;
-};
-
-asm_x86_t *asm_x86_new(mp_uint_t max_num_labels) {
- asm_x86_t *as;
-
- as = m_new0(asm_x86_t, 1);
- as->max_num_labels = max_num_labels;
- as->label_offsets = m_new(mp_uint_t, max_num_labels);
-
- return as;
-}
-
-void asm_x86_free(asm_x86_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_x86_t, as);
-}
-
-void asm_x86_start_pass(asm_x86_t *as, mp_uint_t pass) {
- if (pass == ASM_X86_PASS_COMPUTE) {
- // reset all labels
- memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
- } else if (pass == ASM_X86_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_x86_end_pass(asm_x86_t *as) {
- (void)as;
-}
-
-// all functions must go through this one to emit bytes
-STATIC byte *asm_x86_get_cur_to_write_bytes(asm_x86_t *as, int num_bytes_to_write) {
- //printf("emit %d\n", num_bytes_to_write);
- if (as->pass < ASM_X86_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;
- }
-}
-
-mp_uint_t asm_x86_get_code_pos(asm_x86_t *as) {
- return as->code_offset;
-}
-
-mp_uint_t asm_x86_get_code_size(asm_x86_t *as) {
- return as->code_size;
-}
-
-void *asm_x86_get_code(asm_x86_t *as) {
- return as->code_base;
-}
-
STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) {
byte* c = asm_x86_get_cur_to_write_bytes(as, 1);
c[0] = b1;
@@ -200,21 +126,6 @@ STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {
c[3] = IMM32_L3(w32);
}
-// align must be a multiple of 2
-void asm_x86_align(asm_x86_t* as, mp_uint_t align) {
- // TODO fill unused data with NOPs?
- as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
-}
-
-void asm_x86_data(asm_x86_t* as, mp_uint_t bytesize, mp_uint_t val) {
- byte *c = asm_x86_get_cur_to_write_bytes(as, bytesize);
- // machine is little endian
- for (uint i = 0; i < bytesize; i++) {
- *c++ = val;
- val >>= 8;
- }
-}
-
STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {
assert(disp_r32 != ASM_X86_REG_ESP);
@@ -419,19 +330,6 @@ void asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8) {
asm_x86_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r8));
}
-void asm_x86_label_assign(asm_x86_t *as, mp_uint_t label) {
- assert(label < as->max_num_labels);
- if (as->pass < ASM_X86_PASS_EMIT) {
- // assign label offset
- assert(as->label_offsets[label] == (mp_uint_t)-1);
- as->label_offsets[label] = as->code_offset;
- } else {
- // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
- //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
- assert(as->label_offsets[label] == as->code_offset);
- }
-}
-
STATIC mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) {
assert(label < as->max_num_labels);
return as->label_offsets[label];
diff --git a/py/asmx86.h b/py/asmx86.h
index e0c57722ad..85352fff35 100644
--- a/py/asmx86.h
+++ b/py/asmx86.h
@@ -28,6 +28,7 @@
#include "py/mpconfig.h"
#include "py/misc.h"
+#include "py/asmbase.h"
// x86 cdecl calling convention is:
// - args passed on the stack in reverse order
@@ -42,9 +43,6 @@
// NOTE: this is a change from the old convention used in this file and
// some functions still use the old (reverse) convention.
-#define ASM_X86_PASS_COMPUTE (1)
-#define ASM_X86_PASS_EMIT (2)
-
#define ASM_X86_REG_EAX (0)
#define ASM_X86_REG_ECX (1)
#define ASM_X86_REG_EDX (2)
@@ -75,18 +73,15 @@
#define ASM_X86_CC_JLE (0xe) // less or equal, signed
#define ASM_X86_CC_JG (0xf) // greater, signed
-typedef struct _asm_x86_t asm_x86_t;
-
-asm_x86_t* asm_x86_new(mp_uint_t max_num_labels);
-void asm_x86_free(asm_x86_t* as, bool free_code);
-void asm_x86_start_pass(asm_x86_t *as, mp_uint_t pass);
-void asm_x86_end_pass(asm_x86_t *as);
-mp_uint_t asm_x86_get_code_pos(asm_x86_t *as);
-mp_uint_t asm_x86_get_code_size(asm_x86_t* as);
-void* asm_x86_get_code(asm_x86_t* as);
+typedef struct _asm_x86_t {
+ mp_asm_base_t base;
+ byte dummy_data[4]; // in addition to dummy_data in base
+ int num_locals;
+} asm_x86_t;
-void asm_x86_align(asm_x86_t *as, mp_uint_t align);
-void asm_x86_data(asm_x86_t *as, mp_uint_t bytesize, mp_uint_t val);
+static inline void asm_x86_end_pass(asm_x86_t *as) {
+ (void)as;
+}
void asm_x86_mov_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);
void asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32);
@@ -108,7 +103,6 @@ void asm_x86_mul_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);
void asm_x86_cmp_r32_with_r32(asm_x86_t* as, int src_r32_a, int src_r32_b);
void asm_x86_test_r8_with_r8(asm_x86_t* as, int src_r32_a, int src_r32_b);
void asm_x86_setcc_r8(asm_x86_t* as, mp_uint_t jcc_type, int dest_r8);
-void asm_x86_label_assign(asm_x86_t* as, mp_uint_t label);
void asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label);
void asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label);
void asm_x86_entry(asm_x86_t* as, mp_uint_t num_locals);
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 90a68caa6d..760ec8cc0d 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -63,13 +63,15 @@ emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
emit->max_num_labels = max_num_labels;
emit->label_lookup = m_new(qstr, max_num_labels);
- emit->as = asm_thumb_new(max_num_labels);
+ emit->as = m_new0(asm_thumb_t, 1);
+ mp_asm_base_init(&emit->as->base, max_num_labels);
return emit;
}
void emit_inline_thumb_free(emit_inline_asm_t *emit) {
m_del(qstr, emit->label_lookup, emit->max_num_labels);
- asm_thumb_free(emit->as, false);
+ mp_asm_base_deinit(&emit->as->base, false);
+ m_del_obj(asm_thumb_t, emit->as);
m_del_obj(emit_inline_asm_t, emit);
}
@@ -80,7 +82,7 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa
if (emit->pass == MP_PASS_CODE_SIZE) {
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
}
- asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE);
+ mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
asm_thumb_entry(emit->as, 0);
}
@@ -89,9 +91,9 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_s
asm_thumb_end_pass(emit->as);
if (emit->pass == MP_PASS_EMIT) {
- void *f = asm_thumb_get_code(emit->as);
+ void *f = mp_asm_base_get_code(&emit->as->base);
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
- asm_thumb_get_code_size(emit->as), NULL, emit->scope->num_pos_args, 0, type_sig);
+ mp_asm_base_get_code_size(&emit->as->base), NULL, emit->scope->num_pos_args, 0, type_sig);
}
}
@@ -125,16 +127,16 @@ STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num
}
}
emit->label_lookup[label_num] = label_id;
- asm_thumb_label_assign(emit->as, label_num);
+ mp_asm_base_label_assign(&emit->as->base, label_num);
return true;
}
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, mp_uint_t align) {
- asm_thumb_align(emit->as, align);
+ mp_asm_base_align(&emit->as->base, align);
}
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
- asm_thumb_data(emit->as, bytesize, val);
+ mp_asm_base_data(&emit->as->base, bytesize, val);
}
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
diff --git a/py/emitnative.c b/py/emitnative.c
index 46e1076a96..d19dfe467c 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -91,24 +91,11 @@
#define REG_LOCAL_3 ASM_X64_REG_R13
#define REG_LOCAL_NUM (3)
-#define ASM_PASS_COMPUTE ASM_X64_PASS_COMPUTE
-#define ASM_PASS_EMIT ASM_X64_PASS_EMIT
-
#define ASM_T asm_x64_t
-#define ASM_NEW asm_x64_new
-#define ASM_FREE asm_x64_free
-#define ASM_GET_CODE asm_x64_get_code
-#define ASM_GET_CODE_POS asm_x64_get_code_pos
-#define ASM_GET_CODE_SIZE asm_x64_get_code_size
-#define ASM_START_PASS asm_x64_start_pass
#define ASM_END_PASS asm_x64_end_pass
#define ASM_ENTRY asm_x64_entry
#define ASM_EXIT asm_x64_exit
-#define ASM_ALIGN asm_x64_align
-#define ASM_DATA asm_x64_data
-
-#define ASM_LABEL_ASSIGN asm_x64_label_assign
#define ASM_JUMP asm_x64_jmp_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
do { \
@@ -236,24 +223,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define REG_LOCAL_3 ASM_X86_REG_EDI
#define REG_LOCAL_NUM (3)
-#define ASM_PASS_COMPUTE ASM_X86_PASS_COMPUTE
-#define ASM_PASS_EMIT ASM_X86_PASS_EMIT
-
#define ASM_T asm_x86_t
-#define ASM_NEW asm_x86_new
-#define ASM_FREE asm_x86_free
-#define ASM_GET_CODE asm_x86_get_code
-#define ASM_GET_CODE_POS asm_x86_get_code_pos
-#define ASM_GET_CODE_SIZE asm_x86_get_code_size
-#define ASM_START_PASS asm_x86_start_pass
#define ASM_END_PASS asm_x86_end_pass
#define ASM_ENTRY asm_x86_entry
#define ASM_EXIT asm_x86_exit
-#define ASM_ALIGN asm_x86_align
-#define ASM_DATA asm_x86_data
-
-#define ASM_LABEL_ASSIGN asm_x86_label_assign
#define ASM_JUMP asm_x86_jmp_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
do { \
@@ -331,24 +305,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define REG_LOCAL_3 ASM_THUMB_REG_R6
#define REG_LOCAL_NUM (3)
-#define ASM_PASS_COMPUTE ASM_THUMB_PASS_COMPUTE
-#define ASM_PASS_EMIT ASM_THUMB_PASS_EMIT
-
#define ASM_T asm_thumb_t
-#define ASM_NEW asm_thumb_new
-#define ASM_FREE asm_thumb_free
-#define ASM_GET_CODE asm_thumb_get_code
-#define ASM_GET_CODE_POS asm_thumb_get_code_pos
-#define ASM_GET_CODE_SIZE asm_thumb_get_code_size
-#define ASM_START_PASS asm_thumb_start_pass
#define ASM_END_PASS asm_thumb_end_pass
#define ASM_ENTRY asm_thumb_entry
#define ASM_EXIT asm_thumb_exit
-#define ASM_ALIGN asm_thumb_align
-#define ASM_DATA asm_thumb_data
-
-#define ASM_LABEL_ASSIGN asm_thumb_label_assign
#define ASM_JUMP asm_thumb_b_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
do { \
@@ -425,24 +386,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define REG_LOCAL_3 ASM_ARM_REG_R6
#define REG_LOCAL_NUM (3)
-#define ASM_PASS_COMPUTE ASM_ARM_PASS_COMPUTE
-#define ASM_PASS_EMIT ASM_ARM_PASS_EMIT
-
#define ASM_T asm_arm_t
-#define ASM_NEW asm_arm_new
-#define ASM_FREE asm_arm_free
-#define ASM_GET_CODE asm_arm_get_code
-#define ASM_GET_CODE_POS asm_arm_get_code_pos
-#define ASM_GET_CODE_SIZE asm_arm_get_code_size
-#define ASM_START_PASS asm_arm_start_pass
#define ASM_END_PASS asm_arm_end_pass
#define ASM_ENTRY asm_arm_entry
#define ASM_EXIT asm_arm_exit
-#define ASM_ALIGN asm_arm_align
-#define ASM_DATA asm_arm_data
-
-#define ASM_LABEL_ASSIGN asm_arm_label_assign
#define ASM_JUMP asm_arm_b_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
do { \
@@ -582,12 +530,14 @@ struct _emit_t {
emit_t *EXPORT_FUN(new)(mp_obj_t *error_slot, mp_uint_t max_num_labels) {
emit_t *emit = m_new0(emit_t, 1);
emit->error_slot = error_slot;
- emit->as = ASM_NEW(max_num_labels);
+ emit->as = m_new0(ASM_T, 1);
+ mp_asm_base_init(&emit->as->base, max_num_labels);
return emit;
}
void EXPORT_FUN(free)(emit_t *emit) {
- ASM_FREE(emit->as, false);
+ mp_asm_base_deinit(&emit->as->base, false);
+ m_del_obj(ASM_T, emit->as);
m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);
m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);
m_del_obj(emit_t, emit);
@@ -679,7 +629,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
emit->stack_info[i].vtype = VTYPE_UNBOUND;
}
- ASM_START_PASS(emit->as, pass == MP_PASS_EMIT ? ASM_PASS_EMIT : ASM_PASS_COMPUTE);
+ mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
// generate code for entry to function
@@ -824,21 +774,21 @@ STATIC void emit_native_end_pass(emit_t *emit) {
}
if (!emit->do_viper_types) {
- emit->prelude_offset = ASM_GET_CODE_POS(emit->as);
- ASM_DATA(emit->as, 1, emit->scope->scope_flags);
- ASM_DATA(emit->as, 1, emit->scope->num_pos_args);
- ASM_DATA(emit->as, 1, emit->scope->num_kwonly_args);
- ASM_DATA(emit->as, 1, emit->scope->num_def_pos_args);
+ emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->num_def_pos_args);
// write code info
#if MICROPY_PERSISTENT_CODE
- ASM_DATA(emit->as, 1, 5);
- ASM_DATA(emit->as, 1, emit->scope->simple_name);
- ASM_DATA(emit->as, 1, emit->scope->simple_name >> 8);
- ASM_DATA(emit->as, 1, emit->scope->source_file);
- ASM_DATA(emit->as, 1, emit->scope->source_file >> 8);
+ mp_asm_base_data(&emit->as->base, 1, 5);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file);
+ mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file >> 8);
#else
- ASM_DATA(emit->as, 1, 1);
+ mp_asm_base_data(&emit->as->base, 1, 1);
#endif
// bytecode prelude: initialise closed over variables
@@ -846,13 +796,13 @@ STATIC void emit_native_end_pass(emit_t *emit) {
id_info_t *id = &emit->scope->id_info[i];
if (id->kind == ID_INFO_KIND_CELL) {
assert(id->local_num < 255);
- ASM_DATA(emit->as, 1, id->local_num); // write the local which should be converted to a cell
+ mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell
}
}
- ASM_DATA(emit->as, 1, 255); // end of list sentinel
+ mp_asm_base_data(&emit->as->base, 1, 255); // end of list sentinel
- ASM_ALIGN(emit->as, ASM_WORD_SIZE);
- emit->const_table_offset = ASM_GET_CODE_POS(emit->as);
+ mp_asm_base_align(&emit->as->base, ASM_WORD_SIZE);
+ emit->const_table_offset = mp_asm_base_get_code_pos(&emit->as->base);
// write argument names as qstr objects
// see comment in corresponding part of emitbc.c about the logic here
@@ -865,7 +815,7 @@ STATIC void emit_native_end_pass(emit_t *emit) {
break;
}
}
- ASM_DATA(emit->as, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
+ mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
}
}
@@ -878,8 +828,8 @@ STATIC void emit_native_end_pass(emit_t *emit) {
}
if (emit->pass == MP_PASS_EMIT) {
- void *f = ASM_GET_CODE(emit->as);
- mp_uint_t f_len = ASM_GET_CODE_SIZE(emit->as);
+ void *f = mp_asm_base_get_code(&emit->as->base);
+ mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base);
// compute type signature
// note that the lower 4 bits of a vtype are tho correct MP_NATIVE_TYPE_xxx
@@ -1255,7 +1205,7 @@ STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) {
emit_native_pre(emit);
// need to commit stack because we can jump here from elsewhere
need_stack_settled(emit);
- ASM_LABEL_ASSIGN(emit->as, l);
+ mp_asm_base_label_assign(&emit->as->base, l);
emit_post(emit);
}
diff --git a/py/py.mk b/py/py.mk
index ec67ac2a08..87a860f755 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -120,6 +120,7 @@ PY_O_BASENAME = \
compile.o \
emitcommon.o \
emitbc.o \
+ asmbase.o \
asmx64.o \
emitnx64.o \
asmx86.o \