Skip to content

Commit e5f8a77

Browse files
committed
py: Add 'align' and 'data' meta-instructions to inline assembler.
1 parent 764af4b commit e5f8a77

6 files changed

Lines changed: 59 additions & 1 deletion

File tree

py/asmthumb.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,20 @@ void asm_thumb_label_assign(asm_thumb_t *as, uint label) {
209209
}
210210
}
211211

212+
void asm_thumb_align(asm_thumb_t* as, uint align) {
213+
// TODO fill unused data with NOPs?
214+
as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
215+
}
216+
217+
void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val) {
218+
byte *c = asm_thumb_get_cur_to_write_bytes(as, bytesize);
219+
// little endian
220+
for (uint i = 0; i < bytesize; i++) {
221+
*c++ = val;
222+
val >>= 8;
223+
}
224+
}
225+
212226
STATIC int get_label_dest(asm_thumb_t *as, uint label) {
213227
assert(label < as->max_num_labels);
214228
return as->label_offsets[label];

py/asmthumb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ void asm_thumb_exit(asm_thumb_t *as);
5555

5656
void asm_thumb_label_assign(asm_thumb_t *as, uint label);
5757

58+
void asm_thumb_align(asm_thumb_t* as, uint align);
59+
void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val);
60+
5861
// argument order follows ARM, in general dest is first
5962
// note there is a difference between movw and mov.w, and many others!
6063

py/compile.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3184,7 +3184,7 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
31843184
int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
31853185

31863186
// emit instructions
3187-
if (strcmp(qstr_str(op), "label") == 0) {
3187+
if (op == MP_QSTR_label) {
31883188
if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
31893189
compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument");
31903190
return;
@@ -3193,6 +3193,29 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
31933193
if (pass > PASS_1) {
31943194
EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
31953195
}
3196+
} else if (op == MP_QSTR_align) {
3197+
if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
3198+
compile_syntax_error(comp, nodes[i], "inline assembler 'align' requires 1 argument");
3199+
return;
3200+
}
3201+
if (pass > PASS_1) {
3202+
EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
3203+
}
3204+
} else if (op == MP_QSTR_data) {
3205+
if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
3206+
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires at least 2 arguments");
3207+
return;
3208+
}
3209+
if (pass > PASS_1) {
3210+
machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
3211+
for (uint i = 1; i < n_args; i++) {
3212+
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) {
3213+
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires integer arguments");
3214+
return;
3215+
}
3216+
EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[i]));
3217+
}
3218+
}
31963219
} else {
31973220
if (pass > PASS_1) {
31983221
EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);

py/emit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ typedef struct _emit_inline_asm_method_table_t {
143143
bool (*end_pass)(emit_inline_asm_t *emit);
144144
int (*count_params)(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params);
145145
void (*label)(emit_inline_asm_t *emit, uint label_num, qstr label_id);
146+
void (*align)(emit_inline_asm_t *emit, uint align);
147+
void (*data)(emit_inline_asm_t *emit, uint bytesize, uint val);
146148
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args);
147149
} emit_inline_asm_method_table_t;
148150

py/emitinlinethumb.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, uint label_num, qst
104104
asm_thumb_label_assign(emit->as, label_num);
105105
}
106106

107+
STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, uint align) {
108+
asm_thumb_align(emit->as, align);
109+
}
110+
111+
STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, uint bytesize, uint val) {
112+
asm_thumb_data(emit->as, bytesize, val);
113+
}
114+
107115
typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
108116
STATIC const reg_name_t reg_name_table[] = {
109117
{0, "r0\0"},
@@ -418,6 +426,8 @@ const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
418426
emit_inline_thumb_end_pass,
419427
emit_inline_thumb_count_params,
420428
emit_inline_thumb_label,
429+
emit_inline_thumb_align,
430+
emit_inline_thumb_data,
421431
emit_inline_thumb_op,
422432
};
423433

py/qstrdefs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ Q(micropython)
3636
Q(byte_code)
3737
Q(native)
3838
Q(viper)
39+
40+
#if MICROPY_EMIT_INLINE_THUMB
3941
Q(asm_thumb)
42+
Q(label)
43+
Q(align)
44+
Q(data)
45+
#endif
4046

4147
Q(Ellipsis)
4248
Q(StopIteration)

0 commit comments

Comments
 (0)