diff --git a/py/asmthumb.c b/py/asmthumb.c index 7037ac5187..c178f634d6 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -209,6 +209,20 @@ void asm_thumb_label_assign(asm_thumb_t *as, uint label) { } } +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); + // little endian + for (uint i = 0; i < bytesize; i++) { + *c++ = val; + val >>= 8; + } +} + STATIC int get_label_dest(asm_thumb_t *as, uint label) { assert(label < as->max_num_labels); return as->label_offsets[label]; diff --git a/py/asmthumb.h b/py/asmthumb.h index ca81b847f4..d700e53279 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -55,6 +55,9 @@ 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/compile.c b/py/compile.c index 57f6f1546f..3ab377f897 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3184,7 +3184,7 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg); // emit instructions - if (strcmp(qstr_str(op), "label") == 0) { + if (op == MP_QSTR_label) { if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) { compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument"); return; @@ -3193,6 +3193,29 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass if (pass > PASS_1) { EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0])); } + } else if (op == MP_QSTR_align) { + if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) { + compile_syntax_error(comp, nodes[i], "inline assembler 'align' requires 1 argument"); + return; + } + if (pass > PASS_1) { + EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0])); + } + } else if (op == MP_QSTR_data) { + if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) { + compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires at least 2 arguments"); + return; + } + if (pass > PASS_1) { + machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]); + for (uint i = 1; i < n_args; i++) { + if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) { + compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires integer arguments"); + return; + } + EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[i])); + } + } } else { if (pass > PASS_1) { EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg); diff --git a/py/emit.h b/py/emit.h index 5fca153163..40f56605f9 100644 --- a/py/emit.h +++ b/py/emit.h @@ -143,6 +143,8 @@ typedef struct _emit_inline_asm_method_table_t { bool (*end_pass)(emit_inline_asm_t *emit); int (*count_params)(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params); void (*label)(emit_inline_asm_t *emit, uint label_num, qstr label_id); + void (*align)(emit_inline_asm_t *emit, uint align); + void (*data)(emit_inline_asm_t *emit, uint bytesize, uint val); void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args); } emit_inline_asm_method_table_t; diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index dabd5a8831..1ed5526631 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -104,6 +104,14 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, uint label_num, qst asm_thumb_label_assign(emit->as, label_num); } +STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, uint align) { + asm_thumb_align(emit->as, align); +} + +STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, uint bytesize, uint val) { + asm_thumb_data(emit->as, bytesize, val); +} + typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t; STATIC const reg_name_t reg_name_table[] = { {0, "r0\0"}, @@ -418,6 +426,8 @@ const emit_inline_asm_method_table_t emit_inline_thumb_method_table = { emit_inline_thumb_end_pass, emit_inline_thumb_count_params, emit_inline_thumb_label, + emit_inline_thumb_align, + emit_inline_thumb_data, emit_inline_thumb_op, }; diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 86a5f2632c..e970f58bef 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -36,7 +36,13 @@ Q(micropython) Q(byte_code) Q(native) Q(viper) + +#if MICROPY_EMIT_INLINE_THUMB Q(asm_thumb) +Q(label) +Q(align) +Q(data) +#endif Q(Ellipsis) Q(StopIteration)