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 #8458. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
df9a412206
commit
bf3585b33c
|
@ -27,7 +27,7 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
// wrapper around everything in this file
|
||||
#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) {
|
|||
asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A0);
|
||||
}
|
||||
|
||||
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) {
|
||||
if (idx < 16) {
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
|
||||
void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) {
|
||||
if (word_offset < 16) {
|
||||
asm_xtensa_op_l32i_n(as, reg_dest, reg_base, word_offset);
|
||||
} else if (word_offset < 256) {
|
||||
asm_xtensa_op_l32i(as, reg_dest, reg_base, word_offset);
|
||||
} else {
|
||||
asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
|
||||
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow"));
|
||||
}
|
||||
}
|
||||
|
||||
void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) {
|
||||
if (word_offset < 16) {
|
||||
asm_xtensa_op_s32i_n(as, reg_src, reg_base, word_offset);
|
||||
} else if (word_offset < 256) {
|
||||
asm_xtensa_op_s32i(as, reg_src, reg_base, word_offset);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow"));
|
||||
}
|
||||
}
|
||||
|
||||
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) {
|
||||
asm_xtensa_l32i_optimised(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
|
||||
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0);
|
||||
}
|
||||
|
||||
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) {
|
||||
if (idx < 16) {
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
|
||||
} else {
|
||||
asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
|
||||
}
|
||||
asm_xtensa_l32i_optimised(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
|
||||
asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8);
|
||||
}
|
||||
|
||||
|
|
|
@ -278,6 +278,8 @@ void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src);
|
|||
void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num);
|
||||
void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num);
|
||||
void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label);
|
||||
void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset);
|
||||
void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset);
|
||||
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx);
|
||||
void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
|
||||
|
||||
|
@ -393,12 +395,12 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
|
|||
#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src))
|
||||
|
||||
#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))
|
||||
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_l32i_optimised((as), (reg_dest), (reg_base), (word_offset))
|
||||
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0)
|
||||
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0)
|
||||
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0)
|
||||
|
||||
#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))
|
||||
#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_s32i_optimised((as), (reg_dest), (reg_base), (word_offset))
|
||||
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0)
|
||||
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0)
|
||||
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0)
|
||||
|
|
Loading…
Reference in New Issue