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;/**                                                                       */
16;/** ThreadX Component                                                     */
17;/**                                                                       */
18;/**   Thread                                                              */
19;/**                                                                       */
20;/**************************************************************************/
21;/**************************************************************************/
22
23    .global     __tx_thread_system_state
24    .global     __tx_thread_current_ptr
25    .global     __tx_thread_system_stack_ptr
26
27    .text
28;/**************************************************************************/
29;/*                                                                        */
30;/*  FUNCTION                                               RELEASE        */
31;/*                                                                        */
32;/*    _tx_thread_context_save                              RXv1/GNURX     */
33;/*                                                           6.1.11       */
34;/*  AUTHOR                                                                */
35;/*                                                                        */
36;/*    William E. Lamie, Microsoft Corporation                             */
37;/*                                                                        */
38;/*  DESCRIPTION                                                           */
39;/*                                                                        */
40;/*    This function saves the context of an executing thread in the       */
41;/*    beginning of interrupt processing.  The function also ensures that  */
42;/*    the system stack is used upon return to the calling ISR.            */
43;/*                                                                        */
44;/*  INPUT                                                                 */
45;/*                                                                        */
46;/*    None                                                                */
47;/*                                                                        */
48;/*  OUTPUT                                                                */
49;/*                                                                        */
50;/*    None                                                                */
51;/*                                                                        */
52;/*  CALLS                                                                 */
53;/*                                                                        */
54;/*    None                                                                */
55;/*                                                                        */
56;/*  CALLED BY                                                             */
57;/*                                                                        */
58;/*    ISRs                                                                */
59;/*                                                                        */
60;/*  RELEASE HISTORY                                                       */
61;/*                                                                        */
62;/*    DATE              NAME                      DESCRIPTION             */
63;/*                                                                        */
64;/*  08-02-2021     William E. Lamie         Initial Version 6.1.8         */
65;/*  10-15-2021     William E. Lamie         Modified comment(s),          */
66;/*                                            resulting in version 6.1.9  */
67;/*  01-31-2022     William E. Lamie         Modified comment(s),          */
68;/*                                            resulting in version 6.1.10 */
69;/*  04-25-2022     William E. Lamie         Modified comment(s),          */
70;/*                                            resulting in version 6.1.11 */
71;/*                                                                        */
72;/**************************************************************************/
73;VOID   _tx_thread_context_save(VOID)
74;{
75    .global __tx_thread_context_save
76__tx_thread_context_save:
77;
78;    /* Upon entry to this routine, it is assumed that interrupts are locked
79;       out and the (interrupt) stack frame looks like the following:
80;
81;           (lower address) SP   ->     [return address of this call]
82;                           SP+4 ->     Saved R1
83;                           SP+8 ->     Saved R2
84;                           SP+12->     Interrupted PC
85;                           SP+16->     Interrupted PSW
86;
87;    /* Check for a nested interrupt condition.  */
88;    if (_tx_thread_system_state++)
89;    {
90;
91
92    MOV.L   #__tx_thread_system_state, R1        ; Pick up address of system state
93    MOV.L   [R1], R2                             ; Pick up system state
94    CMP     #0, R2                               ; 0 -> no nesting
95    BEQ     __tx_thread_not_nested_save
96;
97;    /* Nested interrupt condition.  */
98;
99    ADD   #1, r2                                 ; _tx_thread_system_state++
100    MOV.L   r2, [r1]
101
102;
103;   /* Save the rest of the scratch registers on the interrupt stack and return to the
104;       calling ISR.  */
105    POP R1                                       ; Recuperate return address from stack
106    PUSHM   R3-R5
107    PUSHM   R14-R15
108    JMP     R1                                   ; Return address was preserved in R1
109
110;
111__tx_thread_not_nested_save:
112;    }
113;
114;    /* Otherwise, not nested, check to see if a thread was running.  */
115;    else if (_tx_thread_current_ptr)
116;    {
117;
118    ADD     #1, R2                               ; _tx_thread_system_state++
119    MOV.L   R2, [R1]
120
121    MOV.L   #__tx_thread_current_ptr, R2         ; Pickup current thread pointer
122    MOV.L   [R2], R2
123    CMP     #0,R2                                ; Is it NULL?
124    BEQ      __tx_thread_idle_system_save        ; Yes, idle system is running - idle restore
125;
126;    /* Move stack frame over to the current threads stack.  */
127;    /* complete stack frame with registers not saved yet (R3-R5, R14-R15, FPSW)   */
128;
129    MVFC    USP, R1                              ; Pick up user stack pointer
130    MOV.L   16[R0], R2
131    MOV.L   R2, [-R1]                            ; Save PSW on thread stack
132    MOV.L   12[R0], R2
133    MOV.L   R2, [-R1]                            ; Save PC on thread stack
134    MOV.L   8[R0], R2
135    MOV.L   R2, [-R1]                            ; Save R2 on thread stack
136    MOV.L   4[R0], R2
137    MOV.L   R2, [-R1]                            ; Save R1 on thread stack
138    MOV.L   R5, [-R1]                            ; Save R5 on thread stack
139    MOV.L   R4, [-R1]                            ; Save R4 on thread stack
140    MOV.L   R3, [-R1]                            ; Save R3 on thread stack
141    MOV.L   R15, [-R1]                           ; Save R15 on thread stack
142    MOV.L   R14, [-R1]                           ; Save R14 on thread stack
143
144    POP     R2                                   ; Pick up return address from interrupt stack
145    ADD     #16, R0, R0                          ; Correct interrupt stack pointer back to the bottom
146    MVTC    R1, USP                              ; Set user/thread stack pointer
147    JMP     R2                                   ; Return to ISR
148
149;    }
150;    else
151;    {
152;
153__tx_thread_idle_system_save:
154;
155;        /* Interrupt occurred in the scheduling loop.  */
156;
157    POP     R1                                   ; Pick up return address
158    ADD     #16, R0, R0                          ; Correct interrupt stack pointer back to the bottom (PC), don't care about saved registers
159    JMP     R1                                   ; Return to caller
160;
161;    }
162;}
163    .end
164