123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*****************************************************************
- * exception.s
- * by Zhiyi Huang, [email protected]
- * University of Otago
- *
- ********************************************************************/
- .align 4
- .section .text
- .global vectors
- vectors:
- ldr pc, reset_handler
- ldr pc, undefintr_handler
- ldr pc, swi_handler
- ldr pc, prefetch_handler
- ldr pc, data_handler
- ldr pc, unused_handler
- ldr pc, irq_handler
- ldr pc, fiq_handler
- reset_handler:
- .word hang /* reset, in svc mode already */
- undefintr_handler:
- .word do_und /* undefined instruction */
- swi_handler:
- .word do_svc /* SWI & SVC */
- prefetch_handler:
- .word do_pabt /* prefetch abort */
- data_handler:
- .word do_dabt /* data abort */
- unused_handler:
- .word hang /* reserved */
- irq_handler:
- .word do_irq /* IRQ */
- fiq_handler:
- .word hang /* FIQ */
- hang:
- bl NotOkLoop;
- b hang
- do_svc:
- push {lr}
- mrs lr, spsr
- push {lr}
- mrs lr, cpsr
- push {lr}
- mrc p15, 0, lr, c6, c0, 2 /* read Instruction Fault Address Register (IFAR) */
- push {lr}
- mov lr, #0x40
- push {lr}
- STMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14}
- sub sp, sp, #60
- mov r0, sp /* save sp */
- STMFD r0, {r13}^ /* save user mode sp */
- mov r1, r1 /* three nops after STM with user mode banked registers */
- mov r1, r1
- mov r1, r1
- mov sp, r0 /* restore sp */
- sub sp, sp, #4
- mov r0, sp
- bl trap
- .global trapret
- trapret:
- mov r0, sp /* save sp in case it is changed to sp_usr after the following LDMFD instruction */
- LDMFD r0, {r13}^ /* restore user mode sp */
- mov r1, r1 /* three nops after LDMFD */
- mov r1, r1
- mov r1, r1
- mov sp, r0 /* restore sp */
- add sp, sp, #4
- LDMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
- add sp, sp, #72
- pop {lr}
- msr spsr, lr
- pop {lr}
- movs pc, lr /* subs pc,lr,#0 */
- do_und:
- STMFD sp, {r0-r4}
- mov r0, #0x01
- b _switchtosvc
- do_pabt:
- STMFD sp, {r0-r4}
- mov r0, #0x02
- b _switchtosvc
- do_dabt:
- STMFD sp, {r0-r4}
- mov r0, #0x04
- b _switchtosvc
- do_irq:
- STMFD sp, {r0-r4}
- mov r0, #0x80
- b _switchtosvc
- _switchtosvc:
- mrs r1, spsr
- sub r2, lr, #4
- mov r3, sp
- mrs lr, cpsr
- bic lr, #0x0000001F /* PSR_MASK */
- orr lr, #0x00000080 /* PSR_DISABLE_IRQ */
- orr lr, #0x00000013 /* PSR_MODE_SVC */
- msr cpsr, lr /* switch to svc */
- push {r2}
- push {r1}
- mrs r1, cpsr
- push {r1}
- mrc p15, 0, r1, c6, c0, 2 /* read Instruction Fault Address Register (I
- FAR) */
- push {r1}
- push {r0}
- sub r1, r3, #20
- LDMFD r1, {r0-r4}
- STMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14}
- sub sp, sp, #60
- mov r0, sp /* save sp */
- STMFD r0, {r13}^ /* save user mode sp */
- mov r1, r1 /* three nops after STM with user mode banked registers */
- mov r1, r1
- mov r1, r1
- mov sp, r0 /* restore sp */
- sub sp, sp, #4
- mov r0, sp
- bl trap
- mov r0, sp
- add r0, #76
- LDMIA r0, {r1}
- mov r2, r1
- and r2, #0xf
- cmp r2, #0
- beq _backtouser
- msr cpsr, r1
- add sp, #4
- LDMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
- add sp, sp, #56
- pop {r14}
- add sp, sp, #16
- pop {pc}
- _backtouser:
- mov r0, sp /* save sp in case it is changed to sp_usr after the following LDMFD instruction */
- LDMFD r0, {r13}^ /* restore user mode sp */
- mov r1, r1 /* three nops after LDMFD */
- mov r1, r1
- mov r1, r1
- mov sp, r0 /* restore sp */
- add sp, sp, #4
- LDMIA sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
- add sp, sp, #72
- pop {lr}
- msr spsr, lr
- pop {lr}
- movs pc, lr /* subs pc,lr,#0 */
- .global set_mode_sp
- set_mode_sp:
- mrs r2, cpsr
- msr cpsr_c,r1
- mov sp, r0
- mrs r0, cpsr
- orr r0, #0x00000080 /* PSR_DISABLE_IRQ */
- orr r0, #0x00000040 /* PSR_DISABLE_FIQ */
- msr cpsr, r0
- msr cpsr_c, r2
- bx lr
- .global readcpsr
- readcpsr:
- mrs r0, cpsr
- bx lr
- .global cli
- cli:
- mrs r0, cpsr
- orr r0, #0x00000080 /* PSR_DISABLE_IRQ */
- msr cpsr, r0
- bx lr
- .global sti
- sti:
- mrs r0, cpsr
- bic r0, r0, #0x00000080 /* PSR_DISABLE_IRQ */
- msr cpsr, r0
- bx lr
- .global swtch
- swtch:
- push {lr} /* save the return address */
- push {lr}
- /* save old callee-save registers */
- push {r12}
- push {r11}
- push {r10}
- push {r9}
- push {r8}
- push {r7}
- push {r6}
- push {r5}
- push {r4}
- /* switch stacks */
- str sp, [r0]
- mov sp, r1
- /* load new callee-save registers */
- pop {r4}
- pop {r5}
- pop {r6}
- pop {r7}
- pop {r8}
- pop {r9}
- pop {r10}
- pop {r11}
- pop {r12}
- /* return to previously saved pc */
- pop {lr}
- pop {pc}
|