summaryrefslogtreecommitdiff
path: root/py/asmxtensa.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-03-29 22:38:19 +1100
committerDamien George <damien@micropython.org>2022-03-30 16:32:17 +1100
commitbf3585b33c4fcd47edcf39494b7bc464a018b4fc (patch)
tree390a6b97dce63e4d937f772d9d80566b7614581f /py/asmxtensa.c
parentdf9a4122062ff706ad4b6a76cb5bc16d1a23d384 (diff)
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>
Diffstat (limited to 'py/asmxtensa.c')
-rw-r--r--py/asmxtensa.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/py/asmxtensa.c b/py/asmxtensa.c
index 0956d50f3..8ac914ec4 100644
--- a/py/asmxtensa.c
+++ b/py/asmxtensa.c
@@ -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"));
}
- 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);
+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 {
- asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx);
+ 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) {
+ 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);
}