diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 847210006f55b82520f1b3660f6fd7868d6c265f..84366003eaafaa709ac86538dda949043ecc5c83 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 0000000000000000000000000000000000000000..edfe4c2bd7e0724ba6632889ca3147853f909fc2
--- /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 0000000000000000000000000000000000000000..aa47d0d46d47a06090f436b0b851b76bb6f3b6e2
--- /dev/null
+++ b/tests/inlineasm/asmspecialregs.py.exp
@@ -0,0 +1,2 @@
+0
+0