Skip to content

Commit 3a8de5d

Browse files
committed
py/emitnative: Emit a shorter prologue if Zcmt opcodes are used.
This commit updates the native code prologue generator if Zcmt opcodes are used, since there is no more need for the emitted function to know the address of the native function table. By using Zcmt opcodes the prologue for selected RISC-V configurations can be reduced to just the initial stack adjustment and clobbered registers saving. Doing this also has the benefit of freeing up the register associated with the function table address, which could not be used by anything else in the emitted function. For RISC-V, without using Zcmt opcodes an extra register might have been used to store the function index to allow for compressed short function calls. That is now free to use as well with Zcmt opcodes. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 629e10b commit 3a8de5d

1 file changed

Lines changed: 58 additions & 22 deletions

File tree

py/emitnative.c

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,18 @@ static void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) {
384384
emit_native_mov_state_reg((emit), (local_num), (reg_temp)); \
385385
} while (false)
386386

387+
#if N_RV32
388+
#if MICROPY_DYNAMIC_COMPILER
389+
#define RV32_USE_ZCMT ((asm_rv32_allowed_extensions() & RV32_EXT_ZCMT) != 0)
390+
#elif (MICROPY_RV32_EXTENSIONS & RV32_EXT_ZCMT) != 0
391+
#define RV32_USE_ZCMT (true)
392+
#else
393+
#define RV32_USE_ZCMT (false)
394+
#endif
395+
#else
396+
#define RV32_USE_ZCMT (false)
397+
#endif
398+
387399
static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
388400
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
389401

@@ -508,13 +520,20 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
508520
asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1);
509521
#endif
510522

511-
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
512-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
513-
#if MICROPY_PERSISTENT_CODE_SAVE
514-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
515-
#endif
516-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
517-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
523+
if (RV32_USE_ZCMT) {
524+
#if MICROPY_PERSISTENT_CODE_SAVE
525+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
526+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
527+
#endif
528+
} else {
529+
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
530+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
531+
#if MICROPY_PERSISTENT_CODE_SAVE
532+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
533+
#endif
534+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
535+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
536+
}
518537

519538
// Store function object (passed as first arg) to stack if needed
520539
if (NEED_FUN_OBJ(emit)) {
@@ -592,14 +611,23 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
592611
#endif
593612
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_PARENT_ARG_2);
594613

595-
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
596-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit));
597-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONTEXT);
598-
#if MICROPY_PERSISTENT_CODE_SAVE
599-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
600-
#endif
601-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
602-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_TEMP0, fun_table_off);
614+
if (RV32_USE_ZCMT) {
615+
#if MICROPY_PERSISTENT_CODE_SAVE
616+
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
617+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit));
618+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONTEXT);
619+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
620+
#endif
621+
} else {
622+
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
623+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit));
624+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONTEXT);
625+
#if MICROPY_PERSISTENT_CODE_SAVE
626+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
627+
#endif
628+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
629+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_TEMP0, fun_table_off);
630+
}
603631
} else {
604632
// The locals and stack start after the code_state structure
605633
emit->stack_start = emit->code_state_start + SIZEOF_CODE_STATE;
@@ -616,13 +644,21 @@ static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
616644
asm_x86_mov_arg_to_r32(emit->as, 3, REG_PARENT_ARG_4);
617645
#endif
618646

619-
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
620-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
621-
#if MICROPY_PERSISTENT_CODE_SAVE
622-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
623-
#endif
624-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
625-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
647+
if (RV32_USE_ZCMT) {
648+
#if MICROPY_PERSISTENT_CODE_SAVE
649+
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
650+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
651+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
652+
#endif
653+
} else {
654+
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
655+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
656+
#if MICROPY_PERSISTENT_CODE_SAVE
657+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
658+
#endif
659+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
660+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
661+
}
626662

627663
// Set code_state.fun_bc
628664
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);

0 commit comments

Comments
 (0)