@@ -81,45 +81,36 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, int label_num, qstr
8181 asm_thumb_label_assign (emit -> as , label_num );
8282}
8383
84- STATIC bool check_n_arg (qstr op , int n_args , int wanted_n_args ) {
85- if (wanted_n_args == n_args ) {
86- return true;
87- } else {
88- printf ("SyntaxError: '%s' expects %d arguments'\n" , qstr_str (op ), wanted_n_args );
89- return false;
90- }
91- }
92-
93- STATIC uint get_arg_rlo (qstr op , mp_parse_node_t * pn_args , int wanted_arg_num ) {
84+ STATIC uint get_arg_rlo (const char * op , mp_parse_node_t * pn_args , int wanted_arg_num ) {
9485 if (!MP_PARSE_NODE_IS_ID (pn_args [wanted_arg_num ])) {
95- printf ("SyntaxError: '%s' expects a register in position %d\n" , qstr_str ( op ) , wanted_arg_num );
86+ printf ("SyntaxError: '%s' expects a register in position %d\n" , op , wanted_arg_num );
9687 return 0 ;
9788 }
9889 qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG (pn_args [wanted_arg_num ]);
9990 const char * reg_str = qstr_str (reg_qstr );
10091 if (!(strlen (reg_str ) == 2 && reg_str [0 ] == 'r' && ('0' <= reg_str [1 ] && reg_str [1 ] <= '7' ))) {
101- printf ("SyntaxError: '%s' expects a register in position %d\n" , qstr_str ( op ) , wanted_arg_num );
92+ printf ("SyntaxError: '%s' expects a register in position %d\n" , op , wanted_arg_num );
10293 return 0 ;
10394 }
10495 return reg_str [1 ] - '0' ;
10596}
10697
107- STATIC int get_arg_i (qstr op , mp_parse_node_t * pn_args , int wanted_arg_num , int fit_mask ) {
98+ STATIC int get_arg_i (const char * op , mp_parse_node_t * pn_args , int wanted_arg_num , int fit_mask ) {
10899 if (!MP_PARSE_NODE_IS_SMALL_INT (pn_args [wanted_arg_num ])) {
109- printf ("SyntaxError: '%s' expects an integer in position %d\n" , qstr_str ( op ) , wanted_arg_num );
100+ printf ("SyntaxError: '%s' expects an integer in position %d\n" , op , wanted_arg_num );
110101 return 0 ;
111102 }
112103 int i = MP_PARSE_NODE_LEAF_SMALL_INT (pn_args [wanted_arg_num ]);
113104 if ((i & (~fit_mask )) != 0 ) {
114- printf ("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n" , qstr_str ( op ) , i , fit_mask );
105+ printf ("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n" , op , i , fit_mask );
115106 return 0 ;
116107 }
117108 return i ;
118109}
119110
120- STATIC int get_arg_label (emit_inline_asm_t * emit , qstr op , mp_parse_node_t * pn_args , int wanted_arg_num ) {
111+ STATIC int get_arg_label (emit_inline_asm_t * emit , const char * op , mp_parse_node_t * pn_args , int wanted_arg_num ) {
121112 if (!MP_PARSE_NODE_IS_ID (pn_args [wanted_arg_num ])) {
122- printf ("SyntaxError: '%s' expects a label in position %d\n" , qstr_str ( op ) , wanted_arg_num );
113+ printf ("SyntaxError: '%s' expects a label in position %d\n" , op , wanted_arg_num );
123114 return 0 ;
124115 }
125116 qstr label_qstr = MP_PARSE_NODE_LEAF_ARG (pn_args [wanted_arg_num ]);
@@ -135,6 +126,24 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_a
135126 return 0 ;
136127}
137128
129+ typedef struct _cc_name_t { byte cc ; byte name [2 ]; } cc_name_t ;
130+ STATIC const cc_name_t cc_name_table [] = {
131+ {THUMB_CC_EQ , "eq" },
132+ {THUMB_CC_NE , "ne" },
133+ {THUMB_CC_CS , "cs" },
134+ {THUMB_CC_CC , "cc" },
135+ {THUMB_CC_MI , "mi" },
136+ {THUMB_CC_PL , "pl" },
137+ {THUMB_CC_VS , "vs" },
138+ {THUMB_CC_VC , "vc" },
139+ {THUMB_CC_HI , "hi" },
140+ {THUMB_CC_LS , "ls" },
141+ {THUMB_CC_GE , "ge" },
142+ {THUMB_CC_LT , "lt" },
143+ {THUMB_CC_GT , "gt" },
144+ {THUMB_CC_LE , "le" },
145+ };
146+
138147STATIC void emit_inline_thumb_op (emit_inline_asm_t * emit , qstr op , int n_args , mp_parse_node_t * pn_args ) {
139148 // TODO perhaps make two tables:
140149 // one_args =
@@ -146,60 +155,86 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
146155 // three_args =
147156 // "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
148157
149- // 1 arg
150- if (strcmp (qstr_str (op ), "b" ) == 0 ) {
151- if (!check_n_arg (op , n_args , 1 )) {
152- return ;
153- }
154- int label_num = get_arg_label (emit , op , pn_args , 0 );
155- // TODO check that this succeeded, ie branch was within range
156- asm_thumb_b_n (emit -> as , label_num );
157- } else if (strcmp (qstr_str (op ), "bgt" ) == 0 ) {
158- if (!check_n_arg (op , n_args , 1 )) {
159- return ;
160- }
161- int label_num = get_arg_label (emit , op , pn_args , 0 );
162- // TODO check that this succeeded, ie branch was within range
163- asm_thumb_bcc_n (emit -> as , THUMB_CC_GT , label_num );
164-
165- // 2 args
166- } else if (strcmp (qstr_str (op ), "movs" ) == 0 ) {
167- if (!check_n_arg (op , n_args , 2 )) {
168- return ;
158+ const char * op_str = qstr_str (op );
159+ uint op_len = strlen (op_str );
160+
161+ if (n_args == 0 ) {
162+ if (strcmp (op_str , "ite.ge" ) == 0 ) { // TODO correct name for this op?
163+ asm_thumb_ite_ge (emit -> as );
164+ } else {
165+ goto unknown_op ;
169166 }
170- uint rlo_dest = get_arg_rlo (op , pn_args , 0 );
171- int i_src = get_arg_i (op , pn_args , 1 , 0xff );
172- asm_thumb_movs_rlo_i8 (emit -> as , rlo_dest , i_src );
173- } else if (strcmp (qstr_str (op ), "movw" ) == 0 ) {
174- if (!check_n_arg (op , n_args , 2 )) {
175- return ;
167+
168+ } else if (n_args == 1 ) {
169+ if (strcmp (op_str , "b" ) == 0 ) {
170+ int label_num = get_arg_label (emit , op_str , pn_args , 0 );
171+ // TODO check that this succeeded, ie branch was within range
172+ asm_thumb_b_n (emit -> as , label_num );
173+ } else if (op_str [0 ] == 'b' && op_len == 3 ) {
174+ uint cc = -1 ;
175+ for (uint i = 0 ; i < (sizeof cc_name_table ) / (sizeof cc_name_table [0 ]); i ++ ) {
176+ if (op_str [1 ] == cc_name_table [i ].name [0 ] && op_str [2 ] == cc_name_table [i ].name [1 ]) {
177+ cc = cc_name_table [i ].cc ;
178+ }
179+ }
180+ if (cc == -1 ) {
181+ goto unknown_op ;
182+ }
183+ int label_num = get_arg_label (emit , op_str , pn_args , 0 );
184+ // TODO check that this succeeded, ie branch was within range
185+ asm_thumb_bcc_n (emit -> as , cc , label_num );
186+ } else {
187+ goto unknown_op ;
176188 }
177- uint rlo_dest = get_arg_rlo (op , pn_args , 0 ); // TODO can be reg lo or hi
178- int i_src = get_arg_i (op , pn_args , 1 , 0xffff );
179- asm_thumb_movw_reg_i16 (emit -> as , rlo_dest , i_src );
180- } else if (strcmp (qstr_str (op ), "cmp" ) == 0 ) {
181- if (!check_n_arg (op , n_args , 2 )) {
182- return ;
189+
190+ } else if (n_args == 2 ) {
191+ if (strcmp (op_str , "mov" ) == 0 ) {
192+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 );
193+ uint rlo_src = get_arg_rlo (op_str , pn_args , 1 );
194+ asm_thumb_mov_reg_reg (emit -> as , rlo_dest , rlo_src );
195+ } else if (strcmp (op_str , "movs" ) == 0 ) {
196+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 );
197+ int i_src = get_arg_i (op_str , pn_args , 1 , 0xff );
198+ asm_thumb_movs_rlo_i8 (emit -> as , rlo_dest , i_src );
199+ } else if (strcmp (op_str , "movw" ) == 0 ) {
200+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 ); // TODO can be reg lo or hi
201+ int i_src = get_arg_i (op_str , pn_args , 1 , 0xffff );
202+ asm_thumb_movw_reg_i16 (emit -> as , rlo_dest , i_src );
203+ } else if (strcmp (op_str , "movt" ) == 0 ) {
204+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 ); // TODO can be reg lo or hi
205+ int i_src = get_arg_i (op_str , pn_args , 1 , 0xffff );
206+ asm_thumb_movt_reg_i16 (emit -> as , rlo_dest , i_src );
207+ } else if (strcmp (op_str , "cmp" ) == 0 ) {
208+ uint rlo = get_arg_rlo (op_str , pn_args , 0 );
209+ int i8 = get_arg_i (op_str , pn_args , 1 , 0xff );
210+ asm_thumb_cmp_rlo_i8 (emit -> as , rlo , i8 );
211+ } else {
212+ goto unknown_op ;
183213 }
184- uint rlo = get_arg_rlo (op , pn_args , 0 );
185- int i8 = get_arg_i (op , pn_args , 1 , 0xff );
186- asm_thumb_cmp_rlo_i8 (emit -> as , rlo , i8 );
187-
188- // 3 args
189- } else if (strcmp (qstr_str (op ), "subs" ) == 0 ) {
190- if (!check_n_arg (op , n_args , 3 )) {
191- return ;
214+
215+ } else if (n_args == 3 ) {
216+ if (strcmp (op_str , "add" ) == 0 ) {
217+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 );
218+ uint rlo_src_a = get_arg_rlo (op_str , pn_args , 1 );
219+ uint rlo_src_b = get_arg_rlo (op_str , pn_args , 2 );
220+ asm_thumb_add_reg_reg_reg (emit -> as , rlo_dest , rlo_src_a , rlo_src_b );
221+ } else if (strcmp (op_str , "subs" ) == 0 ) {
222+ uint rlo_dest = get_arg_rlo (op_str , pn_args , 0 );
223+ uint rlo_src = get_arg_rlo (op_str , pn_args , 1 );
224+ int i3_src = get_arg_i (op_str , pn_args , 2 , 0x7 );
225+ asm_thumb_subs_rlo_rlo_i3 (emit -> as , rlo_dest , rlo_src , i3_src );
226+ } else {
227+ goto unknown_op ;
192228 }
193- uint rlo_dest = get_arg_rlo (op , pn_args , 0 );
194- uint rlo_src = get_arg_rlo (op , pn_args , 1 );
195- int i3_src = get_arg_i (op , pn_args , 2 , 0x7 );
196- asm_thumb_subs_rlo_rlo_i3 (emit -> as , rlo_dest , rlo_src , i3_src );
197229
198- // unknown op
199230 } else {
200- printf ("SyntaxError: unsupported ARM Thumb instruction '%s'\n" , qstr_str (op ));
201- return ;
231+ goto unknown_op ;
202232 }
233+
234+ return ;
235+
236+ unknown_op :
237+ printf ("SyntaxError: unsupported ARM Thumb instruction '%s' with %d arguments\n" , op_str , n_args );
203238}
204239
205240const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
0 commit comments