mirror of
https://github.com/micropython/micropython.git
synced 2026-03-16 22:00:22 +01:00
py/asmthumb: Do not clobber index register on viper load/store.
This commit lets the native emitter preserve the value of the index register when performing register-indexed loads or stores of halfword or word values on Thumb. The original code was optimised too aggressively for a register-starved architecture like Thumb, and the index value in the sequence to generate was assumed to be allocated somewhere safe. This is valid on other architectures, but not on Thumb. To solve this, load operations do clobber a temporary register that should be safe to use, REG_TEMP2, to store the scaled register offset. REG_TEMP2's value is only used within the scope of a single ASM API instruction. Save operations unfortunately use a register that is aliased to REG_TEMP2, since they need to have three values in registers to perform the operation. This means the index register needs to be pushed to the stack before performing the scale + store operation, and then popped from the stack. That's a 4 bytes penalty on each store and a minor speed hit on generated code (plus a minor footprint increase of the firmware image). Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit is contained in:
committed by
Damien George
parent
f02dc6dd8f
commit
b46f9f503f
@@ -465,24 +465,28 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel);
|
||||
#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_thumb_ldrb_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index))
|
||||
#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) \
|
||||
do { \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \
|
||||
asm_thumb_ldrh_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), REG_TEMP2, (reg_index), 1); \
|
||||
asm_thumb_ldrh_rlo_rlo_rlo((as), (reg_dest), (reg_base), REG_TEMP2); \
|
||||
} while (0)
|
||||
#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) \
|
||||
do { \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \
|
||||
asm_thumb_ldr_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), REG_TEMP2, (reg_index), 2); \
|
||||
asm_thumb_ldr_rlo_rlo_rlo((as), (reg_dest), (reg_base), REG_TEMP2); \
|
||||
} while (0)
|
||||
#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_thumb_strb_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index))
|
||||
#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) \
|
||||
do { \
|
||||
asm_thumb_op16((as), 0xB400 | (1 << reg_index)); \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \
|
||||
asm_thumb_strh_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \
|
||||
asm_thumb_op16((as), 0xBC00 | (1 << reg_index)); \
|
||||
} while (0)
|
||||
#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) \
|
||||
do { \
|
||||
asm_thumb_op16((as), 0xB400 | (1 << reg_index)); \
|
||||
asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \
|
||||
asm_thumb_str_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \
|
||||
asm_thumb_op16((as), 0xBC00 | (1 << reg_index)); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_CLR_REG(as, reg_dest) asm_thumb_mov_rlo_i8((as), (reg_dest), 0)
|
||||
|
||||
Reference in New Issue
Block a user