8000 py/emitnative: Generate shorter RV32 code for exception handling. · micropython/micropython@2b5669d · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b5669d

Browse files
committed
py/emitnative: Generate shorter RV32 code for exception handling.
This commit lets the native emitte 10000 r generate shorter code when clearing exception objects on RV32. Since there are no direct generic ASM functions to set a specific immediate to a local variable, the native emitter usually generates an immediate assignment to a temporary register and then a store of that register into the chosen local variable. This pattern is also followed when clearing certain local variables related to exception handling, using MP_OBJ_NULL as the immediate value to set. Given that at the moment MP_OBJ_NULL is defined to be 0 (with some other spots in the native emitter that leverage that fact when checking the state of the variables mentioned earlier), and that the RV32 CPU has a dedicated register that is hardwired to read 0, a new method to set local variables to MP_OBJ_NULL is introduced. When generating RV32 code, the new macro will skip the intermediate register assignment and directly uses the X0/ZERO register to set the chosen local variable to MP_OBJ_NULL. Other platforms will still generate the same code sequence as before this change. This is a followup to 40585ea. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent e0a9b70 commit 2b5669d

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

py/emitnative.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,27 @@ struct _emit_t {
287287
#define ASM_CLR_REG(state, rd) ASM_XOR_REG_REG(state, rd, rd)
288288
#endif
289289

290+
#if N_RV32
291+
#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \
292+
ASM_MOV_LOCAL_REG(as, local_num, REG_ZERO)
293+
#else
294+
#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \
295+
ASM_MOV_REG_IMM(as, reg_temp, (mp_uint_t)MP_OBJ_NULL); \
296+
ASM_MOV_LOCAL_REG(as, local_num, reg_temp)
297+
#endif
298+
290299
static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj);
291300
static void emit_native_global_exc_entry(emit_t *emit);
292301
static void emit_native_global_exc_exit(emit_t *emit);
293302
static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj);
294303

295304
emit_t *EXPORT_FUN(new)(mp_emit_common_t * emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) {
305+
// Generated code performing exception handling assumes that MP_OBJ_NULL
306+
// equals to 0 to simplify some checks, leveraging dedicated opcodes for
307+
// comparisons against 0. If this assumption does not hold true anymore
308+
// then generated code won't work correctly.
309+
MP_STATIC_ASSERT(MP_OBJ_NULL == 0);
310+
296311
emit_t *emit = m_new0(emit_t, 1);
297312
emit->emit_common = emit_common;
298313
emit->error_slot = error_slot;
@@ -1291,8 +1306,7 @@ static void emit_native_global_exc_entry(emit_t *emit) {
12911306

12921307
// Check LOCAL_IDX_THROW_VAL for any injected value
12931308
ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit));
1294-
ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL);
1295-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
1309+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
12961310
emit_call(emit, MP_F_NATIVE_RAISE);
12971311
}
12981312
}
@@ -2208,8 +2222,7 @@ static void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) {
22082222

22092223
// Replace exception with MP_OBJ_NULL.
22102224
emit_native_label_assign(emit, *emit->label_slot);
2211-
ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL);
2212-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
2225+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
22132226

22142227
// end of with cleanup nlr_catch block
22152228
emit_native_label_assign(emit, *emit->label_slot + 1);
@@ -2316,8 +2329,7 @@ static void emit_native_for_iter_end(emit_t *emit) {
23162329
static void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
23172330
if (within_exc_handler) {
23182331
// Cancel any active exception so subsequent handlers don't see it
2319-
ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL);
2320-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
2332+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
23212333
} else {
23222334
emit_native_leave_exc_stack(emit, false);
23232335
}
@@ -3002,8 +3014,7 @@ static void emit_native_yield(emit_t *emit, int kind) {
30023014
if (kind == MP_EMIT_YIELD_VALUE) {
30033015
// Check LOCAL_IDX_THROW_VAL for any injected value
30043016
ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit));
3005-
ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL);
3006-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
3017+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
30073018
emit_call(emit, MP_F_NATIVE_RAISE);
30083019
} else {
30093020
// Label loop entry

0 commit comments

Comments
 (0)
0