]> git.sur5r.net Git - freertos/blobdiff - 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
index 1808f77cb543afdcc2071b54ec96ca454d191c95..2a661c57c8c4e04cbbf22c4cb1ffff6307e7663a 100644 (file)
@@ -1,82 +1,46 @@
 /*\r
-    FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.\r
-    All rights reserved\r
-\r
-    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    FreeRTOS provides completely free yet professionally developed,    *\r
-     *    robust, strictly quality controlled, supported, and cross          *\r
-     *    platform software that has become a de facto standard.             *\r
-     *                                                                       *\r
-     *    Help yourself get started quickly and support the FreeRTOS         *\r
-     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
-     *                                                                       *\r
-     *    Thank you!                                                         *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    This file is part of the FreeRTOS distribution.\r
-\r
-    FreeRTOS is free software; you can redistribute it and/or modify it under\r
-    the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
-    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
-    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
-    >>!   obliged to provide the source code for proprietary components     !<<\r
-    >>!   outside of the FreeRTOS kernel.                                   !<<\r
-\r
-    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
-    FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    1 tab == 4 spaces!\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    Having a problem?  Start by reading the FAQ "My application does   *\r
-     *    not run, what could be wrong?"                                     *\r
-     *                                                                       *\r
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
-    license and Real Time Engineers Ltd. contact details.\r
-\r
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
-    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
-    licenses offer ticketed support, indemnification and middleware.\r
-\r
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
-    engineered and independently SIL3 certified version for use in safety and\r
-    mission critical applications that require provable dependability.\r
-\r
-    1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.0.0\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software. If you wish to use our Amazon\r
+ * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
 \r
 #include <xc.h>\r
 #include <sys/asm.h>\r
 #include "FreeRTOSConfig.h"\r
 #include "ISR_Support.h"\r
 \r
-\r
        .extern pxCurrentTCB\r
        .extern vTaskSwitchContext\r
        .extern vPortIncrementTick\r
        .extern xISRStackTop\r
+       .extern ulTaskHasFPUContext\r
 \r
        .global vPortStartFirstTask\r
        .global vPortYieldISR\r
        .global vPortTickInterruptHandler\r
+       .global vPortInitialiseFPSCR\r
 \r
 \r
 /******************************************************************/\r
@@ -185,228 +149,621 @@ vPortStartFirstTask:
        .ent  vPortYieldISR\r
 vPortYieldISR:\r
 \r
-       /* Make room for the context. First save the current status so it can be\r
-       manipulated, and the cause and EPC registers so thier original values are\r
-       captured. */\r
-       addiu           sp, sp, -portCONTEXT_SIZE\r
-       mfc0            k1, _CP0_STATUS\r
-\r
-       /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
-       maintain the values of these registers across the ISR. */\r
-       sw                      s6, 44(sp)\r
-       sw                      s5, 40(sp)\r
-       sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
-\r
-       /* Prepare to re-enabled interrupts above the kernel priority. */\r
-       ins             k1, zero, 10, 7         /* Clear IPL bits 0:6. */\r
-    ins                k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */\r
-       ori                     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
-    ins                        k1, zero, 1, 4          /* Clear EXL, ERL and UM. */\r
-\r
-       /* s5 is used as the frame pointer. */\r
-       add                     s5, zero, sp\r
-\r
-       /* Swap to the system stack.  This is not conditional on the nesting\r
-       count as this interrupt is always the lowest priority and therefore\r
-       the nesting is always 0. */\r
-       la                      sp, xISRStackTop\r
-       lw                      sp, (sp)\r
-\r
-       /* Set the nesting count. */\r
-       la                      k0, uxInterruptNesting\r
-       addiu           s6, zero, 1\r
-       sw                      s6, 0(k0)\r
-\r
-       /* s6 holds the EPC value, this is saved with the rest of the context\r
-       after interrupts are enabled. */\r
-       mfc0            s6, _CP0_EPC\r
-\r
-       /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
-       mtc0            k1, _CP0_STATUS\r
-\r
-       /* Save the context into the space just created.  s6 is saved again\r
-       here as it now contains the EPC value. */\r
-       sw                      ra, 120(s5)\r
-       sw                      s8, 116(s5)\r
-       sw                      t9, 112(s5)\r
-       sw                      t8, 108(s5)\r
-       sw                      t7, 104(s5)\r
-       sw                      t6, 100(s5)\r
-       sw                      t5, 96(s5)\r
-       sw                      t4, 92(s5)\r
-       sw                      t3, 88(s5)\r
-       sw                      t2, 84(s5)\r
-       sw                      t1, 80(s5)\r
-       sw                      t0, 76(s5)\r
-       sw                      a3, 72(s5)\r
-       sw                      a2, 68(s5)\r
-       sw                      a1, 64(s5)\r
-       sw                      a0, 60(s5)\r
-       sw                      v1, 56(s5)\r
-       sw                      v0, 52(s5)\r
-       sw                      s7, 48(s5)\r
-       sw                      s6, portEPC_STACK_LOCATION(s5)\r
-       /* s5 and s6 has already been saved. */\r
-       sw                      s4,     36(s5)\r
-       sw                      s3, 32(s5)\r
-       sw                      s2, 28(s5)\r
-       sw                      s1, 24(s5)\r
-       sw                      s0, 20(s5)\r
-       sw                      $1, 16(s5)\r
-\r
-       /* s7 is used as a scratch register as this should always be saved across\r
-       nesting interrupts. */\r
-\r
-       /* Save the AC0, AC1, AC2 and AC3. */\r
-       mfhi            s7, $ac1\r
-       sw                      s7, 128(s5)\r
-       mflo            s7, $ac1\r
-       sw                      s7, 124(s5)\r
-\r
-       mfhi            s7, $ac2\r
-       sw                      s7, 136(s5)\r
-       mflo            s7, $ac2\r
-       sw                      s7, 132(s5)\r
-\r
-       mfhi            s7, $ac3\r
-       sw                      s7, 144(s5)\r
-       mflo            s7, $ac3\r
-       sw                      s7, 140(s5)\r
-\r
-       rddsp           s7\r
-       sw                      s7, 148(s5)\r
-\r
-       mfhi            s7, $ac0\r
-       sw                      s7, 12(s5)\r
-       mflo            s7, $ac0\r
-       sw                      s7, 8(s5)\r
-\r
-       /* Save the stack pointer to the task. */\r
-       la                      s7, pxCurrentTCB\r
-       lw                      s7, (s7)\r
-       sw                      s5, (s7)\r
-\r
-       /* Set the interrupt mask to the max priority that can use the API.  The\r
-       yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
-       is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
-       raise the IPL value and never lower it. */\r
-       di\r
-       ehb\r
-       mfc0            s7, _CP0_STATUS\r
-       ins             s7, zero, 10, 7\r
-    ins                s7, zero, 18, 1\r
-       ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
-\r
-       /* This mtc0 re-enables interrupts, but only above\r
-       configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
-       mtc0            s6, _CP0_STATUS\r
-       ehb\r
+       #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
+               /* Code sequence for FPU support, the context save requires advance\r
+               knowledge of the stack frame size and if the current task actually uses the \r
+               FPU. */\r
+\r
+               /* Make room for the context. First save the current status so it can be\r
+               manipulated, and the cause and EPC registers so their original values are\r
+               captured. */\r
+               la              k0, ulTaskHasFPUContext\r
+               lw              k0, 0(k0)\r
+               beq             k0, zero, 1f\r
+               addiu   sp, sp, -portCONTEXT_SIZE       /* always reserve space for the context. */\r
+               addiu   sp, sp, -portFPU_CONTEXT_SIZE   /* reserve additional space for the FPU context. */\r
+       1:\r
+               mfc0    k1, _CP0_STATUS\r
+\r
+               /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
+               maintain the values of these registers across the ISR. */\r
+               sw              s6, 44(sp)\r
+               sw              s5, 40(sp)\r
+               sw              k1, portSTATUS_STACK_LOCATION(sp)\r
+               sw              k0, portTASK_HAS_FPU_STACK_LOCATION(sp)\r
+\r
+               /* Prepare to re-enabled interrupts above the kernel priority. */\r
+               ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */\r
+               ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */\r
+               ori             k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
+               ins             k1, zero, 1, 4          /* Clear EXL, ERL and UM. */\r
+\r
+               /* s5 is used as the frame pointer. */\r
+               add             s5, zero, sp\r
+\r
+               /* Swap to the system stack.  This is not conditional on the nesting\r
+               count as this interrupt is always the lowest priority and therefore\r
+               the nesting is always 0. */\r
+               la              sp, xISRStackTop\r
+               lw              sp, (sp)\r
+\r
+               /* Set the nesting count. */\r
+               la              k0, uxInterruptNesting\r
+               addiu   s6, zero, 1\r
+               sw              s6, 0(k0)\r
+\r
+               /* s6 holds the EPC value, this is saved with the rest of the context\r
+               after interrupts are enabled. */\r
+               mfc0    s6, _CP0_EPC\r
+\r
+               /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
+               mtc0    k1, _CP0_STATUS\r
+\r
+               /* Save the context into the space just created.  s6 is saved again\r
+               here as it now contains the EPC value. */\r
+               sw              ra, 120(s5)\r
+               sw              s8, 116(s5)\r
+               sw              t9, 112(s5)\r
+               sw              t8, 108(s5)\r
+               sw              t7, 104(s5)\r
+               sw              t6, 100(s5)\r
+               sw              t5, 96(s5)\r
+               sw              t4, 92(s5)\r
+               sw              t3, 88(s5)\r
+               sw              t2, 84(s5)\r
+               sw              t1, 80(s5)\r
+               sw              t0, 76(s5)\r
+               sw              a3, 72(s5)\r
+               sw              a2, 68(s5)\r
+               sw              a1, 64(s5)\r
+               sw              a0, 60(s5)\r
+               sw              v1, 56(s5)\r
+               sw              v0, 52(s5)\r
+               sw              s7, 48(s5)\r
+               sw              s6, portEPC_STACK_LOCATION(s5)\r
+               /* s5 and s6 has already been saved. */\r
+               sw              s4, 36(s5)\r
+               sw              s3, 32(s5)\r
+               sw              s2, 28(s5)\r
+               sw              s1, 24(s5)\r
+               sw              s0, 20(s5)\r
+               sw              $1, 16(s5)\r
+\r
+               /* s7 is used as a scratch register as this should always be saved across\r
+               nesting interrupts. */\r
+\r
+               /* Save the AC0, AC1, AC2 and AC3. */\r
+               mfhi    s7, $ac1\r
+               sw              s7, 128(s5)\r
+               mflo    s7, $ac1\r
+               sw              s7, 124(s5)\r
+\r
+               mfhi    s7, $ac2\r
+               sw              s7, 136(s5)\r
+               mflo    s7, $ac2\r
+               sw              s7, 132(s5)\r
+\r
+               mfhi    s7, $ac3\r
+               sw              s7, 144(s5)\r
+               mflo    s7, $ac3\r
+               sw              s7, 140(s5)\r
+\r
+               rddsp   s7\r
+               sw              s7, 148(s5)\r
+\r
+               mfhi    s7, $ac0\r
+               sw              s7, 12(s5)\r
+               mflo    s7, $ac0\r
+               sw              s7, 8(s5)\r
+\r
+               /* Test if FPU context save is required. */\r
+               lw              s7, portTASK_HAS_FPU_STACK_LOCATION(s5)\r
+               beq             s7, zero, 1f\r
+               nop\r
+\r
+               /* Save the FPU registers above the normal context. */\r
+               portSAVE_FPU_REGS   (portCONTEXT_SIZE + 8), s5\r
+\r
+               /* Save the FPU status register */\r
+               cfc1    s7, $f31\r
+               sw              s7, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)\r
+\r
+       1:\r
+               /* Save the stack pointer to the task. */\r
+               la              s7, pxCurrentTCB\r
+               lw              s7, (s7)\r
+               sw              s5, (s7)\r
+\r
+               /* Set the interrupt mask to the max priority that can use the API.  The\r
+               yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
+               is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
+               raise the IPL value and never lower it. */\r
+               di\r
+               ehb\r
+               mfc0    s7, _CP0_STATUS\r
+               ins     s7, zero, 10, 7\r
+               ins     s7, zero, 18, 1\r
+               ori             s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
+\r
+               /* This mtc0 re-enables interrupts, but only above\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
+               mtc0    s6, _CP0_STATUS\r
+               ehb\r
+\r
+               /* Clear the software interrupt in the core. */\r
+               mfc0    s6, _CP0_CAUSE\r
+               ins             s6, zero, 8, 1\r
+               mtc0    s6, _CP0_CAUSE\r
+               ehb\r
+\r
+               /* Clear the interrupt in the interrupt controller. */\r
+               la              s6, IFS0CLR\r
+               addiu   s4, zero, 2\r
+               sw              s4, (s6)\r
+\r
+               jal             vTaskSwitchContext\r
+               nop\r
+\r
+               /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
+               mtc0    s7, _CP0_STATUS\r
+               ehb\r
+\r
+               /* Restore the stack pointer from the TCB. */\r
+               la              s0, pxCurrentTCB\r
+               lw              s0, (s0)\r
+               lw              s5, (s0)\r
+\r
+               /* Test if the FPU context needs restoring. */\r
+               lw              s0, portTASK_HAS_FPU_STACK_LOCATION(s5)\r
+               beq             s0, zero, 1f\r
+               nop\r
+\r
+               /* Restore the FPU status register. */\r
+               lw              s0, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5)\r
+               ctc1    s0, $f31\r
+\r
+               /* Restore the FPU registers. */\r
+               portLOAD_FPU_REGS   ( portCONTEXT_SIZE + 8 ), s5\r
+\r
+       1:\r
+               /* Restore the rest of the context. */\r
+               lw              s0, 128(s5)\r
+               mthi    s0, $ac1\r
+               lw              s0, 124(s5)\r
+               mtlo            s0, $ac1\r
+\r
+               lw              s0, 136(s5)\r
+               mthi    s0, $ac2\r
+               lw              s0, 132(s5)\r
+               mtlo    s0, $ac2\r
+\r
+               lw              s0, 144(s5)\r
+               mthi    s0, $ac3\r
+               lw              s0, 140(s5)\r
+               mtlo    s0, $ac3\r
+\r
+               lw              s0, 148(s5)\r
+               wrdsp   s0\r
+\r
+               lw              s0, 8(s5)\r
+               mtlo    s0, $ac0\r
+               lw              s0, 12(s5)\r
+               mthi    s0, $ac0\r
+\r
+               lw              $1, 16(s5)\r
+               lw              s0, 20(s5)\r
+               lw              s1, 24(s5)\r
+               lw              s2, 28(s5)\r
+               lw              s3, 32(s5)\r
+               lw              s4, 36(s5)\r
+\r
+               /* s5 is loaded later. */\r
+               lw              s6, 44(s5)\r
+               lw              s7, 48(s5)\r
+               lw              v0, 52(s5)\r
+               lw              v1, 56(s5)\r
+               lw              a0, 60(s5)\r
+               lw              a1, 64(s5)\r
+               lw              a2, 68(s5)\r
+               lw              a3, 72(s5)\r
+               lw              t0, 76(s5)\r
+               lw              t1, 80(s5)\r
+               lw              t2, 84(s5)\r
+               lw              t3, 88(s5)\r
+               lw              t4, 92(s5)\r
+               lw              t5, 96(s5)\r
+               lw              t6, 100(s5)\r
+               lw              t7, 104(s5)\r
+               lw              t8, 108(s5)\r
+               lw              t9, 112(s5)\r
+               lw              s8, 116(s5)\r
+               lw              ra, 120(s5)\r
+\r
+               /* Protect access to the k registers, and others. */\r
+               di\r
+               ehb\r
+\r
+               /* Set nesting back to zero.  As the lowest priority interrupt this\r
+               interrupt cannot have nested. */\r
+               la              k0, uxInterruptNesting\r
+               sw              zero, 0(k0)\r
+\r
+               /* Switch back to use the real stack pointer. */\r
+               add             sp, zero, s5\r
+\r
+               /* Restore the real s5 value. */\r
+               lw              s5, 40(sp)\r
+\r
+               /* Pop the FPU context value from the stack */\r
+               lw              k0, portTASK_HAS_FPU_STACK_LOCATION(sp)\r
+               la              k1, ulTaskHasFPUContext\r
+               sw              k0, 0(k1)\r
+               beq             k0, zero, 1f\r
+               nop\r
+\r
+               /* task has FPU context so adjust the stack frame after popping the\r
+               status and epc values. */\r
+               lw              k1, portSTATUS_STACK_LOCATION(sp)\r
+               lw              k0, portEPC_STACK_LOCATION(sp)\r
+               addiu   sp, sp, portFPU_CONTEXT_SIZE\r
+               beq             zero, zero, 2f\r
+               nop\r
+\r
+       1:\r
+               /* Pop the status and epc values. */\r
+               lw              k1, portSTATUS_STACK_LOCATION(sp)\r
+               lw              k0, portEPC_STACK_LOCATION(sp)\r
+\r
+       2:\r
+               /* Remove stack frame. */\r
+               addiu   sp, sp, portCONTEXT_SIZE\r
 \r
-       /* Clear the software interrupt in the core. */\r
-       mfc0            s6, _CP0_CAUSE\r
-       ins                     s6, zero, 8, 1\r
-       mtc0            s6, _CP0_CAUSE\r
+       #else\r
+               /* Code sequence for no FPU support, the context save requires advance\r
+               knowledge of the stack frame size when no FPU is being used */\r
+\r
+               /* Make room for the context. First save the current status so it can be\r
+               manipulated, and the cause and EPC registers so thier original values are\r
+               captured. */\r
+               addiu   sp, sp, -portCONTEXT_SIZE\r
+               mfc0    k1, _CP0_STATUS\r
+\r
+               /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
+               maintain the values of these registers across the ISR. */\r
+               sw              s6, 44(sp)\r
+               sw              s5, 40(sp)\r
+               sw              k1, portSTATUS_STACK_LOCATION(sp)\r
+\r
+               /* Prepare to re-enabled interrupts above the kernel priority. */\r
+               ins     k1, zero, 10, 7         /* Clear IPL bits 0:6. */\r
+               ins     k1, zero, 18, 1         /* Clear IPL bit 7.  It would be an error here if this bit were set anyway. */\r
+               ori             k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
+               ins             k1, zero, 1, 4          /* Clear EXL, ERL and UM. */\r
+\r
+               /* s5 is used as the frame pointer. */\r
+               add             s5, zero, sp\r
+\r
+               /* Swap to the system stack.  This is not conditional on the nesting\r
+               count as this interrupt is always the lowest priority and therefore\r
+               the nesting is always 0. */\r
+               la              sp, xISRStackTop\r
+               lw              sp, (sp)\r
+\r
+               /* Set the nesting count. */\r
+               la              k0, uxInterruptNesting\r
+               addiu   s6, zero, 1\r
+               sw              s6, 0(k0)\r
+\r
+               /* s6 holds the EPC value, this is saved with the rest of the context\r
+               after interrupts are enabled. */\r
+               mfc0    s6, _CP0_EPC\r
+\r
+               /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
+               mtc0    k1, _CP0_STATUS\r
+\r
+               /* Save the context into the space just created.  s6 is saved again\r
+               here as it now contains the EPC value. */\r
+               sw              ra, 120(s5)\r
+               sw              s8, 116(s5)\r
+               sw              t9, 112(s5)\r
+               sw              t8, 108(s5)\r
+               sw              t7, 104(s5)\r
+               sw              t6, 100(s5)\r
+               sw              t5, 96(s5)\r
+               sw              t4, 92(s5)\r
+               sw              t3, 88(s5)\r
+               sw              t2, 84(s5)\r
+               sw              t1, 80(s5)\r
+               sw              t0, 76(s5)\r
+               sw              a3, 72(s5)\r
+               sw              a2, 68(s5)\r
+               sw              a1, 64(s5)\r
+               sw              a0, 60(s5)\r
+               sw              v1, 56(s5)\r
+               sw              v0, 52(s5)\r
+               sw              s7, 48(s5)\r
+               sw              s6, portEPC_STACK_LOCATION(s5)\r
+               /* s5 and s6 has already been saved. */\r
+               sw              s4, 36(s5)\r
+               sw              s3, 32(s5)\r
+               sw              s2, 28(s5)\r
+               sw              s1, 24(s5)\r
+               sw              s0, 20(s5)\r
+               sw              $1, 16(s5)\r
+\r
+               /* s7 is used as a scratch register as this should always be saved across\r
+               nesting interrupts. */\r
+\r
+               /* Save the AC0, AC1, AC2 and AC3. */\r
+               mfhi    s7, $ac1\r
+               sw              s7, 128(s5)\r
+               mflo    s7, $ac1\r
+               sw              s7, 124(s5)\r
+\r
+               mfhi    s7, $ac2\r
+               sw              s7, 136(s5)\r
+               mflo    s7, $ac2\r
+               sw              s7, 132(s5)\r
+\r
+               mfhi    s7, $ac3\r
+               sw              s7, 144(s5)\r
+               mflo    s7, $ac3\r
+               sw              s7, 140(s5)\r
+\r
+               rddsp   s7\r
+               sw              s7, 148(s5)\r
+\r
+               mfhi    s7, $ac0\r
+               sw              s7, 12(s5)\r
+               mflo    s7, $ac0\r
+               sw              s7, 8(s5)\r
+\r
+               /* Save the stack pointer to the task. */\r
+               la              s7, pxCurrentTCB\r
+               lw              s7, (s7)\r
+               sw              s5, (s7)\r
+\r
+               /* Set the interrupt mask to the max priority that can use the API.  The\r
+               yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
+               is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
+               raise the IPL value and never lower it. */\r
+               di\r
+               ehb\r
+               mfc0    s7, _CP0_STATUS\r
+               ins     s7, zero, 10, 7\r
+               ins     s7, zero, 18, 1\r
+               ori             s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
+\r
+               /* This mtc0 re-enables interrupts, but only above\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
+               mtc0    s6, _CP0_STATUS\r
+               ehb\r
+\r
+               /* Clear the software interrupt in the core. */\r
+               mfc0    s6, _CP0_CAUSE\r
+               ins             s6, zero, 8, 1\r
+               mtc0    s6, _CP0_CAUSE\r
+               ehb\r
+\r
+               /* Clear the interrupt in the interrupt controller. */\r
+               la              s6, IFS0CLR\r
+               addiu   s4, zero, 2\r
+               sw              s4, (s6)\r
+\r
+               jal             vTaskSwitchContext\r
+               nop\r
+\r
+               /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
+               mtc0    s7, _CP0_STATUS\r
+               ehb\r
+\r
+               /* Restore the stack pointer from the TCB. */\r
+               la              s0, pxCurrentTCB\r
+               lw              s0, (s0)\r
+               lw              s5, (s0)\r
+\r
+               /* Restore the rest of the context. */\r
+               lw              s0, 128(s5)\r
+               mthi    s0, $ac1\r
+               lw              s0, 124(s5)\r
+               mtlo    s0, $ac1\r
+\r
+               lw              s0, 136(s5)\r
+               mthi    s0, $ac2\r
+               lw              s0, 132(s5)\r
+               mtlo    s0, $ac2\r
+\r
+               lw              s0, 144(s5)\r
+               mthi    s0, $ac3\r
+               lw              s0, 140(s5)\r
+               mtlo    s0, $ac3\r
+\r
+               lw              s0, 148(s5)\r
+               wrdsp   s0\r
+\r
+               lw              s0, 8(s5)\r
+               mtlo    s0, $ac0\r
+               lw              s0, 12(s5)\r
+               mthi    s0, $ac0\r
+\r
+               lw              $1, 16(s5)\r
+               lw              s0, 20(s5)\r
+               lw              s1, 24(s5)\r
+               lw              s2, 28(s5)\r
+               lw              s3, 32(s5)\r
+               lw              s4, 36(s5)\r
+\r
+               /* s5 is loaded later. */\r
+               lw              s6, 44(s5)\r
+               lw              s7, 48(s5)\r
+               lw              v0, 52(s5)\r
+               lw              v1, 56(s5)\r
+               lw              a0, 60(s5)\r
+               lw              a1, 64(s5)\r
+               lw              a2, 68(s5)\r
+               lw              a3, 72(s5)\r
+               lw              t0, 76(s5)\r
+               lw              t1, 80(s5)\r
+               lw              t2, 84(s5)\r
+               lw              t3, 88(s5)\r
+               lw              t4, 92(s5)\r
+               lw              t5, 96(s5)\r
+               lw              t6, 100(s5)\r
+               lw              t7, 104(s5)\r
+               lw              t8, 108(s5)\r
+               lw              t9, 112(s5)\r
+               lw              s8, 116(s5)\r
+               lw              ra, 120(s5)\r
+\r
+               /* Protect access to the k registers, and others. */\r
+               di\r
+               ehb\r
+\r
+               /* Set nesting back to zero.  As the lowest priority interrupt this\r
+               interrupt cannot have nested. */\r
+               la              k0, uxInterruptNesting\r
+               sw              zero, 0(k0)\r
+\r
+               /* Switch back to use the real stack pointer. */\r
+               add             sp, zero, s5\r
+\r
+               /* Restore the real s5 value. */\r
+               lw              s5, 40(sp)\r
+\r
+               /* Pop the status and epc values. */\r
+               lw              k1, portSTATUS_STACK_LOCATION(sp)\r
+               lw              k0, portEPC_STACK_LOCATION(sp)\r
+\r
+               /* Remove stack frame. */\r
+               addiu   sp, sp, portCONTEXT_SIZE\r
+\r
+       #endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
+\r
+       /* Restore the status and EPC registers and return */\r
+       mtc0    k1, _CP0_STATUS\r
+       mtc0    k0, _CP0_EPC\r
        ehb\r
-\r
-       /* Clear the interrupt in the interrupt controller. */\r
-       la                      s6, IFS0CLR\r
-       addiu           s4, zero, 2\r
-       sw                      s4, (s6)\r
-\r
-       jal                     vTaskSwitchContext\r
+       eret\r
        nop\r
 \r
-       /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
-       mtc0            s7, _CP0_STATUS\r
-       ehb\r
+       .end    vPortYieldISR\r
 \r
-       /* Restore the stack pointer from the TCB. */\r
-       la                      s0, pxCurrentTCB\r
-       lw                      s0, (s0)\r
-       lw                      s5, (s0)\r
-\r
-       /* Restore the rest of the context. */\r
-       lw                      s0, 128(s5)\r
-       mthi            s0, $ac1\r
-       lw                      s0, 124(s5)\r
-       mtlo            s0, $ac1\r
-\r
-       lw                      s0, 136(s5)\r
-       mthi            s0, $ac2\r
-       lw                      s0, 132(s5)\r
-       mtlo            s0, $ac2\r
-\r
-       lw                      s0, 144(s5)\r
-       mthi            s0, $ac3\r
-       lw                      s0, 140(s5)\r
-       mtlo            s0, $ac3\r
-\r
-       lw                      s0, 148(s5)\r
-       wrdsp           s0\r
-\r
-       lw                      s0, 8(s5)\r
-       mtlo            s0, $ac0\r
-       lw                      s0, 12(s5)\r
-       mthi            s0, $ac0\r
-\r
-       lw                      $1, 16(s5)\r
-       lw                      s0, 20(s5)\r
-       lw                      s1, 24(s5)\r
-       lw                      s2, 28(s5)\r
-       lw                      s3, 32(s5)\r
-       lw                      s4, 36(s5)\r
-\r
-       /* s5 is loaded later. */\r
-       lw                      s6, 44(s5)\r
-       lw                      s7, 48(s5)\r
-       lw                      v0, 52(s5)\r
-       lw                      v1, 56(s5)\r
-       lw                      a0, 60(s5)\r
-       lw                      a1, 64(s5)\r
-       lw                      a2, 68(s5)\r
-       lw                      a3, 72(s5)\r
-       lw                      t0, 76(s5)\r
-       lw                      t1, 80(s5)\r
-       lw                      t2, 84(s5)\r
-       lw                      t3, 88(s5)\r
-       lw                      t4, 92(s5)\r
-       lw                      t5, 96(s5)\r
-       lw                      t6, 100(s5)\r
-       lw                      t7, 104(s5)\r
-       lw                      t8, 108(s5)\r
-       lw                      t9, 112(s5)\r
-       lw                      s8, 116(s5)\r
-       lw                      ra, 120(s5)\r
-\r
-       /* Protect access to the k registers, and others. */\r
-       di\r
-       ehb\r
+/******************************************************************/\r
 \r
-       /* Set nesting back to zero.  As the lowest priority interrupt this\r
-       interrupt cannot have nested. */\r
-       la                      k0, uxInterruptNesting\r
-       sw                      zero, 0(k0)\r
+#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
 \r
-       /* Switch back to use the real stack pointer. */\r
-       add                     sp, zero, s5\r
+       .macro portFPUSetAndInc reg, dest\r
+       mtc1    \reg, \dest\r
+       cvt.d.w \dest, \dest\r
+       addiu   \reg, \reg, 1\r
+       .endm\r
 \r
-       /* Restore the real s5 value. */\r
-       lw                      s5, 40(sp)\r
+       .set    noreorder\r
+       .set    noat\r
+       .section .text, code\r
+       .ent    vPortInitialiseFPSCR\r
+\r
+vPortInitialiseFPSCR:\r
+\r
+       /* Initialize the floating point status register in CP1. The initial\r
+       value is passed in a0. */\r
+       ctc1            a0, $f31\r
+\r
+       /* Clear the FPU registers */\r
+       addiu                   a0, zero, 0x0000\r
+       portFPUSetAndInc        a0, $f0\r
+       portFPUSetAndInc        a0, $f1\r
+       portFPUSetAndInc        a0, $f2\r
+       portFPUSetAndInc        a0, $f3\r
+       portFPUSetAndInc        a0, $f4\r
+       portFPUSetAndInc        a0, $f5\r
+       portFPUSetAndInc        a0, $f6\r
+       portFPUSetAndInc        a0, $f7\r
+       portFPUSetAndInc        a0, $f8\r
+       portFPUSetAndInc        a0, $f9\r
+       portFPUSetAndInc        a0, $f10\r
+       portFPUSetAndInc        a0, $f11\r
+       portFPUSetAndInc        a0, $f12\r
+       portFPUSetAndInc        a0, $f13\r
+       portFPUSetAndInc        a0, $f14\r
+       portFPUSetAndInc        a0, $f15\r
+       portFPUSetAndInc        a0, $f16\r
+       portFPUSetAndInc        a0, $f17\r
+       portFPUSetAndInc        a0, $f18\r
+       portFPUSetAndInc        a0, $f19\r
+       portFPUSetAndInc        a0, $f20\r
+       portFPUSetAndInc        a0, $f21\r
+       portFPUSetAndInc        a0, $f22\r
+       portFPUSetAndInc        a0, $f23\r
+       portFPUSetAndInc        a0, $f24\r
+       portFPUSetAndInc        a0, $f25\r
+       portFPUSetAndInc        a0, $f26\r
+       portFPUSetAndInc        a0, $f27\r
+       portFPUSetAndInc        a0, $f28\r
+       portFPUSetAndInc        a0, $f29\r
+       portFPUSetAndInc        a0, $f30\r
+       portFPUSetAndInc        a0, $f31\r
+\r
+       jr              ra\r
+       nop\r
 \r
-       /* Pop the status and epc values. */\r
-       lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
-       lw                      k0, portEPC_STACK_LOCATION(sp)\r
+       .end vPortInitialiseFPSCR\r
 \r
-       /* Remove stack frame. */\r
-       addiu           sp, sp, portCONTEXT_SIZE\r
+#endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
+       \r
+#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 )\r
 \r
-       mtc0            k1, _CP0_STATUS\r
-       mtc0            k0, _CP0_EPC\r
-       ehb\r
-       eret\r
+       /**********************************************************************/\r
+       /* Test read back                                                               */\r
+       /* a0 = address to store registers                              */\r
+\r
+       .set            noreorder\r
+       .set            noat\r
+       .section        .text, code\r
+       .ent            vPortFPUReadback\r
+       .global         vPortFPUReadback\r
+\r
+vPortFPUReadback:\r
+       sdc1            $f0, 0(a0)\r
+       sdc1            $f1, 8(a0)\r
+       sdc1            $f2, 16(a0)\r
+       sdc1            $f3, 24(a0)\r
+       sdc1            $f4, 32(a0)\r
+       sdc1            $f5, 40(a0)\r
+       sdc1            $f6, 48(a0)\r
+       sdc1            $f7, 56(a0)\r
+       sdc1            $f8, 64(a0)\r
+       sdc1            $f9, 72(a0)\r
+       sdc1            $f10, 80(a0)\r
+       sdc1            $f11, 88(a0)\r
+       sdc1            $f12, 96(a0)\r
+       sdc1            $f13, 104(a0)\r
+       sdc1            $f14, 112(a0)\r
+       sdc1            $f15, 120(a0)\r
+       sdc1            $f16, 128(a0)\r
+       sdc1            $f17, 136(a0)\r
+       sdc1            $f18, 144(a0)\r
+       sdc1            $f19, 152(a0)\r
+       sdc1            $f20, 160(a0)\r
+       sdc1            $f21, 168(a0)\r
+       sdc1            $f22, 176(a0)\r
+       sdc1            $f23, 184(a0)\r
+       sdc1            $f24, 192(a0)\r
+       sdc1            $f25, 200(a0)\r
+       sdc1            $f26, 208(a0)\r
+       sdc1            $f27, 216(a0)\r
+       sdc1            $f28, 224(a0)\r
+       sdc1            $f29, 232(a0)\r
+       sdc1            $f30, 240(a0)\r
+       sdc1            $f31, 248(a0)\r
+\r
+       jr              ra\r
        nop\r
 \r
-       .end            vPortYieldISR\r
+       .end vPortFPUReadback\r
+\r
+#endif /* ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */\r
+\r
 \r
 \r
 \r