📄 proc-arm6,7.s
字号:
/* * linux/arch/arm/mm/arm6.S: MMU functions for ARM6 * * (C) 1997 Russell King * * These are the low level assembler for performing cache and TLB * functions on the ARM6 & ARM7. */#include <asm/assembler.h>#include "../lib/constants.h"#define current current_set/* * Function: arm6_7_flush_cache_all (void) * : arm6_7_flush_cache_page (unsigned long address, int size, int flags) * * Params : address Area start address * : size size of area * : flags b0 = I cache as well * * Purpose : Flush all cache lines */arm6_7_flush_cache: mov r0, #0#ifndef NO_MM mcr p15, 0, r0, c7, c0, 0 @ flush cache#endifarm6_7_null: mov pc, lr/* * Function: arm6_7_flush_tlb_all (void) * * Purpose : flush all TLB entries in all caches */arm6_7_flush_tlb_all: mov r0, #0#ifndef NO_MM mcr p15, 0, r0, c5, c0, 0 @ flush TLB#endif mov pc, lr/* * Function: arm6_7_flush_tlb_page (unsigned long address, int end, int flags) * * Params : address Area start address * : end Area end address * : flags b0 = I cache as well * * Purpose : flush a TLB entry*/arm6_7_flush_tlb_area:#ifndef NO_MM1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB add r0, r0, #4096 cmp r0, r1 blt 1b#endif mov pc, lrLC0: .word current/* * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next) * * Params : prev Old task structure * : next New task structure for process to run * * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. * * Notes : We don't fiddle with the FP registers here - we postpone this until * the new task actually uses FP. This way, we don't swap FP for tasks * that do not require it. */arm6_7_switch_to: stmfd sp!, {r4 - r10, fp, lr} @ Store most regs on stack mrs ip, cpsr stmfd sp!, {ip} @ Save cpsr_SVC str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr r2, LC0 str r1, [r2] ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC#ifndef NO_MM ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer mov r1, #0 mcr p15, 0, r1, c7, c0, 0 @ flush cache mcr p15, 0, r0, c2, c0, 0 @ update page table ptr mcr p15, 0, r1, c5, c0, 0 @ flush TLBs#endif ldmfd sp!, {ip} msr spsr, ip @ Save tasks CPSR into SPSR for this return ldmfd sp!, {r4 - r10, fp, pc}^ @ Load all regs saved previously/* * Function: arm6_7_data_abort () * * Params : r0 = address of aborted instruction * * Purpose : obtain information about current aborted instruction * * Returns : r0 = address of abort * : r1 = FSR * : r2 != 0 if writing * : sp = pointer to registers * * Notes : data abort *** NEEDS WORK *** */Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0" .alignmsg: .ascii "DA*%p=%p\n\0" .alignarm6_data_abort: ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L and r1, r4, #15 << 24 add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine movs pc, lr b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_earlyldrpost @ ldr rd, [rn], #m b Ldata_simple @ ldr rd, [rn, #m] @ RegVal b Ldata_earlyldrpost @ ldr rd, [rn], rm b Ldata_simple @ 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_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m b Ldata_simple @ ldc rd, [rn, #m] b Ldata_unknownLdata_unknown: @ Part of jumptable ldr r3, [sp, #15 * 4] @ Get PC str r3, [sp, #-4]! mov r1, r1, lsr #2 mov r3, r4 mov r2, r0 adr r0, Lukabttxt bl panicLstop: b Lstoparm7_data_abort: ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L and r1, r4, #15 << 24 add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine movs pc, lr b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_unknown b Ldata_lateldrpostconst @ ldr rd, [rn], #m b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal b Ldata_lateldrpostreg @ ldr rd, [rn], rm b Ldata_lateldrprereg @ 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_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m b Ldata_simple @ ldc rd, [rn, #m] b Ldata_unknown b Ldata_unknownLdata_ldmstm: tst r4, #1 << 21 @ check writeback bit beq Ldata_simple 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. and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] @ Get register 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) str r7, [sp, r5, lsr #14] @ Put registerLdata_simple: and r2, r2, #2 @ check read/write bit mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r1, c5, c0, 0 @ get FSR and r1, r1, #15 mov pc, lrLdata_earlyldrpost: tst r2, #4 and r2, r2, #2 @ check read/write bit orrne r2, r2, #1 @ T bit mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r1, c5, c0, 0 @ get FSR and r1, r1, #15 mov pc, lrLdata_lateldrpostconst: movs r1, r4, lsl #20 @ Get offset beq Ldata_earlyldrpost @ if offset is zero, no effect and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit subne r0, r0, r1, lsr #20 addeq r0, r0, r1, lsr #20 str r0, [sp, r5, lsr #14] @ Put register b Ldata_earlyldrpostLdata_lateldrpreconst: tst r4, #1 << 21 @ check writeback bit movnes r1, r4, lsl #20 @ Get offset beq Ldata_simple and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit subne r0, r0, r1, lsr #20 addeq r0, r0, r1, lsr #20 str r0, [sp, r5, lsr #14] @ Put register b Ldata_simpleLdata_lateldrpostreg: and r5, r4, #15 ldr r1, [sp, r5, lsl #2] @ Get Rm mov r3, r4, lsr #7 ands r3, r3, #31 and r6, r4, #0x70 orreq r6, r6, #8 add pc, pc, r6 mov r0, r0 mov r1, r1, lsl r3 @ 0: LSL #!0 b 1f b 1f @ 1: LSL #0 mov r0, r0 b 1f @ 2: MUL? mov r0, r0 b 1f @ 3: MUL? mov r0, r0 mov r1, r1, lsr r3 @ 4: LSR #!0 b 1f mov r1, r1, lsr #32 @ 5: LSR #32 b 1f b 1f @ 6: MUL? mov r0, r0 b 1f @ 7: MUL? mov r0, r0 mov r1, r1, asr r3 @ 8: ASR #!0 b 1f mov r1, r1, asr #32 @ 9: ASR #32 b 1f b 1f @ A: MUL? mov r0, r0 b 1f @ B: MUL? mov r0, r0 mov r1, r1, ror r3 @ C: ROR #!0 b 1f mov r1, r1, rrx @ D: RRX b 1f mov r0, r0 @ E: MUL? mov r0, r0 mov r0, r0 @ F: MUL?1: and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit subne r0, r0, r1 addeq r0, r0, r1 str r0, [sp, r5, lsr #14] @ Put register b Ldata_earlyldrpostLdata_lateldrprereg: tst r4, #1 << 21 @ check writeback bit beq Ldata_simple and r5, r4, #15 ldr r1, [sp, r5, lsl #2] @ Get Rm mov r3, r4, lsr #7 ands r3, r3, #31 and r6, r4, #0x70 orreq r6, r6, #8 add pc, pc, r6 mov r0, r0 mov r1, r1, lsl r3 @ 0: LSL #!0 b 1f b 1f @ 1: LSL #0 mov r0, r0 b 1f @ 2: MUL? mov r0, r0 b 1f @ 3: MUL? mov r0, r0 mov r1, r1, lsr r3 @ 4: LSR #!0 b 1f mov r1, r1, lsr #32 @ 5: LSR #32 b 1f b 1f @ 6: MUL? mov r0, r0 b 1f @ 7: MUL? mov r0, r0 mov r1, r1, asr r3 @ 8: ASR #!0 b 1f mov r1, r1, asr #32 @ 9: ASR #32 b 1f b 1f @ A: MUL? mov r0, r0 b 1f @ B: MUL? mov r0, r0 mov r1, r1, ror r3 @ C: ROR #!0 b 1f mov r1, r1, rrx @ D: RRX b 1f mov r0, r0 @ E: MUL? mov r0, r0 mov r0, r0 @ F: MUL?1: and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit subne r0, r0, r1 addeq r0, r0, r1 str r0, [sp, r5, lsr #14] @ Put register b Ldata_simple/* * Function: arm6_7_check_bugs (void) * : arm6_7_proc_init (void) * : arm6_7_proc_fin (void) * * Notes : This processor does not require these */arm6_7_check_bugs: mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, iparm6_7_proc_init:arm6_7_proc_fin: mov pc, lr/* * Function: arm6_set_pmd () * * Params : r0 = Address to set * : r1 = value to set * * Purpose : Set a PMD and flush it out of any WB cache */arm6_set_pmd: and r2, r1, #3 teq r2, #2 andeq r2, r1, #8 orreq r1, r1, r2, lsl #1 @ Updatable = Cachable teq r2, #1 orreq r1, r1, #16 @ Updatable = 1 if Page table str r1, [r0] mov pc, lr/* * Function: arm7_set_pmd () * * Params : r0 = Address to set * : r1 = value to set * * Purpose : Set a PMD and flush it out of any WB cache */arm7_set_pmd:#ifndef NO_MM orr r1, r1, #16 @ Updatable bit is always set on ARM7 str r1, [r0]#endif mov pc, lr/* * Function: arm6_7_reset * * Notes : This sets up everything for a reset */arm6_7_reset: mrs r1, cpsr orr r1, r1, #F_BIT|I_BIT msr cpsr, r1 mov r0, #0#ifndef NO_MM mcr p15, 0, r0, c7, c0, 0 @ flush cache mcr p15, 0, r0, c5, c0, 0 @ flush TLB#endif mov r1, #F_BIT | I_BIT | 3 mov pc, lr/* * Purpose : Function pointers used to access above functions - all calls * come through these */arm6_name: .ascii "arm6\0" .align .globl arm6_processor_functionsarm6_processor_functions: .word arm6_name @ 0 .word arm6_7_switch_to @ 4 .word arm6_data_abort @ 8 .word arm6_7_check_bugs @ 12 .word arm6_7_proc_init @ 16 .word arm6_7_proc_fin @ 20 .word arm6_7_flush_cache @ 24 .word arm6_7_flush_cache @ 28 .word arm6_7_flush_cache @ 32 .word arm6_7_null @ 36 .word arm6_7_flush_cache @ 40 .word arm6_7_flush_tlb_all @ 44 .word arm6_7_flush_tlb_area @ 48 .word arm6_set_pmd @ 52 .word arm6_7_reset @ 54/* * Purpose : Function pointers used to access above functions - all calls * come through these */arm7_name: .ascii "arm7\0" .align .globl arm7_processor_functionsarm7_processor_functions: .word arm7_name @ 0 .word arm6_7_switch_to @ 4 .word arm7_data_abort @ 8 .word arm6_7_check_bugs @ 12 .word arm6_7_proc_init @ 16 .word arm6_7_proc_fin @ 20 .word arm6_7_flush_cache @ 24 .word arm6_7_flush_cache @ 28 .word arm6_7_flush_cache @ 32 .word arm6_7_null @ 36 .word arm6_7_flush_cache @ 40 .word arm6_7_flush_tlb_all @ 44 .word arm6_7_flush_tlb_area @ 48 .word arm7_set_pmd @ 52 .word arm6_7_reset @ 54
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -