aboutsummaryrefslogtreecommitdiff
path: root/py/emitinlinethumb.c
diff options
context:
space:
mode:
authorHenrik Sölver <henrik.solver@gmail.com>2015-11-21 22:27:54 +0100
committerDamien George <damien.p.george@gmail.com>2015-12-10 17:32:54 +0000
commite242b1785f9e25b36f5d225652c679cd7cec6ec0 (patch)
tree3a715a4628f9c1965943d76e574b5160901eca98 /py/emitinlinethumb.c
parent1f0aaece3ab7ab578de7e227ce46c45129b6b51e (diff)
py/emitinlinethumb: Add support for MRS instruction.
Only IPSR and BASEPRI special registers supported at the moment, but easy to extend in the future.
Diffstat (limited to 'py/emitinlinethumb.c')
-rw-r--r--py/emitinlinethumb.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 847210006..84366003e 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -161,6 +161,13 @@ STATIC const reg_name_t reg_name_table[] = {
{15, "pc\0"},
};
+#define MAX_SPECIAL_REGISTER_NAME_LENGTH 7
+typedef struct _special_reg_name_t { byte reg; char name[MAX_SPECIAL_REGISTER_NAME_LENGTH + 1]; } special_reg_name_t;
+STATIC const special_reg_name_t special_reg_name_table[] = {
+ {5, "IPSR"},
+ {17, "BASEPRI"},
+};
+
// 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) {
@@ -196,6 +203,20 @@ 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) {
+ 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];
+ if (strcmp(r->name, reg_str) == 0) {
+ return r->reg;
+ }
+ }
+ emit_inline_thumb_error_exc(emit,
+ mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
+ "'%s' expects a special register", op));
+ return 0;
+}
+
#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) {
const char *reg_str = get_arg_str(pn);
@@ -627,6 +648,10 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
op_code_hi = 0xfa90;
op_code = 0xf0a0;
goto op_clz_rbit;
+ } else if (ARMV7M && strcmp(op_str, "mrs") == 0){
+ mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);
+ mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);
+ asm_thumb_op32(emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
} else {
if (strcmp(op_str, "and_") == 0) {
op_code = ASM_THUMB_FORMAT_4_AND;