Skip to content

Commit a7fd786

Browse files
committed
py/emitinline: Embed entire asm struct instead of a pointer to it.
This reduces fragmentation, and memory use by 1 word. But more importantly it means the emit_inline_asm_t struct now "derives" from mp_asm_base.
1 parent 3a4ebf5 commit a7fd786

2 files changed

Lines changed: 69 additions & 71 deletions

File tree

py/emitinlinethumb.c

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ typedef enum {
4343
} pn_kind_t;
4444

4545
struct _emit_inline_asm_t {
46+
asm_thumb_t as;
4647
uint16_t pass;
4748
scope_t *scope;
4849
mp_obj_t *error_slot;
4950
mp_uint_t max_num_labels;
5051
qstr *label_lookup;
51-
asm_thumb_t *as;
5252
};
5353

5454
STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) {
@@ -61,17 +61,16 @@ STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {
6161

6262
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
6363
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
64+
memset(&emit->as, 0, sizeof(emit->as));
65+
mp_asm_base_init(&emit->as.base, max_num_labels);
6466
emit->max_num_labels = max_num_labels;
6567
emit->label_lookup = m_new(qstr, max_num_labels);
66-
emit->as = m_new0(asm_thumb_t, 1);
67-
mp_asm_base_init(&emit->as->base, max_num_labels);
6868
return emit;
6969
}
7070

7171
void emit_inline_thumb_free(emit_inline_asm_t *emit) {
7272
m_del(qstr, emit->label_lookup, emit->max_num_labels);
73-
mp_asm_base_deinit(&emit->as->base, false);
74-
m_del_obj(asm_thumb_t, emit->as);
73+
mp_asm_base_deinit(&emit->as.base, false);
7574
m_del_obj(emit_inline_asm_t, emit);
7675
}
7776

@@ -82,18 +81,18 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa
8281
if (emit->pass == MP_PASS_CODE_SIZE) {
8382
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
8483
}
85-
mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
86-
asm_thumb_entry(emit->as, 0);
84+
mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
85+
asm_thumb_entry(&emit->as, 0);
8786
}
8887

8988
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
90-
asm_thumb_exit(emit->as);
91-
asm_thumb_end_pass(emit->as);
89+
asm_thumb_exit(&emit->as);
90+
asm_thumb_end_pass(&emit->as);
9291

9392
if (emit->pass == MP_PASS_EMIT) {
94-
void *f = mp_asm_base_get_code(&emit->as->base);
93+
void *f = mp_asm_base_get_code(&emit->as.base);
9594
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
96-
mp_asm_base_get_code_size(&emit->as->base), NULL, emit->scope->num_pos_args, 0, type_sig);
95+
mp_asm_base_get_code_size(&emit->as.base), NULL, emit->scope->num_pos_args, 0, type_sig);
9796
}
9897
}
9998

@@ -127,16 +126,16 @@ STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num
127126
}
128127
}
129128
emit->label_lookup[label_num] = label_id;
130-
mp_asm_base_label_assign(&emit->as->base, label_num);
129+
mp_asm_base_label_assign(&emit->as.base, label_num);
131130
return true;
132131
}
133132

134133
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, mp_uint_t align) {
135-
mp_asm_base_align(&emit->as->base, align);
134+
mp_asm_base_align(&emit->as.base, align);
136135
}
137136

138137
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
139-
mp_asm_base_data(&emit->as->base, bytesize, val);
138+
mp_asm_base_data(&emit->as.base, bytesize, val);
140139
}
141140

142141
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
@@ -445,7 +444,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
445444
op_vfp_twoargs:;
446445
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
447446
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
448-
asm_thumb_op32(emit->as,
447+
asm_thumb_op32(&emit->as,
449448
op_code_hi | ((vd & 1) << 6),
450449
op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
451450
} else if (op == MP_QSTR_vsqrt) {
@@ -472,7 +471,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
472471
const char *reg_str1 = get_arg_str(pn_args[1]);
473472
if (strcmp(reg_str1, "FPSCR") == 0) {
474473
// FP status to ARM reg
475-
asm_thumb_op32(emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));
474+
asm_thumb_op32(&emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));
476475
} else {
477476
goto unknown_op;
478477
}
@@ -488,7 +487,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
488487
vm = get_arg_vfpreg(emit, op_str, pn_args[0]);
489488
r_arm = get_arg_reg(emit, op_str, pn_args[1], 15);
490489
}
491-
asm_thumb_op32(emit->as,
490+
asm_thumb_op32(&emit->as,
492491
op_code_hi | ((vm & 0x1e) >> 1),
493492
0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
494493
} else if (op == MP_QSTR_vldr) {
@@ -500,7 +499,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
500499
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
501500
mp_uint_t i8;
502501
i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2;
503-
asm_thumb_op32(emit->as,
502+
asm_thumb_op32(&emit->as,
504503
op_code_hi | rlo_base | ((vd & 1) << 6),
505504
0x0a00 | ((vd & 0x1e) << 11) | i8);
506505
}
@@ -519,7 +518,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
519518
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
520519
mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]);
521520
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]);
522-
asm_thumb_op32(emit->as,
521+
asm_thumb_op32(&emit->as,
523522
op_code_hi | ((vd & 1) << 6) | (vn >> 1),
524523
op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7));
525524
return;
@@ -533,27 +532,27 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
533532
#endif
534533
if (n_args == 0) {
535534
if (op == MP_QSTR_nop) {
536-
asm_thumb_op16(emit->as, ASM_THUMB_OP_NOP);
535+
asm_thumb_op16(&emit->as, ASM_THUMB_OP_NOP);
537536
} else if (op == MP_QSTR_wfi) {
538-
asm_thumb_op16(emit->as, ASM_THUMB_OP_WFI);
537+
asm_thumb_op16(&emit->as, ASM_THUMB_OP_WFI);
539538
} else {
540539
goto unknown_op;
541540
}
542541

543542
} else if (n_args == 1) {
544543
if (op == MP_QSTR_b) {
545544
int label_num = get_arg_label(emit, op_str, pn_args[0]);
546-
if (!asm_thumb_b_n_label(emit->as, label_num)) {
545+
if (!asm_thumb_b_n_label(&emit->as, label_num)) {
547546
goto branch_not_in_range;
548547
}
549548
} else if (op == MP_QSTR_bl) {
550549
int label_num = get_arg_label(emit, op_str, pn_args[0]);
551-
if (!asm_thumb_bl_label(emit->as, label_num)) {
550+
if (!asm_thumb_bl_label(&emit->as, label_num)) {
552551
goto branch_not_in_range;
553552
}
554553
} else if (op == MP_QSTR_bx) {
555554
mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
556-
asm_thumb_op16(emit->as, 0x4700 | (r << 3));
555+
asm_thumb_op16(&emit->as, 0x4700 | (r << 3));
557556
} else if (op_str[0] == 'b' && (op_len == 3
558557
|| (op_len == 5 && op_str[3] == '_'
559558
&& (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) {
@@ -567,7 +566,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
567566
goto unknown_op;
568567
}
569568
int label_num = get_arg_label(emit, op_str, pn_args[0]);
570-
if (!asm_thumb_bcc_nw_label(emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
569+
if (!asm_thumb_bcc_nw_label(&emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
571570
goto branch_not_in_range;
572571
}
573572
} else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') {
@@ -602,32 +601,32 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
602601
goto unknown_op;
603602
}
604603
}
605-
asm_thumb_it_cc(emit->as, cc, it_mask);
604+
asm_thumb_it_cc(&emit->as, cc, it_mask);
606605
} else if (op == MP_QSTR_cpsid) {
607606
// TODO check pn_args[0] == i
608-
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSID_I);
607+
asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSID_I);
609608
} else if (op == MP_QSTR_cpsie) {
610609
// TODO check pn_args[0] == i
611-
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSIE_I);
610+
asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSIE_I);
612611
} else if (op == MP_QSTR_push) {
613612
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
614613
if ((reglist & 0xff00) == 0) {
615-
asm_thumb_op16(emit->as, 0xb400 | reglist);
614+
asm_thumb_op16(&emit->as, 0xb400 | reglist);
616615
} else {
617616
if (!ARMV7M) {
618617
goto unknown_op;
619618
}
620-
asm_thumb_op32(emit->as, 0xe92d, reglist);
619+
asm_thumb_op32(&emit->as, 0xe92d, reglist);
621620
}
622621
} else if (op == MP_QSTR_pop) {
623622
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
624623
if ((reglist & 0xff00) == 0) {
625-
asm_thumb_op16(emit->as, 0xbc00 | reglist);
624+
asm_thumb_op16(&emit->as, 0xbc00 | reglist);
626625
} else {
627626
if (!ARMV7M) {
628627
goto unknown_op;
629628
}
630-
asm_thumb_op32(emit->as, 0xe8bd, reglist);
629+
asm_thumb_op32(&emit->as, 0xe8bd, reglist);
631630
}
632631
} else {
633632
goto unknown_op;
@@ -640,31 +639,31 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
640639
if (op == MP_QSTR_mov) {
641640
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
642641
mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
643-
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
642+
asm_thumb_mov_reg_reg(&emit->as, reg_dest, reg_src);
644643
} else if (ARMV7M && op == MP_QSTR_clz) {
645644
op_code_hi = 0xfab0;
646645
op_code = 0xf080;
647646
mp_uint_t rd, rm;
648647
op_clz_rbit:
649648
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
650649
rm = get_arg_reg(emit, op_str, pn_args[1], 15);
651-
asm_thumb_op32(emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
650+
asm_thumb_op32(&emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
652651
} else if (ARMV7M && op == MP_QSTR_rbit) {
653652
op_code_hi = 0xfa90;
654653
op_code = 0xf0a0;
655654
goto op_clz_rbit;
656655
} else if (ARMV7M && op == MP_QSTR_mrs){
657656
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);
658657
mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);
659-
asm_thumb_op32(emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
658+
asm_thumb_op32(&emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
660659
} else {
661660
if (op == MP_QSTR_and_) {
662661
op_code = ASM_THUMB_FORMAT_4_AND;
663662
mp_uint_t reg_dest, reg_src;
664663
op_format_4:
665664
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
666665
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
667-
asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
666+
asm_thumb_format_4(&emit->as, op_code, reg_dest, reg_src);
668667
return;
669668
}
670669
// search table for ALU ops
@@ -685,7 +684,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
685684
op_format_3:
686685
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
687686
i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
688-
asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
687+
asm_thumb_format_3(&emit->as, op_code, rlo_dest, i8_src);
689688
} else if (op == MP_QSTR_cmp) {
690689
op_code = ASM_THUMB_FORMAT_3_CMP;
691690
goto op_format_3;
@@ -701,23 +700,23 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
701700
op_movw_movt:
702701
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
703702
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
704-
asm_thumb_mov_reg_i16(emit->as, op_code, reg_dest, i_src);
703+
asm_thumb_mov_reg_i16(&emit->as, op_code, reg_dest, i_src);
705704
} else if (ARMV7M && op == MP_QSTR_movt) {
706705
op_code = ASM_THUMB_OP_MOVT;
707706
goto op_movw_movt;
708707
} else if (ARMV7M && op == MP_QSTR_movwt) {
709708
// this is a convenience instruction
710709
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
711710
uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
712-
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
713-
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
711+
asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
712+
asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
714713
} else if (ARMV7M && op == MP_QSTR_ldrex) {
715714
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
716715
mp_parse_node_t pn_base, pn_offset;
717716
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
718717
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
719718
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
720-
asm_thumb_op32(emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
719+
asm_thumb_op32(&emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
721720
}
722721
} else {
723722
// search table for ldr/str instructions
@@ -736,7 +735,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
736735
} else {
737736
i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
738737
}
739-
asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
738+
asm_thumb_format_9_10(&emit->as, op_code, rlo_dest, rlo_base, i5);
740739
return;
741740
}
742741
break;
@@ -755,7 +754,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
755754
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
756755
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
757756
i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
758-
asm_thumb_format_1(emit->as, op_code, rlo_dest, rlo_src, i5);
757+
asm_thumb_format_1(&emit->as, op_code, rlo_dest, rlo_src, i5);
759758
} else if (op == MP_QSTR_lsr) {
760759
op_code = ASM_THUMB_FORMAT_1_LSR;
761760
goto op_format_1;
@@ -776,15 +775,15 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
776775
op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;
777776
src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
778777
}
779-
asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
778+
asm_thumb_format_2(&emit->as, op_code, rlo_dest, rlo_src, src_b);
780779
} else if (ARMV7M && op == MP_QSTR_sdiv) {
781780
op_code = 0xfb90; // sdiv high part
782781
mp_uint_t rd, rn, rm;
783782
op_sdiv_udiv:
784783
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
785784
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
786785
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
787-
asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
786+
asm_thumb_op32(&emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
788787
} else if (ARMV7M && op == MP_QSTR_udiv) {
789788
op_code = 0xfbb0; // udiv high part
790789
goto op_sdiv_udiv;
@@ -798,7 +797,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
798797
if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
799798
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
800799
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
801-
asm_thumb_op32(emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);
800+
asm_thumb_op32(&emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);
802801
}
803802
} else {
804803
goto unknown_op;

0 commit comments

Comments
 (0)