Skip to content

Commit 424ae08

Browse files
agattidpgeorge
authored andcommitted
py/asmrv32: 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 for halfword or word values on RV32. The original code was optimised too aggressively to reduce the generated code's size, using compressed opcodes that alias the target register to one of the operands. In register-indexed load/store operations, the index register was assumed to be allocated somewhere safe, but it was not always the case. To solve this, now all halfword and word register-indexed operations will use REG_TEMP2 to store the scaled index register. The size penalty on generated code varies across operation sizes and enabled extensions: - byte operations stay the same size with or without Zba - halfword operations will be 2 bytes larger without Zba, and will stay the same size with Zba - word operations will be 4 bytes larger without Zba, and 2 bytes larger with Zba There is also a minor firmware footprint increase to hold the extra logic needed for conditional register clobbering, but it shouldn't be that large anyway. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent b46f9f5 commit 424ae08

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

py/asmrv32.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -620,28 +620,31 @@ void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs)
620620
asm_rv32_opcode_xor(state, rd, rd, rs);
621621
}
622622

623+
// WARNING: The scaled offset will be stored in REG_TEMP2.
623624
static void asm_rv32_fix_up_scaled_reg_reg_reg(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) {
624625
assert(operation_size <= 2 && "Operation size value out of range.");
625626

626627
if (operation_size > 0 && asm_rv32_allow_zba_opcodes()) {
627628
// sh{1,2}add rs1, rs2, rs1
628-
asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 1 << operation_size, 0x10, rs1, rs2, rs1));
629+
asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 1 << operation_size, 0x10, REG_TEMP2, rs2, rs1));
629630
} else {
630631
if (operation_size > 0) {
631-
asm_rv32_opcode_cslli(state, rs2, operation_size);
632+
asm_rv32_opcode_slli(state, REG_TEMP2, rs2, operation_size);
633+
asm_rv32_opcode_cadd(state, REG_TEMP2, rs1);
634+
} else {
635+
asm_rv32_opcode_add(state, REG_TEMP2, rs1, rs2);
632636
}
633-
asm_rv32_opcode_cadd(state, rs1, rs2);
634637
}
635638
}
636639

637640
void asm_rv32_emit_load_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) {
638641
asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size);
639-
asm_rv32_emit_load_reg_reg_offset(state, rd, rs1, 0, operation_size);
642+
asm_rv32_emit_load_reg_reg_offset(state, rd, REG_TEMP2, 0, operation_size);
640643
}
641644

642645
void asm_rv32_emit_store_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) {
643646
asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size);
644-
asm_rv32_emit_store_reg_reg_offset(state, rd, rs1, 0, operation_size);
647+
asm_rv32_emit_store_reg_reg_offset(state, rd, REG_TEMP2, 0, operation_size);
645648
}
646649

647650
void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd) {

0 commit comments

Comments
 (0)