summaryrefslogtreecommitdiff
path: root/ports_smp/mips32_interaptiv_smp/gnu/src/tx_thread_context_save.S
blob: 29dd34dfcaa7ac3720ba1111d35b4d1a909276d3 (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
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * 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                                                              */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


#define UserLocal     $4,2
#define C0_TCBind     $2,2
#define C0_TCContext  $2,5


    .text
    .set        noreorder
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _tx_thread_context_save                       MIPS32_interAptiv/GNU */
/*                                                           6.2.1        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Scott Larson, Microsoft Corporation                                 */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function saves the context of an executing thread in the       */
/*    beginning of interrupt processing.  The function also ensures that  */
/*    the system stack is used upon return to the calling ISR.            */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    ISRs                                                                */
/*                                                                        */
/**************************************************************************/
/* VOID   _tx_thread_context_save(VOID)
{  */
    .globl _tx_thread_context_save
_tx_thread_context_save:

    /* Upon entry to this routine, it is assumed that interrupts are locked
       out and the stack is exactly were it was when the interrupt occurred.
       The return address is in $27 (k1).  */

    subu    $29, $29, 392                   # Allocate space for a full stack frame
                                        /*  #   even though the whole thing might
                                            #   not be needed for awhile  */
    sw      $25, 48($29)                    # Store t9
    sw      $24, 52($29)                    # Store t8
    sw      $8, 84($29)                     # Save t0
    mfc0    $25, UserLocal                  # Pickup VPE ID
    sll     $24, $25, 2                     # Build index based on VPE number
    la      $26, _tx_thread_system_state    # Pickup address of system state
    addu    $26, $26, $24                   # Index by VPE
    lw      $8, ($26)                       # Pickup system state

    /* Check for a nested interrupt condition.  */
    /* if (_tx_thread_system_state[VPE]++)
    {  */

    beqz    $8, _tx_thread_not_nested_save  # If 0, first interrupt condition
    addu    $8, $8, 1                       # Increment the nested interrupt counter


    /* Nested interrupt condition.  */

    sw      $8, ($26)                       # Store the interrupt counter


#ifdef TX_ENABLE_64BIT_FPU_SUPPORT

    /* Check if FPU is enabled for this thread. Note that threads with FPU enabled will only be
       scheduled in VPE 0.  */

    bne     $25, $0, _tx_skip_nest_int_save # If not VPE 0, skip FPU save
    nop                                     #

    /* Save scratch floating point registers.  */

    cfc1    $8, $31                         # Pickup floating point control reg
    sdc1    $f19, 224($29)                  # Save f19
    sdc1    $f18, 232($29)                  # Save f18
    sdc1    $f17, 240($29)                  # Save f17
    sdc1    $f16, 248($29)                  # Save f16
    sdc1    $f15, 256($29)                  # Save f15
    sdc1    $f14, 264($29)                  # Save f14
    sdc1    $f13, 272($29)                  # Save f13
    sdc1    $f12, 280($29)                  # Save f12
    sdc1    $f11, 288($29)                  # Save f11
    sdc1    $f10, 296($29)                  # Save f10
    sdc1    $f9,  304($29)                  # Save f9
    sdc1    $f8,  312($29)                  # Save f8
    sdc1    $f7,  320($29)                  # Save f7
    sdc1    $f6,  328($29)                  # Save f6
    sdc1    $f5,  336($29)                  # Save f5
    sdc1    $f4,  344($29)                  # Save f4
    sdc1    $f3,  352($29)                  # Save f3
    sdc1    $f2,  360($29)                  # Save f2
    sdc1    $f1,  368($29)                  # Save f1
    sdc1    $f0,  376($29)                  # Save f0
    sw      $8,   384($29)                  # Save fcr31
_tx_skip_nest_int_save:

#endif


    /* Save the rest of the scratch registers on the stack and return to the
       calling ISR.  */

    sw      $16, 36($29)                    # Store s0
    mfhi    $8                              # Pickup hi
    mflo    $26                             # Pickup lo
    sw      $8,  40($29)                    # Store hi
    sw      $26, 44($29)                    # Store lo
    sw      $15, 56($29)                    # Store t7
    sw      $14, 60($29)                    # Store t6
    sw      $13, 64($29)                    # Store t5
    sw      $12, 68($29)                    # Store t4
    sw      $11, 72($29)                    # Store t3
    sw      $10, 76($29)                    # Store t2
    sw      $9,  80($29)                    # Store t1
    sw      $7,  88($29)                    # Store a3
    sw      $6,  92($29)                    # Store a2
    sw      $5,  96($29)                    # Store a1
    sw      $4, 100($29)                    # Store a0
    sw      $3, 104($29)                    # Store v1
    sw      $2, 108($29)                    # Store v0
    .set    noat
    sw      $1, 112($29)                    # Store at
    .set    at
    sw      $31, 116($29)                   # Store ra
    mfc0    $8, $12                         # Pickup SR
    mfc0    $9, $14                         # Pickup EPC
    sw      $8, 120($29)                    # Store SR
    sw      $9, 124($29)                    # Store EPC

    /* Return to the ISR.  */

    j       $27                             # Return to ISR
    nop                                     #

_tx_thread_not_nested_save:
    /* }  */

    /* Otherwise, not nested, check to see if a thread was running.  */
    /* else if (_tx_thread_current_ptr[VPE])
    {  */

    sw      $8, ($26)                       # Store the interrupt counter
    la      $26, _tx_thread_current_ptr     # Pickup address of current ptr
    addu    $26, $26, $24                   # Build address of current pointer for this VPE

    lw      $8, ($26)                       # Pickup current thread pointer
    beqz    $8, _tx_thread_idle_system_save # If NULL, idle system was interrupted
    sw      $16, 36($29)                    # Store s0

    /* Save minimal context of interrupted thread.  */

#ifdef TX_ENABLE_64BIT_FPU_SUPPORT

    /* Check if FPU is enabled for this thread. Note that threads with FPU enabled will only be
       scheduled in TC 0.  */

    bne     $25, $0, _tx_skip_int_save      # If not VPE 0, skip FPU save
    nop                                     # Delay
    lw      $26, 176($8)                    # Pickup FPU enable flag
    beq     $26, $0, _tx_skip_int_save      # If FPU not enabled, skip FPU save
    nop                                     # Delay

    /* Save scratch floating point registers.  */

    cfc1    $8, $31                         # Pickup floating point control reg
    sdc1    $f19, 224($29)                  # Save f19
    sdc1    $f18, 232($29)                  # Save f18
    sdc1    $f17, 240($29)                  # Save f17
    sdc1    $f16, 248($29)                  # Save f16
    sdc1    $f15, 256($29)                  # Save f15
    sdc1    $f14, 264($29)                  # Save f14
    sdc1    $f13, 272($29)                  # Save f13
    sdc1    $f12, 280($29)                  # Save f12
    sdc1    $f11, 288($29)                  # Save f11
    sdc1    $f10, 296($29)                  # Save f10
    sdc1    $f9,  304($29)                  # Save f9
    sdc1    $f8,  312($29)                  # Save f8
    sdc1    $f7,  320($29)                  # Save f7
    sdc1    $f6,  328($29)                  # Save f6
    sdc1    $f5,  336($29)                  # Save f5
    sdc1    $f4,  344($29)                  # Save f4
    sdc1    $f3,  352($29)                  # Save f3
    sdc1    $f2,  360($29)                  # Save f2
    sdc1    $f1,  368($29)                  # Save f1
    sdc1    $f0,  376($29)                  # Save f0
    sw      $8,   384($29)                  # Save fcr31
_tx_skip_int_save:

#endif

    /* Save the standard scratch registers.  */

    mfhi    $8                              # Pickup hi
    mflo    $26                             # Pickup lo
    sw      $8,  40($29)                    # Store hi
    sw      $26, 44($29)                    # Store lo
    sw      $15, 56($29)                    # Store t7
    sw      $14, 60($29)                    # Store t6
    sw      $13, 64($29)                    # Store t5
    sw      $12, 68($29)                    # Store t4
    sw      $11, 72($29)                    # Store t3
    sw      $10, 76($29)                    # Store t2
    sw      $9,  80($29)                    # Store t1
    sw      $7,  88($29)                    # Store a3
    sw      $6,  92($29)                    # Store a2
    sw      $5,  96($29)                    # Store a1
    sw      $4, 100($29)                    # Store a0
    sw      $3, 104($29)                    # Store v1
    sw      $2, 108($29)                    # Store v0
    .set    noat
    sw      $1, 112($29)                    # Store at
    .set    at
    sw      $31, 116($29)                   # Store ra
    mfc0    $8, $12                         # Pickup SR
    mfc0    $9, $14                         # Pickup EPC
    sw      $8, 120($29)                    # Store SR
    sw      $9, 124($29)                    # Store EPC

    li      $8, 1                           # Build stack type
    sw      $8, ($29)                       # Store stack type

    /* Save the current stack pointer in the thread's control block.  */
    /* _tx_thread_current_ptr[VPE] -> tx_thread_stack_ptr =  sp;  */

    /* Switch to the system stack.  */
    /* sp =  _tx_thread_system_stack_ptr[VPE];  */

    la      $9, _tx_thread_current_ptr      # Pickup address of current ptr
    addu    $9, $9, $24                     # Build address of current pointer for this VPE

    lw      $11, ($9)                       # Pickup current thread pointer
    la      $10,_tx_thread_system_stack_ptr # Pickup the stack pointer address
    sw      $29, 8($11)                     # Save stack pointer
    addu    $10, $10, $24                   # Build offset to system stack pointer
    lw      $29, ($10)                      # Switch to system stack

    j       $27                             # Return to ISR
    nop                                     #

    /* }
    else
    {  */

_tx_thread_idle_system_save:

    /* Interrupt occurred in the scheduling loop.  */

    addu    $29, $29, 392                   # Recover the reserved stack space
    j       $27                             # Return to ISR
    nop                                     #

    /* }
}  */