[rtems commit] riscv: Add floating-point support

Sebastian Huber sebh at rtems.org
Fri Jun 29 10:01:20 UTC 2018


Module:    rtems
Branch:    master
Commit:    52352387cc0b502fd42164604ae9217700b83e31
Changeset: http://git.rtems.org/rtems/commit/?id=52352387cc0b502fd42164604ae9217700b83e31

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Jun 28 09:32:26 2018 +0200

riscv: Add floating-point support

Update #3433.

---

 cpukit/score/cpu/riscv/cpu.c                       |  44 +++++
 cpukit/score/cpu/riscv/include/rtems/asm.h         |  32 ++++
 cpukit/score/cpu/riscv/include/rtems/score/cpu.h   |  61 +++----
 .../score/cpu/riscv/include/rtems/score/cpuimpl.h  | 131 +++++++++++++++
 cpukit/score/cpu/riscv/riscv-context-switch.S      |  46 ++++--
 cpukit/score/cpu/riscv/riscv-context-validate.S    | 178 ++++++++++++++++++++-
 .../cpu/riscv/riscv-context-volatile-clobber.S     |  46 ++++++
 cpukit/score/cpu/riscv/riscv-exception-handler.S   |  50 ++++++
 8 files changed, 538 insertions(+), 50 deletions(-)

diff --git a/cpukit/score/cpu/riscv/cpu.c b/cpukit/score/cpu/riscv/cpu.c
index 508f0c8..687502f 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 0240913..259fe3d 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 124bbae..2220161 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 c56e1ac..2bff715 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 3626155..2be3434 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 1c9d3d8..bd2a7f0 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 9d3d39b..628bd1a 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 844d417..b15bab4 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)
 



More information about the vc mailing list