summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/asmthumb.c14
-rw-r--r--py/asmthumb.h3
-rw-r--r--py/compile.c25
-rw-r--r--py/emit.h2
-rw-r--r--py/emitinlinethumb.c10
-rw-r--r--py/qstrdefs.h6
6 files changed, 59 insertions, 1 deletions
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)