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