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;
33    .GLB     __tx_thread_system_state
34    .GLB     __tx_thread_current_ptr
35    .GLB     __tx_thread_system_stack_ptr
36    .GLB     __tx_thread_execute_ptr
37    .GLB     __tx_timer_time_slice
38    .GLB     __tx_thread_schedule
39    .GLB     __tx_thread_preempt_disable
40;
41    .SECTION    P,CODE
42;/**************************************************************************/
43;/*                                                                        */
44;/*  FUNCTION                                               RELEASE        */
45;/*                                                                        */
46;/*    _tx_thread_context_restore                           RXv1/CCRX      */
47;/*                                                           6.1.11       */
48;/*  AUTHOR                                                                */
49;/*                                                                        */
50;/*    William E. Lamie, Microsoft Corporation                             */
51;/*                                                                        */
52;/*  DESCRIPTION                                                           */
53;/*                                                                        */
54;/*    This function restores the interrupt context if it is processing a  */
55;/*    nested interrupt.  If not, it returns to the interrupt thread if no */
56;/*    preemption is necessary.  Otherwise, if preemption is necessary or  */
57;/*    if no thread was running, the function returns to the scheduler.    */
58;/*                                                                        */
59;/*  INPUT                                                                 */
60;/*                                                                        */
61;/*    None                                                                */
62;/*                                                                        */
63;/*  OUTPUT                                                                */
64;/*                                                                        */
65;/*    None                                                                */
66;/*                                                                        */
67;/*  CALLS                                                                 */
68;/*                                                                        */
69;/*    _tx_thread_schedule                   Thread scheduling routine     */
70;/*                                                                        */
71;/*  CALLED BY                                                             */
72;/*                                                                        */
73;/*    ISRs                                  Interrupt Service Routines    */
74;/*                                                                        */
75;/*  RELEASE HISTORY                                                       */
76;/*                                                                        */
77;/*    DATE              NAME                      DESCRIPTION             */
78;/*                                                                        */
79;/*  08-02-2021     William E. Lamie         Initial Version 6.1.8         */
80;/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
81;/*                                            removed unnecessary stack   */
82;/*                                            type placement,             */
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;VOID   _tx_thread_context_restore(VOID)
91;{
92    .GLB __tx_thread_context_restore
93__tx_thread_context_restore:
94;
95;    /* Lockout interrupts.  */
96
97     CLRPSW I                                    ; Disable interrupts
98
99;    /* Determine if interrupts are nested.  */
100;    if (--_tx_thread_system_state)
101;    {
102
103     MOV.L    #__tx_thread_system_state, R1
104     MOV.L    [R1], R2
105     SUB      #1, R2
106     MOV.L    R2,[R1]
107     BEQ      __tx_thread_not_nested_restore
108
109;
110;    /* Interrupts are nested.  */
111;
112;    /* Recover the saved registers from the interrupt stack
113;       and return to the point of interrupt.  */
114;
115__tx_thread_nested_restore:
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     POPM    R14-R15                             ; Restore R14-R15
146     POPM    R3-R5                               ; Restore R3-R5
147     POPM    R1-R2                               ; Restore R1-R2
148     RTE                                         ; Return to point of interrupt, restore PSW including IPL
149
150;    }
151;    else
152;    {
153
154__tx_thread_preempt_restore:
155
156;    /* Save the remaining time-slice and disable it.  */
157;    if (_tx_timer_time_slice)
158;    {
159
160     MOV.L    #__tx_timer_time_slice, R3         ; Pickup time-slice address
161     MOV.L    [R3],R4                            ; Pickup actual time-slice
162     CMP      #0, R4
163     BEQ      __tx_thread_dont_save_ts           ; No time slice to save
164;
165;        _tx_thread_current_ptr -> tx_thread_time_slice =  _tx_timer_time_slice;
166;        _tx_timer_time_slice =  0;
167;
168     MOV.L    R4,24[R2]                          ; Save thread's time slice
169     MOV.L    #0,R4                              ; Clear value
170     MOV.L    R4,[R3]                            ; Disable global time slice flag
171;    }
172__tx_thread_dont_save_ts:
173;
174;   /* Now store the remaining registers!   */
175
176     SETPSW   U                                  ; User stack
177     PUSHM    R6-R13
178
179     MVFACHI   R5
180     MVFACMI   R6
181     PUSHM     R5-R6
182
183;
184;    /* Clear the current task pointer.  */
185;    _tx_thread_current_ptr =  TX_NULL;
186;    R1 ->  _tx_thread_current_ptr
187;    R2 -> *_tx_thread_current_ptr
188
189     MOV.L   R0,8[R2]                            ; Save thread's stack pointer in thread control block
190     MOV.L   #0,R2                               ; Build NULL value
191     MOV.L   R2,[R1]                             ; Set current thread to NULL
192
193;    /* Return to the scheduler.  */
194;    _tx_thread_schedule();
195
196__tx_thread_idle_system_restore:
197     MVTC    #0, PSW                             ; Reset interrupt priority level to 0
198     BRA     __tx_thread_schedule                ; Jump to scheduler
199;    }
200;
201;}
202;
203    .END
204