1/*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 12/**************************************************************************/ 13/**************************************************************************/ 14/** */ 15/** ThreadX Component */ 16/** */ 17/** Thread */ 18/** */ 19/**************************************************************************/ 20/**************************************************************************/ 21 22#include "tx_port.h" 23 24 .section .text 25/**************************************************************************/ 26/* */ 27/* FUNCTION RELEASE */ 28/* */ 29/* _tx_thread_schedule RISC-V64/GNU */ 30/* 6.2.1 */ 31/* AUTHOR */ 32/* */ 33/* Scott Larson, Microsoft Corporation */ 34/* */ 35/* DESCRIPTION */ 36/* */ 37/* This function waits for a thread control block pointer to appear in */ 38/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ 39/* in the variable, the corresponding thread is resumed. */ 40/* */ 41/* INPUT */ 42/* */ 43/* None */ 44/* */ 45/* OUTPUT */ 46/* */ 47/* None */ 48/* */ 49/* CALLS */ 50/* */ 51/* None */ 52/* */ 53/* CALLED BY */ 54/* */ 55/* _tx_initialize_kernel_enter ThreadX entry function */ 56/* _tx_thread_system_return Return to system from thread */ 57/* _tx_thread_context_restore Restore thread's context */ 58/* */ 59/* RELEASE HISTORY */ 60/* */ 61/* DATE NAME DESCRIPTION */ 62/* */ 63/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ 64/* */ 65/**************************************************************************/ 66/* VOID _tx_thread_schedule(VOID) 67{ */ 68 .global _tx_thread_schedule 69_tx_thread_schedule: 70 71 /* Enable interrupts. */ 72 csrsi mstatus, 0x08 // Enable interrupts 73 74 /* Wait for a thread to execute. */ 75 /* do 76 { */ 77 78 la t0, _tx_thread_execute_ptr // Pickup address of execute ptr 79_tx_thread_schedule_loop: 80 LOAD t1, 0(t0) // Pickup next thread to execute 81 beqz t1, _tx_thread_schedule_loop // If NULL, wait for thread to execute 82 83 /* } 84 while(_tx_thread_execute_ptr == TX_NULL); */ 85 86 /* Yes! We have a thread to execute. Lockout interrupts and 87 transfer control to it. */ 88 csrci mstatus, 0x08 // Lockout interrupts 89 90 /* Setup the current thread pointer. */ 91 /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ 92 93 la t0, _tx_thread_current_ptr // Pickup current thread pointer address 94 STORE t1, 0(t0) // Set current thread pointer 95 96 /* Increment the run count for this thread. */ 97 /* _tx_thread_current_ptr -> tx_thread_run_count++; */ 98 99 LOAD t2, 1*REGBYTES(t1) // Pickup run count 100 LOAD t3, 6*REGBYTES(t1) // Pickup time slice value 101 addi t2, t2, 1 // Increment run count 102 STORE t2, 1*REGBYTES(t1) // Store new run count 103 104 /* Setup time-slice, if present. */ 105 /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ 106 107 la t2, _tx_timer_time_slice // Pickup time-slice variable address 108 109 /* Switch to the thread's stack. */ 110 /* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ 111 112 LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack 113 STORE t3, 0(t2) // Store new time-slice*/ 114 115#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 116 117 call _tx_execution_thread_enter // Call the thread execution enter function 118#endif 119 120 /* Determine if an interrupt frame or a synchronous task suspension frame 121 is present. */ 122 123 LOAD t2, 0(sp) // Pickup stack type 124 beqz t2, _tx_thread_synch_return // If 0, solicited thread return 125 126 /* Determine if floating point registers need to be recovered. */ 127 128#if defined(__riscv_float_abi_single) 129 flw f0, 31*REGBYTES(sp) // Recover ft0 130 flw f1, 32*REGBYTES(sp) // Recover ft1 131 flw f2, 33*REGBYTES(sp) // Recover ft2 132 flw f3, 34*REGBYTES(sp) // Recover ft3 133 flw f4, 35*REGBYTES(sp) // Recover ft4 134 flw f5, 36*REGBYTES(sp) // Recover ft5 135 flw f6, 37*REGBYTES(sp) // Recover ft6 136 flw f7, 38*REGBYTES(sp) // Recover ft7 137 flw f8, 39*REGBYTES(sp) // Recover fs0 138 flw f9, 40*REGBYTES(sp) // Recover fs1 139 flw f10,41*REGBYTES(sp) // Recover fa0 140 flw f11,42*REGBYTES(sp) // Recover fa1 141 flw f12,43*REGBYTES(sp) // Recover fa2 142 flw f13,44*REGBYTES(sp) // Recover fa3 143 flw f14,45*REGBYTES(sp) // Recover fa4 144 flw f15,46*REGBYTES(sp) // Recover fa5 145 flw f16,47*REGBYTES(sp) // Recover fa6 146 flw f17,48*REGBYTES(sp) // Recover fa7 147 flw f18,49*REGBYTES(sp) // Recover fs2 148 flw f19,50*REGBYTES(sp) // Recover fs3 149 flw f20,51*REGBYTES(sp) // Recover fs4 150 flw f21,52*REGBYTES(sp) // Recover fs5 151 flw f22,53*REGBYTES(sp) // Recover fs6 152 flw f23,54*REGBYTES(sp) // Recover fs7 153 flw f24,55*REGBYTES(sp) // Recover fs8 154 flw f25,56*REGBYTES(sp) // Recover fs9 155 flw f26,57*REGBYTES(sp) // Recover fs10 156 flw f27,58*REGBYTES(sp) // Recover fs11 157 flw f28,59*REGBYTES(sp) // Recover ft8 158 flw f29,60*REGBYTES(sp) // Recover ft9 159 flw f30,61*REGBYTES(sp) // Recover ft10 160 flw f31,62*REGBYTES(sp) // Recover ft11 161 LOAD t0, 63*REGBYTES(sp) // Recover fcsr 162 csrw fcsr, t0 // 163#elif defined(__riscv_float_abi_double) 164 fld f0, 31*REGBYTES(sp) // Recover ft0 165 fld f1, 32*REGBYTES(sp) // Recover ft1 166 fld f2, 33*REGBYTES(sp) // Recover ft2 167 fld f3, 34*REGBYTES(sp) // Recover ft3 168 fld f4, 35*REGBYTES(sp) // Recover ft4 169 fld f5, 36*REGBYTES(sp) // Recover ft5 170 fld f6, 37*REGBYTES(sp) // Recover ft6 171 fld f7, 38*REGBYTES(sp) // Recover ft7 172 fld f8, 39*REGBYTES(sp) // Recover fs0 173 fld f9, 40*REGBYTES(sp) // Recover fs1 174 fld f10,41*REGBYTES(sp) // Recover fa0 175 fld f11,42*REGBYTES(sp) // Recover fa1 176 fld f12,43*REGBYTES(sp) // Recover fa2 177 fld f13,44*REGBYTES(sp) // Recover fa3 178 fld f14,45*REGBYTES(sp) // Recover fa4 179 fld f15,46*REGBYTES(sp) // Recover fa5 180 fld f16,47*REGBYTES(sp) // Recover fa6 181 fld f17,48*REGBYTES(sp) // Recover fa7 182 fld f18,49*REGBYTES(sp) // Recover fs2 183 fld f19,50*REGBYTES(sp) // Recover fs3 184 fld f20,51*REGBYTES(sp) // Recover fs4 185 fld f21,52*REGBYTES(sp) // Recover fs5 186 fld f22,53*REGBYTES(sp) // Recover fs6 187 fld f23,54*REGBYTES(sp) // Recover fs7 188 fld f24,55*REGBYTES(sp) // Recover fs8 189 fld f25,56*REGBYTES(sp) // Recover fs9 190 fld f26,57*REGBYTES(sp) // Recover fs10 191 fld f27,58*REGBYTES(sp) // Recover fs11 192 fld f28,59*REGBYTES(sp) // Recover ft8 193 fld f29,60*REGBYTES(sp) // Recover ft9 194 fld f30,61*REGBYTES(sp) // Recover ft10 195 fld f31,62*REGBYTES(sp) // Recover ft11 196 LOAD t0, 63*REGBYTES(sp) // Recover fcsr 197#endif 198 199 /* Recover standard registers. */ 200 201 LOAD t0, 30*REGBYTES(sp) // Recover mepc 202 csrw mepc, t0 // Store mepc 203 li t0, 0x1880 // Prepare MPIP 204 csrw mstatus, t0 // Enable MPIP 205 206 LOAD x1, 28*REGBYTES(sp) // Recover RA 207 LOAD x5, 19*REGBYTES(sp) // Recover t0 208 LOAD x6, 18*REGBYTES(sp) // Recover t1 209 LOAD x7, 17*REGBYTES(sp) // Recover t2 210 LOAD x8, 12*REGBYTES(sp) // Recover s0 211 LOAD x9, 11*REGBYTES(sp) // Recover s1 212 LOAD x10, 27*REGBYTES(sp) // Recover a0 213 LOAD x11, 26*REGBYTES(sp) // Recover a1 214 LOAD x12, 25*REGBYTES(sp) // Recover a2 215 LOAD x13, 24*REGBYTES(sp) // Recover a3 216 LOAD x14, 23*REGBYTES(sp) // Recover a4 217 LOAD x15, 22*REGBYTES(sp) // Recover a5 218 LOAD x16, 21*REGBYTES(sp) // Recover a6 219 LOAD x17, 20*REGBYTES(sp) // Recover a7 220 LOAD x18, 10*REGBYTES(sp) // Recover s2 221 LOAD x19, 9*REGBYTES(sp) // Recover s3 222 LOAD x20, 8*REGBYTES(sp) // Recover s4 223 LOAD x21, 7*REGBYTES(sp) // Recover s5 224 LOAD x22, 6*REGBYTES(sp) // Recover s6 225 LOAD x23, 5*REGBYTES(sp) // Recover s7 226 LOAD x24, 4*REGBYTES(sp) // Recover s8 227 LOAD x25, 3*REGBYTES(sp) // Recover s9 228 LOAD x26, 2*REGBYTES(sp) // Recover s10 229 LOAD x27, 1*REGBYTES(sp) // Recover s11 230 LOAD x28, 16*REGBYTES(sp) // Recover t3 231 LOAD x29, 15*REGBYTES(sp) // Recover t4 232 LOAD x30, 14*REGBYTES(sp) // Recover t5 233 LOAD x31, 13*REGBYTES(sp) // Recover t6 234 235#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) 236 addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point registers 237#else 238 addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point registers 239#endif 240 mret // Return to point of interrupt 241 242_tx_thread_synch_return: 243 244#if defined(__riscv_float_abi_single) 245 flw f8, 15*REGBYTES(sp) // Recover fs0 246 flw f9, 16*REGBYTES(sp) // Recover fs1 247 flw f18,17*REGBYTES(sp) // Recover fs2 248 flw f19,18*REGBYTES(sp) // Recover fs3 249 flw f20,19*REGBYTES(sp) // Recover fs4 250 flw f21,20*REGBYTES(sp) // Recover fs5 251 flw f22,21*REGBYTES(sp) // Recover fs6 252 flw f23,22*REGBYTES(sp) // Recover fs7 253 flw f24,23*REGBYTES(sp) // Recover fs8 254 flw f25,24*REGBYTES(sp) // Recover fs9 255 flw f26,25*REGBYTES(sp) // Recover fs10 256 flw f27,26*REGBYTES(sp) // Recover fs11 257 LOAD t0, 27*REGBYTES(sp) // Recover fcsr 258 csrw fcsr, t0 // 259#elif defined(__riscv_float_abi_double) 260 fld f8, 15*REGBYTES(sp) // Recover fs0 261 fld f9, 16*REGBYTES(sp) // Recover fs1 262 fld f18,17*REGBYTES(sp) // Recover fs2 263 fld f19,18*REGBYTES(sp) // Recover fs3 264 fld f20,19*REGBYTES(sp) // Recover fs4 265 fld f21,20*REGBYTES(sp) // Recover fs5 266 fld f22,21*REGBYTES(sp) // Recover fs6 267 fld f23,22*REGBYTES(sp) // Recover fs7 268 fld f24,23*REGBYTES(sp) // Recover fs8 269 fld f25,24*REGBYTES(sp) // Recover fs9 270 fld f26,25*REGBYTES(sp) // Recover fs10 271 fld f27,26*REGBYTES(sp) // Recover fs11 272 LOAD t0, 27*REGBYTES(sp) // Recover fcsr 273 csrw fcsr, t0 // 274#endif 275 276 /* Recover standard preserved registers. */ 277 /* Recover standard registers. */ 278 279 LOAD x1, 13*REGBYTES(sp) // Recover RA 280 LOAD x8, 12*REGBYTES(sp) // Recover s0 281 LOAD x9, 11*REGBYTES(sp) // Recover s1 282 LOAD x18, 10*REGBYTES(sp) // Recover s2 283 LOAD x19, 9*REGBYTES(sp) // Recover s3 284 LOAD x20, 8*REGBYTES(sp) // Recover s4 285 LOAD x21, 7*REGBYTES(sp) // Recover s5 286 LOAD x22, 6*REGBYTES(sp) // Recover s6 287 LOAD x23, 5*REGBYTES(sp) // Recover s7 288 LOAD x24, 4*REGBYTES(sp) // Recover s8 289 LOAD x25, 3*REGBYTES(sp) // Recover s9 290 LOAD x26, 2*REGBYTES(sp) // Recover s10 291 LOAD x27, 1*REGBYTES(sp) // Recover s11 292 LOAD t0, 14*REGBYTES(sp) // Recover mstatus 293 csrw mstatus, t0 // Store mstatus, enables interrupt 294#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) 295 addi sp, sp, 29*REGBYTES // Recover stack frame 296#else 297 addi sp, sp, 16*REGBYTES // Recover stack frame 298#endif 299 ret // Return to thread 300 301/* } */ 302