summaryrefslogtreecommitdiff
path: root/ports/arc_hs/metaware/src/tx_thread_context_fast_restore.s
blob: d2f5284cf416eb4c57d399868920c2b7eab23940 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * https://opensource.org/licenses/MIT.
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/**                                                                       */
;/** ThreadX Component                                                     */
;/**                                                                       */
;/**   Thread                                                              */
;/**                                                                       */
;/**************************************************************************/
;/**************************************************************************/
#ifdef TX_INCLUDE_USER_DEFINE_FILE
#include "tx_user.h"
#endif

    .equ    BTA, 0x412

;/**************************************************************************/
;/*                                                                        */
;/*  FUNCTION                                               RELEASE        */
;/*                                                                        */
;/*    _tx_thread_context_fast_restore                   ARC_HS/MetaWare   */
;/*                                                           6.2.1        */
;/*  AUTHOR                                                                */
;/*                                                                        */
;/*    William E. Lamie, Microsoft Corporation                             */
;/*                                                                        */
;/*  DESCRIPTION                                                           */
;/*                                                                        */
;/*    This function restores the fast interrupt context, which can be a   */
;/*    nesting condition on a non-fast ISR, an idle system restore, a      */
;/*    restore of an interrupted thread, and a preemption of an interrupted*/
;/*    thread.                                                             */
;/*                                                                        */
;/*  INPUT                                                                 */
;/*                                                                        */
;/*    None                                                                */
;/*                                                                        */
;/*  OUTPUT                                                                */
;/*                                                                        */
;/*    None                                                                */
;/*                                                                        */
;/*  CALLS                                                                 */
;/*                                                                        */
;/*    _tx_thread_schedule                   Thread scheduling routine     */
;/*                                                                        */
;/*  CALLED BY                                                             */
;/*                                                                        */
;/*    ISRs                                  Interrupt Service Routines    */
;/*                                                                        */
;/**************************************************************************/
;VOID   _tx_thread_context_fast_restore(VOID)
;{

    .global _tx_thread_context_fast_restore
    .type   _tx_thread_context_fast_restore, @function
_tx_thread_context_fast_restore:
;
;    /* Note: it is assumed that the stack pointer is in the same position now as
;       it was after the last context fast save call.  */
;

    .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
;    /* Call the ISR exit function to indicate an ISR is complete.  */
;
    bl.d    _tx_execution_isr_exit                      ; Call the ISR exit function
    sub     sp, sp, 16                                  ; ..allocating some space on the stack
    add     sp, sp, 16                                  ; Recover the stack space
    .endif
;
;    /* Determine if interrupts are nested.  */
;    if (--_tx_thread_system_state)
;    {
;
    ld      r0, [gp, _tx_thread_system_state@sda]       ; Pickup system state contents
    sub     r0, r0, 1                                   ; Decrement the system state
    st      r0, [gp, _tx_thread_system_state@sda]       ; Store the new system state
    breq    r0, 0, __tx_thread_not_nested_restore       ; If zero, not a nested interrupt
;
;    /* Interrupts are nested.  */
;
;    /* Just recover the saved registers and return to the point of
;       interrupt.  */
;

__tx_thread_nested_restore:
    rtie                                                ; Return from interrupt
;
;
;    }
__tx_thread_not_nested_restore:
;
;    /* Determine if a thread was interrupted and no preemption is required.  */
;    else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr))
;               || (_tx_thread_preempt_disable))
;    {
;
    ld      r0, [gp, _tx_thread_current_ptr@sda]        ; Pickup current thread pointer
    ld      r2, [gp, _tx_thread_preempt_disable@sda]    ; Pickup preempt disable flag
    sub.f   0, r0, 0                                    ; Set condition codes
    beq.d   __tx_thread_idle_system_restore             ; If NULL, idle system was interrupted
    lr      r4, [AUX_IRQ_ACT]                           ; Pickup the interrupt active register
    neg     r5, r4                                      ; Negate
    and     r5, r4, r5                                  ; See if there are any other interrupts present
    brne.d  r4, r5, __tx_thread_no_preempt_restore      ; If more interrupts, just return to the point of interrupt
    ld      r4, [gp, _tx_thread_execute_ptr@sda]        ; Pickup next thread to execute
    brne    r2, 0, __tx_thread_no_preempt_restore       ; If set, don't preempt executing thread
    brne    r0, r4, __tx_thread_preempt_restore         ; Not equal, preempt executing thread
;
;
__tx_thread_no_preempt_restore:
;
;    /* Restore interrupted thread or ISR.  */
;
;    /* Pickup the saved stack pointer.  */
;    sp =  _tx_thread_current_ptr -> tx_thread_stack_ptr;
;
;   /* Return to the point of interrupt.  */
;
    rtie                                                ; Return from interrupt
;
;    }
;    else
;    {
__tx_thread_preempt_restore:
;
    lr      r3, [status32_p0]                           ; Pickup the interrupted status32.p0 register
    lsr     r4, r3, 16                                  ; Move the register bank bits down
    and     r4, r4, 7                                   ; Isolate the register bank
    breq    r4, 0, __tx_software_interrupt_context      ; If register bank 0, software interrupt context is present
    st      ilink, [sp, 0]                              ; Save ilink (point of interrupt)
    st      r3, [sp, 4]                                 ; Save actual status32.p0
    bclr    r4, r3, 16                                  ; Build register bank 0 value
    bclr    r4, r4, 17                                  ;
    bclr    r4, r4, 18                                  ;
    sr      r4, [status32_p0]                           ; Setup status32.p0 to return to bank 0 when fast ISR is finishe
    mov     ilink, sp                                   ; Pass the information back to the other register bank via ilink
    bclr    r3, r3, 31                                  ; Make sure interrupts are not enabled
    kflag   r3                                          ; Switch back to the interrupted thread's hardware register bank
    sub     sp, sp, 168                                 ; Allocate an hardware interrupt stack frame
    st      r0, [sp, 132]                               ; Temporarily save r0
    mov     r0, 3                                       ; Build hardware interrupt stack type
    st      r0,  [sp, 0]                                ; Setup interrupt stack type

    .ifndef  TX_DISABLE_LP
    lr      r0, [LP_START]                              ; Pickup LP_START
    st      r0, [sp, 4]                                 ; Save LP_START
    lr      r0, [LP_END]                                ; Pickup LP_END
    st      r0, [sp, 8]                                 ; Save LP_END
    st      LP_COUNT, [sp, 12]                          ; Save LP_COUNT
    .endif

    lr      r0, [BTA]                                   ; Pickup BTA
    st      r0, [sp, 156]                               ; Save BTA
    ld      r0, [ilink, 0]                              ; Pickup the point of interrupt
    st      r0, [sp, 160]                               ; Setup the point of interrupt
    st      r0, [sp, 20]                                ; Save ilink
    ld      r0, [ilink, 4]                              ; Pickup the status32
    st      r0, [sp, 164]                               ; Setup the status32
    ld      r0, [gp, _tx_thread_current_ptr@sda]        ; Pickup current thread pointer
    st      sp, [r0, 8]                                 ; Save stack pointer in thread control block
    ld      r0, [sp, 132]                               ; Restore r0
    lr      ilink, [status32]                           ; Pickup status32 register
    bset    ilink, ilink, 16                            ; Build register bank 1 value
    bclr    ilink, ilink, 17                            ;
    bclr    ilink, ilink, 18                            ;
    kflag   ilink                                       ; Move back to register bank 0
    b       __tx_preempt_save_done                      ; Done, finished with preemption save

__tx_software_interrupt_context:
    st      ilink, [sp, 0]                              ; Save ilink (point of interrupt)
    st      r3, [sp, 4]                                 ; Save status32
    mov     ilink, sp                                   ; Pass the information back to the other register bank via ilink
    bclr    r3, r3, 31                                  ; Make sure interrupts are not enabled
    kflag   r3                                          ; Switch back to the interrupted thread's hardware register bank
    sub     sp, sp, 168                                 ; Allocate an hardware interrupt stack frame
    st      blink, [sp, 16]                             ; Save blink
    st      fp,  [sp, 24]                               ; Save fp
    st      gp,  [sp, 28]                               ; Save gp
    st      r25, [sp, 32]                               ; Save r25
    st      r24, [sp, 36]                               ; Save r24
    st      r23, [sp, 40]                               ; Save r23
    st      r22, [sp, 44]                               ; Save r22
    st      r21, [sp, 48]                               ; Save r21
    st      r20, [sp, 52]                               ; Save r20
    st      r19, [sp, 56]                               ; Save r19
    st      r18, [sp, 60]                               ; Save r18
    st      r17, [sp, 64]                               ; Save r17
    st      r16, [sp, 68]                               ; Save r16
    st      r15, [sp, 72]                               ; Save r15
    st      r14, [sp, 76]                               ; Save r14
    st      r13, [sp, 80]                               ; Save r13
    st      r12, [sp, 84]                               ; Save r12
    st      r11, [sp, 88]                               ; Save r11
    st      r10, [sp, 92]                               ; Save r10
    st      r9,  [sp, 96]                               ; Save r9
    st      r8,  [sp, 100]                              ; Save r8
    st      r7,  [sp, 104]                              ; Save r7
    st      r6,  [sp, 108]                              ; Save r6
    st      r5,  [sp, 112]                              ; Save r5
    st      r4,  [sp, 116]                              ; Save r6
    st      r3,  [sp, 120]                              ; Save r3
    st      r2,  [sp, 124]                              ; Save r2
    st      r1,  [sp, 128]                              ; Save r1
    st      r0,  [sp, 132]                              ; Save r0
    st      r30, [sp, 136]                              ; Save r30

    .ifndef  TX_DISABLE_LP
    lr      r10, [LP_START]                             ; Pickup LP_START
    lr      r9,  [LP_END]                               ; Pickup LP_END
    st      LP_COUNT, [sp, 12]                          ; Save LP_COUNT
    st      r10, [sp, 4]                                ; Save LP_START
    st      r9,  [sp, 8]                                ; Save LP_END
    .endif

    lr      r0,  [BTA]                                  ; Pickup BTA
    st      r0,  [sp, 156]                              ; Save BTA
    mov     r6, 1                                       ; Build interrupt stack type
    st      r6,  [sp, 0]                                ; Setup interrupt stack type
    ld      r0, [ilink, 0]                              ; Pickup the point of interrupt
    st      r0, [sp, 160]                               ; Setup the point of interrupt
    st      r0, [sp, 20]                                ; Save ilink
    ld      r0, [ilink, 4]                              ; Pickup the status32
    st      r0, [sp, 164]                               ; Setup the status32
    ld      r0, [gp, _tx_thread_current_ptr@sda]        ; Pickup current thread pointer
    st      sp, [r0, 8]                                 ; Save stack pointer in thread control block
    lr      ilink, [status32]                           ; Pickup status32 register
    bset    ilink, ilink, 16                            ; Build register bank 1 value
    bclr    ilink, ilink, 17                            ;
    bclr    ilink, ilink, 18                            ;
    kflag   ilink                                       ; Move back to register bank 1
__tx_preempt_save_done:
;
    ld      r0, [gp, _tx_thread_current_ptr@sda]        ; Pickup current thread ptr
;
;    /* Save the remaining time-slice and disable it.  */
;    if (_tx_timer_time_slice)
;    {
;
    ld      r2, [gp, _tx_timer_time_slice@sda]          ; Pickup time-slice contents
    mov     r7, 0                                       ; Build clear/NULL value
    breq    r2, 0, __tx_thread_dont_save_ts             ; No time-slice, don't need to save it
;
;        _tx_thread_current_ptr -> tx_thread_time_slice =  _tx_timer_time_slice;
;        _tx_timer_time_slice =  0;
;
    st      r2, [r0, 24]                                ; If set, save remaining time-slice
    st      r7, [gp, _tx_timer_time_slice@sda]          ; If set, clear time slice
;
;    }
__tx_thread_dont_save_ts:
;
;
;    /* Clear the current thread pointer.  */
;    _tx_thread_current_ptr =  TX_NULL;
;
    st      r7, [gp, _tx_thread_current_ptr@sda]        ; Set current thread ptr to NULL
    mov     ilink, _tx_thread_schedule                  ; Build address of scheduler
    rtie                                                ; Return from interrupt to scheduler
;
;    }
;
;    /* Return to the scheduler.  */
;    _tx_thread_schedule();
;
__tx_thread_idle_system_restore:

    lr      r4, [AUX_IRQ_ACT]                           ; Pickup the interrupt active register
    neg     r5, r4                                      ; Negate
    and     r5, r4, r5                                  ; See if there are any other interrupts present
    sub.f   0, r4, r5                                   ; Set condition codes
    bne     __tx_thread_nested_restore                  ; If more interrupts, just return to the point of interrupt

    mov     ilink, _tx_thread_schedule                  ; Build address of scheduler
    rtie                                                ; Return from interrupt to scheduler
;
;}
    .end