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.
This commit is contained in:
parent
e9d1a94bf0
commit
28adab36c7
|
@ -392,15 +392,16 @@ STATIC const format_4_op_t format_4_op_table[] = {
|
|||
};
|
||||
#undef X
|
||||
|
||||
typedef struct _format_9_10_op_t { uint16_t op; char name[5]; } format_9_10_op_t;
|
||||
// name is actually a qstr, which should fit in 16 bits
|
||||
typedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t;
|
||||
#define X(x) (x)
|
||||
STATIC const format_9_10_op_t format_9_10_op_table[] = {
|
||||
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "ldr" },
|
||||
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "ldrb" },
|
||||
{ X(ASM_THUMB_FORMAT_10_LDRH), "ldrh" },
|
||||
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), "str" },
|
||||
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), "strb" },
|
||||
{ X(ASM_THUMB_FORMAT_10_STRH), "strh" },
|
||||
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr },
|
||||
{ X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb },
|
||||
{ X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh },
|
||||
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_str },
|
||||
{ X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_strb },
|
||||
{ X(ASM_THUMB_FORMAT_10_STRH), MP_QSTR_strh },
|
||||
};
|
||||
#undef X
|
||||
|
||||
|
@ -437,7 +438,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
// floating point operations
|
||||
if (n_args == 2) {
|
||||
mp_uint_t op_code = 0x0ac0, op_code_hi;
|
||||
if (strcmp(op_str, "vcmp") == 0) {
|
||||
if (op == MP_QSTR_vcmp) {
|
||||
op_code_hi = 0xeeb4;
|
||||
op_vfp_twoargs:;
|
||||
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
||||
|
@ -445,20 +446,20 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
asm_thumb_op32(emit->as,
|
||||
op_code_hi | ((vd & 1) << 6),
|
||||
op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
|
||||
} else if (strcmp(op_str, "vsqrt") == 0) {
|
||||
} else if (op == MP_QSTR_vsqrt) {
|
||||
op_code_hi = 0xeeb1;
|
||||
goto op_vfp_twoargs;
|
||||
} else if (strcmp(op_str, "vneg") == 0) {
|
||||
} else if (op == MP_QSTR_vneg) {
|
||||
op_code_hi = 0xeeb1;
|
||||
op_code = 0x0a40;
|
||||
goto op_vfp_twoargs;
|
||||
} else if (strcmp(op_str, "vcvt_f32_s32") == 0) {
|
||||
} else if (op == MP_QSTR_vcvt_f32_s32) {
|
||||
op_code_hi = 0xeeb8; // int to float
|
||||
goto op_vfp_twoargs;
|
||||
} else if (strcmp(op_str, "vcvt_s32_f32") == 0) {
|
||||
} else if (op == MP_QSTR_vcvt_s32_f32) {
|
||||
op_code_hi = 0xeebd; // float to int
|
||||
goto op_vfp_twoargs;
|
||||
} else if (strcmp(op_str, "vmrs") == 0) {
|
||||
} else if (op == MP_QSTR_vmrs) {
|
||||
mp_uint_t reg_dest;
|
||||
const char *reg_str0 = get_arg_str(pn_args[0]);
|
||||
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
|
|||
} else {
|
||||
goto unknown_op;
|
||||
}
|
||||
} else if (strcmp(op_str, "vmov") == 0) {
|
||||
} else if (op == MP_QSTR_vmov) {
|
||||
op_code_hi = 0xee00;
|
||||
mp_uint_t r_arm, vm;
|
||||
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
|
|||
asm_thumb_op32(emit->as,
|
||||
op_code_hi | ((vm & 0x1e) >> 1),
|
||||
0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
|
||||
} else if (strcmp(op_str, "vldr") == 0) {
|
||||
} else if (op == MP_QSTR_vldr) {
|
||||
op_code_hi = 0xed90;
|
||||
op_vldr_vstr:;
|
||||
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
|
|||
op_code_hi | rlo_base | ((vd & 1) << 6),
|
||||
0x0a00 | ((vd & 0x1e) << 11) | i8);
|
||||
}
|
||||
} else if (strcmp(op_str, "vstr") == 0) {
|
||||
} else if (op == MP_QSTR_vstr) {
|
||||
op_code_hi = 0xed80;
|
||||
goto op_vldr_vstr;
|
||||
} else {
|
||||
|
@ -529,26 +530,26 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
} else
|
||||
#endif
|
||||
if (n_args == 0) {
|
||||
if (strcmp(op_str, "nop") == 0) {
|
||||
if (op == MP_QSTR_nop) {
|
||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_NOP);
|
||||
} else if (strcmp(op_str, "wfi") == 0) {
|
||||
} else if (op == MP_QSTR_wfi) {
|
||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_WFI);
|
||||
} else {
|
||||
goto unknown_op;
|
||||
}
|
||||
|
||||
} else if (n_args == 1) {
|
||||
if (strcmp(op_str, "b") == 0) {
|
||||
if (op == MP_QSTR_b) {
|
||||
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
||||
if (!asm_thumb_b_n_label(emit->as, label_num)) {
|
||||
goto branch_not_in_range;
|
||||
}
|
||||
} else if (strcmp(op_str, "bl") == 0) {
|
||||
} else if (op == MP_QSTR_bl) {
|
||||
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
||||
if (!asm_thumb_bl_label(emit->as, label_num)) {
|
||||
goto branch_not_in_range;
|
||||
}
|
||||
} else if (strcmp(op_str, "bx") == 0) {
|
||||
} else if (op == MP_QSTR_bx) {
|
||||
mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
asm_thumb_op16(emit->as, 0x4700 | (r << 3));
|
||||
} 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
|
|||
}
|
||||
}
|
||||
asm_thumb_it_cc(emit->as, cc, it_mask);
|
||||
} else if (strcmp(op_str, "cpsid") == 0) {
|
||||
} else if (op == MP_QSTR_cpsid) {
|
||||
// TODO check pn_args[0] == i
|
||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSID_I);
|
||||
} else if (strcmp(op_str, "cpsie") == 0) {
|
||||
} else if (op == MP_QSTR_cpsie) {
|
||||
// TODO check pn_args[0] == i
|
||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSIE_I);
|
||||
} else if (strcmp(op_str, "push") == 0) {
|
||||
} else if (op == MP_QSTR_push) {
|
||||
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
||||
if ((reglist & 0xff00) == 0) {
|
||||
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
|
|||
}
|
||||
asm_thumb_op32(emit->as, 0xe92d, reglist);
|
||||
}
|
||||
} else if (strcmp(op_str, "pop") == 0) {
|
||||
} else if (op == MP_QSTR_pop) {
|
||||
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
||||
if ((reglist & 0xff00) == 0) {
|
||||
asm_thumb_op16(emit->as, 0xbc00 | reglist);
|
||||
|
@ -634,11 +635,11 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
|
||||
// second arg is a register (or should be)
|
||||
mp_uint_t op_code, op_code_hi;
|
||||
if (strcmp(op_str, "mov") == 0) {
|
||||
if (op == MP_QSTR_mov) {
|
||||
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||
asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
|
||||
} else if (ARMV7M && strcmp(op_str, "clz") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_clz) {
|
||||
op_code_hi = 0xfab0;
|
||||
op_code = 0xf080;
|
||||
mp_uint_t rd, rm;
|
||||
|
@ -646,16 +647,16 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
rm = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||
asm_thumb_op32(emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
|
||||
} else if (ARMV7M && strcmp(op_str, "rbit") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_rbit) {
|
||||
op_code_hi = 0xfa90;
|
||||
op_code = 0xf0a0;
|
||||
goto op_clz_rbit;
|
||||
} else if (ARMV7M && strcmp(op_str, "mrs") == 0){
|
||||
} else if (ARMV7M && op == MP_QSTR_mrs){
|
||||
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);
|
||||
mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);
|
||||
asm_thumb_op32(emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
|
||||
} else {
|
||||
if (strcmp(op_str, "and_") == 0) {
|
||||
if (op == MP_QSTR_and_) {
|
||||
op_code = ASM_THUMB_FORMAT_4_AND;
|
||||
mp_uint_t reg_dest, reg_src;
|
||||
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
|
|||
} else {
|
||||
// second arg is not a register
|
||||
mp_uint_t op_code;
|
||||
if (strcmp(op_str, "mov") == 0) {
|
||||
if (op == MP_QSTR_mov) {
|
||||
op_code = ASM_THUMB_FORMAT_3_MOV;
|
||||
mp_uint_t rlo_dest, i8_src;
|
||||
op_format_3:
|
||||
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||
i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
|
||||
asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
|
||||
} else if (strcmp(op_str, "cmp") == 0) {
|
||||
} else if (op == MP_QSTR_cmp) {
|
||||
op_code = ASM_THUMB_FORMAT_3_CMP;
|
||||
goto op_format_3;
|
||||
} else if (strcmp(op_str, "add") == 0) {
|
||||
} else if (op == MP_QSTR_add) {
|
||||
op_code = ASM_THUMB_FORMAT_3_ADD;
|
||||
goto op_format_3;
|
||||
} else if (strcmp(op_str, "sub") == 0) {
|
||||
} else if (op == MP_QSTR_sub) {
|
||||
op_code = ASM_THUMB_FORMAT_3_SUB;
|
||||
goto op_format_3;
|
||||
} else if (ARMV7M && strcmp(op_str, "movw") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_movw) {
|
||||
op_code = ASM_THUMB_OP_MOVW;
|
||||
mp_uint_t reg_dest;
|
||||
op_movw_movt:
|
||||
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
|
||||
asm_thumb_mov_reg_i16(emit->as, op_code, reg_dest, i_src);
|
||||
} else if (ARMV7M && strcmp(op_str, "movt") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_movt) {
|
||||
op_code = ASM_THUMB_OP_MOVT;
|
||||
goto op_movw_movt;
|
||||
} else if (ARMV7M && strcmp(op_str, "movwt") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_movwt) {
|
||||
// this is a convenience instruction
|
||||
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
|
||||
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
|
||||
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
|
||||
} else if (ARMV7M && strcmp(op_str, "ldrex") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_ldrex) {
|
||||
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
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
|
|||
} else {
|
||||
// search table for ldr/str instructions
|
||||
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
|
||||
if (strcmp(op_str, format_9_10_op_table[i].name) == 0) {
|
||||
if (op == format_9_10_op_table[i].name) {
|
||||
op_code = format_9_10_op_table[i].op;
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||
|
@ -745,7 +746,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
|
||||
} else if (n_args == 3) {
|
||||
mp_uint_t op_code;
|
||||
if (strcmp(op_str, "lsl") == 0) {
|
||||
if (op == MP_QSTR_lsl) {
|
||||
op_code = ASM_THUMB_FORMAT_1_LSL;
|
||||
mp_uint_t rlo_dest, rlo_src, i5;
|
||||
op_format_1:
|
||||
|
@ -753,13 +754,13 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
||||
i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
|
||||
asm_thumb_format_1(emit->as, op_code, rlo_dest, rlo_src, i5);
|
||||
} else if (strcmp(op_str, "lsr") == 0) {
|
||||
} else if (op == MP_QSTR_lsr) {
|
||||
op_code = ASM_THUMB_FORMAT_1_LSR;
|
||||
goto op_format_1;
|
||||
} else if (strcmp(op_str, "asr") == 0) {
|
||||
} else if (op == MP_QSTR_asr) {
|
||||
op_code = ASM_THUMB_FORMAT_1_ASR;
|
||||
goto op_format_1;
|
||||
} else if (strcmp(op_str, "add") == 0) {
|
||||
} else if (op == MP_QSTR_add) {
|
||||
op_code = ASM_THUMB_FORMAT_2_ADD;
|
||||
mp_uint_t rlo_dest, rlo_src;
|
||||
op_format_2:
|
||||
|
@ -774,7 +775,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
|
||||
}
|
||||
asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
|
||||
} else if (ARMV7M && strcmp(op_str, "sdiv") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_sdiv) {
|
||||
op_code = 0xfb90; // sdiv high part
|
||||
mp_uint_t rd, rn, rm;
|
||||
op_sdiv_udiv:
|
||||
|
@ -782,13 +783,13 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
|
||||
asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
|
||||
} else if (ARMV7M && strcmp(op_str, "udiv") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_udiv) {
|
||||
op_code = 0xfbb0; // udiv high part
|
||||
goto op_sdiv_udiv;
|
||||
} else if (strcmp(op_str, "sub") == 0) {
|
||||
} else if (op == MP_QSTR_sub) {
|
||||
op_code = ASM_THUMB_FORMAT_2_SUB;
|
||||
goto op_format_2;
|
||||
} else if (ARMV7M && strcmp(op_str, "strex") == 0) {
|
||||
} else if (ARMV7M && op == MP_QSTR_strex) {
|
||||
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
|
|
|
@ -114,6 +114,50 @@ Q(label)
|
|||
Q(align)
|
||||
Q(data)
|
||||
Q(uint)
|
||||
Q(nop)
|
||||
Q(mov)
|
||||
Q(and_)
|
||||
Q(cmp)
|
||||
Q(add)
|
||||
Q(sub)
|
||||
Q(lsl)
|
||||
Q(lsr)
|
||||
Q(asr)
|
||||
Q(ldr)
|
||||
Q(ldrb)
|
||||
Q(ldrh)
|
||||
Q(str)
|
||||
Q(strb)
|
||||
Q(strh)
|
||||
Q(b)
|
||||
Q(bl)
|
||||
Q(bx)
|
||||
Q(push)
|
||||
Q(pop)
|
||||
Q(cpsid)
|
||||
Q(cpsie)
|
||||
Q(wfi)
|
||||
Q(clz)
|
||||
Q(rbit)
|
||||
Q(movw)
|
||||
Q(movt)
|
||||
Q(movwt)
|
||||
Q(mrs)
|
||||
Q(sdiv)
|
||||
Q(udiv)
|
||||
Q(ldrex)
|
||||
Q(strex)
|
||||
#if MICROPY_EMIT_INLINE_THUMB_FLOAT
|
||||
Q(vcmp)
|
||||
Q(vneg)
|
||||
Q(vcvt_f32_s32)
|
||||
Q(vcvt_s32_f32)
|
||||
Q(vsqrt)
|
||||
Q(vmov)
|
||||
Q(vmrs)
|
||||
Q(vldr)
|
||||
Q(vstr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Q(builtins)
|
||||
|
|
Loading…
Reference in New Issue