Skip to content

Commit 28adab3

Browse files
committed
py/emitinlinethumb: Use qstrs instead of char* for names of asm ops.
Reduces code size by 112 bytes on Thumb2 arch, and makes assembler faster because comparison can be a simple equals instead of a string compare. Not all ops have been converted, only those that were simple to convert and reduced code size.
1 parent e9d1a94 commit 28adab3

2 files changed

Lines changed: 92 additions & 47 deletions

File tree

py/emitinlinethumb.c

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,16 @@ STATIC const format_4_op_t format_4_op_table[] = {
392392
};
393393
#undef X
394394

395-
typedef struct _format_9_10_op_t { uint16_t op; char name[5]; } format_9_10_op_t;
395+
// name is actually a qstr, which should fit in 16 bits
396+
typedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t;
396397
#define X(x) (x)
397398
STATIC const format_9_10_op_t format_9_10_op_table[] = {
398-
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "ldr" },
399-
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "ldrb" },
400-
{ X(ASM_THUMB_FORMAT_10_LDRH), "ldrh" },
401-
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "str" },
402-
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "strb" },
403-
{ X(ASM_THUMB_FORMAT_10_STRH), "strh" },
399+
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr },
400+
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb },
401+
{ X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh },
402+
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_str },
403+
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_strb },
404+
{ X(ASM_THUMB_FORMAT_10_STRH), MP_QSTR_strh },
404405
};
405406
#undef X
406407

@@ -437,28 +438,28 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
437438
// floating point operations
438439
if (n_args == 2) {
439440
mp_uint_t op_code = 0x0ac0, op_code_hi;
440-
if (strcmp(op_str, "vcmp") == 0) {
441+
if (op == MP_QSTR_vcmp) {
441442
op_code_hi = 0xeeb4;
442443
op_vfp_twoargs:;
443444
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
444445
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
445446
asm_thumb_op32(emit->as,
446447
op_code_hi | ((vd & 1) << 6),
447448
op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
448-
} else if (strcmp(op_str, "vsqrt") == 0) {
449+
} else if (op == MP_QSTR_vsqrt) {
449450
op_code_hi = 0xeeb1;
450451
goto op_vfp_twoargs;
451-
} else if (strcmp(op_str, "vneg") == 0) {
452+
} else if (op == MP_QSTR_vneg) {
452453
op_code_hi = 0xeeb1;
453454
op_code = 0x0a40;
454455
goto op_vfp_twoargs;
455-
} else if (strcmp(op_str, "vcvt_f32_s32") == 0) {
456+
} else if (op == MP_QSTR_vcvt_f32_s32) {
456457
op_code_hi = 0xeeb8; // int to float
457458
goto op_vfp_twoargs;
458-
} else if (strcmp(op_str, "vcvt_s32_f32") == 0) {
459+
} else if (op == MP_QSTR_vcvt_s32_f32) {
459460
op_code_hi = 0xeebd; // float to int
460461
goto op_vfp_twoargs;
461-
} else if (strcmp(op_str, "vmrs") == 0) {
462+
} else if (op == MP_QSTR_vmrs) {
462463
mp_uint_t reg_dest;
463464
const char *reg_str0 = get_arg_str(pn_args[0]);
464465
if (strcmp(reg_str0, "APSR_nzcv") == 0) {
@@ -473,7 +474,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
473474
} else {
474475
goto unknown_op;
475476
}
476-
} else if (strcmp(op_str, "vmov") == 0) {
477+
} else if (op == MP_QSTR_vmov) {
477478
op_code_hi = 0xee00;
478479
mp_uint_t r_arm, vm;
479480
const char *reg_str = get_arg_str(pn_args[0]);
@@ -488,7 +489,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
488489
asm_thumb_op32(emit->as,
489490
op_code_hi | ((vm & 0x1e) >> 1),
490491
0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
491-
} else if (strcmp(op_str, "vldr") == 0) {
492+
} else if (op == MP_QSTR_vldr) {
492493
op_code_hi = 0xed90;
493494
op_vldr_vstr:;
494495
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
@@ -501,7 +502,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
501502
op_code_hi | rlo_base | ((vd & 1) << 6),
502503
0x0a00 | ((vd & 0x1e) << 11) | i8);
503504
}
504-
} else if (strcmp(op_str, "vstr") == 0) {
505+
} else if (op == MP_QSTR_vstr) {
505506
op_code_hi = 0xed80;
506507
goto op_vldr_vstr;
507508
} else {
@@ -529,26 +530,26 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
529530
} else
530531
#endif
531532
if (n_args == 0) {
532-
if (strcmp(op_str, "nop") == 0) {
533+
if (op == MP_QSTR_nop) {
533534
asm_thumb_op16(emit->as, ASM_THUMB_OP_NOP);
534-
} else if (strcmp(op_str, "wfi") == 0) {
535+
} else if (op == MP_QSTR_wfi) {
535536
asm_thumb_op16(emit->as, ASM_THUMB_OP_WFI);
536537
} else {
537538
goto unknown_op;
538539
}
539540

540541
} else if (n_args == 1) {
541-
if (strcmp(op_str, "b") == 0) {
542+
if (op == MP_QSTR_b) {
542543
int label_num = get_arg_label(emit, op_str, pn_args[0]);
543544
if (!asm_thumb_b_n_label(emit->as, label_num)) {
544545
goto branch_not_in_range;
545546
}
546-
} else if (strcmp(op_str, "bl") == 0) {
547+
} else if (op == MP_QSTR_bl) {
547548
int label_num = get_arg_label(emit, op_str, pn_args[0]);
548549
if (!asm_thumb_bl_label(emit->as, label_num)) {
549550
goto branch_not_in_range;
550551
}
551-
} else if (strcmp(op_str, "bx") == 0) {
552+
} else if (op == MP_QSTR_bx) {
552553
mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
553554
asm_thumb_op16(emit->as, 0x4700 | (r << 3));
554555
} else if (op_str[0] == 'b' && (op_len == 3
@@ -600,13 +601,13 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
600601
}
601602
}
602603
asm_thumb_it_cc(emit->as, cc, it_mask);
603-
} else if (strcmp(op_str, "cpsid") == 0) {
604+
} else if (op == MP_QSTR_cpsid) {
604605
// TODO check pn_args[0] == i
605606
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSID_I);
606-
} else if (strcmp(op_str, "cpsie") == 0) {
607+
} else if (op == MP_QSTR_cpsie) {
607608
// TODO check pn_args[0] == i
608609
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSIE_I);
609-
} else if (strcmp(op_str, "push") == 0) {
610+
} else if (op == MP_QSTR_push) {
610611
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
611612
if ((reglist & 0xff00) == 0) {
612613
asm_thumb_op16(emit->as, 0xb400 | reglist);
@@ -616,7 +617,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
616617
}
617618
asm_thumb_op32(emit->as, 0xe92d, reglist);
618619
}
619-
} else if (strcmp(op_str, "pop") == 0) {
620+
} else if (op == MP_QSTR_pop) {
620621
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
621622
if ((reglist & 0xff00) == 0) {
622623
asm_thumb_op16(emit->as, 0xbc00 | reglist);
@@ -634,28 +635,28 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
634635
if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
635636
// second arg is a register (or should be)
636637
mp_uint_t op_code, op_code_hi;
637-
if (strcmp(op_str, "mov") == 0) {
638+
if (op == MP_QSTR_mov) {
638639
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
639640
mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
640641
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
641-
} else if (ARMV7M && strcmp(op_str, "clz") == 0) {
642+
} else if (ARMV7M && op == MP_QSTR_clz) {
642643
op_code_hi = 0xfab0;
643644
op_code = 0xf080;
644645
mp_uint_t rd, rm;
645646
op_clz_rbit:
646647
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
647648
rm = get_arg_reg(emit, op_str, pn_args[1], 15);
648649
asm_thumb_op32(emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
649-
} else if (ARMV7M && strcmp(op_str, "rbit") == 0) {
650+
} else if (ARMV7M && op == MP_QSTR_rbit) {
650651
op_code_hi = 0xfa90;
651652
op_code = 0xf0a0;
652653
goto op_clz_rbit;
653-
} else if (ARMV7M && strcmp(op_str, "mrs") == 0){
654+
} else if (ARMV7M && op == MP_QSTR_mrs){
654655
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);
655656
mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);
656657
asm_thumb_op32(emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
657658
} else {
658-
if (strcmp(op_str, "and_") == 0) {
659+
if (op == MP_QSTR_and_) {
659660
op_code = ASM_THUMB_FORMAT_4_AND;
660661
mp_uint_t reg_dest, reg_src;
661662
op_format_4:
@@ -676,39 +677,39 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
676677
} else {
677678
// second arg is not a register
678679
mp_uint_t op_code;
679-
if (strcmp(op_str, "mov") == 0) {
680+
if (op == MP_QSTR_mov) {
680681
op_code = ASM_THUMB_FORMAT_3_MOV;
681682
mp_uint_t rlo_dest, i8_src;
682683
op_format_3:
683684
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
684685
i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
685686
asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
686-
} else if (strcmp(op_str, "cmp") == 0) {
687+
} else if (op == MP_QSTR_cmp) {
687688
op_code = ASM_THUMB_FORMAT_3_CMP;
688689
goto op_format_3;
689-
} else if (strcmp(op_str, "add") == 0) {
690+
} else if (op == MP_QSTR_add) {
690691
op_code = ASM_THUMB_FORMAT_3_ADD;
691692
goto op_format_3;
692-
} else if (strcmp(op_str, "sub") == 0) {
693+
} else if (op == MP_QSTR_sub) {
693694
op_code = ASM_THUMB_FORMAT_3_SUB;
694695
goto op_format_3;
695-
} else if (ARMV7M && strcmp(op_str, "movw") == 0) {
696+
} else if (ARMV7M && op == MP_QSTR_movw) {
696697
op_code = ASM_THUMB_OP_MOVW;
697698
mp_uint_t reg_dest;
698699
op_movw_movt:
699700
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
700701
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
701702
asm_thumb_mov_reg_i16(emit->as, op_code, reg_dest, i_src);
702-
} else if (ARMV7M && strcmp(op_str, "movt") == 0) {
703+
} else if (ARMV7M && op == MP_QSTR_movt) {
703704
op_code = ASM_THUMB_OP_MOVT;
704705
goto op_movw_movt;
705-
} else if (ARMV7M && strcmp(op_str, "movwt") == 0) {
706+
} else if (ARMV7M && op == MP_QSTR_movwt) {
706707
// this is a convenience instruction
707708
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
708709
uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
709710
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
710711
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
711-
} else if (ARMV7M && strcmp(op_str, "ldrex") == 0) {
712+
} else if (ARMV7M && op == MP_QSTR_ldrex) {
712713
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
713714
mp_parse_node_t pn_base, pn_offset;
714715
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
@@ -719,7 +720,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
719720
} else {
720721
// search table for ldr/str instructions
721722
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
722-
if (strcmp(op_str, format_9_10_op_table[i].name) == 0) {
723+
if (op == format_9_10_op_table[i].name) {
723724
op_code = format_9_10_op_table[i].op;
724725
mp_parse_node_t pn_base, pn_offset;
725726
mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
@@ -745,21 +746,21 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
745746

746747
} else if (n_args == 3) {
747748
mp_uint_t op_code;
748-
if (strcmp(op_str, "lsl") == 0) {
749+
if (op == MP_QSTR_lsl) {
749750
op_code = ASM_THUMB_FORMAT_1_LSL;
750751
mp_uint_t rlo_dest, rlo_src, i5;
751752
op_format_1:
752753
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
753754
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
754755
i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
755756
asm_thumb_format_1(emit->as, op_code, rlo_dest, rlo_src, i5);
756-
} else if (strcmp(op_str, "lsr") == 0) {
757+
} else if (op == MP_QSTR_lsr) {
757758
op_code = ASM_THUMB_FORMAT_1_LSR;
758759
goto op_format_1;
759-
} else if (strcmp(op_str, "asr") == 0) {
760+
} else if (op == MP_QSTR_asr) {
760761
op_code = ASM_THUMB_FORMAT_1_ASR;
761762
goto op_format_1;
762-
} else if (strcmp(op_str, "add") == 0) {
763+
} else if (op == MP_QSTR_add) {
763764
op_code = ASM_THUMB_FORMAT_2_ADD;
764765
mp_uint_t rlo_dest, rlo_src;
765766
op_format_2:
@@ -774,21 +775,21 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
774775
src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
775776
}
776777
asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
777-
} else if (ARMV7M && strcmp(op_str, "sdiv") == 0) {
778+
} else if (ARMV7M && op == MP_QSTR_sdiv) {
778779
op_code = 0xfb90; // sdiv high part
779780
mp_uint_t rd, rn, rm;
780781
op_sdiv_udiv:
781782
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
782783
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
783784
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
784785
asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
785-
} else if (ARMV7M && strcmp(op_str, "udiv") == 0) {
786+
} else if (ARMV7M && op == MP_QSTR_udiv) {
786787
op_code = 0xfbb0; // udiv high part
787788
goto op_sdiv_udiv;
788-
} else if (strcmp(op_str, "sub") == 0) {
789+
} else if (op == MP_QSTR_sub) {
789790
op_code = ASM_THUMB_FORMAT_2_SUB;
790791
goto op_format_2;
791-
} else if (ARMV7M && strcmp(op_str, "strex") == 0) {
792+
} else if (ARMV7M && op == MP_QSTR_strex) {
792793
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
793794
mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
794795
mp_parse_node_t pn_base, pn_offset;

py/qstrdefs.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,50 @@ Q(label)
114114
Q(align)
115115
Q(data)
116116
Q(uint)
117+
Q(nop)
118+
Q(mov)
119+
Q(and_)
120+
Q(cmp)
121+
Q(add)
122+
Q(sub)
123+
Q(lsl)
124+
Q(lsr)
125+
Q(asr)
126+
Q(ldr)
127+
Q(ldrb)
128+
Q(ldrh)
129+
Q(str)
130+
Q(strb)
131+
Q(strh)
132+
Q(b)
133+
Q(bl)
134+
Q(bx)
135+
Q(push)
136+
Q(pop)
137+
Q(cpsid)
138+
Q(cpsie)
139+
Q(wfi)
140+
Q(clz)
141+
Q(rbit)
142+
Q(movw)
143+
Q(movt)
144+
Q(movwt)
145+
Q(mrs)
146+
Q(sdiv)
147+
Q(udiv)
148+
Q(ldrex)
149+
Q(strex)
150+
#if MICROPY_EMIT_INLINE_THUMB_FLOAT
151+
Q(vcmp)
152+
Q(vneg)
153+
Q(vcvt_f32_s32)
154+
Q(vcvt_s32_f32)
155+
Q(vsqrt)
156+
Q(vmov)
157+
Q(vmrs)
158+
Q(vldr)
159+
Q(vstr)
160+
#endif
117161
#endif
118162

119163
Q(builtins)

0 commit comments

Comments
 (0)