@@ -168,57 +168,79 @@ static int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_
168168 return 0 ;
169169}
170170
171- #define RRR (0)
172- #define RRI8 (1)
173- #define RRI8_B (2)
171+ static const qstr_short_t BRANCH_OPCODE_NAMES [] = {
172+ MP_QSTR_bnone , MP_QSTR_beq , MP_QSTR_blt , MP_QSTR_bltu , MP_QSTR_ball ,
173+ MP_QSTR_bbc , MP_QSTR_ , MP_QSTR_ , MP_QSTR_bany , MP_QSTR_bne ,
174+ MP_QSTR_bge , MP_QSTR_bgeu , MP_QSTR_bnall , MP_QSTR_bbs ,
175+ };
176+
177+ #define RRR_R0 (1 << 4)
178+ #define RRR_R1 (2 << 4)
179+ #define RRR_R2 (3 << 4)
180+
181+ #define RRR (0)
182+ #define RRI8 (1)
174183
175- typedef struct _opcode_table_3arg_t {
184+ static const struct opcode_entry_t {
176185 qstr_short_t name ;
177- uint8_t type ;
178- uint8_t a0 : 4 ;
179- uint8_t a1 : 4 ;
180- } opcode_table_3arg_t ;
181-
182- static const opcode_table_3arg_t opcode_table_3arg [] = {
183- // arithmetic opcodes: reg, reg, reg
184- {MP_QSTR_and_ , RRR , 0 , 1 },
185- {MP_QSTR_or_ , RRR , 0 , 2 },
186- {MP_QSTR_xor , RRR , 0 , 3 },
187- {MP_QSTR_add , RRR , 0 , 8 },
188- {MP_QSTR_sub , RRR , 0 , 12 },
189- {MP_QSTR_mull , RRR , 2 , 8 },
190- {MP_QSTR_addx2 , RRR , 0 , 9 },
191- {MP_QSTR_addx4 , RRR , 0 , 10 },
192- {MP_QSTR_addx8 , RRR , 0 , 11 },
193- {MP_QSTR_subx2 , RRR , 0 , 13 },
194- {MP_QSTR_subx4 , RRR , 0 , 14 },
195- {MP_QSTR_subx8 , RRR , 0 , 15 },
196- {MP_QSTR_src , RRR , 1 , 8 },
197-
198- // load/store/addi opcodes: reg, reg, imm
199- // upper nibble of type encodes the range of the immediate arg
200- {MP_QSTR_l8ui , RRI8 | 0x10 , 2 , 0 },
201- {MP_QSTR_l16ui , RRI8 | 0x30 , 2 , 1 },
202- {MP_QSTR_l32i , RRI8 | 0x50 , 2 , 2 },
203- {MP_QSTR_s8i , RRI8 | 0x10 , 2 , 4 },
204- {MP_QSTR_s16i , RRI8 | 0x30 , 2 , 5 },
205- {MP_QSTR_s32i , RRI8 | 0x50 , 2 , 6 },
206- {MP_QSTR_l16si , RRI8 | 0x30 , 2 , 9 },
207- {MP_QSTR_addi , RRI8 | 0x00 , 2 , 12 },
208-
209- // branch opcodes: reg, reg, label
210- {MP_QSTR_ball , RRI8_B , ASM_XTENSA_CC_ALL , 0 },
211- {MP_QSTR_bany , RRI8_B , ASM_XTENSA_CC_ANY , 0 },
212- {MP_QSTR_bbc , RRI8_B , ASM_XTENSA_CC_BC , 0 },
213- {MP_QSTR_bbs , RRI8_B , ASM_XTENSA_CC_BS , 0 },
214- {MP_QSTR_beq , RRI8_B , ASM_XTENSA_CC_EQ , 0 },
215- {MP_QSTR_bge , RRI8_B , ASM_XTENSA_CC_GE , 0 },
216- {MP_QSTR_bgeu , RRI8_B , ASM_XTENSA_CC_GEU , 0 },
217- {MP_QSTR_blt , RRI8_B , ASM_XTENSA_CC_LT , 0 },
218- {MP_QSTR_bltu , RRI8_B , ASM_XTENSA_CC_LTU , 0 },
219- {MP_QSTR_bnall , RRI8_B , ASM_XTENSA_CC_NALL , 0 },
220- {MP_QSTR_bne , RRI8_B , ASM_XTENSA_CC_NE , 0 },
221- {MP_QSTR_bnone , RRI8_B , ASM_XTENSA_CC_NONE , 0 },
186+ uint16_t operands : 2 ;
187+ uint16_t op2 : 4 ;
188+ uint16_t op1 : 4 ;
189+ uint16_t op0 : 4 ;
190+ // 2 bits available here
191+ uint32_t r : 6 ;
192+ uint32_t s : 6 ;
193+ uint32_t t : 6 ;
194+ uint32_t shift : 4 ;
195+ uint32_t kind : 1 ;
196+ // 13 bits available here
197+ } OPCODE_TABLE [] = {
198+ { MP_QSTR_abs_ , 2 , 6 , 0 , 0 , RRR_R0 , 1 , RRR_R1 , 0 , RRR },
199+ { MP_QSTR_add , 3 , 8 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
200+ { MP_QSTR_addi , 3 , 0 , 0 , 2 , 12 , RRR_R1 , RRR_R0 , 0 , RRI8 },
201+ { MP_QSTR_addx2 , 3 , 9 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
202+ { MP_QSTR_addx4 , 3 , 10 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
203+ { MP_QSTR_addx8 , 3 , 11 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
204+ { MP_QSTR_and_ , 3 , 1 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
205+ { MP_QSTR_callx0 , 1 , 0 , 0 , 0 , 0 , RRR_R0 , 12 , 0 , RRR },
206+ { MP_QSTR_jx , 1 , 0 , 0 , 0 , 0 , RRR_R0 , 10 , 0 , RRR },
207+ { MP_QSTR_l16si , 3 , 0 , 0 , 2 , 9 , RRR_R1 , RRR_R0 , 3 , RRI8 },
208+ { MP_QSTR_l16ui , 3 , 0 , 0 , 2 , 1 , RRR_R1 , RRR_R0 , 3 , RRI8 },
209+ { MP_QSTR_l32i , 3 , 0 , 0 , 2 , 2 , RRR_R1 , RRR_R0 , 5 , RRI8 },
210+ { MP_QSTR_l8ui , 3 , 0 , 0 , 2 , 0 , RRR_R1 , RRR_R0 , 1 , RRI8 },
211+ { MP_QSTR_mull , 3 , 8 , 2 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
212+ { MP_QSTR_neg , 2 , 6 , 0 , 0 , RRR_R0 , 0 , RRR_R1 , 0 , RRR },
213+ { MP_QSTR_nop , 0 , 0 , 0 , 0 , 2 , 0 , 15 , 0 , RRR },
214+ { MP_QSTR_nsa , 2 , 4 , 0 , 0 , 14 , RRR_R1 , RRR_R0 , 0 , RRR },
215+ { MP_QSTR_nsau , 2 , 4 , 0 , 0 , 15 , RRR_R1 , RRR_R0 , 0 , RRR },
216+ { MP_QSTR_or_ , 3 , 2 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
217+ { MP_QSTR_s16i , 3 , 0 , 0 , 2 , 5 , RRR_R1 , RRR_R0 , 3 , RRI8 },
218+ { MP_QSTR_s32i , 3 , 0 , 0 , 2 , 6 , RRR_R1 , RRR_R0 , 5 , RRI8 },
219+ { MP_QSTR_s8i , 3 , 0 , 0 , 2 , 4 , RRR_R1 , RRR_R0 , 1 , RRI8 },
220+ { MP_QSTR_sll , 2 , 10 , 1 , 0 , RRR_R0 , RRR_R1 , 0 , 0 , RRR },
221+ { MP_QSTR_sra , 2 , 11 , 1 , 0 , RRR_R0 , 0 , RRR_R1 , 0 , RRR },
222+ { MP_QSTR_src , 3 , 8 , 1 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
223+ { MP_QSTR_srl , 2 , 9 , 1 , 0 , RRR_R0 , 0 , RRR_R1 , 0 , RRR },
224+ { MP_QSTR_ssa8b , 1 , 4 , 0 , 0 , 3 , RRR_R0 , 0 , 0 , RRR },
225+ { MP_QSTR_ssa8l , 1 , 4 , 0 , 0 , 2 , RRR_R0 , 0 , 0 , RRR },
226+ { MP_QSTR_ssl , 1 , 4 , 0 , 0 , 1 , RRR_R0 , 0 , 0 , RRR },
227+ { MP_QSTR_ssr , 1 , 4 , 0 , 0 , 0 , RRR_R0 , 0 , 0 , RRR },
228+ { MP_QSTR_sub , 3 , 12 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
229+ { MP_QSTR_subx2 , 3 , 13 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
230+ { MP_QSTR_subx4 , 3 , 14 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
231+ { MP_QSTR_subx8 , 3 , 15 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
232+ { MP_QSTR_xor , 3 , 3 , 0 , 0 , RRR_R0 , RRR_R1 , RRR_R2 , 0 , RRR },
233+ #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
234+ { MP_QSTR_dsync , 0 , 0 , 0 , 0 , 2 , 0 , 3 , 0 , RRR },
235+ { MP_QSTR_esync , 0 , 0 , 0 , 0 , 2 , 0 , 2 , 0 , RRR },
236+ { MP_QSTR_extw , 0 , 0 , 0 , 0 , 2 , 0 , 13 , 0 , RRR },
237+ { MP_QSTR_ill , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , RRR },
238+ { MP_QSTR_isync , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , RRR },
239+ { MP_QSTR_memw , 0 , 0 , 0 , 0 , 2 , 0 , 12 , 0 , RRR },
240+ { MP_QSTR_rer , 2 , 4 , 0 , 0 , 6 , RRR_R1 , RRR_R0 , 0 , RRR },
241+ { MP_QSTR_rsync , 0 , 0 , 0 , 0 , 2 , 0 , 1 , 0 , RRR },
242+ { MP_QSTR_wer , 2 , 4 , 0 , 0 , 7 , RRR_R1 , RRR_R0 , 0 , RRR },
243+ #endif
222244};
223245
224246// The index of the first four qstrs matches the CCZ condition value to be
@@ -228,75 +250,64 @@ static const qstr_short_t BCCZ_OPCODES[] = {
228250 MP_QSTR_beqz_n , MP_QSTR_bnez_n
229251};
230252
231- #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
232- typedef struct _single_opcode_t {
233- qstr_short_t name ;
234- uint16_t value ;
235- } single_opcode_t ;
236-
237- static const single_opcode_t NOARGS_OPCODES [] = {
238- {MP_QSTR_dsync , 0x2030 },
239- {MP_QSTR_esync , 0x2020 },
240- {MP_QSTR_extw , 0x20D0 },
241- {MP_QSTR_ill , 0x0000 },
242- {MP_QSTR_isync , 0x2000 },
243- {MP_QSTR_memw , 0x20C0 },
244- {MP_QSTR_rsync , 0x2010 },
245- };
246- #endif
247-
248253static void emit_inline_xtensa_op (emit_inline_asm_t * emit , qstr op , mp_uint_t n_args , mp_parse_node_t * pn_args ) {
249254 size_t op_len ;
250255 const char * op_str = (const char * )qstr_data (op , & op_len );
251256
257+ for (size_t index = 0 ; index < MP_ARRAY_SIZE (OPCODE_TABLE ); index ++ ) {
258+ const struct opcode_entry_t * entry = & OPCODE_TABLE [index ];
259+ if (entry -> name == op ) {
260+ if (n_args != entry -> operands ) {
261+ goto unknown_op ;
262+ }
263+
264+ uint32_t op24 = ((entry -> r & 0x0F ) << 12 ) | ((entry -> s & 0x0F ) << 8 ) | ((entry -> t & 0x0F ) << 4 ) | entry -> op0 ;
265+ if (entry -> kind == RRR ) {
266+ op24 |= (entry -> op2 << 20 ) | (entry -> op1 << 16 );
267+ } else {
268+ int min = 0 ;
269+ int max = 0 ;
270+ int shift = entry -> shift ;
271+ if (shift > 0 ) {
272+ shift >>= 1 ;
273+ max = 0xFF << shift ;
274+ } else {
275+ min = -128 ;
276+ max = 127 ;
277+ }
278+ uint32_t immediate = get_arg_i (emit , op_str , pn_args [2 ], min , max );
279+ op24 |= ((immediate >> shift ) & 0xFF ) << 16 ;
280+ }
281+ if (entry -> r >= RRR_R0 ) {
282+ op24 |= get_arg_reg (emit , op_str , pn_args [(entry -> r >> 4 ) - 1 ]) << 12 ;
283+ }
284+ if (entry -> s >= RRR_R0 ) {
285+ op24 |= get_arg_reg (emit , op_str , pn_args [(entry -> s >> 4 ) - 1 ]) << 8 ;
286+ }
287+ if (entry -> t >= RRR_R0 ) {
288+ op24 |= get_arg_reg (emit , op_str , pn_args [(entry -> t >> 4 ) - 1 ]) << 4 ;
289+ }
290+ asm_xtensa_op24 (& emit -> as , op24 );
291+ return ;
292+ }
293+ }
294+
252295 if (n_args == 0 ) {
253296 if (op == MP_QSTR_ret_n || op == MP_QSTR_ret ) {
254297 asm_xtensa_op_ret_n (& emit -> as );
255298 return ;
256- } else if (op == MP_QSTR_nop ) {
257- asm_xtensa_op24 (& emit -> as , 0x20F0 );
258- return ;
259299 } else if (op == MP_QSTR_nop_n ) {
260300 asm_xtensa_op16 (& emit -> as , 0xF03D );
261301 return ;
262302 }
263- #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
264- for (size_t index = 0 ; index < MP_ARRAY_SIZE (NOARGS_OPCODES ); index ++ ) {
265- const single_opcode_t * opcode = & NOARGS_OPCODES [index ];
266- if (op == opcode -> name ) {
267- asm_xtensa_op24 (& emit -> as , opcode -> value );
268- return ;
269- }
270- }
271- #endif
272-
273303 goto unknown_op ;
274-
275304 } else if (n_args == 1 ) {
276- if (op == MP_QSTR_callx0 ) {
277- uint r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
278- asm_xtensa_op_callx0 (& emit -> as , r0 );
279- } else if (op == MP_QSTR_j ) {
305+ if (op == MP_QSTR_j ) {
280306 int label = get_arg_label (emit , op_str , pn_args [0 ]);
281307 asm_xtensa_j_label (& emit -> as , label );
282- } else if (op == MP_QSTR_jx ) {
283- uint r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
284- asm_xtensa_op_jx (& emit -> as , r0 );
285- } else if (op == MP_QSTR_ssl ) {
286- mp_uint_t r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
287- asm_xtensa_op_ssl (& emit -> as , r0 );
288- } else if (op == MP_QSTR_ssr ) {
289- mp_uint_t r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
290- asm_xtensa_op_ssr (& emit -> as , r0 );
291308 } else if (op == MP_QSTR_ssai ) {
292309 mp_uint_t sa = get_arg_i (emit , op_str , pn_args [0 ], 0 , 31 );
293310 asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 4 , 4 , sa & 0x0F , (sa >> 4 ) & 0x01 ));
294- } else if (op == MP_QSTR_ssa8b ) {
295- mp_uint_t r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
296- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 4 , 3 , r0 , 0 ));
297- } else if (op == MP_QSTR_ssa8l ) {
298- mp_uint_t r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
299- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 4 , 2 , r0 , 0 ));
300311 } else if (op == MP_QSTR_call0 ) {
301312 mp_uint_t label = get_arg_label (emit , op_str , pn_args [0 ]);
302313 asm_xtensa_call0 (& emit -> as , label );
@@ -310,7 +321,6 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
310321 } else {
311322 goto unknown_op ;
312323 }
313-
314324 } else if (n_args == 2 ) {
315325 uint r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
316326 for (size_t index = 0 ; index < MP_ARRAY_SIZE (BCCZ_OPCODES ); index ++ ) {
@@ -328,27 +338,6 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
328338 // for convenience we emit l32r if the integer doesn't fit in movi
329339 uint32_t imm = get_arg_i (emit , op_str , pn_args [1 ], 0 , 0 );
330340 asm_xtensa_mov_reg_i32 (& emit -> as , r0 , imm );
331- } else if (op == MP_QSTR_abs_ ) {
332- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
333- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 6 , r0 , 1 , r1 ));
334- } else if (op == MP_QSTR_neg ) {
335- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
336- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 6 , r0 , 0 , r1 ));
337- } else if (op == MP_QSTR_sll ) {
338- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
339- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 1 , 10 , r0 , r1 , 0 ));
340- } else if (op == MP_QSTR_sra ) {
341- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
342- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 1 , 11 , r0 , 0 , r1 ));
343- } else if (op == MP_QSTR_srl ) {
344- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
345- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 1 , 9 , r0 , 0 , r1 ));
346- } else if (op == MP_QSTR_nsa ) {
347- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
348- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 4 , 14 , r1 , r0 ));
349- } else if (op == MP_QSTR_nsau ) {
350- mp_uint_t r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
351- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , 0 , 4 , 15 , r1 , r0 ));
352341 } else if (op == MP_QSTR_l32r ) {
353342 mp_uint_t label = get_arg_label (emit , op_str , pn_args [1 ]);
354343 asm_xtensa_l32r (& emit -> as , r0 , label );
@@ -377,34 +366,13 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
377366 {
378367 goto unknown_op ;
379368 }
380-
381369 } else if (n_args == 3 ) {
382- // search table for 3 arg instructions
383- for (uint i = 0 ; i < MP_ARRAY_SIZE (opcode_table_3arg ); i ++ ) {
384- const opcode_table_3arg_t * o = & opcode_table_3arg [i ];
385- if (op == o -> name ) {
386- uint r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
387- uint r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
388- if (o -> type == RRR ) {
389- uint r2 = get_arg_reg (emit , op_str , pn_args [2 ]);
390- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRR (0 , o -> a0 , o -> a1 , r0 , r1 , r2 ));
391- } else if (o -> type == RRI8_B ) {
392- int label = get_arg_label (emit , op_str , pn_args [2 ]);
393- asm_xtensa_bcc_reg_reg_label (& emit -> as , o -> a0 , r0 , r1 , label );
394- } else {
395- int shift , min , max ;
396- if ((o -> type & 0xf0 ) == 0 ) {
397- shift = 0 ;
398- min = -128 ;
399- max = 127 ;
400- } else {
401- shift = (o -> type & 0xf0 ) >> 5 ;
402- min = 0 ;
403- max = 0xff << shift ;
404- }
405- uint32_t imm = get_arg_i (emit , op_str , pn_args [2 ], min , max );
406- asm_xtensa_op24 (& emit -> as , ASM_XTENSA_ENCODE_RRI8 (o -> a0 , o -> a1 , r1 , r0 , (imm >> shift ) & 0xff ));
407- }
370+ for (size_t index = 0 ; index < MP_ARRAY_SIZE (BRANCH_OPCODE_NAMES ); index ++ ) {
371+ if (BRANCH_OPCODE_NAMES [index ] == op ) {
372+ int r0 = get_arg_reg (emit , op_str , pn_args [0 ]);
373+ int r1 = get_arg_reg (emit , op_str , pn_args [1 ]);
374+ int label = get_arg_label (emit , op_str , pn_args [2 ]);
375+ asm_xtensa_bcc_reg_reg_label (& emit -> as , index , r0 , r1 , label );
408376 return ;
409377 }
410378 }
0 commit comments