1/*
2 * FreeRTOS Kernel V11.1.0
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
107vPortTickInterruptHandler:
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
125vPortStartFirstTask:
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
150vPortYieldISR:
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
666vPortInitialiseFPSCR:
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
726vPortFPUReadback:
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 ) */
766