Skip to content

Commit 7e31dc6

Browse files
committed
feat: restore Lazy FPU stacking without assembly macros
Reintroduce the Lazy FPU stacking optimization while preserving the reviewer-requested assembly style: - no tx_port.h include from .S files - no STORE/LOAD/REGBYTES abstractions - stack offsets remain hardcoded as in the upstream RISC-V32 GNU port The optimization records mstatus in the interrupt stack frame and checks the FS field before saving/restoring floating point state. If FS is Off, FP register and fcsr save/restore are skipped. If FS is Initial/Clean/Dirty, the existing FP context path is used. This touches only tx_thread_context_save.S and tx_thread_context_restore.S, and credits Wei-Chen Lai in the AUTHOR blocks for those Lazy FPU changes.
1 parent 08d2bea commit 7e31dc6

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

ports/risc-v32/gnu/src/tx_thread_context_restore.S

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/* AUTHOR */
3030
/* */
3131
/* Akif Ejaz, 10xEngineers */
32+
/* Wei-Chen Lai, National Cheng Kung University */
3233
/* */
3334
/* DESCRIPTION */
3435
/* */
@@ -82,7 +83,13 @@ _tx_thread_context_restore:
8283
/* Just recover the saved registers and return to the point of
8384
interrupt. */
8485

85-
/* Recover floating point registers. */
86+
/* Recover floating point registers only if saved mstatus.FS was not Off. */
87+
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
88+
lw t1, 29*4(sp) // Pickup saved mstatus
89+
srli t1, t1, 13
90+
andi t1, t1, 0x3
91+
beqz t1, _tx_thread_skip_fp_restore // Skip if FS was Off
92+
#endif
8693
#if defined(__riscv_float_abi_single)
8794
flw f0, 31*4(sp) // Recover ft0
8895
flw f1, 32*4(sp) // Recover ft1
@@ -130,6 +137,7 @@ _tx_thread_context_restore:
130137
lw t0, 63*4(sp) // Recover fcsr
131138
csrw fcsr, t0 // Restore fcsr
132139
#endif
140+
_tx_thread_skip_fp_restore:
133141

134142
/* Recover standard registers. */
135143

@@ -222,7 +230,13 @@ _tx_thread_no_preempt_restore:
222230

223231
lw sp, 8(t1) // Switch back to thread's stack
224232

225-
/* Recover floating point registers. */
233+
/* Recover floating point registers only if saved mstatus.FS was not Off. */
234+
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
235+
lw t3, 29*4(sp) // Pickup saved mstatus
236+
srli t3, t3, 13
237+
andi t3, t3, 0x3
238+
beqz t3, _tx_thread_no_preempt_skip_fp_restore // Skip if FS was Off
239+
#endif
226240
#if defined(__riscv_float_abi_single)
227241
flw f0, 31*4(sp) // Recover ft0
228242
flw f1, 32*4(sp) // Recover ft1
@@ -270,6 +284,7 @@ _tx_thread_no_preempt_restore:
270284
lw t0, 63*4(sp) // Recover fcsr
271285
csrw fcsr, t0 // Restore fcsr
272286
#endif
287+
_tx_thread_no_preempt_skip_fp_restore:
273288

274289
/* Recover the saved context and return to the point of interrupt. */
275290

@@ -331,7 +346,13 @@ _tx_thread_preempt_restore:
331346
ori t3, zero, 1 // Build interrupt stack type
332347
sw t3, 0(t0) // Store stack type
333348

334-
/* Store floating point preserved registers. */
349+
/* Store floating point preserved registers only if saved mstatus.FS was not Off. */
350+
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
351+
lw t3, 29*4(t0) // Pickup saved mstatus
352+
srli t3, t3, 13
353+
andi t3, t3, 0x3
354+
beqz t3, _tx_thread_preempt_skip_fp_restore // Skip if FS was Off
355+
#endif
335356
#ifdef __riscv_float_abi_single
336357
fsw f8, 39*4(t0) // Store fs0
337358
fsw f9, 40*4(t0) // Store fs1
@@ -359,6 +380,7 @@ _tx_thread_preempt_restore:
359380
fsd f26, 57*4(t0) // Store fs10
360381
fsd f27, 58*4(t0) // Store fs11
361382
#endif
383+
_tx_thread_preempt_skip_fp_restore:
362384

363385
/* Store standard preserved registers. */
364386

ports/risc-v32/gnu/src/tx_thread_context_save.S

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/* AUTHOR */
3030
/* */
3131
/* Akif Ejaz, 10xEngineers */
32+
/* Wei-Chen Lai, National Cheng Kung University */
3233
/* */
3334
/* DESCRIPTION */
3435
/* */
@@ -96,6 +97,15 @@ _tx_thread_context_save:
9697
sw t5, 14*4(sp) // Store t5
9798
sw t6, 13*4(sp) // Store t6
9899

100+
/* Save mstatus and skip FP state if FS is Off. */
101+
csrr t0, mstatus
102+
sw t0, 29*4(sp)
103+
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
104+
srli t1, t0, 13
105+
andi t1, t1, 0x3
106+
beqz t1, _tx_thread_skip_fpu_save
107+
#endif
108+
99109
/* Save floating point registers. */
100110
#if defined(__riscv_float_abi_single)
101111
fsw f0, 31*4(sp) // Store ft0
@@ -144,14 +154,11 @@ _tx_thread_context_save:
144154
csrr t0, fcsr
145155
sw t0, 63*4(sp) // Store fcsr
146156
#endif
157+
_tx_thread_skip_fpu_save:
147158

148159
csrr t0, mepc
149160
sw t0, 30*4(sp) // Save it on the stack
150161

151-
/* Save mstatus. */
152-
csrr t0, mstatus
153-
sw t0, 29*4(sp)
154-
155162
la t1, _tx_thread_current_ptr // Pickup address of current thread ptr
156163
lw t2, 0(t1) // Pickup current thread pointer
157164
beqz t2, _tx_thread_idle_system_save // If NULL, idle system was interrupted
@@ -190,6 +197,15 @@ _tx_thread_nested_save:
190197
sw t5, 14*4(sp) // Store t5
191198
sw t6, 13*4(sp) // Store t6
192199

200+
/* Save mstatus and skip FP state if FS is Off. */
201+
csrr t0, mstatus
202+
sw t0, 29*4(sp)
203+
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
204+
srli t1, t0, 13
205+
andi t1, t1, 0x3
206+
beqz t1, _tx_thread_skip_nested_fpu_save
207+
#endif
208+
193209
/* Save floating point registers. */
194210
#if defined(__riscv_float_abi_single)
195211
fsw f0, 31*4(sp) // Store ft0
@@ -238,13 +254,11 @@ _tx_thread_nested_save:
238254
csrr t0, fcsr
239255
sw t0, 63*4(sp) // Store fcsr
240256
#endif
257+
_tx_thread_skip_nested_fpu_save:
241258

242259
csrr t0, mepc
243260
sw t0, 30*4(sp) // Save it on stack
244261

245-
csrr t0, mstatus
246-
sw t0, 29*4(sp)
247-
248262
/* Call the ISR execution exit function if enabled. */
249263
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
250264
call _tx_execution_isr_enter // Call the ISR execution enter function

0 commit comments

Comments
 (0)