111111 #define MSTATUS_VS_CLEAN 0x400
112112 #define MSTATUS_VS_DIRTY 0x600
113113 #define MSTATUS_VS_OFFSET 9
114+
114115 #ifndef __riscv_vector
115116 #error configENABLE_VPU must not be set to 1 if the hardware does not have VPU
116117 #endif
@@ -204,57 +205,68 @@ addi sp, sp, ( portFPU_CONTEXT_SIZE )
204205/*-----------------------------------------------------------*/
205206
206207 .macro portcontexSAVE_VPU_CONTEXT
207- /* Store the vector registers on groups of 8. Use the length in bytes (vlenb)
208- to know how much space they need and reserve it in the stack. */
209- csrr t0 , vlenb
210- slli t0 , t0 , 3 /* vlenb * 8 */
211- neg t0 , t0
212- /* Store the vector registers. */
208+ /* Un-reserve the space reserved for mstatus and epc. */
209+ add sp , sp , ( 2 * portWORD_SIZE )
210+
211+ csrr t0 , vlenb /* t0 = vlenb. vlenb is the length of each vector register in bytes. */
212+ slli t0 , t0 , 3 /* t0 = vlenb * 8. t0 now contains the space required to store 8 vector registers. */
213+ neg t0 , t0
214+
215+ /* Store the vector registers in group of 8. */
213216add sp , sp , t0
214- vs8r .v v0 , (sp )
217+ vs8r .v v0 , (sp ) /* Store v0-v7. */
215218add sp , sp , t0
216- vs8r .v v8 , (sp )
219+ vs8r .v v8 , (sp ) /* Store v8-v15. */
217220add sp , sp , t0
218- vs8r .v v16 , (sp )
221+ vs8r .v v16 , (sp ) /* Store v16-v23. */
219222add sp , sp , t0
220- vs8r .v v24 , (sp )
221- /* Store the VPU registers. */
222- addi sp , sp , - ( 4 * portWORD_SIZE )
223- csrr t0 , vstart
223+ vs8r .v v24 , (sp ) /* Store v24-v31. */
224+
225+ /* Store the VPU CSRs. */
226+ addi sp , sp , - ( 4 * portWORD_SIZE )
227+ csrr t0 , vstart
224228store_x t0 , 0 * portWORD_SIZE ( sp )
225229csrr t0 , vcsr
226230store_x t0 , 1 * portWORD_SIZE ( sp )
227231csrr t0 , vl
228232store_x t0 , 2 * portWORD_SIZE ( sp )
229233csrr t0 , vtype
230234store_x t0 , 3 * portWORD_SIZE ( sp )
235+
236+ /* Re-reserve the space for mstatus and epc. */
237+ add sp , sp , - ( 2 * portWORD_SIZE )
231238 .endm
232239/*-----------------------------------------------------------*/
233240
234241 .macro portcontextRESTORE_VPU_CONTEXT
235- /* Restore the VPU registers. */
236- load_x t0 , 0 * portWORD_SIZE ( sp )
242+ /* Un-reserve the space reserved for mstatus and epc. */
243+ add sp , sp , ( 2 * portWORD_SIZE )
244+
245+ /* Restore the VPU CSRs. */
246+ load_x t0 , 0 * portWORD_SIZE ( sp )
237247csrw vstart , t0
238- load_x t0 , 1 * portWORD_SIZE ( sp )
248+ load_x t0 , 1 * portWORD_SIZE ( sp )
239249csrw vcsr , t0
240- load_x t0 , 2 * portWORD_SIZE ( sp )
241- load_x t1 , 3 * portWORD_SIZE ( sp )
242- /* vlen and vtype can only be updated by using vset*vl* instructions. */
243- vsetvl x0 , t0 , t1
244- addi sp , sp , ( 4 * portWORD_SIZE )
245- /* Load the vector registers on groups of 8. Use the length in bytes (vlenb)
246- to know how much space they use. */
247- csrr t0 , vlenb
248- slli t0 , t0 , 3 /* vlenb * 8 */
250+ load_x t0 , 2 * portWORD_SIZE ( sp )
251+ load_x t1 , 3 * portWORD_SIZE ( sp )
252+ vsetvl x0 , t0 , t1 /* vlen and vtype can only be updated by using vset*vl* instructions. */
253+ addi sp , sp , ( 4 * portWORD_SIZE )
254+
255+ csrr t0 , vlenb /* t0 = vlenb. vlenb is the length of each vector register in bytes. */
256+ slli t0 , t0 , 3 /* t0 = vlenb * 8. t0 now contains the space required to store 8 vector registers. */
257+
249258/* Restore the vector registers. */
250259vl8r .v v24 , (sp )
251- add sp , sp , t0
260+ add sp , sp , t0
252261vl8r .v v16 , (sp )
253- add sp , sp , t0
262+ add sp , sp , t0
254263vl8r .v v8 , (sp )
255- add sp , sp , t0
264+ add sp , sp , t0
256265vl8r .v v0 , (sp )
257- add sp , sp , t0
266+ add sp , sp , t0
267+
268+ /* Re-reserve the space for mstatus and epc. */
269+ add sp , sp , - ( 2 * portWORD_SIZE )
258270 .endm
259271/*-----------------------------------------------------------*/
260272
@@ -310,10 +322,10 @@ store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the criti
310322 srl t1 , t0 , MSTATUS_VS_OFFSET
311323 andi t1 , t1 , 3
312324 addi t2 , x0 , 3
313- bne t1 , t2 , 1f /* If VPU status is not dirty, do not save FPU registers. */
325+ bne t1 , t2 , 2f /* If VPU status is not dirty, do not save FPU registers. */
314326
315327 portcontexSAVE_VPU_CONTEXT
316- 1 :
328+ 2 :
317329#endif
318330
319331portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
@@ -326,29 +338,29 @@ store_x t0, 1 * portWORD_SIZE( sp )
326338 srl t1 , t0 , MSTATUS_FS_OFFSET
327339 andi t1 , t1 , 3
328340 addi t2 , x0 , 3
329- bne t1 , t2 , 2f
341+ bne t1 , t2 , 3f
330342
331343 li t1 , ~MSTATUS_FS_MASK
332344 and t0 , t0 , t1
333345 li t1 , MSTATUS_FS_CLEAN
334346 or t0 , t0 , t1
335347 csrw mstatus , t0
336- 2 :
348+ 3 :
337349#endif
338350
339351#if ( configENABLE_VPU == 1 )
340352 /* Mark the VPU as clean, if it was dirty and we saved VPU registers. */
341353 srl t1 , t0 , MSTATUS_VS_OFFSET
342354 andi t1 , t1 , 3
343355 addi t2 , x0 , 3
344- bne t1 , t2 , 2f
356+ bne t1 , t2 , 4f
345357
346358 li t1 , ~MSTATUS_VS_MASK
347359 and t0 , t0 , t1
348360 li t1 , MSTATUS_VS_CLEAN
349361 or t0 , t0 , t1
350362 csrw mstatus , t0
351- 2 :
363+ 4 :
352364#endif
353365
354366load_x t0 , pxCurrentTCB /* Load pxCurrentTCB. */
@@ -396,21 +408,21 @@ portasmRESTORE_ADDITIONAL_REGISTERS
396408 srl t1 , t0 , MSTATUS_VS_OFFSET
397409 andi t1 , t1 , 3
398410 addi t2 , x0 , 3
399- bne t1 , t2 , 3f /* If VPU status is not dirty, do not restore VPU registers. */
411+ bne t1 , t2 , 5f /* If VPU status is not dirty, do not restore VPU registers. */
400412
401413 portcontextRESTORE_VPU_CONTEXT
402- 3 :
414+ 5 :
403415#endif /* ifdef portasmSTORE_VPU_CONTEXT */
404416
405417#if ( configENABLE_FPU == 1 )
406418 csrr t0 , mstatus
407419 srl t1 , t0 , MSTATUS_FS_OFFSET
408420 andi t1 , t1 , 3
409421 addi t2 , x0 , 3
410- bne t1 , t2 , 3f /* If FPU status is not dirty, do not restore FPU registers. */
422+ bne t1 , t2 , 6f /* If FPU status is not dirty, do not restore FPU registers. */
411423
412424 portcontextRESTORE_FPU_CONTEXT
413- 3 :
425+ 6 :
414426#endif /* ifdef portasmSTORE_FPU_CONTEXT */
415427
416428load_x t0 , portCRITICAL_NESTING_OFFSET * portWORD_SIZE ( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
0 commit comments