1/**************************************************************************/ 2/* */ 3/* Copyright (c) Microsoft Corporation. All rights reserved. */ 4/* */ 5/* This software is licensed under the Microsoft Software License */ 6/* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8/* and in the root directory of this software. */ 9/* */ 10/**************************************************************************/ 11 12 13/**************************************************************************/ 14/**************************************************************************/ 15/** */ 16/** ThreadX Component */ 17/** */ 18/** Thread */ 19/** */ 20/**************************************************************************/ 21/**************************************************************************/ 22 23#include "tx_port.h" 24 25 .section .text 26/**************************************************************************/ 27/* */ 28/* FUNCTION RELEASE */ 29/* */ 30/* _tx_thread_context_save RISC-V64/GNU */ 31/* 6.2.1 */ 32/* AUTHOR */ 33/* */ 34/* Scott Larson, Microsoft Corporation */ 35/* */ 36/* DESCRIPTION */ 37/* */ 38/* This function saves the context of an executing thread in the */ 39/* beginning of interrupt processing. The function also ensures that */ 40/* the system stack is used upon return to the calling ISR. */ 41/* */ 42/* INPUT */ 43/* */ 44/* None */ 45/* */ 46/* OUTPUT */ 47/* */ 48/* None */ 49/* */ 50/* CALLS */ 51/* */ 52/* None */ 53/* */ 54/* CALLED BY */ 55/* */ 56/* ISRs */ 57/* */ 58/* RELEASE HISTORY */ 59/* */ 60/* DATE NAME DESCRIPTION */ 61/* */ 62/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ 63/* */ 64/**************************************************************************/ 65/* VOID _tx_thread_context_save(VOID) 66{ */ 67 .global _tx_thread_context_save 68_tx_thread_context_save: 69 70 /* Upon entry to this routine, it is assumed that interrupts are locked 71 out and the interrupt stack fame has been allocated and x1 (ra) has 72 been saved on the stack. */ 73 74 STORE x5, 19*REGBYTES(sp) // First store t0 and t1 75 STORE x6, 18*REGBYTES(sp) 76 77 la x5, _tx_thread_system_state // Pickup address of system state 78 LOAD x6, 0(x5) // Pickup system state 79 80 /* Check for a nested interrupt condition. */ 81 /* if (_tx_thread_system_state++) 82 { */ 83 beqz x6, _tx_thread_not_nested_save // If 0, first interrupt condition 84 addi x6, x6, 1 // Increment the interrupt counter 85 STORE x6, 0(x5) // Store the interrupt counter 86 87 /* Nested interrupt condition. 88 Save the reset of the scratch registers on the stack and return to the 89 calling ISR. */ 90 91 STORE x7, 17*REGBYTES(sp) // Store t2 92 STORE x8, 12*REGBYTES(sp) // Store s0 93 STORE x10, 27*REGBYTES(sp) // Store a0 94 STORE x11, 26*REGBYTES(sp) // Store a1 95 STORE x12, 25*REGBYTES(sp) // Store a2 96 STORE x13, 24*REGBYTES(sp) // Store a3 97 STORE x14, 23*REGBYTES(sp) // Store a4 98 STORE x15, 22*REGBYTES(sp) // Store a5 99 STORE x16, 21*REGBYTES(sp) // Store a6 100 STORE x17, 20*REGBYTES(sp) // Store a7 101 STORE x28, 16*REGBYTES(sp) // Store t3 102 STORE x29, 15*REGBYTES(sp) // Store t4 103 STORE x30, 14*REGBYTES(sp) // Store t5 104 STORE x31, 13*REGBYTES(sp) // Store t6 105 csrr t0, mepc // Load exception program counter 106 STORE t0, 30*REGBYTES(sp) // Save it on the stack 107 108 /* Save floating point scratch registers. */ 109#if defined(__riscv_float_abi_single) 110 fsw f0, 31*REGBYTES(sp) // Store ft0 111 fsw f1, 32*REGBYTES(sp) // Store ft1 112 fsw f2, 33*REGBYTES(sp) // Store ft2 113 fsw f3, 34*REGBYTES(sp) // Store ft3 114 fsw f4, 35*REGBYTES(sp) // Store ft4 115 fsw f5, 36*REGBYTES(sp) // Store ft5 116 fsw f6, 37*REGBYTES(sp) // Store ft6 117 fsw f7, 38*REGBYTES(sp) // Store ft7 118 fsw f10,41*REGBYTES(sp) // Store fa0 119 fsw f11,42*REGBYTES(sp) // Store fa1 120 fsw f12,43*REGBYTES(sp) // Store fa2 121 fsw f13,44*REGBYTES(sp) // Store fa3 122 fsw f14,45*REGBYTES(sp) // Store fa4 123 fsw f15,46*REGBYTES(sp) // Store fa5 124 fsw f16,47*REGBYTES(sp) // Store fa6 125 fsw f17,48*REGBYTES(sp) // Store fa7 126 fsw f28,59*REGBYTES(sp) // Store ft8 127 fsw f29,60*REGBYTES(sp) // Store ft9 128 fsw f30,61*REGBYTES(sp) // Store ft10 129 fsw f31,62*REGBYTES(sp) // Store ft11 130 csrr t0, fcsr 131 STORE t0, 63*REGBYTES(sp) // Store fcsr 132#elif defined(__riscv_float_abi_double) 133 fsd f0, 31*REGBYTES(sp) // Store ft0 134 fsd f1, 32*REGBYTES(sp) // Store ft1 135 fsd f2, 33*REGBYTES(sp) // Store ft2 136 fsd f3, 34*REGBYTES(sp) // Store ft3 137 fsd f4, 35*REGBYTES(sp) // Store ft4 138 fsd f5, 36*REGBYTES(sp) // Store ft5 139 fsd f6, 37*REGBYTES(sp) // Store ft6 140 fsd f7, 38*REGBYTES(sp) // Store ft7 141 fsd f10,41*REGBYTES(sp) // Store fa0 142 fsd f11,42*REGBYTES(sp) // Store fa1 143 fsd f12,43*REGBYTES(sp) // Store fa2 144 fsd f13,44*REGBYTES(sp) // Store fa3 145 fsd f14,45*REGBYTES(sp) // Store fa4 146 fsd f15,46*REGBYTES(sp) // Store fa5 147 fsd f16,47*REGBYTES(sp) // Store fa6 148 fsd f17,48*REGBYTES(sp) // Store fa7 149 fsd f28,59*REGBYTES(sp) // Store ft8 150 fsd f29,60*REGBYTES(sp) // Store ft9 151 fsd f30,61*REGBYTES(sp) // Store ft10 152 fsd f31,62*REGBYTES(sp) // Store ft11 153 csrr t0, fcsr 154 STORE t0, 63*REGBYTES(sp) // Store fcsr 155#endif 156 157#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 158 call _tx_execution_isr_enter // Call the ISR execution enter function 159#endif 160 161 ret // Return to calling ISR 162 163_tx_thread_not_nested_save: 164 /* } */ 165 166 /* Otherwise, not nested, check to see if a thread was running. */ 167 /* else if (_tx_thread_current_ptr) 168 { */ 169 addi x6, x6, 1 // Increment the interrupt counter 170 STORE x6, 0(x5) // Store the interrupt counter 171 172 /* Not nested: Find the user thread that was running and load our SP */ 173 174 LOAD x5, _tx_thread_current_ptr // Pickup current thread pointer 175 beqz x5, _tx_thread_idle_system_save // If NULL, idle system was interrupted 176 177 /* Save the standard scratch registers. */ 178 179 STORE x7, 17*REGBYTES(sp) // Store t2 180 STORE x8, 12*REGBYTES(sp) // Store s0 181 STORE x10, 27*REGBYTES(sp) // Store a0 182 STORE x11, 26*REGBYTES(sp) // Store a1 183 STORE x12, 25*REGBYTES(sp) // Store a2 184 STORE x13, 24*REGBYTES(sp) // Store a3 185 STORE x14, 23*REGBYTES(sp) // Store a4 186 STORE x15, 22*REGBYTES(sp) // Store a5 187 STORE x16, 21*REGBYTES(sp) // Store a6 188 STORE x17, 20*REGBYTES(sp) // Store a7 189 STORE x28, 16*REGBYTES(sp) // Store t3 190 STORE x29, 15*REGBYTES(sp) // Store t4 191 STORE x30, 14*REGBYTES(sp) // Store t5 192 STORE x31, 13*REGBYTES(sp) // Store t6 193 194 csrr t0, mepc // Load exception program counter 195 STORE t0, 30*REGBYTES(sp) // Save it on the stack 196 197 /* Save floating point scratch registers. */ 198#if defined(__riscv_float_abi_single) 199 fsw f0, 31*REGBYTES(sp) // Store ft0 200 fsw f1, 32*REGBYTES(sp) // Store ft1 201 fsw f2, 33*REGBYTES(sp) // Store ft2 202 fsw f3, 34*REGBYTES(sp) // Store ft3 203 fsw f4, 35*REGBYTES(sp) // Store ft4 204 fsw f5, 36*REGBYTES(sp) // Store ft5 205 fsw f6, 37*REGBYTES(sp) // Store ft6 206 fsw f7, 38*REGBYTES(sp) // Store ft7 207 fsw f10,41*REGBYTES(sp) // Store fa0 208 fsw f11,42*REGBYTES(sp) // Store fa1 209 fsw f12,43*REGBYTES(sp) // Store fa2 210 fsw f13,44*REGBYTES(sp) // Store fa3 211 fsw f14,45*REGBYTES(sp) // Store fa4 212 fsw f15,46*REGBYTES(sp) // Store fa5 213 fsw f16,47*REGBYTES(sp) // Store fa6 214 fsw f17,48*REGBYTES(sp) // Store fa7 215 fsw f28,59*REGBYTES(sp) // Store ft8 216 fsw f29,60*REGBYTES(sp) // Store ft9 217 fsw f30,61*REGBYTES(sp) // Store ft10 218 fsw f31,62*REGBYTES(sp) // Store ft11 219 csrr t0, fcsr 220 STORE t0, 63*REGBYTES(sp) // Store fcsr 221#elif defined(__riscv_float_abi_double) 222 fsd f0, 31*REGBYTES(sp) // Store ft0 223 fsd f1, 32*REGBYTES(sp) // Store ft1 224 fsd f2, 33*REGBYTES(sp) // Store ft2 225 fsd f3, 34*REGBYTES(sp) // Store ft3 226 fsd f4, 35*REGBYTES(sp) // Store ft4 227 fsd f5, 36*REGBYTES(sp) // Store ft5 228 fsd f6, 37*REGBYTES(sp) // Store ft6 229 fsd f7, 38*REGBYTES(sp) // Store ft7 230 fsd f10,41*REGBYTES(sp) // Store fa0 231 fsd f11,42*REGBYTES(sp) // Store fa1 232 fsd f12,43*REGBYTES(sp) // Store fa2 233 fsd f13,44*REGBYTES(sp) // Store fa3 234 fsd f14,45*REGBYTES(sp) // Store fa4 235 fsd f15,46*REGBYTES(sp) // Store fa5 236 fsd f16,47*REGBYTES(sp) // Store fa6 237 fsd f17,48*REGBYTES(sp) // Store fa7 238 fsd f28,59*REGBYTES(sp) // Store ft8 239 fsd f29,60*REGBYTES(sp) // Store ft9 240 fsd f30,61*REGBYTES(sp) // Store ft10 241 fsd f31,62*REGBYTES(sp) // Store ft11 242 csrr t0, fcsr 243 STORE t0, 63*REGBYTES(sp) // Store fcsr 244#endif 245 246 /* Save the current stack pointer in the thread's control block. */ 247 /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ 248 249 /* Switch to the system stack. */ 250 /* sp = _tx_thread_system_stack_ptr; */ 251 252 LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer 253 STORE sp, 2*REGBYTES(t1) // Save stack pointer 254 255#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 256 /* _tx_execution_isr_enter is called with thread stack pointer */ 257 call _tx_execution_isr_enter // Call the ISR execution enter function 258#endif 259 260 261 LOAD sp, _tx_thread_system_stack_ptr // Switch to system stack 262 ret // Return to calling ISR 263 264 /* } 265 else 266 { */ 267 268_tx_thread_idle_system_save: 269 270 271#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 272 call _tx_execution_isr_enter // Call the ISR execution enter function 273#endif 274 275 /* Interrupt occurred in the scheduling loop. */ 276 277 /* } 278} */ 279#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) 280 addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled 281#else 282 addi sp, sp, 32*REGBYTES // Recover the reserved stack space 283#endif 284 ret // Return to calling ISR 285