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