diff options
Diffstat (limited to 'ports/risc-v32/gnu/src')
| -rw-r--r-- | ports/risc-v32/gnu/src/tx_initialize_low_level.S | 2 | ||||
| -rw-r--r-- | ports/risc-v32/gnu/src/tx_thread_context_restore.S | 32 | ||||
| -rw-r--r-- | ports/risc-v32/gnu/src/tx_thread_context_save.S | 28 | ||||
| -rw-r--r-- | ports/risc-v32/gnu/src/tx_thread_schedule.S | 22 | ||||
| -rw-r--r-- | ports/risc-v32/gnu/src/tx_thread_system_return.S | 18 |
5 files changed, 79 insertions, 23 deletions
diff --git a/ports/risc-v32/gnu/src/tx_initialize_low_level.S b/ports/risc-v32/gnu/src/tx_initialize_low_level.S index 703466bd..2940f215 100644 --- a/ports/risc-v32/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v32/gnu/src/tx_initialize_low_level.S @@ -62,7 +62,7 @@ __tx_free_memory_start: /**************************************************************************/ /* VOID _tx_initialize_low_level(VOID) { */ - .global _tx_initialize_low_level + .weak _tx_initialize_low_level .weak _tx_initialize_low_level _tx_initialize_low_level: diff --git a/ports/risc-v32/gnu/src/tx_thread_context_restore.S b/ports/risc-v32/gnu/src/tx_thread_context_restore.S index 73a07f61..d3d449e4 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_restore.S @@ -29,6 +29,7 @@ /* AUTHOR */ /* */ /* Akif Ejaz, 10xEngineers */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -82,7 +83,13 @@ _tx_thread_context_restore: /* Just recover the saved registers and return to the point of interrupt. */ - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + lw t1, 29*4(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 #if defined(__riscv_float_abi_single) flw f0, 31*4(sp) // Recover ft0 flw f1, 32*4(sp) // Recover ft1 @@ -130,6 +137,7 @@ _tx_thread_context_restore: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_skip_fp_restore: /* Recover standard registers. */ @@ -149,7 +157,7 @@ _tx_thread_context_restore: /* 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) + li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, preserve everything except the bits we will modify. */ @@ -222,7 +230,13 @@ _tx_thread_no_preempt_restore: lw sp, 8(t1) // Switch back to thread's stack - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + lw t3, 29*4(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 #if defined(__riscv_float_abi_single) flw f0, 31*4(sp) // Recover ft0 flw f1, 32*4(sp) // Recover ft1 @@ -270,6 +284,7 @@ _tx_thread_no_preempt_restore: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_no_preempt_skip_fp_restore: /* Recover the saved context and return to the point of interrupt. */ @@ -284,7 +299,7 @@ _tx_thread_no_preempt_restore: csrr t1, mstatus li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode + li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE and t1, t1, t4 or t1, t1, t3 @@ -331,7 +346,13 @@ _tx_thread_preempt_restore: ori t3, zero, 1 // Build interrupt stack type sw t3, 0(t0) // Store stack type - /* Store floating point preserved registers. */ + /* Store floating point preserved registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + lw t3, 29*4(t0) // Pickup saved mstatus + srli t3, t3, 13 + andi t3, t3, 0x3 + beqz t3, _tx_thread_preempt_skip_fp_restore // Skip if FS was Off +#endif #ifdef __riscv_float_abi_single fsw f8, 39*4(t0) // Store fs0 fsw f9, 40*4(t0) // Store fs1 @@ -359,6 +380,7 @@ _tx_thread_preempt_restore: fsd f26, 57*4(t0) // Store fs10 fsd f27, 58*4(t0) // Store fs11 #endif +_tx_thread_preempt_skip_fp_restore: /* Store standard preserved registers. */ diff --git a/ports/risc-v32/gnu/src/tx_thread_context_save.S b/ports/risc-v32/gnu/src/tx_thread_context_save.S index 66402934..0a0c0c15 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -29,6 +29,7 @@ /* AUTHOR */ /* */ /* Akif Ejaz, 10xEngineers */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -96,6 +97,15 @@ _tx_thread_context_save: sw t5, 14*4(sp) // Store t5 sw t6, 13*4(sp) // Store t6 + /* Save mstatus and skip FP state if FS is Off. */ + csrr t0, mstatus + sw t0, 29*4(sp) +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t1, t0, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_skip_fpu_save +#endif + /* Save floating point registers. */ #if defined(__riscv_float_abi_single) fsw f0, 31*4(sp) // Store ft0 @@ -144,14 +154,11 @@ _tx_thread_context_save: csrr t0, fcsr sw t0, 63*4(sp) // Store fcsr #endif +_tx_thread_skip_fpu_save: csrr t0, mepc sw t0, 30*4(sp) // Save it on the stack - /* Save mstatus. */ - csrr t0, mstatus - sw t0, 29*4(sp) - la t1, _tx_thread_current_ptr // Pickup address of current thread ptr lw t2, 0(t1) // Pickup current thread pointer beqz t2, _tx_thread_idle_system_save // If NULL, idle system was interrupted @@ -190,6 +197,15 @@ _tx_thread_nested_save: sw t5, 14*4(sp) // Store t5 sw t6, 13*4(sp) // Store t6 + /* Save mstatus and skip FP state if FS is Off. */ + csrr t0, mstatus + sw t0, 29*4(sp) +#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 +#endif + /* Save floating point registers. */ #if defined(__riscv_float_abi_single) fsw f0, 31*4(sp) // Store ft0 @@ -238,13 +254,11 @@ _tx_thread_nested_save: csrr t0, fcsr sw t0, 63*4(sp) // Store fcsr #endif +_tx_thread_skip_nested_fpu_save: csrr t0, mepc sw t0, 30*4(sp) // Save it on stack - csrr t0, mstatus - sw t0, 29*4(sp) - /* Call the ISR execution exit function if enabled. */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY call _tx_execution_isr_enter // Call the ISR execution enter function diff --git a/ports/risc-v32/gnu/src/tx_thread_schedule.S b/ports/risc-v32/gnu/src/tx_thread_schedule.S index 1c235a2d..79bfd51a 100644 --- a/ports/risc-v32/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v32/gnu/src/tx_thread_schedule.S @@ -133,7 +133,12 @@ _tx_thread_ready_to_run: lw t0, 0(sp) // Pickup stack type beqz t0, _tx_thread_solicited_return // If 0, solicited return - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + lw t1, 29*4(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 #if defined(__riscv_float_abi_single) flw f0, 31*4(sp) // Recover ft0 flw f1, 32*4(sp) // Recover ft1 @@ -205,9 +210,10 @@ _tx_thread_ready_to_run: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_skip_fp_restore: +#endif /* Recover standard registers. */ - lw t0, 30*4(sp) // Recover mepc csrw mepc, t0 // Setup mepc @@ -256,7 +262,12 @@ _tx_thread_ready_to_run: _tx_thread_solicited_return: - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + lw t1, 14*4(sp) // Pickup saved mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_schedule_solicited_skip_fp_restore // Skip if FS was Off #if defined(__riscv_float_abi_single) flw f8, 15*4(sp) // Recover fs0 flw f9, 16*4(sp) // Recover fs1 @@ -288,10 +299,11 @@ _tx_thread_solicited_return: lw t0, 27*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_solicited_skip_fp_restore: +#endif /* Recover standard registers. */ - - lw t0, 14*4(sp) // Recover mstatus + lw t0, 14*4(sp) // Reload saved mstatus (t0 may hold fcsr if FP was restored) csrw mstatus, t0 // Restore mstatus lw ra, 13*4(sp) // Recover return address diff --git a/ports/risc-v32/gnu/src/tx_thread_system_return.S b/ports/risc-v32/gnu/src/tx_thread_system_return.S index 4090e7b2..20ff25f2 100644 --- a/ports/risc-v32/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v32/gnu/src/tx_thread_system_return.S @@ -69,7 +69,17 @@ _tx_thread_system_return: addi sp, sp, -16*4 // Allocate space on the stack - without floating point enabled #endif - /* Store floating point preserved registers. */ + sw zero, 0(sp) // Solicited stack type (store early so slot is always written) + + /* Read and save mstatus first; use it to guard FP register save. */ + csrr t0, mstatus // Pickup current mstatus + sw t0, 14*4(sp) // Save mstatus + + /* Store floating point preserved registers — only if FS != Off. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t1, t0, 13 // Shift FS field to bits [1:0] + andi t1, t1, 0x3 // Isolate FS bits + beqz t1, _tx_thread_system_return_skip_fp // Skip FP save if FS == Off #if defined(__riscv_float_abi_single) fsw f8, 15*4(sp) // Store fs0 fsw f9, 16*4(sp) // Store fs1 @@ -101,8 +111,9 @@ _tx_thread_system_return: csrr t0, fcsr sw t0, 27*4(sp) // Store fcsr #endif +_tx_thread_system_return_skip_fp: +#endif - sw zero, 0(sp) // Solicited stack type sw ra, 13*4(sp) // Save return address sw s0, 12*4(sp) // Save s0 sw s1, 11*4(sp) // Save s1 @@ -116,9 +127,6 @@ _tx_thread_system_return: sw s9, 3*4(sp) // Save s9 sw s10, 2*4(sp) // Save s10 sw s11, 1*4(sp) // Save s11 - csrr t0, mstatus // Pickup mstatus - sw t0, 14*4(sp) // Save mstatus - /* Lockout interrupts. will be enabled in _tx_thread_schedule */ |
