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    extern __tx_thread_system_state
24    extern __tx_thread_current_ptr
25    extern __tx_thread_preempt_disable
26    extern __tx_thread_execute_ptr
27    extern __tx_timer_time_slice
28    extern __tx_thread_schedule
29
30    section .text:CODE:ROOT
31
32;/**************************************************************************/
33;/*                                                                        */
34;/*  FUNCTION                                               RELEASE        */
35;/*                                                                        */
36;/*    _tx_thread_context_restore                           RXv1/IAR       */
37;/*                                                           6.1.11       */
38;/*  AUTHOR                                                                */
39;/*                                                                        */
40;/*    William E. Lamie, Microsoft Corporation                             */
41;/*                                                                        */
42;/*  DESCRIPTION                                                           */
43;/*                                                                        */
44;/*    This function restores the interrupt context if it is processing a  */
45;/*    nested interrupt.  If not, it returns to the interrupt thread if no */
46;/*    preemption is necessary.  Otherwise, if preemption is necessary or  */
47;/*    if no thread was running, the function returns to the scheduler.    */
48;/*                                                                        */
49;/*  INPUT                                                                 */
50;/*                                                                        */
51;/*    None                                                                */
52;/*                                                                        */
53;/*  OUTPUT                                                                */
54;/*                                                                        */
55;/*    None                                                                */
56;/*                                                                        */
57;/*  CALLS                                                                 */
58;/*                                                                        */
59;/*    _tx_thread_schedule                   Thread scheduling routine     */
60;/*                                                                        */
61;/*  CALLED BY                                                             */
62;/*                                                                        */
63;/*    ISRs                                  Interrupt Service Routines    */
64;/*                                                                        */
65;/*  RELEASE HISTORY                                                       */
66;/*                                                                        */
67;/*    DATE              NAME                      DESCRIPTION             */
68;/*                                                                        */
69;/*  08-02-2021     William E. Lamie         Initial Version 6.1.8         */
70;/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
71;/*                                            removed unnecessary stack   */
72;/*                                            type placement,             */
73;/*                                            resulting in version 6.1.9  */
74;/*  01-31-2022     William E. Lamie         Modified comment(s),          */
75;/*                                            resulting in version 6.1.10 */
76;/*  04-25-2022     William E. Lamie         Modified comment(s),          */
77;/*                                            resulting in version 6.1.11 */
78;/*                                                                        */
79;/**************************************************************************/
80    public __tx_thread_context_restore
81
82__tx_thread_context_restore:
83;
84;    /* Lockout interrupts.  */
85
86     CLRPSW I                                    ; Disable interrupts
87
88;    /* Determine if interrupts are nested.  */
89;    if (--_tx_thread_system_state)
90;    {
91
92     MOV.L    #__tx_thread_system_state, R1
93     MOV.L    [R1], R2
94     SUB      #1, R2
95     MOV.L    R2,[R1]
96     BEQ      __tx_thread_not_nested_restore
97
98;
99;    /* Interrupts are nested.  */
100;
101;    /* Recover the saved registers from the interrupt stack
102;       and return to the point of interrupt.  */
103;
104__tx_thread_nested_restore:
105     POPM    R14-R15                             ; Restore R14-R15
106     POPM    R3-R5                               ; Restore R3-R5
107     POPM    R1-R2                               ; Restore R1-R2
108     RTE                                         ; Return to point of interrupt, restore PSW including IPL
109;    }
110
111__tx_thread_not_nested_restore:
112;
113;    /* Determine if a thread was interrupted and no preemption is required.  */
114;    else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr))
115;               || (_tx_thread_preempt_disable))
116;    {
117
118     MOV.L    #__tx_thread_current_ptr, R1       ; Pickup current thread ptr address
119     MOV.L    [R1], R2
120     CMP      #0, R2
121     BEQ      __tx_thread_idle_system_restore
122
123     MOV.L    #__tx_thread_preempt_disable, R3   ; Pick up preempt disable flag
124     MOV.L    [R3], R3
125     CMP      #0, R3
126     BNE      __tx_thread_no_preempt_restore     ; If pre-empt disable flag set, we simply return to the original point of interrupt regardless
127
128     MOV.L    #__tx_thread_execute_ptr, R3       ; (_tx_thread_current_ptr != _tx_thread_execute_ptr)
129     CMP      [R3], R2
130     BNE      __tx_thread_preempt_restore        ; Jump to pre-empt restoring
131;
132__tx_thread_no_preempt_restore:
133     SETPSW  U                                   ; User stack
134     POPM    R14-R15                             ; Restore R14-R15
135     POPM    R3-R5                               ; Restore R3-R5
136     POPM    R1-R2                               ; Restore R1-R2
137     RTE                                         ; Return to point of interrupt, restore PSW including IPL
138
139;    }
140;    else
141;    {
142
143__tx_thread_preempt_restore:
144
145;    /* Save the remaining time-slice and disable it.  */
146;    if (_tx_timer_time_slice)
147;    {
148
149     MOV.L    #__tx_timer_time_slice, R3         ; Pickup time-slice address
150     MOV.L    [R3],R4                            ; Pickup actual time-slice
151     CMP      #0, R4
152     BEQ      __tx_thread_dont_save_ts           ; No time slice to save
153;
154;        _tx_thread_current_ptr -> tx_thread_time_slice =  _tx_timer_time_slice;
155;        _tx_timer_time_slice =  0;
156;
157     MOV.L    R4,24[R2]                          ; Save thread's time slice
158     MOV.L    #0,R4                              ; Clear value
159     MOV.L    R4,[R3]                            ; Disable global time slice flag
160;    }
161__tx_thread_dont_save_ts:
162;
163;   /* Now store the remaining registers!   */
164
165     SETPSW   U                                  ; User stack
166     PUSHM    R6-R13
167
168     MVFACHI   R5
169     MVFACMI   R6
170     PUSHM     R5-R6
171
172;
173;    /* Clear the current task pointer.  */
174;    _tx_thread_current_ptr =  TX_NULL;
175;    R1 ->  _tx_thread_current_ptr
176;    R2 -> *_tx_thread_current_ptr
177
178     MOV.L   R0,8[R2]                            ; Save thread's stack pointer in thread control block
179     MOV.L   #0,R2                               ; Build NULL value
180     MOV.L   R2,[R1]                             ; Set current thread to NULL
181
182;    /* Return to the scheduler.  */
183;    _tx_thread_schedule();
184
185__tx_thread_idle_system_restore:
186     MVTC    #0, PSW                             ; Reset interrupt priority level to 0
187     BRA     __tx_thread_schedule                ; Jump to scheduler
188;    }
189;
190;}
191;
192    END
193