From 52352387cc0b502fd42164604ae9217700b83e31 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 28 Jun 2018 09:32:26 +0200 Subject: 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(-) (limited to 'cpukit') 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) -- cgit v1.2.3