summaryrefslogtreecommitdiffstatshomepage
path: root/py/emitinlinethumb.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2015-10-13 17:55:30 +0100
committerDamien George <damien.p.george@gmail.com>2016-04-18 15:09:34 +0100
commit6cdf8167f70bf6c782d91a4b1bb5fa90e4bcf944 (patch)
treeb997d34acb8d303486e8279587c5b0cec1d7675b /py/emitinlinethumb.c
parent127d1f5a2b3b64dd4ca658fea8582ab5af8555a7 (diff)
downloadmicropython-6cdf8167f70bf6c782d91a4b1bb5fa90e4bcf944.tar.gz
micropython-6cdf8167f70bf6c782d91a4b1bb5fa90e4bcf944.zip
fixing inline assembler (emitinlinethumb.c)
Diffstat (limited to 'py/emitinlinethumb.c')
-rw-r--r--py/emitinlinethumb.c132
1 files changed, 70 insertions, 62 deletions
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 90a68caa6d..9ee1ab170d 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -95,18 +95,21 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_s
}
}
-STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) {
- if (n_params > 4) {
- emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
- return 0;
- }
- for (mp_uint_t i = 0; i < n_params; i++) {
- if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {
+STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, const byte *p, const byte *ptop) {
+ mp_uint_t n_params = 0;
+ while (p != ptop) {
+ if (++n_params > 4) {
+ emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
+ return 0;
+ }
+ if (!pt_is_any_id(p)) {
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
return 0;
}
- const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));
- if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
+ qstr qst;
+ p = pt_extract_id(p, &qst);
+ const char *param = qstr_str(qst);
+ if (!(strlen(param) == 2 && param[0] == 'r' && param[1] == '0' + n_params - 1)) {
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
return 0;
}
@@ -171,16 +174,17 @@ STATIC const special_reg_name_t special_reg_name_table[] = {
// return empty string in case of error, so we can attempt to parse the string
// without a special check if it was in fact a string
-STATIC const char *get_arg_str(mp_parse_node_t pn) {
- if (MP_PARSE_NODE_IS_ID(pn)) {
- qstr qst = MP_PARSE_NODE_LEAF_ARG(pn);
+STATIC const char *get_arg_str(const byte *pn) {
+ if (pt_is_any_id(pn)) {
+ qstr qst;
+ pt_extract_id(pn, &qst);
return qstr_str(qst);
} else {
return "";
}
}
-STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) {
+STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, const byte *pn, mp_uint_t max_reg) {
const char *reg_str = get_arg_str(pn);
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
const reg_name_t *r = &reg_name_table[i];
@@ -204,7 +208,7 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n
return 0;
}
-STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
+STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, const byte *pn) {
const char *reg_str = get_arg_str(pn);
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) {
const special_reg_name_t *r = &special_reg_name_table[i];
@@ -219,7 +223,7 @@ STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp
}
#if MICROPY_EMIT_INLINE_THUMB_FLOAT
-STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
+STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, const byte *pn) {
const char *reg_str = get_arg_str(pn);
if (reg_str[0] == 's' && reg_str[1] != '\0') {
mp_uint_t regno = 0;
@@ -247,43 +251,42 @@ malformed:
}
#endif
-STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
+STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, const byte *p) {
// a register list looks like {r0, r1, r2} and is parsed as a Python set
- if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_brace)) {
+ if (!pt_is_rule(p, PN_atom_brace)) {
goto bad_arg;
}
- mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
- assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 1); // should always be
- pn = pns->nodes[0];
+ const byte *ptop;
+ p = pt_rule_extract_top(p, &ptop);
mp_uint_t reglist = 0;
- if (MP_PARSE_NODE_IS_ID(pn)) {
+ if (p == ptop) {
+ goto bad_arg;
+ } else if (pt_is_any_id(p)) {
// set with one element
- reglist |= 1 << get_arg_reg(emit, op, pn, 15);
- } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
- pns = (mp_parse_node_struct_t*)pn;
- if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
- assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
- mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
- if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
- // set with multiple elements
-
- // get first element of set (we rely on get_arg_reg to catch syntax errors)
- reglist |= 1 << get_arg_reg(emit, op, pns->nodes[0], 15);
-
- // get tail elements (2nd, 3rd, ...)
- mp_parse_node_t *nodes;
- int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
-
- // process rest of elements
- for (int i = 0; i < n; i++) {
- reglist |= 1 << get_arg_reg(emit, op, nodes[i], 15);
- }
- } else {
- goto bad_arg;
+ reglist |= 1 << get_arg_reg(emit, op, p, 15);
+ } else if (pt_is_rule(p, PN_dictorsetmaker)) {
+ p = pt_rule_first(p);
+ const byte *p1 = pt_next(p);
+ if (pt_is_rule(p1, PN_dictorsetmaker_list)) {
+ // set with multiple elements
+
+ // get first element of set (we rely on get_arg_reg to catch syntax errors)
+ reglist |= 1 << get_arg_reg(emit, op, p, 15);
+
+ // get tail elements (2nd, 3rd, ...)
+ const byte *p1_top;
+ p1 = pt_rule_extract_top(p1, &p1_top);
+ if (p1 != p1_top) {
+ mp_parse_node_extract_list(&p1, PN_dictorsetmaker_list2);
+ }
+
+ // process rest of elements
+ for (; p1 != p1_top; p1 = pt_next(p1)) {
+ reglist |= 1 << get_arg_reg(emit, op, p1, 15);
}
} else {
goto bad_arg;
@@ -299,7 +302,7 @@ bad_arg:
return 0;
}
-STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) {
+STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, const byte *pn, uint32_t fit_mask) {
mp_obj_t o;
if (!mp_parse_node_get_int_maybe(pn, &o)) {
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op));
@@ -313,21 +316,25 @@ STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node
return i;
}
-STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) {
- if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) {
+STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, const byte *p, const byte **p_base, const byte **p_offset) {
+ if (!pt_is_rule(p, PN_atom_bracket)) {
+ goto bad_arg;
+ }
+ if (pt_is_rule_empty(p)) {
goto bad_arg;
}
- mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
- if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
+ p = pt_rule_first(p);
+ if (!pt_is_rule(p, PN_testlist_comp)) {
goto bad_arg;
}
- pns = (mp_parse_node_struct_t*)pns->nodes[0];
- if (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) != 2) {
+ const byte *ptop;
+ p = pt_rule_extract_top(p, &ptop);
+ if (pt_num_nodes(p, ptop) != 2) {
goto bad_arg;
}
- *pn_base = pns->nodes[0];
- *pn_offset = pns->nodes[1];
+ *p_base = p;
+ *p_offset = pt_next(p);
return true;
bad_arg:
@@ -335,12 +342,13 @@ bad_arg:
return false;
}
-STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
- if (!MP_PARSE_NODE_IS_ID(pn)) {
+STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, const byte *p) {
+ if (!pt_is_any_id(p)) {
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op));
return 0;
}
- qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
+ qstr label_qstr;
+ pt_extract_id(p, &label_qstr);
for (uint i = 0; i < emit->max_num_labels; i++) {
if (emit->label_lookup[i] == label_qstr) {
return i;
@@ -419,7 +427,7 @@ STATIC const format_vfp_op_t format_vfp_op_table[] = {
// shorthand alias for whether we allow ARMv7-M instructions
#define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M
-STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
+STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, const byte **pn_args) {
// TODO perhaps make two tables:
// one_args =
// "b", LAB, asm_thumb_b_n,
@@ -493,7 +501,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
op_code_hi = 0xed90;
op_vldr_vstr:;
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
- mp_parse_node_t pn_base, pn_offset;
+ const byte *pn_base, *pn_offset;
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
mp_uint_t i8;
@@ -632,7 +640,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
}
} else if (n_args == 2) {
- if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
+ if (pt_is_any_id(pn_args[1])) {
// second arg is a register (or should be)
mp_uint_t op_code, op_code_hi;
if (op == MP_QSTR_mov) {
@@ -711,7 +719,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
} else if (ARMV7M && op == MP_QSTR_ldrex) {
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
- mp_parse_node_t pn_base, pn_offset;
+ const byte *pn_base, *pn_offset;
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
@@ -722,7 +730,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
if (op == format_9_10_op_table[i].name) {
op_code = format_9_10_op_table[i].op;
- mp_parse_node_t pn_base, pn_offset;
+ const byte *pn_base, *pn_offset;
mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
@@ -767,7 +775,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
int src_b;
- if (MP_PARSE_NODE_IS_ID(pn_args[2])) {
+ if (pt_is_any_id(pn_args[2])) {
op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND;
src_b = get_arg_reg(emit, op_str, pn_args[2], 7);
} else {
@@ -792,7 +800,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
} else if (ARMV7M && op == MP_QSTR_strex) {
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
- mp_parse_node_t pn_base, pn_offset;
+ const byte *pn_base, *pn_offset;
if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;