#define MODE_MASK 0x0000001f /* Bits 0-4: Mode bits */ # define USR26_MODE 0x00000000 /* 26-bit User mode */ # define FIQ26_MODE 0x00000001 /* 26-bit FIQ mode */ # define IRQ26_MODE 0x00000002 /* 26-bit IRQ mode */ # define SVC26_MODE 0x00000003 /* 26-bit Supervisor mode */ # define MODE32_BIT 0x00000010 /* Bit 4: 32-bit mode */ # define USR_MODE 0x00000010 /* 32-bit User mode */ # define FIQ_MODE 0x00000011 /* 32-bit FIQ mode */ # define IRQ_MODE 0x00000012 /* 32-bit IRQ mode */ # define SVC_MODE 0x00000013 /* 32-bit Supervisor mode */ # define ABT_MODE 0x00000017 /* 32-bit Abort mode */ # define UND_MODE 0x0000001b /* 32-bit Undefined mode */ # define SYSTEM_MODE 0x0000001f /* 32-bit System mode */ #define PSR_T_BIT 0x00000020 /* Bit 5: Thumb state */ #define PSR_F_BIT 0x00000040 /* Bit 6: FIQ disable */ #define PSR_I_BIT 0x00000080 /* Bit 7: IRQ disable */ /* Bits 8-23: Reserved */ #define PSR_J_BIT 0x01000000 /* Bit 24: Jazelle state bit */ /* Bits 25-26: Reserved */ #define PSR_Q_BIT 0x08000000 /* Bit 27: Sticky overflow */ #define PSR_V_BIT 0x10000000 /* Bit 28: Overflow */ #define PSR_C_BIT 0x20000000 /* Bit 29: Carry/Borrow/Extend */ #define PSR_Z_BIT 0x40000000 /* Bit 30: Zero */ #define PSR_N_BIT 0x80000000 /* Bit 31: Negative/Less than */ /* CR1 bits (CP#15 CR1) */ #define CR_M 0x00000001 /* MMU enable */ #define CR_A 0x00000002 /* Alignment abort enable */ #define CR_C 0x00000004 /* Dcache enable */ #define CR_W 0x00000008 /* Write buffer enable */ #define CR_P 0x00000010 /* 32-bit exception handler */ #define CR_D 0x00000020 /* 32-bit data address range */ #define CR_L 0x00000040 /* Implementation defined */ #define CR_B 0x00000080 /* Big endian */ #define CR_S 0x00000100 /* System MMU protection */ #define CR_R 0x00000200 /* ROM MMU protection */ #define CR_F 0x00000400 /* Implementation defined */ #define CR_Z 0x00000800 /* Implementation defined */ #define CR_I 0x00001000 /* Icache enable */ #define CR_V 0x00002000 /* Vectors relocated to 0xffff0000 */ #define CR_RR 0x00004000 /* Round Robin cache replacement */ #define CR_L4 0x00008000 /* LDR pc can set T bit */ #define CR_DT 0x00010000 #define CR_IT 0x00040000 #define CR_ST 0x00080000 #define CR_FI 0x00200000 /* Fast interrupt (lower latency mode) */ #define CR_U 0x00400000 /* Unaligned access operation */ #define CR_XP 0x00800000 /* Extended page tables */ #define CR_VE 0x01000000 /* Vectored interrupts */ #define REG_R0 (0) #define REG_R1 (1) #define REG_R2 (2) #define REG_R3 (3) #define REG_R4 (4) #define REG_R5 (5) #define REG_R6 (6) #define REG_R7 (7) #define REG_R8 (8) #define REG_R9 (9) #define REG_R10 (10) #define REG_R11 (11) #define REG_R12 (12) #define REG_R13 (13) #define REG_R14 (14) #define REG_R15 (15) #define REG_CPSR (16) #define XCPTCONTEXT_REGS (17) #define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) #define REG_A1 REG_R0 #define REG_A2 REG_R1 #define REG_A3 REG_R2 #define REG_A4 REG_R3 #define REG_V1 REG_R4 #define REG_V2 REG_R5 #define REG_V3 REG_R6 #define REG_V4 REG_R7 #define REG_V5 REG_R8 #define REG_V6 REG_R9 #define REG_V7 REG_R10 #define REG_SB REG_R9 #define REG_SL REG_R10 #define REG_FP REG_R11 #define REG_IP REG_R12 #define REG_SP REG_R13 #define REG_LR REG_R14 #define REG_PC REG_R15 .section data g_irqtmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ g_undeftmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ g_aborttmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ .section text .global irq_handler irq_handler: /* On entry, we are in IRQ mode. We are free to use * the IRQ mode r13 and r14. */ ldr r13, .Lirqtmp sub lr, lr, #4 str lr, [r13] @ save lr_IRQ mrs lr, spsr str lr, [r13, #4] @ save spsr_IRQ /* Then switch back to SVC mode */ bic lr, lr, #MODE_MASK /* Keep F and T bits */ orr lr, lr, #(SVC_MODE | PSR_I_BIT) msr cpsr_c, lr /* Switch to SVC mode */ /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ add r1, sp, #XCPTCONTEXT_SIZE mov r2, r14 /* Get the values for r15(pc) and CPSR in r3 and r4 */ ldr r0, .Lirqtmp /* Points to temp storage */ ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the IRQ handler with interrupts disabled. */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 ldr sp, .Lirqstackbase /* SP = interrupt stack base */ str r0, [sp] /* Save the user stack pointer */ bl irq_handler_c /* Call the handler */ ldr sp, [sp] /* Restore the user stack pointer */ #else bl irq_handler_c /* Call the handler */ /* Restore the CPSR, SVC mode registers and return */ .Lnoirqset: ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 #endif ldmia sp, {r0-r15}^ /* Return */ .Lirqtmp: .word g_irqtmp #if CONFIG_ARCH_INTERRUPTSTACK > 3 .Lirqstackbase: .word g_intstackbase #endif .size irq_handler, . - irq_handler .align 5 .globl swi_handler .type swi_handler, %function swi_handler: /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp), r14(lr), r15(pc) * and CPSR in r1-r4 */ add r1, sp, #XCPTCONTEXT_SIZE mov r2, r14 /* R14 is altered on return from SWI */ mov r3, r14 /* Save r14 as the PC as well */ mrs r4, spsr /* Get the saved CPSR */ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the SWI handler with interrupts disabled. * void up_syscall(struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ /*bl swi_handler_c*/ /* Call the handler */ /* Restore the CPSR, SVC mode registers and return */ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .size swi_handler, . - swi_handler .align 5