Skip to content

Commit 8f7976b

Browse files
committed
py: Reduce code size of inline thumb assembler by using static tables.
Reduces stmhal by about 300 bytes ROM.
1 parent 2330fe0 commit 8f7976b

File tree

1 file changed

+70
-55
lines changed

1 file changed

+70
-55
lines changed

py/emitinlinethumb.c

Lines changed: 70 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,39 @@ STATIC const cc_name_t cc_name_table[] = {
308308
{ ASM_THUMB_CC_LE, "le" },
309309
};
310310

311+
typedef struct _format_4_op_t { byte op; char name[3]; } format_4_op_t;
312+
#define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops
313+
STATIC const format_4_op_t format_4_op_table[] = {
314+
{ X(ASM_THUMB_FORMAT_4_EOR), "eor" },
315+
{ X(ASM_THUMB_FORMAT_4_LSL), "lsl" },
316+
{ X(ASM_THUMB_FORMAT_4_LSR), "lsr" },
317+
{ X(ASM_THUMB_FORMAT_4_ASR), "asr" },
318+
{ X(ASM_THUMB_FORMAT_4_ADC), "adc" },
319+
{ X(ASM_THUMB_FORMAT_4_SBC), "sbc" },
320+
{ X(ASM_THUMB_FORMAT_4_ROR), "ror" },
321+
{ X(ASM_THUMB_FORMAT_4_TST), "tst" },
322+
{ X(ASM_THUMB_FORMAT_4_NEG), "neg" },
323+
{ X(ASM_THUMB_FORMAT_4_CMP), "cmp" },
324+
{ X(ASM_THUMB_FORMAT_4_CMN), "cmn" },
325+
{ X(ASM_THUMB_FORMAT_4_ORR), "orr" },
326+
{ X(ASM_THUMB_FORMAT_4_MUL), "mul" },
327+
{ X(ASM_THUMB_FORMAT_4_BIC), "bic" },
328+
{ X(ASM_THUMB_FORMAT_4_MVN), "mvn" },
329+
};
330+
#undef X
331+
332+
typedef struct _format_9_10_op_t { uint16_t op; char name[5]; } format_9_10_op_t;
333+
#define X(x) (x)
334+
STATIC const format_9_10_op_t format_9_10_op_table[] = {
335+
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "ldr" },
336+
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "ldrb" },
337+
{ X(ASM_THUMB_FORMAT_10_LDRH), "ldrh" },
338+
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "str" },
339+
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "strb" },
340+
{ X(ASM_THUMB_FORMAT_10_STRH), "strh" },
341+
};
342+
#undef X
343+
311344
STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
312345
// TODO perhaps make two tables:
313346
// one_args =
@@ -421,29 +454,6 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
421454
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
422455
mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
423456
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
424-
} else if (strcmp(op_str, "and_") == 0) {
425-
op_code = ASM_THUMB_FORMAT_4_AND;
426-
mp_uint_t reg_dest, reg_src;
427-
op_format_4:
428-
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
429-
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
430-
asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
431-
// TODO probably uses less ROM if these ops are in a lookup table
432-
} else if (strcmp(op_str, "eor") == 0) { op_code = ASM_THUMB_FORMAT_4_EOR; goto op_format_4;
433-
} else if (strcmp(op_str, "lsl") == 0) { op_code = ASM_THUMB_FORMAT_4_LSL; goto op_format_4;
434-
} else if (strcmp(op_str, "lsr") == 0) { op_code = ASM_THUMB_FORMAT_4_LSR; goto op_format_4;
435-
} else if (strcmp(op_str, "asr") == 0) { op_code = ASM_THUMB_FORMAT_4_ASR; goto op_format_4;
436-
} else if (strcmp(op_str, "adc") == 0) { op_code = ASM_THUMB_FORMAT_4_ADC; goto op_format_4;
437-
} else if (strcmp(op_str, "sbc") == 0) { op_code = ASM_THUMB_FORMAT_4_SBC; goto op_format_4;
438-
} else if (strcmp(op_str, "ror") == 0) { op_code = ASM_THUMB_FORMAT_4_ROR; goto op_format_4;
439-
} else if (strcmp(op_str, "tst") == 0) { op_code = ASM_THUMB_FORMAT_4_TST; goto op_format_4;
440-
} else if (strcmp(op_str, "neg") == 0) { op_code = ASM_THUMB_FORMAT_4_NEG; goto op_format_4;
441-
} else if (strcmp(op_str, "cmp") == 0) { op_code = ASM_THUMB_FORMAT_4_CMP; goto op_format_4;
442-
} else if (strcmp(op_str, "cmn") == 0) { op_code = ASM_THUMB_FORMAT_4_CMN; goto op_format_4;
443-
} else if (strcmp(op_str, "orr") == 0) { op_code = ASM_THUMB_FORMAT_4_ORR; goto op_format_4;
444-
} else if (strcmp(op_str, "mul") == 0) { op_code = ASM_THUMB_FORMAT_4_MUL; goto op_format_4;
445-
} else if (strcmp(op_str, "bic") == 0) { op_code = ASM_THUMB_FORMAT_4_BIC; goto op_format_4;
446-
} else if (strcmp(op_str, "mvn") == 0) { op_code = ASM_THUMB_FORMAT_4_MVN; goto op_format_4;
447457
} else if (strcmp(op_str, "clz") == 0) {
448458
op_code_hi = 0xfab0;
449459
op_code = 0xf080;
@@ -457,6 +467,21 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
457467
op_code = 0xf0a0;
458468
goto op_clz_rbit;
459469
} else {
470+
if (strcmp(op_str, "and_") == 0) {
471+
op_code = ASM_THUMB_FORMAT_4_AND;
472+
mp_uint_t reg_dest, reg_src;
473+
op_format_4:
474+
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
475+
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
476+
asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
477+
}
478+
// search table
479+
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_4_op_table); i++) {
480+
if (strncmp(op_str, format_4_op_table[i].name, 3) == 0 && op_str[3] == '\0') {
481+
op_code = 0x4000 | (format_4_op_table[i].op << 4);
482+
goto op_format_4;
483+
}
484+
}
460485
goto unknown_op;
461486
}
462487
} else {
@@ -493,38 +518,6 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
493518
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
494519
asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src & 0xffff);
495520
asm_thumb_movt_reg_i16(emit->as, reg_dest, (i_src >> 16) & 0x7fff);
496-
} else if (strcmp(op_str, "ldr") == 0) {
497-
op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER;
498-
mp_uint_t rlo_dest, rlo_base, i5;
499-
mp_parse_node_t pn_base, pn_offset;
500-
op_format_9_10:
501-
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
502-
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
503-
rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
504-
if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) {
505-
i5 = get_arg_i(emit, op_str, pn_offset, 0x1f);
506-
} else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH
507-
i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1;
508-
} else {
509-
i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
510-
}
511-
asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
512-
}
513-
} else if (strcmp(op_str, "ldrb") == 0) {
514-
op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER;
515-
goto op_format_9_10;
516-
} else if (strcmp(op_str, "ldrh") == 0) {
517-
op_code = ASM_THUMB_FORMAT_10_LDRH;
518-
goto op_format_9_10;
519-
} else if (strcmp(op_str, "str") == 0) {
520-
op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER;
521-
goto op_format_9_10;
522-
} else if (strcmp(op_str, "strb") == 0) {
523-
op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER;
524-
goto op_format_9_10;
525-
} else if (strcmp(op_str, "strh") == 0) {
526-
op_code = ASM_THUMB_FORMAT_10_STRH;
527-
goto op_format_9_10;
528521
} else if (strcmp(op_str, "ldrex") == 0) {
529522
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
530523
mp_parse_node_t pn_base, pn_offset;
@@ -534,6 +527,28 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
534527
asm_thumb_op32(emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
535528
}
536529
} else {
530+
// search table for ldr/str instructions
531+
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
532+
if (strcmp(op_str, format_9_10_op_table[i].name) == 0) {
533+
op_code = format_9_10_op_table[i].op;
534+
mp_parse_node_t pn_base, pn_offset;
535+
mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
536+
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
537+
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
538+
mp_uint_t i5;
539+
if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) {
540+
i5 = get_arg_i(emit, op_str, pn_offset, 0x1f);
541+
} else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH
542+
i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1;
543+
} else {
544+
i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
545+
}
546+
asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
547+
return;
548+
}
549+
break;
550+
}
551+
}
537552
goto unknown_op;
538553
}
539554
}

0 commit comments

Comments
 (0)