summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/src
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-06-08 10:01:32 +0200
committerGitHub <[email protected]>2026-06-08 10:01:32 +0200
commit87ab09cce305eb9cd4aacac4e8c62af72f665bff (patch)
treedd062ebbea5235d1921c64b396bf7e4ce79e9e15 /ports/risc-v64/gnu/src
parent9ab0cf9683f832cdb48e2099533a5b06a3afcd64 (diff)
parent730b61874bc5cf40768987605ae5187fde0fa1e2 (diff)
Merge pull request #544 from eclipse-threadx/devv6.5.1.202602_rel
Merging changes for the v.6.5.1.202602 release
Diffstat (limited to 'ports/risc-v64/gnu/src')
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_context_restore.S218
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_context_save.S85
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_interrupt_control.S19
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_schedule.S137
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_stack_build.S52
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_system_return.S56
-rw-r--r--ports/risc-v64/gnu/src/tx_timer_interrupt.S8
7 files changed, 518 insertions, 57 deletions
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 6aae3981..cebc8a06 100644
--- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S
+++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S
@@ -63,7 +63,11 @@ _tx_thread_context_restore:
/* Lockout interrupts. */
+#ifdef TX_RISCV_SMODE
+ csrci sstatus, 0x02 // Disable interrupts (SIE bit 1)
+#else
csrci mstatus, 0x08 // Disable interrupts (MIE bit 3)
+#endif
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_isr_exit // Call the ISR execution exit function
@@ -74,9 +78,9 @@ _tx_thread_context_restore:
{ */
la t0, _tx_thread_system_state // Pickup addr of nested interrupt count
- ld t1, 0(t0) // Pickup nested interrupt count
+ lw t1, 0(t0) // Pickup nested interrupt count
addi t1, t1, -1 // Decrement the nested interrupt counter
- sd t1, 0(t0) // Store new nested count
+ sw t1, 0(t0) // Store new nested count
beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore
/* Interrupts are nested. */
@@ -133,6 +137,34 @@ _tx_thread_context_restore:
csrw fcsr, t0
#endif
+#if defined(__riscv_vector)
+ /* Recover vector registers v0-v31 */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 64*8
+#else
+ addi t1, sp, 31*8
+#endif
+ addi t2, t1, 4*8
+ vsetvli t3, zero, e8, m8, ta, ma
+ vle8.v v0, (t2) // Recover v0 ~ v7
+ add t2, t2, t3
+ vle8.v v8, (t2) // Recover v8 ~ v15
+ add t2, t2, t3
+ vle8.v v16, (t2) // Recover v16 ~ v23
+ add t2, t2, t3
+ vle8.v v24, (t2) // Recover v24 ~ v31
+ add t2, t2, t3
+
+ /* Recover vector CSRs */
+ ld t2, 0*8(t1)
+ ld t3, 1*8(t1)
+ ld t4, 2*8(t1)
+ vsetvl zero, t4, t3
+ csrw vstart, t2
+ ld t4, 3*8(t1)
+ csrw vcsr, t4
+#endif
+
/* Recover standard registers. */
/* Restore registers,
@@ -140,31 +172,46 @@ _tx_thread_context_restore:
Also skip the saved registers since they have been restored by any function we called,
except s0 since we use it ourselves. */
- ld t0, 30*8(sp) // Recover mepc
+ ld t0, 30*8(sp) // Recover exception PC
+#ifdef TX_RISCV_SMODE
+ csrw sepc, t0 // Setup sepc
+
+ /* Compose sstatus via read/modify/write to avoid clobbering unrelated bits.
+ Set SPIE and restore SPP to Supervisor, preserve other fields. */
+
+ csrr t1, sstatus
+ li t4, ~0x122 // Clear mask for SPP/SPIE/SIE
+ and t1, t1, t4
+ li t3, 0x120 // Set SPP=Supervisor(0x100) + SPIE(0x20) so sret re-enables SIE
+ or t1, t1, t3
+
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state
+ or t1, t1, t0
+#endif
+ csrw sstatus, t1 // Update sstatus safely
+#else
csrw mepc, t0 // Setup mepc
/* Compose mstatus via read/modify/write to avoid clobbering unrelated bits.
Set MPIE and restore MPP to Machine, preserve other fields. */
csrr t1, mstatus
+ li t2, 0x1880 // Set MPP(0x1800) | MPIE(0x80)
- /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */
-
- li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
- li t3, 0x1800 // Set MPP to Machine mode (bits 12:11)
-
- /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit,
- preserve everything except the bits we will modify. */
-
- li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE
- and t1, t1, t4
- or t1, t1, t3
+ or t1, t1, t2 // MPP and MPIE are now set. All other bits are preserved
+ 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
or t1, t1, t0
#endif
+#if defined(__riscv_vector)
+ li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
+ or t1, t1, t0
+#endif
csrw mstatus, t1 // Update mstatus safely
+#endif
ld ra, 28*8(sp) // Recover return address
ld t0, 19*8(sp) // Recover t0
@@ -189,7 +236,26 @@ _tx_thread_context_restore:
#else
addi sp, sp, 32*8 // Recover stack frame - without floating point enabled
#endif
+
+#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
+ 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
+ add sp, sp, t1 // Recover vector stack frame
+
+ ld t1, 18*8(t0) // Recover t1
+ ld t0, 19*8(t0) // Recover t0
+#endif
+#ifdef TX_RISCV_SMODE
+ sret // Return to point of interrupt
+#else
mret // Return to point of interrupt
+#endif
/* } */
_tx_thread_not_nested_restore:
@@ -217,7 +283,7 @@ _tx_thread_no_preempt_restore:
/* Pickup the saved stack pointer. */
/* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
- ld sp, 16(t1) // Switch back to thread's stack
+ ld sp, 8(t1) // Switch back to thread's stack
/* Recover floating point registers. */
#if defined(__riscv_float_abi_single)
@@ -268,29 +334,80 @@ _tx_thread_no_preempt_restore:
csrw fcsr, t0 // Restore fcsr
#endif
+#if defined(__riscv_vector)
+ /* Recover vector registers v0-v31 */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 64*8
+#else
+ addi t1, sp, 31*8
+#endif
+ addi t2, t1, 4*8
+ vsetvli t3, zero, e8, m8, ta, ma
+ vle8.v v0, (t2) // Recover v0 ~ v7
+ add t2, t2, t3
+ vle8.v v8, (t2) // Recover v8 ~ v15
+ add t2, t2, t3
+ vle8.v v16, (t2) // Recover v16 ~ v23
+ add t2, t2, t3
+ vle8.v v24, (t2) // Recover v24 ~ v31
+ add t2, t2, t3
+
+ /* Recover vector CSRs */
+ ld t2, 0*8(t1)
+ ld t3, 1*8(t1)
+ ld t4, 2*8(t1)
+ vsetvl zero, t4, t3
+ csrw vstart, t2
+ ld t4, 3*8(t1)
+ csrw vcsr, t4
+#endif
+
/* Recover the saved context and return to the point of interrupt. */
/* Recover standard registers. */
/* Restore registers,
Skip global pointer because that does not change */
- ld t0, 30*8(sp) // Recover mepc
- csrw mepc, t0 // Setup mepc
+ ld t0, 30*8(sp) // Recover exception PC
+#ifdef TX_RISCV_SMODE
+ csrw sepc, t0 // Setup sepc
- /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. */
+ /* Compose sstatus via read/modify/write to avoid clobbering unrelated bits. */
- csrr t1, mstatus
- li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
- li t3, 0x1800 // Set MPP to Machine mode
- li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE
+ csrr t1, sstatus
+ li t4, ~0x122 // Clear mask for SPP/SPIE/SIE
and t1, t1, t4
+ li t3, 0x120 // Set SPP=Supervisor(0x100) + SPIE(0x20) so sret re-enables SIE
or t1, t1, t3
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state
+ or t1, t1, t0
+#endif
+ csrw sstatus, t1 // Update sstatus safely
+#else
+ csrw mepc, t0 // Setup mepc
+
+
+ /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits.
+ Set MPIE and restore MPP to Machine, preserve other fields. */
+
+ csrr t1, mstatus
+ li t2, 0x1880 // Set MPP(0x1800) | MPIE(0x80)
+
+ or t1, t1, t2 // MPP and MPIE are now set. All other bits are preserved
+ 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
or t1, t1, t0
#endif
+#if defined(__riscv_vector)
+ li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
+ or t1, t1, t0
+#endif
csrw mstatus, t1 // Update mstatus safely
+#endif
ld ra, 28*8(sp) // Recover return address
ld t0, 19*8(sp) // Recover t0
@@ -315,7 +432,26 @@ _tx_thread_no_preempt_restore:
#else
addi sp, sp, 32*8 // Recover stack frame - without floating point enabled
#endif
+
+#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
+ 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
+ add sp, sp, t1 // Recover vector stack frame
+
+ ld t1, 18*8(t0) // Recover t1
+ ld t0, 19*8(t0) // Recover t0
+#endif
+#ifdef TX_RISCV_SMODE
+ sret // Return to point of interrupt
+#else
mret // Return to point of interrupt
+#endif
/* }
else
@@ -324,7 +460,7 @@ _tx_thread_preempt_restore:
/* Instead of directly activating the thread again, ensure we save the
entire stack frame by saving the remaining registers. */
- ld t0, 16(t1) // Pickup thread's stack pointer
+ ld t0, 8(t1) // Pickup thread's stack pointer
ori t3, zero, 1 // Build interrupt stack type
sd t3, 0(t0) // Store stack type
@@ -357,6 +493,36 @@ _tx_thread_preempt_restore:
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
+
/* Store standard preserved registers. */
sd x9, 11*8(t0) // Store s1
@@ -377,14 +543,14 @@ _tx_thread_preempt_restore:
{ */
la t0, _tx_timer_time_slice // Pickup time slice variable address
- ld t2, 0(t0) // Pickup time slice
+ lw t2, 0(t0) // Pickup time slice
beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice
_tx_timer_time_slice = 0; */
- sd t2, 48(t1) // Save current time slice
- sd x0, 0(t0) // Clear global time slice
+ sw t2, 36(t1) // Save current time slice
+ sw x0, 0(t0) // Clear global time slice
/* } */
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 df6f2c9a..7935bfee 100644
--- a/ports/risc-v64/gnu/src/tx_thread_context_save.S
+++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S
@@ -94,7 +94,11 @@ _tx_thread_context_save:
sd t4, 15*8(sp) // Store t4
sd t5, 14*8(sp) // Store t5
sd t6, 13*8(sp) // Store t6
+#ifdef TX_RISCV_SMODE
+ csrr t0, sepc // Load exception program counter
+#else
csrr t0, mepc // Load exception program counter
+#endif
sd t0, 30*8(sp) // Save it on the stack
/* Save floating point scratch registers if floating point is enabled. */
@@ -146,6 +150,36 @@ _tx_thread_context_save:
sd t0, 63*8(sp) // Store fcsr
#endif
+#if defined(__riscv_vector)
+ /* Store vector registers and CSRs */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 64*8
+#else
+ addi t1, sp, 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
+
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_isr_enter // Call the ISR execution enter function
#endif
@@ -184,7 +218,11 @@ _tx_thread_not_nested_save:
sd t5, 14*8(sp) // Store t5
sd t6, 13*8(sp) // Store t6
+#ifdef TX_RISCV_SMODE
+ csrr t1, sepc // Load exception program counter
+#else
csrr t1, mepc // Load exception program counter
+#endif
sd t1, 30*8(sp) // Save it on the stack
/* Save floating point scratch registers if floating point is enabled. */
@@ -236,6 +274,36 @@ _tx_thread_not_nested_save:
sd t0, 63*8(sp) // Store fcsr
#endif
+#if defined(__riscv_vector)
+ /* Store vector registers and CSRs */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 64*8
+#else
+ addi t1, sp, 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
+
/* Save the current stack pointer in the thread's control block. */
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
@@ -244,7 +312,7 @@ _tx_thread_not_nested_save:
la t1, _tx_thread_current_ptr // Pickup current thread pointer address
ld t1, 0(t1) // Pickup current thread pointer
- sd sp, 16(t1) // Save stack pointer
+ sd sp, 8(t1) // Save stack pointer
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/* _tx_execution_isr_enter is called with thread stack pointer */
@@ -275,4 +343,19 @@ _tx_thread_idle_system_save:
#else
addi sp, sp, 32*8 // Recover the reserved stack space
#endif
+
+#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
+ 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
+ add sp, sp, t1 // Recover vector stack frame
+
+ ld t1, 18*8(t0) // Recover t1
+ ld t0, 19*8(t0) // Recover t0
+#endif
ret // Return to calling ISR
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 dfcb6b47..b43d9558 100644
--- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S
+++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S
@@ -59,20 +59,25 @@
.global _tx_thread_interrupt_control
_tx_thread_interrupt_control:
/* Pickup current interrupt lockout posture. */
- /* old_mstatus = mstatus; */
+#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
+ 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
+#else
csrr t0, mstatus
mv t1, t0 // Save original mstatus for return
-
- /* Apply the new interrupt posture while preserving unrelated mstatus bits. */
- /* Only modify the MIE bit (bit 3) */
- /* mstatus = (mstatus & ~MIE) | (new_posture & MIE); */
-
li t2, ~0x08 // Build mask to clear MIE
and t0, t0, t2 // Clear MIE bit
- and a0, a0, 0x08 // Mask incoming to only MIE bit
+ 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
+#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 d3332896..860adf0b 100644
--- a/ports/risc-v64/gnu/src/tx_thread_schedule.S
+++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S
@@ -62,7 +62,11 @@
_tx_thread_schedule:
/* Enable interrupts. */
+#ifdef TX_RISCV_SMODE
+ csrsi sstatus, 0x02 // Enable interrupts (SIE bit 1)
+#else
csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3)
+#endif
/* Wait for a thread to execute. */
/* do
@@ -94,7 +98,11 @@ _tx_thread_schedule_loop:
/* Yes! We have a thread to execute. Lockout interrupts and
transfer control to it. */
+#ifdef TX_RISCV_SMODE
+ csrci sstatus, 0x02 // Lockout interrupts
+#else
csrci mstatus, 0x08 // Lockout interrupts
+#endif
/* Setup the current thread pointer. */
/* _tx_thread_current_ptr = _tx_thread_execute_ptr; */
@@ -105,10 +113,10 @@ _tx_thread_schedule_loop:
/* Increment the run count for this thread. */
/* _tx_thread_current_ptr -> tx_thread_run_count++; */
- ld t2, 8(t1) // Pickup run count
- ld t3, 48(t1) // Pickup time slice value
+ lw t2, 4(t1) // Pickup run count
+ lw t3, 36(t1) // Pickup time slice value
addi t2, t2, 1 // Increment run count
- sd t2, 8(t1) // Store new run count
+ sw t2, 4(t1) // Store new run count
/* Setup time-slice, if present. */
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */
@@ -118,8 +126,8 @@ _tx_thread_schedule_loop:
/* Switch to the thread's stack. */
/* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */
- ld sp, 16(t1) // Switch to thread's stack
- sd t3, 0(t2) // Store new time-slice
+ ld sp, 8(t1) // Switch to thread's stack
+ sw t3, 0(t2) // Store new time-slice
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@@ -206,16 +214,71 @@ _tx_thread_schedule_loop:
csrw fcsr, t0 // Restore fcsr
#endif
+#if defined(__riscv_vector)
+ /* Recover vector registers v0-v31 */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 64*8
+#else
+ addi t1, sp, 31*8
+#endif
+ addi t2, t1, 4*8
+ vsetvli t3, zero, e8, m8, ta, ma
+ vle8.v v0, (t2) // Recover v0 ~ v7
+ add t2, t2, t3
+ vle8.v v8, (t2) // Recover v8 ~ v15
+ add t2, t2, t3
+ vle8.v v16, (t2) // Recover v16 ~ v23
+ add t2, t2, t3
+ vle8.v v24, (t2) // Recover v24 ~ v31
+ add t2, t2, t3
+
+ /* Recover vector CSRs */
+ ld t2, 0*8(t1)
+ ld t3, 1*8(t1)
+ ld t4, 2*8(t1)
+ vsetvl zero, t4, t3
+ csrw vstart, t2
+ ld t4, 3*8(t1)
+ csrw vcsr, t4
+#endif
+
/* Recover standard registers. */
- ld t0, 30*8(sp) // Recover mepc
+ ld t0, 30*8(sp) // Recover mepc/sepc
+#ifdef TX_RISCV_SMODE
+ csrw sepc, t0 // Store sepc
+
+ /* Read/modify/write sstatus to preserve SUM, MXR, UXL, FS, etc.
+ Only touch SPP, SPIE, SIE — the bits SRET consumes. */
+ csrr t0, sstatus
+ li t1, ~0x122 // Clear mask: SIE(1) | SPIE(5) | SPP(8)
+ and t0, t0, t1
+ li t1, 0x120 // Set SPP=Supervisor(0x100) | SPIE(0x20)
+ or t0, t0, t1
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ li t1, 0x6000 // Set FS=Dirty (bits 14:13)
+ or t0, t0, t1
+#endif
+ csrw sstatus, t0 // Update sstatus safely
+#else
csrw mepc, t0 // Store mepc
- li t0, 0x1880 // Prepare mstatus: MPP=Machine(0x1800) | MPIE(0x80)
+
+ /* Read/modify/write mstatus — same principle as S-mode path. */
+ csrr t0, mstatus
+ li t1, ~0x1888 // Clear mask: MIE(3) | MPIE(7) | MPP(11:12)
+ and t0, t0, t1
+ li t1, 0x1880 // Set MPP=Machine(0x1800) | MPIE(0x80)
+ or t0, t0, t1
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
- li t1, 0x2000 // Set FS bits for FP state
+ li t1, 0x6000 // Set FS=Dirty (bits 14:13)
+ or t0, t0, t1
+#endif
+#if defined(__riscv_vector)
+ li t1, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state
or t0, t0, t1
#endif
csrw mstatus, t0 // Set mstatus
+#endif
ld ra, 28*8(sp) // Recover return address
ld t0, 19*8(sp) // Recover t0
@@ -251,7 +314,25 @@ _tx_thread_schedule_loop:
#else
addi sp, sp, 32*8 // Recover stack frame - without floating point registers
#endif
+#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
+ 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
+ add sp, sp, t1 // Recover vector stack frame
+
+ ld t1, 18*8(t0) // Recover t1
+ ld t0, 19*8(t0) // Recover t0
+#endif
+#ifdef TX_RISCV_SMODE
+ sret // Return to point of interrupt
+#else
mret // Return to point of interrupt
+#endif
_tx_thread_synch_return:
@@ -287,6 +368,34 @@ _tx_thread_synch_return:
csrw fcsr, t0 //
#endif
+#if defined(__riscv_vector)
+ /* Recover vector registers v0-v31 */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 28*8
+#else
+ addi t1, sp, 15*8
+#endif
+ addi t2, t1, 4*8
+ vsetvli t3, zero, e8, m8, ta, ma
+ vle8.v v0, (t2) // Recover v0 ~ v7
+ add t2, t2, t3
+ vle8.v v8, (t2) // Recover v8 ~ v15
+ add t2, t2, t3
+ vle8.v v16, (t2) // Recover v16 ~ v23
+ add t2, t2, t3
+ vle8.v v24, (t2) // Recover v24 ~ v31
+ add t2, t2, t3
+
+ /* Recover vector CSRs */
+ ld t2, 0*8(t1)
+ ld t3, 1*8(t1)
+ ld t4, 2*8(t1)
+ vsetvl zero, t4, t3
+ csrw vstart, t2
+ ld t4, 3*8(t1)
+ csrw vcsr, t4
+#endif
+
/* Recover standard preserved registers. */
/* Recover standard registers. */
@@ -303,13 +412,23 @@ _tx_thread_synch_return:
ld s9, 3*8(sp) // Recover s9
ld s10, 2*8(sp) // Recover s10
ld s11, 1*8(sp) // Recover s11
- ld t0, 14*8(sp) // Recover mstatus
+ ld t0, 14*8(sp) // Recover status register
+#ifdef TX_RISCV_SMODE
+ csrw sstatus, t0 // Store sstatus, enables interrupt
+#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
+#if defined(__riscv_vector)
+ 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
+ add sp, sp, t1 // Recover vector stack frame
+#endif
ret // Return to thread
/* } */
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 8663a6f1..86cab4f0 100644
--- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S
+++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S
@@ -128,10 +128,19 @@ If floating point support:
f30 61 Inital ft10
f31 62 Inital ft11
fscr 63 Inital fscr
+If vector extension support:
+ vstart 64 Initial vstart
+ vtype 65 Initial vtype
+ vl 66 Initial vl
+ vcsr 67 Initial vcsr
+ v0 68 Initial v0
+ v1 69 Initial v1
+ ...
+ v31 99 Initial v31
Stack Bottom: (higher memory address) */
- ld t0, 32(a0) // Pickup end of stack area
+ ld t0, 24(a0) // Pickup end of stack area
li t1, ~15 // Build 16-byte alignment mask
and t0, t0, t1 // Make sure 16-byte alignment
@@ -142,6 +151,17 @@ If floating point support:
#else
addi t0, t0, -32*8 // Allocate space for the stack frame
#endif
+
+#if defined(__riscv_vector)
+ /* Vector extension support: calculate space based on vlenb */
+ csrr t4, vlenb // Get vector register byte length
+ slli t4, t4, 5 // Multiply by 32 (number of vector registers)
+ addi t4, t4, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr
+ sub t0, t0, t4 // Allocate vector space for the stack frame
+#else
+ li t4, 0
+#endif
+
li t1, 1 // Build stack type
sd t1, 0*8(t0) // Place stack type on the top
sd zero, 1*8(t0) // Initial s11
@@ -172,7 +192,7 @@ If floating point support:
sd zero, 26*8(t0) // Initial a1
sd zero, 27*8(t0) // Initial a0
sd zero, 28*8(t0) // Initial ra
- sd a1, 30*8(t0) // Initial mepc (thread entry point)
+ 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
sd zero, 32*8(t0) // Initial ft1
@@ -208,14 +228,36 @@ If floating point support:
sd zero, 62*8(t0) // Initial ft11
csrr a1, fcsr // Read fcsr for initial value
sd a1, 63*8(t0) // Initial fcsr
- sd zero, 64*8(t0) // Reserved word (0)
+#endif
+
+#if defined(__riscv_vector)
+ /* Clear vector register space */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t2, t0, 64*8 // t2 = start of vector registers
+#else
+ addi t2, t0, 31*8 // t2 = start of vector registers
+#endif
+ add t3, t2, t4 // t3 = end of vector registers
+
+vector_clear_loop:
+ beq t2, t3, vector_clear_done // Done if reached end
+ sd zero, 0(t2) // Clear 8 bytes
+ addi t2, t2, 8 // Move to next 8 bytes
+ j vector_clear_loop
+
+vector_clear_done:
+#endif
+
+ add t2, t0, t4
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ sd zero, 64*8(t2) // Reserved word (0)
#else
- sd zero, 31*8(t0) // Reserved word (0)
+ sd zero, 31*8(t2) // Reserved word (0)
#endif
/* Setup stack pointer. */
/* thread_ptr -> tx_thread_stack_ptr = t0; */
- sd t0, 16(a0) // Save stack pointer in thread's
+ sd t0, 8(a0) // Save stack pointer in thread's
ret // control block and return
/* } */
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 4e954ebe..583b3f3e 100644
--- a/ports/risc-v64/gnu/src/tx_thread_system_return.S
+++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S
@@ -68,6 +68,12 @@ _tx_thread_system_return:
#else
addi sp, sp, -16*8 // Allocate space on the stack - without floating point enabled
#endif
+#if defined(__riscv_vector)
+ 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
+ sub sp, sp, t1 // Allocate vector space on the stack
+#endif
/* Store floating point preserved registers. */
#if defined(__riscv_float_abi_single)
@@ -102,6 +108,36 @@ _tx_thread_system_return:
sd t0, 27*8(sp) // Store fcsr
#endif
+#if defined(__riscv_vector)
+ /* Store vector registers and CSRs */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi t1, sp, 28*8
+#else
+ addi t1, sp, 15*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
+
sd zero, 0(sp) // Solicited stack type
sd ra, 13*8(sp) // Save return address
sd s0, 12*8(sp) // Save s0
@@ -116,6 +152,15 @@ _tx_thread_system_return:
sd s9, 3*8(sp) // Save s9
sd s10, 2*8(sp) // Save s10
sd s11, 1*8(sp) // Save s11
+#ifdef TX_RISCV_SMODE
+ csrr t0, sstatus // Pickup sstatus
+ sd t0, 14*8(sp) // Save sstatus
+
+
+ /* Lockout interrupts. will be enabled in _tx_thread_schedule */
+
+ csrci sstatus, 0x02 // Disable interrupts (SIE bit 1)
+#else
csrr t0, mstatus // Pickup mstatus
sd t0, 14*8(sp) // Save mstatus
@@ -123,6 +168,7 @@ _tx_thread_system_return:
/* Lockout interrupts. will be enabled in _tx_thread_schedule */
csrci mstatus, 0x08 // Disable interrupts (MIE bit 3)
+#endif
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@@ -137,15 +183,15 @@ _tx_thread_system_return:
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
SP = _tx_thread_system_stack_ptr; */
- sd sp, 16(t1) // Save stack pointer
- ld sp, 0(t2) // Switch to system stack
+ sd sp, 8(t1) // Save stack pointer
+ ld sp, 0(t2) // Switch to system stack
/* Determine if the time-slice is active. */
/* if (_tx_timer_time_slice)
{ */
la t4, _tx_timer_time_slice // Pickup time slice variable addr
- ld t3, 0(t4) // Pickup time slice value
+ lw t3, 0(t4) // Pickup time slice value
la t2, _tx_thread_schedule // Pickup address of scheduling loop
beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it
@@ -153,8 +199,8 @@ _tx_thread_system_return:
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
_tx_timer_time_slice = 0; */
- sd t3, 48(t1) // Save current time-slice for thread
- sd zero, 0(t4) // Clear time-slice variable
+ sw t3, 36(t1) // Save current time-slice for thread
+ sw zero, 0(t4) // Clear time-slice variable
/* } */
_tx_thread_dont_save_ts:
diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S
index 02b70461..53e572f3 100644
--- a/ports/risc-v64/gnu/src/tx_timer_interrupt.S
+++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S
@@ -66,11 +66,11 @@ _tx_timer_interrupt:
/* _tx_timer_system_clock++; */
la t0, _tx_timer_system_clock // Pickup address of system clock
- ld t1, 0(t0) // Pickup system clock
+ lw t1, 0(t0) // Pickup system clock
la t2, _tx_timer_time_slice // Pickup address of time slice
- ld t3, 0(t2) // Pickup time slice
+ lw t3, 0(t2) // Pickup time slice
addi t1, t1, 1 // Increment system clock
- sd t1, 0(t0) // Store new system clock
+ sw t1, 0(t0) // Store new system clock
li t6, 0 // Clear local expired flag
/* Test for time-slice expiration. */
@@ -83,7 +83,7 @@ _tx_timer_interrupt:
/* Decrement the time_slice. */
/* _tx_timer_time_slice--; */
- sd t3, 0(t2) // Store new time slice
+ sw t3, 0(t2) // Store new time slice
/* Check for expiration. */
/* if (_tx_timer_time_slice == 0) */