📄 entry-armo.s
字号:
mov r6, r13 mov r7, r14 teqp pc, #0x04000003 @ back to svc mov r0, r0 stmfd sp!, {r1-r7} ldmia r0, {r0-r7} stmfd sp!, {r0-r7} mov r0, sp mov r1, #BAD_ADDREXCPTN b SYMBOL_NAME(bad_mode)/*============================================================================= * Interrupt (IRQ) handler *----------------------------------------------------------------------------- * Note: if in user mode, then *no* kernel routine is running, so do not have * to save svc lr * (r13 points to irq temp save area) */vector_IRQ: ldr r13, .LCirq @ I will leave this one in just in case... sub lr, lr, #4 str lr, [r13] tst lr, #3 bne __irq_svc teqp pc, #0x08000003 mov r0, r0 ldr lr, .LCirq ldr lr, [lr] save_user_regs1: get_irqnr_and_base r6, r5 teq r6, #0 ldrneb r0, [r5, r6] @ get IRQ number movne r1, sp @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adr lr, 1b orr lr, lr, #0x08000003 @ Force SVC bne do_IRQ mov why, #0 get_current_task r5 b ret_to_user irq_prio_table__irq_svc: teqp pc, #0x08000003 mov r0, r0 SVC_IRQ_SAVE_ALL and r2, lr, #3 teq r2, #3 bne __irq_invalid1: get_irqnr_and_base r6, r5 teq r6, #0 ldrneb r0, [r5, r6] @ get IRQ number movne r1, sp @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adr lr, 1b orr lr, lr, #0x08000003 @ Force SVC bne do_IRQ @ Returns to 1b SVC_RESTORE_ALL__irq_invalid: mov r0, sp mov r1, #BAD_IRQ b SYMBOL_NAME(bad_mode)/*============================================================================= * Data abort handler code *----------------------------------------------------------------------------- * * This handles both exceptions from user and SVC modes, computes the address * range of the problem, and does any correction that is required. It then * calls the kernel data abort routine. * * This is where I wish that the ARM would tell you which address aborted. */vector_data: sub lr, lr, #8 @ Correct lr tst lr, #3 bne Ldata_not_user save_user_regs teqp pc, #0x00000003 @ NOT a problem - doesnt change mode mask_pc r0, lr bl Ldata_do b ret_from_exceptionLdata_not_user: SVC_SAVE_ALL and r2, lr, #3 teq r2, #3 bne Ldata_illegal_mode tst lr, #0x08000000 teqeqp pc, #0x00000003 @ NOT a problem - doesnt change mode mask_pc r0, lr bl Ldata_do SVC_RESTORE_ALLLdata_illegal_mode: mov r0, sp mov r1, #BAD_DATA b SYMBOL_NAME(bad_mode)Ldata_do: mov r3, sp ldr r4, [r0] @ Get instruction mov r2, #0 tst r4, #1 << 20 @ Check to see if it is a write instruction orreq r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction mov r1, r4, lsr #22 @ Now branch to the relevent processing routine and r1, r1, #15 << 2 add pc, pc, r1 movs pc, lr b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_ldrstr_post @ ldr rd, [rn], #m b Ldata_ldrstr_numindex @ ldr rd, [rn, #m] @ RegVal b Ldata_ldrstr_post @ ldr rd, [rn], rm b Ldata_ldrstr_regindex @ ldr rd, [rn, rm] b Ldata_ldmstm @ ldm*a rn, <rlist> b Ldata_ldmstm @ ldm*b rn, <rlist> b Ldata_unknown b Ldata_unknown b Ldata_ldrstr_post @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m b Ldata_ldcstc_pre @ ldc rd, [rn, #m] b Ldata_unknownLdata_unknown: @ Part of jumptable mov r0, r1 mov r1, r4 mov r2, r3 b baddataabortLdata_ldrstr_post: mov r0, r4, lsr #14 @ Get Rn and r0, r0, #15 << 2 @ Mask out reg. teq r0, #15 << 2 ldr r0, [r3, r0] @ Get register biceq r0, r0, #PCMASK mov r1, r0#ifdef FAULT_CODE_LDRSTRPOST orr r2, r2, #FAULT_CODE_LDRSTRPOST#endif b SYMBOL_NAME(do_DataAbort)Ldata_ldrstr_numindex: mov r0, r4, lsr #14 @ Get Rn and r0, r0, #15 << 2 @ Mask out reg. teq r0, #15 << 2 ldr r0, [r3, r0] @ Get register mov r1, r4, lsl #20 biceq r0, r0, #PCMASK tst r4, #1 << 23 addne r0, r0, r1, lsr #20 subeq r0, r0, r1, lsr #20 mov r1, r0#ifdef FAULT_CODE_LDRSTRPRE orr r2, r2, #FAULT_CODE_LDRSTRPRE#endif b SYMBOL_NAME(do_DataAbort)Ldata_ldrstr_regindex: mov r0, r4, lsr #14 @ Get Rn and r0, r0, #15 << 2 @ Mask out reg. teq r0, #15 << 2 ldr r0, [r3, r0] @ Get register and r7, r4, #15 biceq r0, r0, #PCMASK teq r7, #15 @ Check for PC ldr r7, [r3, r7, lsl #2] @ Get Rm and r8, r4, #0x60 @ Get shift types biceq r7, r7, #PCMASK mov r9, r4, lsr #7 @ Get shift amount and r9, r9, #31 teq r8, #0 moveq r7, r7, lsl r9 teq r8, #0x20 @ LSR shift moveq r7, r7, lsr r9 teq r8, #0x40 @ ASR shift moveq r7, r7, asr r9 teq r8, #0x60 @ ROR shift moveq r7, r7, ror r9 tst r4, #1 << 23 addne r0, r0, r7 subeq r0, r0, r7 @ Apply correction mov r1, r0#ifdef FAULT_CODE_LDRSTRREG orr r2, r2, #FAULT_CODE_LDRSTRREG#endif b SYMBOL_NAME(do_DataAbort)Ldata_ldmstm: mov r7, #0x11 orr r7, r7, r7, lsl #8 and r0, r4, r7 and r1, r4, r7, lsl #1 add r0, r0, r1, lsr #1 and r1, r4, r7, lsl #2 add r0, r0, r1, lsr #2 and r1, r4, r7, lsl #3 add r0, r0, r1, lsr #3 add r0, r0, r0, lsr #8 add r0, r0, r0, lsr #4 and r7, r0, #15 @ r7 = no. of registers to transfer. mov r5, r4, lsr #14 @ Get Rn and r5, r5, #15 << 2 ldr r0, [r3, r5] @ Get reg eor r6, r4, r4, lsl #2 tst r6, #1 << 23 @ Check inc/dec ^ writeback rsbeq r7, r7, #0 add r7, r0, r7, lsl #2 @ Do correction (signed) subne r1, r7, #1 subeq r1, r0, #1 moveq r0, r7 tst r4, #1 << 21 @ Check writeback strne r7, [r3, r5] eor r6, r4, r4, lsl #1 tst r6, #1 << 24 @ Check Pre/Post ^ inc/dec addeq r0, r0, #4 addeq r1, r1, #4 teq r5, #15*4 @ CHECK FOR PC biceq r1, r1, #PCMASK biceq r0, r0, #PCMASK#ifdef FAULT_CODE_LDMSTM orr r2, r2, #FAULT_CODE_LDMSTM#endif b SYMBOL_NAME(do_DataAbort)Ldata_ldcstc_pre: mov r0, r4, lsr #14 @ Get Rn and r0, r0, #15 << 2 @ Mask out reg. teq r0, #15 << 2 ldr r0, [r3, r0] @ Get register mov r1, r4, lsl #24 @ Get offset biceq r0, r0, #PCMASK tst r4, #1 << 23 addne r0, r0, r1, lsr #24 subeq r0, r0, r1, lsr #24 mov r1, r0#ifdef FAULT_CODE_LDCSTC orr r2, r2, #FAULT_CODE_LDCSTC#endif b SYMBOL_NAME(do_DataAbort)/* * This is the return code to user mode for abort handlers */ENTRY(ret_from_exception) get_current_task tsk mov why, #0 b ret_to_user .dataENTRY(fp_enter) .word fpe_not_present .text/* * Register switch for older 26-bit only ARMs */ENTRY(__switch_to) stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously/* *============================================================================= * Low-level interface code *----------------------------------------------------------------------------- * Trap initialisation *----------------------------------------------------------------------------- * * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20 * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes * some excess cycles). * * What we need to put into 0-0x1c are branches to branch to the kernel. */ .section ".text.init",#alloc,#execinstr.Ljump_addresses: swi SYS_ERROR0 .word vector_undefinstr - 12 .word vector_swi - 16 .word vector_prefetch - 20 .word vector_data - 24 .word vector_addrexcptn - 28 .word vector_IRQ - 32 .word _unexp_fiq - 36 b . + 8/* * initialise the trap system */ENTRY(__trap_init) stmfd sp!, {r4 - r7, lr} adr r1, .Ljump_addresses ldmia r1, {r1 - r7, ip, lr} orr r2, lr, r2, lsr #2 orr r3, lr, r3, lsr #2 orr r4, lr, r4, lsr #2 orr r5, lr, r5, lsr #2 orr r6, lr, r6, lsr #2 orr r7, lr, r7, lsr #2 orr ip, lr, ip, lsr #2 mov r0, #0 stmia r0, {r1 - r7, ip} ldmfd sp!, {r4 - r7, pc}^ .bss__temp_irq: .space 4 @ saved lr_irq__temp_fiq: .space 128
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -