fernly/irqasm.S
2014-08-27 12:32:06 +08:00

212 lines
8.2 KiB
ArmAsm

#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