Skip to content

Commit 40585ea

Browse files
agattidpgeorge
authored andcommitted
py/emitnative: Emit shorter exception handler entry code on RV32.
This commit improves the RV32 code sequence that is emitted if a function needs to set up an exception handler as its prologue. The old code would clear a temporary register and then copy that value to places that needed to be initialised with zero values. On RV32 there's a dedicated register that's hardwired to be equal to zero, which allows us to bypass the extra register clear and use the zero register to initialise values. Signed-off-by: Alessandro Gatti <[email protected]>
1 parent bfc0d7b commit 40585ea

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

py/asmrv32.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ static inline void asm_rv32_opcode_xori(asm_rv32_t *state, mp_uint_t rd, mp_uint
694694
#define REG_LOCAL_1 ASM_RV32_REG_S3
695695
#define REG_LOCAL_2 ASM_RV32_REG_S4
696696
#define REG_LOCAL_3 ASM_RV32_REG_S5
697+
#define REG_ZERO ASM_RV32_REG_ZERO
697698

698699
void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd);
699700
void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd);
@@ -756,6 +757,7 @@ void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_
756757
#define ASM_STORE_REG_REG(state, rs1, rs2) ASM_STORE32_REG_REG(state, rs1, rs2)
757758
#define ASM_SUB_REG_REG(state, rd, rs) asm_rv32_opcode_sub(state, rd, rd, rs)
758759
#define ASM_XOR_REG_REG(state, rd, rs) asm_rv32_emit_optimised_xor(state, rd, rs)
760+
#define ASM_CLR_REG(state, rd)
759761

760762
#endif
761763

py/emitnative.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ struct _emit_t {
288288
ASM_T *as;
289289
};
290290

291+
#ifndef REG_ZERO
292+
#define REG_ZERO REG_TEMP0
293+
#define ASM_CLR_REG(state, rd) ASM_XOR_REG_REG(state, rd, rd)
294+
#endif
295+
291296
static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj);
292297
static void emit_native_global_exc_entry(emit_t *emit);
293298
static void emit_native_global_exc_exit(emit_t *emit);
@@ -1200,12 +1205,12 @@ static void emit_native_global_exc_entry(emit_t *emit) {
12001205
ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, start_label, true);
12011206
} else {
12021207
// Clear the unwind state
1203-
ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0);
1204-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_TEMP0);
1208+
ASM_CLR_REG(emit->as, REG_ZERO);
1209+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_ZERO);
12051210

12061211
// clear nlr.ret_val, because it's passed to mp_native_raise regardless
12071212
// of whether there was an exception or not
1208-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
1213+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_ZERO);
12091214

12101215
// Put PC of start code block into REG_LOCAL_1
12111216
ASM_MOV_REG_PCREL(emit->as, REG_LOCAL_1, start_label);
@@ -1221,8 +1226,8 @@ static void emit_native_global_exc_entry(emit_t *emit) {
12211226
ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, global_except_label, true);
12221227

12231228
// Clear PC of current code block, and jump there to resume execution
1224-
ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0);
1225-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_TEMP0);
1229+
ASM_CLR_REG(emit->as, REG_ZERO);
1230+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_ZERO);
12261231
ASM_JUMP_REG(emit->as, REG_LOCAL_1);
12271232

12281233
// Global exception handler: check for valid exception handler

0 commit comments

Comments
 (0)