Skip to content

Commit 34e4df7

Browse files
committed
inlineasm: Add inline assembler support for RV32.
This commit adds support for writing inline assembler functions when targeting a RV32IMC processor. Given that this takes up a bit of rodata space due to its large instruction decoding table and its extensive error messages, it is enabled by default only on offline targets such as mpy-cross and the qemu-riscv port. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 480a75e commit 34e4df7

36 files changed

+1934
-41
lines changed

mpy-cross/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#define MICROPY_EMIT_INLINE_XTENSA (1)
4848
#define MICROPY_EMIT_XTENSAWIN (1)
4949
#define MICROPY_EMIT_RV32 (1)
50+
#define MICROPY_EMIT_INLINE_RV32 (1)
5051
#define MICROPY_EMIT_NATIVE_DEBUG (1)
5152
#define MICROPY_EMIT_NATIVE_DEBUG_PRINTER (&mp_stdout_print)
5253

ports/qemu-riscv/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
3232

3333
#define MICROPY_EMIT_RV32 (1)
34+
#define MICROPY_EMIT_INLINE_RV32 (1)
3435
#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1)
3536
#define MICROPY_MEM_STATS (1)
3637
#define MICROPY_ENABLE_GC (1)

ports/qemu-riscv/tests_profile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Port-specific test directories.
22

3-
test_dirs.update(())
3+
test_dirs.update(("inlineasm/rv32imc",))
44

55
# Port-specific tests exclusion list.
66

py/asmrv32.c

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@
4545
#endif
4646

4747
#define INTERNAL_TEMPORARY ASM_RV32_REG_S0
48-
#define AVAILABLE_REGISTERS_COUNT 32
49-
50-
#define IS_IN_C_REGISTER_WINDOW(register_number) \
51-
(((register_number) >= ASM_RV32_REG_X8) && ((register_number) <= ASM_RV32_REG_X15))
52-
#define MAP_IN_C_REGISTER_WINDOW(register_number) \
53-
((register_number) - ASM_RV32_REG_X8)
5448

5549
#define FIT_UNSIGNED(value, bits) (((value) & ~((1U << (bits)) - 1)) == 0)
5650
#define FIT_SIGNED(value, bits) \
@@ -106,7 +100,6 @@ static void split_immediate(mp_int_t immediate, mp_uint_t *upper, mp_uint_t *low
106100
// Turn the lower half from unsigned to signed.
107101
if ((*lower & 0x800) != 0) {
108102
*upper += 0x1000;
109-
*lower -= 0x1000;
110103
}
111104
}
112105

@@ -180,7 +173,7 @@ void asm_rv32_emit_optimised_load_immediate(asm_rv32_t *state, mp_uint_t rd, mp_
180173

181174
static void emit_registers_store(asm_rv32_t *state, mp_uint_t registers_mask) {
182175
mp_uint_t offset = 0;
183-
for (mp_uint_t register_index = 0; register_index < AVAILABLE_REGISTERS_COUNT; register_index++) {
176+
for (mp_uint_t register_index = 0; register_index < RV32_AVAILABLE_REGISTERS_COUNT; register_index++) {
184177
if (registers_mask & (1U << register_index)) {
185178
assert(FIT_UNSIGNED(offset >> 2, 6) && "Registers save stack offset out of range.");
186179
// c.swsp register, offset
@@ -192,7 +185,7 @@ static void emit_registers_store(asm_rv32_t *state, mp_uint_t registers_mask) {
192185

193186
static void emit_registers_load(asm_rv32_t *state, mp_uint_t registers_mask) {
194187
mp_uint_t offset = 0;
195-
for (mp_uint_t register_index = 0; register_index < AVAILABLE_REGISTERS_COUNT; register_index++) {
188+
for (mp_uint_t register_index = 0; register_index < RV32_AVAILABLE_REGISTERS_COUNT; register_index++) {
196189
if (registers_mask & (1U << register_index)) {
197190
assert(FIT_UNSIGNED(offset >> 2, 6) && "Registers load stack offset out of range.");
198191
// c.lwsp register, offset
@@ -262,7 +255,7 @@ static bool calculate_displacement_for_label(asm_rv32_t *state, mp_uint_t label,
262255

263256
void asm_rv32_entry(asm_rv32_t *state, mp_uint_t locals) {
264257
state->saved_registers_mask |= (1U << REG_FUN_TABLE) | (1U << REG_LOCAL_1) | \
265-
(1U << REG_LOCAL_2) | (1U << REG_LOCAL_3) | (1U << INTERNAL_TEMPORARY);
258+
(1U << REG_LOCAL_2) | (1U << REG_LOCAL_3);
266259
state->locals_count = locals;
267260
emit_function_prologue(state, state->saved_registers_mask);
268261
}
@@ -281,10 +274,11 @@ void asm_rv32_emit_call_ind(asm_rv32_t *state, mp_uint_t index) {
281274
mp_uint_t offset = index * ASM_WORD_SIZE;
282275
state->saved_registers_mask |= (1U << ASM_RV32_REG_RA);
283276

284-
if (IS_IN_C_REGISTER_WINDOW(REG_FUN_TABLE) && IS_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY) && FIT_UNSIGNED(offset, 6)) {
277+
if (RV32_IS_IN_C_REGISTER_WINDOW(REG_FUN_TABLE) && RV32_IS_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY) && FIT_UNSIGNED(offset, 6)) {
278+
state->saved_registers_mask |= (1U << INTERNAL_TEMPORARY);
285279
// c.lw temporary, offset(fun_table)
286280
// c.jalr temporary
287-
asm_rv32_opcode_clw(state, MAP_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY), MAP_IN_C_REGISTER_WINDOW(REG_FUN_TABLE), offset);
281+
asm_rv32_opcode_clw(state, RV32_MAP_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY), RV32_MAP_IN_C_REGISTER_WINDOW(REG_FUN_TABLE), offset);
288282
asm_rv32_opcode_cjalr(state, INTERNAL_TEMPORARY);
289283
return;
290284
}
@@ -341,9 +335,9 @@ void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_
341335
ptrdiff_t displacement = 0;
342336
bool can_emit_short_jump = calculate_displacement_for_label(state, label, &displacement);
343337

344-
if (can_emit_short_jump && FIT_SIGNED(displacement, 8) && IS_IN_C_REGISTER_WINDOW(rs)) {
338+
if (can_emit_short_jump && FIT_SIGNED(displacement, 8) && RV32_IS_IN_C_REGISTER_WINDOW(rs)) {
345339
// c.bnez rs', displacement
346-
asm_rv32_opcode_cbnez(state, MAP_IN_C_REGISTER_WINDOW(rs), displacement);
340+
asm_rv32_opcode_cbnez(state, RV32_MAP_IN_C_REGISTER_WINDOW(rs), displacement);
347341
return;
348342
}
349343

@@ -364,8 +358,8 @@ void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_
364358
// jalr zero, temporary, LO(displacement) ; PC + 8
365359
// ... ; PC + 12
366360

367-
if (can_emit_short_jump && IS_IN_C_REGISTER_WINDOW(rs)) {
368-
asm_rv32_opcode_cbeqz(state, MAP_IN_C_REGISTER_WINDOW(rs), 10);
361+
if (can_emit_short_jump && RV32_IS_IN_C_REGISTER_WINDOW(rs)) {
362+
asm_rv32_opcode_cbeqz(state, RV32_MAP_IN_C_REGISTER_WINDOW(rs), 10);
369363
// Compensate for the C.BEQZ opcode.
370364
displacement -= ASM_HALFWORD_SIZE;
371365
} else {
@@ -438,9 +432,9 @@ void asm_rv32_emit_mov_reg_local(asm_rv32_t *state, mp_uint_t rd, mp_uint_t loca
438432
void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local) {
439433
mp_uint_t offset = state->locals_stack_offset + (local * ASM_WORD_SIZE);
440434

441-
if (FIT_UNSIGNED(offset, 10) && offset != 0 && IS_IN_C_REGISTER_WINDOW(rd)) {
435+
if (FIT_UNSIGNED(offset, 10) && offset != 0 && RV32_IS_IN_C_REGISTER_WINDOW(rd)) {
442436
// c.addi4spn rd', offset
443-
asm_rv32_opcode_caddi4spn(state, MAP_IN_C_REGISTER_WINDOW(rd), offset);
437+
asm_rv32_opcode_caddi4spn(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), offset);
444438
return;
445439
}
446440

@@ -459,9 +453,9 @@ void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t
459453
void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
460454
mp_int_t scaled_offset = offset * sizeof(ASM_WORD_SIZE);
461455

462-
if (scaled_offset >= 0 && IS_IN_C_REGISTER_WINDOW(rd) && IS_IN_C_REGISTER_WINDOW(rs) && FIT_UNSIGNED(scaled_offset, 6)) {
456+
if (scaled_offset >= 0 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && FIT_UNSIGNED(scaled_offset, 6)) {
463457
// c.lw rd', offset(rs')
464-
asm_rv32_opcode_clw(state, MAP_IN_C_REGISTER_WINDOW(rd), MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset);
458+
asm_rv32_opcode_clw(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), RV32_MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset);
465459
return;
466460
}
467461

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy