Skip to content

Commit 15dcb7d

Browse files
committed
qemu: Emit Zcmt opcodes by default for RV32 boards.
This commit updates the configuration for RISC-V 32-bit boards to always emit Zcmt opcodes when it comes to natively compiled functions. QEMU's CPU configuration was changed accordingly, with Zcmt opcodes also sharing opcode space with the Zcd instructions (just like Zcmp ones). The entry point for the port will also perform the necessary initialisation steps to create a suitable function table in RAM that can be used for Zcmt opcodes, and also sets up the appropriate CPU registers in order to make jump opcodes read the correct address. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 3a8de5d commit 15dcb7d

3 files changed

Lines changed: 27 additions & 2 deletions

File tree

ports/qemu/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,14 @@ GCC_VERSION = $(word 1, $(subst ., , $(shell $(CC) -dumpversion)))
105105

106106
RV32_ABI = ilp32
107107

108-
QEMU_ARGS += -bios none -cpu rv32,zcd=off,zcmp=on
108+
QEMU_ARGS += -bios none -cpu rv32,zcd=off,zcmp=on,zcmt=on
109109

110110
# GCC 10 and lower do not recognise the Zicsr extension in the architecture name.
111111
ifeq ($(shell test $(GCC_VERSION) -le 10; echo $$?),0)
112112
RV32_ARCH ?= rv32imac
113113
else
114114
# Recent GCC versions explicitly require to declare extensions.
115-
RV32_ARCH ?= rv32imac_zicsr
115+
RV32_ARCH ?= rv32imac_zicsr_zifencei
116116
endif
117117

118118
AFLAGS += -mabi=$(RV32_ABI) -march=$(RV32_ARCH)

ports/qemu/mcu/rv32/startup.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,36 @@
2929
#include <stdlib.h>
3030

3131
#include "uart.h"
32+
#include "mpconfigport.h"
3233

3334
extern void set_interrupt_table(void);
3435
extern int main(int argc, char **argv);
3536

37+
#if MICROPY_EMIT_RV32_ZCMT
38+
extern const uintptr_t mp_fun_table;
39+
40+
static void jump_table_init(void) {
41+
// Relocate the table address to always perform a jump and link (index has
42+
// to be between 32 and 255), so that calling function index #32 will perform
43+
// a jump-and-link to the real function at index #0 (see §28.14.5).
44+
__asm volatile (
45+
// Use the JVT CSR index directly for compatibility.
46+
"csrw 0x017, %0 \n"
47+
"fence.i \n"
48+
:
49+
: "r" ((ptrdiff_t)&mp_fun_table - (ptrdiff_t)(32 * sizeof(uintptr_t)))
50+
: "memory"
51+
);
52+
}
53+
#endif
54+
3655
void _entry_point(void) {
3756
// Set interrupt table
3857
set_interrupt_table();
58+
#if MICROPY_EMIT_RV32_ZCMT
59+
// Build native jump table.
60+
jump_table_init();
61+
#endif
3962
// Enable UART
4063
uart_init();
4164
// Now that we have a basic system up and running we can call main

ports/qemu/mpconfigport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
#define MICROPY_EMIT_RV32 (1)
4545
#define MICROPY_EMIT_RV32_ZBA (1)
4646
#define MICROPY_EMIT_RV32_ZCMP (1)
47+
#define MICROPY_EMIT_RV32_ZCMT (1)
48+
#define MICROPY_NATIVE_FUN_TABLE_ALIGNMENT (64)
4749
#define MICROPY_EMIT_INLINE_RV32 (1)
4850
#elif (__riscv_xlen == 64)
4951
#define MICROPY_PERSISTENT_CODE_LOAD_NATIVE (1)

0 commit comments

Comments
 (0)