summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/src
diff options
context:
space:
mode:
Diffstat (limited to 'ports/risc-v64/gnu/src')
-rw-r--r--ports/risc-v64/gnu/src/tx_initialize_low_level.S16
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_context_restore.S142
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_context_save.S90
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_interrupt_control.S32
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_schedule.S47
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_stack_build.S19
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_system_return.S12
-rw-r--r--ports/risc-v64/gnu/src/tx_timer_interrupt.S4
8 files changed, 232 insertions, 130 deletions
diff --git a/ports/risc-v64/gnu/src/tx_initialize_low_level.S b/ports/risc-v64/gnu/src/tx_initialize_low_level.S
index 6a35272f..952be957 100644
--- a/ports/risc-v64/gnu/src/tx_initialize_low_level.S
+++ b/ports/risc-v64/gnu/src/tx_initialize_low_level.S
@@ -79,10 +79,26 @@ _tx_initialize_low_level:
/* Initialize floating point control/status register if floating point is enabled. */
#ifdef __riscv_flen
+#ifdef TX_RISCV_SMODE
+ li t0, 0x2000 // Set sstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap
+ csrrs zero, sstatus, t0
+#else
+ li t0, 0x2000 // Set mstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap
+ csrrs zero, mstatus, t0
+#endif
li t0, 0
csrw fcsr, t0 // Clear FP control/status register
#endif
+#ifdef __riscv_vector
+ li t0, 0x200 // Set VS=Initial before a vector restore
+#ifdef TX_RISCV_SMODE
+ csrrs zero, sstatus, t0
+#else
+ csrrs zero, mstatus, t0
+#endif
+#endif
+
ret
/* Timer Interrupt Handler Note:
diff --git a/ports/risc-v64/gnu/src/tx_thread_context_restore.S b/ports/risc-v64/gnu/src/tx_thread_context_restore.S
index cebc8a06..f5a68d2e 100644
--- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S
+++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S
@@ -58,6 +58,8 @@
/**************************************************************************/
/* VOID _tx_thread_context_restore(VOID)
{ */
+#include "tx_port.h"
+ .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE
.global _tx_thread_context_restore
_tx_thread_context_restore:
@@ -88,8 +90,18 @@ _tx_thread_context_restore:
/* Just recover the saved registers and return to the point of
interrupt. */
+ /* Recover the FP state only when the saved mstatus.FS was not Off. The
+ save side skips the FP stores for a thread that has not touched the
+ unit, so those slots hold nothing worth loading back. */
+#if (__riscv_flen == 32) || (__riscv_flen == 64)
+ ld t1, 29*8(sp) // Pickup saved mstatus
+ srli t1, t1, 13
+ andi t1, t1, 0x3
+ beqz t1, _tx_thread_skip_fp_restore // Skip if FS was Off
+#endif
+
/* Recover floating point registers. */
-#if defined(__riscv_float_abi_single)
+#if (__riscv_flen == 32)
flw f0, 31*8(sp) // Recover ft0
flw f1, 32*8(sp) // Recover ft1
flw f2, 33*8(sp) // Recover ft2
@@ -112,7 +124,7 @@ _tx_thread_context_restore:
flw f31,62*8(sp) // Recover ft11
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0 // Restore fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fld f0, 31*8(sp) // Recover ft0
fld f1, 32*8(sp) // Recover ft1
fld f2, 33*8(sp) // Recover ft2
@@ -121,6 +133,20 @@ _tx_thread_context_restore:
fld f5, 36*8(sp) // Recover ft5
fld f6, 37*8(sp) // Recover ft6
fld f7, 38*8(sp) // Recover ft7
+#if defined(__riscv_float_abi_single)
+ fld f8, 39*8(sp) // Recover fs0
+ fld f9, 40*8(sp) // Recover fs1
+ fld f18, 49*8(sp) // Recover fs2
+ fld f19, 50*8(sp) // Recover fs3
+ fld f20, 51*8(sp) // Recover fs4
+ fld f21, 52*8(sp) // Recover fs5
+ fld f22, 53*8(sp) // Recover fs6
+ fld f23, 54*8(sp) // Recover fs7
+ fld f24, 55*8(sp) // Recover fs8
+ fld f25, 56*8(sp) // Recover fs9
+ fld f26, 57*8(sp) // Recover fs10
+ fld f27, 58*8(sp) // Recover fs11
+#endif
fld f10,41*8(sp) // Recover fa0
fld f11,42*8(sp) // Recover fa1
fld f12,43*8(sp) // Recover fa2
@@ -136,6 +162,7 @@ _tx_thread_context_restore:
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0
#endif
+_tx_thread_skip_fp_restore:
#if defined(__riscv_vector)
/* Recover vector registers v0-v31 */
@@ -189,6 +216,10 @@ _tx_thread_context_restore:
li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state
or t1, t1, t0
#endif
+#if defined(__riscv_vector)
+ li t0, 0x0600
+ or t1, t1, t0
+#endif
csrw sstatus, t1 // Update sstatus safely
#else
csrw mepc, t0 // Setup mepc
@@ -203,11 +234,11 @@ _tx_thread_context_restore:
andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- li t0, 0x2000 // Set FS bits (bits 14:13 to 01) for FP state
+ li t0, 0x6000
or t1, t1, t0
#endif
#if defined(__riscv_vector)
- li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
+ li t0, 0x0600
or t1, t1, t0
#endif
csrw mstatus, t1 // Update mstatus safely
@@ -231,18 +262,10 @@ _tx_thread_context_restore:
ld t5, 14*8(sp) // Recover t5
ld t6, 13*8(sp) // Recover t6
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, 65*8 // Recover stack frame - with floating point enabled
-#else
- addi sp, sp, 32*8 // Recover stack frame - without floating point enabled
-#endif
+ addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad)
#if defined(__riscv_vector)
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t0, sp, -65*8
-#else
- addi t0, sp, -32*8
-#endif
+ addi t0, sp, -TX_TRAP_FRAME_SIZE
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr
@@ -270,7 +293,7 @@ _tx_thread_not_nested_restore:
la t0, _tx_thread_preempt_disable // Pickup preempt disable flag address
lw t2, 0(t0) // Pickup preempt disable flag (UINT)
- bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread
+ bnez t2, _tx_thread_no_preempt_restore // If set (nonzero), restore interrupted thread
la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address
ld t2, 0(t0) // Pickup thread execute pointer
@@ -285,8 +308,18 @@ _tx_thread_no_preempt_restore:
ld sp, 8(t1) // Switch back to thread's stack
+ /* Recover the FP state only when the saved mstatus.FS was not Off. The
+ save side skips the FP stores for a thread that has not touched the
+ unit, so those slots hold nothing worth loading back. */
+#if (__riscv_flen == 32) || (__riscv_flen == 64)
+ ld t3, 29*8(sp) // Pickup saved mstatus
+ srli t3, t3, 13
+ andi t3, t3, 0x3
+ beqz t3, _tx_thread_no_preempt_skip_fp_restore // Skip if FS was Off
+#endif
+
/* Recover floating point registers. */
-#if defined(__riscv_float_abi_single)
+#if (__riscv_flen == 32)
flw f0, 31*8(sp) // Recover ft0
flw f1, 32*8(sp) // Recover ft1
flw f2, 33*8(sp) // Recover ft2
@@ -309,7 +342,7 @@ _tx_thread_no_preempt_restore:
flw f31,62*8(sp) // Recover ft11
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0 // Restore fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fld f0, 31*8(sp) // Recover ft0
fld f1, 32*8(sp) // Recover ft1
fld f2, 33*8(sp) // Recover ft2
@@ -318,6 +351,20 @@ _tx_thread_no_preempt_restore:
fld f5, 36*8(sp) // Recover ft5
fld f6, 37*8(sp) // Recover ft6
fld f7, 38*8(sp) // Recover ft7
+#if defined(__riscv_float_abi_single)
+ fld f8, 39*8(sp) // Recover fs0
+ fld f9, 40*8(sp) // Recover fs1
+ fld f18, 49*8(sp) // Recover fs2
+ fld f19, 50*8(sp) // Recover fs3
+ fld f20, 51*8(sp) // Recover fs4
+ fld f21, 52*8(sp) // Recover fs5
+ fld f22, 53*8(sp) // Recover fs6
+ fld f23, 54*8(sp) // Recover fs7
+ fld f24, 55*8(sp) // Recover fs8
+ fld f25, 56*8(sp) // Recover fs9
+ fld f26, 57*8(sp) // Recover fs10
+ fld f27, 58*8(sp) // Recover fs11
+#endif
fld f10,41*8(sp) // Recover fa0
fld f11,42*8(sp) // Recover fa1
fld f12,43*8(sp) // Recover fa2
@@ -333,6 +380,7 @@ _tx_thread_no_preempt_restore:
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0 // Restore fcsr
#endif
+_tx_thread_no_preempt_skip_fp_restore:
#if defined(__riscv_vector)
/* Recover vector registers v0-v31 */
@@ -384,6 +432,10 @@ _tx_thread_no_preempt_restore:
li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state
or t1, t1, t0
#endif
+#if defined(__riscv_vector)
+ li t0, 0x0600 // Set VS bits (bits 10:9 to 11, Dirty) for restored vector state
+ or t1, t1, t0
+#endif
csrw sstatus, t1 // Update sstatus safely
#else
csrw mepc, t0 // Setup mepc
@@ -399,11 +451,11 @@ _tx_thread_no_preempt_restore:
andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- li t0, 0x2000 // Set FS bits for FP state
+ li t0, 0x6000
or t1, t1, t0
#endif
#if defined(__riscv_vector)
- li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
+ li t0, 0x0600
or t1, t1, t0
#endif
csrw mstatus, t1 // Update mstatus safely
@@ -427,18 +479,10 @@ _tx_thread_no_preempt_restore:
ld t5, 14*8(sp) // Recover t5
ld t6, 13*8(sp) // Recover t6
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, 65*8 // Recover stack frame - with floating point enabled
-#else
- addi sp, sp, 32*8 // Recover stack frame - without floating point enabled
-#endif
+ addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame
#if defined(__riscv_vector)
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t0, sp, -65*8
-#else
- addi t0, sp, -32*8
-#endif
+ addi t0, sp, -TX_TRAP_FRAME_SIZE
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr
@@ -464,8 +508,10 @@ _tx_thread_preempt_restore:
ori t3, zero, 1 // Build interrupt stack type
sd t3, 0(t0) // Store stack type
- /* Store floating point preserved registers. */
-#ifdef __riscv_float_abi_single
+ /* Store floating point preserved registers. LP64F saved the complete
+ FLEN=64 state before the C interrupt handler ran. */
+#if !defined(__riscv_float_abi_single) || (__riscv_flen != 64)
+#if (__riscv_flen == 32)
fsw f8, 39*8(t0) // Store fs0
fsw f9, 40*8(t0) // Store fs1
fsw f18, 49*8(t0) // Store fs2
@@ -478,7 +524,7 @@ _tx_thread_preempt_restore:
fsw f25, 56*8(t0) // Store fs9
fsw f26, 57*8(t0) // Store fs10
fsw f27, 58*8(t0) // Store fs11
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fsd f8, 39*8(t0) // Store fs0
fsd f9, 40*8(t0) // Store fs1
fsd f18, 49*8(t0) // Store fs2
@@ -492,36 +538,12 @@ _tx_thread_preempt_restore:
fsd f26, 57*8(t0) // Store fs10
fsd f27, 58*8(t0) // Store fs11
#endif
-
-#if defined(__riscv_vector)
- /* Store vector registers and CSRs */
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t1, t0, 64*8
-#else
- addi t1, t0, 31*8
#endif
- /* Store vector CSRs */
- csrr t2, vstart // Store vstart
- sd t2, 0*8(t1)
- csrr t2, vtype // Store vtype
- sd t2, 1*8(t1)
- csrr t2, vl // Store vl
- sd t2, 2*8(t1)
- csrr t2, vcsr // Store vcsr
- sd t2, 3*8(t1)
- /* Store vector registers v0-v31 */
- addi t2, t1, 4*8
- vsetvli t3, zero, e8, m8, ta, ma
- vse8.v v0, 0(t2) // Store v0 ~ v7
- add t2, t2, t3
- vse8.v v8, 0(t2) // Store v8 ~ v15
- add t2, t2, t3
- vse8.v v16, 0(t2) // Store v16 ~ v23
- add t2, t2, t3
- vse8.v v24, 0(t2) // Store v24 ~ v31
- add t2, t2, t3
-#endif
+ /* No vector save here. _tx_thread_context_save stored v0-v31 and the
+ vector CSRs before the C handler ran. The psABI treats v0-v31, vl and
+ vtype as caller-saved, so the handler may have changed them; a second
+ store here would overwrite the good copy with the handler's state. */
/* Store standard preserved registers. */
diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S
index 7935bfee..1924bd6e 100644
--- a/ports/risc-v64/gnu/src/tx_thread_context_save.S
+++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S
@@ -9,6 +9,7 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
/**************************************************************************/
/**************************************************************************/
@@ -21,6 +22,8 @@
/**************************************************************************/
.section .text
+#include "tx_port.h"
+ .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -30,6 +33,7 @@
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
+/* Wei-Chen Lai, National Cheng Kung University */
/* */
/* DESCRIPTION */
/* */
@@ -67,14 +71,14 @@ _tx_thread_context_save:
sd t1, 18*8(sp)
la t0, _tx_thread_system_state // Pickup address of system state
- ld t1, 0(t0) // Pickup system state
+ lw t1, 0(t0) // Pickup system state
/* Check for a nested interrupt condition. */
/* if (_tx_thread_system_state++)
{ */
beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition
addi t1, t1, 1 // Increment the interrupt counter
- sd t1, 0(t0) // Store the interrupt counter
+ sw t1, 0(t0) // Store the interrupt counter
/* Nested interrupt condition.
Save the rest of the scratch registers on the stack and return to the
@@ -101,8 +105,17 @@ _tx_thread_context_save:
#endif
sd t0, 30*8(sp) // Save it on the stack
+ /* Save mstatus and skip FP state if FS is Off. */
+ csrr t0, mstatus
+ sd t0, 29*8(sp) // Save mstatus
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ srli t1, t0, 13
+ andi t1, t1, 0x3
+ beqz t1, _tx_thread_skip_nested_fpu_save // Skip if FS was Off
+#endif
+
/* Save floating point scratch registers if floating point is enabled. */
-#ifdef __riscv_float_abi_single
+#if (__riscv_flen == 32)
fsw f0, 31*8(sp) // Store ft0
fsw f1, 32*8(sp) // Store ft1
fsw f2, 33*8(sp) // Store ft2
@@ -125,7 +138,7 @@ _tx_thread_context_save:
fsw f31,62*8(sp) // Store ft11
csrr t0, fcsr
sd t0, 63*8(sp) // Store fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fsd f0, 31*8(sp) // Store ft0
fsd f1, 32*8(sp) // Store ft1
fsd f2, 33*8(sp) // Store ft2
@@ -134,6 +147,20 @@ _tx_thread_context_save:
fsd f5, 36*8(sp) // Store ft5
fsd f6, 37*8(sp) // Store ft6
fsd f7, 38*8(sp) // Store ft7
+#if defined(__riscv_float_abi_single)
+ fsd f8, 39*8(sp) // Store fs0
+ fsd f9, 40*8(sp) // Store fs1
+ fsd f18, 49*8(sp) // Store fs2
+ fsd f19, 50*8(sp) // Store fs3
+ fsd f20, 51*8(sp) // Store fs4
+ fsd f21, 52*8(sp) // Store fs5
+ fsd f22, 53*8(sp) // Store fs6
+ fsd f23, 54*8(sp) // Store fs7
+ fsd f24, 55*8(sp) // Store fs8
+ fsd f25, 56*8(sp) // Store fs9
+ fsd f26, 57*8(sp) // Store fs10
+ fsd f27, 58*8(sp) // Store fs11
+#endif
fsd f10,41*8(sp) // Store fa0
fsd f11,42*8(sp) // Store fa1
fsd f12,43*8(sp) // Store fa2
@@ -149,6 +176,7 @@ _tx_thread_context_save:
csrr t0, fcsr
sd t0, 63*8(sp) // Store fcsr
#endif
+_tx_thread_skip_nested_fpu_save:
#if defined(__riscv_vector)
/* Store vector registers and CSRs */
@@ -181,7 +209,11 @@ _tx_thread_context_save:
#endif
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ addi sp, sp, -16 // Reserve space to save the return address
+ sd ra, 0(sp) // Save the return address
call _tx_execution_isr_enter // Call the ISR execution enter function
+ ld ra, 0(sp) // Recover the return address
+ addi sp, sp, 16 // Recover the reserved stack space
#endif
ret // Return to calling ISR
@@ -193,7 +225,7 @@ _tx_thread_not_nested_save:
/* else if (_tx_thread_current_ptr)
{ */
addi t1, t1, 1 // Increment the interrupt counter
- sd t1, 0(t0) // Store the interrupt counter
+ sw t1, 0(t0) // Store the interrupt counter
/* Not nested: Find the user thread that was running and load our SP */
@@ -225,8 +257,17 @@ _tx_thread_not_nested_save:
#endif
sd t1, 30*8(sp) // Save it on the stack
+ /* Save mstatus and skip FP state if FS is Off. */
+ csrr t1, mstatus
+ sd t1, 29*8(sp) // Save mstatus
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ srli t2, t1, 13
+ andi t2, t2, 0x3
+ beqz t2, _tx_thread_skip_fpu_save // Skip if FS was Off
+#endif
+
/* Save floating point scratch registers if floating point is enabled. */
-#ifdef __riscv_float_abi_single
+#if (__riscv_flen == 32)
fsw f0, 31*8(sp) // Store ft0
fsw f1, 32*8(sp) // Store ft1
fsw f2, 33*8(sp) // Store ft2
@@ -249,7 +290,7 @@ _tx_thread_not_nested_save:
fsw f31,62*8(sp) // Store ft11
csrr t0, fcsr
sd t0, 63*8(sp) // Store fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fsd f0, 31*8(sp) // Store ft0
fsd f1, 32*8(sp) // Store ft1
fsd f2, 33*8(sp) // Store ft2
@@ -258,6 +299,20 @@ _tx_thread_not_nested_save:
fsd f5, 36*8(sp) // Store ft5
fsd f6, 37*8(sp) // Store ft6
fsd f7, 38*8(sp) // Store ft7
+#if defined(__riscv_float_abi_single)
+ fsd f8, 39*8(sp) // Store fs0
+ fsd f9, 40*8(sp) // Store fs1
+ fsd f18, 49*8(sp) // Store fs2
+ fsd f19, 50*8(sp) // Store fs3
+ fsd f20, 51*8(sp) // Store fs4
+ fsd f21, 52*8(sp) // Store fs5
+ fsd f22, 53*8(sp) // Store fs6
+ fsd f23, 54*8(sp) // Store fs7
+ fsd f24, 55*8(sp) // Store fs8
+ fsd f25, 56*8(sp) // Store fs9
+ fsd f26, 57*8(sp) // Store fs10
+ fsd f27, 58*8(sp) // Store fs11
+#endif
fsd f10,41*8(sp) // Store fa0
fsd f11,42*8(sp) // Store fa1
fsd f12,43*8(sp) // Store fa2
@@ -273,6 +328,7 @@ _tx_thread_not_nested_save:
csrr t0, fcsr
sd t0, 63*8(sp) // Store fcsr
#endif
+_tx_thread_skip_fpu_save:
#if defined(__riscv_vector)
/* Store vector registers and CSRs */
@@ -316,7 +372,11 @@ _tx_thread_not_nested_save:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/* _tx_execution_isr_enter is called with thread stack pointer */
+ addi sp, sp, -16 // Reserve space to save the return address
+ sd ra, 0(sp) // Save the return address
call _tx_execution_isr_enter // Call the ISR execution enter function
+ ld ra, 0(sp) // Recover the return address
+ addi sp, sp, 16 // Recover the reserved stack space
#endif
la t0, _tx_thread_system_stack_ptr // Pickup system stack pointer address
@@ -331,25 +391,21 @@ _tx_thread_idle_system_save:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ addi sp, sp, -16 // Reserve space to save the return address
+ sd ra, 0(sp) // Save the return address
call _tx_execution_isr_enter // Call the ISR execution enter function
+ ld ra, 0(sp) // Recover the return address
+ addi sp, sp, 16 // Recover the reserved stack space
#endif
/* Interrupt occurred in the scheduling loop. */
/* }
} */
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, 65*8 // Recover stack frame - with floating point enabled
-#else
- addi sp, sp, 32*8 // Recover the reserved stack space
-#endif
+ addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad)
#if defined(__riscv_vector)
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t0, sp, -65*8
-#else
- addi t0, sp, -32*8
-#endif
+ addi t0, sp, -TX_TRAP_FRAME_SIZE
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr
diff --git a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S
index b43d9558..d791e508 100644
--- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S
+++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S
@@ -27,7 +27,7 @@
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control RISC-V64/GNU */
-/* 6.2.1 */
+/* 6.5.1.202602a */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -61,23 +61,25 @@ _tx_thread_interrupt_control:
/* Pickup current interrupt lockout posture. */
#ifdef TX_RISCV_SMODE
- csrr t0, sstatus
- mv t1, t0 // Save original sstatus for return
- li t2, ~0x02 // Build mask to clear SIE (bit 1)
- and t0, t0, t2 // Clear SIE bit
+ li t1, 0x02 // Build SIE bit mask (bit 1)
andi a0, a0, 0x02 // Mask incoming to only SIE bit
- or t0, t0, a0 // Set requested SIE state
- csrw sstatus, t0
- andi a0, t1, 0x02 // Return original SIE bit
+ bnez a0, 1f // If set, enable interrupts
+ csrrc t0, sstatus, t1 // Atomically clear SIE, read old sstatus
+ j 2f
+1:
+ csrrs t0, sstatus, t1 // Atomically set SIE, read old sstatus
+2:
+ andi a0, t0, 0x02 // Return original SIE bit
#else
- csrr t0, mstatus
- mv t1, t0 // Save original mstatus for return
- li t2, ~0x08 // Build mask to clear MIE
- and t0, t0, t2 // Clear MIE bit
+ li t1, 0x08 // Build MIE bit mask (bit 3)
andi a0, a0, 0x08 // Mask incoming to only MIE bit
- or t0, t0, a0 // Set requested MIE state
- csrw mstatus, t0
- andi a0, t1, 0x08 // Return original MIE bit
+ bnez a0, 1f // If set, enable interrupts
+ csrrc t0, mstatus, t1 // Atomically clear MIE, read old mstatus
+ j 2f
+1:
+ csrrs t0, mstatus, t1 // Atomically set MIE, read old mstatus
+2:
+ andi a0, t0, 0x08 // Return original MIE bit
#endif
ret
/* } */
diff --git a/ports/risc-v64/gnu/src/tx_thread_schedule.S b/ports/risc-v64/gnu/src/tx_thread_schedule.S
index 860adf0b..26220726 100644
--- a/ports/risc-v64/gnu/src/tx_thread_schedule.S
+++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S
@@ -58,6 +58,9 @@
/**************************************************************************/
/* VOID _tx_thread_schedule(VOID)
{ */
+#include "tx_port.h"
+ .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE
+ .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE
.global _tx_thread_schedule
_tx_thread_schedule:
@@ -140,9 +143,18 @@ _tx_thread_schedule_loop:
ld t2, 0(sp) // Pickup stack type
beqz t2, _tx_thread_synch_return // If 0, solicited thread return
- /* Determine if floating point registers need to be recovered. */
+ /* Determine if floating point registers need to be recovered. This is an
+ interrupt frame, so _tx_thread_context_save built it and may have
+ skipped the FP stores when mstatus.FS was Off. Read back the same slot
+ it wrote rather than reloading whatever those slots happen to hold. */
+#if (__riscv_flen == 32) || (__riscv_flen == 64)
+ ld t1, 29*8(sp) // Pickup saved mstatus
+ srli t1, t1, 13
+ andi t1, t1, 0x3
+ beqz t1, _tx_thread_schedule_skip_fp_restore // Skip if FS was Off
+#endif
-#if defined(__riscv_float_abi_single)
+#if (__riscv_flen == 32)
flw f0, 31*8(sp) // Recover ft0
flw f1, 32*8(sp) // Recover ft1
flw f2, 33*8(sp) // Recover ft2
@@ -177,7 +189,7 @@ _tx_thread_schedule_loop:
flw f31,62*8(sp) // Recover ft11
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0 // Restore fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fld f0, 31*8(sp) // Recover ft0
fld f1, 32*8(sp) // Recover ft1
fld f2, 33*8(sp) // Recover ft2
@@ -213,6 +225,7 @@ _tx_thread_schedule_loop:
ld t0, 63*8(sp) // Recover fcsr
csrw fcsr, t0 // Restore fcsr
#endif
+_tx_thread_schedule_skip_fp_restore:
#if defined(__riscv_vector)
/* Recover vector registers v0-v31 */
@@ -259,6 +272,10 @@ _tx_thread_schedule_loop:
li t1, 0x6000 // Set FS=Dirty (bits 14:13)
or t0, t0, t1
#endif
+#if defined(__riscv_vector)
+ li t1, 0x0600
+ or t0, t0, t1
+#endif
csrw sstatus, t0 // Update sstatus safely
#else
csrw mepc, t0 // Store mepc
@@ -274,7 +291,7 @@ _tx_thread_schedule_loop:
or t0, t0, t1
#endif
#if defined(__riscv_vector)
- li t1, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
+ li t1, 0x0600
or t0, t0, t1
#endif
csrw mstatus, t0 // Set mstatus
@@ -309,17 +326,9 @@ _tx_thread_schedule_loop:
ld t5, 14*8(sp) // Recover t5
ld t6, 13*8(sp) // Recover t6
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, 65*8 // Recover stack frame - with floating point registers
-#else
- addi sp, sp, 32*8 // Recover stack frame - without floating point registers
-#endif
+ addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point registers (65*8 data + 8 pad)
#if defined(__riscv_vector)
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t0, sp, -65*8
-#else
- addi t0, sp, -32*8
-#endif
+ addi t0, sp, -TX_TRAP_FRAME_SIZE
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr
@@ -336,7 +345,7 @@ _tx_thread_schedule_loop:
_tx_thread_synch_return:
-#if defined(__riscv_float_abi_single)
+#if (__riscv_flen == 32)
flw f8, 15*8(sp) // Recover fs0
flw f9, 16*8(sp) // Recover fs1
flw f18,17*8(sp) // Recover fs2
@@ -351,7 +360,7 @@ _tx_thread_synch_return:
flw f27,26*8(sp) // Recover fs11
ld t0, 27*8(sp) // Recover fcsr
csrw fcsr, t0 //
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fld f8, 15*8(sp) // Recover fs0
fld f9, 16*8(sp) // Recover fs1
fld f18,17*8(sp) // Recover fs2
@@ -418,11 +427,7 @@ _tx_thread_synch_return:
#else
csrw mstatus, t0 // Store mstatus, enables interrupt
#endif
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, 29*8 // Recover stack frame
-#else
- addi sp, sp, 16*8 // Recover stack frame
-#endif
+ addi sp, sp, TX_SOL_FRAME_SIZE // Recover stack frame (29*8 data + 8 pad)
#if defined(__riscv_vector)
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
diff --git a/ports/risc-v64/gnu/src/tx_thread_stack_build.S b/ports/risc-v64/gnu/src/tx_thread_stack_build.S
index 86cab4f0..47e5c995 100644
--- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S
+++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S
@@ -21,6 +21,8 @@
/**************************************************************************/
.section .text
+#include "tx_port.h"
+ .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -30,6 +32,7 @@
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
+/* Wei-Chen Lai, National Cheng Kung University */
/* */
/* DESCRIPTION */
/* */
@@ -92,7 +95,7 @@ _tx_thread_stack_build:
x11 26 Initial a1
x10 27 Initial a0
x1 28 Initial ra
- -- 29 reserved
+ mstatus 29 Initial mstatus
mepc 30 Initial mepc
If floating point support:
f0 31 Inital ft0
@@ -138,6 +141,9 @@ If vector extension support:
...
v31 99 Initial v31
+ With floating point enabled, 8 pad bytes sit at the top of the frame
+ (bytes 520-527) so the 528-byte total keeps sp 16-byte aligned.
+
Stack Bottom: (higher memory address) */
ld t0, 24(a0) // Pickup end of stack area
@@ -146,11 +152,7 @@ If vector extension support:
/* Actually build the stack frame. */
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi t0, t0, -65*8
-#else
- addi t0, t0, -32*8 // Allocate space for the stack frame
-#endif
+ addi t0, t0, -TX_TRAP_FRAME_SIZE
#if defined(__riscv_vector)
/* Vector extension support: calculate space based on vlenb */
@@ -192,6 +194,8 @@ If vector extension support:
sd zero, 26*8(t0) // Initial a1
sd zero, 27*8(t0) // Initial a0
sd zero, 28*8(t0) // Initial ra
+ li t1, 0x2000 // mstatus.FS = Initial
+ sd t1, 29*8(t0) // Initial mstatus
sd a1, 30*8(t0) // Initial mepc/sepc (thread entry point)
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
sd zero, 31*8(t0) // Initial ft0
@@ -226,8 +230,7 @@ If vector extension support:
sd zero, 60*8(t0) // Initial ft9
sd zero, 61*8(t0) // Initial ft10
sd zero, 62*8(t0) // Initial ft11
- csrr a1, fcsr // Read fcsr for initial value
- sd a1, 63*8(t0) // Initial fcsr
+ sd zero, 63*8(t0) // Initial fcsr (0: no sticky flags, round-to-nearest)
#endif
#if defined(__riscv_vector)
diff --git a/ports/risc-v64/gnu/src/tx_thread_system_return.S b/ports/risc-v64/gnu/src/tx_thread_system_return.S
index 583b3f3e..2f4daeed 100644
--- a/ports/risc-v64/gnu/src/tx_thread_system_return.S
+++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S
@@ -57,17 +57,15 @@
/**************************************************************************/
/* VOID _tx_thread_system_return(VOID)
{ */
+#include "tx_port.h"
+ .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE
.global _tx_thread_system_return
_tx_thread_system_return:
/* Save minimal context on the stack. */
/* sp -= sizeof(stack_frame); */
-#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- addi sp, sp, -29*8 // Allocate space on the stack - with floating point enabled
-#else
- addi sp, sp, -16*8 // Allocate space on the stack - without floating point enabled
-#endif
+ addi sp, sp, -TX_SOL_FRAME_SIZE // Allocate space on the stack
#if defined(__riscv_vector)
csrr t1, vlenb // Get vector register byte length
slli t1, t1, 5 // Multiply by 32 (number of vector registers)
@@ -76,7 +74,7 @@ _tx_thread_system_return:
#endif
/* Store floating point preserved registers. */
-#if defined(__riscv_float_abi_single)
+#if (__riscv_flen == 32)
fsw f8, 15*8(sp) // Store fs0
fsw f9, 16*8(sp) // Store fs1
fsw f18, 17*8(sp) // Store fs2
@@ -91,7 +89,7 @@ _tx_thread_system_return:
fsw f27, 26*8(sp) // Store fs11
csrr t0, fcsr
sd t0, 27*8(sp) // Store fcsr
-#elif defined(__riscv_float_abi_double)
+#elif (__riscv_flen == 64)
fsd f8, 15*8(sp) // Store fs0
fsd f9, 16*8(sp) // Store fs1
fsd f18, 17*8(sp) // Store fs2
diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S
index 53e572f3..207d6677 100644
--- a/ports/risc-v64/gnu/src/tx_timer_interrupt.S
+++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S
@@ -88,7 +88,7 @@ _tx_timer_interrupt:
/* Check for expiration. */
/* if (_tx_timer_time_slice == 0) */
- bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet
+ bnez t3, _tx_timer_no_time_slice // If not 0, has not expired yet
li t1, 1 // Build expired flag
/* Set the time-slice expired flag. */
@@ -181,7 +181,7 @@ _tx_timer_dont_activate:
/* if (_tx_timer_expired_time_slice)
{ */
- andi t2, t6, 1 // Is the timer expired bit set?
+ andi t2, t6, 1 // Is the time-slice expired bit set?
beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing
/* Time slice interrupted thread. */