Skip to content

Commit e813541

Browse files
committed
py: Add option for inline assembler to support ARMv7-M instructions.
Cortex-M0, M0+ and M1 only have ARMv6-M Thumb/Thumb2 instructions. M3, M4 and M7 have a superset of these, named ARMv7-M. This patch adds a config option to enable support of the superset of instructions.
1 parent 4bf3f2d commit e813541

2 files changed

Lines changed: 25 additions & 11 deletions

File tree

py/emitinlinethumb.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ STATIC const format_vfp_op_t format_vfp_op_table[] = {
392392
};
393393
#endif
394394

395+
// shorthand alias for whether we allow ARMv7-M instructions
396+
#define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M
397+
395398
STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
396399
// TODO perhaps make two tables:
397400
// one_args =
@@ -527,7 +530,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
527530
asm_thumb_op16(emit->as, 0x4700 | (r << 3));
528531
} else if (op_str[0] == 'b' && (op_len == 3
529532
|| (op_len == 5 && op_str[3] == '_'
530-
&& (op_str[4] == 'n' || op_str[4] == 'w')))) {
533+
&& (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) {
531534
mp_uint_t cc = -1;
532535
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
533536
if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
@@ -541,7 +544,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
541544
if (!asm_thumb_bcc_nw_label(emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
542545
goto branch_not_in_range;
543546
}
544-
} else if (op_str[0] == 'i' && op_str[1] == 't') {
547+
} else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') {
545548
const char *arg_str = get_arg_str(pn_args[0]);
546549
mp_uint_t cc = -1;
547550
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
@@ -585,13 +588,19 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
585588
if ((reglist & 0xff00) == 0) {
586589
asm_thumb_op16(emit->as, 0xb400 | reglist);
587590
} else {
591+
if (!ARMV7M) {
592+
goto unknown_op;
593+
}
588594
asm_thumb_op32(emit->as, 0xe92d, reglist);
589595
}
590596
} else if (strcmp(op_str, "pop") == 0) {
591597
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
592598
if ((reglist & 0xff00) == 0) {
593599
asm_thumb_op16(emit->as, 0xbc00 | reglist);
594600
} else {
601+
if (!ARMV7M) {
602+
goto unknown_op;
603+
}
595604
asm_thumb_op32(emit->as, 0xe8bd, reglist);
596605
}
597606
} else {
@@ -606,15 +615,15 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
606615
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
607616
mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
608617
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
609-
} else if (strcmp(op_str, "clz") == 0) {
618+
} else if (ARMV7M && strcmp(op_str, "clz") == 0) {
610619
op_code_hi = 0xfab0;
611620
op_code = 0xf080;
612621
mp_uint_t rd, rm;
613622
op_clz_rbit:
614623
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
615624
rm = get_arg_reg(emit, op_str, pn_args[1], 15);
616625
asm_thumb_op32(emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
617-
} else if (strcmp(op_str, "rbit") == 0) {
626+
} else if (ARMV7M && strcmp(op_str, "rbit") == 0) {
618627
op_code_hi = 0xfa90;
619628
op_code = 0xf0a0;
620629
goto op_clz_rbit;
@@ -656,24 +665,24 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
656665
} else if (strcmp(op_str, "sub") == 0) {
657666
op_code = ASM_THUMB_FORMAT_3_SUB;
658667
goto op_format_3;
659-
} else if (strcmp(op_str, "movw") == 0) {
668+
} else if (ARMV7M && strcmp(op_str, "movw") == 0) {
660669
op_code = ASM_THUMB_OP_MOVW;
661670
mp_uint_t reg_dest;
662671
op_movw_movt:
663672
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
664673
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
665674
asm_thumb_mov_reg_i16(emit->as, op_code, reg_dest, i_src);
666-
} else if (strcmp(op_str, "movt") == 0) {
675+
} else if (ARMV7M && strcmp(op_str, "movt") == 0) {
667676
op_code = ASM_THUMB_OP_MOVT;
668677
goto op_movw_movt;
669-
} else if (strcmp(op_str, "movwt") == 0) {
678+
} else if (ARMV7M && strcmp(op_str, "movwt") == 0) {
670679
// this is a convenience instruction
671680
// we clear the MSB since it might be set from extracting the small int value
672681
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
673682
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
674683
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
675684
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0x7fff);
676-
} else if (strcmp(op_str, "ldrex") == 0) {
685+
} else if (ARMV7M && strcmp(op_str, "ldrex") == 0) {
677686
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
678687
mp_parse_node_t pn_base, pn_offset;
679688
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
@@ -725,21 +734,21 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
725734
src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
726735
}
727736
asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
728-
} else if (strcmp(op_str, "sdiv") == 0) {
737+
} else if (ARMV7M && strcmp(op_str, "sdiv") == 0) {
729738
op_code = 0xfb90; // sdiv high part
730739
mp_uint_t rd, rn, rm;
731740
op_sdiv_udiv:
732741
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
733742
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
734743
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
735744
asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
736-
} else if (strcmp(op_str, "udiv") == 0) {
745+
} else if (ARMV7M && strcmp(op_str, "udiv") == 0) {
737746
op_code = 0xfbb0; // udiv high part
738747
goto op_sdiv_udiv;
739748
} else if (strcmp(op_str, "sub") == 0) {
740749
op_code = ASM_THUMB_FORMAT_2_SUB;
741750
goto op_format_2;
742-
} else if (strcmp(op_str, "strex") == 0) {
751+
} else if (ARMV7M && strcmp(op_str, "strex") == 0) {
743752
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
744753
mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
745754
mp_parse_node_t pn_base, pn_offset;

py/mpconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@
199199
#define MICROPY_EMIT_INLINE_THUMB (0)
200200
#endif
201201

202+
// Whether to enable ARMv7-M instruction support in the Thumb2 inline assembler
203+
#ifndef MICROPY_EMIT_INLINE_THUMB_ARMV7M
204+
#define MICROPY_EMIT_INLINE_THUMB_ARMV7M (1)
205+
#endif
206+
202207
// Whether to enable float support in the Thumb2 inline assembler
203208
#ifndef MICROPY_EMIT_INLINE_THUMB_FLOAT
204209
#define MICROPY_EMIT_INLINE_THUMB_FLOAT (1)

0 commit comments

Comments
 (0)