@@ -170,6 +170,58 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n
170170 return 0 ;
171171}
172172
173+ STATIC mp_uint_t get_arg_reglist (emit_inline_asm_t * emit , const char * op , mp_parse_node_t pn ) {
174+ // a register list looks like {r0, r1, r2} and is parsed as a Python set
175+
176+ if (!MP_PARSE_NODE_IS_STRUCT_KIND (pn , PN_atom_brace )) {
177+ goto bad_arg ;
178+ }
179+
180+ mp_parse_node_struct_t * pns = (mp_parse_node_struct_t * )pn ;
181+ assert (MP_PARSE_NODE_STRUCT_NUM_NODES (pns ) == 1 ); // should always be
182+ pn = pns -> nodes [0 ];
183+
184+ mp_uint_t reglist = 0 ;
185+
186+ if (MP_PARSE_NODE_IS_ID (pn )) {
187+ // set with one element
188+ reglist |= 1 << get_arg_reg (emit , op , pn , 15 );
189+ } else if (MP_PARSE_NODE_IS_STRUCT (pn )) {
190+ pns = (mp_parse_node_struct_t * )pn ;
191+ if (MP_PARSE_NODE_STRUCT_KIND (pns ) == PN_dictorsetmaker ) {
192+ assert (MP_PARSE_NODE_IS_STRUCT (pns -> nodes [1 ])); // should succeed
193+ mp_parse_node_struct_t * pns1 = (mp_parse_node_struct_t * )pns -> nodes [1 ];
194+ if (MP_PARSE_NODE_STRUCT_KIND (pns1 ) == PN_dictorsetmaker_list ) {
195+ // set with multiple elements
196+
197+ // get first element of set (we rely on get_arg_reg to catch syntax errors)
198+ reglist |= 1 << get_arg_reg (emit , op , pns -> nodes [0 ], 15 );
199+
200+ // get tail elements (2nd, 3rd, ...)
201+ mp_parse_node_t * nodes ;
202+ int n = mp_parse_node_extract_list (& pns1 -> nodes [0 ], PN_dictorsetmaker_list2 , & nodes );
203+
204+ // process rest of elements
205+ for (int i = 0 ; i < n ; i ++ ) {
206+ reglist |= 1 << get_arg_reg (emit , op , nodes [i ], 15 );
207+ }
208+ } else {
209+ goto bad_arg ;
210+ }
211+ } else {
212+ goto bad_arg ;
213+ }
214+ } else {
215+ goto bad_arg ;
216+ }
217+
218+ return reglist ;
219+
220+ bad_arg :
221+ emit_inline_thumb_error_exc (emit , mp_obj_new_exception_msg_varg (& mp_type_SyntaxError , "'%s' expects {r0, r1, ...}" , op ));
222+ return 0 ;
223+ }
224+
173225STATIC int get_arg_i (emit_inline_asm_t * emit , const char * op , mp_parse_node_t pn , int fit_mask ) {
174226 if (!MP_PARSE_NODE_IS_SMALL_INT (pn )) {
175227 emit_inline_thumb_error_exc (emit , mp_obj_new_exception_msg_varg (& mp_type_SyntaxError , "'%s' expects an integer" , op ));
@@ -284,12 +336,26 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
284336 int label_num = get_arg_label (emit , op_str , pn_args [0 ]);
285337 // TODO check that this succeeded, ie branch was within range
286338 asm_thumb_bcc_n (emit -> as , cc , label_num );
287- } else if (strcmp (op_str , "cpsid" )) {
339+ } else if (strcmp (op_str , "cpsid" ) == 0 ) {
288340 // TODO check pn_args[0] == i
289341 asm_thumb_op16 (emit -> as , ASM_THUMB_OP_CPSID_I );
290- } else if (strcmp (op_str , "cpsie" )) {
342+ } else if (strcmp (op_str , "cpsie" ) == 0 ) {
291343 // TODO check pn_args[0] == i
292344 asm_thumb_op16 (emit -> as , ASM_THUMB_OP_CPSIE_I );
345+ } else if (strcmp (op_str , "push" ) == 0 ) {
346+ mp_uint_t reglist = get_arg_reglist (emit , op_str , pn_args [0 ]);
347+ if ((reglist & 0xff00 ) == 0 ) {
348+ asm_thumb_op16 (emit -> as , 0xb400 | reglist );
349+ } else {
350+ asm_thumb_op32 (emit -> as , 0xe92d , reglist );
351+ }
352+ } else if (strcmp (op_str , "pop" ) == 0 ) {
353+ mp_uint_t reglist = get_arg_reglist (emit , op_str , pn_args [0 ]);
354+ if ((reglist & 0xff00 ) == 0 ) {
355+ asm_thumb_op16 (emit -> as , 0xbc00 | reglist );
356+ } else {
357+ asm_thumb_op32 (emit -> as , 0xe8bd , reglist );
358+ }
293359 } else {
294360 goto unknown_op ;
295361 }
0 commit comments