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