@@ -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+
311344STATIC 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