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