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;/** ThreadX Component                                                     */
16;/**                                                                       */
17;/**   Thread                                                              */
18;/**                                                                       */
19;/**************************************************************************/
20;/**************************************************************************/
21#ifdef TX_INCLUDE_USER_DEFINE_FILE
22#include "tx_user.h"
23#endif
24
25    .equ    BTA, 0x412
26
27;/**************************************************************************/
28;/*                                                                        */
29;/*  FUNCTION                                               RELEASE        */
30;/*                                                                        */
31;/*    _tx_thread_context_save                           ARC_HS/MetaWare   */
32;/*                                                           6.2.1        */
33;/*  AUTHOR                                                                */
34;/*                                                                        */
35;/*    William E. Lamie, Microsoft Corporation                             */
36;/*                                                                        */
37;/*  DESCRIPTION                                                           */
38;/*                                                                        */
39;/*    This function saves the context of an executing thread in the       */
40;/*    beginning of interrupt processing.  The function also ensures that  */
41;/*    the system stack is used upon return to the calling ISR.            */
42;/*                                                                        */
43;/*  INPUT                                                                 */
44;/*                                                                        */
45;/*    None                                                                */
46;/*                                                                        */
47;/*  OUTPUT                                                                */
48;/*                                                                        */
49;/*    None                                                                */
50;/*                                                                        */
51;/*  CALLS                                                                 */
52;/*                                                                        */
53;/*    None                                                                */
54;/*                                                                        */
55;/*  CALLED BY                                                             */
56;/*                                                                        */
57;/*    ISRs                                                                */
58;/*                                                                        */
59;/*  RELEASE HISTORY                                                       */
60;/*                                                                        */
61;/*    DATE              NAME                      DESCRIPTION             */
62;/*                                                                        */
63;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
64;/*  10-15-2021     Andres Mlinar            Modified comment(s), and      */
65;/*                                            r25/r30 are caller saved,   */
66;/*                                            resulting in version 6.1.9  */
67;/*  03-08-2023     Cindy Deng               Modified comment(s), added    */
68;/*                                            #include tx_user.h,         */
69;/*                                            resulting in version 6.2.1  */
70;/*                                                                        */
71;/**************************************************************************/
72;VOID   _tx_thread_context_save(VOID)
73;{
74    .global _tx_thread_context_save
75    .type   _tx_thread_context_save, @function
76_tx_thread_context_save:
77;
78;    /* Upon entry to this routine, it is assumed that an interrupt stack frame
79;       has already been allocated, and the interrupted blink register is already saved.  */
80;
81    clri                                                ; Disable interrupts
82    st      r1, [sp, 128]                               ; Save r1
83    st      r0, [sp, 132]                               ; Save r0
84;
85;    /* Check for a nested interrupt condition.  */
86;    if (_tx_thread_system_state++)
87;    {
88;
89    ld      r0, [gp, _tx_thread_system_state@sda]       ; Pickup system state
90    st      r3, [sp, 120]                               ; Save r3
91    st      r2, [sp, 124]                               ; Save r2
92    breq    r0, 0, __tx_thread_not_nested_save          ; If 0, we are not in a nested
93                                                        ;   condition
94;
95;    /* Nested interrupt condition.  */
96;
97    add     r0, r0, 1                                   ; Increment the nested interrupt count
98    st      r0, [gp, _tx_thread_system_state@sda]       ; Update system state
99;
100;   /* Save the rest of the scratch registers on the stack and return to the
101;      calling ISR.  */
102;
103__tx_thread_nested_save:                                ; Label is for special nested interrupt case from idle system save below
104    st      r30, [sp, 136]                              ; Save r30
105    st      r25, [sp, 32]                               ; Save r25
106    st      r12, [sp, 84]                               ; Save r12
107    st      r11, [sp, 88]                               ; Save r11
108    st      r10, [sp, 92]                               ; Save r10
109    st      r9,  [sp, 96]                               ; Save r9
110    st      r8,  [sp, 100]                              ; Save r8
111    st      r7,  [sp, 104]                              ; Save r7
112    st      r6,  [sp, 108]                              ; Save r6
113    st      r5,  [sp, 112]                              ; Save r5
114    st      r4,  [sp, 116]                              ; Save r4
115    lr      r10, [LP_START]                             ; Pickup LP_START
116    lr      r9,  [LP_END]                               ; Pickup LP_END
117    st      LP_COUNT, [sp, 12]                          ; Save LP_COUNT
118    st      r10, [sp, 4]                                ; Save LP_START
119    st      r9,  [sp, 8]                                ; Save LP_END
120    .ifdef   TX_ENABLE_ACC
121    st      r58, [sp, 140]                              ; Save r58
122    st      r59, [sp, 144]                              ; Save r59
123    .endif
124    lr      r0,  [BTA]                                  ; Pickup BTA
125    st      r0,  [sp, 156]                              ; Save BTA
126
127;
128;    /* Return to the ISR.  */
129;
130    .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
131;
132;    /* Call the ISR enter function to indicate an ISR is executing.  */
133;
134    sub     sp, sp, 32                                  ; Allocating some space on the stack
135    st      blink, [sp, 16]                             ; Save blink
136    bl.d    _tx_execution_isr_enter                     ; Call the ISR enter function
137    nop                                                 ; Delay slot
138    ld      blink, [sp, 16]                             ; Recover blink
139    add     sp, sp, 32                                  ; Recover the stack space
140    .endif
141;
142
143    j.d     [blink]                                     ; Return to Level 1 ISR
144    st      ilink, [sp, 20]                             ; Save ilink
145;
146__tx_thread_not_nested_save:
147;    }
148;
149;    /* Otherwise, not nested, check to see if a thread was running.  */
150;    else if (_tx_thread_current_ptr)
151;    {
152;
153    add     r0, r0, 1                                   ; Increment the nested interrupt count
154    st      r0, [gp, _tx_thread_system_state@sda]       ; Update system state
155    ld      r1, [gp, _tx_thread_current_ptr@sda]        ; Pickup current thread pointer
156    st      r30, [sp, 136]                              ; Save r30
157    st      r25, [sp, 32]                               ; Save r25
158    st      r12, [sp, 84]                               ; Save r12
159    st      r11, [sp, 88]                               ; Save r11
160    breq    r1, 0, __tx_thread_idle_system_save         ; If no thread is running, idle system was
161                                                        ;   interrupted.
162;
163;    /* Save minimal context of interrupted thread.  */
164;
165    st      r10, [sp, 92]                               ; Save r10
166    st      r9,  [sp, 96]                               ; Save r9
167    st      r8,  [sp, 100]                              ; Save r8
168    st      r7,  [sp, 104]                              ; Save r7
169    st      r6,  [sp, 108]                              ; Save r6
170    st      r5,  [sp, 112]                              ; Save r5
171    st      r4,  [sp, 116]                              ; Save r4
172    lr      r10, [LP_START]                             ; Pickup LP_START
173    lr      r9,  [LP_END]                               ; Pickup LP_END
174    st      LP_COUNT, [sp, 12]                          ; Save LP_COUNT
175    st      r10, [sp, 4]                                ; Save LP_START
176    st      r9,  [sp, 8]                                ; Save LP_END
177    st      ilink, [sp, 20]                             ; Save ilink
178    .ifdef   TX_ENABLE_ACC
179    st      r58, [sp, 140]                              ; Save r58
180    st      r59, [sp, 144]                              ; Save r59
181    .endif
182    lr      r0,  [BTA]                                  ; Pickup BTA
183    st      r0,  [sp, 156]                              ; Save BTA
184;
185;    /* Save the current stack pointer in the thread's control block.  */
186;    _tx_thread_current_ptr -> tx_thread_stack_ptr =  sp;
187;
188    st      sp, [r1, 8]                                 ; Save thread's stack pointer
189
190    .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
191;
192;    /* Call the ISR enter function to indicate an ISR is executing.  */
193;
194    sub     sp, sp, 32                                  ; Allocating some space on the stack
195    st      blink, [sp, 16]                             ; Save blink
196    bl.d    _tx_execution_isr_enter                     ; Call the ISR enter function
197    nop                                                 ; Delay slot
198    ld      blink, [sp, 16]                             ; Recover blink
199    add     sp, sp, 32                                  ; Recover the stack space
200    .endif
201
202;
203;    /* Switch to the system stack.  */
204;    sp =  _tx_thread_system_stack_ptr;
205;
206    j_s.d   [blink]                                     ; Return to calling ISR
207    ld      sp, [gp, _tx_thread_system_stack_ptr@sda]   ; Switch to system stack
208;
209;    }
210;    else
211;    {
212;
213__tx_thread_idle_system_save:
214;
215;    /* Interrupt occurred in the scheduling loop.  */
216;
217    .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
218;
219;    /* Call the ISR enter function to indicate an ISR is executing.  */
220;
221    sub     sp, sp, 32                                  ; Allocating some space on the stack
222    st      blink, [sp, 16]                             ; Save blink
223    bl.d    _tx_execution_isr_enter                     ; Call the ISR enter function
224    nop                                                 ; Delay slot
225    ld      blink, [sp, 16]                             ; Recover blink
226    add     sp, sp, 32                                  ; Recover the stack space
227    .endif
228;
229;     /* See if we have a special nesting condition.  This happens when the higher priority
230;        interrupt occurs before the nested interrupt logic is valid.  */
231;
232    lr      r0, [AUX_IRQ_ACT]                           ; Pickup the interrupt active register
233    neg     r1, r0                                      ; Negate
234    and     r1, r0, r1                                  ; See if there are any other interrupts present
235    brne    r0, r1, __tx_thread_nested_save             ; If more interrupts, go into the nested interrupt save logic
236;
237;    /* Not much to do here, just adjust the stack pointer, and return to
238;       ISR processing.  */
239;
240    j_s.d   [blink]                                     ; Return to ISR
241    add     sp, sp, 160                                 ; Recover stack space
242;
243;    }
244;}
245    .end
246