]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MZ/port_asm.S
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MZ / port_asm.S
1 /*\r
2     FreeRTOS V9.0.0rc2 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 #include <xc.h>\r
71 #include <sys/asm.h>\r
72 #include "FreeRTOSConfig.h"\r
73 #include "ISR_Support.h"\r
74 \r
75 \r
76         .extern pxCurrentTCB\r
77         .extern vTaskSwitchContext\r
78         .extern vPortIncrementTick\r
79         .extern xISRStackTop\r
80         .extern ulTaskHasFPUContext\r
81 \r
82         .global vPortStartFirstTask\r
83         .global vPortYieldISR\r
84         .global vPortTickInterruptHandler\r
85         .global vPortInitialiseFPSCR\r
86 \r
87 \r
88 /******************************************************************/\r
89 \r
90         .set  nomips16\r
91         .set  nomicromips\r
92         .set  noreorder\r
93         .set  noat\r
94 \r
95         /***************************************************************\r
96         *  The following is needed to locate the\r
97         *  vPortTickInterruptHandler function into the correct vector\r
98         ***************************************************************/\r
99         #ifdef configTICK_INTERRUPT_VECTOR\r
100                 #if (configTICK_INTERRUPT_VECTOR == _CORE_TIMER_VECTOR)\r
101                         .equ     __vector_dispatch_0, vPortTickInterruptHandler\r
102                         .global  __vector_dispatch_0\r
103                         .section .vector_0, code, keep\r
104                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_1_VECTOR)\r
105                         .equ     __vector_dispatch_4, vPortTickInterruptHandler\r
106                         .global  __vector_dispatch_4\r
107                         .section .vector_4, code, keep\r
108                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_2_VECTOR)\r
109                         .equ     __vector_dispatch_9, vPortTickInterruptHandler\r
110                         .global  __vector_dispatch_9\r
111                         .section .vector_9, code, keep\r
112                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_3_VECTOR)\r
113                         .equ     __vector_dispatch_14, vPortTickInterruptHandler\r
114                         .global  __vector_dispatch_14\r
115                         .section .vector_14, code, keep\r
116                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_4_VECTOR)\r
117                         .equ     __vector_dispatch_19, vPortTickInterruptHandler\r
118                         .global  __vector_dispatch_19\r
119                         .section .vector_19, code, keep\r
120                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_5_VECTOR)\r
121                         .equ     __vector_dispatch_24, vPortTickInterruptHandler\r
122                         .global  __vector_dispatch_24\r
123                         .section .vector_24, code, keep\r
124                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_6_VECTOR)\r
125                         .equ     __vector_dispatch_28, vPortTickInterruptHandler\r
126                         .global  __vector_dispatch_28\r
127                         .section .vector_28, code, keep\r
128                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_7_VECTOR)\r
129                         .equ     __vector_dispatch_32, vPortTickInterruptHandler\r
130                         .global  __vector_dispatch_32\r
131                         .section .vector_32, code, keep\r
132                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_8_VECTOR)\r
133                         .equ     __vector_dispatch_36, vPortTickInterruptHandler\r
134                         .global  __vector_dispatch_36\r
135                         .section .vector_36, code, keep\r
136                 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_9_VECTOR)\r
137                         .equ     __vector_dispatch_40, vPortTickInterruptHandler\r
138                         .global  __vector_dispatch_40\r
139                         .section .vector_40, code, keep\r
140                 #endif\r
141         #else\r
142                 .equ     __vector_dispatch_4, vPortTickInterruptHandler\r
143                 .global  __vector_dispatch_4\r
144                 .section .vector_4, code, keep\r
145         #endif\r
146 \r
147         .ent            vPortTickInterruptHandler\r
148 \r
149 vPortTickInterruptHandler:\r
150 \r
151         portSAVE_CONTEXT\r
152 \r
153         jal             vPortIncrementTick\r
154         nop\r
155 \r
156         portRESTORE_CONTEXT\r
157 \r
158         .end vPortTickInterruptHandler\r
159 \r
160 /******************************************************************/\r
161 \r
162         .set            noreorder\r
163         .set            noat\r
164         .section .text, code\r
165         .ent            vPortStartFirstTask\r
166 \r
167 vPortStartFirstTask:\r
168 \r
169         /* Simply restore the context of the highest priority task that has been\r
170         created so far. */\r
171         portRESTORE_CONTEXT\r
172 \r
173         .end vPortStartFirstTask\r
174 \r
175 \r
176 \r
177 /*******************************************************************/\r
178 \r
179         .set  nomips16\r
180         .set  nomicromips\r
181         .set  noreorder\r
182         .set  noat\r
183         /***************************************************************\r
184         *  The following is needed to locate the vPortYieldISR function\r
185         *  into the correct vector\r
186         ***************************************************************/\r
187         .equ     __vector_dispatch_1, vPortYieldISR\r
188         .global  __vector_dispatch_1\r
189         .section .vector_1, code\r
190 \r
191         .ent  vPortYieldISR\r
192 vPortYieldISR:\r
193 \r
194         #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
195                 /* Code sequence for FPU support, the context save requires advance\r
196                 knowledge of the stack frame size and if the current task actually uses the \r
197                 FPU. */\r
198 \r
199                 /* Make room for the context. First save the current status so it can be\r
200                 manipulated, and the cause and EPC registers so their original values are\r
201                 captured. */\r
202                 la              k0, ulTaskHasFPUContext\r
203                 lw              k0, 0(k0)\r
204                 beq             k0, zero, 1f\r
205                 addiu   sp, sp, -portCONTEXT_SIZE       /* always reserve space for the context. */\r
206                 addiu   sp, sp, -portFPU_CONTEXT_SIZE   /* reserve additional space for the FPU context. */\r
207         1:\r
208                 mfc0    k1, _CP0_STATUS\r
209 \r
210                 /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
211                 maintain the values of these registers across the ISR. */\r
212                 sw              s6, 44(sp)\r
213                 sw              s5, 40(sp)\r
214                 sw              k1, portSTATUS_STACK_LOCATION(sp)\r
215                 sw              k0, portTASK_HAS_FPU_STACK_LOCATION(sp)\r
216 \r
217                 /* Prepare to re-enabled interrupts above the kernel priority. */\r
218                 ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */\r
219                 ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */\r
220                 ori             k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
221                 ins             k1, zero, 1, 4          /* Clear EXL, ERL and UM. */\r
222 \r
223                 /* s5 is used as the frame pointer. */\r
224                 add             s5, zero, sp\r
225 \r
226                 /* Swap to the system stack.  This is not conditional on the nesting\r
227                 count as this interrupt is always the lowest priority and therefore\r
228                 the nesting is always 0. */\r
229                 la              sp, xISRStackTop\r
230                 lw              sp, (sp)\r
231 \r
232                 /* Set the nesting count. */\r
233                 la              k0, uxInterruptNesting\r
234                 addiu   s6, zero, 1\r
235                 sw              s6, 0(k0)\r
236 \r
237                 /* s6 holds the EPC value, this is saved with the rest of the context\r
238                 after interrupts are enabled. */\r
239                 mfc0    s6, _CP0_EPC\r
240 \r
241                 /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
242                 mtc0    k1, _CP0_STATUS\r
243 \r
244                 /* Save the context into the space just created.  s6 is saved again\r
245                 here as it now contains the EPC value. */\r
246                 sw              ra, 120(s5)\r
247                 sw              s8, 116(s5)\r
248                 sw              t9, 112(s5)\r
249                 sw              t8, 108(s5)\r
250                 sw              t7, 104(s5)\r
251                 sw              t6, 100(s5)\r
252                 sw              t5, 96(s5)\r
253                 sw              t4, 92(s5)\r
254                 sw              t3, 88(s5)\r
255                 sw              t2, 84(s5)\r
256                 sw              t1, 80(s5)\r
257                 sw              t0, 76(s5)\r
258                 sw              a3, 72(s5)\r
259                 sw              a2, 68(s5)\r
260                 sw              a1, 64(s5)\r
261                 sw              a0, 60(s5)\r
262                 sw              v1, 56(s5)\r
263                 sw              v0, 52(s5)\r
264                 sw              s7, 48(s5)\r
265                 sw              s6, portEPC_STACK_LOCATION(s5)\r
266                 /* s5 and s6 has already been saved. */\r
267                 sw              s4, 36(s5)\r
268                 sw              s3, 32(s5)\r
269                 sw              s2, 28(s5)\r
270                 sw              s1, 24(s5)\r
271                 sw              s0, 20(s5)\r
272                 sw              $1, 16(s5)\r
273 \r
274                 /* s7 is used as a scratch register as this should always be saved across\r
275                 nesting interrupts. */\r
276 \r
277                 /* Save the AC0, AC1, AC2 and AC3. */\r
278                 mfhi    s7, $ac1\r
279                 sw              s7, 128(s5)\r
280                 mflo    s7, $ac1\r
281                 sw              s7, 124(s5)\r
282 \r
283                 mfhi    s7, $ac2\r
284                 sw              s7, 136(s5)\r
285                 mflo    s7, $ac2\r
286                 sw              s7, 132(s5)\r
287 \r
288                 mfhi    s7, $ac3\r
289                 sw              s7, 144(s5)\r
290                 mflo    s7, $ac3\r
291                 sw              s7, 140(s5)\r
292 \r
293                 rddsp   s7\r
294                 sw              s7, 148(s5)\r
295 \r
296                 mfhi    s7, $ac0\r
297                 sw              s7, 12(s5)\r
298                 mflo    s7, $ac0\r
299                 sw              s7, 8(s5)\r
300 \r
301                 /* Test if FPU context save is required. */\r
302                 lw              s7, portTASK_HAS_FPU_STACK_LOCATION(s5)\r
303                 beq             s7, zero, 1f\r
304                 nop\r
305 \r
306                 /* Save the FPU registers above the normal context. */\r
307                 portSAVE_FPU_REGS   (portCONTEXT_SIZE + 8), s5\r
308 \r
309                 /* Save the FPU status register */\r
310                 cfc1    s7, $f31\r
311                 sw              s7, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)\r
312 \r
313         1:\r
314                 /* Save the stack pointer to the task. */\r
315                 la              s7, pxCurrentTCB\r
316                 lw              s7, (s7)\r
317                 sw              s5, (s7)\r
318 \r
319                 /* Set the interrupt mask to the max priority that can use the API.  The\r
320                 yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
321                 is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
322                 raise the IPL value and never lower it. */\r
323                 di\r
324                 ehb\r
325                 mfc0    s7, _CP0_STATUS\r
326                 ins     s7, zero, 10, 7\r
327                 ins     s7, zero, 18, 1\r
328                 ori             s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
329 \r
330                 /* This mtc0 re-enables interrupts, but only above\r
331                 configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
332                 mtc0    s6, _CP0_STATUS\r
333                 ehb\r
334 \r
335                 /* Clear the software interrupt in the core. */\r
336                 mfc0    s6, _CP0_CAUSE\r
337                 ins             s6, zero, 8, 1\r
338                 mtc0    s6, _CP0_CAUSE\r
339                 ehb\r
340 \r
341                 /* Clear the interrupt in the interrupt controller. */\r
342                 la              s6, IFS0CLR\r
343                 addiu   s4, zero, 2\r
344                 sw              s4, (s6)\r
345 \r
346                 jal             vTaskSwitchContext\r
347                 nop\r
348 \r
349                 /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
350                 mtc0    s7, _CP0_STATUS\r
351                 ehb\r
352 \r
353                 /* Restore the stack pointer from the TCB. */\r
354                 la              s0, pxCurrentTCB\r
355                 lw              s0, (s0)\r
356                 lw              s5, (s0)\r
357 \r
358                 /* Test if the FPU context needs restoring. */\r
359                 lw              s0, portTASK_HAS_FPU_STACK_LOCATION(s5)\r
360                 beq             s0, zero, 1f\r
361                 nop\r
362 \r
363                 /* Restore the FPU status register. */\r
364                 lw              s0, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)\r
365                 ctc1    s0, $f31\r
366 \r
367                 /* Restore the FPU registers. */\r
368                 portLOAD_FPU_REGS   ( portCONTEXT_SIZE + 8 ), s5\r
369 \r
370         1:\r
371                 /* Restore the rest of the context. */\r
372                 lw              s0, 128(s5)\r
373                 mthi    s0, $ac1\r
374                 lw              s0, 124(s5)\r
375                 mtlo            s0, $ac1\r
376 \r
377                 lw              s0, 136(s5)\r
378                 mthi    s0, $ac2\r
379                 lw              s0, 132(s5)\r
380                 mtlo    s0, $ac2\r
381 \r
382                 lw              s0, 144(s5)\r
383                 mthi    s0, $ac3\r
384                 lw              s0, 140(s5)\r
385                 mtlo    s0, $ac3\r
386 \r
387                 lw              s0, 148(s5)\r
388                 wrdsp   s0\r
389 \r
390                 lw              s0, 8(s5)\r
391                 mtlo    s0, $ac0\r
392                 lw              s0, 12(s5)\r
393                 mthi    s0, $ac0\r
394 \r
395                 lw              $1, 16(s5)\r
396                 lw              s0, 20(s5)\r
397                 lw              s1, 24(s5)\r
398                 lw              s2, 28(s5)\r
399                 lw              s3, 32(s5)\r
400                 lw              s4, 36(s5)\r
401 \r
402                 /* s5 is loaded later. */\r
403                 lw              s6, 44(s5)\r
404                 lw              s7, 48(s5)\r
405                 lw              v0, 52(s5)\r
406                 lw              v1, 56(s5)\r
407                 lw              a0, 60(s5)\r
408                 lw              a1, 64(s5)\r
409                 lw              a2, 68(s5)\r
410                 lw              a3, 72(s5)\r
411                 lw              t0, 76(s5)\r
412                 lw              t1, 80(s5)\r
413                 lw              t2, 84(s5)\r
414                 lw              t3, 88(s5)\r
415                 lw              t4, 92(s5)\r
416                 lw              t5, 96(s5)\r
417                 lw              t6, 100(s5)\r
418                 lw              t7, 104(s5)\r
419                 lw              t8, 108(s5)\r
420                 lw              t9, 112(s5)\r
421                 lw              s8, 116(s5)\r
422                 lw              ra, 120(s5)\r
423 \r
424                 /* Protect access to the k registers, and others. */\r
425                 di\r
426                 ehb\r
427 \r
428                 /* Set nesting back to zero.  As the lowest priority interrupt this\r
429                 interrupt cannot have nested. */\r
430                 la              k0, uxInterruptNesting\r
431                 sw              zero, 0(k0)\r
432 \r
433                 /* Switch back to use the real stack pointer. */\r
434                 add             sp, zero, s5\r
435 \r
436                 /* Restore the real s5 value. */\r
437                 lw              s5, 40(sp)\r
438 \r
439                 /* Pop the FPU context value from the stack */\r
440                 lw              k0, portTASK_HAS_FPU_STACK_LOCATION(sp)\r
441                 la              k1, ulTaskHasFPUContext\r
442                 sw              k0, 0(k1)\r
443                 beq             k0, zero, 1f\r
444                 nop\r
445 \r
446                 /* task has FPU context so adjust the stack frame after popping the\r
447                 status and epc values. */\r
448                 lw              k1, portSTATUS_STACK_LOCATION(sp)\r
449                 lw              k0, portEPC_STACK_LOCATION(sp)\r
450                 addiu   sp, sp, portFPU_CONTEXT_SIZE\r
451                 beq             zero, zero, 2f\r
452                 nop\r
453 \r
454         1:\r
455                 /* Pop the status and epc values. */\r
456                 lw              k1, portSTATUS_STACK_LOCATION(sp)\r
457                 lw              k0, portEPC_STACK_LOCATION(sp)\r
458 \r
459         2:\r
460                 /* Remove stack frame. */\r
461                 addiu   sp, sp, portCONTEXT_SIZE\r
462 \r
463         #else\r
464                 /* Code sequence for no FPU support, the context save requires advance\r
465                 knowledge of the stack frame size when no FPU is being used */\r
466 \r
467                 /* Make room for the context. First save the current status so it can be\r
468                 manipulated, and the cause and EPC registers so thier original values are\r
469                 captured. */\r
470                 addiu   sp, sp, -portCONTEXT_SIZE\r
471                 mfc0    k1, _CP0_STATUS\r
472 \r
473                 /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
474                 maintain the values of these registers across the ISR. */\r
475                 sw              s6, 44(sp)\r
476                 sw              s5, 40(sp)\r
477                 sw              k1, portSTATUS_STACK_LOCATION(sp)\r
478 \r
479                 /* Prepare to re-enabled interrupts above the kernel priority. */\r
480                 ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */\r
481                 ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */\r
482                 ori             k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
483                 ins             k1, zero, 1, 4          /* Clear EXL, ERL and UM. */\r
484 \r
485                 /* s5 is used as the frame pointer. */\r
486                 add             s5, zero, sp\r
487 \r
488                 /* Swap to the system stack.  This is not conditional on the nesting\r
489                 count as this interrupt is always the lowest priority and therefore\r
490                 the nesting is always 0. */\r
491                 la              sp, xISRStackTop\r
492                 lw              sp, (sp)\r
493 \r
494                 /* Set the nesting count. */\r
495                 la              k0, uxInterruptNesting\r
496                 addiu   s6, zero, 1\r
497                 sw              s6, 0(k0)\r
498 \r
499                 /* s6 holds the EPC value, this is saved with the rest of the context\r
500                 after interrupts are enabled. */\r
501                 mfc0    s6, _CP0_EPC\r
502 \r
503                 /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
504                 mtc0    k1, _CP0_STATUS\r
505 \r
506                 /* Save the context into the space just created.  s6 is saved again\r
507                 here as it now contains the EPC value. */\r
508                 sw              ra, 120(s5)\r
509                 sw              s8, 116(s5)\r
510                 sw              t9, 112(s5)\r
511                 sw              t8, 108(s5)\r
512                 sw              t7, 104(s5)\r
513                 sw              t6, 100(s5)\r
514                 sw              t5, 96(s5)\r
515                 sw              t4, 92(s5)\r
516                 sw              t3, 88(s5)\r
517                 sw              t2, 84(s5)\r
518                 sw              t1, 80(s5)\r
519                 sw              t0, 76(s5)\r
520                 sw              a3, 72(s5)\r
521                 sw              a2, 68(s5)\r
522                 sw              a1, 64(s5)\r
523                 sw              a0, 60(s5)\r
524                 sw              v1, 56(s5)\r
525                 sw              v0, 52(s5)\r
526                 sw              s7, 48(s5)\r
527                 sw              s6, portEPC_STACK_LOCATION(s5)\r
528                 /* s5 and s6 has already been saved. */\r
529                 sw              s4, 36(s5)\r
530                 sw              s3, 32(s5)\r
531                 sw              s2, 28(s5)\r
532                 sw              s1, 24(s5)\r
533                 sw              s0, 20(s5)\r
534                 sw              $1, 16(s5)\r
535 \r
536                 /* s7 is used as a scratch register as this should always be saved across\r
537                 nesting interrupts. */\r
538 \r
539                 /* Save the AC0, AC1, AC2 and AC3. */\r
540                 mfhi    s7, $ac1\r
541                 sw              s7, 128(s5)\r
542                 mflo    s7, $ac1\r
543                 sw              s7, 124(s5)\r
544 \r
545                 mfhi    s7, $ac2\r
546                 sw              s7, 136(s5)\r
547                 mflo    s7, $ac2\r
548                 sw              s7, 132(s5)\r
549 \r
550                 mfhi    s7, $ac3\r
551                 sw              s7, 144(s5)\r
552                 mflo    s7, $ac3\r
553                 sw              s7, 140(s5)\r
554 \r
555                 rddsp   s7\r
556                 sw              s7, 148(s5)\r
557 \r
558                 mfhi    s7, $ac0\r
559                 sw              s7, 12(s5)\r
560                 mflo    s7, $ac0\r
561                 sw              s7, 8(s5)\r
562 \r
563                 /* Save the stack pointer to the task. */\r
564                 la              s7, pxCurrentTCB\r
565                 lw              s7, (s7)\r
566                 sw              s5, (s7)\r
567 \r
568                 /* Set the interrupt mask to the max priority that can use the API.  The\r
569                 yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
570                 is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
571                 raise the IPL value and never lower it. */\r
572                 di\r
573                 ehb\r
574                 mfc0    s7, _CP0_STATUS\r
575                 ins     s7, zero, 10, 7\r
576                 ins     s7, zero, 18, 1\r
577                 ori             s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
578 \r
579                 /* This mtc0 re-enables interrupts, but only above\r
580                 configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
581                 mtc0    s6, _CP0_STATUS\r
582                 ehb\r
583 \r
584                 /* Clear the software interrupt in the core. */\r
585                 mfc0    s6, _CP0_CAUSE\r
586                 ins             s6, zero, 8, 1\r
587                 mtc0    s6, _CP0_CAUSE\r
588                 ehb\r
589 \r
590                 /* Clear the interrupt in the interrupt controller. */\r
591                 la              s6, IFS0CLR\r
592                 addiu   s4, zero, 2\r
593                 sw              s4, (s6)\r
594 \r
595                 jal             vTaskSwitchContext\r
596                 nop\r
597 \r
598                 /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
599                 mtc0    s7, _CP0_STATUS\r
600                 ehb\r
601 \r
602                 /* Restore the stack pointer from the TCB. */\r
603                 la              s0, pxCurrentTCB\r
604                 lw              s0, (s0)\r
605                 lw              s5, (s0)\r
606 \r
607                 /* Restore the rest of the context. */\r
608                 lw              s0, 128(s5)\r
609                 mthi    s0, $ac1\r
610                 lw              s0, 124(s5)\r
611                 mtlo    s0, $ac1\r
612 \r
613                 lw              s0, 136(s5)\r
614                 mthi    s0, $ac2\r
615                 lw              s0, 132(s5)\r
616                 mtlo    s0, $ac2\r
617 \r
618                 lw              s0, 144(s5)\r
619                 mthi    s0, $ac3\r
620                 lw              s0, 140(s5)\r
621                 mtlo    s0, $ac3\r
622 \r
623                 lw              s0, 148(s5)\r
624                 wrdsp   s0\r
625 \r
626                 lw              s0, 8(s5)\r
627                 mtlo    s0, $ac0\r
628                 lw              s0, 12(s5)\r
629                 mthi    s0, $ac0\r
630 \r
631                 lw              $1, 16(s5)\r
632                 lw              s0, 20(s5)\r
633                 lw              s1, 24(s5)\r
634                 lw              s2, 28(s5)\r
635                 lw              s3, 32(s5)\r
636                 lw              s4, 36(s5)\r
637 \r
638                 /* s5 is loaded later. */\r
639                 lw              s6, 44(s5)\r
640                 lw              s7, 48(s5)\r
641                 lw              v0, 52(s5)\r
642                 lw              v1, 56(s5)\r
643                 lw              a0, 60(s5)\r
644                 lw              a1, 64(s5)\r
645                 lw              a2, 68(s5)\r
646                 lw              a3, 72(s5)\r
647                 lw              t0, 76(s5)\r
648                 lw              t1, 80(s5)\r
649                 lw              t2, 84(s5)\r
650                 lw              t3, 88(s5)\r
651                 lw              t4, 92(s5)\r
652                 lw              t5, 96(s5)\r
653                 lw              t6, 100(s5)\r
654                 lw              t7, 104(s5)\r
655                 lw              t8, 108(s5)\r
656                 lw              t9, 112(s5)\r
657                 lw              s8, 116(s5)\r
658                 lw              ra, 120(s5)\r
659 \r
660                 /* Protect access to the k registers, and others. */\r
661                 di\r
662                 ehb\r
663 \r
664                 /* Set nesting back to zero.  As the lowest priority interrupt this\r
665                 interrupt cannot have nested. */\r
666                 la              k0, uxInterruptNesting\r
667                 sw              zero, 0(k0)\r
668 \r
669                 /* Switch back to use the real stack pointer. */\r
670                 add             sp, zero, s5\r
671 \r
672                 /* Restore the real s5 value. */\r
673                 lw              s5, 40(sp)\r
674 \r
675                 /* Pop the status and epc values. */\r
676                 lw              k1, portSTATUS_STACK_LOCATION(sp)\r
677                 lw              k0, portEPC_STACK_LOCATION(sp)\r
678 \r
679                 /* Remove stack frame. */\r
680                 addiu   sp, sp, portCONTEXT_SIZE\r
681 \r
682         #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
683 \r
684         /* Restore the status and EPC registers and return */\r
685         mtc0    k1, _CP0_STATUS\r
686         mtc0    k0, _CP0_EPC\r
687         ehb\r
688         eret\r
689         nop\r
690 \r
691         .end    vPortYieldISR\r
692 \r
693 /******************************************************************/\r
694 \r
695 #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
696 \r
697         .macro portFPUSetAndInc reg, dest\r
698         mtc1    \reg, \dest\r
699         cvt.d.w \dest, \dest\r
700         addiu   \reg, \reg, 1\r
701         .endm\r
702 \r
703         .set    noreorder\r
704         .set    noat\r
705         .section .text, code\r
706         .ent    vPortInitialiseFPSCR\r
707 \r
708 vPortInitialiseFPSCR:\r
709 \r
710         /* Initialize the floating point status register in CP1. The initial\r
711         value is passed in a0. */\r
712         ctc1            a0, $f31\r
713 \r
714         /* Clear the FPU registers */\r
715         addiu                   a0, zero, 0x0000\r
716         portFPUSetAndInc        a0, $f0\r
717         portFPUSetAndInc        a0, $f1\r
718         portFPUSetAndInc        a0, $f2\r
719         portFPUSetAndInc        a0, $f3\r
720         portFPUSetAndInc        a0, $f4\r
721         portFPUSetAndInc        a0, $f5\r
722         portFPUSetAndInc        a0, $f6\r
723         portFPUSetAndInc        a0, $f7\r
724         portFPUSetAndInc        a0, $f8\r
725         portFPUSetAndInc        a0, $f9\r
726         portFPUSetAndInc        a0, $f10\r
727         portFPUSetAndInc        a0, $f11\r
728         portFPUSetAndInc        a0, $f12\r
729         portFPUSetAndInc        a0, $f13\r
730         portFPUSetAndInc        a0, $f14\r
731         portFPUSetAndInc        a0, $f15\r
732         portFPUSetAndInc        a0, $f16\r
733         portFPUSetAndInc        a0, $f17\r
734         portFPUSetAndInc        a0, $f18\r
735         portFPUSetAndInc        a0, $f19\r
736         portFPUSetAndInc        a0, $f20\r
737         portFPUSetAndInc        a0, $f21\r
738         portFPUSetAndInc        a0, $f22\r
739         portFPUSetAndInc        a0, $f23\r
740         portFPUSetAndInc        a0, $f24\r
741         portFPUSetAndInc        a0, $f25\r
742         portFPUSetAndInc        a0, $f26\r
743         portFPUSetAndInc        a0, $f27\r
744         portFPUSetAndInc        a0, $f28\r
745         portFPUSetAndInc        a0, $f29\r
746         portFPUSetAndInc        a0, $f30\r
747         portFPUSetAndInc        a0, $f31\r
748 \r
749         jr              ra\r
750         nop\r
751 \r
752         .end vPortInitialiseFPSCR\r
753 \r
754 #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
755         \r
756 #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
757 \r
758         /**********************************************************************/\r
759         /* Test read back                                                               */\r
760         /* a0 = address to store registers                              */\r
761 \r
762         .set            noreorder\r
763         .set            noat\r
764         .section        .text, code\r
765         .ent            vPortFPUReadback\r
766         .global         vPortFPUReadback\r
767 \r
768 vPortFPUReadback:\r
769         sdc1            $f0, 0(a0)\r
770         sdc1            $f1, 8(a0)\r
771         sdc1            $f2, 16(a0)\r
772         sdc1            $f3, 24(a0)\r
773         sdc1            $f4, 32(a0)\r
774         sdc1            $f5, 40(a0)\r
775         sdc1            $f6, 48(a0)\r
776         sdc1            $f7, 56(a0)\r
777         sdc1            $f8, 64(a0)\r
778         sdc1            $f9, 72(a0)\r
779         sdc1            $f10, 80(a0)\r
780         sdc1            $f11, 88(a0)\r
781         sdc1            $f12, 96(a0)\r
782         sdc1            $f13, 104(a0)\r
783         sdc1            $f14, 112(a0)\r
784         sdc1            $f15, 120(a0)\r
785         sdc1            $f16, 128(a0)\r
786         sdc1            $f17, 136(a0)\r
787         sdc1            $f18, 144(a0)\r
788         sdc1            $f19, 152(a0)\r
789         sdc1            $f20, 160(a0)\r
790         sdc1            $f21, 168(a0)\r
791         sdc1            $f22, 176(a0)\r
792         sdc1            $f23, 184(a0)\r
793         sdc1            $f24, 192(a0)\r
794         sdc1            $f25, 200(a0)\r
795         sdc1            $f26, 208(a0)\r
796         sdc1            $f27, 216(a0)\r
797         sdc1            $f28, 224(a0)\r
798         sdc1            $f29, 232(a0)\r
799         sdc1            $f30, 240(a0)\r
800         sdc1            $f31, 248(a0)\r
801 \r
802         jr              ra\r
803         nop\r
804 \r
805         .end vPortFPUReadback\r
806 \r
807 #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
808 \r
809 \r
810 \r
811 \r