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__