From e242b1785f9e25b36f5d225652c679cd7cec6ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20S=C3=B6lver?= Date: Sat, 21 Nov 2015 22:27:54 +0100 Subject: [PATCH] py/emitinlinethumb: Add support for MRS instruction. Only IPSR and BASEPRI special registers supported at the moment, but easy to extend in the future. --- py/emitinlinethumb.c | 25 +++++++++++++++++++++++++ tests/inlineasm/asmspecialregs.py | 11 +++++++++++ tests/inlineasm/asmspecialregs.py.exp | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 tests/inlineasm/asmspecialregs.py create mode 100644 tests/inlineasm/asmspecialregs.py.exp diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 847210006f..84366003ea 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; diff --git a/tests/inlineasm/asmspecialregs.py b/tests/inlineasm/asmspecialregs.py new file mode 100644 index 0000000000..edfe4c2bd7 --- /dev/null +++ b/tests/inlineasm/asmspecialregs.py @@ -0,0 +1,11 @@ +@micropython.asm_thumb +def getIPSR(): + mrs(r0, IPSR) + +@micropython.asm_thumb +def getBASEPRI(): + mrs(r0, BASEPRI) + +print(getBASEPRI()) +print(getIPSR()) + diff --git a/tests/inlineasm/asmspecialregs.py.exp b/tests/inlineasm/asmspecialregs.py.exp new file mode 100644 index 0000000000..aa47d0d46d --- /dev/null +++ b/tests/inlineasm/asmspecialregs.py.exp @@ -0,0 +1,2 @@ +0 +0