nall, libco: add support for risc-v arch (#1249)

Tested with qemu-system-riscv64 and Ubuntu as the guest OS.
このコミットが含まれているのは:
invertego 2023-10-02 00:45:43 -07:00 committed by GitHub
コミット e369049d0a
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
5個のファイルの変更193行の追加1行の削除

ファイルの表示

@ -21,6 +21,8 @@
#include "ppc64v2.c"
#elif defined(_ARCH_PPC) && !defined(__LITTLE_ENDIAN__)
#include "ppc.c"
#elif defined(__riscv)
#include "riscv.c"
#elif defined(_WIN32)
#include "fiber.c"
#else

150
libco/riscv.c ノーマルファイル
ファイルの表示

@ -0,0 +1,150 @@
#define LIBCO_C
#include "libco.h"
#include "settings.h"
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local uint64_t co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
#if __riscv_xlen == 32
#define I_STORE "sw"
#define I_LOAD "lw"
#elif __riscv_xlen == 64
#define I_STORE "sd"
#define I_LOAD "ld"
#else
#error Unsupported RISC-V XLEN
#endif
#if !defined(__riscv_flen)
#define F_STORE "#"
#define F_LOAD "#"
#elif __riscv_flen == 32
#define F_STORE "fsw"
#define F_LOAD "flw"
#elif __riscv_flen == 64
#define F_STORE "fsd"
#define F_LOAD "fld"
#else
#error Unsupported RISC-V FLEN
#endif
__attribute__((naked))
static void co_swap(cothread_t active, cothread_t previous) {
__asm__(
I_STORE " ra, 0 *8(a1)\n"
I_STORE " sp, 1 *8(a1)\n"
I_STORE " s0, 2 *8(a1)\n"
I_STORE " s1, 3 *8(a1)\n"
I_STORE " s2, 4 *8(a1)\n"
I_STORE " s3, 5 *8(a1)\n"
I_STORE " s4, 6 *8(a1)\n"
I_STORE " s5, 7 *8(a1)\n"
I_STORE " s6, 8 *8(a1)\n"
I_STORE " s7, 9 *8(a1)\n"
I_STORE " s8, 10*8(a1)\n"
I_STORE " s9, 11*8(a1)\n"
I_STORE " s10, 12*8(a1)\n"
I_STORE " s11, 13*8(a1)\n"
F_STORE " fs0, 14*8(a1)\n"
F_STORE " fs1, 15*8(a1)\n"
F_STORE " fs2, 16*8(a1)\n"
F_STORE " fs3, 17*8(a1)\n"
F_STORE " fs4, 18*8(a1)\n"
F_STORE " fs5, 19*8(a1)\n"
F_STORE " fs6, 20*8(a1)\n"
F_STORE " fs7, 21*8(a1)\n"
F_STORE " fs8, 22*8(a1)\n"
F_STORE " fs9, 23*8(a1)\n"
F_STORE " fs10, 24*8(a1)\n"
F_STORE " fs11, 25*8(a1)\n"
I_LOAD " ra, 0 *8(a0)\n"
I_LOAD " sp, 1 *8(a0)\n"
I_LOAD " s0, 2 *8(a0)\n"
I_LOAD " s1, 3 *8(a0)\n"
I_LOAD " s2, 4 *8(a0)\n"
I_LOAD " s3, 5 *8(a0)\n"
I_LOAD " s4, 6 *8(a0)\n"
I_LOAD " s5, 7 *8(a0)\n"
I_LOAD " s6, 8 *8(a0)\n"
I_LOAD " s7, 9 *8(a0)\n"
I_LOAD " s8, 10*8(a0)\n"
I_LOAD " s9, 11*8(a0)\n"
I_LOAD " s10, 12*8(a0)\n"
I_LOAD " s11, 13*8(a0)\n"
F_LOAD " fs0, 14*8(a0)\n"
F_LOAD " fs1, 15*8(a0)\n"
F_LOAD " fs2, 16*8(a0)\n"
F_LOAD " fs3, 17*8(a0)\n"
F_LOAD " fs4, 18*8(a0)\n"
F_LOAD " fs5, 19*8(a0)\n"
F_LOAD " fs6, 20*8(a0)\n"
F_LOAD " fs7, 21*8(a0)\n"
F_LOAD " fs8, 22*8(a0)\n"
F_LOAD " fs9, 23*8(a0)\n"
F_LOAD " fs10, 24*8(a0)\n"
F_LOAD " fs11, 25*8(a0)\n"
"ret\n"
);
}
static void co_entrypoint(cothread_t handle) {
uint64_t* buffer = (uint64_t*)handle;
void (*entrypoint)(void) = (void (*)(void))(uintptr_t)buffer[3];
entrypoint();
abort(); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active() {
if(!co_active_handle) co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
uint64_t* handle;
if(!co_active_handle) co_active_handle = &co_active_buffer;
if(handle = (uint64_t*)memory) {
unsigned int offset = (size & ~15);
uint64_t* p = (uint64_t*)((uint8_t*)handle + offset);
*(uintptr_t*)&handle[0] = (uintptr_t)co_entrypoint; /* ra (return address) */
*(uintptr_t*)&handle[1] = (uintptr_t)p; /* sp (stack pointer) */
*(uintptr_t*)&handle[2] = (uintptr_t)p; /* s0 (frame pointer) */
*(uintptr_t*)&handle[3] = (uintptr_t)entrypoint; /* s1 (entry point) */
}
return handle;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
void* memory = malloc(size);
if(!memory) return (cothread_t)0;
return co_derive(memory, size, entrypoint);
}
void co_delete(cothread_t handle) {
free(handle);
}
void co_switch(cothread_t handle) {
cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
int co_serializable() {
return 1;
}
#ifdef __cplusplus
}
#endif

ファイルの表示

@ -101,6 +101,10 @@ else
machine := arm32
else ifneq ($(filter powerpc64-% powerpc64le-%,$(machine_str)),)
machine := ppc64
else ifneq ($(filter riscv64-%,$(machine_str)),)
machine := rv64
else ifneq ($(filter riscv32-%,$(machine_str)),)
machine := rv32
endif
# detect clang with msvc target

ファイルの表示

@ -188,6 +188,8 @@ namespace nall {
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__amd64__) || defined(_M_AMD64)
#define ARCHITECTURE_AMD64
@ -201,6 +203,8 @@ namespace nall {
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCHITECTURE_ARM64
@ -214,6 +218,8 @@ namespace nall {
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__arm__)
#define ARCHITECTURE_ARM32
@ -224,6 +230,8 @@ namespace nall {
static constexpr bool arm32 = 1;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__ppc64__) || defined(_ARCH_PPC64)
#define ARCHITECTURE_PPC64
@ -234,6 +242,8 @@ namespace nall {
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 1;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__ppc__) || defined(_ARCH_PPC) || defined(_M_PPC)
#define ARCHITECTURE_PPC32
@ -244,6 +254,32 @@ namespace nall {
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 1;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 0;
};
#elif defined(__riscv) && __riscv_xlen == 64
#define ARCHITECTURE_RV64
struct Architecture {
static constexpr bool x86 = 0;
static constexpr bool amd64 = 0;
static constexpr bool arm64 = 0;
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 1;
static constexpr bool rv32 = 0;
};
#elif defined(__riscv) && __riscv_xlen == 32
#define ARCHITECTURE_RV32
struct Architecture {
static constexpr bool x86 = 0;
static constexpr bool amd64 = 0;
static constexpr bool arm64 = 0;
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;
static constexpr bool ppc32 = 0;
static constexpr bool rv64 = 0;
static constexpr bool rv32 = 1;
};
#else
#error "unable to detect architecture"

ファイルの表示

@ -3,7 +3,7 @@
#if defined(SLJIT)
namespace nall::recompiler {
struct generic {
static constexpr bool supported = Architecture::amd64 | Architecture::arm64 | Architecture::ppc64;
static constexpr bool supported = Architecture::amd64 | Architecture::arm64 | Architecture::ppc64 | Architecture::rv64;
bump_allocator& allocator;
sljit_compiler* compiler = nullptr;