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