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