mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
Merge remote-tracking branch 'lightening/main'
This commit is contained in:
commit
5d3f561d7d
21 changed files with 4622 additions and 32 deletions
|
@ -1,40 +1,60 @@
|
|||
image: debian:stable
|
||||
|
||||
before_script:
|
||||
- dpkg --add-architecture i386
|
||||
- dpkg --add-architecture arm64
|
||||
- dpkg --add-architecture armhf
|
||||
- apt-get update -qq
|
||||
- apt-get install -y
|
||||
libc6-dev:amd64 gcc make
|
||||
binfmt-support qemu-user-static
|
||||
gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386
|
||||
gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64
|
||||
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6:armhf
|
||||
- update-binfmts --enable qemu-aarch64
|
||||
- update-binfmts --enable qemu-arm
|
||||
- apt-get install -y make binfmt-support qemu-user-static
|
||||
|
||||
x86-64:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture arm64
|
||||
- apt-get update -qq
|
||||
- apt-get install -y libc6-dev:amd64 gcc
|
||||
- make -C tests test-native
|
||||
|
||||
i686:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture i386
|
||||
- apt-get update -qq
|
||||
- apt-get install -y gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386
|
||||
- make -C tests test-ia32 CC_IA32=i686-linux-gnu-gcc
|
||||
|
||||
aarch64:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture arm64
|
||||
- apt-get update -qq
|
||||
- apt-get install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64
|
||||
- make -C tests test-aarch64 CC_AARCH64=aarch64-linux-gnu-gcc
|
||||
|
||||
armhf:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture armhf
|
||||
- apt-get update -qq
|
||||
- apt-get install -y gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6:armhf
|
||||
- make -C tests test-armv7 CC_ARMv7="arm-linux-gnueabihf-gcc -marm"
|
||||
|
||||
|
||||
armhf-thumb:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture armhf
|
||||
- apt-get update -qq
|
||||
- apt-get install -y gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6:armhf
|
||||
- make -C tests test-armv7 CC_ARMv7="arm-linux-gnueabihf-gcc -mthumb"
|
||||
|
||||
|
||||
riscv:
|
||||
stage: test
|
||||
script:
|
||||
- dpkg --add-architecture riscv64
|
||||
- apt-get update -qq
|
||||
- apt-get install -y gcc-riscv64-linux-gnu
|
||||
- echo /usr/local/lib/riscv64-linux-gnu >>/etc/ld.so.conf.d/riscv64-linux-gnu.conf
|
||||
- echo /lib/riscv64-linux-gnu >>/etc/ld.so.conf.d/riscv64-linux-gnu.conf
|
||||
- echo /usr/lib/riscv64-linux-gnu >>/etc/ld.so.conf.d/riscv64-linux-gnu.conf
|
||||
- echo /usr/riscv64-linux-gnu/lib >>/etc/ld.so.conf.d/riscv64-linux-gnu.conf
|
||||
- ln -s /usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1 /lib
|
||||
- make -C tests test-riscv CC_RISCV="riscv64-linux-gnu-gcc -static"
|
||||
|
|
|
@ -40,6 +40,7 @@ lightening_extra_files = \
|
|||
$(lightening)/lightening/mips.h \
|
||||
$(lightening)/lightening/ppc.h \
|
||||
$(lightening)/lightening/x86.h \
|
||||
$(lightening)/lightening/riscv.h \
|
||||
\
|
||||
$(lightening)/lightening/aarch64.c \
|
||||
$(lightening)/lightening/aarch64-cpu.c \
|
||||
|
@ -55,4 +56,7 @@ lightening_extra_files = \
|
|||
$(lightening)/lightening/ppc-fpu.c \
|
||||
$(lightening)/lightening/x86.c \
|
||||
$(lightening)/lightening/x86-cpu.c \
|
||||
$(lightening)/lightening/x86-sse.c
|
||||
$(lightening)/lightening/x86-sse.c \
|
||||
$(lightening)/lightening/riscv.c \
|
||||
$(lightening)/lightening/riscv-cpu.c \
|
||||
$(lightening)/lightening/riscv-fpu.c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2020 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2012-2020, 2025 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
|
@ -77,6 +77,8 @@ jit_same_fprs (jit_fpr_t a, jit_fpr_t b)
|
|||
# include "lightening/aarch64.h"
|
||||
#elif defined(__s390__) || defined(__s390x__)
|
||||
# include "lightening/s390.h"
|
||||
#elif defined(__riscv__) || defined(__riscv)
|
||||
# include "lightening/riscv.h"
|
||||
#endif
|
||||
|
||||
enum jit_reloc_kind
|
||||
|
@ -622,6 +624,10 @@ jit_load_args_3(jit_state_t *_jit, jit_operand_t a, jit_operand_t b,
|
|||
M(_FF__, extr_f_d) \
|
||||
M(_FF__, movr_f) \
|
||||
M(_FF__, movr_d) \
|
||||
M(_GF__, movr_i_f) \
|
||||
M(_FG__, movr_f_i) \
|
||||
WHEN_64(M(_GF__, movr_l_d)) \
|
||||
WHEN_64(M(_FG__, movr_d_l)) \
|
||||
M(_Ff__, movi_f) \
|
||||
M(_Fd__, movi_d) \
|
||||
M(_GF__, truncr_d_i) \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2019 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2013-2019, 2025 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
|
@ -638,6 +638,18 @@ movi_f(jit_state_t *_jit, int32_t r0, float i0)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
FMOVSW(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
FMOVWS(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
buneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
|
@ -759,6 +771,18 @@ movi_d(jit_state_t *_jit, int32_t r0, double i0)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
FMOVDX(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
FMOVXD(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
buneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
|
|
|
@ -165,7 +165,6 @@ struct abi_arg_iterator
|
|||
};
|
||||
|
||||
static size_t page_size;
|
||||
static int has_lse_atomics;
|
||||
|
||||
# define HWCAP_ATOMICS (1 << 8)
|
||||
|
||||
|
@ -262,3 +261,9 @@ bless_function_pointer(void *ptr)
|
|||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static jit_gpr_t
|
||||
get_callr_temp (jit_state_t * _jit)
|
||||
{
|
||||
return _LR;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2017, 2019 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2012-2017, 2019, 2025 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
|
@ -913,6 +913,18 @@ movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
VMOV_S_A(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
VMOV_A_S32(_jit, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
|
|
|
@ -109,7 +109,7 @@ next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg)
|
|||
}
|
||||
}
|
||||
*arg = jit_operand_mem (abi, JIT_SP, iter->stack_size);
|
||||
iter->stack_size += 4;
|
||||
iter->stack_size += 4 + (abi == JIT_OPERAND_ABI_DOUBLE ? 4 : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -137,3 +137,9 @@ bless_function_pointer(void *ptr)
|
|||
// Set low bit to mark as thumb mode.
|
||||
return (void*) (((uintptr_t)ptr) | 1);
|
||||
}
|
||||
|
||||
static jit_gpr_t
|
||||
get_callr_temp (jit_state_t * _jit)
|
||||
{
|
||||
return _LR;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
# else
|
||||
# define __WORDSIZE 64
|
||||
# endif
|
||||
# elif defined(__riscv_xlen)
|
||||
# define __WORDSIZE __riscv_xlen /* riscv */
|
||||
# else /* From FreeBSD 9.1 stdint.h */
|
||||
# if defined(UINTPTR_MAX) && defined(UINT64_MAX) && \
|
||||
(UINTPTR_MAX == UINT64_MAX)
|
||||
|
|
|
@ -123,6 +123,8 @@ static void reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc,
|
|||
static void next_abi_arg(struct abi_arg_iterator *iter,
|
||||
jit_operand_t *arg);
|
||||
|
||||
static jit_gpr_t get_callr_temp (jit_state_t * _jit);
|
||||
|
||||
jit_bool_t
|
||||
init_jit(void)
|
||||
{
|
||||
|
@ -268,6 +270,22 @@ get_temp_gpr(jit_state_t *_jit)
|
|||
#ifdef JIT_TMP1
|
||||
case 1:
|
||||
return JIT_TMP1;
|
||||
#endif
|
||||
#ifdef JIT_TMP2
|
||||
case 2:
|
||||
return JIT_TMP2;
|
||||
#endif
|
||||
#ifdef JIT_TMP3
|
||||
case 3:
|
||||
return JIT_TMP3;
|
||||
#endif
|
||||
#ifdef JIT_TMP4
|
||||
case 4:
|
||||
return JIT_TMP4;
|
||||
#endif
|
||||
#ifdef JIT_TMP5
|
||||
case 5:
|
||||
return JIT_TMP5;
|
||||
#endif
|
||||
default:
|
||||
abort();
|
||||
|
@ -558,6 +576,8 @@ jit_emit_addr(jit_state_t *j)
|
|||
# include "aarch64.c"
|
||||
#elif defined(__s390__) || defined(__s390x__)
|
||||
# include "s390.c"
|
||||
#elif defined(__riscv__) || defined(__riscv)
|
||||
# include "riscv.c"
|
||||
#endif
|
||||
|
||||
#define JIT_IMPL_0(stem, ret) \
|
||||
|
@ -786,6 +806,14 @@ abi_mem_to_gpr(jit_state_t *_jit, enum jit_operand_abi abi,
|
|||
case JIT_OPERAND_ABI_INT16:
|
||||
jit_ldxi_s(_jit, dst, base, offset);
|
||||
break;
|
||||
case JIT_OPERAND_ABI_FLOAT:
|
||||
{
|
||||
jit_fpr_t tmp = get_temp_fpr(_jit);
|
||||
jit_ldxi_f(_jit, tmp, base, offset);
|
||||
jit_movr_i_f(_jit, dst, tmp);
|
||||
unget_temp_fpr(_jit);
|
||||
break;
|
||||
}
|
||||
#if __WORDSIZE == 32
|
||||
case JIT_OPERAND_ABI_UINT32:
|
||||
case JIT_OPERAND_ABI_POINTER:
|
||||
|
@ -802,6 +830,14 @@ abi_mem_to_gpr(jit_state_t *_jit, enum jit_operand_abi abi,
|
|||
case JIT_OPERAND_ABI_INT64:
|
||||
jit_ldxi_l(_jit, dst, base, offset);
|
||||
break;
|
||||
case JIT_OPERAND_ABI_DOUBLE:
|
||||
{
|
||||
jit_fpr_t tmp = get_temp_fpr(_jit);
|
||||
jit_ldxi_d(_jit, tmp, base, offset);
|
||||
jit_movr_l_d(_jit, dst, tmp);
|
||||
unget_temp_fpr(_jit);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
abort();
|
||||
|
@ -866,7 +902,8 @@ enum move_kind {
|
|||
MOVE_KIND_ENUM(IMM, MEM),
|
||||
MOVE_KIND_ENUM(GPR, MEM),
|
||||
MOVE_KIND_ENUM(FPR, MEM),
|
||||
MOVE_KIND_ENUM(MEM, MEM)
|
||||
MOVE_KIND_ENUM(MEM, MEM),
|
||||
MOVE_KIND_ENUM(FPR, GPR)
|
||||
};
|
||||
#undef MOVE_KIND_ENUM
|
||||
|
||||
|
@ -880,6 +917,14 @@ move_operand(jit_state_t *_jit, jit_operand_t dst, jit_operand_t src)
|
|||
case MOVE_GPR_TO_GPR:
|
||||
return jit_movr(_jit, dst.loc.gpr.gpr, src.loc.gpr.gpr);
|
||||
|
||||
case MOVE_FPR_TO_GPR:
|
||||
#if __WORDSIZE > 32
|
||||
if (src.abi == JIT_OPERAND_ABI_DOUBLE)
|
||||
return jit_movr_l_d(_jit, dst.loc.gpr.gpr, src.loc.fpr);
|
||||
else
|
||||
#endif
|
||||
return jit_movr_i_f(_jit, dst.loc.gpr.gpr, src.loc.fpr);
|
||||
|
||||
case MOVE_MEM_TO_GPR:
|
||||
return abi_mem_to_gpr(_jit, src.abi, dst.loc.gpr.gpr, src.loc.mem.base,
|
||||
src.loc.mem.offset);
|
||||
|
@ -1095,6 +1140,15 @@ jit_move_operands(jit_state_t *_jit, jit_operand_t *dst, jit_operand_t *src,
|
|||
enum move_status status[argc];
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
status[i] = TO_MOVE;
|
||||
|
||||
// Mem-to-mem moves require a temp register but don't overwrite
|
||||
// other argument registers. Perform them first to free up the tmp
|
||||
// for other uses.
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
if ((status[i] == TO_MOVE)
|
||||
&& (MOVE_KIND (src[i].kind, dst[i].kind) == MOVE_MEM_TO_MEM))
|
||||
move_one(_jit, dst, src, argc, status, i);
|
||||
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
if (status[i] == TO_MOVE)
|
||||
move_one(_jit, dst, src, argc, status, i);
|
||||
|
@ -1155,6 +1209,9 @@ static const jit_gpr_t user_callee_save_gprs[] = {
|
|||
#endif
|
||||
#ifdef JIT_V9
|
||||
, JIT_V9
|
||||
#endif
|
||||
#ifdef JIT_V10
|
||||
, JIT_V10
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1183,6 +1240,18 @@ static const jit_fpr_t user_callee_save_fprs[] = {
|
|||
#ifdef JIT_VF7
|
||||
, JIT_VF7
|
||||
#endif
|
||||
#ifdef JIT_VF8
|
||||
, JIT_VF8
|
||||
#endif
|
||||
#ifdef JIT_VF9
|
||||
, JIT_VF9
|
||||
#endif
|
||||
#ifdef JIT_VF10
|
||||
, JIT_VF10
|
||||
#endif
|
||||
#ifdef JIT_VF11
|
||||
, JIT_VF11
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(X) (sizeof (X)/sizeof ((X)[0]))
|
||||
|
@ -1235,11 +1304,23 @@ jit_leave_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size)
|
|||
|
||||
// Precondition: stack is already aligned.
|
||||
static size_t
|
||||
prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
||||
prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[],
|
||||
jit_gpr_t *fun)
|
||||
{
|
||||
jit_operand_t dst[argc];
|
||||
size_t count = argc + (fun == NULL ? 0 : 1);
|
||||
jit_operand_t src[count];
|
||||
jit_operand_t dst[count];
|
||||
|
||||
memcpy (src, args, sizeof (jit_operand_t) * argc);
|
||||
if (fun != NULL) {
|
||||
jit_gpr_t fun_tmp = argc == 0 ? *fun : get_callr_temp (_jit);
|
||||
src[argc] = jit_operand_gpr (JIT_OPERAND_ABI_POINTER, *fun);
|
||||
dst[argc] = jit_operand_gpr (JIT_OPERAND_ABI_POINTER, fun_tmp);
|
||||
*fun = fun_tmp;
|
||||
}
|
||||
|
||||
struct abi_arg_iterator iter;
|
||||
|
||||
|
||||
// Compute shuffle destinations and space for spilled arguments.
|
||||
reset_abi_arg_iterator(&iter, argc, args);
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
|
@ -1264,7 +1345,7 @@ prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
|||
}
|
||||
}
|
||||
|
||||
jit_move_operands(_jit, dst, args, argc);
|
||||
jit_move_operands(_jit, dst, src, count);
|
||||
|
||||
return stack_size;
|
||||
}
|
||||
|
@ -1272,7 +1353,7 @@ prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
|||
void
|
||||
jit_calli(jit_state_t *_jit, jit_pointer_t f, size_t argc, jit_operand_t args[])
|
||||
{
|
||||
size_t stack_bytes = prepare_call_args(_jit, argc, args);
|
||||
size_t stack_bytes = prepare_call_args(_jit, argc, args, NULL);
|
||||
|
||||
calli(_jit, (jit_word_t)f);
|
||||
|
||||
|
@ -1282,7 +1363,7 @@ jit_calli(jit_state_t *_jit, jit_pointer_t f, size_t argc, jit_operand_t args[])
|
|||
void
|
||||
jit_callr(jit_state_t *_jit, jit_gpr_t f, size_t argc, jit_operand_t args[])
|
||||
{
|
||||
size_t stack_bytes = prepare_call_args(_jit, argc, args);
|
||||
size_t stack_bytes = prepare_call_args(_jit, argc, args, &f);
|
||||
|
||||
callr(_jit, jit_gpr_regno(f));
|
||||
|
||||
|
|
2479
libguile/lightening/lightening/riscv-cpu.c
Normal file
2479
libguile/lightening/lightening/riscv-cpu.c
Normal file
File diff suppressed because it is too large
Load diff
883
libguile/lightening/lightening/riscv-fpu.c
Normal file
883
libguile/lightening/lightening/riscv-fpu.c
Normal file
|
@ -0,0 +1,883 @@
|
|||
/*
|
||||
* RV32F Standard Extension
|
||||
*/
|
||||
#define _FLW(rd, rs1, im) Itype(7, rd, 2, rs1, im)
|
||||
#define _FSW(rs1, rs2, imm) Stype(39, 2, rs1, rs2, imm)
|
||||
#define _FMADD_S(rd, rs1, rs2, rs3) R4type(67, rd, 0, rs1, rs2, 0, rs3)
|
||||
#define _FMSUB_S(rd, rs1, rs2, rs3) R4type(71, rd, 0, rs1, rs2, 0, rs3)
|
||||
#define _FNMSUB_S(rd, rs1, rs2, rs3) R4type(75, rd, 0, rs1, rs2, 0, rs3)
|
||||
#define _FNMADD_S(rd, rs1, rs2, rs3) R4type(79, rd, 0, rs1, rs2, 0, rs3)
|
||||
#define _FADD_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 0)
|
||||
#define _FSUB_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 4)
|
||||
#define _FMUL_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 8)
|
||||
#define _FDIV_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 12)
|
||||
#define _FSQRT_S(rd, rs1) Rtype(83, rd, 0, rs1, 0, 44)
|
||||
#define _FSGNJ_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 16)
|
||||
#define _FSGNJN_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 16)
|
||||
#define _FSGNJX_S(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 16)
|
||||
#define _FMIN_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 20)
|
||||
#define _FMAX_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 20)
|
||||
#define _FCVT_W_S(rd, rs1, rm) Rtype(83, rd, rm, rs1, 0, 96)
|
||||
#define _FCVT_WU_S(rd, rs1, rm) Rtype(83, rd, rm, rs1, 1, 96)
|
||||
#define _FMV_X_W(rd, rs1) Rtype(83, rd, 0, rs1, 0, 112)
|
||||
#define _FEQ_S(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 80)
|
||||
#define _FLT_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 80)
|
||||
#define _FLE_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 80)
|
||||
#define _FCLASS_S(rd, rs1) Rtype(83, rd, 1, rs1, 0, 112)
|
||||
#define _FCVT_S_W(rd, rs1, rm) Rtype(83, rd, rm, rs1, 0, 104)
|
||||
#define _FCVT_S_WU(rd, rs1, rm) Rtype(83, rd, rm, rs1, 1, 104)
|
||||
#define _FMV_W_X(rd, rs1) Rtype(83, rd, 0, rs1, 0, 120)
|
||||
/*
|
||||
* RV64F Standard Extension (in addition to RV32F)
|
||||
*/
|
||||
#define _FCVT_L_S(rd, rs1, rm) Rtype(83, rd, rm, rs1, 2, 96)
|
||||
#define _FCVT_LU_S(rd, rs1, rm) Rtype(83, rd, rm, rs1, 3, 96)
|
||||
#define _FCVT_S_L(rd, rs1, rm) Rtype(83, rd, rm, rs1, 2, 104)
|
||||
#define _FCVT_S_LU(rd, rs1, rm) Rtype(83, rd, rm, rs1, 3, 104)
|
||||
/*
|
||||
* RV32D Standard Extension
|
||||
*/
|
||||
#define _FLD(rd, rs1, im) Itype(7, rd, 3, rs1, im)
|
||||
#define _FSD(rs1, rs2, imm) Stype(39, 3, rs1, rs2, imm)
|
||||
#define _FMADD_D(rd, rs1, rs2, rs3) R4type(67, rd, 0, rs1, rs2, 1, rs3)
|
||||
#define _FMSUB_D(rd, rs1, rs2, rs3) R4type(71, rd, 0, rs1, rs2, 1, rs3)
|
||||
#define _FNMSUB_D(rd, rs1, rs2, rs3) R4type(75, rd, 0, rs1, rs2, 1, rs3)
|
||||
#define _FNMADD_D(rd, rs1, rs2, rs3) R4type(79, rd, 0, rs1, rs2, 1, rs3)
|
||||
#define _FADD_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 1)
|
||||
#define _FSUB_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 5)
|
||||
#define _FMUL_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 9)
|
||||
#define _FDIV_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 13)
|
||||
#define _FSQRT_D(rd, rs1) Rtype(83, rd, 0, rs1, 0, 45)
|
||||
#define _FSGNJ_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 17)
|
||||
#define _FSGNJN_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 17)
|
||||
#define _FSGNJX_D(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 17)
|
||||
#define _FMIN_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 21)
|
||||
#define _FMAX_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 21)
|
||||
#define _FCVT_S_D(rd, rs1, rm) Rtype(83, rd, rm, rs1, 1, 32)
|
||||
#define _FCVT_D_S(rd, rs1, rm) Rtype(83, rd, rm, rs1, 0, 33)
|
||||
#define _FEQ_D(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 81)
|
||||
#define _FLT_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 81)
|
||||
#define _FLE_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 81)
|
||||
#define _FCLASS_D(rd, rs1) Rtype(83, rd, 1, rs1, 0, 113)
|
||||
#define _FCVT_W_D(rd, rs1, rm) Rtype(83, rd, rm, rs1, 0, 97)
|
||||
#define _FCVT_WU_D(rd, rs1, rm) Rtype(83, rd, rm, rs1, 1, 97)
|
||||
#define _FCVT_D_W(rd, rs1, rm) Rtype(83, rd, rm, rs1, 0, 105)
|
||||
#define _FCVT_D_WU(rd, rs1, rm) Rtype(83, rd, rm, rs1, 1, 105)
|
||||
/*
|
||||
* RV64D Standard Extension (in addition to RV32D)
|
||||
*/
|
||||
#define _FCVT_L_D(rd, rs1, rm) Rtype(83, rd, rm, rs1, 2, 97)
|
||||
#define _FCVT_LU_D(rd, rs1, rm) Rtype(83, rd, rm, rs1, 3, 97)
|
||||
#define _FMV_X_D(rd, rs1) Rtype(83, rd, 0, rs1, 0, 113)
|
||||
#define _FCVT_D_L(rd, rs1, rm) Rtype(83, rd, rm, rs1, 2, 105)
|
||||
#define _FCVT_D_LU(rd, rs1, rm) Rtype(83, rd, rm, rs1, 3, 105)
|
||||
#define _FMV_D_X(rd, rs1) Rtype(83, rd, 0, rs1, 0, 121)
|
||||
/*
|
||||
* Pseudo instructions
|
||||
*/
|
||||
#define _FMV_S(r0, r1) _FSGNJ_S(r0, r1, r1)
|
||||
#define _FABS_S(r0, r1) _FSGNJX_S(r0, r1, r1)
|
||||
#define _FNEG_S(r0, r1) _FSGNJN_S(r0, r1, r1)
|
||||
#define _FMV_D(r0, r1) _FSGNJ_D(r0, r1, r1)
|
||||
#define _FABS_D(r0, r1) _FSGNJX_D(r0, r1, r1)
|
||||
#define _FNEG_D(r0, r1) _FSGNJN_D(r0, r1, r1)
|
||||
|
||||
// Binary ALU operations
|
||||
static void addr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void addr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
|
||||
// Unary ALU operations
|
||||
static void sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void negr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void negr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void absr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void absr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
|
||||
// Transfer operations
|
||||
static void movr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void movr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
|
||||
// Argument management
|
||||
static void retr_f(jit_state_t *_jit, int32_t u);
|
||||
static void retr_d(jit_state_t *_jit, int32_t u);
|
||||
|
||||
// Load operations
|
||||
static void ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0);
|
||||
static void ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0);
|
||||
static void ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0);
|
||||
static void ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0);
|
||||
|
||||
// Store operations
|
||||
static void str_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void str_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static void sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0);
|
||||
static void stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1);
|
||||
static void sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0);
|
||||
static void stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2);
|
||||
static void stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1);
|
||||
|
||||
// Branch instructions
|
||||
static jit_reloc_t bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bler_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bger_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bner_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t buneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunger_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bler_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bger_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bner_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t buneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bunger_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
static jit_reloc_t bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||
|
||||
/*
|
||||
* Binary ALU operations
|
||||
*/
|
||||
static void
|
||||
addr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FADD_S(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
addr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FADD_D(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FSUB_S(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FSUB_D(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FMUL_S(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FMUL_D(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FDIV_S(r0, r1, r2));
|
||||
}
|
||||
static void
|
||||
divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
em_wp(_jit, _FDIV_D(r0, r1, r2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Unary ALU operations
|
||||
*/
|
||||
static void
|
||||
sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FSQRT_S(r0, r1));
|
||||
}
|
||||
static void
|
||||
sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FSQRT_D(r0, r1));
|
||||
}
|
||||
static void
|
||||
negr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FNEG_S(r0, r1));
|
||||
}
|
||||
static void
|
||||
negr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FNEG_D(r0, r1));
|
||||
}
|
||||
static void
|
||||
absr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FABS_S(r0, r1));
|
||||
}
|
||||
|
||||
static void
|
||||
absr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FABS_D(r0, r1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load operations
|
||||
*/
|
||||
static void
|
||||
ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FLW(r0, r1, 0));
|
||||
}
|
||||
static void
|
||||
ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FLD(r0, r1, 0));
|
||||
}
|
||||
static void
|
||||
ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(t0), i0);
|
||||
ldr_f(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addr(_jit, jit_gpr_regno(t0), r1, r2);
|
||||
ldr_f(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
||||
{
|
||||
if (simm12_p(i0))
|
||||
em_wp(_jit, _FLW(r0, r1, i0));
|
||||
else {
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addi(_jit, jit_gpr_regno(t0), r1, i0);
|
||||
ldr_f(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
}
|
||||
static void
|
||||
ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(t0), i0);
|
||||
ldr_d(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
|
||||
static void
|
||||
ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addr(_jit, jit_gpr_regno(t0), r1, r2);
|
||||
ldr_d(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
|
||||
static void
|
||||
ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
||||
{
|
||||
if (simm12_p(i0))
|
||||
em_wp(_jit, _FLD(r0, r1, i0));
|
||||
else {
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addi(_jit, jit_gpr_regno(t0), r1, i0);
|
||||
ldr_d(_jit, r0, jit_gpr_regno(t0));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Store operations
|
||||
*/
|
||||
static void
|
||||
str_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FSW(r0, r1, 0));
|
||||
}
|
||||
static void
|
||||
str_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FSD(r0, r1, 0));
|
||||
}
|
||||
static void
|
||||
sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(t0), i0);
|
||||
str_f(_jit, jit_gpr_regno(t0), r0);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addr(_jit, jit_gpr_regno(t0), r0, r1);
|
||||
str_f(_jit, jit_gpr_regno(t0), r2);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
||||
{
|
||||
if (simm12_p(i0))
|
||||
em_wp(_jit, _FSW(r0, r1, i0));
|
||||
else {
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addi(_jit, jit_gpr_regno(t0), r0, i0);
|
||||
str_f(_jit, jit_gpr_regno(t0), r1);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
}
|
||||
static void
|
||||
sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(t0), i0);
|
||||
str_d(_jit, jit_gpr_regno(t0), r0);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
||||
{
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addr(_jit, jit_gpr_regno(t0), r0, r1);
|
||||
str_d(_jit, jit_gpr_regno(t0), r2);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
||||
{
|
||||
if (simm12_p(i0))
|
||||
em_wp(_jit, _FSD(r0, r1, i0));
|
||||
else {
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
addi(_jit, jit_gpr_regno(t0), r0, i0);
|
||||
str_d(_jit, jit_gpr_regno(t0), r1);
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transfer operations
|
||||
*/
|
||||
static void
|
||||
movr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
if (r0 != r1)
|
||||
em_wp(_jit, _FMV_S(r0, r1));
|
||||
}
|
||||
|
||||
static void
|
||||
movr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
if (r0 != r1)
|
||||
em_wp(_jit, _FMV_D(r0, r1));
|
||||
}
|
||||
static void
|
||||
movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FMV_X_W(r0, r1));
|
||||
}
|
||||
static void
|
||||
movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FMV_W_X(r0, r1));
|
||||
}
|
||||
static void
|
||||
movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FMV_X_D(r0, r1));
|
||||
}
|
||||
static void
|
||||
movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FMV_D_X(r0, r1));
|
||||
}
|
||||
|
||||
static void
|
||||
truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_W_S(r0, r1, 1));
|
||||
}
|
||||
static void
|
||||
truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_W_D(r0, r1, 1));
|
||||
}
|
||||
static void
|
||||
truncr_f_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_L_S(r0, r1, 1));
|
||||
}
|
||||
static void
|
||||
truncr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_L_D(r0, r1, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
extr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
#if __WORDSIZE == 64
|
||||
em_wp(_jit, _FCVT_S_L(r0, r1, 0));
|
||||
#elif __WORDSIZE == 32
|
||||
em_wp(_jit, _FCVT_S_W(r0, r1, 0));
|
||||
#endif
|
||||
}
|
||||
static void
|
||||
extr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
#if __WORDSIZE == 64
|
||||
em_wp(_jit, _FCVT_D_L(r0, r1, 0));
|
||||
#elif __WORDSIZE == 32
|
||||
em_wp(_jit, _FCVT_D_W(r0, r1, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_D_S(r0, r1, 0));
|
||||
}
|
||||
static void
|
||||
extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
em_wp(_jit, _FCVT_S_D(r0, r1, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0)
|
||||
{
|
||||
union { int32_t i; jit_float32_t f; } u = { .f = i0 };
|
||||
jit_gpr_t reg = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(reg), u.i);
|
||||
em_wp(_jit, _FMV_W_X(r0, jit_gpr_regno(reg)));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
static void
|
||||
movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0)
|
||||
{
|
||||
// TODO: How to move a 64 bit value from a 32 bit X register?
|
||||
// ATM only works on RV64
|
||||
union { int64_t i; jit_float64_t f; } u = { .f = i0 };
|
||||
jit_gpr_t reg = get_temp_gpr(_jit);
|
||||
movi(_jit, jit_gpr_regno(reg), u.i);
|
||||
em_wp(_jit, _FMV_D_X(r0, jit_gpr_regno(reg)));
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Argument management
|
||||
*/
|
||||
static void
|
||||
retval_f(jit_state_t *_jit, int32_t r0)
|
||||
{
|
||||
movr_f(_jit, jit_fpr_regno(_FA0), r0);
|
||||
}
|
||||
|
||||
static void
|
||||
retval_d(jit_state_t *_jit, int32_t r0)
|
||||
{
|
||||
movr_d(_jit, jit_fpr_regno(_FA0), r0);
|
||||
}
|
||||
|
||||
static void
|
||||
retr_f(jit_state_t *_jit, int32_t u)
|
||||
{
|
||||
movr_f(_jit, jit_fpr_regno(_FA0), u);
|
||||
ret(_jit);
|
||||
}
|
||||
|
||||
static void
|
||||
retr_d(jit_state_t *_jit, int32_t u)
|
||||
{
|
||||
movr_d(_jit, jit_fpr_regno(_FA0), u);
|
||||
ret(_jit);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Branch instructions
|
||||
*/
|
||||
|
||||
static jit_reloc_t
|
||||
bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_S(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bler_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_S(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FEQ_S(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bger_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
return bler_f(_jit, r1, r0);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
return bltr_f(_jit, r1, r0);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bner_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FEQ_S(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_S(t0, r1, r0));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_S(t0, r1, r0));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
buneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FLT_S(t0, r0, r1));
|
||||
em_wp(_jit, _FLT_S(t1, r1, r0));
|
||||
orr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunger_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_S(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_S(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FLT_S(t0, r1, r0));
|
||||
em_wp(_jit, _FLT_S(t1, r0, r1));
|
||||
orr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FEQ_S(t0, r0, r0));
|
||||
em_wp(_jit, _FEQ_S(t1, r1, r1));
|
||||
andr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FEQ_S(t0, r1, r1));
|
||||
em_wp(_jit, _FEQ_S(t1, r0, r0));
|
||||
andr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_D(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bler_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_D(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FEQ_D(t0, r0, r1));
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bger_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
return bler_d(_jit, r1, r0);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
return bltr_d(_jit, r1, r0);
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bner_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FEQ_D(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_D(t0, r1, r0));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_D(t0, r1, r0));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
buneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FLT_D(t0, r0, r1));
|
||||
em_wp(_jit, _FLT_D(t1, r1, r0));
|
||||
orr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunger_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLT_D(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
jit_gpr_t tmp1 = get_temp_gpr(_jit);
|
||||
int32_t t0 = jit_gpr_regno(tmp1);
|
||||
|
||||
em_wp(_jit, _FLE_D(t0, r0, r1));
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FLT_D(t0, r1, r0));
|
||||
em_wp(_jit, _FLT_D(t1, r0, r1));
|
||||
orr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FEQ_D(t0, r0, r0));
|
||||
em_wp(_jit, _FEQ_D(t1, r1, r1));
|
||||
andr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = bner(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jit_reloc_t
|
||||
bunordr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
int32_t t0 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
int32_t t1 = jit_gpr_regno(get_temp_gpr(_jit));
|
||||
|
||||
em_wp(_jit, _FEQ_D(t0, r1, r1));
|
||||
em_wp(_jit, _FEQ_D(t1, r0, r0));
|
||||
andr(_jit, t0, t0, t1);
|
||||
jit_reloc_t ret = beqr(_jit, t0, jit_gpr_regno(_ZERO));
|
||||
|
||||
unget_temp_gpr(_jit);
|
||||
return ret;
|
||||
}
|
341
libguile/lightening/lightening/riscv.c
Normal file
341
libguile/lightening/lightening/riscv.c
Normal file
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright (C) 2021-2024 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* Authors:
|
||||
* Ekaitz Zarraga <ekaitz@elenq.tech>
|
||||
*/
|
||||
|
||||
#include "riscv-cpu.c"
|
||||
#include "riscv-fpu.c"
|
||||
|
||||
static const jit_gpr_t abi_gpr_args[] = {
|
||||
_A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7
|
||||
};
|
||||
static const jit_fpr_t abi_fpr_args[] = {
|
||||
_FA0, _FA1, _FA2, _FA3, _FA4, _FA5, _FA6, _FA7
|
||||
};
|
||||
static const int abi_gpr_arg_count = sizeof(abi_gpr_args) / sizeof(abi_gpr_args[0]);
|
||||
static const int abi_fpr_arg_count = sizeof(abi_fpr_args) / sizeof(abi_fpr_args[0]);
|
||||
|
||||
struct abi_arg_iterator
|
||||
{
|
||||
const jit_operand_t *args;
|
||||
size_t argc;
|
||||
|
||||
size_t arg_idx;
|
||||
size_t gpr_idx;
|
||||
size_t fpr_idx;
|
||||
uint32_t vfp_used_registers;
|
||||
size_t stack_size;
|
||||
size_t stack_padding;
|
||||
};
|
||||
|
||||
static size_t page_size;
|
||||
|
||||
jit_bool_t
|
||||
jit_get_cpu(void)
|
||||
{
|
||||
page_size = sysconf(_SC_PAGE_SIZE);
|
||||
// FIXME check version, extensions, hardware fp support
|
||||
//
|
||||
// List of macro definitions for riscv support:
|
||||
// -------------------------------------------
|
||||
// __riscv: defined for any RISC-V target. Older versions of the GCC
|
||||
// toolchain defined __riscv__.
|
||||
//
|
||||
// __riscv_xlen: 32 for RV32 and 64 for RV64.
|
||||
//
|
||||
// __riscv_float_abi_soft, __riscv_float_abi_single,
|
||||
// __riscv_float_abi_double: one of these three will be defined, depending on
|
||||
// target ABI.
|
||||
//
|
||||
// __riscv_cmodel_medlow, __riscv_cmodel_medany: one of these two will be
|
||||
// defined, depending on the target code model.
|
||||
//
|
||||
// __riscv_mul: defined when targeting the 'M' ISA extension.
|
||||
//
|
||||
// __riscv_muldiv: defined when targeting the 'M' ISA extension and -mno-div
|
||||
// has not been used.
|
||||
//
|
||||
// __riscv_div: defined when targeting the 'M' ISA extension and -mno-div has
|
||||
// not been used.
|
||||
//
|
||||
// __riscv_atomic: defined when targeting the 'A' ISA extension.
|
||||
//
|
||||
// __riscv_flen: 32 when targeting the 'F' ISA extension (but not 'D') and 64
|
||||
// when targeting 'FD'.
|
||||
//
|
||||
// __riscv_fdiv: defined when targeting the 'F' or 'D' ISA extensions and
|
||||
// -mno-fdiv has not been used.
|
||||
//
|
||||
// __riscv_fsqrt: defined when targeting the 'F' or 'D' ISA extensions and
|
||||
// -mno-fdiv has not been used.
|
||||
//
|
||||
// __riscv_compressed: defined when targeting the 'C' ISA extension.
|
||||
return 1;
|
||||
}
|
||||
|
||||
jit_bool_t
|
||||
jit_init(jit_state_t *_jit)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
jit_initial_frame_size (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc,
|
||||
const jit_operand_t *args)
|
||||
{
|
||||
memset(iter, 0, sizeof *iter);
|
||||
iter->argc = argc;
|
||||
iter->args = args;
|
||||
}
|
||||
|
||||
static void
|
||||
next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg)
|
||||
{
|
||||
// RISC-V Calling convention:
|
||||
// https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
|
||||
//
|
||||
// The RISC-V calling convention passes arguments in registers when possible.
|
||||
// Up to eight integer registers, a0–a7, and up to eight floating-point
|
||||
// registers, fa0–fa7, are used for this purpose.
|
||||
//
|
||||
// If argument i < 8 is a floating-point type, it is passed in floating-point
|
||||
// register fai; otherwise, it is passed in integer register ai.
|
||||
|
||||
ASSERT(iter->arg_idx < iter->argc);
|
||||
enum jit_operand_abi abi = iter->args[iter->arg_idx].abi;
|
||||
iter->arg_idx++;
|
||||
if (is_gpr_arg(abi) && iter->gpr_idx < abi_gpr_arg_count) {
|
||||
*arg = jit_operand_gpr (abi, abi_gpr_args[iter->gpr_idx++]);
|
||||
return;
|
||||
}
|
||||
if (is_fpr_arg(abi) && iter->fpr_idx < abi_fpr_arg_count) {
|
||||
*arg = jit_operand_fpr (abi, abi_fpr_args[iter->fpr_idx++]);
|
||||
return;
|
||||
} else if (is_fpr_arg(abi) && iter->gpr_idx < abi_gpr_arg_count) {
|
||||
*arg = jit_operand_gpr (abi, abi_gpr_args[iter->gpr_idx++]);
|
||||
return;
|
||||
}
|
||||
*arg = jit_operand_mem (abi, JIT_SP, iter->stack_size);
|
||||
#if __WORDSIZE == 32
|
||||
iter->stack_size += 4 + (abi == JIT_OPERAND_ABI_DOUBLE ? 4 : 0);
|
||||
#elif __WORDSIZE == 64
|
||||
iter->stack_size += 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
jit_flush(void *fptr, void *tptr)
|
||||
{
|
||||
jit_word_t f = (jit_word_t)fptr & -page_size;
|
||||
jit_word_t t = (((jit_word_t)tptr) + page_size - 1) & -page_size;
|
||||
__clear_cache((void *)f, (void *)t);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
jit_stack_alignment(void)
|
||||
{
|
||||
return 16;
|
||||
// NOTE: See: https://github.com/riscv/riscv-gcc/issues/61
|
||||
}
|
||||
|
||||
static void
|
||||
jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr)
|
||||
{
|
||||
}
|
||||
|
||||
static void*
|
||||
bless_function_pointer(void *ptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static jit_gpr_t
|
||||
get_callr_temp (jit_state_t * _jit)
|
||||
{
|
||||
return _RA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Veneers
|
||||
*/
|
||||
struct veneer{
|
||||
instr_t auipc;
|
||||
instr_t load; // `ld` in RV64 and `lw` in RV32
|
||||
instr_t jalr;
|
||||
#if __WORDSIZE == 64
|
||||
uint32_t padding;
|
||||
uint64_t address;
|
||||
#elif __WORDSIZE == 32
|
||||
uint32_t address;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
||||
{
|
||||
// We need to generate something like this:
|
||||
// ----------------------------------------------
|
||||
// 32 bits: | 64 bits:
|
||||
// auipc t0, 0 | auipc t0, 0
|
||||
// ld t0, 12(t0) | ld t0, 16(t0)
|
||||
// jalr zero, 0(t0) | jalr zero, 0(t0)
|
||||
// ADDRESS_LITERAL | .byte 0x00, 0x00, 0x00, 0x00 (padding)
|
||||
// | ADDRESS_LITERAL
|
||||
//
|
||||
jit_gpr_t t0 = get_temp_gpr(_jit);
|
||||
emit_u32(_jit, _AUIPC(jit_gpr_regno(t0), 0));
|
||||
#if __WORDSIZE == 64
|
||||
emit_u32(_jit, _LD(jit_gpr_regno(t0), jit_gpr_regno(t0), 16));
|
||||
#elif __WORDSIZE == 32
|
||||
emit_u32(_jit, _LW(jit_gpr_regno(t0), jit_gpr_regno(t0), 12));
|
||||
#endif
|
||||
emit_u32(_jit, _JALR(jit_gpr_regno(_ZERO), jit_gpr_regno(t0), 0));
|
||||
#if __WORDSIZE == 64
|
||||
emit_u32(_jit, 0); // Padding
|
||||
emit_u64(_jit, (uint64_t) target);
|
||||
#elif __WORDSIZE == 32
|
||||
emit_u32(_jit, (uint32_t) target);
|
||||
#endif
|
||||
unget_temp_gpr(_jit);
|
||||
}
|
||||
|
||||
static void
|
||||
patch_veneer(uint32_t *loc, jit_pointer_t addr)
|
||||
{
|
||||
struct veneer *v = (struct veneer*) loc;
|
||||
#if __WORDSIZE == 64
|
||||
v->address = (uint64_t) addr;
|
||||
#elif __WORDSIZE == 32
|
||||
v->address = (uint32_t) addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Conditional jumps
|
||||
*/
|
||||
static void
|
||||
patch_jcc_offset(uint32_t *loc, ptrdiff_t v)
|
||||
{
|
||||
instr_t *i = (instr_t *) loc;
|
||||
i->w = patch_cc_jump(i->w, v);
|
||||
}
|
||||
static void
|
||||
patch_veneer_jcc_offset(uint32_t *loc, ptrdiff_t offset){
|
||||
patch_jcc_offset(loc, offset);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
read_jcc_offset(uint32_t *loc)
|
||||
{
|
||||
instr_t i;
|
||||
i.w = *loc;
|
||||
|
||||
int32_t offset = i.B.imm12 << 31;
|
||||
offset >>= 20;
|
||||
offset |= (i.B.imm11 << 11);
|
||||
offset |= (i.B.imm10_5 << 5);
|
||||
offset |= (i.B.imm4_1 << 1);
|
||||
|
||||
return offset;
|
||||
}
|
||||
static int
|
||||
offset_in_jcc_range(ptrdiff_t offset, int flags)
|
||||
{
|
||||
if(offset & 1)
|
||||
return 0;
|
||||
else
|
||||
return simm12_p(offset >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditional jumps
|
||||
*/
|
||||
static int32_t read_jmp_offset(uint32_t *loc)
|
||||
{
|
||||
instr_t i;
|
||||
i.w = *loc;
|
||||
|
||||
int32_t offset = i.J.imm20 << 31;
|
||||
offset >>= 12;
|
||||
offset |= (i.J.imm19_12 << 12);
|
||||
offset |= (i.J.imm11 << 11);
|
||||
offset |= (i.J.imm10_1 << 1);
|
||||
return offset;
|
||||
}
|
||||
static int
|
||||
offset_in_jmp_range(ptrdiff_t offset, int flags)
|
||||
{
|
||||
if(offset & 1)
|
||||
return 0;
|
||||
else
|
||||
return simm20_p(offset >> 1);
|
||||
}
|
||||
|
||||
static void
|
||||
patch_jmp_offset(uint32_t *loc, ptrdiff_t v)
|
||||
{
|
||||
instr_t *i = (instr_t *) loc;
|
||||
i->w = patch_jump(i->w, v);
|
||||
}
|
||||
|
||||
static void
|
||||
patch_veneer_jmp_offset(uint32_t *loc, ptrdiff_t offset)
|
||||
{
|
||||
patch_jmp_offset(loc, offset);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Jumps around the veneer
|
||||
*/
|
||||
static void
|
||||
patch_jmp_without_veneer(jit_state_t *_jit, uint32_t *loc)
|
||||
{
|
||||
patch_jmp_offset(loc, _jit->pc.uw - (uintptr_t)loc);
|
||||
}
|
||||
static uint32_t*
|
||||
jmp_without_veneer(jit_state_t *_jit)
|
||||
{
|
||||
uint32_t *loc = _jit->pc.ui;
|
||||
emit_u32(_jit, _JAL(jit_gpr_regno(_ZERO), 0));
|
||||
return loc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load from pool offset
|
||||
*/
|
||||
static void
|
||||
patch_load_from_pool_offset(uint32_t *loc, int32_t v)
|
||||
{
|
||||
load_from_pool_t *i = (load_from_pool_t *) loc;
|
||||
i->l = patch_load_from_pool(i->l, v);
|
||||
}
|
||||
static int32_t
|
||||
read_load_from_pool_offset(uint32_t *loc)
|
||||
{
|
||||
load_from_pool_t *i = (load_from_pool_t*) loc;
|
||||
return i->inst.auipc.U.imm31_12 + i->inst.load.I.imm11_0;
|
||||
}
|
||||
|
194
libguile/lightening/lightening/riscv.h
Normal file
194
libguile/lightening/lightening/riscv.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (C) 2021-2024 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* Authors:
|
||||
* Ekaitz Zarraga <ekaitz@elenq.tech>
|
||||
*/
|
||||
|
||||
#ifndef _jit_riscv_h
|
||||
#define _jit_riscv_h
|
||||
|
||||
#define JIT_NEEDS_LITERAL_POOL 1
|
||||
|
||||
// x registers
|
||||
// Special registers
|
||||
#define _RA JIT_GPR(1) // Return address
|
||||
#define _SP JIT_GPR(2) // Stack pointer
|
||||
#define _GP JIT_GPR(3) // Global pointer
|
||||
#define _TP JIT_GPR(4) // Thread pointer
|
||||
#define _FP JIT_GPR(8) // Frame pointer
|
||||
#define _ZERO JIT_GPR(0) // Always zero
|
||||
// Argument passing
|
||||
#define _A0 JIT_GPR(10)
|
||||
#define _A1 JIT_GPR(11)
|
||||
#define _A2 JIT_GPR(12)
|
||||
#define _A3 JIT_GPR(13)
|
||||
#define _A4 JIT_GPR(14)
|
||||
#define _A5 JIT_GPR(15)
|
||||
#define _A6 JIT_GPR(16)
|
||||
#define _A7 JIT_GPR(17)
|
||||
// Saved registers
|
||||
#define _S0 _FP // S0 is the frame pointer normally
|
||||
#define _S1 JIT_GPR(9)
|
||||
#define _S2 JIT_GPR(18)
|
||||
#define _S3 JIT_GPR(19)
|
||||
#define _S4 JIT_GPR(20)
|
||||
#define _S5 JIT_GPR(21)
|
||||
#define _S6 JIT_GPR(22)
|
||||
#define _S7 JIT_GPR(23)
|
||||
#define _S8 JIT_GPR(24)
|
||||
#define _S9 JIT_GPR(25)
|
||||
#define _S10 JIT_GPR(26)
|
||||
#define _S11 JIT_GPR(27)
|
||||
// Temporaries
|
||||
#define _T0 JIT_GPR(5)
|
||||
#define _T1 JIT_GPR(6)
|
||||
#define _T2 JIT_GPR(7)
|
||||
#define _T3 JIT_GPR(28)
|
||||
#define _T4 JIT_GPR(29)
|
||||
#define _T5 JIT_GPR(30)
|
||||
#define _T6 JIT_GPR(31)
|
||||
|
||||
// f registers
|
||||
// Termporaries
|
||||
#define _FT0 JIT_FPR(0)
|
||||
#define _FT1 JIT_FPR(1)
|
||||
#define _FT2 JIT_FPR(2)
|
||||
#define _FT3 JIT_FPR(3)
|
||||
#define _FT4 JIT_FPR(4)
|
||||
#define _FT5 JIT_FPR(5)
|
||||
#define _FT6 JIT_FPR(6)
|
||||
#define _FT7 JIT_FPR(7)
|
||||
#define _FT8 JIT_FPR(28)
|
||||
#define _FT9 JIT_FPR(29)
|
||||
#define _FT10 JIT_FPR(30)
|
||||
#define _FT11 JIT_FPR(31)
|
||||
// Saved registers
|
||||
#define _FS0 JIT_FPR(8)
|
||||
#define _FS1 JIT_FPR(9)
|
||||
#define _FS2 JIT_FPR(18)
|
||||
#define _FS3 JIT_FPR(19)
|
||||
#define _FS4 JIT_FPR(20)
|
||||
#define _FS5 JIT_FPR(21)
|
||||
#define _FS6 JIT_FPR(22)
|
||||
#define _FS7 JIT_FPR(23)
|
||||
#define _FS8 JIT_FPR(24)
|
||||
#define _FS9 JIT_FPR(25)
|
||||
#define _FS10 JIT_FPR(26)
|
||||
#define _FS11 JIT_FPR(27)
|
||||
// Argument passing
|
||||
#define _FA0 JIT_FPR(10)
|
||||
#define _FA1 JIT_FPR(11)
|
||||
#define _FA2 JIT_FPR(12)
|
||||
#define _FA3 JIT_FPR(13)
|
||||
#define _FA4 JIT_FPR(14)
|
||||
#define _FA5 JIT_FPR(15)
|
||||
#define _FA6 JIT_FPR(16)
|
||||
#define _FA7 JIT_FPR(17)
|
||||
|
||||
|
||||
// JIT Registers
|
||||
// ----------------------------------------------------------------------
|
||||
// Caller-save registers JIT_R${NUM}
|
||||
// Callee-save registers JIT_V${NUM}
|
||||
// Caller-save temporary registers JIT_TMP${NUM}
|
||||
// Caller-save floating point registers JIT_F${NUM}
|
||||
// Callee-save floating point registers JIT_VF${NUM}
|
||||
// Caller-save floating point temporary registers JIT_FTMP${NUM}
|
||||
|
||||
// Caller-save registers
|
||||
#define JIT_R0 _A0
|
||||
#define JIT_R1 _A1
|
||||
#define JIT_R2 _A2
|
||||
#define JIT_R3 _A3
|
||||
#define JIT_R4 _A4
|
||||
#define JIT_R5 _A5
|
||||
#define JIT_R6 _A6
|
||||
#define JIT_R7 _A7
|
||||
|
||||
// Use this as a CARRY
|
||||
#define JIT_CARRY _T0
|
||||
#define JIT_TMP0 _T1
|
||||
#define JIT_TMP1 _T2
|
||||
#define JIT_TMP2 _T3
|
||||
|
||||
#define JIT_TMP3 _T4
|
||||
// Temporaries
|
||||
#define JIT_TMP4 _T5
|
||||
#define JIT_TMP5 _T6
|
||||
|
||||
// Callee-save registers
|
||||
#define JIT_V0 _S1
|
||||
#define JIT_V1 _S2
|
||||
#define JIT_V2 _S3
|
||||
#define JIT_V3 _S4
|
||||
#define JIT_V4 _S5
|
||||
#define JIT_V5 _S6
|
||||
#define JIT_V6 _S7
|
||||
#define JIT_V7 _S8
|
||||
#define JIT_V8 _S9
|
||||
#define JIT_V9 _S10
|
||||
#define JIT_V10 _S11
|
||||
|
||||
|
||||
// Callee-save floating point registers
|
||||
#define JIT_VF0 _FS0
|
||||
#define JIT_VF1 _FS1
|
||||
#define JIT_VF2 _FS2
|
||||
#define JIT_VF3 _FS3
|
||||
#define JIT_VF4 _FS4
|
||||
#define JIT_VF5 _FS5
|
||||
#define JIT_VF6 _FS6
|
||||
#define JIT_VF7 _FS7
|
||||
#define JIT_VF8 _FS8
|
||||
#define JIT_VF9 _FS9
|
||||
#define JIT_VF10 _FS10
|
||||
#define JIT_VF11 _FS11
|
||||
|
||||
// Caller save floating point registers
|
||||
#define JIT_F0 _FA0
|
||||
#define JIT_F1 _FA1
|
||||
#define JIT_F2 _FA2
|
||||
#define JIT_F3 _FA3
|
||||
#define JIT_F4 _FA4
|
||||
#define JIT_F5 _FA5
|
||||
#define JIT_F6 _FA6
|
||||
#define JIT_F7 _FA7
|
||||
// NOTE: These are temporaries, but we can use them as general purpose
|
||||
// registers as there's only one temporary JIT_FTMP supported by lightening.c
|
||||
#define JIT_F8 _FT0
|
||||
#define JIT_F9 _FT1
|
||||
#define JIT_F10 _FT2
|
||||
#define JIT_F11 _FT3
|
||||
#define JIT_F12 _FT4
|
||||
#define JIT_F13 _FT5
|
||||
#define JIT_F14 _FT6
|
||||
#define JIT_F15 _FT7
|
||||
#define JIT_F16 _FT8
|
||||
#define JIT_F17 _FT9
|
||||
#define JIT_F18 _FT10
|
||||
|
||||
// Floating point temporary register
|
||||
#define JIT_FTMP _FT11
|
||||
|
||||
// Special purpose registers
|
||||
#define JIT_FP _FP
|
||||
#define JIT_LR _RA
|
||||
#define JIT_SP _SP
|
||||
|
||||
// TODO: Make sure this is correct
|
||||
#define JIT_PLATFORM_CALLEE_SAVE_GPRS JIT_LR
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2017, 2019 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2012-2017, 2019, 2025 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
|
@ -128,13 +128,24 @@ movdlxr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|||
{
|
||||
ssexr(_jit, 0x66, X86_SSE_X2G, r0, r1);
|
||||
}
|
||||
static void
|
||||
movdlrx(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
ssexr(_jit, 0x66, X86_SSE_G2X, r0, r1);
|
||||
}
|
||||
|
||||
static void movdqxr(jit_state_t *_jit, int32_t r0, int32_t r1) maybe_unused;
|
||||
static void movdqrx(jit_state_t *_jit, int32_t r0, int32_t r1) maybe_unused;
|
||||
static void
|
||||
movdqxr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
sselxr(_jit, 0x66, X86_SSE_X2G, r0, r1);
|
||||
}
|
||||
static void
|
||||
movdqrx(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
sselxr(_jit, 0x66, X86_SSE_G2X, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
movssmr(jit_state_t *_jit, int32_t md, int32_t rb, int32_t ri, int32_t ms, int32_t rd)
|
||||
|
@ -171,6 +182,29 @@ movr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|||
ssexr(_jit, 0xf2, X86_SSE_MOV, r0, r1);
|
||||
}
|
||||
|
||||
static void
|
||||
movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
movdlrx(_jit, r0, r1);
|
||||
}
|
||||
static void
|
||||
movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
movdlxr(_jit, r0, r1);
|
||||
}
|
||||
#if __X64
|
||||
static void
|
||||
movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
movdqrx(_jit, r0, r1);
|
||||
}
|
||||
static void
|
||||
movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
movdqxr(_jit, r0, r1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
addssr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||
{
|
||||
|
|
|
@ -405,3 +405,9 @@ bless_function_pointer(void *ptr)
|
|||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static jit_gpr_t
|
||||
get_callr_temp (jit_state_t * _jit)
|
||||
{
|
||||
return _RAX;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
TESTS=$(sort $(basename $(wildcard *.c)))
|
||||
TARGETS ?= native ia32 aarch64 armv7
|
||||
TESTS ?= $(sort $(basename $(wildcard *.c)))
|
||||
TARGETS ?= native ia32 aarch64 armv7 riscv
|
||||
|
||||
# Suitable values of cross-compiler variables for Debian:
|
||||
#
|
||||
|
@ -14,13 +14,15 @@ TARGETS ?= native ia32 aarch64 armv7
|
|||
# libc6-dev:amd64 gcc make \
|
||||
# qemu binfmt-support qemu-user-static \
|
||||
# gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 \
|
||||
# gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64
|
||||
# gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64\
|
||||
# gcc-riscv64-linux-gnu libc6-dev-riscv64-cross libc6:riscv64
|
||||
#
|
||||
CC = gcc
|
||||
CC_IA32=guix environment --pure -s i686-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CC_AARCH64=guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CC_ARMv7=guix environment --pure -s armhf-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CFLAGS = -Wall -O0 -g
|
||||
CC_IA32 ?= guix environment --pure -s i686-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CC_AARCH64 ?= guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CC_ARMv7 ?= guix environment --pure -s armhf-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CC_RISCV ?= guix environment --pure -s riscv64-linux --ad-hoc gcc-toolchain -- gcc
|
||||
CFLAGS ?= -Wall -O0 -g
|
||||
|
||||
all: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS)))
|
||||
|
||||
|
@ -54,6 +56,10 @@ test-armv7-%: CC = $(CC_ARMv7)
|
|||
test-armv7-%: %.c lightening-armv7.o test.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-armv7.o $<
|
||||
|
||||
test-riscv-%: CC = $(CC_RISCV)
|
||||
test-riscv-%: %.c lightening-riscv.o test.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-riscv.o $<
|
||||
|
||||
.PRECIOUS: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS)))
|
||||
.PRECIOUS: $(foreach TARGET,$(TARGETS),lightening-$(TARGET).o)
|
||||
|
||||
|
|
165
libguile/lightening/tests/call_10_2.c
Normal file
165
libguile/lightening/tests/call_10_2.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
#include "test.h"
|
||||
#include "regarrays.inc"
|
||||
|
||||
#define DEFINE_TEST_INT(ABI_TYPE, TYPE, LIT, NEGATE) \
|
||||
static TYPE \
|
||||
check_##TYPE (TYPE a, TYPE b, TYPE c, TYPE d, TYPE e, \
|
||||
TYPE f, TYPE g, TYPE h, TYPE i, TYPE j) \
|
||||
{ \
|
||||
ASSERT(a == LIT(0)); \
|
||||
ASSERT(b == NEGATE(1)); \
|
||||
ASSERT(c == LIT(2)); \
|
||||
ASSERT(d == NEGATE(3)); \
|
||||
ASSERT(e == LIT(4)); \
|
||||
ASSERT(f == NEGATE(5)); \
|
||||
ASSERT(g == LIT(6)); \
|
||||
ASSERT(h == NEGATE(7)); \
|
||||
ASSERT(i == LIT(8)); \
|
||||
ASSERT(j == NEGATE(9)); \
|
||||
return LIT(42); \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
run_test_##TYPE (jit_state_t *j, uint8_t *arena_base, size_t arena_size, \
|
||||
jit_gpr_t base) \
|
||||
{ \
|
||||
jit_begin(j, arena_base, arena_size); \
|
||||
size_t align = jit_enter_jit_abi(j, v_count, 0, 0); \
|
||||
jit_load_args_1(j, jit_operand_gpr (JIT_OPERAND_ABI_POINTER, base)); \
|
||||
\
|
||||
jit_operand_t args[10] = { \
|
||||
jit_operand_mem(ABI_TYPE, base, 0 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 1 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 2 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 3 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 4 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 5 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 6 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 7 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 8 * sizeof(TYPE)), \
|
||||
jit_operand_mem(ABI_TYPE, base, 9 * sizeof(TYPE)), \
|
||||
}; \
|
||||
jit_calli(j, check_##TYPE, 10, args); \
|
||||
jit_leave_jit_abi(j, v_count, 0, align); \
|
||||
jit_ret(j); \
|
||||
\
|
||||
size_t size = 0; \
|
||||
void* ret = jit_end(j, &size); \
|
||||
\
|
||||
TYPE (*f)(TYPE*) = ret; \
|
||||
\
|
||||
TYPE iargs[10] = { LIT(0), NEGATE(1), LIT(2), NEGATE(3), LIT(4), \
|
||||
NEGATE(5), LIT(6), NEGATE(7), LIT(8), NEGATE(9) }; \
|
||||
ASSERT(f(iargs) == LIT(42)); \
|
||||
}
|
||||
|
||||
#define LIT(X) (X)
|
||||
#define NEGATE(X) (-X)
|
||||
DEFINE_TEST_INT(JIT_OPERAND_ABI_INT32, int32_t, LIT, NEGATE);
|
||||
#if (UINTPTR_MAX == UINT64_MAX)
|
||||
DEFINE_TEST_INT(JIT_OPERAND_ABI_INT64, int64_t, LIT, NEGATE);
|
||||
#endif
|
||||
#undef NEGATE
|
||||
|
||||
#define NEGATE(X) (~X)
|
||||
DEFINE_TEST_INT(JIT_OPERAND_ABI_UINT32, uint32_t, LIT, NEGATE);
|
||||
#if (UINTPTR_MAX == UINT64_MAX)
|
||||
DEFINE_TEST_INT(JIT_OPERAND_ABI_UINT64, uint64_t, LIT, NEGATE);
|
||||
#endif
|
||||
#undef NEGATE
|
||||
#undef LIT
|
||||
|
||||
typedef uint8_t* ptr_t;
|
||||
#define LIT(X) ((ptr_t)(uintptr_t)(X))
|
||||
#define NEGATE(X) ((ptr_t)(~(uintptr_t)(X)))
|
||||
DEFINE_TEST_INT(JIT_OPERAND_ABI_POINTER, ptr_t, LIT, NEGATE);
|
||||
|
||||
static double
|
||||
check_double (double a, double b, double c, double d, double e,
|
||||
double f, double g, double h, double i, double j)
|
||||
{
|
||||
ASSERT(a == 0.0);
|
||||
ASSERT(b == -1.0);
|
||||
ASSERT(c == -0xfffffffffffffp+100l);
|
||||
ASSERT(d == +0xfffffffffffffp-100l);
|
||||
ASSERT(e == -0xfffffffffffffp+101l);
|
||||
ASSERT(f == +0xfffffffffffffp-102l);
|
||||
ASSERT(g == -0xfffffffffffffp+102l);
|
||||
ASSERT(h == +0xfffffffffffffp-103l);
|
||||
ASSERT(i == -0xfffffffffffffp+103l);
|
||||
ASSERT(j == +0xfffffffffffffp-104l);
|
||||
return 42;
|
||||
}
|
||||
|
||||
static void
|
||||
run_test_double (jit_state_t *j, uint8_t *arena_base, size_t arena_size,
|
||||
jit_gpr_t base)
|
||||
{
|
||||
double dargs[10] = {
|
||||
0.0,
|
||||
-1.0,
|
||||
-0xfffffffffffffp+100l,
|
||||
+0xfffffffffffffp-100l,
|
||||
-0xfffffffffffffp+101l,
|
||||
+0xfffffffffffffp-102l,
|
||||
-0xfffffffffffffp+102l,
|
||||
+0xfffffffffffffp-103l,
|
||||
-0xfffffffffffffp+103l,
|
||||
+0xfffffffffffffp-104l,
|
||||
};
|
||||
jit_begin(j, arena_base, arena_size);
|
||||
size_t align = jit_enter_jit_abi(j, v_count, 0, 0);
|
||||
jit_load_args_1(j, jit_operand_gpr (JIT_OPERAND_ABI_POINTER, base));
|
||||
enum jit_operand_abi abi = JIT_OPERAND_ABI_DOUBLE;
|
||||
jit_movi_d(j, JIT_F0, dargs[0]);
|
||||
jit_movi_d(j, JIT_F1, dargs[1]);
|
||||
jit_movi_d(j, JIT_F2, dargs[2]);
|
||||
jit_movi_d(j, JIT_F3, dargs[3]);
|
||||
jit_movi_d(j, JIT_F4, dargs[4]);
|
||||
jit_movi_d(j, JIT_F5, dargs[5]);
|
||||
jit_movi_d(j, JIT_F6, dargs[6]);
|
||||
jit_operand_t args[10] = {
|
||||
jit_operand_fpr(abi, JIT_F0),
|
||||
jit_operand_fpr(abi, JIT_F1),
|
||||
jit_operand_fpr(abi, JIT_F2),
|
||||
jit_operand_fpr(abi, JIT_F3),
|
||||
jit_operand_fpr(abi, JIT_F4),
|
||||
jit_operand_fpr(abi, JIT_F5),
|
||||
jit_operand_fpr(abi, JIT_F6),
|
||||
jit_operand_mem(abi, base, 7 * sizeof(double)),
|
||||
jit_operand_mem(abi, base, 8 * sizeof(double)),
|
||||
jit_operand_mem(abi, base, 9 * sizeof(double)),
|
||||
};
|
||||
jit_calli(j, check_double, 10, args);
|
||||
jit_leave_jit_abi(j, v_count, 0, align);
|
||||
jit_ret(j);
|
||||
|
||||
size_t size = 0;
|
||||
void* ret = jit_end(j, &size);
|
||||
|
||||
double (*f)(double*) = ret;
|
||||
|
||||
ASSERT(f(dargs) == 42);
|
||||
}
|
||||
|
||||
static void
|
||||
run_test (jit_state_t * j, uint8_t * arena_base, size_t arena_size)
|
||||
{
|
||||
for (unsigned i = 0; i < gpr_count; i++)
|
||||
{
|
||||
run_test_int32_t (j, arena_base, arena_size, gpr_ref (i));
|
||||
run_test_uint32_t (j, arena_base, arena_size, gpr_ref (i));
|
||||
#if (UINTPTR_MAX == UINT64_MAX)
|
||||
run_test_int64_t (j, arena_base, arena_size, gpr_ref (i));
|
||||
run_test_uint64_t (j, arena_base, arena_size, gpr_ref (i));
|
||||
#endif
|
||||
run_test_ptr_t (j, arena_base, arena_size, gpr_ref (i));
|
||||
run_test_double (j, arena_base, arena_size, gpr_ref (i));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return main_helper(argc, argv, run_test);
|
||||
}
|
66
libguile/lightening/tests/callr_10.c
Normal file
66
libguile/lightening/tests/callr_10.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "test.h"
|
||||
#include "regarrays.inc"
|
||||
|
||||
static int32_t f(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
|
||||
int32_t f, int32_t g, int32_t h, int32_t i, int32_t j) {
|
||||
ASSERT(a == 0);
|
||||
ASSERT(b == 1);
|
||||
ASSERT(c == 2);
|
||||
ASSERT(d == 3);
|
||||
ASSERT(e == 4);
|
||||
ASSERT(f == 5);
|
||||
ASSERT(g == 6);
|
||||
ASSERT(h == 7);
|
||||
ASSERT(i == 8);
|
||||
ASSERT(j == 9);
|
||||
return 42;
|
||||
}
|
||||
|
||||
static void
|
||||
run_test_2 (jit_state_t *j, uint8_t *arena_base, size_t arena_size,
|
||||
jit_gpr_t base, jit_gpr_t fun)
|
||||
{
|
||||
jit_begin(j, arena_base, arena_size);
|
||||
size_t align = jit_enter_jit_abi(j, v_count, 0, 0);
|
||||
jit_load_args_1(j, jit_operand_gpr (JIT_OPERAND_ABI_POINTER, base));
|
||||
|
||||
jit_operand_t args[10] = {
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 0 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 1 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 2 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 3 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 4 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 5 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 6 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 7 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 8 * sizeof(int32_t)),
|
||||
jit_operand_mem(JIT_OPERAND_ABI_INT32, base, 9 * sizeof(int32_t))
|
||||
};
|
||||
jit_movi(j, fun, (uintptr_t)f);
|
||||
jit_callr(j, fun, 10, args);
|
||||
jit_leave_jit_abi(j, v_count, 0, align);
|
||||
jit_ret(j);
|
||||
|
||||
size_t size = 0;
|
||||
void* ret = jit_end(j, &size);
|
||||
|
||||
int32_t (*f)(int32_t*) = ret;
|
||||
|
||||
int32_t iargs[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
ASSERT(f(iargs) == 42);
|
||||
}
|
||||
|
||||
static void
|
||||
run_test (jit_state_t *jit, uint8_t *arena_base, size_t arena_size)
|
||||
{
|
||||
for (unsigned i = 0; i < gpr_count; i++)
|
||||
for (unsigned j = 0; j < gpr_count; j++)
|
||||
if (i != j)
|
||||
run_test_2 (jit, arena_base, arena_size, gpr_ref(i), gpr_ref(j));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return main_helper(argc, argv, run_test);
|
||||
}
|
26
libguile/lightening/tests/movr_dl.c
Normal file
26
libguile/lightening/tests/movr_dl.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "test.h"
|
||||
|
||||
static void
|
||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||
{
|
||||
#if __WORDSIZE > 32
|
||||
jit_begin(j, arena_base, arena_size);
|
||||
size_t align = jit_enter_jit_abi(j, 0, 0, 0);
|
||||
|
||||
jit_movi_d(j, JIT_F0, 3.14159);
|
||||
jit_movr_l_d(j, JIT_R0, JIT_F0);
|
||||
jit_movr_d_l(j, JIT_F1, JIT_R0);
|
||||
jit_leave_jit_abi(j, 0, 0, align);
|
||||
jit_retr_d(j, JIT_F1);
|
||||
|
||||
double (*f)(void) = jit_end(j, NULL);
|
||||
|
||||
ASSERT(f() == 3.14159);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return main_helper(argc, argv, run_test);
|
||||
}
|
24
libguile/lightening/tests/movr_fi.c
Normal file
24
libguile/lightening/tests/movr_fi.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "test.h"
|
||||
|
||||
static void
|
||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||
{
|
||||
jit_begin(j, arena_base, arena_size);
|
||||
size_t align = jit_enter_jit_abi(j, 0, 0, 0);
|
||||
|
||||
jit_movi_f(j, JIT_F0, 3.14159);
|
||||
jit_movr_i_f(j, JIT_R0, JIT_F0);
|
||||
jit_movr_f_i(j, JIT_F1, JIT_R0);
|
||||
jit_leave_jit_abi(j, 0, 0, align);
|
||||
jit_retr_f(j, JIT_F1);
|
||||
|
||||
float (*f)(void) = jit_end(j, NULL);
|
||||
|
||||
ASSERT(f() == 3.14159f);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return main_helper(argc, argv, run_test);
|
||||
}
|
206
libguile/lightening/tests/regarrays.inc
Normal file
206
libguile/lightening/tests/regarrays.inc
Normal file
|
@ -0,0 +1,206 @@
|
|||
/* Arrays describing the available user registers. -*- mode: c -*- */
|
||||
|
||||
// #ifdef orgy factored out to common include file
|
||||
|
||||
static const jit_gpr_t rregs[] = {
|
||||
JIT_R0,
|
||||
JIT_R1,
|
||||
JIT_R2,
|
||||
#ifdef JIT_R3
|
||||
JIT_R3,
|
||||
#endif
|
||||
#ifdef JIT_R4
|
||||
JIT_R4,
|
||||
#endif
|
||||
#ifdef JIT_R5
|
||||
JIT_R5,
|
||||
#endif
|
||||
#ifdef JIT_R6
|
||||
JIT_R6,
|
||||
#endif
|
||||
#ifdef JIT_R7
|
||||
JIT_R7,
|
||||
#endif
|
||||
#ifdef JIT_R8
|
||||
JIT_R8,
|
||||
#endif
|
||||
#ifdef JIT_R9
|
||||
JIT_R9,
|
||||
#endif
|
||||
#ifdef JIT_R10
|
||||
JIT_R10,
|
||||
#endif
|
||||
#ifdef JIT_R11
|
||||
JIT_R11,
|
||||
#endif
|
||||
#ifdef JIT_R12
|
||||
JIT_R12,
|
||||
#endif
|
||||
#ifdef JIT_R13
|
||||
JIT_R13,
|
||||
#endif
|
||||
#ifdef JIT_R14
|
||||
JIT_R14,
|
||||
#endif
|
||||
#ifdef JIT_R15
|
||||
JIT_R15,
|
||||
#endif
|
||||
#ifdef JIT_R16
|
||||
JIT_R16,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const jit_gpr_t vregs[] = {
|
||||
JIT_V0, JIT_V1, JIT_V2,
|
||||
#ifdef JIT_V3
|
||||
JIT_V3,
|
||||
#endif
|
||||
#ifdef JIT_V4
|
||||
JIT_V4,
|
||||
#endif
|
||||
#ifdef JIT_V5
|
||||
JIT_V5,
|
||||
#endif
|
||||
#ifdef JIT_V6
|
||||
JIT_V6,
|
||||
#endif
|
||||
#ifdef JIT_V7
|
||||
JIT_V7,
|
||||
#endif
|
||||
#ifdef JIT_V8
|
||||
JIT_V8,
|
||||
#endif
|
||||
#ifdef JIT_V9
|
||||
JIT_V9,
|
||||
#endif
|
||||
#ifdef JIT_V10
|
||||
JIT_V10,
|
||||
#endif
|
||||
#ifdef JIT_V11
|
||||
JIT_V11,
|
||||
#endif
|
||||
#ifdef JIT_V12
|
||||
JIT_V12,
|
||||
#endif
|
||||
#ifdef JIT_V13
|
||||
JIT_V13,
|
||||
#endif
|
||||
#ifdef JIT_V14
|
||||
JIT_V14,
|
||||
#endif
|
||||
#ifdef JIT_V15
|
||||
JIT_V15,
|
||||
#endif
|
||||
#ifdef JIT_V16
|
||||
JIT_V16,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const jit_fpr_t fregs[] = {
|
||||
JIT_F0, JIT_F1, JIT_F2,
|
||||
JIT_F2, JIT_F3, JIT_F4,
|
||||
#ifdef JIT_F7
|
||||
JIT_F7,
|
||||
#endif
|
||||
#ifdef JIT_F8
|
||||
JIT_F8,
|
||||
#endif
|
||||
#ifdef JIT_F9
|
||||
JIT_F9,
|
||||
#endif
|
||||
#ifdef JIT_F10
|
||||
JIT_F10,
|
||||
#endif
|
||||
#ifdef JIT_F11
|
||||
JIT_F11,
|
||||
#endif
|
||||
#ifdef JIT_F12
|
||||
JIT_F12,
|
||||
#endif
|
||||
#ifdef JIT_F13
|
||||
JIT_F13,
|
||||
#endif
|
||||
#ifdef JIT_F14
|
||||
JIT_F14,
|
||||
#endif
|
||||
#ifdef JIT_F15
|
||||
JIT_F15,
|
||||
#endif
|
||||
#ifdef JIT_F16
|
||||
JIT_F16,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const jit_fpr_t vfregs[] = {
|
||||
#ifdef JIT_VF0
|
||||
JIT_VF0,
|
||||
#endif
|
||||
#ifdef JIT_VF1
|
||||
JIT_VF1,
|
||||
#endif
|
||||
#ifdef JIT_VF2
|
||||
JIT_VF2,
|
||||
#endif
|
||||
#ifdef JIT_VF2
|
||||
JIT_VF2,
|
||||
#endif
|
||||
#ifdef JIT_VF3
|
||||
JIT_VF3,
|
||||
#endif
|
||||
#ifdef JIT_VF4
|
||||
JIT_VF4,
|
||||
#endif
|
||||
#ifdef JIT_VF5
|
||||
JIT_VF5,
|
||||
#endif
|
||||
#ifdef JIT_VF6
|
||||
JIT_VF6,
|
||||
#endif
|
||||
#ifdef JIT_VF7
|
||||
JIT_VF7,
|
||||
#endif
|
||||
#ifdef JIT_VF8
|
||||
JIT_VF8,
|
||||
#endif
|
||||
#ifdef JIT_VF9
|
||||
JIT_VF9,
|
||||
#endif
|
||||
#ifdef JIT_VF10
|
||||
JIT_VF10,
|
||||
#endif
|
||||
#ifdef JIT_VF11
|
||||
JIT_VF11,
|
||||
#endif
|
||||
#ifdef JIT_VF12
|
||||
JIT_VF12,
|
||||
#endif
|
||||
#ifdef JIT_VF13
|
||||
JIT_VF13,
|
||||
#endif
|
||||
#ifdef JIT_VF14
|
||||
JIT_VF14,
|
||||
#endif
|
||||
#ifdef JIT_VF15
|
||||
JIT_VF15,
|
||||
#endif
|
||||
#ifdef JIT_VF16
|
||||
JIT_VF16,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(X) (sizeof (X)/sizeof ((X)[0]))
|
||||
static const size_t r_count = ARRAY_SIZE (rregs);
|
||||
static const size_t v_count = ARRAY_SIZE (vregs);
|
||||
static const size_t f_count = ARRAY_SIZE (fregs);
|
||||
static const size_t vf_count = ARRAY_SIZE (vfregs);
|
||||
static const size_t gpr_count = r_count + v_count;
|
||||
|
||||
static jit_gpr_t
|
||||
gpr_ref (uintptr_t i)
|
||||
{
|
||||
if (i < r_count)
|
||||
return rregs[i];
|
||||
if (i < r_count + v_count)
|
||||
return vregs[i - r_count];
|
||||
abort ();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue