summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/src/tx_thread_context_save.S
diff options
context:
space:
mode:
Diffstat (limited to 'ports/risc-v64/gnu/src/tx_thread_context_save.S')
-rw-r--r--ports/risc-v64/gnu/src/tx_thread_context_save.S284
1 files changed, 284 insertions, 0 deletions
diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..5e0e4be0
--- /dev/null
+++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,284 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#include "tx_port.h"
+
+ .section .text
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save RISC-V64/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves the context of an executing thread in the */
+/* beginning of interrupt processing. The function also ensures that */
+/* the system stack is used upon return to the calling ISR. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
+/* */
+/**************************************************************************/
+/* VOID _tx_thread_context_save(VOID)
+{ */
+ .global _tx_thread_context_save
+_tx_thread_context_save:
+
+ /* Upon entry to this routine, it is assumed that interrupts are locked
+ out and the interrupt stack fame has been allocated and x1 (ra) has
+ been saved on the stack. */
+
+ STORE x5, 19*REGBYTES(sp) // First store t0 and t1
+ STORE x6, 18*REGBYTES(sp)
+
+ la x5, _tx_thread_system_state // Pickup address of system state
+ LOAD x6, 0(x5) // Pickup system state
+
+ /* Check for a nested interrupt condition. */
+ /* if (_tx_thread_system_state++)
+ { */
+ beqz x6, _tx_thread_not_nested_save // If 0, first interrupt condition
+ addi x6, x6, 1 // Increment the interrupt counter
+ STORE x6, 0(x5) // Store the interrupt counter
+
+ /* Nested interrupt condition.
+ Save the reset of the scratch registers on the stack and return to the
+ calling ISR. */
+
+ STORE x7, 17*REGBYTES(sp) // Store t2
+ STORE x8, 12*REGBYTES(sp) // Store s0
+ STORE x10, 27*REGBYTES(sp) // Store a0
+ STORE x11, 26*REGBYTES(sp) // Store a1
+ STORE x12, 25*REGBYTES(sp) // Store a2
+ STORE x13, 24*REGBYTES(sp) // Store a3
+ STORE x14, 23*REGBYTES(sp) // Store a4
+ STORE x15, 22*REGBYTES(sp) // Store a5
+ STORE x16, 21*REGBYTES(sp) // Store a6
+ STORE x17, 20*REGBYTES(sp) // Store a7
+ STORE x28, 16*REGBYTES(sp) // Store t3
+ STORE x29, 15*REGBYTES(sp) // Store t4
+ STORE x30, 14*REGBYTES(sp) // Store t5
+ STORE x31, 13*REGBYTES(sp) // Store t6
+ csrr t0, mepc // Load exception program counter
+ STORE t0, 30*REGBYTES(sp) // Save it on the stack
+
+ /* Save floating point scratch registers. */
+#if defined(__riscv_float_abi_single)
+ fsw f0, 31*REGBYTES(sp) // Store ft0
+ fsw f1, 32*REGBYTES(sp) // Store ft1
+ fsw f2, 33*REGBYTES(sp) // Store ft2
+ fsw f3, 34*REGBYTES(sp) // Store ft3
+ fsw f4, 35*REGBYTES(sp) // Store ft4
+ fsw f5, 36*REGBYTES(sp) // Store ft5
+ fsw f6, 37*REGBYTES(sp) // Store ft6
+ fsw f7, 38*REGBYTES(sp) // Store ft7
+ fsw f10,41*REGBYTES(sp) // Store fa0
+ fsw f11,42*REGBYTES(sp) // Store fa1
+ fsw f12,43*REGBYTES(sp) // Store fa2
+ fsw f13,44*REGBYTES(sp) // Store fa3
+ fsw f14,45*REGBYTES(sp) // Store fa4
+ fsw f15,46*REGBYTES(sp) // Store fa5
+ fsw f16,47*REGBYTES(sp) // Store fa6
+ fsw f17,48*REGBYTES(sp) // Store fa7
+ fsw f28,59*REGBYTES(sp) // Store ft8
+ fsw f29,60*REGBYTES(sp) // Store ft9
+ fsw f30,61*REGBYTES(sp) // Store ft10
+ fsw f31,62*REGBYTES(sp) // Store ft11
+ csrr t0, fcsr
+ STORE t0, 63*REGBYTES(sp) // Store fcsr
+#elif defined(__riscv_float_abi_double)
+ fsd f0, 31*REGBYTES(sp) // Store ft0
+ fsd f1, 32*REGBYTES(sp) // Store ft1
+ fsd f2, 33*REGBYTES(sp) // Store ft2
+ fsd f3, 34*REGBYTES(sp) // Store ft3
+ fsd f4, 35*REGBYTES(sp) // Store ft4
+ fsd f5, 36*REGBYTES(sp) // Store ft5
+ fsd f6, 37*REGBYTES(sp) // Store ft6
+ fsd f7, 38*REGBYTES(sp) // Store ft7
+ fsd f10,41*REGBYTES(sp) // Store fa0
+ fsd f11,42*REGBYTES(sp) // Store fa1
+ fsd f12,43*REGBYTES(sp) // Store fa2
+ fsd f13,44*REGBYTES(sp) // Store fa3
+ fsd f14,45*REGBYTES(sp) // Store fa4
+ fsd f15,46*REGBYTES(sp) // Store fa5
+ fsd f16,47*REGBYTES(sp) // Store fa6
+ fsd f17,48*REGBYTES(sp) // Store fa7
+ fsd f28,59*REGBYTES(sp) // Store ft8
+ fsd f29,60*REGBYTES(sp) // Store ft9
+ fsd f30,61*REGBYTES(sp) // Store ft10
+ fsd f31,62*REGBYTES(sp) // Store ft11
+ csrr t0, fcsr
+ STORE t0, 63*REGBYTES(sp) // Store fcsr
+#endif
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ call _tx_execution_isr_enter // Call the ISR execution enter function
+#endif
+
+ ret // Return to calling ISR
+
+_tx_thread_not_nested_save:
+ /* } */
+
+ /* Otherwise, not nested, check to see if a thread was running. */
+ /* else if (_tx_thread_current_ptr)
+ { */
+ addi x6, x6, 1 // Increment the interrupt counter
+ STORE x6, 0(x5) // Store the interrupt counter
+
+ /* Not nested: Find the user thread that was running and load our SP */
+
+ LOAD x5, _tx_thread_current_ptr // Pickup current thread pointer
+ beqz x5, _tx_thread_idle_system_save // If NULL, idle system was interrupted
+
+ /* Save the standard scratch registers. */
+
+ STORE x7, 17*REGBYTES(sp) // Store t2
+ STORE x8, 12*REGBYTES(sp) // Store s0
+ STORE x10, 27*REGBYTES(sp) // Store a0
+ STORE x11, 26*REGBYTES(sp) // Store a1
+ STORE x12, 25*REGBYTES(sp) // Store a2
+ STORE x13, 24*REGBYTES(sp) // Store a3
+ STORE x14, 23*REGBYTES(sp) // Store a4
+ STORE x15, 22*REGBYTES(sp) // Store a5
+ STORE x16, 21*REGBYTES(sp) // Store a6
+ STORE x17, 20*REGBYTES(sp) // Store a7
+ STORE x28, 16*REGBYTES(sp) // Store t3
+ STORE x29, 15*REGBYTES(sp) // Store t4
+ STORE x30, 14*REGBYTES(sp) // Store t5
+ STORE x31, 13*REGBYTES(sp) // Store t6
+
+ csrr t0, mepc // Load exception program counter
+ STORE t0, 30*REGBYTES(sp) // Save it on the stack
+
+ /* Save floating point scratch registers. */
+#if defined(__riscv_float_abi_single)
+ fsw f0, 31*REGBYTES(sp) // Store ft0
+ fsw f1, 32*REGBYTES(sp) // Store ft1
+ fsw f2, 33*REGBYTES(sp) // Store ft2
+ fsw f3, 34*REGBYTES(sp) // Store ft3
+ fsw f4, 35*REGBYTES(sp) // Store ft4
+ fsw f5, 36*REGBYTES(sp) // Store ft5
+ fsw f6, 37*REGBYTES(sp) // Store ft6
+ fsw f7, 38*REGBYTES(sp) // Store ft7
+ fsw f10,41*REGBYTES(sp) // Store fa0
+ fsw f11,42*REGBYTES(sp) // Store fa1
+ fsw f12,43*REGBYTES(sp) // Store fa2
+ fsw f13,44*REGBYTES(sp) // Store fa3
+ fsw f14,45*REGBYTES(sp) // Store fa4
+ fsw f15,46*REGBYTES(sp) // Store fa5
+ fsw f16,47*REGBYTES(sp) // Store fa6
+ fsw f17,48*REGBYTES(sp) // Store fa7
+ fsw f28,59*REGBYTES(sp) // Store ft8
+ fsw f29,60*REGBYTES(sp) // Store ft9
+ fsw f30,61*REGBYTES(sp) // Store ft10
+ fsw f31,62*REGBYTES(sp) // Store ft11
+ csrr t0, fcsr
+ STORE t0, 63*REGBYTES(sp) // Store fcsr
+#elif defined(__riscv_float_abi_double)
+ fsd f0, 31*REGBYTES(sp) // Store ft0
+ fsd f1, 32*REGBYTES(sp) // Store ft1
+ fsd f2, 33*REGBYTES(sp) // Store ft2
+ fsd f3, 34*REGBYTES(sp) // Store ft3
+ fsd f4, 35*REGBYTES(sp) // Store ft4
+ fsd f5, 36*REGBYTES(sp) // Store ft5
+ fsd f6, 37*REGBYTES(sp) // Store ft6
+ fsd f7, 38*REGBYTES(sp) // Store ft7
+ fsd f10,41*REGBYTES(sp) // Store fa0
+ fsd f11,42*REGBYTES(sp) // Store fa1
+ fsd f12,43*REGBYTES(sp) // Store fa2
+ fsd f13,44*REGBYTES(sp) // Store fa3
+ fsd f14,45*REGBYTES(sp) // Store fa4
+ fsd f15,46*REGBYTES(sp) // Store fa5
+ fsd f16,47*REGBYTES(sp) // Store fa6
+ fsd f17,48*REGBYTES(sp) // Store fa7
+ fsd f28,59*REGBYTES(sp) // Store ft8
+ fsd f29,60*REGBYTES(sp) // Store ft9
+ fsd f30,61*REGBYTES(sp) // Store ft10
+ fsd f31,62*REGBYTES(sp) // Store ft11
+ csrr t0, fcsr
+ STORE t0, 63*REGBYTES(sp) // Store fcsr
+#endif
+
+ /* Save the current stack pointer in the thread's control block. */
+ /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
+
+ /* Switch to the system stack. */
+ /* sp = _tx_thread_system_stack_ptr; */
+
+ LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer
+ STORE sp, 2*REGBYTES(t1) // Save stack pointer
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* _tx_execution_isr_enter is called with thread stack pointer */
+ call _tx_execution_isr_enter // Call the ISR execution enter function
+#endif
+
+
+ LOAD sp, _tx_thread_system_stack_ptr // Switch to system stack
+ ret // Return to calling ISR
+
+ /* }
+ else
+ { */
+
+_tx_thread_idle_system_save:
+
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ call _tx_execution_isr_enter // Call the ISR execution enter function
+#endif
+
+ /* Interrupt occurred in the scheduling loop. */
+
+ /* }
+} */
+#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
+ addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled
+#else
+ addi sp, sp, 32*REGBYTES // Recover the reserved stack space
+#endif
+ ret // Return to calling ISR