py/emitinlinethumb: Add support for MRS instruction.
Only IPSR and BASEPRI special registers supported at the moment, but easy to extend in the future.
This commit is contained in:
parent
1f0aaece3a
commit
e242b1785f
@ -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;
|
||||
|
11
tests/inlineasm/asmspecialregs.py
Normal file
11
tests/inlineasm/asmspecialregs.py
Normal file
@ -0,0 +1,11 @@
|
||||
@micropython.asm_thumb
|
||||
def getIPSR():
|
||||
mrs(r0, IPSR)
|
||||
|
||||
@micropython.asm_thumb
|
||||
def getBASEPRI():
|
||||
mrs(r0, BASEPRI)
|
||||
|
||||
print(getBASEPRI())
|
||||
print(getIPSR())
|
||||
|
2
tests/inlineasm/asmspecialregs.py.exp
Normal file
2
tests/inlineasm/asmspecialregs.py.exp
Normal file
@ -0,0 +1,2 @@
|
||||
0
|
||||
0
|
Loading…
Reference in New Issue
Block a user