summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-06-28 09:32:26 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-06-29 10:04:38 +0200
commit52352387cc0b502fd42164604ae9217700b83e31 (patch)
tree310ce36df9400a55d09b11f87a9cb5bb0460584c /cpukit
parentriscv: Fix global construction (diff)
downloadrtems-52352387cc0b502fd42164604ae9217700b83e31.tar.bz2
riscv: Add floating-point support
Update #3433.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/score/cpu/riscv/cpu.c44
-rw-r--r--cpukit/score/cpu/riscv/include/rtems/asm.h32
-rw-r--r--cpukit/score/cpu/riscv/include/rtems/score/cpu.h61
-rw-r--r--cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h131
-rw-r--r--cpukit/score/cpu/riscv/riscv-context-switch.S46
-rw-r--r--cpukit/score/cpu/riscv/riscv-context-validate.S178
-rw-r--r--cpukit/score/cpu/riscv/riscv-context-volatile-clobber.S46
-rw-r--r--cpukit/score/cpu/riscv/riscv-exception-handler.S50
8 files changed, 538 insertions, 50 deletions
diff --git a/cpukit/score/cpu/riscv/cpu.c b/cpukit/score/cpu/riscv/cpu.c
index 508f0c83b2..687502f705 100644
--- a/cpukit/score/cpu/riscv/cpu.c
+++ b/cpukit/score/cpu/riscv/cpu.c
@@ -59,6 +59,24 @@ RISCV_ASSERT_CONTEXT_OFFSET( s9, S9 );
RISCV_ASSERT_CONTEXT_OFFSET( s10, S10 );
RISCV_ASSERT_CONTEXT_OFFSET( s11, S11 );
+#if __riscv_flen > 0
+
+RISCV_ASSERT_CONTEXT_OFFSET( fcsr, FCSR );
+RISCV_ASSERT_CONTEXT_OFFSET( fs0, FS0 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs1, FS1 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs2, FS2 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs3, FS3 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs4, FS4 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs5, FS5 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs6, FS6 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs7, FS7 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs8, FS8 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs9, FS9 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs10, FS10 );
+RISCV_ASSERT_CONTEXT_OFFSET( fs11, FS11 );
+
+#endif /* __riscv_flen */
+
#define RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( field, off ) \
RTEMS_STATIC_ASSERT( \
offsetof( CPU_Interrupt_frame, field) == RISCV_INTERRUPT_FRAME_ ## off, \
@@ -86,6 +104,32 @@ RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( t6, T6 );
RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( a0, A0 );
RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( a1, A1 );
+#if __riscv_flen > 0
+
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fcsr, FCSR );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft0, FT0 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft1, FT1 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft2, FT2 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft3, FT3 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft4, FT4 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft5, FT5 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft6, FT6 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft7, FT7 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft8, FT8 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft9, FT9 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft10, FT10 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( ft11, FT11 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa0, FA0 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa1, FA1 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa2, FA2 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa3, FA3 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa4, FA4 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa5, FA5 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa6, FA6 );
+RISCV_ASSERT_INTERRUPT_FRAME_OFFSET( fa7, FA7 );
+
+#endif /* __riscv_flen */
+
RTEMS_STATIC_ASSERT(
sizeof( CPU_Interrupt_frame ) % CPU_STACK_ALIGNMENT == 0,
riscv_interrupt_frame_size
diff --git a/cpukit/score/cpu/riscv/include/rtems/asm.h b/cpukit/score/cpu/riscv/include/rtems/asm.h
index 024091375d..259fe3de2c 100644
--- a/cpukit/score/cpu/riscv/include/rtems/asm.h
+++ b/cpukit/score/cpu/riscv/include/rtems/asm.h
@@ -131,6 +131,38 @@
#endif /* __riscv_xlen */
+#if __riscv_flen == 32
+
+#define FLREG flw
+
+#define FSREG fsw
+
+#define FMVYX fmv.s.x
+
+#define FMVXY fmv.x.s
+
+#elif __riscv_flen == 64
+
+#define FLREG fld
+
+#define FSREG fsd
+
+#if __riscv_xlen == 32
+
+#define FMVYX fmv.s.x
+
+#define FMVXY fmv.x.s
+
+#elif __riscv_xlen == 64
+
+#define FMVYX fmv.d.x
+
+#define FMVXY fmv.x.d
+
+#endif /* __riscv_xlen */
+
+#endif /* __riscv_flen */
+
.macro GET_SELF_CPU_CONTROL REG
#ifdef RTEMS_SMP
csrr \REG, mscratch
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
index 124bbae1d4..2220161c9e 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
@@ -64,8 +64,6 @@ extern "C" {
#define CPU_LITTLE_ENDIAN TRUE
#define CPU_MODES_INTERRUPT_MASK 0x0000000000000001
-#define CPU_CONTEXT_FP_SIZE 0
-
#define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_CACHE_LINE_BYTES 64
@@ -100,6 +98,12 @@ extern "C" {
#ifndef ASM
+#if __riscv_flen == 32
+typedef float RISCV_Float;
+#elif __riscv_flen == 64
+typedef double RISCV_Float;
+#endif
+
typedef struct {
#ifdef RTEMS_SMP
volatile uint32_t is_executing;
@@ -122,18 +126,26 @@ typedef struct {
uintptr_t s9;
uintptr_t s10;
uintptr_t s11;
+#if __riscv_flen > 0
+ uint32_t fcsr;
+ RISCV_Float fs0;
+ RISCV_Float fs1;
+ RISCV_Float fs2;
+ RISCV_Float fs3;
+ RISCV_Float fs4;
+ RISCV_Float fs5;
+ RISCV_Float fs6;
+ RISCV_Float fs7;
+ RISCV_Float fs8;
+ RISCV_Float fs9;
+ RISCV_Float fs10;
+ RISCV_Float fs11;
+#endif
} Context_Control;
#define _CPU_Context_Get_SP( _context ) \
(_context)->sp
-typedef struct {
- /** TODO FPU registers are listed here */
- double some_float_register;
-} Context_Control_fp;
-
-Context_Control_fp _CPU_Null_fp_context;
-
#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
@@ -204,15 +216,6 @@ void _CPU_Context_Initialize(
#define _CPU_Context_Restart_self( _the_context ) \
_CPU_Context_restore( (_the_context) )
-
-#define _CPU_Context_Fp_start( _base, _offset ) \
- ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
-
-#define _CPU_Context_Initialize_fp( _destination ) \
- { \
- *(*(_destination)) = _CPU_Null_fp_context; \
- }
-
extern void _CPU_Fatal_halt(uint32_t source, uint32_t error) RTEMS_NO_RETURN;
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
@@ -326,28 +329,6 @@ void _CPU_Context_restore(
Context_Control *new_context
) RTEMS_NO_RETURN;
-/*
- * _CPU_Context_save_fp
- *
- * This routine saves the floating point context passed to it.
- *
- */
-
-void _CPU_Context_save_fp(
- void **fp_context_ptr
-);
-
-/*
- * _CPU_Context_restore_fp
- *
- * This routine restores the floating point context passed to it.
- *
- */
-
-void _CPU_Context_restore_fp(
- void **fp_context_ptr
-);
-
/* The following routine swaps the endian format of an unsigned int.
* It must be static because it is referenced indirectly.
*
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
index c56e1acab2..2bff71567c 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
@@ -78,11 +78,46 @@
#define RISCV_INTERRUPT_FRAME_T4 60
#define RISCV_INTERRUPT_FRAME_T5 64
#define RISCV_INTERRUPT_FRAME_T6 68
+
+#if __riscv_flen == 0
+
#define RISCV_INTERRUPT_FRAME_A0 72
#define RISCV_INTERRUPT_FRAME_A1 76
#define CPU_INTERRUPT_FRAME_SIZE 80
+#elif __riscv_flen == 32
+
+#define RISCV_CONTEXT_FCSR 68
+
+#define RISCV_CONTEXT_F( x ) (72 + 4 * (x))
+
+#define RISCV_INTERRUPT_FRAME_FCSR 72
+
+#define RISCV_INTERRUPT_FRAME_F( x ) (76 + 4 * (x))
+
+#define RISCV_INTERRUPT_FRAME_A0 156
+#define RISCV_INTERRUPT_FRAME_A1 160
+
+#define CPU_INTERRUPT_FRAME_SIZE 176
+
+#elif __riscv_flen == 64
+
+#define RISCV_CONTEXT_FCSR 68
+
+#define RISCV_CONTEXT_F( x ) (72 + 8 * (x))
+
+#define RISCV_INTERRUPT_FRAME_FCSR 72
+
+#define RISCV_INTERRUPT_FRAME_F( x ) (80 + 8 * (x))
+
+#define RISCV_INTERRUPT_FRAME_A0 240
+#define RISCV_INTERRUPT_FRAME_A1 244
+
+#define CPU_INTERRUPT_FRAME_SIZE 256
+
+#endif /* __riscv_flen */
+
#elif __riscv_xlen == 64
#define RISCV_CONTEXT_RA 8
@@ -119,13 +154,86 @@
#define RISCV_INTERRUPT_FRAME_T4 120
#define RISCV_INTERRUPT_FRAME_T5 128
#define RISCV_INTERRUPT_FRAME_T6 136
+
+#if __riscv_flen == 0
+
#define RISCV_INTERRUPT_FRAME_A0 144
#define RISCV_INTERRUPT_FRAME_A1 152
#define CPU_INTERRUPT_FRAME_SIZE 160
+#elif __riscv_flen == 32
+
+#define RISCV_CONTEXT_FCSR 128
+
+#define RISCV_CONTEXT_F( x ) (132 + 4 * (x))
+
+#define RISCV_INTERRUPT_FRAME_FCSR 144
+
+#define RISCV_INTERRUPT_FRAME_F( x ) (148 + 4 * (x))
+
+#define RISCV_INTERRUPT_FRAME_A0 232
+#define RISCV_INTERRUPT_FRAME_A1 240
+
+#define CPU_INTERRUPT_FRAME_SIZE 256
+
+#elif __riscv_flen == 64
+
+#define RISCV_CONTEXT_FCSR 128
+
+#define RISCV_CONTEXT_F( x ) (136 + 8 * (x))
+
+#define RISCV_INTERRUPT_FRAME_FCSR 144
+
+#define RISCV_INTERRUPT_FRAME_F( x ) (152 + 8 * (x))
+
+#define RISCV_INTERRUPT_FRAME_A0 312
+#define RISCV_INTERRUPT_FRAME_A1 320
+
+#define CPU_INTERRUPT_FRAME_SIZE 336
+
+#endif /* __riscv_flen */
+
#endif /* __riscv_xlen */
+#if __riscv_flen > 0
+
+#define RISCV_CONTEXT_FS0 RISCV_CONTEXT_F( 0 )
+#define RISCV_CONTEXT_FS1 RISCV_CONTEXT_F( 1 )
+#define RISCV_CONTEXT_FS2 RISCV_CONTEXT_F( 2 )
+#define RISCV_CONTEXT_FS3 RISCV_CONTEXT_F( 3 )
+#define RISCV_CONTEXT_FS4 RISCV_CONTEXT_F( 4 )
+#define RISCV_CONTEXT_FS5 RISCV_CONTEXT_F( 5 )
+#define RISCV_CONTEXT_FS6 RISCV_CONTEXT_F( 6 )
+#define RISCV_CONTEXT_FS7 RISCV_CONTEXT_F( 7 )
+#define RISCV_CONTEXT_FS8 RISCV_CONTEXT_F( 8 )
+#define RISCV_CONTEXT_FS9 RISCV_CONTEXT_F( 9 )
+#define RISCV_CONTEXT_FS10 RISCV_CONTEXT_F( 10 )
+#define RISCV_CONTEXT_FS11 RISCV_CONTEXT_F( 11 )
+
+#define RISCV_INTERRUPT_FRAME_FT0 RISCV_INTERRUPT_FRAME_F( 0 )
+#define RISCV_INTERRUPT_FRAME_FT1 RISCV_INTERRUPT_FRAME_F( 1 )
+#define RISCV_INTERRUPT_FRAME_FT2 RISCV_INTERRUPT_FRAME_F( 2 )
+#define RISCV_INTERRUPT_FRAME_FT3 RISCV_INTERRUPT_FRAME_F( 3 )
+#define RISCV_INTERRUPT_FRAME_FT4 RISCV_INTERRUPT_FRAME_F( 4 )
+#define RISCV_INTERRUPT_FRAME_FT5 RISCV_INTERRUPT_FRAME_F( 5 )
+#define RISCV_INTERRUPT_FRAME_FT6 RISCV_INTERRUPT_FRAME_F( 6 )
+#define RISCV_INTERRUPT_FRAME_FT7 RISCV_INTERRUPT_FRAME_F( 7 )
+#define RISCV_INTERRUPT_FRAME_FT8 RISCV_INTERRUPT_FRAME_F( 8 )
+#define RISCV_INTERRUPT_FRAME_FT9 RISCV_INTERRUPT_FRAME_F( 9 )
+#define RISCV_INTERRUPT_FRAME_FT10 RISCV_INTERRUPT_FRAME_F( 10 )
+#define RISCV_INTERRUPT_FRAME_FT11 RISCV_INTERRUPT_FRAME_F( 11 )
+#define RISCV_INTERRUPT_FRAME_FA0 RISCV_INTERRUPT_FRAME_F( 12 )
+#define RISCV_INTERRUPT_FRAME_FA1 RISCV_INTERRUPT_FRAME_F( 13 )
+#define RISCV_INTERRUPT_FRAME_FA2 RISCV_INTERRUPT_FRAME_F( 14 )
+#define RISCV_INTERRUPT_FRAME_FA3 RISCV_INTERRUPT_FRAME_F( 15 )
+#define RISCV_INTERRUPT_FRAME_FA4 RISCV_INTERRUPT_FRAME_F( 16 )
+#define RISCV_INTERRUPT_FRAME_FA5 RISCV_INTERRUPT_FRAME_F( 17 )
+#define RISCV_INTERRUPT_FRAME_FA6 RISCV_INTERRUPT_FRAME_F( 18 )
+#define RISCV_INTERRUPT_FRAME_FA7 RISCV_INTERRUPT_FRAME_F( 19 )
+
+#endif /* __riscv_flen */
+
#ifndef ASM
#ifdef __cplusplus
@@ -151,6 +259,29 @@ typedef struct {
uintptr_t t4;
uintptr_t t5;
uintptr_t t6;
+#if __riscv_flen > 0
+ uint32_t fcsr;
+ RISCV_Float ft0;
+ RISCV_Float ft1;
+ RISCV_Float ft2;
+ RISCV_Float ft3;
+ RISCV_Float ft4;
+ RISCV_Float ft5;
+ RISCV_Float ft6;
+ RISCV_Float ft7;
+ RISCV_Float ft8;
+ RISCV_Float ft9;
+ RISCV_Float ft10;
+ RISCV_Float ft11;
+ RISCV_Float fa0;
+ RISCV_Float fa1;
+ RISCV_Float fa2;
+ RISCV_Float fa3;
+ RISCV_Float fa4;
+ RISCV_Float fa5;
+ RISCV_Float fa6;
+ RISCV_Float fa7;
+#endif
uintptr_t a0;
uintptr_t a1;
} RTEMS_ALIGNED( CPU_STACK_ALIGNMENT ) CPU_Interrupt_frame;
diff --git a/cpukit/score/cpu/riscv/riscv-context-switch.S b/cpukit/score/cpu/riscv/riscv-context-switch.S
index 3626155409..2be34342d9 100644
--- a/cpukit/score/cpu/riscv/riscv-context-switch.S
+++ b/cpukit/score/cpu/riscv/riscv-context-switch.S
@@ -38,13 +38,15 @@
PUBLIC(_CPU_Context_switch)
PUBLIC(_CPU_Context_restore)
-PUBLIC(_CPU_Context_restore_fp)
-PUBLIC(_CPU_Context_save_fp)
SYM(_CPU_Context_switch):
GET_SELF_CPU_CONTROL a2
lw a3, PER_CPU_ISR_DISPATCH_DISABLE(a2)
+#if __riscv_flen > 0
+ frcsr a4
+#endif
+
SREG ra, RISCV_CONTEXT_RA(a0)
SREG sp, RISCV_CONTEXT_SP(a0)
SREG s0, RISCV_CONTEXT_S0(a0)
@@ -60,6 +62,22 @@ SYM(_CPU_Context_switch):
SREG s10, RISCV_CONTEXT_S10(a0)
SREG s11, RISCV_CONTEXT_S11(a0)
+#if __riscv_flen > 0
+ sw a4, RISCV_CONTEXT_FCSR(a0)
+ FSREG fs0, RISCV_CONTEXT_FS0(a0)
+ FSREG fs1, RISCV_CONTEXT_FS1(a0)
+ FSREG fs2, RISCV_CONTEXT_FS2(a0)
+ FSREG fs3, RISCV_CONTEXT_FS3(a0)
+ FSREG fs4, RISCV_CONTEXT_FS4(a0)
+ FSREG fs5, RISCV_CONTEXT_FS5(a0)
+ FSREG fs6, RISCV_CONTEXT_FS6(a0)
+ FSREG fs7, RISCV_CONTEXT_FS7(a0)
+ FSREG fs8, RISCV_CONTEXT_FS8(a0)
+ FSREG fs9, RISCV_CONTEXT_FS9(a0)
+ FSREG fs10, RISCV_CONTEXT_FS10(a0)
+ FSREG fs11, RISCV_CONTEXT_FS11(a0)
+#endif
+
sw a3, RISCV_CONTEXT_ISR_DISPATCH_DISABLE(a0)
.Lrestore:
@@ -81,6 +99,23 @@ SYM(_CPU_Context_switch):
LREG s10, RISCV_CONTEXT_S10(a1)
LREG s11, RISCV_CONTEXT_S11(a1)
+#if __riscv_flen > 0
+ lw a4, RISCV_CONTEXT_FCSR(a1)
+ FLREG fs0, RISCV_CONTEXT_FS0(a1)
+ FLREG fs1, RISCV_CONTEXT_FS1(a1)
+ FLREG fs2, RISCV_CONTEXT_FS2(a1)
+ FLREG fs3, RISCV_CONTEXT_FS3(a1)
+ FLREG fs4, RISCV_CONTEXT_FS4(a1)
+ FLREG fs5, RISCV_CONTEXT_FS5(a1)
+ FLREG fs6, RISCV_CONTEXT_FS6(a1)
+ FLREG fs7, RISCV_CONTEXT_FS7(a1)
+ FLREG fs8, RISCV_CONTEXT_FS8(a1)
+ FLREG fs9, RISCV_CONTEXT_FS9(a1)
+ FLREG fs10, RISCV_CONTEXT_FS10(a1)
+ FLREG fs11, RISCV_CONTEXT_FS11(a1)
+ fscsr a4
+#endif
+
sw a3, PER_CPU_ISR_DISPATCH_DISABLE(a2)
ret
@@ -89,10 +124,3 @@ SYM(_CPU_Context_restore):
mv a1, a0
GET_SELF_CPU_CONTROL a2
j .Lrestore
-
- /* TODO no FP support for riscv32 yet */
- SYM(_CPU_Context_restore_fp):
- nop
-
- SYM(_CPU_Context_save_fp):
- nop
diff --git a/cpukit/score/cpu/riscv/riscv-context-validate.S b/cpukit/score/cpu/riscv/riscv-context-validate.S
index 1c9d3d856c..bd2a7f0317 100644
--- a/cpukit/score/cpu/riscv/riscv-context-validate.S
+++ b/cpukit/score/cpu/riscv/riscv-context-validate.S
@@ -61,9 +61,18 @@
#define T4_OFFSET OFFSET(25)
#define T5_OFFSET OFFSET(26)
#define T6_OFFSET OFFSET(27)
+#define TMP_OFFSET OFFSET(28)
+
+#if __riscv_flen == 32
+#define FOFFSET(i) (OFFSET(29) + (i) * 4)
+#elif __riscv_flen == 64
+#define FOFFSET(i) (OFFSET(29) + (i) * 8)
+#else
+#define FOFFSET(i) OFFSET(29)
+#endif /* __riscv_flen */
#define FRAME_SIZE \
- ((OFFSET(28) + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
+ ((FOFFSET(32) + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
.section .text, "ax", @progbits
.align 2
@@ -73,6 +82,7 @@ SYM(_CPU_Context_validate):
addi sp, sp, -FRAME_SIZE
/* Save */
+
SREG ra, RA_OFFSET(sp)
SREG t0, T0_OFFSET(sp)
SREG t1, T1_OFFSET(sp)
@@ -102,7 +112,43 @@ SYM(_CPU_Context_validate):
SREG t5, T5_OFFSET(sp)
SREG t6, T6_OFFSET(sp)
+#if __riscv_flen > 0
+ FSREG f0, FOFFSET(0)(sp)
+ FSREG f1, FOFFSET(1)(sp)
+ FSREG f2, FOFFSET(2)(sp)
+ FSREG f3, FOFFSET(3)(sp)
+ FSREG f4, FOFFSET(4)(sp)
+ FSREG f5, FOFFSET(5)(sp)
+ FSREG f6, FOFFSET(6)(sp)
+ FSREG f7, FOFFSET(7)(sp)
+ FSREG f8, FOFFSET(8)(sp)
+ FSREG f9, FOFFSET(9)(sp)
+ FSREG f10, FOFFSET(10)(sp)
+ FSREG f11, FOFFSET(11)(sp)
+ FSREG f12, FOFFSET(12)(sp)
+ FSREG f13, FOFFSET(13)(sp)
+ FSREG f14, FOFFSET(14)(sp)
+ FSREG f15, FOFFSET(15)(sp)
+ FSREG f16, FOFFSET(16)(sp)
+ FSREG f17, FOFFSET(17)(sp)
+ FSREG f18, FOFFSET(18)(sp)
+ FSREG f19, FOFFSET(19)(sp)
+ FSREG f20, FOFFSET(20)(sp)
+ FSREG f21, FOFFSET(21)(sp)
+ FSREG f22, FOFFSET(22)(sp)
+ FSREG f23, FOFFSET(23)(sp)
+ FSREG f24, FOFFSET(24)(sp)
+ FSREG f25, FOFFSET(25)(sp)
+ FSREG f26, FOFFSET(26)(sp)
+ FSREG f27, FOFFSET(27)(sp)
+ FSREG f28, FOFFSET(28)(sp)
+ FSREG f29, FOFFSET(29)(sp)
+ FSREG f30, FOFFSET(30)(sp)
+ FSREG f31, FOFFSET(31)(sp)
+#endif /* __riscv_flen */
+
/* Fill */
+
addi ra, a0, 1
/* sp must remain as is */
/* gp must remain as is */
@@ -136,7 +182,51 @@ SYM(_CPU_Context_validate):
xor t5, gp, a0
xor t6, tp, a0
+#if __riscv_flen > 0
+ andi t0, a0, 0x1f
+ fsflags t0
+
+ .macro fill_f reg, inc
+ addi t0, a0, 24 + \inc
+ FMVYX \reg, t0
+ .endm
+
+ fill_f f0, 0
+ fill_f f1, 1
+ fill_f f2, 2
+ fill_f f3, 3
+ fill_f f4, 4
+ fill_f f5, 5
+ fill_f f6, 6
+ fill_f f7, 7
+ fill_f f8, 8
+ fill_f f9, 9
+ fill_f f10, 10
+ fill_f f11, 11
+ fill_f f12, 12
+ fill_f f13, 13
+ fill_f f14, 14
+ fill_f f15, 15
+ fill_f f16, 16
+ fill_f f17, 17
+ fill_f f18, 18
+ fill_f f19, 19
+ fill_f f20, 20
+ fill_f f21, 21
+ fill_f f22, 22
+ fill_f f23, 23
+ fill_f f24, 24
+ fill_f f25, 25
+ fill_f f26, 26
+ fill_f f27, 27
+ fill_f f28, 28
+ fill_f f29, 29
+ fill_f f30, 30
+ fill_f f31, 31
+#endif /* __riscv_flen */
+
/* Check */
+
.Lcheck:
.macro check_register reg, inc
addi t0, a0, \inc
@@ -176,10 +266,61 @@ SYM(_CPU_Context_validate):
xor t0, tp, a0
bne t6, t0, .Lrestore
+#if __riscv_flen > 0
+ SREG t1, TMP_OFFSET(sp)
+ frflags t0
+ andi t1, a0, 0x1f
+ xor t0, t1, t0
+ LREG t1, TMP_OFFSET(sp)
+ bnez t0, .Lrestore
+
+
+ .macro check_f reg, inc
+ FMVXY t0, \reg
+ addi t0, t0, -24 - \inc
+ bne t0, a0, .Lrestore
+ .endm
+
+ check_f f0, 0
+ check_f f1, 1
+ check_f f2, 2
+ check_f f3, 3
+ check_f f4, 4
+ check_f f5, 5
+ check_f f6, 6
+ check_f f7, 7
+ check_f f8, 8
+ check_f f9, 9
+ check_f f10, 10
+ check_f f11, 11
+ check_f f12, 12
+ check_f f13, 13
+ check_f f14, 14
+ check_f f15, 15
+ check_f f16, 16
+ check_f f17, 17
+ check_f f18, 18
+ check_f f19, 19
+ check_f f20, 20
+ check_f f21, 21
+ check_f f22, 22
+ check_f f23, 23
+ check_f f24, 24
+ check_f f25, 25
+ check_f f26, 26
+ check_f f27, 27
+ check_f f28, 28
+ check_f f29, 29
+ check_f f30, 30
+ check_f f31, 31
+#endif /* __riscv_flen */
+
j .Lcheck
/* Restore */
+
.Lrestore:
+
LREG ra, RA_OFFSET(sp)
LREG t0, T0_OFFSET(sp)
LREG t1, T1_OFFSET(sp)
@@ -209,5 +350,40 @@ SYM(_CPU_Context_validate):
LREG t5, T5_OFFSET(sp)
LREG t6, T6_OFFSET(sp)
+#if __riscv_flen > 0
+ FLREG f0, FOFFSET(0)(sp)
+ FLREG f1, FOFFSET(1)(sp)
+ FLREG f2, FOFFSET(2)(sp)
+ FLREG f3, FOFFSET(3)(sp)
+ FLREG f4, FOFFSET(4)(sp)
+ FLREG f5, FOFFSET(5)(sp)
+ FLREG f6, FOFFSET(6)(sp)
+ FLREG f7, FOFFSET(7)(sp)
+ FLREG f8, FOFFSET(8)(sp)
+ FLREG f9, FOFFSET(9)(sp)
+ FLREG f10, FOFFSET(10)(sp)
+ FLREG f11, FOFFSET(11)(sp)
+ FLREG f12, FOFFSET(12)(sp)
+ FLREG f13, FOFFSET(13)(sp)
+ FLREG f14, FOFFSET(14)(sp)
+ FLREG f15, FOFFSET(15)(sp)
+ FLREG f16, FOFFSET(16)(sp)
+ FLREG f17, FOFFSET(17)(sp)
+ FLREG f18, FOFFSET(18)(sp)
+ FLREG f19, FOFFSET(19)(sp)
+ FLREG f20, FOFFSET(20)(sp)
+ FLREG f21, FOFFSET(21)(sp)
+ FLREG f22, FOFFSET(22)(sp)
+ FLREG f23, FOFFSET(23)(sp)
+ FLREG f24, FOFFSET(24)(sp)
+ FLREG f25, FOFFSET(25)(sp)
+ FLREG f26, FOFFSET(26)(sp)
+ FLREG f27, FOFFSET(27)(sp)
+ FLREG f28, FOFFSET(28)(sp)
+ FLREG f29, FOFFSET(29)(sp)
+ FLREG f30, FOFFSET(30)(sp)
+ FLREG f31, FOFFSET(31)(sp)
+#endif /* __riscv_flen */
+
addi sp, sp, FRAME_SIZE
ret
diff --git a/cpukit/score/cpu/riscv/riscv-context-volatile-clobber.S b/cpukit/score/cpu/riscv/riscv-context-volatile-clobber.S
index 9d3d39b32d..628bd1a467 100644
--- a/cpukit/score/cpu/riscv/riscv-context-volatile-clobber.S
+++ b/cpukit/score/cpu/riscv/riscv-context-volatile-clobber.S
@@ -36,6 +36,52 @@
PUBLIC(_CPU_Context_volatile_clobber)
SYM(_CPU_Context_volatile_clobber):
+#if __riscv_flen > 0
+ andi t0, a0, 0x1f
+ fsflags t0
+
+ addi t0, a0, 15
+ FMVYX ft0, t0
+ addi t0, a0, 16
+ FMVYX ft1, t0
+ addi t0, a0, 17
+ FMVYX ft2, t0
+ addi t0, a0, 18
+ FMVYX ft3, t0
+ addi t0, a0, 19
+ FMVYX ft4, t0
+ addi t0, a0, 20
+ FMVYX ft5, t0
+ addi t0, a0, 21
+ FMVYX ft6, t0
+ addi t0, a0, 22
+ FMVYX ft7, t0
+ addi t0, a0, 23
+ FMVYX ft8, t0
+ addi t0, a0, 24
+ FMVYX ft9, t0
+ addi t0, a0, 25
+ FMVYX ft10, t0
+ addi t0, a0, 26
+ FMVYX ft11, t0
+ addi t0, a0, 27
+ FMVYX fa0, t0
+ addi t0, a0, 28
+ FMVYX fa1, t0
+ addi t0, a0, 29
+ FMVYX fa2, t0
+ addi t0, a0, 30
+ FMVYX fa3, t0
+ addi t0, a0, 31
+ FMVYX fa4, t0
+ addi t0, a0, 32
+ FMVYX fa5, t0
+ addi t0, a0, 33
+ FMVYX fa6, t0
+ addi t0, a0, 34
+ FMVYX fa7, t0
+#endif /* __riscv_flen */
+
addi a1, a0, 1
addi a2, a0, 2
addi a3, a0, 3
diff --git a/cpukit/score/cpu/riscv/riscv-exception-handler.S b/cpukit/score/cpu/riscv/riscv-exception-handler.S
index 844d417738..b15bab49c7 100644
--- a/cpukit/score/cpu/riscv/riscv-exception-handler.S
+++ b/cpukit/score/cpu/riscv/riscv-exception-handler.S
@@ -62,6 +62,9 @@ SYM(ISR_Handler):
csrr a2, mepc
GET_SELF_CPU_CONTROL s0
SREG s1, RISCV_INTERRUPT_FRAME_S1(sp)
+#if __riscv_flen > 0
+ frcsr s1
+#endif
SREG ra, RISCV_INTERRUPT_FRAME_RA(sp)
SREG a3, RISCV_INTERRUPT_FRAME_A3(sp)
SREG a4, RISCV_INTERRUPT_FRAME_A4(sp)
@@ -77,6 +80,29 @@ SYM(ISR_Handler):
SREG t6, RISCV_INTERRUPT_FRAME_T6(sp)
SREG a1, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
SREG a2, RISCV_INTERRUPT_FRAME_MEPC(sp)
+#if __riscv_flen > 0
+ sw s1, RISCV_INTERRUPT_FRAME_FCSR(sp)
+ FSREG ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
+ FSREG ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
+ FSREG ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
+ FSREG ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
+ FSREG ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
+ FSREG ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
+ FSREG ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
+ FSREG ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
+ FSREG ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
+ FSREG ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
+ FSREG ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
+ FSREG ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
+ FSREG fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
+ FSREG fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
+ FSREG fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
+ FSREG fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
+ FSREG fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
+ FSREG fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
+ FSREG fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
+ FSREG fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
+#endif
/* FIXME Only handle interrupts for now (MSB = 1) */
andi a0, a0, 0xf
@@ -191,6 +217,30 @@ SYM(ISR_Handler):
LREG t6, RISCV_INTERRUPT_FRAME_T6(sp)
csrw mstatus, a0
csrw mepc, a1
+#if __riscv_flen > 0
+ lw a0, RISCV_INTERRUPT_FRAME_FCSR(sp)
+ FLREG ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
+ FLREG ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
+ FLREG ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
+ FLREG ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
+ FLREG ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
+ FLREG ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
+ FLREG ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
+ FLREG ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
+ FLREG ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
+ FLREG ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
+ FLREG ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
+ FLREG ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
+ FLREG fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
+ FLREG fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
+ FLREG fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
+ FLREG fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
+ FLREG fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
+ FLREG fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
+ FLREG fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
+ FLREG fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
+ fscsr a0
+#endif
LREG a0, RISCV_INTERRUPT_FRAME_A0(sp)
LREG a1, RISCV_INTERRUPT_FRAME_A1(sp)