entry-armv.s
来自「Linux Kernel 2.6.9 for OMAP1710」· S 代码 · 共 1,729 行 · 第 1/3 页
S
1,729 行
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE)) ldr \irqnr,[\irqstat] cmp \irqnr,#0 subne \irqnr,\irqnr,#1 .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_IOP321) .macro disable_fiq .endm /* * Note: only deal with normal interrupts, not FIQ */ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqnr, #0 mrc p6, 0, \irqstat, c8, c0, 0 @ Read IINTSRC cmp \irqstat, #0 beq 1001f clz \irqnr, \irqstat mov \base, #31 subs \irqnr,\base,\irqnr add \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT1001: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_IOP331) .macro disable_fiq .endm /* * Note: only deal with normal interrupts, not FIQ */ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqnr, #0 mrc p6, 0, \irqstat, c4, c0, 0 @ Read IINTSRC0 cmp \irqstat, #0 bne 1002f mrc p6, 0, \irqstat, c5, c0, 0 @ Read IINTSRC1 cmp \irqstat, #0 beq 1001f clz \irqnr, \irqstat/* * mov \base, #31 * subs \irqnr,\base,\irqnr */ rsbs \irqnr,\irqnr,#31 @ recommend by RMK add \irqnr,\irqnr,#IRQ_IOP331_XINT8 b 1001f1002: clz \irqnr, \irqstat mov \base, #31 subs \irqnr,\base,\irqnr add \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT1001: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_PXA) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp#ifdef CONFIG_PXA27x mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR#else mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000 add \base, \base, #0x00d00000 ldr \irqstat, [\base, #0] @ ICIP ldr \irqnr, [\base, #4] @ ICMR#endif ands \irqnr, \irqstat, \irqnr beq 1001f rsb \irqstat, \irqnr, #0 and \irqstat, \irqstat, \irqnr clz \irqnr, \irqstat rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)1001: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_IXP2000) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqnr, #0x0 @clear out irqnr as default mov \base, #0xfe000000 orr \base, \base, #0x00ff0000 orr \base, \base, #0x0000a000 orr \base, \base, #0x08 ldr \irqstat, [\base] @ get interrupts mov \tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff and \irqstat, \irqstat, \tmp cmp \irqstat, #0 beq 1001f clz \irqnr, \irqstat mov \base, #31 subs \irqnr, \base, \irqnr /* * We handle PCIA and PCIB here so we don't have an * extra layer of code just to check these two bits. */ cmp \irqnr, #IRQ_IXP2000_PCI bne 1001f mov \base, #0xfe000000 orr \base, \base, #0x00fd0000 orr \base, \base, #0x0000e100 orr \base, \base, #0x00000058 ldr \irqstat, [\base] mov \tmp, #(1<<26) tst \irqstat, \tmp movne \irqnr, #IRQ_IXP2000_PCIA bne 1001f mov \tmp, #(1<<27) tst \irqstat, \tmp movne \irqnr, #IRQ_IXP2000_PCIB1001: .endm .macro irq_prio_table .endm#elif defined (CONFIG_ARCH_IXP4XX) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET) ldr \irqstat, [\irqstat] @ get interrupts cmp \irqstat, #0 beq 1002f clz \irqnr, \irqstat mov \base, #31 subs \irqnr, \base, \irqnr /*1001: tst \irqstat, #1 addeq \irqnr, \irqnr, #1 moveq \irqstat, \irqstat, lsr #1 tsteq \irqnr, #32 beq 1001b teq \irqnr, #32*/1002: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_OMAP) #if defined(CONFIG_ARCH_OMAP730) && \ (defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP16XX))#error "FIXME: OMAP730 doesn't support multiple-OMAP" #elif defined(CONFIG_ARCH_OMAP730)#undef INT_IH2_IRQ#define INT_IH2_IRQ INT_730_IH2_IRQ#endif .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \base, =IO_ADDRESS(OMAP_IH1_BASE) ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET] ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET] mov \irqstat, #0xffffffff bic \tmp, \irqstat, \tmp tst \irqnr, \tmp beq 1510f ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET] cmp \irqnr, #0 ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] cmpeq \irqnr, #INT_IH2_IRQ ldreq \base, =IO_ADDRESS(OMAP_IH2_BASE) ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] addeqs \irqnr, \irqnr, #321510: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_S3C2410) /* S3C2410X IRQ Handler, <ben@simtec.co.uk> */ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp30000: mov \tmp, #S3C2410_VA_IRQ ldr \irqnr, [ \tmp, #0x14 ] @ get irq no teq \irqnr, #4 teqne \irqnr, #5 beq 1002f @ external irq reg teq \irqnr, #16 beq 1003f @ lcd controller @ debug check to see if interrupt reported is the same @ as the offset.... teq \irqnr, #0 beq 20002f ldr \irqstat, [ \tmp, #0x10 ] @ INTPND mov \irqstat, \irqstat, lsr \irqnr tst \irqstat, #1 bne 20002f#if 1 stmfd r13!, { r0 - r4 , r14 } ldr r1, [ \tmp, #0x14 ] @ intoffset ldr r2, [ \tmp, #0x10 ] @ INTPND ldr r3, [ \tmp, #0x00 ] @ SRCPND adr r0, 20003f bl printk b 20004f#endif20003: .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n" .byte 0 .align 420004: mov r1, #1 mov \tmp, #S3C2410_VA_IRQ ldmfd r13!, { r0 - r4 , r14 } @ try working out interript number for ourselves mov \irqnr, #0 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND10021: movs \irqstat, \irqstat, lsr#1 bcs 30000b @ try and re-start the proccess add \irqnr, \irqnr, #1 cmp \irqnr, #32 ble 10021b @ found no interrupt, set Z flag and leave movs \irqnr, #0 b 1001f20005:20002: @ exit @ we base the s3c2410x interrupts at 16 and above to allow @ isa peripherals to have their standard interrupts, also @ ensure that Z flag is un-set on exit @ note, we cannot be sure if we get IRQ_EINT0 (0) that @ there is simply no interrupt pending, so in all other @ cases we jump to say we have found something, otherwise @ we check to see if the interrupt really is assrted adds \irqnr, \irqnr, #IRQ_EINT0 teq \irqnr, #IRQ_EINT0 bne 1001f @ exit ldr \irqstat, [ \tmp, #0x10 ] @ INTPND teq \irqstat, #0 moveq \irqnr, #0 b 1001f @ we get here from no main or external interrupts pending1002: add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK bic \irqstat, \irqstat, \irqnr @ clear masked irqs mov \irqnr, #IRQ_EINT4 @ start extint nos mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits10021: movs \irqstat, \irqstat, lsr#1 bcs 1004f add \irqnr, \irqnr, #1 cmp \irqnr, #IRQ_EINT23 ble 10021b @ found no interrupt, set Z flag and leave movs \irqnr, #0 b 1001f1003: @ lcd interrupt has been asserted... add \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ ldr \irqstat, [ \tmp, # 0x54 ] @ lcd int pending tst \irqstat, #2 movne \irqnr, #IRQ_LCD_FRAME tst \irqstat, #1 movne \irqnr, #IRQ_LCD_FIFO @ fall through to exit with flags updated1004: @ ensure Z flag clear in case our MOVS shifted out the last bit teq \irqnr, #01001: @ exit irq routine .endm /* currently don't need an disable_fiq macro */ .macro disable_fiq .endm /* we don't have an irq priority table */ .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_LH7A400)# if defined (CONFIG_ARCH_LH7A404)# error "LH7A400 and LH7A404 are mutually exclusive"# endif .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqnr, #0 mov \base, #io_p2v(0x80000000) @ APB registers ldr \irqstat, [\base, #0x500] @ PIC INTSR1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry bcs 1008f @ Bit set; irq found add \irqnr, \irqnr, #1 bne 1001b @ Until no bits b 1009f @ Nothing? Hmm.1008: movs \irqstat, #1 @ Force !Z1009: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_LH7A404) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqnr, #0 @ VIC1 irq base mov \base, #io_p2v(0x80000000) @ APB registers add \base, \base, #0x8000 ldr \tmp, [\base, #0x0030] @ VIC1_VECTADDR tst \tmp, #VA_VECTORED @ Direct vectored bne 1002f tst \tmp, #VA_VIC1DEFAULT @ Default vectored VIC1 ldrne \irqstat, [\base, #0] @ VIC1_IRQSTATUS bne 1001f add \base, \base, #(0xa000 - 0x8000) ldr \tmp, [\base, #0x0030] @ VIC2_VECTADDR tst \tmp, #VA_VECTORED @ Direct vectored bne 1002f ldr \irqstat, [\base, #0] @ VIC2_IRQSTATUS mov \irqnr, #32 @ VIC2 irq base1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry bcs 1008f @ Bit set; irq found add \irqnr, \irqnr, #1 bne 1001b @ Until no bits b 1009f @ Nothing? Hmm.1002: and \irqnr, \tmp, #0x3f @ Mask for valid bits1008: movs \irqstat, #1 @ Force !Z str \tmp, [\base, #0x0030] @ Clear vector1009: .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_IMX) .macro disable_fiq .endm#define AITC_NIVECSR 0x40 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE) @ Load offset & priority of the highest priority @ interrupt pending. ldr \irqnr, [\irqstat, #AITC_NIVECSR] @ Shift off the priority leaving the offset or @ "interrupt number" mov \irqnr, \irqnr, lsr #16 ldr \irqstat, =1 @ dummy compare ldr \base, =0xFFFF // invalid interrupt cmp \irqnr, \base bne 1001f ldr \irqstat, =01001: tst \irqstat, #1 @ to make the condition code = TRUE .endm .macro irq_prio_table .endm#elif defined(CONFIG_ARCH_H720X) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202) @ we could use the id register on H7202, but this is not @ properly updated when we come back from asm_do_irq @ without a previous return from interrupt @ (see loops below in irq_svc, irq_usr) @ We see unmasked pending ints only, as the masked pending ints @ are not visible here mov \base, #0xf0000000 @ base register orr \base, \base, #0x24000 @ irqbase ldr \irqstat, [\base, #0x04] @ get interrupt status#if defined (CONFIG_CPU_H7201) ldr \tmp, =0x001fffff#else mvn \tmp, #0xc0000000#endif and \irqstat, \irqstat, \tmp @ mask out unused ints mov \irqnr, #0 mov \tmp, #0xff00 orr \tmp, \tmp, #0xff tst \irqstat, \tmp addeq \irqnr, \irqnr, #16 moveq \irqstat, \irqstat, lsr #16 tst \irqstat, #255 addeq \irqnr, \irqnr, #8 moveq \irqstat, \irqstat, lsr #8 tst \irqstat, #15 addeq \irqnr, \irqnr, #4 moveq \irqstat, \irqstat, lsr #4 tst \irqstat, #3 addeq \irqnr, \irqnr, #2 moveq \irqstat, \irqstat, lsr #2 tst \irqstat, #1 addeq \irqnr, \irqnr, #1 moveq \irqstat, \irqstat, lsr #1 tst \irqstat, #1 @ bit 0 should be set .endm .macro irq_prio_table .endm#else#error hynix processor selection missmatch#endif#else#error Unknown architecture#endif/* * Invalid mode handlers */__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmia sp, {r0 - lr} @ Save XXX r0 - lr ldr r4, .LCabt mov r1, #BAD_PREFETCH b 1f__dabt_invalid: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] ldr r4, .LCabt mov r1, #BAD_DATA b 1f__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame stmfd sp, {r0 - lr} @ Save r0 - lr ldr r4, .LCirq mov r1, #BAD_IRQ b 1f__und_invalid: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - lr} ldr r4, .LCund mov r1, #BAD_UNDEFINSTR @ int reason1: zero_fp ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0 add r4, sp, #S_PC stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0 mov r0, sp and r2, r6, #31 @ int mode b bad_mode/* * SVC mode handlers */ .align 5__dabt_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 ldr r2, .LCabt add r0, sp, #S_FRAME_SIZE ldmia r2, {r2 - r4} @ get pc, cpsr add r5, sp, #S_SP mov r1, lr stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro mrs r9, cpsr @ Enable interrupts if they were tst r3, #PSR_I_BIT biceq r9, r9, #PSR_I_BIT @ previously/* * This routine must not corrupt r9 */#ifdef MULTI_ABORT ldr r4, .LCprocfns @ pass r2, r3 to mov lr, pc @ processor code ldr pc, [r4] @ call processor specific code#else bl CPU_ABORT_HANDLER#endif msr cpsr_c, r9 mov r2, sp bl do_DataAbort disable_irq r0 ldr r0, [sp, #S_PSR] msr spsr_cxsf, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr .align 5__irq_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 ldr r7, .LCirq add r5, sp, #S_FRAME_SIZE ldmia r7, {r7 - r9} add r4, sp, #S_SP mov r6, lr stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro#ifdef CONFIG_PREEMPT get_thread_info r8 ldr r9, [r8, #TI_PREEMPT] @ get preempt count add r7, r9, #1 @ increment it str r7, [r8, #TI_PREEMPT]#endif1: get_irqnr_and_base r0, r6, r5, lr movne r1, sp @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adrsvc ne, lr, 1b bne asm_do_IRQ#ifdef CONFIG_PREEMPT ldr r0, [r8, #TI_FLAGS] @ get flags tst r0, #_TIF_NEED_RESCHED blne svc_preemptpreempt_return: ldr r0, [r8, #TI_PREEMPT] @ read preempt value teq r0, r7 str r9, [r8, #TI_PREEMPT] @ restore preempt count strne r0, [r0, -r0] @ bug()#endif ldr r0, [sp, #S_PSR] @ irqs are already disabled msr spsr_cxsf, r0
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?