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