8000 py/emitinlinextensa: Add the rest of LX6 opcodes to the assembler. · micropython/micropython@ad02cf3 · GitHub
[go: up one dir, main page]

Skip to content

Commit ad02cf3

Browse files
committed
py/emitinlinextensa: Add the rest of LX6 opcodes to the assembler.
This commit expands the Xtensa inline assembler to support most if not all opcodes available on the ESP8266 and LX6 Xtensa cores. This is meant as a stepping stone to add inline assembler support for the ESP32, along to windowed-specific opcodes and additional opcodes that are present only on the LX7 core (ESP32-S3 and later). New opcodes being added are covered by tests, and the provided tests were expanded to also include opcodes available in the existing implementation. Given that the ESP8266 space requirements are tighter than ESP32's, certain opcodes that won't be commonly used have been put behind a define to save some space in the general use case. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent e07730c commit ad02cf3

16 files changed

+1102
-11
lines changed

py/asmxtensa.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define WORD_SIZE (4)
3838
#define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80))
3939
#define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800))
40+
#define SIGNED_FIT18(x) ((((x) & 0xfffc0000) == 0) || (((x) & 0xfffc0000) == 0xfffc0000))
4041

4142
#define ET_OUT_OF_RANGE MP_ERROR_TEXT("ERROR: xtensa %q out of range")
4243

@@ -266,4 +267,40 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) {
266267
asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8);
267268
}
268269

270+
void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition) {
271+
uint32_t dest = get_label_dest(as, label);
272+
int32_t rel = dest - as->base.code_offset - 4;
273+
if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) {
274+
mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bit_branch);
275+
}
276+
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, condition | ((bit >> 4) & 0x01), reg, bit & 0x0F, rel & 0xFF));
277+
}
278+
279+
void asm_xtensa_immediate_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t immediate, mp_uint_t label, mp_uint_t cond) {
280+
uint32_t dest = get_label_dest(as, label);
281+
int32_t rel = dest - as->base.code_offset - 4;
282+
if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) {
283+
mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_immediate_branch);
284+
}
285+
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI8(6, immediate, reg, (cond >> 2) & 0x03, cond & 0x03, rel));
286+
}
287+
288+
void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label) {
289+
uint32_t dest = get_label_dest(as, label);
290+
int32_t rel = dest - as->base.code_offset - 3;
291+
if (as->base.pass == MP_ASM_PASS_EMIT && (((rel & 0x3) != 0) || !SIGNED_FIT18(rel))) {
292+
mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_call0);
293+
}
294+
asm_xtensa_op_call0(as, rel);
295+
}
296+
297+
void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label) {
298+
uint32_t dest = get_label_dest(as, label);
299+
int32_t rel = dest - as->base.code_offset;
300+
if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT18(rel)) {
301+
mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_l32r);
302+
}
303+
asm_xtensa_op_l32r(as, reg, as->base.code_offset, dest);
304+
}
305+
269306
#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN

py/asmxtensa.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@
6464
#define ASM_XTENSA_REG_A14 (14)
6565
#define ASM_XTENSA_REG_A15 (15)
6666

67-
// for bccz
67+
// for bccz and bcci
6868
#define ASM_XTENSA_CCZ_EQ (0)
6969
#define ASM_XTENSA_CCZ_NE (1)
70+
#define ASM_XTENSA_CCZ_LT (2)
71+
#define ASM_XTENSA_CCZ_GE (3)
7072

7173
// for bcc and setcc
7274
#define ASM_XTENSA_CC_NONE (0)
@@ -295,6 +297,10 @@ void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, u
295297
void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset);
296298
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx);
297299
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
300+
void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition);
301+
void asm_xtensa_immediate_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t immediate, mp_uint_t label, mp_uint_t cond);
302+
void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label);
303+
void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label);
298304

299305
// Holds a pointer to mp_fun_table
300306
#define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15

py/emitinlinextensa.c

Lines changed: 225 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,29 @@ static int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_
169169
return 0;
170170
}
171171

172+
static const int8_t B4CONST[] = {
173+
-1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128
174+
};
175+
176+
static mp_int_t encode_b4const(mp_int_t immediate) {
177+
for (size_t index = 0; index < MP_ARRAY_SIZE(B4CONST); index++) {
178+
if (immediate == (mp_int_t)(B4CONST[index])) {
179+
return index;
180+
}
181+
}
182+
return immediate == 256 ? 15 : -1;
183+
}
184+
172185
#define RRR (0)
173186
#define RRI8 (1)
174187
#define RRI8_B (2)
188+
#define BRI8 (3)
189+
190+
#define UNSIGNED 1
191+
#define BUILD_BRANCH_IMM(cond) (2 | ((cond) << 2))
175192

176193
typedef struct _opcode_table_3arg_t {
177-
uint16_t name; // actually a qstr, which should fit in 16 bits
194+
qstr_short_t name;
178195
uint8_t type;
179196
uint8_t a0 : 4;
180197
uint8_t a1 : 4;
@@ -188,6 +205,13 @@ static const opcode_table_3arg_t opcode_table_3arg[] = {
188205
{MP_QSTR_add, RRR, 0, 8},
189206
{MP_QSTR_sub, RRR, 0, 12},
190207
{MP_QSTR_mull, RRR, 2, 8},
208+
{MP_QSTR_addx2, RRR, 0, 9},
209+
{MP_QSTR_addx4, RRR, 0, 10},
210+
{MP_QSTR_addx8, RRR, 0, 11},
211+
{MP_QSTR_subx2, RRR, 0, 13},
212+
{MP_QSTR_subx4, RRR, 0, 14},
213+
{MP_QSTR_subx8, RRR, 0, 15},
214+
{MP_QSTR_src, RRR, 1, 8},
191215

192216
// load/store/addi opcodes: reg, reg, imm
193217
// upper nibble of type encodes the range of the immediate arg
@@ -209,21 +233,71 @@ static const opcode_table_3arg_t opcode_table_3arg[] = {
209233
{MP_QSTR_bge, RRI8_B, ASM_XTENSA_CC_GE, 0},
210234
{MP_QSTR_bgeu, RRI8_B, ASM_XTENSA_CC_GEU, 0},
211235
{MP_QSTR_blt, RRI8_B, ASM_XTENSA_CC_LT, 0},
236+
{MP_QSTR_bltu, RRI8_B, ASM_XTENSA_CC_LTU, 0},
212237
{MP_QSTR_bnall, RRI8_B, ASM_XTENSA_CC_NALL, 0},
213238
{MP_QSTR_bne, RRI8_B, ASM_XTENSA_CC_NE, 0},
214239
{MP_QSTR_bnone, RRI8_B, ASM_XTENSA_CC_NONE, 0},
215240
};
216241

242+
#undef UNSIGNED
243+
244+
// The index of the qstrs matches the CCZ condition value to be embedded into the opcode.
245+
static const qstr_short_t BCCZ_OPCODES[] = { MP_QSTR_beqz, MP_QSTR_bnez, MP_QSTR_bltz, MP_QSTR_bgez };
246+
247+
#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
248+
typedef struct _single_opcode_t {
249+
qstr_short_t name;
250+
uint16_t value;
251+
} single_opcode_t;
252+
253+
static const single_opcode_t NOARGS_OPCODES[] = {
254+
{MP_QSTR_dsync, 0x2030},
255+
{MP_QSTR_esync, 0x2020},
256+
{MP_QSTR_extw, 0x20D0},
257+
{MP_QSTR_ill, 0x0000},
258+
{MP_QSTR_isync, 0x2000},
259+
{MP_QSTR_memw, 0x20C0},
260+
{MP_QSTR_rsync, 0x2010},
261+
};
262+
#endif
263+
264+
static void handle_branch_immediate(emit_inline_asm_t *emit, const char *op_str, const uint8_t mn, mp_uint_t reg, mp_parse_node_t *pn_args) {
265+
mp_int_t imm = get_arg_i(emit, op_str, pn_args[1], -1, 256);
266+
mp_int_t encoded = encode_b4const(imm);
267+
if (encoded >= 0) {
268+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[2]);
269+
asm_xtensa_immediate_branch(&emit->as, reg, (mp_uint_t)encoded, label, mn);
270+
return;
271+
}
272+
emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a valid immediate"), imm));
273+
}
274+
217275
static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
218276
size_t op_len;
219277
const char *op_str = (const char *)qstr_data(op, &op_len);
220278

221279
if (n_args == 0) {
222-
if (op == MP_QSTR_ret_n) {
280+
if (op == MP_QSTR_ret_n || op == MP_QSTR_ret) {
223281
asm_xtensa_op_ret_n(&emit->as);
224-
} else {
225-
goto unknown_op;
282+
return;
283+
} else if (op == MP_QSTR_nop) {
284+
asm_xtensa_op24(&emit->as, 0x20F0);
285+
return;
286+
} else if (op == MP_QSTR_nop_n) {
287+
asm_xtensa_op16(&emit->as, 0xF03D);
288+
return;
289+
}
290+
#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
291+
for (size_t index = 0; index < MP_ARRAY_SIZE(NOARGS_OPCODES); index++) {
292+
const single_opcode_t *opcode = &NOARGS_OPCODES[index];
293+
if (op == opcode->name) {
294+
asm_xtensa_op24(&emit->as, opcode->value);
295+
return;
296+
}
226297
}
298+
#endif
299+
300+
goto unknown_op;
227301

228302
} else if (n_args == 1) {
229303
if (op == MP_QSTR_callx0) {
@@ -235,17 +309,49 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
235309
} else if (op == MP_QSTR_jx) {
236310
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
237311
asm_xtensa_op_jx(&emit->as, r0);
312+
} else if (op == M 10000 P_QSTR_ssl) {
313+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
314+
asm_xtensa_op_ssl(&emit->as, r0);
315+
} else if (op == MP_QSTR_ssr) {
316+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
317+
asm_xtensa_op_ssr(&emit->as, r0);
318+
} else if (op == MP_QSTR_ssai) {
319+
mp_uint_t sa = get_arg_i(emit, op_str, pn_args[0], 0, 31);
320+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 4, sa & 0x0F, (sa >> 4) & 0x01));
321+
} else if (op == MP_QSTR_ssa8b) {
322+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
323+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 3, r0, 0));
324+
} else if (op == MP_QSTR_ssa8l) {
325+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
326+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 2, r0, 0));
327+
} else if (op == MP_QSTR_call0) {
328+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[0]);
329+
asm_xtensa_call0(&emit->as, label);
330+
#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
331+
} else if (op == MP_QSTR_fsync) {
332+
mp_uint_t imm3 = get_arg_i(emit, op_str, pn_args[0], 0, 7);
333+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 0, 2, 8 | imm3, 0));
334+
} else if (op == MP_QSTR_ill_n) {
335+
asm_xtensa_op16(&emit->as, 0xF06D);
336+
#endif
238337
} else {
239338
goto unknown_op;
240339
}
241340

242341
} else if (n_args == 2) {
243342
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
244-
if (op == MP_QSTR_beqz) {
245-
int label = get_arg_label(emit, op_str, pn_args[1]);
343+
for (size_t index = 0; index < MP_ARRAY_SIZE(BCCZ_OPCODES); index++) {
344+
if (op == BCCZ_OPCODES[index]) {
345+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]);
346+
asm_xtensa_bccz_reg_label(&emit->as, index, r0, label);
347+
return;
348+
}
349+
}
350+
if (op == MP_QSTR_beqz_n) {
351+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]);
246352
asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label);
247-
} else if (op == MP_QSTR_bnez) {
248-
int label = get_arg_label(emit, op_str, pn_args[1]);
353+
} else if (op == MP_QSTR_bnez_n) {
354+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]);
249355
asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label);
250356
} else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
251357
// we emit mov.n for both "mov" and "mov_n" opcodes
@@ -255,7 +361,47 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
255361
// for convenience we emit l32r if the integer doesn't fit in movi
256362
uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
257363
asm_xtensa_mov_reg_i32(&emit->as, r0, imm);
258-
} else {
364+
} else if (op == MP_QSTR_abs_) {
365+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
366+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 1, r1));
367+
} else if (op == MP_QSTR_neg) {
368+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
369+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 0, r1));
370+
} else if (op == MP_QSTR_sll) {
371+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
372+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 10, r0, r1, 0));
373+
} else if (op == MP_QSTR_sra) {
374+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
375+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 11, r0, 0, r1));
376+
} else if (op == MP_QSTR_srl) {
377+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
378+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 9, r0, 0, r1));
379+
} else if (op == MP_QSTR_l32r) {
380+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]);
381+
asm_xtensa_l32r(&emit->as, r0, label);
382+
} else if (op == MP_QSTR_movi_n) {
383+
mp_int_t imm = get_arg_i(emit, op_str, pn_args[1], -32, 95);
384+
asm_xtensa_op_movi_n(&emit->as, r0, imm);
385+
} else
386+
#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
387+
if (op == MP_QSTR_rsr) {
388+
mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255);
389+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 0, sr, r0));
390+
} else if (op == MP_QSTR_rur) {
391+
mp_uint_t imm8 = get_arg_i(emit, op_str, pn_args[1], 0, 255);
392+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 3, 14, r0, (imm8 >> 4) & 0x0F, imm8 & 0x0F));
393+
} else if (op == MP_QSTR_wsr) {
394+
mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255);
395+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 1, sr, r0));
396+
} else if (op == MP_QSTR_wur) {
397+
mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255);
398+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 15, sr, r0));
399+
} else if (op == MP_QSTR_xsr) {
400+
mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255);
401+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 1, 6, sr, r0));
402+
} else
403+
#endif
404+
{
259405
goto unknown_op;
260406
}
261407

@@ -265,6 +411,10 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
265411
const opcode_table_3arg_t *o = &opcode_table_3arg[i];
266412
if (op == o->name) {
267413
uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
414+
if (o->type == BRI8) {
415+
handle_branch_immediate(emit, op_str, o->a0, r0, pn_args);
416+
return;
417+
}
268418
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
269419
if (o->type == RRR) {
270420
uint r2 = get_arg_reg(emit, op_str, pn_args[2]);
@@ -289,7 +439,72 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
289439
return;
290440
}
291441
}
292-
goto unknown_op;
442+
443+
if (op == MP_QSTR_add_n) {
444+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
445+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
446+
mp_uint_t r2 = get_arg_reg(emit, op_str, pn_args[2]);
447+
asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(10, r0, r1, r2));
448+
} else if (op == MP_QSTR_addi_n) {
449+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
450+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
451+
mp_int_t imm4 = get_arg_i(emit, op_str, pn_args[2], -1, 15);
452+
asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(11, r0, r1, (imm4 != 0 ? imm4 : -1)));
453+
} else if (op == MP_QSTR_addmi) {
454+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
455+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
456+
mp_int_t imm8 = get_arg_i(emit, op_str, pn_args[2], -128 * 256, 127 * 256);
457+
if ((imm8 & 0xFF) != 0) {
458+
emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm8, 256));
459+
} else {
460+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(2, 13, r1, r0, imm8 >> 8));
461+
}
462+
} else if (op == MP_QSTR_bbci) {
463+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
464+
mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31);
465+
mp_int_t label = get_arg_label(emit, op_str, pn_args[2]);
466+
asm_xtensa_bit_branch(&emit->as, r0, bit, label, 6);
467+
} else if (op == MP_QSTR_bbsi) {
468+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
469+
mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31);
470+
mp_uint_t label = get_arg_label(emit, op_str, pn_args[2]);
471+
asm_xtensa_bit_branch(&emit->as, r0, bit, label, 14);
472+
} else if (op == MP_QSTR_slli) {
473+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
474+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
475+
mp_uint_t bits = 32 - get_arg_i(emit, op_str, pn_args[2], 1, 31);
476+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 0 | ((bits >> 4) & 0x01), r0, r1, bits & 0x0F));
477+
} else if (op == MP_QSTR_srai) {
478+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
479+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
480+
mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 31);
481+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 2 | ((bits >> 4) & 0x01), r0, bits & 0x0F, r1));
482+
} else if (op == MP_QSTR_srli) {
483+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
484+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
485+
mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 15);
486+
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 4, r0, bits, r1));
487+
} else if (op == MP_QSTR_l32i_n) {
488+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
489+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
490+
mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60);
491+
if ((imm & 0x03) != 0) {
492+
emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4));
493+
} else {
494+
asm_xtensa_op_l32i_n(&emit->as, r0, r1, imm >> 2);
495+
}
496+
} else if (op == MP_QSTR_s32i_n) {
497+
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
498+
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
499+
mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60);
500+
if ((imm & 0x03) != 0) {
501+
emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4));
502+
} else {
503+
asm_xtensa_op_s32i_n(&emit->as, r0, r1, imm >> 2);
504+
}
505+
} else {
506+
goto unknown_op;
507+
}
293508

294509
} else {
295510
goto unknown_op;

py/mpconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@
406406
#define MICROPY_EMIT_INLINE_XTENSA (0)
407407
#endif
408408

409+
// Whether to support uncommon Xtensa inline assembler opcodes
410+
#ifndef MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES
411+
#define MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES (0)
412+
#endif
413+
409414
// Whether to emit Xtensa-Windowed native code
410415
#ifndef MICROPY_EMIT_XTENSAWIN
411416
#define MICROPY_EMIT_XTENSAWIN (0)

0 commit comments

Comments
 (0)
0