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