py: Add 'align' and 'data' meta-instructions to inline assembler.
This commit is contained in:
parent
764af4b7c5
commit
e5f8a77db6
@ -209,6 +209,20 @@ void asm_thumb_label_assign(asm_thumb_t *as, uint label) {
|
||||
}
|
||||
}
|
||||
|
||||
void asm_thumb_align(asm_thumb_t* as, uint align) {
|
||||
// TODO fill unused data with NOPs?
|
||||
as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
|
||||
}
|
||||
|
||||
void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val) {
|
||||
byte *c = asm_thumb_get_cur_to_write_bytes(as, bytesize);
|
||||
// little endian
|
||||
for (uint i = 0; i < bytesize; i++) {
|
||||
*c++ = val;
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC int get_label_dest(asm_thumb_t *as, uint label) {
|
||||
assert(label < as->max_num_labels);
|
||||
return as->label_offsets[label];
|
||||
|
@ -55,6 +55,9 @@ void asm_thumb_exit(asm_thumb_t *as);
|
||||
|
||||
void asm_thumb_label_assign(asm_thumb_t *as, uint label);
|
||||
|
||||
void asm_thumb_align(asm_thumb_t* as, uint align);
|
||||
void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val);
|
||||
|
||||
// argument order follows ARM, in general dest is first
|
||||
// note there is a difference between movw and mov.w, and many others!
|
||||
|
||||
|
25
py/compile.c
25
py/compile.c
@ -3184,7 +3184,7 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
|
||||
int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
|
||||
|
||||
// emit instructions
|
||||
if (strcmp(qstr_str(op), "label") == 0) {
|
||||
if (op == MP_QSTR_label) {
|
||||
if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
|
||||
compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument");
|
||||
return;
|
||||
@ -3193,6 +3193,29 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
|
||||
if (pass > PASS_1) {
|
||||
EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
|
||||
}
|
||||
} else if (op == MP_QSTR_align) {
|
||||
if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
|
||||
compile_syntax_error(comp, nodes[i], "inline assembler 'align' requires 1 argument");
|
||||
return;
|
||||
}
|
||||
if (pass > PASS_1) {
|
||||
EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
|
||||
}
|
||||
} else if (op == MP_QSTR_data) {
|
||||
if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
|
||||
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires at least 2 arguments");
|
||||
return;
|
||||
}
|
||||
if (pass > PASS_1) {
|
||||
machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
|
||||
for (uint i = 1; i < n_args; i++) {
|
||||
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) {
|
||||
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires integer arguments");
|
||||
return;
|
||||
}
|
||||
EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[i]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pass > PASS_1) {
|
||||
EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
|
||||
|
@ -143,6 +143,8 @@ typedef struct _emit_inline_asm_method_table_t {
|
||||
bool (*end_pass)(emit_inline_asm_t *emit);
|
||||
int (*count_params)(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params);
|
||||
void (*label)(emit_inline_asm_t *emit, uint label_num, qstr label_id);
|
||||
void (*align)(emit_inline_asm_t *emit, uint align);
|
||||
void (*data)(emit_inline_asm_t *emit, uint bytesize, uint val);
|
||||
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args);
|
||||
} emit_inline_asm_method_table_t;
|
||||
|
||||
|
@ -104,6 +104,14 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, uint label_num, qst
|
||||
asm_thumb_label_assign(emit->as, label_num);
|
||||
}
|
||||
|
||||
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, uint align) {
|
||||
asm_thumb_align(emit->as, align);
|
||||
}
|
||||
|
||||
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, uint bytesize, uint val) {
|
||||
asm_thumb_data(emit->as, bytesize, val);
|
||||
}
|
||||
|
||||
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
|
||||
STATIC const reg_name_t reg_name_table[] = {
|
||||
{0, "r0\0"},
|
||||
@ -418,6 +426,8 @@ const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
|
||||
emit_inline_thumb_end_pass,
|
||||
emit_inline_thumb_count_params,
|
||||
emit_inline_thumb_label,
|
||||
emit_inline_thumb_align,
|
||||
emit_inline_thumb_data,
|
||||
emit_inline_thumb_op,
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,13 @@ Q(micropython)
|
||||
Q(byte_code)
|
||||
Q(native)
|
||||
Q(viper)
|
||||
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
Q(asm_thumb)
|
||||
Q(label)
|
||||
Q(align)
|
||||
Q(data)
|
||||
#endif
|
||||
|
||||
Q(Ellipsis)
|
||||
Q(StopIteration)
|
||||
|
Loading…
Reference in New Issue
Block a user