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/* Copyright (c) Cadence Design Systems, Inc. */ 14/* */ 15/* Permission is hereby granted, free of charge, to any person obtaining */ 16/* a copy of this software and associated documentation files (the */ 17/* "Software"), to deal in the Software without restriction, including */ 18/* without limitation the rights to use, copy, modify, merge, publish, */ 19/* distribute, sublicense, and/or sell copies of the Software, and to */ 20/* permit persons to whom the Software is furnished to do so, subject to */ 21/* the following conditions: */ 22/* */ 23/* The above copyright notice and this permission notice shall be */ 24/* included in all copies or substantial portions of the Software. */ 25/* */ 26/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 27/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 28/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 29/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 30/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 31/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 32/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 33/**************************************************************************/ 34 35/**************************************************************************/ 36/**************************************************************************/ 37/** */ 38/** ThreadX Component */ 39/** */ 40/** Thread */ 41/** */ 42/**************************************************************************/ 43/**************************************************************************/ 44 45 46#include "xtensa_rtos.h" 47#include "tx_api_asm.h" 48 49 50#if XCHAL_HAVE_XEA2 51 52 .text 53 54/**************************************************************************/ 55/* */ 56/* DESCRIPTION */ 57/* */ 58/* This function restores the interrupt context if it is processing a */ 59/* nested interrupt. If not, it returns to the interrupt thread if no */ 60/* preemption is necessary. Otherwise, if preemption is necessary or */ 61/* if no thread was running, the function returns to the scheduler. */ 62/* */ 63/* RELEASE HISTORY */ 64/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */ 65/* 10-31-2022 Scott Larson Updated EPK definitions, */ 66/* resulting in version 6.2.0 */ 67/* */ 68/**************************************************************************/ 69 70// VOID _tx_thread_context_restore(VOID) 71// { 72 .globl _tx_thread_context_restore 73 .type _tx_thread_context_restore,@function 74 .align 4 75_tx_thread_context_restore: 76 77 /* 78 Please note: Control flow might seem strange. This is because it has been 79 optimized to avoid taken branches in the longest normal path (the critical 80 one for worst-case latency), presumed to be a non-nested interrupt that 81 preempts) and to hide pipeline interlock cycles where possible. 82 */ 83 84 /* Lockout interrupts. */ 85 XT_INTS_DISABLE(a0) 86 87 #if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 88 /* Call the ISR exit function to indicate an ISR is complete. */ 89 #ifdef __XTENSA_CALL0_ABI__ 90 call0 _tx_execution_isr_exit 91 #else 92 call8 _tx_execution_isr_exit 93 #endif 94 #endif 95 96 /* Determine if interrupts are nested. */ 97 // if (--_tx_thread_system_state) 98 // { 99 100 movi a2, _tx_thread_system_state /* a2 = & interrupt nesting count */ 101 l32i a3, a2, 0 /* decrement interrupt nesting count */ 102 addi a3, a3, -1 103 s32i a3, a2, 0 104 bnez a3, .L_tx_thread_nested_restore 105 106 // } 107 108.Ln_tx_thread_not_nested_restore: 109 110 /* Determine if a thread was interrupted and no preemption is required. */ 111 // else if (((_tx_thread_current_ptr) 112 // && (_tx_thread_current_ptr == _tx_thread_execute_ptr)) 113 // || (_tx_thread_preempt_disable)) 114 // { 115 116 movi a0, _tx_thread_current_ptr /* a0 = &_tx_thread_current_ptr */ 117 l32i a2, a0, 0 /* a2 = _tx_thread_current_ptr (old) */ 118 movi a3, _tx_thread_execute_ptr 119 beqz a2, .L_tx_thread_idle_system_restore 120 121 l32i a3, a3, 0 /* a3 = _tx_thread_execute_ptr (new) */ 122 beq a3, a2, .L_tx_thread_no_preempt_restore 123 124 movi a3, _tx_thread_preempt_disable 125 l32i a3, a3, 0 /* a3 = _tx_thread_preempt_disable */ 126 127 // /* the no-preempt case has moved down so we fall-thru to preempt */ 128 bgei a3, 1, .L_tx_thread_no_preempt_restore 129 130 // } 131 // else 132 // { 133 134.Ln_tx_thread_preempt_restore: 135 136 /* Save remaining context on the thread's stack. */ 137 l32i a3, a2, tx_thread_stack_ptr /* a3 = thread's stack ptr */ 138 139 /* Store standard preserved registers. */ 140 /* 141 Call0 ABI callee-saved regs a12-15 need to be saved before preemption. 142 However a12-13 were saved for scratch by _tx_thread_context_save(). 143 */ 144 #ifdef __XTENSA_CALL0_ABI__ /* Call0: now save callee-save regs */ 145 s32i a14, a3, XT_STK_A14 146 s32i a15, a3, XT_STK_A15 147 #endif 148 149 /* Save the remaining time-slice and disable it. */ 150 // if (_tx_timer_time_slice) 151 // { 152 movi a3, _tx_timer_time_slice /* a3 = &_tx_timer_time_slice */ 153 l32i a4, a3, 0 /* a4 = _tx_timer_time_slice */ 154 beqz a4, .L_tx_thread_dont_save_ts 155 156 // _tx_thread_current_ptr -> tx_thread_time_slice 157 // = _tx_timer_time_slice; 158 // _tx_timer_time_slice = 0; */ 159 s32i a4, a2, tx_thread_time_slice 160 movi a4, 0 161 s32i a4, a3, 0 162 163 // } 164 165.L_tx_thread_dont_save_ts: 166 167 /* Clear the current task pointer. */ 168 // _tx_thread_current_ptr = TX_NULL; 169 s32i a4, a0, 0 /* a4 == 0 == TX_NULL */ 170 171 #if XCHAL_CP_NUM > 0 172 /* Save CPENABLE in thread's co-processor save area, and clear CPENABLE. */ 173 rsr a3, CPENABLE 174 s16i a3, a2, tx_thread_cp_state + XT_CPENABLE 175 wsr a4, CPENABLE /* disable all co-processors */ 176 #endif 177 178.L_tx_thread_idle_system_restore: 179 180 /* 181 Return via the scheduler. 182 Scheduler returns eventually to this function's caller as if called by it. 183 At this point we are still on the system stack. 184 */ 185 // _tx_thread_schedule(); 186 call0 _tx_thread_schedule /* never returns here */ 187 188 // } 189 190 /* Flow never falls through here. */ 191 192.L_tx_thread_no_preempt_restore: 193 194 /* Restore interrupted thread. */ 195 196 /* Pickup the saved stack pointer. */ 197 // SP = _tx_thread_current_ptr -> tx_thread_stack_ptr; 198 l32i sp, a2, tx_thread_stack_ptr 199 200.L_tx_thread_nested_restore: 201 202 /* Recover the saved context and return to the point of interrupt. */ 203 204 call0 _xt_context_restore 205 206 /* 207 Must return via the exit dispatcher corresponding to the entrypoint 208 from which this was called. Interruptee's A0, A1, PS, PC are restored 209 and the interrupt stack frame is deallocated in the exit dispatcher. 210 At this point we are on the thread's stack. 211 */ 212 l32i a0, sp, XT_STK_EXIT 213 ret 214 215// } 216 217#endif /* XCHAL_HAVE_XEA2 */ 218 219