Skip to content

Commit bf3585b

Browse files
committedMar 30, 2022
py/asmxtensa: Fix use of l32i/s32i when offset won't fit in encoding.
This commit adds optimised l32i/s32i functions that select the best load/ store encoding based on the size of the offset, and uses the function when necessary in code generation. Without this, ASM_LOAD_REG_REG_OFFSET() could overflow the word offset (using a narrow encoding), for example when loading the prelude from the constant table when there are many (>16) constants. Fixes issue micropython#8458. Signed-off-by: Damien George <damien@micropython.org>
1 parent df9a412 commit bf3585b

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed
 

‎py/asmxtensa.c

+22-10
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include <stdio.h>
2828
#include <assert.h>
2929

30-
#include "py/mpconfig.h"
30+
#include "py/runtime.h"
3131

3232
// wrapper around everything in this file
3333
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN
@@ -232,21 +232,33 @@ void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label) {
232232
asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A0);
233233
}
234234

235-
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) {
236-
if (idx < 16) {
237-
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
235+
void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) {
236+
if (word_offset < 16) {
237+
asm_xtensa_op_l32i_n(as, reg_dest, reg_base, word_offset);
238+
} else if (word_offset < 256) {
239+
asm_xtensa_op_l32i(as, reg_dest, reg_base, word_offset);
238240
} else {
239-
asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
241+
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow"));
240242
}
241-
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0);
242243
}
243244

244-
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) {
245-
if (idx < 16) {
246-
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
245+
void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) {
246+
if (word_offset < 16) {
247+
asm_xtensa_op_s32i_n(as, reg_src, reg_base, word_offset);
248+
} else if (word_offset < 256) {
249+
asm_xtensa_op_s32i(as, reg_src, reg_base, word_offset);
247250
} else {
248-
asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
251+
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow"));
249252
}
253+
}
254+
255+
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) {
256+
asm_xtensa_l32i_optimised(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
257+
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0);
258+
}
259+
260+
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) {
261+
asm_xtensa_l32i_optimised(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
250262
asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8);
251263
}
252264

‎py/asmxtensa.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src);
278278
void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num);
279279
void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num);
280280
void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label);
281+
void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset);
282+
void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset);
281283
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx);
282284
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
283285

@@ -393,12 +395,12 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
393395
#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src))
394396
#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src))
395397

396-
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), (word_offset))
398+
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_l32i_optimised((as), (reg_dest), (reg_base), (word_offset))
397399
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0)
398400
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0)
399401
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0)
400402

401-
#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_s32i_n((as), (reg_dest), (reg_base), (word_offset))
403+
#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_s32i_optimised((as), (reg_dest), (reg_base), (word_offset))
402404
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0)
403405
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0)
404406
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0)

0 commit comments

Comments
 (0)
Please sign in to comment.