Skip to content

Commit b7d7a26

Browse files
agattidpgeorge
authored andcommitted
py/emitinlinextensa: Refactor handling of selected narrow opcodes.
This commit migrates handling of certain narrow (ie. 16-bits) opcodes from a per-opcode dedicated code snippet to the existing table-driven opcode handler. The final ESP8266 firmware binary is 64 bytes shorter, without any change in the existing behaviour and with a reduced source code lines count too. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 9dcad25 commit b7d7a26

1 file changed

Lines changed: 27 additions & 34 deletions

File tree

py/emitinlinextensa.c

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ static const qstr_short_t BRANCH_OPCODE_NAMES[] = {
200200

201201
#define RRR (0)
202202
#define RRI8 (1)
203+
#define RRRN (2)
203204

204205
static const struct opcode_entry_t {
205206
qstr_short_t name;
@@ -211,12 +212,13 @@ static const struct opcode_entry_t {
211212
uint32_t r : 6;
212213
uint32_t s : 6;
213214
uint32_t t : 6;
214-
uint32_t shift : 4;
215-
uint32_t kind : 1;
216-
// 13 bits available here
215+
uint32_t shift : 3;
216+
uint32_t kind : 2;
217+
// 9 bits available here
217218
} OPCODE_TABLE[] = {
218219
{ MP_QSTR_abs_, 2, 6, 0, 0, RRR_R0, 1, RRR_R1, 0, RRR },
219220
{ MP_QSTR_add, 3, 8, 0, 0, RRR_R0, RRR_R1, RRR_R2, 0, RRR },
221+
{ MP_QSTR_add_n, 3, 0, 0, 10, RRR_R0, RRR_R1, RRR_R2, 0, RRRN },
220222
{ MP_QSTR_addi, 3, 0, 0, 2, 12, RRR_R1, RRR_R0, 0, RRI8 },
221223
{ MP_QSTR_addx2, 3, 9, 0, 0, RRR_R0, RRR_R1, RRR_R2, 0, RRR },
222224
{ MP_QSTR_addx4, 3, 10, 0, 0, RRR_R0, RRR_R1, RRR_R2, 0, RRR },
@@ -228,12 +230,17 @@ static const struct opcode_entry_t {
228230
{ MP_QSTR_l16ui, 3, 0, 0, 2, 1, RRR_R1, RRR_R0, 3, RRI8 },
229231
{ MP_QSTR_l32i, 3, 0, 0, 2, 2, RRR_R1, RRR_R0, 5, RRI8 },
230232
{ MP_QSTR_l8ui, 3, 0, 0, 2, 0, RRR_R1, RRR_R0, 1, RRI8 },
233+
{ MP_QSTR_mov, 2, 0, 0, 13, 0, RRR_R1, RRR_R0, 0, RRRN },
234+
{ MP_QSTR_mov_n, 2, 0, 0, 13, 0, RRR_R1, RRR_R0, 0, RRRN },
231235
{ MP_QSTR_mull, 3, 8, 2, 0, RRR_R0, RRR_R1, RRR_R2, 0, RRR },
232236
{ MP_QSTR_neg, 2, 6, 0, 0, RRR_R0, 0, RRR_R1, 0, RRR },
233237
{ MP_QSTR_nop, 0, 0, 0, 0, 2, 0, 15, 0, RRR },
238+
{ MP_QSTR_nop_n, 0, 0, 0, 13, 15, 0, 3, 0, RRRN },
234239
{ MP_QSTR_nsa, 2, 4, 0, 0, 14, RRR_R1, RRR_R0, 0, RRR },
235240
{ MP_QSTR_nsau, 2, 4, 0, 0, 15, RRR_R1, RRR_R0, 0, RRR },
236241
{ MP_QSTR_or_, 3, 2, 0, 0, RRR_R0, RRR_R1, RRR_R2, 0, RRR },
242+
{ MP_QSTR_ret, 0, 0, 0, 13, 15, 0, 0, 0, RRRN },
243+
{ MP_QSTR_ret_n, 0, 0, 0, 13, 15, 0, 0, 0, RRRN },
237244
{ MP_QSTR_s16i, 3, 0, 0, 2, 5, RRR_R1, RRR_R0, 3, RRI8 },
238245
{ MP_QSTR_s32i, 3, 0, 0, 2, 6, RRR_R1, RRR_R0, 5, RRI8 },
239246
{ MP_QSTR_s8i, 3, 0, 0, 2, 4, RRR_R1, RRR_R0, 1, RRI8 },
@@ -255,6 +262,7 @@ static const struct opcode_entry_t {
255262
{ MP_QSTR_esync, 0, 0, 0, 0, 2, 0, 2, 0, RRR },
256263
{ MP_QSTR_extw, 0, 0, 0, 0, 2, 0, 13, 0, RRR },
257264
{ MP_QSTR_ill, 0, 0, 0, 0, 2, 0, 0, 0, RRR },
265+
{ MP_QSTR_ill_n, 0, 0, 0, 13, 15, 0, 6, 0, RRRN },
258266
{ MP_QSTR_isync, 0, 0, 0, 0, 2, 0, 0, 0, RRR },
259267
{ MP_QSTR_memw, 0, 0, 0, 0, 2, 0, 12, 0, RRR },
260268
{ MP_QSTR_rer, 2, 4, 0, 0, 6, RRR_R1, RRR_R0, 0, RRR },
@@ -281,10 +289,10 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
281289
goto unknown_op;
282290
}
283291

284-
uint32_t op24 = ((entry->r & 0x0F) << 12) | ((entry->s & 0x0F) << 8) | ((entry->t & 0x0F) << 4) | entry->op0;
292+
uint32_t opcode = ((entry->r & 0x0F) << 12) | ((entry->s & 0x0F) << 8) | ((entry->t & 0x0F) << 4) | entry->op0;
285293
if (entry->kind == RRR) {
286-
op24 |= (entry->op2 << 20) | (entry->op1 << 16);
287-
} else {
294+
opcode |= (entry->op2 << 20) | (entry->op1 << 16);
295+
} else if (entry->kind == RRI8) {
288296
int min = 0;
289297
int max = 0;
290298
int shift = entry->shift;
@@ -296,32 +304,28 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
296304
max = 127;
297305
}
298306
uint32_t immediate = get_arg_i(emit, op_str, pn_args[2], min, max);
299-
op24 |= ((immediate >> shift) & 0xFF) << 16;
307+
opcode |= ((immediate >> shift) & 0xFF) << 16;
300308
}
301309
if (entry->r >= RRR_R0) {
302-
op24 |= get_arg_reg(emit, op_str, pn_args[(entry->r >> 4) - 1]) << 12;
310+
opcode |= get_arg_reg(emit, op_str, pn_args[(entry->r >> 4) - 1]) << 12;
303311
}
304312
if (entry->s >= RRR_R0) {
305-
op24 |= get_arg_reg(emit, op_str, pn_args[(entry->s >> 4) - 1]) << 8;
313+
opcode |= get_arg_reg(emit, op_str, pn_args[(entry->s >> 4) - 1]) << 8;
306314
}
307315
if (entry->t >= RRR_R0) {
308-
op24 |= get_arg_reg(emit, op_str, pn_args[(entry->t >> 4) - 1]) << 4;
316+
opcode |= get_arg_reg(emit, op_str, pn_args[(entry->t >> 4) - 1]) << 4;
317+
}
318+
if (entry->kind == RRRN) {
319+
assert((opcode >> 16) == 0 && "Stray bits in narrow opcode");
320+
asm_xtensa_op16(&emit->as, (uint16_t)(opcode & 0xFFFF));
321+
} else {
322+
asm_xtensa_op24(&emit->as, opcode);
309323
}
310-
asm_xtensa_op24(&emit->as, op24);
311324
return;
312325
}
313326
}
314327

315-
if (n_args == 0) {
316-
if (op == MP_QSTR_ret_n || op == MP_QSTR_ret) {
317-
asm_xtensa_op_ret_n(&emit->as);
318-
return;
319-
} else if (op == MP_QSTR_nop_n) {
320-
asm_xtensa_op16(&emit->as, 0xF03D);
321-
return;
322-
}
323-
goto unknown_op;
324-
} else if (n_args == 1) {
328+
if (n_args == 1) {
325329
if (op == MP_QSTR_j) {
326330
int label = get_arg_label(emit, op_str, pn_args[0]);
327331
asm_xtensa_j_label(&emit->as, label);
@@ -335,8 +339,6 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
335339
} else if (op == MP_QSTR_fsync) {
336340
mp_uint_t imm3 = get_arg_i(emit, op_str, pn_args[0], 0, 7);
337341
asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 0, 2, 8 | imm3, 0));
338-
} else if (op == MP_QSTR_ill_n) {
339-
asm_xtensa_op16(&emit->as, 0xF06D);
340342
#endif
341343
} else {
342344
goto unknown_op;
@@ -350,11 +352,7 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
350352
return;
351353
}
352354
}
353-
if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
354-
// we emit mov.n for both "mov" and "mov_n" opcodes
355-
uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
356-
asm_xtensa_op_mov_n(&emit->as, r0, r1);
357-
} else if (op == MP_QSTR_movi) {
355+
if (op == MP_QSTR_movi) {
358356
// for convenience we emit l32r if the integer doesn't fit in movi
359357
uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
360358
asm_xtensa_mov_reg_i32(&emit->as, r0, imm);
@@ -397,12 +395,7 @@ static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_
397395
}
398396
}
399397

400-
if (op == MP_QSTR_add_n) {
401-
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
402-
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
403-
mp_uint_t r2 = get_arg_reg(emit, op_str, pn_args[2]);
404-
asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(10, r0, r1, r2));
405-
} else if (op == MP_QSTR_addi_n) {
398+
if (op == MP_QSTR_addi_n) {
406399
mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]);
407400
mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]);
408401
mp_int_t imm4 = get_arg_i(emit, op_str, pn_args[2], -1, 15);

0 commit comments

Comments
 (0)