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