Mercurial > ecos
comparison packages/hal/arm/arch/current/src/vectors.S @ 208:e0c0827131d1 ecos
Merge from eCos master repository on 2002-05-20-20:11:54-BST
| author | jlarmour |
|---|---|
| date | Mon, 20 May 2002 22:19:26 +0000 |
| parents | cd45958b28ff |
| children | d2c90368aeef |
comparison
equal
deleted
inserted
replaced
| 207:74c807ddde34 | 208:e0c0827131d1 |
|---|---|
| 3 // # vectors.S | 3 // # vectors.S |
| 4 // # | 4 // # |
| 5 // # ARM exception vectors | 5 // # ARM exception vectors |
| 6 // # | 6 // # |
| 7 // #======================================================================== | 7 // #======================================================================== |
| 8 // ####COPYRIGHTBEGIN#### | 8 //####ECOSGPLCOPYRIGHTBEGIN#### |
| 9 // | 9 // ------------------------------------------- |
| 10 // ------------------------------------------- | 10 // This file is part of eCos, the Embedded Configurable Operating System. |
| 11 // The contents of this file are subject to the Red Hat eCos Public License | 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
| 12 // Version 1.1 (the "License"); you may not use this file except in | 12 // |
| 13 // compliance with the License. You may obtain a copy of the License at | 13 // eCos is free software; you can redistribute it and/or modify it under |
| 14 // http://www.redhat.com/ | 14 // the terms of the GNU General Public License as published by the Free |
| 15 // | 15 // Software Foundation; either version 2 or (at your option) any later version. |
| 16 // Software distributed under the License is distributed on an "AS IS" | 16 // |
| 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | 17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
| 18 // License for the specific language governing rights and limitations under | 18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 19 // the License. | 19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 20 // | 20 // for more details. |
| 21 // The Original Code is eCos - Embedded Configurable Operating System, | 21 // |
| 22 // released September 30, 1998. | 22 // You should have received a copy of the GNU General Public License along |
| 23 // | 23 // with eCos; if not, write to the Free Software Foundation, Inc., |
| 24 // The Initial Developer of the Original Code is Red Hat. | 24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
| 25 // Portions created by Red Hat are | 25 // |
| 26 // Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. | 26 // As a special exception, if other files instantiate templates or use macros |
| 27 // All Rights Reserved. | 27 // or inline functions from this file, or you compile this file and link it |
| 28 // ------------------------------------------- | 28 // with other works to produce a work based on this file, this file does not |
| 29 // | 29 // by itself cause the resulting work to be covered by the GNU General Public |
| 30 // ####COPYRIGHTEND#### | 30 // License. However the source code for this file must still be made available |
| 31 // in accordance with section (3) of the GNU General Public License. | |
| 32 // | |
| 33 // This exception does not invalidate any other reasons why a work based on | |
| 34 // this file might be covered by the GNU General Public License. | |
| 35 // | |
| 36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. | |
| 37 // at http://sources.redhat.com/ecos/ecos-license | |
| 38 // ------------------------------------------- | |
| 39 //####ECOSGPLCOPYRIGHTEND#### | |
| 31 // #======================================================================== | 40 // #======================================================================== |
| 32 // ######DESCRIPTIONBEGIN#### | 41 // ######DESCRIPTIONBEGIN#### |
| 33 // # | 42 // # |
| 34 // # Author(s): nickg, gthomas | 43 // # Author(s): nickg, gthomas |
| 35 // # Contributors: nickg, gthomas | 44 // # Contributors: nickg, gthomas |
| 131 #endif | 140 #endif |
| 132 | 141 |
| 133 #define UNMAPPED_PTR(name) \ | 142 #define UNMAPPED_PTR(name) \ |
| 134 .##name: .word UNMAPPED(name) | 143 .##name: .word UNMAPPED(name) |
| 135 | 144 |
| 136 .file "vectors.S" | 145 // .file "vectors.S" |
| 137 | 146 |
| 138 | 147 |
| 139 // CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to | 148 // CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to |
| 140 // use r0+r1. Argument is in "\x" - cannot use macro arguments since the | 149 // use r0+r1. Argument is in "\x" - cannot use macro arguments since the |
| 141 // macro may contain #-chars and use of arguments cause these to be | 150 // macro may contain #-chars and use of arguments cause these to be |
| 230 .rept CYGNUM_CALL_IF_TABLE_SIZE | 239 .rept CYGNUM_CALL_IF_TABLE_SIZE |
| 231 .long 0 | 240 .long 0 |
| 232 .endr | 241 .endr |
| 233 #endif | 242 #endif |
| 234 | 243 |
| 244 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT | |
| 245 .balign 16 // Should be at 0x50 | |
| 246 ice_thread_vector: | |
| 247 .long 0 // Must be 'MICE' | |
| 248 .long 0 // Pointer to thread support vector | |
| 249 .long 0 // eCos executing flag | |
| 250 .long 0 // Must be 'GDB ' | |
| 251 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT | |
| 235 .balign 32 | 252 .balign 32 |
| 236 | 253 |
| 237 // Other vectors - this may include "fixed" locations | 254 // Other vectors - this may include "fixed" locations |
| 238 #ifdef PLATFORM_VECTORS | 255 #ifdef PLATFORM_VECTORS |
| 239 PLATFORM_VECTORS | 256 PLATFORM_VECTORS |
| 272 str r2,[r0,#0x24] | 289 str r2,[r0,#0x24] |
| 273 #endif | 290 #endif |
| 274 ldr r2,[r1,#0x08] // software interrupt | 291 ldr r2,[r1,#0x08] // software interrupt |
| 275 str r2,[r0,#0x08] | 292 str r2,[r0,#0x08] |
| 276 | 293 |
| 294 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT | |
| 295 ldr r2,=ice_thread_vector | |
| 296 sub r2,r2,r1 // compute fixed (low memory) address | |
| 297 ldr r3,=0x4D494345 // 'MICE' | |
| 298 str r3,[r2],#4 | |
| 299 ldr r3,=hal_arm_ice_thread_handler | |
| 300 str r3,[r2],#4 | |
| 301 mov r3,#1 | |
| 302 str r3,[r2],#4 | |
| 303 ldr r3,=0x47444220 // 'GDB ' | |
| 304 str r3,[r2],#4 | |
| 305 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT | |
| 277 | 306 |
| 278 #if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT) | 307 #if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT) |
| 279 // Ugly hack to get into supervisor mode | 308 // Ugly hack to get into supervisor mode |
| 280 ldr r2,[r1,#0x40] | 309 ldr r2,[r1,#0x40] |
| 281 str r2,[r0,#0x28] | 310 str r2,[r0,#0x28] |
| 371 | 400 |
| 372 // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!! | 401 // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!! |
| 373 msr spsr,r0 | 402 msr spsr,r0 |
| 374 | 403 |
| 375 // initialize stack | 404 // initialize stack |
| 405 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK | |
| 406 // use interrupt stack for system initialization since it's bigger | |
| 407 // than the "startup" stack in this configuration | |
| 408 ldr sp,.__interrupt_stack | |
| 409 #else | |
| 376 ldr sp,.__startup_stack | 410 ldr sp,.__startup_stack |
| 411 #endif | |
| 377 | 412 |
| 378 // clear BSS | 413 // clear BSS |
| 379 ldr r1,.__bss_start | 414 ldr r1,.__bss_start |
| 380 ldr r2,.__bss_end | 415 ldr r2,.__bss_end |
| 381 mov r0,#0 | 416 mov r0,#0 |
| 382 cmp r1,r2 | 417 cmp r1,r2 |
| 383 beq 2f | 418 beq 2f |
| 384 1: str r0,[r1],#4 | 419 1: str r0,[r1],#4 |
| 385 cmp r1,r2 | 420 cmp r1,r2 |
| 386 bne 1b | 421 bls 1b |
| 387 2: | 422 2: |
| 388 | 423 |
| 389 // Run kernel + application in THUMB mode | 424 // Run kernel + application in THUMB mode |
| 390 THUMB_MODE(r1,10) | 425 THUMB_MODE(r1,10) |
| 391 | 426 |
| 425 bl cyg_hal_invoke_constructors | 460 bl cyg_hal_invoke_constructors |
| 426 | 461 |
| 427 LED 1 | 462 LED 1 |
| 428 | 463 |
| 429 // This starts up the eCos kernel | 464 // This starts up the eCos kernel |
| 465 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK | |
| 466 ldr sp,.__startup_stack | |
| 467 #endif | |
| 430 bl cyg_start | 468 bl cyg_start |
| 431 _start_hang: | 469 _start_hang: |
| 432 b _start_hang | 470 b _start_hang |
| 433 .code 32 | 471 .code 32 |
| 434 | 472 |
| 448 init_done: | 486 init_done: |
| 449 .long 0xDEADB00B | 487 .long 0xDEADB00B |
| 450 | 488 |
| 451 // | 489 // |
| 452 // Exception handlers | 490 // Exception handlers |
| 453 // Assumption: get here from a Supervisor context [mode] | 491 // Assumption: get here from a non-user context [mode] |
| 454 // | 492 // |
| 455 .code 32 | 493 .code 32 |
| 456 undefined_instruction: | 494 undefined_instruction: |
| 457 ldr sp,.__undef_exception_stack // get good stack | 495 ldr sp,.__undef_exception_stack // get good stack |
| 458 stmfd sp!,{r0,fp,ip,lr} | 496 stmfd sp!,{r0-r5} // save some supervisor regs |
| 459 mrs r0,spsr | 497 mrs r1,spsr |
| 460 stmfd sp!,{r0} | 498 tst r1,#CPSR_THUMB_ENABLE |
| 461 mov ip,sp // save SP which will vanish with | 499 subeq r0,lr,#4 // PC at time of interrupt (ARM) |
| 462 // mode switch | 500 subne r0,lr,#2 // PC at time of interrupt (thumb) |
| 463 mrs r0,cpsr // switch to Supervisor Mode | 501 mov r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION |
| 464 bic r0,r0,#CPSR_MODE_BITS | 502 mov r3,sp |
| 465 orr r0,r0,#CPSR_SUPERVISOR_MODE | |
| 466 msr cpsr,r0 // sp,lr are now old values | |
| 467 mov fp,sp | |
| 468 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS | |
| 469 ldr sp,.__GDB_stack | |
| 470 cmp fp,sp // already on GDB stack? | |
| 471 bhi 10f | |
| 472 ldr r0,.__GDB_stack_base | |
| 473 cmp fp,r0 | |
| 474 bls 10f // no - switch to GDB stack | |
| 475 // (already in sp) | |
| 476 mov sp,fp // yes - no switch | |
| 477 10: | |
| 478 #endif | |
| 479 sub sp,sp,#ARMREG_SIZE // make space for frame | |
| 480 stmea sp,{r0-r10,fp} // save immediately visible registers | |
| 481 ldmfd ip,{r0-r4} // saved registers | |
| 482 // Adjust PC according to CPU mode | |
| 483 tst r0,#CPSR_THUMB_ENABLE | |
| 484 subeq r4,r4,#4 // PC at time of interrupt (ARM) | |
| 485 subne r4,r4,#2 // PC at time of interrupt (thumb) | |
| 486 str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt | |
| 487 str r1,[sp,#armreg_r0] // saved R0 | |
| 488 str r2,[sp,#armreg_fp] // saved FP | |
| 489 str r3,[sp,#armreg_ip] // saved IP | |
| 490 str r4,[sp,#armreg_pc] // PC at time of interrupt | |
| 491 str lr,[sp,#armreg_lr] // LR at time of interrupt | |
| 492 add r0,ip,#ARMREG_SIZE | |
| 493 str fp,[sp,#armreg_sp] // SP at time of interrupt | |
| 494 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | |
| 495 mov r0,sp | |
| 496 bl cyg_hal_report_undefined_instruction | |
| 497 #endif | |
| 498 mov v1,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION | |
| 499 b call_exception_handler | 503 b call_exception_handler |
| 500 | 504 |
| 501 .code 32 | 505 .code 32 |
| 502 software_interrupt: | 506 software_interrupt: |
| 503 sub sp,sp,#ARMREG_SIZE+16 // make space for frame | 507 stmfd sp!,{r8} |
| 504 stmea sp,{r0-r10,fp} // save immediately visible registers | 508 ldr r8,.__undef_exception_stack // get good stack |
| 505 mrs r0,spsr | 509 stmfd r8!,{r0-r5} // save some supervisor regs |
| 506 // Adjust PC according to CPU mode | 510 mov r3,r8 |
| 507 tst r0,#CPSR_THUMB_ENABLE | 511 ldmfd sp!,{r8} |
| 508 subeq r3,lr,#4 // PC at time of interrupt (ARM) | 512 mrs r1,spsr |
| 509 subne r3,lr,#2 // PC at time of interrupt (thumb) | 513 tst r1,#CPSR_THUMB_ENABLE |
| 510 str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt | 514 subeq r0,lr,#4 // PC at time of SWI (ARM) |
| 511 str ip,[sp,#armreg_ip] // saved IP | 515 subne r0,lr,#2 // PC at time of SWI (thumb) |
| 512 str r3,[sp,#armreg_pc] // PC at time of interrupt | 516 mov r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT |
| 513 str lr,[sp,#armreg_lr] // LR at time of interrupt | |
| 514 add r0,sp,#ARMREG_SIZE+16 | |
| 515 str r0,[sp,#armreg_sp] // SP at time of interrupt | |
| 516 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | |
| 517 mov r0,sp | |
| 518 bl cyg_hal_report_software_interrupt | |
| 519 #endif | |
| 520 mov v1,#CYGNUM_HAL_EXCEPTION_INTERRUPT | |
| 521 b call_exception_handler | 517 b call_exception_handler |
| 522 | 518 |
| 523 .code 32 | 519 .code 32 |
| 524 abort_prefetch: | 520 abort_prefetch: |
| 525 ldr sp,.__undef_exception_stack // get good stack | 521 ldr sp,.__undef_exception_stack // get good stack |
| 526 sub lr,lr,#4 // PC at time of interrupt | 522 stmfd sp!,{r0-r5} // save some supervisor regs |
| 527 stmfd sp!,{r0,fp,ip,lr} | 523 sub r0,lr,#4 // PC at time of interrupt |
| 528 mrs r0,spsr | 524 mrs r1,spsr |
| 529 stmfd sp!,{r0} | 525 mov r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS |
| 530 mov ip,sp // save SP which will vanish with | 526 mov r3,sp |
| 531 // mode switch | |
| 532 mrs r0,cpsr // switch to Supervisor Mode | |
| 533 bic r0,r0,#CPSR_MODE_BITS | |
| 534 orr r0,r0,#CPSR_SUPERVISOR_MODE | |
| 535 msr cpsr,r0 // sp,lr are now old values | |
| 536 mov fp,sp | |
| 537 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS | |
| 538 ldr sp,.__GDB_stack | |
| 539 cmp fp,sp // already on GDB stack? | |
| 540 bhi 10f | |
| 541 ldr r0,.__GDB_stack_base | |
| 542 cmp fp,r0 | |
| 543 bls 10f // no - switch to GDB stack | |
| 544 // (already in sp) | |
| 545 mov sp,fp // yes - no switch | |
| 546 10: | |
| 547 #endif | |
| 548 sub sp,sp,#ARMREG_SIZE // make space for frame | |
| 549 stmea sp,{r0-r10,fp} // save immediately visible registers | |
| 550 ldmfd ip,{r0-r4} // saved registers | |
| 551 str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt | |
| 552 str r1,[sp,#armreg_r0] // saved R0 | |
| 553 str r2,[sp,#armreg_fp] // saved FP | |
| 554 str r3,[sp,#armreg_ip] // saved IP | |
| 555 str r4,[sp,#armreg_pc] // PC at time of interrupt | |
| 556 str lr,[sp,#armreg_lr] // LR at time of interrupt | |
| 557 add r0,ip,#ARMREG_SIZE | |
| 558 str fp,[sp,#armreg_sp] // SP at time of interrupt | |
| 559 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | |
| 560 mov r0,sp | |
| 561 bl cyg_hal_report_abort_prefetch | |
| 562 #endif | |
| 563 mov v1,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS | |
| 564 b call_exception_handler | 527 b call_exception_handler |
| 565 | 528 |
| 566 .code 32 | 529 .code 32 |
| 567 abort_data: | 530 abort_data: |
| 568 ldr sp,.__undef_exception_stack // get good stack | 531 ldr sp,.__undef_exception_stack // get good stack |
| 569 sub lr,lr,#4 // PC at time of interrupt | 532 stmfd sp!,{r0-r5} // save some supervisor regs |
| 570 stmfd sp!,{r0,fp,ip,lr} | 533 sub r0,lr,#4 // PC at time of interrupt |
| 571 mrs r0,spsr | 534 mrs r1,spsr |
| 572 stmfd sp!,{r0} | 535 mov r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS |
| 573 mov ip,sp // save SP which will vanish with | 536 mov r3,sp |
| 574 // mode switch | 537 b call_exception_handler |
| 575 mrs r0,cpsr // switch to Supervisor Mode | 538 |
| 576 bic r0,r0,#CPSR_MODE_BITS | 539 // |
| 577 orr r0,r0,#CPSR_SUPERVISOR_MODE | 540 // Dispatch an exception handler. |
| 578 msr cpsr,r0 // sp,lr are now old values | 541 |
| 579 mov fp,sp | 542 .code 32 |
| 543 call_exception_handler: | |
| 544 // | |
| 545 // On Entry: | |
| 546 // | |
| 547 // r4,r5 = scratch | |
| 548 // r3 = pointer to temp save area | |
| 549 // r2 = vector number | |
| 550 // r1 = exception psr | |
| 551 // r0 = exception pc | |
| 552 // | |
| 553 // [r3+20]: exception r5 | |
| 554 // [r3+16]: exception r4 | |
| 555 // [r3+12]: exception r3 | |
| 556 // [r3+8] : exception r2 | |
| 557 // [r3+4] : exception r1 | |
| 558 // [r3] : exception r0 | |
| 559 | |
| 560 mrs r4,cpsr // switch to Supervisor Mode | |
| 561 bic r4,r4,#CPSR_MODE_BITS | |
| 562 orr r4,r4,#CPSR_SUPERVISOR_MODE | |
| 563 msr cpsr,r4 | |
| 564 | |
| 565 mov r5,sp // save original svc sp | |
| 566 mov r4,lr // and original svc lr | |
| 580 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS | 567 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
| 568 // Make sure we use the GDB stack. | |
| 581 ldr sp,.__GDB_stack | 569 ldr sp,.__GDB_stack |
| 582 cmp fp,sp // already on GDB stack? | 570 cmp r5,sp // already on GDB stack? |
| 583 bhi 10f | 571 bhi 10f |
| 584 ldr r0,.__GDB_stack_base | 572 ldr r4,.__GDB_stack_base |
| 585 cmp fp,r0 | 573 cmp r5,r4 |
| 586 bls 10f // no - switch to GDB stack | 574 movhi sp,r5 |
| 587 // (already in sp) | |
| 588 mov sp,fp // yes - no switch | |
| 589 10: | 575 10: |
| 590 #endif | 576 #endif |
| 591 sub sp,sp,#ARMREG_SIZE // make space for frame | 577 // |
| 592 stmea sp,{r0-r10,fp} // save immediately visible registers | 578 // r5 holds original svc sp, current sp is stack to use |
| 593 ldmfd ip,{r0-r4} // saved registers | 579 // r4 holds original svc lr, which must also be preserved |
| 594 str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt | 580 // |
| 595 str r1,[sp,#armreg_r0] // saved R0 | 581 |
| 596 str r2,[sp,#armreg_fp] // saved FP | 582 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc |
| 597 str r3,[sp,#armreg_ip] // saved IP | 583 |
| 598 str r4,[sp,#armreg_pc] // PC at time of interrupt | 584 // switch to pre-exception mode to get banked regs |
| 599 str lr,[sp,#armreg_lr] // LR at time of interrupt | 585 mov r0,sp // r0 survives mode switch |
| 600 add r0,ip,#ARMREG_SIZE | 586 mrs r2,cpsr // Save current psr for return |
| 601 str fp,[sp,#armreg_sp] // SP at time of interrupt | 587 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE |
| 588 msr cpsr,r1 | |
| 589 stmfd r0!,{r8-r12,sp,lr} | |
| 590 msr cpsr,r2 // back to svc mode | |
| 591 mov sp,r0 // update stack pointer | |
| 592 | |
| 593 // now save pre-exception r0-r7 on current stack | |
| 594 ldmfd r3,{r0-r5} | |
| 595 stmfd sp!,{r0-r7} | |
| 596 | |
| 597 // SP needs fixing if exception occured in SVC mode. | |
| 598 // The original SVC LR is still in place so that | |
| 599 // does not need to be fixed here. | |
| 600 ldr r1,[sp,#armreg_cpsr] | |
| 601 and r1,r1,#CPSR_MODE_BITS | |
| 602 cmp r1,#CPSR_SUPERVISOR_MODE | |
| 603 ldreq r1,[sp,#armreg_svcsp] | |
| 604 streq r1,[sp,#armreg_sp] | |
| 605 | |
| 602 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | 606 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS |
| 603 mov r0,sp | 607 mov r0,sp |
| 604 bl cyg_hal_report_abort_data | 608 ldr r1,.__dump_procs |
| 605 #endif | 609 ldr r2,[sp,#armreg_vector] |
| 606 mov v1,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS | 610 mov lr,pc |
| 607 b call_exception_handler | 611 ldr pc,[r1,r2,lsl #2] |
| 608 | 612 #endif |
| 609 | 613 |
| 610 // | 614 // call exception handler |
| 611 // Dispatch an exception handler. | |
| 612 | |
| 613 .code 32 | |
| 614 call_exception_handler: | |
| 615 str v1,[sp,#armreg_vector] | |
| 616 mov r0,sp | 615 mov r0,sp |
| 617 | |
| 618 THUMB_MODE(r9,10) | 616 THUMB_MODE(r9,10) |
| 619 | |
| 620 bl exception_handler | 617 bl exception_handler |
| 618 | |
| 621 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | 619 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS |
| 622 mov r0,sp | 620 mov r0,sp |
| 623 bl cyg_hal_report_exception_handler_returned | 621 bl cyg_hal_report_exception_handler_returned |
| 624 #endif | 622 #endif |
| 625 | 623 |
| 626 ARM_MODE(r1,10) | 624 ARM_MODE(r1,10) |
| 627 | 625 |
| 628 // Restore [interrupted] context | 626 // |
| 629 mov ip,sp // get stack pointer | 627 // Return from exception |
| 630 | 628 // |
| 631 mrs r0,cpsr // move back to IRQ mode | 629 return_from_exception: |
| 630 | |
| 631 ldr r0,[sp,#armreg_cpsr] | |
| 632 msr spsr,r0 | |
| 633 | |
| 634 // return to supervisor mode is simple | |
| 635 and r1,r0,#CPSR_MODE_BITS | |
| 636 cmp r1,#CPSR_SUPERVISOR_MODE | |
| 637 ldmeqfd sp,{r0-r14,pc}^ | |
| 638 | |
| 639 // | |
| 640 // return to other non-user modes is a little trickier | |
| 641 // | |
| 642 | |
| 643 // switch to pre-exception mode and restore r8-r14 | |
| 644 add r2,sp,#armreg_r8 | |
| 645 mrs r1,cpsr | |
| 632 orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE | 646 orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE |
| 633 msr cpsr,r0 | 647 msr cpsr,r0 |
| 634 nop | 648 ldmfd r2,{r8-r14} |
| 635 nop | 649 msr cpsr, r1 // back to svc mode |
| 636 | 650 |
| 637 ldr lr,[ip,#armreg_lr] | 651 // move sp,lr and pc for final load |
| 638 ldr sp,[sp,#armreg_sp] | 652 ldr r0,[sp,#armreg_svcsp] |
| 639 | 653 str r0,[sp,#armreg_r8] |
| 640 bic r0,r0,#CPSR_MODE_BITS | 654 ldr r0,[sp,#armreg_svclr] |
| 641 orr r0,r0,#CPSR_IRQ_MODE | 655 str r0,[sp,#armreg_r9] |
| 642 msr cpsr,r0 | 656 ldr r0,[sp,#armreg_pc] |
| 643 | 657 str r0,[sp,#armreg_r10] |
| 644 mov sp,ip | 658 |
| 645 ldr lr,[sp,#armreg_pc] | 659 // restore r0-r7,sp,lr and return from exception |
| 646 ldr r0,[sp,#armreg_cpsr] | 660 ldmfd sp,{r0-r7,sp,lr,pc}^ |
| 647 ldr ip,[sp,#armreg_ip] | 661 |
| 648 msr spsr,r0 | 662 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS |
| 649 ldmfd sp,{r0-r10,fp} | 663 __dump_procs: |
| 650 | 664 .word 0 // placeholder for reset |
| 651 movs pc,lr // restore PC from LR, CPSR from SPSR | 665 .word cyg_hal_report_undefined_instruction |
| 666 .word cyg_hal_report_software_interrupt | |
| 667 .word cyg_hal_report_abort_prefetch | |
| 668 .word cyg_hal_report_abort_data | |
| 669 .word 0 // reserved | |
| 670 #endif | |
| 671 | |
| 652 | 672 |
| 653 // Handle device interrupts | 673 // Handle device interrupts |
| 654 // This is slightly more complicated than the other exception handlers because | 674 // This is slightly more complicated than the other exception handlers because |
| 655 // it needs to interface with the kernel (if present). | 675 // it needs to interface with the kernel (if present). |
| 656 | 676 |
| 657 .code 32 | 677 .code 32 |
| 658 FIQ: | 678 FIQ: |
| 659 // We can get here from supervisor mode or from IRQ mode. | 679 // We can get here from any non-user mode. |
| 660 mrs r8,spsr // CPSR at time of interrupt | 680 mrs r8,spsr // CPSR at time of interrupt |
| 661 and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode | 681 and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode |
| 662 cmp r9,#CPSR_IRQ_MODE | 682 cmp r9,#CPSR_IRQ_MODE |
| 663 bne 1f | 683 bne 1f |
| 664 // If FIQ interrupted IRQ mode, just return with FIQ disabled. | 684 // If FIQ interrupted IRQ mode, just return with FIQ disabled. |
| 665 // The common interrupt handling takes care of the rest. | 685 // The common interrupt handling takes care of the rest. |
| 666 orr r8,r8,#CPSR_FIQ_DISABLE | 686 orr r8,r8,#CPSR_FIQ_DISABLE |
| 667 msr spsr,r8 | 687 msr spsr,r8 |
| 668 subs pc,lr,#4 | 688 subs pc,lr,#4 |
| 669 1: | 689 1: |
| 670 // If FIQ interrupted supervisor mode, switch to IRQ mode and | 690 // If FIQ interrupted other non-user mode, switch to IRQ mode and |
| 671 // fall through to IRQ handler. | 691 // fall through to IRQ handler. |
| 672 ldr sp,.__exception_stack // get good stack to save lr and spsr | 692 ldr sp,.__exception_stack // get good stack to save lr and spsr |
| 673 stmdb sp,{r8,lr} | 693 stmdb sp,{r8,lr} |
| 674 mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE | 694 mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE |
| 675 msr cpsr,r8 // switch to IRQ mode | 695 msr cpsr,r8 // switch to IRQ mode |
| 677 ldmdb sp,{sp,lr} | 697 ldmdb sp,{sp,lr} |
| 678 msr spsr,sp | 698 msr spsr,sp |
| 679 | 699 |
| 680 // now it looks like we got an IRQ instead of an FIQ except that | 700 // now it looks like we got an IRQ instead of an FIQ except that |
| 681 // FIQ is disabled so we don't recurse. | 701 // FIQ is disabled so we don't recurse. |
| 682 | |
| 683 IRQ: | 702 IRQ: |
| 684 // Note: I use this exception stack while saving the context because | 703 // Note: I use this exception stack while saving the context because |
| 685 // the current SP does not seem to be always valid in this CPU mode. | 704 // the current SP does not seem to be always valid in this CPU mode. |
| 686 ldr sp,.__exception_stack // get good stack | 705 ldr sp,.__exception_stack // get good stack |
| 687 sub lr,lr,#4 // PC at time of interrupt | 706 stmfd sp!,{r0-r5} // save some supervisor regs |
| 688 stmfd sp!,{r0,fp,ip,lr} | 707 sub r0,lr,#4 // PC at time of interrupt |
| 689 mrs r0,spsr | 708 mrs r1,spsr |
| 690 stmfd sp!,{r0} | 709 mov r2,#CYGNUM_HAL_VECTOR_IRQ |
| 691 | 710 mov r3,sp |
| 692 handle_IRQ_or_FIQ: | 711 |
| 693 mov ip,sp // save SP which will vanish with | 712 handle_IRQ_or_FIQ: |
| 694 // mode switch | 713 |
| 695 mrs r0,cpsr // switch to Supervisor Mode | 714 mrs r4,cpsr // switch to Supervisor Mode |
| 696 bic r0,r0,#CPSR_MODE_BITS | 715 bic r4,r4,#CPSR_MODE_BITS |
| 697 orr r0,r0,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE | 716 orr r4,r4,#CPSR_SUPERVISOR_MODE |
| 698 msr cpsr,r0 // sp,lr are now old values | 717 msr cpsr,r4 |
| 699 mov fp,sp // save old SP | 718 |
| 700 sub sp,sp,#ARMREG_SIZE // make space for frame | 719 mov r5,sp // save original svc sp |
| 701 stmea sp,{r0-r10,fp} // save immediately visible registers | 720 mov r4,lr // save original svc lr |
| 702 ldmfd ip,{r0-r4} // saved registers | 721 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc |
| 703 str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt | 722 |
| 704 str r1,[sp,#armreg_r0] // saved R0 | 723 // switch to pre-exception mode to get banked regs |
| 705 str r2,[sp,#armreg_fp] // saved FP | 724 mov r0,sp // r0 survives mode switch |
| 706 str r3,[sp,#armreg_ip] // saved IP | 725 mrs r2,cpsr // Save current psr for return |
| 707 str r4,[sp,#armreg_pc] // PC at time of interrupt | 726 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE |
| 708 str lr,[sp,#armreg_lr] // LR at time of interrupt | 727 msr cpsr,r1 |
| 709 str fp,[sp,#armreg_sp] // SP at time of interrupt | 728 stmfd r0!,{r8-r12,sp,lr} |
| 710 mov r0,#CYGNUM_HAL_VECTOR_IRQ // FIXME: we don't distinguish | 729 msr cpsr,r2 // back to svc mode |
| 711 str r0,[sp,#armreg_vector] // FIQ and IRQ here | 730 mov sp,r0 // update stack pointer |
| 731 | |
| 732 // now save pre-exception r0-r7 on current stack | |
| 733 ldmfd r3,{r0-r5} | |
| 734 stmfd sp!,{r0-r7} | |
| 735 | |
| 736 // sp needs fixing if exception occured in SVC mode. | |
| 737 ldr r1,[sp,#armreg_cpsr] | |
| 738 and r1,r1,#CPSR_MODE_BITS | |
| 739 cmp r1,#CPSR_SUPERVISOR_MODE | |
| 740 ldreq r1,[sp,#armreg_svcsp] | |
| 741 streq r1,[sp,#armreg_sp] | |
| 742 | |
| 712 mov v6,sp // Save pointer to register frame | 743 mov v6,sp // Save pointer to register frame |
| 713 | 744 |
| 714 // mov r0,sp | 745 // mov r0,sp |
| 715 // bl _show_frame_in | 746 // bl _show_frame_in |
| 716 | 747 |
| 833 #endif | 864 #endif |
| 834 | 865 |
| 835 // mov r0,sp | 866 // mov r0,sp |
| 836 // bl show_frame_out | 867 // bl show_frame_out |
| 837 | 868 |
| 838 mov ip,sp // get stack pointer | 869 // return from IRQ is same as return from exception |
| 839 | 870 b return_from_exception |
| 840 mrs r0,cpsr // move back to IRQ mode | |
| 841 orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE | |
| 842 msr cpsr,r0 | |
| 843 nop | |
| 844 nop | |
| 845 | |
| 846 ldr lr,[ip,#armreg_lr] | |
| 847 ldr sp,[sp,#armreg_sp] | |
| 848 | |
| 849 bic r0,r0,#CPSR_MODE_BITS | |
| 850 orr r0,r0,#CPSR_IRQ_MODE | |
| 851 msr cpsr,r0 | |
| 852 | |
| 853 mov sp,ip | |
| 854 ldr lr,[sp,#armreg_pc] | |
| 855 ldr r0,[sp,#armreg_cpsr] | |
| 856 ldr ip,[sp,#armreg_ip] | |
| 857 msr spsr,r0 | |
| 858 ldmfd sp,{r0-r10,fp} | |
| 859 movs pc,lr // restore PC from LR, CPSR from SPSR | |
| 860 | 871 |
| 861 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK | 872 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
| 862 // Execute pending DSRs the interrupt stack | 873 // Execute pending DSRs the interrupt stack |
| 863 // Note: this can only be called from code running on a thread stack | 874 // Note: this can only be called from code running on a thread stack |
| 864 FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1) | 875 FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1) |
| 999 #endif | 1010 #endif |
| 1000 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK | 1011 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
| 1001 PTR(irq_level) | 1012 PTR(irq_level) |
| 1002 PTR(__interrupt_stack) | 1013 PTR(__interrupt_stack) |
| 1003 #endif | 1014 #endif |
| 1015 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS | |
| 1016 PTR(__dump_procs) | |
| 1017 #endif | |
| 1004 | 1018 |
| 1005 // | 1019 // |
| 1006 // Identification - useful to find out when a system was configured | 1020 // Identification - useful to find out when a system was configured |
| 1007 _eCos_id: | 1021 _eCos_id: |
| 1008 .asciz "eCos : " __DATE__ | 1022 .asciz "eCos : " __DATE__ |
