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