Skip to content

Commit 0bf6773

Browse files
committed
rvjit: Introduce loongarch64 backend
LoongArch is a RISC ISA developed by Loongson, Co., Ltd., and has defined three variants, LA32R (R stands for "reduced"), LA32S, and LA64. This port only targets LA64 variant, since 32-bit LoongArch hardware is barely available on market, and only serves for embedded/education purpose. So far native linker is intentionally left unimplemented, and small immediate loading and conditional branch generation could be further optimized. This port has succeeded to boot a general RISC-V distribution, and passes the riscv-tests. I also verified the correctness with my downstream RVVM co-simulation patches[1]. Benchmarking with fp-disabled coremark, it achieves 7% of native performance, or 4.7x speed up over the interpreter (1176 v.s. 16666 v.s. 250 iterations/sec). Link: https://github.com/ziyao233/RVVM/tree/cosim # [1] Signed-off-by: Yao Zi <me@ziyao.cc>
1 parent c26a2a4 commit 0bf6773

5 files changed

Lines changed: 667 additions & 4 deletions

File tree

project.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ USE_JNI ?= 0 # Enable JNI support in librvvm
9393

9494
# Acceleration
9595
# Enable JIT by default on x86_64, arm64, riscv64
96-
USE_JIT ?= $(if $(filter x86_64 arm64 riscv64,$(ARCH)),1,0)
96+
USE_JIT ?= $(if $(filter x86_64 arm64 riscv64 loongarch64,$(ARCH)),1,0)
9797
USE_KVM ?= 0
9898

9999
# Misc toggles for debugging host platform/compiler issues
@@ -146,7 +146,7 @@ override SRC_USE_LIBRETRO := $(SRCDIR)/bindings/libretro/libretro.c
146146
override SRC_USE_JNI := $(SRCDIR)/bindings/jni/rvvm_jni.c
147147

148148
# Useflag dependencies
149-
override RVJIT_SUPPORTS_ARCH := $(if $(filter i386 x86_64 arm% riscv%,$(ARCH)),1)
149+
override RVJIT_SUPPORTS_ARCH := $(if $(filter i386 x86_64 arm% riscv% loongarch64,$(ARCH)),1)
150150
override DEPS_USE_JIT := RVJIT_SUPPORTS_ARCH
151151

152152
override DEPS_USE_X11 := USE_GUI

src/rvjit/rvjit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ static void rvjit_flush_icache(const void* addr, size_t size)
8686
FlushInstructionCache(GetCurrentProcess(), start, size);
8787
#elif defined(RVJIT_ARM64) && defined(GNU_EXTS)
8888
rvjit_arm64_fluch_icache(start, size);
89+
#elif defined(RVJIT_LA64) && defined(GNU_EXTS)
90+
// LoongArch maintains I/D cache coherency in hardware, but a barrier must
91+
// be inserted to prevent pipeline hazard.
92+
UNUSED(start);
93+
UNUSED(size);
94+
__asm__ __volatile__("ibar 0" : : : "memory");
8995
#elif defined(RVJIT_APPLE_SILICON)
9096
sys_icache_invalidate(start, size);
9197
#elif defined(RVJIT_RISCV) && defined(__linux__) && defined(__NR_riscv_flush_icache)

src/rvjit/rvjit.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7979
#define RVJIT_ARM 1
8080
#define RVJIT_ABI_SYSV 1
8181

82+
#elif (defined(__loongarch__) && __loongarch_lp64) || defined(_M_LOONGARCH64)
83+
84+
#define RVJIT_LA64 1
85+
#define RVJIT_ABI_SYSV 1
86+
#define RVJIT_NATIVE_64BIT 1
87+
8288
#else
8389

8490
#error No JIT support for the target platform!!!

src/rvjit/rvjit_emit.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ file, You can obtain one at https://mozilla.org/MPL/2.0/.
1919
#include "rvjit_arm64.h"
2020
#elif RVJIT_ARM
2121
#include "rvjit_arm.h"
22+
#elif RVJIT_LA64
23+
#include "rvjit_la64.h"
2224
#endif
2325

2426
#define REG_SRC 0x1
@@ -151,7 +153,7 @@ static regid_t rvjit_map_reg(rvjit_block_t* block, regid_t greg, regflags_t flag
151153
rvvm_fatal("Mapped RVJIT register is out of range!");
152154
return REG_ILL;
153155
}
154-
#if defined(RVJIT_RISCV)
156+
#if defined(RVJIT_RISCV) || defined(RVJIT_LA64)
155157
if (greg == RVJIT_REGISTER_ZERO) {
156158
return 0;
157159
}
@@ -166,7 +168,7 @@ static regid_t rvjit_map_reg(rvjit_block_t* block, regid_t greg, regflags_t flag
166168
block->regs[greg].flags = 0;
167169
}
168170
block->regs[greg].last_used = block->size;
169-
#if !defined(RVJIT_RISCV) && !defined(RVJIT_ARM64)
171+
#if !defined(RVJIT_RISCV) && !defined(RVJIT_ARM64) && !defined(RVJIT_LA64)
170172
if (greg == RVJIT_REGISTER_ZERO) {
171173
if (!(block->regs[greg].flags & REG_LOADED) || (block->regs[greg].flags & REG_DIRTY)) {
172174
rvjit_native_zero_reg(block, block->regs[greg].hreg);

0 commit comments

Comments
 (0)