Skip to content

Commit a2f2f7d

Browse files
committed
Almost supports arguments for inline asm functions.
1 parent 5fa5ae4 commit a2f2f7d

3 files changed

Lines changed: 55 additions & 28 deletions

File tree

py/compile.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,25 +2507,30 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
25072507
return;
25082508
}
25092509

2510+
if (comp->pass > PASS_1) {
2511+
EMIT_INLINE_ASM(start_pass, comp->pass, comp->scope_cur);
2512+
}
2513+
25102514
// get the function definition parse node
25112515
assert(PY_PARSE_NODE_IS_STRUCT(scope->pn));
25122516
py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn;
25132517
assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
25142518

2515-
//qstr f_id = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // name
2519+
//qstr f_id = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
2520+
2521+
// parameters are in pns->nodes[1]
2522+
if (comp->pass == PASS_2) {
2523+
py_parse_node_t *pn_params;
2524+
int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
2525+
scope->num_params = EMIT_INLINE_ASM(count_params, n_params, pn_params);
2526+
}
25162527

2517-
scope->num_params = 0;
2518-
assert(PY_PARSE_NODE_IS_NULL(pns->nodes[1])); // arguments
25192528
assert(PY_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
25202529

25212530
py_parse_node_t pn_body = pns->nodes[3]; // body
25222531
py_parse_node_t *nodes;
25232532
int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
25242533

2525-
if (comp->pass > PASS_1) {
2526-
EMIT_INLINE_ASM(start_pass, comp->pass, comp->scope_cur);
2527-
}
2528-
25292534
if (comp->pass == PASS_3) {
25302535
//printf("----\n");
25312536
scope_print_info(scope);

py/emit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ typedef struct _emit_inline_asm_t emit_inline_asm_t;
134134
typedef struct _emit_inline_asm_method_table_t {
135135
void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope);
136136
void (*end_pass)(emit_inline_asm_t *emit);
137+
int (*count_params)(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params);
137138
void (*label)(emit_inline_asm_t *emit, int label_num, qstr label_id);
138-
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *args);
139+
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args);
139140
} emit_inline_asm_method_table_t;
140141

141142
extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table;

py/emitinlinethumb.c

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
5050
}
5151
}
5252

53+
static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params) {
54+
if (n_params > 4) {
55+
printf("SyntaxError: can only have up to 3 parameters to inline assembler\n");
56+
return 0;
57+
}
58+
for (int i = 0; i < n_params; i++) {
59+
if (!PY_PARSE_NODE_IS_ID(pn_params[i])) {
60+
printf("SyntaxError: parameter to inline assembler must be an identifier %d\n", PY_PARSE_NODE_STRUCT_KIND((py_parse_node_struct_t*)pn_params[i]));
61+
return 0;
62+
}
63+
const char *p = qstr_str(PY_PARSE_NODE_LEAF_ARG(pn_params[i]));
64+
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
65+
printf("SyntaxError: parameter %d to inline assembler must be r%d\n", i, i);
66+
return 0;
67+
}
68+
}
69+
return n_params;
70+
}
71+
5372
static void emit_inline_thumb_label(emit_inline_asm_t *emit, int label_num, qstr label_id) {
5473
assert(label_num < emit->max_num_labels);
5574
emit->label_lookup[label_num] = label_id;
@@ -65,12 +84,12 @@ static bool check_n_arg(qstr op, int n_args, int wanted_n_args) {
6584
}
6685
}
6786

68-
static uint get_arg_rlo(qstr op, py_parse_node_t *pn_arg, int wanted_arg_num) {
69-
if (!PY_PARSE_NODE_IS_ID(pn_arg[wanted_arg_num])) {
87+
static uint get_arg_rlo(qstr op, py_parse_node_t *pn_args, int wanted_arg_num) {
88+
if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
7089
printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
7190
return 0;
7291
}
73-
qstr reg_qstr = PY_PARSE_NODE_LEAF_ARG(pn_arg[wanted_arg_num]);
92+
qstr reg_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
7493
const char *reg_str = qstr_str(reg_qstr);
7594
if (!(strlen(reg_str) == 2 && reg_str[0] == 'r' && ('0' <= reg_str[1] && reg_str[1] <= '7'))) {
7695
printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
@@ -79,25 +98,25 @@ static uint get_arg_rlo(qstr op, py_parse_node_t *pn_arg, int wanted_arg_num) {
7998
return reg_str[1] - '0';
8099
}
81100

82-
static int get_arg_i(qstr op, py_parse_node_t *pn_arg, int wanted_arg_num, int fit_mask) {
83-
if (!PY_PARSE_NODE_IS_SMALL_INT(pn_arg[wanted_arg_num])) {
101+
static int get_arg_i(qstr op, py_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
102+
if (!PY_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
84103
printf("SyntaxError: '%s' expects an integer in position %d\n", qstr_str(op), wanted_arg_num);
85104
return 0;
86105
}
87-
int i = PY_PARSE_NODE_LEAF_ARG(pn_arg[wanted_arg_num]);
106+
int i = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
88107
if ((i & (~fit_mask)) != 0) {
89108
printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", qstr_str(op), i, fit_mask);
90109
return 0;
91110
}
92111
return i;
93112
}
94113

95-
static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_arg, int wanted_arg_num) {
96-
if (!PY_PARSE_NODE_IS_ID(pn_arg[wanted_arg_num])) {
114+
static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_args, int wanted_arg_num) {
115+
if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
97116
printf("SyntaxError: '%s' expects a label in position %d\n", qstr_str(op), wanted_arg_num);
98117
return 0;
99118
}
100-
qstr label_qstr = PY_PARSE_NODE_LEAF_ARG(pn_arg[wanted_arg_num]);
119+
qstr label_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
101120
for (int i = 0; i < emit->max_num_labels; i++) {
102121
if (emit->label_lookup[i] == label_qstr) {
103122
return i;
@@ -107,7 +126,7 @@ static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_a
107126
return 0;
108127
}
109128

110-
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_arg) {
129+
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args) {
111130
// TODO perhaps make two tables:
112131
// two_args =
113132
// "movs", RLO, I8, asm_thumb_movs_reg_i8
@@ -120,40 +139,41 @@ static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, p
120139
if (!check_n_arg(op, n_args, 1)) {
121140
return;
122141
}
123-
int label_num = get_arg_label(emit, op, pn_arg, 0);
142+
int label_num = get_arg_label(emit, op, pn_args, 0);
143+
// TODO check that this succeeded, ie branch was within range
124144
asm_thumb_bgt_n(emit->as, label_num);
125145

126146
// 2 args
127147
} else if (strcmp(qstr_str(op), "movs") == 0) {
128148
if (!check_n_arg(op, n_args, 2)) {
129149
return;
130150
}
131-
uint rlo_dest = get_arg_rlo(op, pn_arg, 0);
132-
int i_src = get_arg_i(op, pn_arg, 1, 0xff);
151+
uint rlo_dest = get_arg_rlo(op, pn_args, 0);
152+
int i_src = get_arg_i(op, pn_args, 1, 0xff);
133153
asm_thumb_movs_rlo_i8(emit->as, rlo_dest, i_src);
134154
} else if (strcmp(qstr_str(op), "movw") == 0) {
135155
if (!check_n_arg(op, n_args, 2)) {
136156
return;
137157
}
138-
uint rlo_dest = get_arg_rlo(op, pn_arg, 0); // TODO can be reg lo or hi
139-
int i_src = get_arg_i(op, pn_arg, 1, 0xffff);
158+
uint rlo_dest = get_arg_rlo(op, pn_args, 0); // TODO can be reg lo or hi
159+
int i_src = get_arg_i(op, pn_args, 1, 0xffff);
140160
asm_thumb_movw_reg_i16(emit->as, rlo_dest, i_src);
141161
} else if (strcmp(qstr_str(op), "cmp") == 0) {
142162
if (!check_n_arg(op, n_args, 2)) {
143163
return;
144164
}
145-
uint rlo = get_arg_rlo(op, pn_arg, 0);
146-
int i8 = get_arg_i(op, pn_arg, 1, 0xff);
165+
uint rlo = get_arg_rlo(op, pn_args, 0);
166+
int i8 = get_arg_i(op, pn_args, 1, 0xff);
147167
asm_thumb_cmp_rlo_i8(emit->as, rlo, i8);
148168

149169
// 3 args
150170
} else if (strcmp(qstr_str(op), "subs") == 0) {
151171
if (!check_n_arg(op, n_args, 3)) {
152172
return;
153173
}
154-
uint rlo_dest = get_arg_rlo(op, pn_arg, 0);
155-
uint rlo_src = get_arg_rlo(op, pn_arg, 1);
156-
int i3_src = get_arg_i(op, pn_arg, 2, 0x7);
174+
uint rlo_dest = get_arg_rlo(op, pn_args, 0);
175+
uint rlo_src = get_arg_rlo(op, pn_args, 1);
176+
int i3_src = get_arg_i(op, pn_args, 2, 0x7);
157177
asm_thumb_subs_rlo_rlo_i3(emit->as, rlo_dest, rlo_src, i3_src);
158178

159179
// unknown op
@@ -166,6 +186,7 @@ static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, p
166186
const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
167187
emit_inline_thumb_start_pass,
168188
emit_inline_thumb_end_pass,
189+
emit_inline_thumb_count_params,
169190
emit_inline_thumb_label,
170191
emit_inline_thumb_op,
171192
};

0 commit comments

Comments
 (0)