Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tools/testing/selftests/riscv/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
ARCH ?= $(shell uname -m 2>/dev/null || echo not)

ifneq (,$(filter $(ARCH),riscv))
RISCV_SUBTARGETS ?= abi hwprobe mm sigreturn vector
RISCV_SUBTARGETS ?= abi hwprobe mm sigreturn vector misaligned
else
RISCV_SUBTARGETS :=
endif
Expand Down
1 change: 1 addition & 0 deletions tools/testing/selftests/riscv/misaligned/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
misaligned
12 changes: 12 additions & 0 deletions tools/testing/selftests/riscv/misaligned/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2021 ARM Limited
# Originally tools/testing/arm64/abi/Makefile

CFLAGS += -I$(top_srcdir)/tools/include

TEST_GEN_PROGS := misaligned

include ../../lib.mk

$(OUTPUT)/misaligned: misaligned.c fpu.S gp.S
$(CC) -g3 -static -o$@ -march=rv64imafdc $(CFLAGS) $(LDFLAGS) $^
33 changes: 33 additions & 0 deletions tools/testing/selftests/riscv/misaligned/common.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/

.macro lb_sb temp, offset, src, dst
lb \temp, \offset(\src)
sb \temp, \offset(\dst)
.endm

.macro copy_long_to temp, src, dst
lb_sb \temp, 0, \src, \dst,
lb_sb \temp, 1, \src, \dst,
lb_sb \temp, 2, \src, \dst,
lb_sb \temp, 3, \src, \dst,
lb_sb \temp, 4, \src, \dst,
lb_sb \temp, 5, \src, \dst,
lb_sb \temp, 6, \src, \dst,
lb_sb \temp, 7, \src, \dst,
.endm

.macro sp_stack_prologue offset
addi sp, sp, -8
sub sp, sp, \offset
.endm

.macro sp_stack_epilogue offset
add sp, sp, \offset
addi sp, sp, 8
.endm
180 changes: 180 additions & 0 deletions tools/testing/selftests/riscv/misaligned/fpu.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/

#include "common.S"

#define CASE_ALIGN 4

.macro fpu_load_inst fpreg, inst, precision, load_reg
.align CASE_ALIGN
\inst \fpreg, 0(\load_reg)
fmv.\precision fa0, \fpreg
j 2f
.endm

#define flw(__fpreg) fpu_load_inst __fpreg, flw, s, a4
#define fld(__fpreg) fpu_load_inst __fpreg, fld, d, a4
#define c_flw(__fpreg) fpu_load_inst __fpreg, c.flw, s, a4
#define c_fld(__fpreg) fpu_load_inst __fpreg, c.fld, d, a4
#define c_fldsp(__fpreg) fpu_load_inst __fpreg, c.fldsp, d, sp

.macro fpu_store_inst fpreg, inst, precision, store_reg
.align CASE_ALIGN
fmv.\precision \fpreg, fa0
\inst \fpreg, 0(\store_reg)
j 2f
.endm

#define fsw(__fpreg) fpu_store_inst __fpreg, fsw, s, a4
#define fsd(__fpreg) fpu_store_inst __fpreg, fsd, d, a4
#define c_fsw(__fpreg) fpu_store_inst __fpreg, c.fsw, s, a4
#define c_fsd(__fpreg) fpu_store_inst __fpreg, c.fsd, d, a4
#define c_fsdsp(__fpreg) fpu_store_inst __fpreg, c.fsdsp, d, sp

.macro fp_test_prologue
move a4, a1
/*
* Compute jump offset to store the correct FP register since we don't
* have indirect FP register access (or at least we don't use this
* extension so that works on all archs)
*/
sll t0, a0, CASE_ALIGN
la t2, 1f
add t0, t0, t2
jr t0
.align CASE_ALIGN
1:
.endm

.macro fp_test_prologue_compressed
/* FP registers for compressed instructions starts from 8 to 16 */
addi a0, a0, -8
fp_test_prologue
.endm

#define fp_test_body_compressed(__inst_func) \
__inst_func(f8); \
__inst_func(f9); \
__inst_func(f10); \
__inst_func(f11); \
__inst_func(f12); \
__inst_func(f13); \
__inst_func(f14); \
__inst_func(f15); \
2:

#define fp_test_body(__inst_func) \
__inst_func(f0); \
__inst_func(f1); \
__inst_func(f2); \
__inst_func(f3); \
__inst_func(f4); \
__inst_func(f5); \
__inst_func(f6); \
__inst_func(f7); \
__inst_func(f8); \
__inst_func(f9); \
__inst_func(f10); \
__inst_func(f11); \
__inst_func(f12); \
__inst_func(f13); \
__inst_func(f14); \
__inst_func(f15); \
__inst_func(f16); \
__inst_func(f17); \
__inst_func(f18); \
__inst_func(f19); \
__inst_func(f20); \
__inst_func(f21); \
__inst_func(f22); \
__inst_func(f23); \
__inst_func(f24); \
__inst_func(f25); \
__inst_func(f26); \
__inst_func(f27); \
__inst_func(f28); \
__inst_func(f29); \
__inst_func(f30); \
__inst_func(f31); \
2:
.text

#define __gen_test_inst(__inst, __suffix) \
.global test_ ## __inst; \
test_ ## __inst:; \
fp_test_prologue ## __suffix; \
fp_test_body ## __suffix(__inst); \
ret

#define gen_test_inst_compressed(__inst) \
.option arch,+c; \
__gen_test_inst(c_ ## __inst, _compressed)

#define gen_test_inst(__inst) \
.balign 16; \
.option push; \
.option arch,-c; \
__gen_test_inst(__inst, ); \
.option pop

.macro fp_test_prologue_load_compressed_sp
copy_long_to t0, a1, sp
.endm

.macro fp_test_epilogue_load_compressed_sp
.endm

.macro fp_test_prologue_store_compressed_sp
.endm

.macro fp_test_epilogue_store_compressed_sp
copy_long_to t0, sp, a1
.endm

#define gen_inst_compressed_sp(__inst, __type) \
.global test_c_ ## __inst ## sp; \
test_c_ ## __inst ## sp:; \
sp_stack_prologue a2; \
fp_test_prologue_## __type ## _compressed_sp; \
fp_test_prologue_compressed; \
fp_test_body_compressed(c_ ## __inst ## sp); \
fp_test_epilogue_## __type ## _compressed_sp; \
sp_stack_epilogue a2; \
ret

#define gen_test_load_compressed_sp(__inst) gen_inst_compressed_sp(__inst, load)
#define gen_test_store_compressed_sp(__inst) gen_inst_compressed_sp(__inst, store)

/*
* float_fsw_reg - Set a FP register from a register containing the value
* a0 = FP register index to be set
* a1 = addr where to store register value
* a2 = address offset
* a3 = value to be store
*/
gen_test_inst(fsw)

/*
* float_flw_reg - Get a FP register value and return it
* a0 = FP register index to be retrieved
* a1 = addr to load register from
* a2 = address offset
*/
gen_test_inst(flw)

gen_test_inst(fsd)
#ifdef __riscv_compressed
gen_test_inst_compressed(fsd)
gen_test_store_compressed_sp(fsd)
#endif

gen_test_inst(fld)
#ifdef __riscv_compressed
gen_test_inst_compressed(fld)
gen_test_load_compressed_sp(fld)
#endif
103 changes: 103 additions & 0 deletions tools/testing/selftests/riscv/misaligned/gp.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/

#include "common.S"

.text

.macro __gen_test_inst inst, src_reg
\inst a2, 0(\src_reg)
move a0, a2
.endm

.macro gen_func_header func_name, rvc
.option arch,\rvc
.global test_\func_name
test_\func_name:
.endm

.macro gen_test_inst inst
.option push
gen_func_header \inst, -c
__gen_test_inst \inst, a0
.option pop
ret
.endm

.macro __gen_test_inst_c name, src_reg
.option push
gen_func_header c_\name, +c
__gen_test_inst c.\name, \src_reg
.option pop
ret
.endm

.macro gen_test_inst_c name
__gen_test_inst_c \name, a0
.endm


.macro gen_test_inst_load_c_sp name
.option push
gen_func_header c_\name\()sp, +c
sp_stack_prologue a1
copy_long_to t0, a0, sp
c.ldsp a0, 0(sp)
sp_stack_epilogue a1
.option pop
ret
.endm

.macro lb_sp_sb_a0 reg, offset
lb_sb \reg, \offset, sp, a0
.endm

.macro gen_test_inst_store_c_sp inst_name
.option push
gen_func_header c_\inst_name\()sp, +c
/* Misalign stack pointer */
sp_stack_prologue a1
/* Misalign access */
c.sdsp a2, 0(sp)
copy_long_to t0, sp, a0
sp_stack_epilogue a1
.option pop
ret
.endm


/*
* a0 = addr to load from
* a1 = address offset
* a2 = value to be loaded
*/
gen_test_inst lh
gen_test_inst lhu
gen_test_inst lw
gen_test_inst lwu
gen_test_inst ld
#ifdef __riscv_compressed
gen_test_inst_c lw
gen_test_inst_c ld
gen_test_inst_load_c_sp ld
#endif

/*
* a0 = addr where to store value
* a1 = address offset
* a2 = value to be stored
*/
gen_test_inst sh
gen_test_inst sw
gen_test_inst sd
#ifdef __riscv_compressed
gen_test_inst_c sw
gen_test_inst_c sd
gen_test_inst_store_c_sp sd
#endif

Loading
Loading