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