]> begriffs open source - cmsis-freertos/blob - Source/portable/MPLAB/PIC32MZ/port_asm.S
Update FreeRTOS-Kernel to v10.6.2
[cmsis-freertos] / Source / portable / MPLAB / PIC32MZ / port_asm.S
1 /*
2  * FreeRTOS Kernel V10.6.2
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 #include <xc.h>
30 #include <sys/asm.h>
31 #include "FreeRTOSConfig.h"
32 #include "ISR_Support.h"
33
34     .extern pxCurrentTCB
35     .extern vTaskSwitchContext
36     .extern vPortIncrementTick
37     .extern xISRStackTop
38     .extern ulTaskHasFPUContext
39
40     .global vPortStartFirstTask
41     .global vPortYieldISR
42     .global vPortTickInterruptHandler
43     .global vPortInitialiseFPSCR
44
45
46 /******************************************************************/
47
48     .set  nomips16
49     .set  nomicromips
50     .set  noreorder
51     .set  noat
52
53     /***************************************************************
54     *  The following is needed to locate the
55     *  vPortTickInterruptHandler function into the correct vector
56     ***************************************************************/
57     #ifdef configTICK_INTERRUPT_VECTOR
58         #if (configTICK_INTERRUPT_VECTOR == _CORE_TIMER_VECTOR)
59             .equ     __vector_dispatch_0, vPortTickInterruptHandler
60             .global  __vector_dispatch_0
61             .section .vector_0, code, keep
62         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_1_VECTOR)
63             .equ     __vector_dispatch_4, vPortTickInterruptHandler
64             .global  __vector_dispatch_4
65             .section .vector_4, code, keep
66         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_2_VECTOR)
67             .equ     __vector_dispatch_9, vPortTickInterruptHandler
68             .global  __vector_dispatch_9
69             .section .vector_9, code, keep
70         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_3_VECTOR)
71             .equ     __vector_dispatch_14, vPortTickInterruptHandler
72             .global  __vector_dispatch_14
73             .section .vector_14, code, keep
74         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_4_VECTOR)
75             .equ     __vector_dispatch_19, vPortTickInterruptHandler
76             .global  __vector_dispatch_19
77             .section .vector_19, code, keep
78         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_5_VECTOR)
79             .equ     __vector_dispatch_24, vPortTickInterruptHandler
80             .global  __vector_dispatch_24
81             .section .vector_24, code, keep
82         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_6_VECTOR)
83             .equ     __vector_dispatch_28, vPortTickInterruptHandler
84             .global  __vector_dispatch_28
85             .section .vector_28, code, keep
86         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_7_VECTOR)
87             .equ     __vector_dispatch_32, vPortTickInterruptHandler
88             .global  __vector_dispatch_32
89             .section .vector_32, code, keep
90         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_8_VECTOR)
91             .equ     __vector_dispatch_36, vPortTickInterruptHandler
92             .global  __vector_dispatch_36
93             .section .vector_36, code, keep
94         #elif (configTICK_INTERRUPT_VECTOR == _TIMER_9_VECTOR)
95             .equ     __vector_dispatch_40, vPortTickInterruptHandler
96             .global  __vector_dispatch_40
97             .section .vector_40, code, keep
98         #endif
99     #else
100         .equ     __vector_dispatch_4, vPortTickInterruptHandler
101         .global  __vector_dispatch_4
102         .section .vector_4, code, keep
103     #endif
104
105     .ent        vPortTickInterruptHandler
106
107 vPortTickInterruptHandler:
108
109     portSAVE_CONTEXT
110
111     jal         vPortIncrementTick
112     nop
113
114     portRESTORE_CONTEXT
115
116     .end vPortTickInterruptHandler
117
118 /******************************************************************/
119
120     .set        noreorder
121     .set        noat
122     .section .text, code
123     .ent        vPortStartFirstTask
124
125 vPortStartFirstTask:
126
127     /* Simply restore the context of the highest priority task that has been
128     created so far. */
129     portRESTORE_CONTEXT
130
131     .end vPortStartFirstTask
132
133
134
135 /*******************************************************************/
136
137     .set  nomips16
138     .set  nomicromips
139     .set  noreorder
140     .set  noat
141     /***************************************************************
142     *  The following is needed to locate the vPortYieldISR function
143     *  into the correct vector
144     ***************************************************************/
145     .equ     __vector_dispatch_1, vPortYieldISR
146     .global  __vector_dispatch_1
147     .section .vector_1, code
148
149     .ent  vPortYieldISR
150 vPortYieldISR:
151
152     #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )
153         /* Code sequence for FPU support, the context save requires advance
154         knowledge of the stack frame size and if the current task actually uses the
155         FPU. */
156
157         /* Make room for the context. First save the current status so it can be
158         manipulated, and the cause and EPC registers so their original values are
159         captured. */
160         la      k0, ulTaskHasFPUContext
161         lw      k0, 0(k0)
162         beq     k0, zero, 1f
163         addiu   sp, sp, -portCONTEXT_SIZE   /* always reserve space for the context. */
164         addiu   sp, sp, -portFPU_CONTEXT_SIZE   /* reserve additional space for the FPU context. */
165     1:
166         mfc0    k1, _CP0_STATUS
167
168         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should
169         maintain the values of these registers across the ISR. */
170         sw      s6, 44(sp)
171         sw      s5, 40(sp)
172         sw      k1, portSTATUS_STACK_LOCATION(sp)
173         sw      k0, portTASK_HAS_FPU_STACK_LOCATION(sp)
174
175         /* Prepare to re-enabled interrupts above the kernel priority. */
176         ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */
177         ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */
178         ori     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
179         ins     k1, zero, 1, 4          /* Clear EXL, ERL and UM. */
180
181         /* s5 is used as the frame pointer. */
182         add     s5, zero, sp
183
184         /* Swap to the system stack.  This is not conditional on the nesting
185         count as this interrupt is always the lowest priority and therefore
186         the nesting is always 0. */
187         la      sp, xISRStackTop
188         lw      sp, (sp)
189
190         /* Set the nesting count. */
191         la      k0, uxInterruptNesting
192         addiu   s6, zero, 1
193         sw      s6, 0(k0)
194
195         /* s6 holds the EPC value, this is saved with the rest of the context
196         after interrupts are enabled. */
197         mfc0    s6, _CP0_EPC
198
199         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
200         mtc0    k1, _CP0_STATUS
201
202         /* Save the context into the space just created.  s6 is saved again
203         here as it now contains the EPC value. */
204         sw      ra, 120(s5)
205         sw      s8, 116(s5)
206         sw      t9, 112(s5)
207         sw      t8, 108(s5)
208         sw      t7, 104(s5)
209         sw      t6, 100(s5)
210         sw      t5, 96(s5)
211         sw      t4, 92(s5)
212         sw      t3, 88(s5)
213         sw      t2, 84(s5)
214         sw      t1, 80(s5)
215         sw      t0, 76(s5)
216         sw      a3, 72(s5)
217         sw      a2, 68(s5)
218         sw      a1, 64(s5)
219         sw      a0, 60(s5)
220         sw      v1, 56(s5)
221         sw      v0, 52(s5)
222         sw      s7, 48(s5)
223         sw      s6, portEPC_STACK_LOCATION(s5)
224         /* s5 and s6 has already been saved. */
225         sw      s4, 36(s5)
226         sw      s3, 32(s5)
227         sw      s2, 28(s5)
228         sw      s1, 24(s5)
229         sw      s0, 20(s5)
230         sw      $1, 16(s5)
231
232         /* s7 is used as a scratch register as this should always be saved across
233         nesting interrupts. */
234
235         /* Save the AC0, AC1, AC2 and AC3. */
236         mfhi    s7, $ac1
237         sw      s7, 128(s5)
238         mflo    s7, $ac1
239         sw      s7, 124(s5)
240
241         mfhi    s7, $ac2
242         sw      s7, 136(s5)
243         mflo    s7, $ac2
244         sw      s7, 132(s5)
245
246         mfhi    s7, $ac3
247         sw      s7, 144(s5)
248         mflo    s7, $ac3
249         sw      s7, 140(s5)
250
251         rddsp   s7
252         sw      s7, 148(s5)
253
254         mfhi    s7, $ac0
255         sw      s7, 12(s5)
256         mflo    s7, $ac0
257         sw      s7, 8(s5)
258
259         /* Test if FPU context save is required. */
260         lw      s7, portTASK_HAS_FPU_STACK_LOCATION(s5)
261         beq     s7, zero, 1f
262         nop
263
264         /* Save the FPU registers above the normal context. */
265         portSAVE_FPU_REGS   (portCONTEXT_SIZE + 8), s5
266
267         /* Save the FPU status register */
268         cfc1    s7, $f31
269         sw      s7, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)
270
271     1:
272         /* Save the stack pointer to the task. */
273         la      s7, pxCurrentTCB
274         lw      s7, (s7)
275         sw      s5, (s7)
276
277         /* Set the interrupt mask to the max priority that can use the API.  The
278         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which
279         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever
280         raise the IPL value and never lower it. */
281         di
282         ehb
283         mfc0    s7, _CP0_STATUS
284         ins     s7, zero, 10, 7
285         ins     s7, zero, 18, 1
286         ori     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
287
288         /* This mtc0 re-enables interrupts, but only above
289         configMAX_SYSCALL_INTERRUPT_PRIORITY. */
290         mtc0    s6, _CP0_STATUS
291         ehb
292
293         /* Clear the software interrupt in the core. */
294         mfc0    s6, _CP0_CAUSE
295         ins     s6, zero, 8, 1
296         mtc0    s6, _CP0_CAUSE
297         ehb
298
299         /* Clear the interrupt in the interrupt controller. */
300         la      s6, IFS0CLR
301         addiu   s4, zero, 2
302         sw      s4, (s6)
303
304         jal     vTaskSwitchContext
305         nop
306
307         /* Clear the interrupt mask again.  The saved status value is still in s7. */
308         mtc0    s7, _CP0_STATUS
309         ehb
310
311         /* Restore the stack pointer from the TCB. */
312         la      s0, pxCurrentTCB
313         lw      s0, (s0)
314         lw      s5, (s0)
315
316         /* Test if the FPU context needs restoring. */
317         lw      s0, portTASK_HAS_FPU_STACK_LOCATION(s5)
318         beq     s0, zero, 1f
319         nop
320
321         /* Restore the FPU status register. */
322         lw      s0, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)
323         ctc1    s0, $f31
324
325         /* Restore the FPU registers. */
326         portLOAD_FPU_REGS   ( portCONTEXT_SIZE + 8 ), s5
327
328     1:
329         /* Restore the rest of the context. */
330         lw      s0, 128(s5)
331         mthi    s0, $ac1
332         lw      s0, 124(s5)
333         mtlo        s0, $ac1
334
335         lw      s0, 136(s5)
336         mthi    s0, $ac2
337         lw      s0, 132(s5)
338         mtlo    s0, $ac2
339
340         lw      s0, 144(s5)
341         mthi    s0, $ac3
342         lw      s0, 140(s5)
343         mtlo    s0, $ac3
344
345         lw      s0, 148(s5)
346         wrdsp   s0
347
348         lw      s0, 8(s5)
349         mtlo    s0, $ac0
350         lw      s0, 12(s5)
351         mthi    s0, $ac0
352
353         lw      $1, 16(s5)
354         lw      s0, 20(s5)
355         lw      s1, 24(s5)
356         lw      s2, 28(s5)
357         lw      s3, 32(s5)
358         lw      s4, 36(s5)
359
360         /* s5 is loaded later. */
361         lw      s6, 44(s5)
362         lw      s7, 48(s5)
363         lw      v0, 52(s5)
364         lw      v1, 56(s5)
365         lw      a0, 60(s5)
366         lw      a1, 64(s5)
367         lw      a2, 68(s5)
368         lw      a3, 72(s5)
369         lw      t0, 76(s5)
370         lw      t1, 80(s5)
371         lw      t2, 84(s5)
372         lw      t3, 88(s5)
373         lw      t4, 92(s5)
374         lw      t5, 96(s5)
375         lw      t6, 100(s5)
376         lw      t7, 104(s5)
377         lw      t8, 108(s5)
378         lw      t9, 112(s5)
379         lw      s8, 116(s5)
380         lw      ra, 120(s5)
381
382         /* Protect access to the k registers, and others. */
383         di
384         ehb
385
386         /* Set nesting back to zero.  As the lowest priority interrupt this
387         interrupt cannot have nested. */
388         la      k0, uxInterruptNesting
389         sw      zero, 0(k0)
390
391         /* Switch back to use the real stack pointer. */
392         add     sp, zero, s5
393
394         /* Restore the real s5 value. */
395         lw      s5, 40(sp)
396
397         /* Pop the FPU context value from the stack */
398         lw      k0, portTASK_HAS_FPU_STACK_LOCATION(sp)
399         la      k1, ulTaskHasFPUContext
400         sw      k0, 0(k1)
401         beq     k0, zero, 1f
402         nop
403
404         /* task has FPU context so adjust the stack frame after popping the
405         status and epc values. */
406         lw      k1, portSTATUS_STACK_LOCATION(sp)
407         lw      k0, portEPC_STACK_LOCATION(sp)
408         addiu   sp, sp, portFPU_CONTEXT_SIZE
409         beq     zero, zero, 2f
410         nop
411
412     1:
413         /* Pop the status and epc values. */
414         lw      k1, portSTATUS_STACK_LOCATION(sp)
415         lw      k0, portEPC_STACK_LOCATION(sp)
416
417     2:
418         /* Remove stack frame. */
419         addiu   sp, sp, portCONTEXT_SIZE
420
421     #else
422         /* Code sequence for no FPU support, the context save requires advance
423         knowledge of the stack frame size when no FPU is being used */
424
425         /* Make room for the context. First save the current status so it can be
426         manipulated, and the cause and EPC registers so thier original values are
427         captured. */
428         addiu   sp, sp, -portCONTEXT_SIZE
429         mfc0    k1, _CP0_STATUS
430
431         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should
432         maintain the values of these registers across the ISR. */
433         sw      s6, 44(sp)
434         sw      s5, 40(sp)
435         sw      k1, portSTATUS_STACK_LOCATION(sp)
436
437         /* Prepare to re-enabled interrupts above the kernel priority. */
438         ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */
439         ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */
440         ori     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
441         ins     k1, zero, 1, 4          /* Clear EXL, ERL and UM. */
442
443         /* s5 is used as the frame pointer. */
444         add     s5, zero, sp
445
446         /* Swap to the system stack.  This is not conditional on the nesting
447         count as this interrupt is always the lowest priority and therefore
448         the nesting is always 0. */
449         la      sp, xISRStackTop
450         lw      sp, (sp)
451
452         /* Set the nesting count. */
453         la      k0, uxInterruptNesting
454         addiu   s6, zero, 1
455         sw      s6, 0(k0)
456
457         /* s6 holds the EPC value, this is saved with the rest of the context
458         after interrupts are enabled. */
459         mfc0    s6, _CP0_EPC
460
461         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
462         mtc0    k1, _CP0_STATUS
463
464         /* Save the context into the space just created.  s6 is saved again
465         here as it now contains the EPC value. */
466         sw      ra, 120(s5)
467         sw      s8, 116(s5)
468         sw      t9, 112(s5)
469         sw      t8, 108(s5)
470         sw      t7, 104(s5)
471         sw      t6, 100(s5)
472         sw      t5, 96(s5)
473         sw      t4, 92(s5)
474         sw      t3, 88(s5)
475         sw      t2, 84(s5)
476         sw      t1, 80(s5)
477         sw      t0, 76(s5)
478         sw      a3, 72(s5)
479         sw      a2, 68(s5)
480         sw      a1, 64(s5)
481         sw      a0, 60(s5)
482         sw      v1, 56(s5)
483         sw      v0, 52(s5)
484         sw      s7, 48(s5)
485         sw      s6, portEPC_STACK_LOCATION(s5)
486         /* s5 and s6 has already been saved. */
487         sw      s4, 36(s5)
488         sw      s3, 32(s5)
489         sw      s2, 28(s5)
490         sw      s1, 24(s5)
491         sw      s0, 20(s5)
492         sw      $1, 16(s5)
493
494         /* s7 is used as a scratch register as this should always be saved across
495         nesting interrupts. */
496
497         /* Save the AC0, AC1, AC2 and AC3. */
498         mfhi    s7, $ac1
499         sw      s7, 128(s5)
500         mflo    s7, $ac1
501         sw      s7, 124(s5)
502
503         mfhi    s7, $ac2
504         sw      s7, 136(s5)
505         mflo    s7, $ac2
506         sw      s7, 132(s5)
507
508         mfhi    s7, $ac3
509         sw      s7, 144(s5)
510         mflo    s7, $ac3
511         sw      s7, 140(s5)
512
513         rddsp   s7
514         sw      s7, 148(s5)
515
516         mfhi    s7, $ac0
517         sw      s7, 12(s5)
518         mflo    s7, $ac0
519         sw      s7, 8(s5)
520
521         /* Save the stack pointer to the task. */
522         la      s7, pxCurrentTCB
523         lw      s7, (s7)
524         sw      s5, (s7)
525
526         /* Set the interrupt mask to the max priority that can use the API.  The
527         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which
528         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever
529         raise the IPL value and never lower it. */
530         di
531         ehb
532         mfc0    s7, _CP0_STATUS
533         ins     s7, zero, 10, 7
534         ins     s7, zero, 18, 1
535         ori     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
536
537         /* This mtc0 re-enables interrupts, but only above
538         configMAX_SYSCALL_INTERRUPT_PRIORITY. */
539         mtc0    s6, _CP0_STATUS
540         ehb
541
542         /* Clear the software interrupt in the core. */
543         mfc0    s6, _CP0_CAUSE
544         ins     s6, zero, 8, 1
545         mtc0    s6, _CP0_CAUSE
546         ehb
547
548         /* Clear the interrupt in the interrupt controller. */
549         la      s6, IFS0CLR
550         addiu   s4, zero, 2
551         sw      s4, (s6)
552
553         jal     vTaskSwitchContext
554         nop
555
556         /* Clear the interrupt mask again.  The saved status value is still in s7. */
557         mtc0    s7, _CP0_STATUS
558         ehb
559
560         /* Restore the stack pointer from the TCB. */
561         la      s0, pxCurrentTCB
562         lw      s0, (s0)
563         lw      s5, (s0)
564
565         /* Restore the rest of the context. */
566         lw      s0, 128(s5)
567         mthi    s0, $ac1
568         lw      s0, 124(s5)
569         mtlo    s0, $ac1
570
571         lw      s0, 136(s5)
572         mthi    s0, $ac2
573         lw      s0, 132(s5)
574         mtlo    s0, $ac2
575
576         lw      s0, 144(s5)
577         mthi    s0, $ac3
578         lw      s0, 140(s5)
579         mtlo    s0, $ac3
580
581         lw      s0, 148(s5)
582         wrdsp   s0
583
584         lw      s0, 8(s5)
585         mtlo    s0, $ac0
586         lw      s0, 12(s5)
587         mthi    s0, $ac0
588
589         lw      $1, 16(s5)
590         lw      s0, 20(s5)
591         lw      s1, 24(s5)
592         lw      s2, 28(s5)
593         lw      s3, 32(s5)
594         lw      s4, 36(s5)
595
596         /* s5 is loaded later. */
597         lw      s6, 44(s5)
598         lw      s7, 48(s5)
599         lw      v0, 52(s5)
600         lw      v1, 56(s5)
601         lw      a0, 60(s5)
602         lw      a1, 64(s5)
603         lw      a2, 68(s5)
604         lw      a3, 72(s5)
605         lw      t0, 76(s5)
606         lw      t1, 80(s5)
607         lw      t2, 84(s5)
608         lw      t3, 88(s5)
609         lw      t4, 92(s5)
610         lw      t5, 96(s5)
611         lw      t6, 100(s5)
612         lw      t7, 104(s5)
613         lw      t8, 108(s5)
614         lw      t9, 112(s5)
615         lw      s8, 116(s5)
616         lw      ra, 120(s5)
617
618         /* Protect access to the k registers, and others. */
619         di
620         ehb
621
622         /* Set nesting back to zero.  As the lowest priority interrupt this
623         interrupt cannot have nested. */
624         la      k0, uxInterruptNesting
625         sw      zero, 0(k0)
626
627         /* Switch back to use the real stack pointer. */
628         add     sp, zero, s5
629
630         /* Restore the real s5 value. */
631         lw      s5, 40(sp)
632
633         /* Pop the status and epc values. */
634         lw      k1, portSTATUS_STACK_LOCATION(sp)
635         lw      k0, portEPC_STACK_LOCATION(sp)
636
637         /* Remove stack frame. */
638         addiu   sp, sp, portCONTEXT_SIZE
639
640     #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */
641
642     /* Restore the status and EPC registers and return */
643     mtc0    k1, _CP0_STATUS
644     mtc0    k0, _CP0_EPC
645     ehb
646     eret
647     nop
648
649     .end    vPortYieldISR
650
651 /******************************************************************/
652
653 #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )
654
655     .macro portFPUSetAndInc reg, dest
656     mtc1    \reg, \dest
657     cvt.d.w \dest, \dest
658     addiu   \reg, \reg, 1
659     .endm
660
661     .set    noreorder
662     .set    noat
663     .section .text, code
664     .ent    vPortInitialiseFPSCR
665
666 vPortInitialiseFPSCR:
667
668     /* Initialize the floating point status register in CP1. The initial
669     value is passed in a0. */
670     ctc1        a0, $f31
671
672     /* Clear the FPU registers */
673     addiu           a0, zero, 0x0000
674     portFPUSetAndInc    a0, $f0
675     portFPUSetAndInc    a0, $f1
676     portFPUSetAndInc    a0, $f2
677     portFPUSetAndInc    a0, $f3
678     portFPUSetAndInc    a0, $f4
679     portFPUSetAndInc    a0, $f5
680     portFPUSetAndInc    a0, $f6
681     portFPUSetAndInc    a0, $f7
682     portFPUSetAndInc    a0, $f8
683     portFPUSetAndInc    a0, $f9
684     portFPUSetAndInc    a0, $f10
685     portFPUSetAndInc    a0, $f11
686     portFPUSetAndInc    a0, $f12
687     portFPUSetAndInc    a0, $f13
688     portFPUSetAndInc    a0, $f14
689     portFPUSetAndInc    a0, $f15
690     portFPUSetAndInc    a0, $f16
691     portFPUSetAndInc    a0, $f17
692     portFPUSetAndInc    a0, $f18
693     portFPUSetAndInc    a0, $f19
694     portFPUSetAndInc    a0, $f20
695     portFPUSetAndInc    a0, $f21
696     portFPUSetAndInc    a0, $f22
697     portFPUSetAndInc    a0, $f23
698     portFPUSetAndInc    a0, $f24
699     portFPUSetAndInc    a0, $f25
700     portFPUSetAndInc    a0, $f26
701     portFPUSetAndInc    a0, $f27
702     portFPUSetAndInc    a0, $f28
703     portFPUSetAndInc    a0, $f29
704     portFPUSetAndInc    a0, $f30
705     portFPUSetAndInc    a0, $f31
706
707     jr      ra
708     nop
709
710     .end vPortInitialiseFPSCR
711
712 #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */
713
714 #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )
715
716     /**********************************************************************/
717     /* Test read back                               */
718     /* a0 = address to store registers              */
719
720     .set        noreorder
721     .set        noat
722     .section    .text, code
723     .ent        vPortFPUReadback
724     .global     vPortFPUReadback
725
726 vPortFPUReadback:
727     sdc1        $f0, 0(a0)
728     sdc1        $f1, 8(a0)
729     sdc1        $f2, 16(a0)
730     sdc1        $f3, 24(a0)
731     sdc1        $f4, 32(a0)
732     sdc1        $f5, 40(a0)
733     sdc1        $f6, 48(a0)
734     sdc1        $f7, 56(a0)
735     sdc1        $f8, 64(a0)
736     sdc1        $f9, 72(a0)
737     sdc1        $f10, 80(a0)
738     sdc1        $f11, 88(a0)
739     sdc1        $f12, 96(a0)
740     sdc1        $f13, 104(a0)
741     sdc1        $f14, 112(a0)
742     sdc1        $f15, 120(a0)
743     sdc1        $f16, 128(a0)
744     sdc1        $f17, 136(a0)
745     sdc1        $f18, 144(a0)
746     sdc1        $f19, 152(a0)
747     sdc1        $f20, 160(a0)
748     sdc1        $f21, 168(a0)
749     sdc1        $f22, 176(a0)
750     sdc1        $f23, 184(a0)
751     sdc1        $f24, 192(a0)
752     sdc1        $f25, 200(a0)
753     sdc1        $f26, 208(a0)
754     sdc1        $f27, 216(a0)
755     sdc1        $f28, 224(a0)
756     sdc1        $f29, 232(a0)
757     sdc1        $f30, 240(a0)
758     sdc1        $f31, 248(a0)
759
760     jr      ra
761     nop
762
763     .end vPortFPUReadback
764
765 #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */