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.
This commit is contained in:
parent
3a4ebf5768
commit
a7fd786a1f
|
@ -43,12 +43,12 @@ typedef enum {
|
||||||
} pn_kind_t;
|
} pn_kind_t;
|
||||||
|
|
||||||
struct _emit_inline_asm_t {
|
struct _emit_inline_asm_t {
|
||||||
|
asm_thumb_t as;
|
||||||
uint16_t pass;
|
uint16_t pass;
|
||||||
scope_t *scope;
|
scope_t *scope;
|
||||||
mp_obj_t *error_slot;
|
mp_obj_t *error_slot;
|
||||||
mp_uint_t max_num_labels;
|
mp_uint_t max_num_labels;
|
||||||
qstr *label_lookup;
|
qstr *label_lookup;
|
||||||
asm_thumb_t *as;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) {
|
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) {
|
||||||
|
|
||||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
|
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
|
||||||
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
|
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
|
||||||
|
memset(&emit->as, 0, sizeof(emit->as));
|
||||||
|
mp_asm_base_init(&emit->as.base, max_num_labels);
|
||||||
emit->max_num_labels = max_num_labels;
|
emit->max_num_labels = max_num_labels;
|
||||||
emit->label_lookup = m_new(qstr, max_num_labels);
|
emit->label_lookup = m_new(qstr, max_num_labels);
|
||||||
emit->as = m_new0(asm_thumb_t, 1);
|
|
||||||
mp_asm_base_init(&emit->as->base, max_num_labels);
|
|
||||||
return emit;
|
return emit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_inline_thumb_free(emit_inline_asm_t *emit) {
|
void emit_inline_thumb_free(emit_inline_asm_t *emit) {
|
||||||
m_del(qstr, emit->label_lookup, emit->max_num_labels);
|
m_del(qstr, emit->label_lookup, emit->max_num_labels);
|
||||||
mp_asm_base_deinit(&emit->as->base, false);
|
mp_asm_base_deinit(&emit->as.base, false);
|
||||||
m_del_obj(asm_thumb_t, emit->as);
|
|
||||||
m_del_obj(emit_inline_asm_t, emit);
|
m_del_obj(emit_inline_asm_t, emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,18 +81,18 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa
|
||||||
if (emit->pass == MP_PASS_CODE_SIZE) {
|
if (emit->pass == MP_PASS_CODE_SIZE) {
|
||||||
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
|
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
|
||||||
}
|
}
|
||||||
mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
|
mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
|
||||||
asm_thumb_entry(emit->as, 0);
|
asm_thumb_entry(&emit->as, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
|
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
|
||||||
asm_thumb_exit(emit->as);
|
asm_thumb_exit(&emit->as);
|
||||||
asm_thumb_end_pass(emit->as);
|
asm_thumb_end_pass(&emit->as);
|
||||||
|
|
||||||
if (emit->pass == MP_PASS_EMIT) {
|
if (emit->pass == MP_PASS_EMIT) {
|
||||||
void *f = mp_asm_base_get_code(&emit->as->base);
|
void *f = mp_asm_base_get_code(&emit->as.base);
|
||||||
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
|
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
|
||||||
mp_asm_base_get_code_size(&emit->as->base), NULL, emit->scope->num_pos_args, 0, type_sig);
|
mp_asm_base_get_code_size(&emit->as.base), NULL, emit->scope->num_pos_args, 0, type_sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,16 +126,16 @@ STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit->label_lookup[label_num] = label_id;
|
emit->label_lookup[label_num] = label_id;
|
||||||
mp_asm_base_label_assign(&emit->as->base, label_num);
|
mp_asm_base_label_assign(&emit->as.base, label_num);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, mp_uint_t align) {
|
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, mp_uint_t align) {
|
||||||
mp_asm_base_align(&emit->as->base, align);
|
mp_asm_base_align(&emit->as.base, align);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
|
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
|
||||||
mp_asm_base_data(&emit->as->base, bytesize, val);
|
mp_asm_base_data(&emit->as.base, bytesize, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
|
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
|
||||||
op_vfp_twoargs:;
|
op_vfp_twoargs:;
|
||||||
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
||||||
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
|
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
|
||||||
asm_thumb_op32(emit->as,
|
asm_thumb_op32(&emit->as,
|
||||||
op_code_hi | ((vd & 1) << 6),
|
op_code_hi | ((vd & 1) << 6),
|
||||||
op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
|
op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
|
||||||
} else if (op == MP_QSTR_vsqrt) {
|
} 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
|
||||||
const char *reg_str1 = get_arg_str(pn_args[1]);
|
const char *reg_str1 = get_arg_str(pn_args[1]);
|
||||||
if (strcmp(reg_str1, "FPSCR") == 0) {
|
if (strcmp(reg_str1, "FPSCR") == 0) {
|
||||||
// FP status to ARM reg
|
// FP status to ARM reg
|
||||||
asm_thumb_op32(emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));
|
asm_thumb_op32(&emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
|
@ -488,7 +487,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
vm = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
vm = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
||||||
r_arm = get_arg_reg(emit, op_str, pn_args[1], 15);
|
r_arm = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||||
}
|
}
|
||||||
asm_thumb_op32(emit->as,
|
asm_thumb_op32(&emit->as,
|
||||||
op_code_hi | ((vm & 0x1e) >> 1),
|
op_code_hi | ((vm & 0x1e) >> 1),
|
||||||
0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
|
0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
|
||||||
} else if (op == MP_QSTR_vldr) {
|
} 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
|
||||||
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
|
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
|
||||||
mp_uint_t i8;
|
mp_uint_t i8;
|
||||||
i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2;
|
i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2;
|
||||||
asm_thumb_op32(emit->as,
|
asm_thumb_op32(&emit->as,
|
||||||
op_code_hi | rlo_base | ((vd & 1) << 6),
|
op_code_hi | rlo_base | ((vd & 1) << 6),
|
||||||
0x0a00 | ((vd & 0x1e) << 11) | i8);
|
0x0a00 | ((vd & 0x1e) << 11) | i8);
|
||||||
}
|
}
|
||||||
|
@ -519,7 +518,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
||||||
mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]);
|
mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]);
|
||||||
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]);
|
mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]);
|
||||||
asm_thumb_op32(emit->as,
|
asm_thumb_op32(&emit->as,
|
||||||
op_code_hi | ((vd & 1) << 6) | (vn >> 1),
|
op_code_hi | ((vd & 1) << 6) | (vn >> 1),
|
||||||
op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7));
|
op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7));
|
||||||
return;
|
return;
|
||||||
|
@ -533,9 +532,9 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
#endif
|
#endif
|
||||||
if (n_args == 0) {
|
if (n_args == 0) {
|
||||||
if (op == MP_QSTR_nop) {
|
if (op == MP_QSTR_nop) {
|
||||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_NOP);
|
asm_thumb_op16(&emit->as, ASM_THUMB_OP_NOP);
|
||||||
} else if (op == MP_QSTR_wfi) {
|
} else if (op == MP_QSTR_wfi) {
|
||||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_WFI);
|
asm_thumb_op16(&emit->as, ASM_THUMB_OP_WFI);
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
|
@ -543,17 +542,17 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
} else if (n_args == 1) {
|
} else if (n_args == 1) {
|
||||||
if (op == MP_QSTR_b) {
|
if (op == MP_QSTR_b) {
|
||||||
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
||||||
if (!asm_thumb_b_n_label(emit->as, label_num)) {
|
if (!asm_thumb_b_n_label(&emit->as, label_num)) {
|
||||||
goto branch_not_in_range;
|
goto branch_not_in_range;
|
||||||
}
|
}
|
||||||
} else if (op == MP_QSTR_bl) {
|
} else if (op == MP_QSTR_bl) {
|
||||||
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
||||||
if (!asm_thumb_bl_label(emit->as, label_num)) {
|
if (!asm_thumb_bl_label(&emit->as, label_num)) {
|
||||||
goto branch_not_in_range;
|
goto branch_not_in_range;
|
||||||
}
|
}
|
||||||
} else if (op == MP_QSTR_bx) {
|
} else if (op == MP_QSTR_bx) {
|
||||||
mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
|
mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||||
asm_thumb_op16(emit->as, 0x4700 | (r << 3));
|
asm_thumb_op16(&emit->as, 0x4700 | (r << 3));
|
||||||
} else if (op_str[0] == 'b' && (op_len == 3
|
} else if (op_str[0] == 'b' && (op_len == 3
|
||||||
|| (op_len == 5 && op_str[3] == '_'
|
|| (op_len == 5 && op_str[3] == '_'
|
||||||
&& (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) {
|
&& (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
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
int label_num = get_arg_label(emit, op_str, pn_args[0]);
|
||||||
if (!asm_thumb_bcc_nw_label(emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
|
if (!asm_thumb_bcc_nw_label(&emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
|
||||||
goto branch_not_in_range;
|
goto branch_not_in_range;
|
||||||
}
|
}
|
||||||
} else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') {
|
} 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
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asm_thumb_it_cc(emit->as, cc, it_mask);
|
asm_thumb_it_cc(&emit->as, cc, it_mask);
|
||||||
} else if (op == MP_QSTR_cpsid) {
|
} else if (op == MP_QSTR_cpsid) {
|
||||||
// TODO check pn_args[0] == i
|
// TODO check pn_args[0] == i
|
||||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSID_I);
|
asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSID_I);
|
||||||
} else if (op == MP_QSTR_cpsie) {
|
} else if (op == MP_QSTR_cpsie) {
|
||||||
// TODO check pn_args[0] == i
|
// TODO check pn_args[0] == i
|
||||||
asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSIE_I);
|
asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSIE_I);
|
||||||
} else if (op == MP_QSTR_push) {
|
} else if (op == MP_QSTR_push) {
|
||||||
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
||||||
if ((reglist & 0xff00) == 0) {
|
if ((reglist & 0xff00) == 0) {
|
||||||
asm_thumb_op16(emit->as, 0xb400 | reglist);
|
asm_thumb_op16(&emit->as, 0xb400 | reglist);
|
||||||
} else {
|
} else {
|
||||||
if (!ARMV7M) {
|
if (!ARMV7M) {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
asm_thumb_op32(emit->as, 0xe92d, reglist);
|
asm_thumb_op32(&emit->as, 0xe92d, reglist);
|
||||||
}
|
}
|
||||||
} else if (op == MP_QSTR_pop) {
|
} else if (op == MP_QSTR_pop) {
|
||||||
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
|
||||||
if ((reglist & 0xff00) == 0) {
|
if ((reglist & 0xff00) == 0) {
|
||||||
asm_thumb_op16(emit->as, 0xbc00 | reglist);
|
asm_thumb_op16(&emit->as, 0xbc00 | reglist);
|
||||||
} else {
|
} else {
|
||||||
if (!ARMV7M) {
|
if (!ARMV7M) {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
asm_thumb_op32(emit->as, 0xe8bd, reglist);
|
asm_thumb_op32(&emit->as, 0xe8bd, reglist);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
|
@ -640,7 +639,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
if (op == MP_QSTR_mov) {
|
if (op == MP_QSTR_mov) {
|
||||||
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
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);
|
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);
|
asm_thumb_mov_reg_reg(&emit->as, reg_dest, reg_src);
|
||||||
} else if (ARMV7M && op == MP_QSTR_clz) {
|
} else if (ARMV7M && op == MP_QSTR_clz) {
|
||||||
op_code_hi = 0xfab0;
|
op_code_hi = 0xfab0;
|
||||||
op_code = 0xf080;
|
op_code = 0xf080;
|
||||||
|
@ -648,7 +647,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
op_clz_rbit:
|
op_clz_rbit:
|
||||||
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
|
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||||
rm = get_arg_reg(emit, op_str, pn_args[1], 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);
|
asm_thumb_op32(&emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
|
||||||
} else if (ARMV7M && op == MP_QSTR_rbit) {
|
} else if (ARMV7M && op == MP_QSTR_rbit) {
|
||||||
op_code_hi = 0xfa90;
|
op_code_hi = 0xfa90;
|
||||||
op_code = 0xf0a0;
|
op_code = 0xf0a0;
|
||||||
|
@ -656,7 +655,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
} else if (ARMV7M && op == MP_QSTR_mrs){
|
} 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_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]);
|
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);
|
asm_thumb_op32(&emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
|
||||||
} else {
|
} else {
|
||||||
if (op == MP_QSTR_and_) {
|
if (op == MP_QSTR_and_) {
|
||||||
op_code = ASM_THUMB_FORMAT_4_AND;
|
op_code = ASM_THUMB_FORMAT_4_AND;
|
||||||
|
@ -664,7 +663,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
op_format_4:
|
op_format_4:
|
||||||
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||||
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
||||||
asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
|
asm_thumb_format_4(&emit->as, op_code, reg_dest, reg_src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// search table for ALU ops
|
// 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
|
||||||
op_format_3:
|
op_format_3:
|
||||||
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||||
i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
|
i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
|
||||||
asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
|
asm_thumb_format_3(&emit->as, op_code, rlo_dest, i8_src);
|
||||||
} else if (op == MP_QSTR_cmp) {
|
} else if (op == MP_QSTR_cmp) {
|
||||||
op_code = ASM_THUMB_FORMAT_3_CMP;
|
op_code = ASM_THUMB_FORMAT_3_CMP;
|
||||||
goto op_format_3;
|
goto op_format_3;
|
||||||
|
@ -701,7 +700,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
op_movw_movt:
|
op_movw_movt:
|
||||||
reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
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);
|
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);
|
asm_thumb_mov_reg_i16(&emit->as, op_code, reg_dest, i_src);
|
||||||
} else if (ARMV7M && op == MP_QSTR_movt) {
|
} else if (ARMV7M && op == MP_QSTR_movt) {
|
||||||
op_code = ASM_THUMB_OP_MOVT;
|
op_code = ASM_THUMB_OP_MOVT;
|
||||||
goto op_movw_movt;
|
goto op_movw_movt;
|
||||||
|
@ -709,15 +708,15 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
// this is a convenience instruction
|
// this is a convenience instruction
|
||||||
mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
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);
|
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_MOVW, reg_dest, i_src & 0xffff);
|
||||||
asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
|
asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
|
||||||
} else if (ARMV7M && op == MP_QSTR_ldrex) {
|
} else if (ARMV7M && op == MP_QSTR_ldrex) {
|
||||||
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||||
mp_parse_node_t pn_base, pn_offset;
|
mp_parse_node_t pn_base, pn_offset;
|
||||||
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
|
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
|
||||||
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
||||||
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
||||||
asm_thumb_op32(emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
|
asm_thumb_op32(&emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// search table for ldr/str instructions
|
// 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
|
||||||
} else {
|
} else {
|
||||||
i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
|
i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
|
||||||
}
|
}
|
||||||
asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
|
asm_thumb_format_9_10(&emit->as, op_code, rlo_dest, rlo_base, i5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -755,7 +754,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||||
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
||||||
i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
|
i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
|
||||||
asm_thumb_format_1(emit->as, op_code, rlo_dest, rlo_src, i5);
|
asm_thumb_format_1(&emit->as, op_code, rlo_dest, rlo_src, i5);
|
||||||
} else if (op == MP_QSTR_lsr) {
|
} else if (op == MP_QSTR_lsr) {
|
||||||
op_code = ASM_THUMB_FORMAT_1_LSR;
|
op_code = ASM_THUMB_FORMAT_1_LSR;
|
||||||
goto op_format_1;
|
goto op_format_1;
|
||||||
|
@ -776,7 +775,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
||||||
op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;
|
op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;
|
||||||
src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
|
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);
|
asm_thumb_format_2(&emit->as, op_code, rlo_dest, rlo_src, src_b);
|
||||||
} else if (ARMV7M && op == MP_QSTR_sdiv) {
|
} else if (ARMV7M && op == MP_QSTR_sdiv) {
|
||||||
op_code = 0xfb90; // sdiv high part
|
op_code = 0xfb90; // sdiv high part
|
||||||
mp_uint_t rd, rn, rm;
|
mp_uint_t rd, rn, rm;
|
||||||
|
@ -784,7 +783,7 @@ 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);
|
rd = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||||
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
|
rn = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||||
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
|
rm = get_arg_reg(emit, op_str, pn_args[2], 15);
|
||||||
asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
|
asm_thumb_op32(&emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
|
||||||
} else if (ARMV7M && op == MP_QSTR_udiv) {
|
} else if (ARMV7M && op == MP_QSTR_udiv) {
|
||||||
op_code = 0xfbb0; // udiv high part
|
op_code = 0xfbb0; // udiv high part
|
||||||
goto op_sdiv_udiv;
|
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
|
||||||
if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
|
if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
|
||||||
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
||||||
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
||||||
asm_thumb_op32(emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);
|
asm_thumb_op32(&emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
|
|
|
@ -36,12 +36,12 @@
|
||||||
#if MICROPY_EMIT_INLINE_XTENSA
|
#if MICROPY_EMIT_INLINE_XTENSA
|
||||||
|
|
||||||
struct _emit_inline_asm_t {
|
struct _emit_inline_asm_t {
|
||||||
|
asm_xtensa_t as;
|
||||||
uint16_t pass;
|
uint16_t pass;
|
||||||
scope_t *scope;
|
scope_t *scope;
|
||||||
mp_obj_t *error_slot;
|
mp_obj_t *error_slot;
|
||||||
mp_uint_t max_num_labels;
|
mp_uint_t max_num_labels;
|
||||||
qstr *label_lookup;
|
qstr *label_lookup;
|
||||||
asm_xtensa_t *as;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, const char *msg) {
|
STATIC void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, const char *msg) {
|
||||||
|
@ -54,17 +54,16 @@ STATIC void emit_inline_xtensa_error_exc(emit_inline_asm_t *emit, mp_obj_t exc)
|
||||||
|
|
||||||
emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels) {
|
emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels) {
|
||||||
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
|
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
|
||||||
|
memset(&emit->as, 0, sizeof(emit->as));
|
||||||
|
mp_asm_base_init(&emit->as.base, max_num_labels);
|
||||||
emit->max_num_labels = max_num_labels;
|
emit->max_num_labels = max_num_labels;
|
||||||
emit->label_lookup = m_new(qstr, max_num_labels);
|
emit->label_lookup = m_new(qstr, max_num_labels);
|
||||||
emit->as = m_new0(asm_xtensa_t, 1);
|
|
||||||
mp_asm_base_init(&emit->as->base, max_num_labels);
|
|
||||||
return emit;
|
return emit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_inline_xtensa_free(emit_inline_asm_t *emit) {
|
void emit_inline_xtensa_free(emit_inline_asm_t *emit) {
|
||||||
m_del(qstr, emit->label_lookup, emit->max_num_labels);
|
m_del(qstr, emit->label_lookup, emit->max_num_labels);
|
||||||
mp_asm_base_deinit(&emit->as->base, false);
|
mp_asm_base_deinit(&emit->as.base, false);
|
||||||
m_del_obj(asm_xtensa_t, emit->as);
|
|
||||||
m_del_obj(emit_inline_asm_t, emit);
|
m_del_obj(emit_inline_asm_t, emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,18 +74,18 @@ STATIC void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t p
|
||||||
if (emit->pass == MP_PASS_CODE_SIZE) {
|
if (emit->pass == MP_PASS_CODE_SIZE) {
|
||||||
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
|
memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
|
||||||
}
|
}
|
||||||
mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
|
mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
|
||||||
asm_xtensa_entry(emit->as, 0);
|
asm_xtensa_entry(&emit->as, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
|
STATIC void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
|
||||||
asm_xtensa_exit(emit->as);
|
asm_xtensa_exit(&emit->as);
|
||||||
asm_xtensa_end_pass(emit->as);
|
asm_xtensa_end_pass(&emit->as);
|
||||||
|
|
||||||
if (emit->pass == MP_PASS_EMIT) {
|
if (emit->pass == MP_PASS_EMIT) {
|
||||||
void *f = mp_asm_base_get_code(&emit->as->base);
|
void *f = mp_asm_base_get_code(&emit->as.base);
|
||||||
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
|
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
|
||||||
mp_asm_base_get_code_size(&emit->as->base), NULL, emit->scope->num_pos_args, 0, type_sig);
|
mp_asm_base_get_code_size(&emit->as.base), NULL, emit->scope->num_pos_args, 0, type_sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,16 +119,16 @@ STATIC bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_nu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit->label_lookup[label_num] = label_id;
|
emit->label_lookup[label_num] = label_id;
|
||||||
mp_asm_base_label_assign(&emit->as->base, label_num);
|
mp_asm_base_label_assign(&emit->as.base, label_num);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_xtensa_align(emit_inline_asm_t *emit, mp_uint_t align) {
|
STATIC void emit_inline_xtensa_align(emit_inline_asm_t *emit, mp_uint_t align) {
|
||||||
mp_asm_base_align(&emit->as->base, align);
|
mp_asm_base_align(&emit->as.base, align);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_inline_xtensa_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
|
STATIC void emit_inline_xtensa_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
|
||||||
mp_asm_base_data(&emit->as->base, bytesize, val);
|
mp_asm_base_data(&emit->as.base, bytesize, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
|
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
|
||||||
|
@ -263,7 +262,7 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
|
||||||
|
|
||||||
if (n_args == 0) {
|
if (n_args == 0) {
|
||||||
if (op == MP_QSTR_ret_n) {
|
if (op == MP_QSTR_ret_n) {
|
||||||
asm_xtensa_op_ret_n(emit->as);
|
asm_xtensa_op_ret_n(&emit->as);
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
|
@ -271,13 +270,13 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
|
||||||
} else if (n_args == 1) {
|
} else if (n_args == 1) {
|
||||||
if (op == MP_QSTR_callx0) {
|
if (op == MP_QSTR_callx0) {
|
||||||
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
||||||
asm_xtensa_op_callx0(emit->as, r0);
|
asm_xtensa_op_callx0(&emit->as, r0);
|
||||||
} else if (op == MP_QSTR_j) {
|
} else if (op == MP_QSTR_j) {
|
||||||
int label = get_arg_label(emit, op_str, pn_args[0]);
|
int label = get_arg_label(emit, op_str, pn_args[0]);
|
||||||
asm_xtensa_j_label(emit->as, label);
|
asm_xtensa_j_label(&emit->as, label);
|
||||||
} else if (op == MP_QSTR_jx) {
|
} else if (op == MP_QSTR_jx) {
|
||||||
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
||||||
asm_xtensa_op_jx(emit->as, r0);
|
asm_xtensa_op_jx(&emit->as, r0);
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
|
@ -286,18 +285,18 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
|
||||||
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
|
||||||
if (op == MP_QSTR_beqz) {
|
if (op == MP_QSTR_beqz) {
|
||||||
int label = get_arg_label(emit, op_str, pn_args[1]);
|
int label = get_arg_label(emit, op_str, pn_args[1]);
|
||||||
asm_xtensa_bccz_reg_label(emit->as, ASM_XTENSA_CCZ_EQ, r0, label);
|
asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label);
|
||||||
} else if (op == MP_QSTR_bnez) {
|
} else if (op == MP_QSTR_bnez) {
|
||||||
int label = get_arg_label(emit, op_str, pn_args[1]);
|
int label = get_arg_label(emit, op_str, pn_args[1]);
|
||||||
asm_xtensa_bccz_reg_label(emit->as, ASM_XTENSA_CCZ_NE, r0, label);
|
asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label);
|
||||||
} else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
|
} else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
|
||||||
// we emit mov.n for both "mov" and "mov_n" opcodes
|
// we emit mov.n for both "mov" and "mov_n" opcodes
|
||||||
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
|
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
|
||||||
asm_xtensa_op_mov_n(emit->as, r0, r1);
|
asm_xtensa_op_mov_n(&emit->as, r0, r1);
|
||||||
} else if (op == MP_QSTR_movi) {
|
} else if (op == MP_QSTR_movi) {
|
||||||
// for convenience we emit l32r if the integer doesn't fit in movi
|
// for convenience we emit l32r if the integer doesn't fit in movi
|
||||||
uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
|
uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
|
||||||
asm_xtensa_mov_reg_i32(emit->as, r0, imm);
|
asm_xtensa_mov_reg_i32(&emit->as, r0, imm);
|
||||||
} else {
|
} else {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
}
|
}
|
||||||
|
@ -311,10 +310,10 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
|
||||||
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
|
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
|
||||||
if (o->type == RRR) {
|
if (o->type == RRR) {
|
||||||
uint r2 = get_arg_reg(emit, op_str, pn_args[2]);
|
uint r2 = get_arg_reg(emit, op_str, pn_args[2]);
|
||||||
asm_xtensa_op24(emit->as, ASM_XTENSA_ENCODE_RRR(0, o->a0, o->a1, r0, r1, r2));
|
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, o->a0, o->a1, r0, r1, r2));
|
||||||
} else if (o->type == RRI8_B) {
|
} else if (o->type == RRI8_B) {
|
||||||
int label = get_arg_label(emit, op_str, pn_args[2]);
|
int label = get_arg_label(emit, op_str, pn_args[2]);
|
||||||
asm_xtensa_bcc_reg_reg_label(emit->as, o->a0, r0, r1, label);
|
asm_xtensa_bcc_reg_reg_label(&emit->as, o->a0, r0, r1, label);
|
||||||
} else {
|
} else {
|
||||||
int shift, min, max;
|
int shift, min, max;
|
||||||
if ((o->type & 0xf0) == 0) {
|
if ((o->type & 0xf0) == 0) {
|
||||||
|
@ -327,7 +326,7 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
|
||||||
max = 0xff << shift;
|
max = 0xff << shift;
|
||||||
}
|
}
|
||||||
uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max);
|
uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max);
|
||||||
asm_xtensa_op24(emit->as, ASM_XTENSA_ENCODE_RRI8(o->a0, o->a1, r1, r0, (imm >> shift) & 0xff));
|
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(o->a0, o->a1, r1, r0, (imm >> shift) & 0xff));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue