patch-2.1.80 linux/arch/arm/mm/proc-arm6,7.S
Next file: linux/arch/arm/mm/proc-sa110.S
Previous file: linux/arch/arm/mm/proc-arm2,3.S
Back to the patch index
Back to the overall index
- Lines: 437
- Date:
Tue Jan 20 16:39:42 1998
- Orig file:
v2.1.79/linux/arch/arm/mm/proc-arm6,7.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
@@ -0,0 +1,436 @@
+/*
+ * 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 <linux/linkage.h>
+#include <asm/assembler.h>
+#include "../lib/constants.h"
+
+/*
+ * 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
+ mcr p15, 0, r0, c7, c0, 0 @ flush cache
+_arm6_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
+ mcr p15, 0, r0, c5, c0, 0 @ flush TLB
+ 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:
+1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB
+ add r0, r0, #4096
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+@LC0: .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 - r9, 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 sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
+ ldr r0, [r1, #ADDR_LIMIT]
+ teq r0, #0
+ moveq r0, #KERNEL_DOMAIN
+ movne r0, #USER_DOMAIN
+ mcr p15, 0, r0, c3, c0 @ Set domain reg
+ 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
+ ldmfd sp!, {ip}
+ msr spsr, ip @ Save tasks CPSR into SPSR for this return
+ ldmfd sp!, {r4 - r9, 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
+ */
+
+Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0"
+ .align
+
+msg: .ascii "DA*%p=%p\n\0"
+ .align
+
+_arm6_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_unknown
+Ldata_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 SYMBOL_NAME(panic)
+Lstop: b Lstop
+
+_arm7_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_unknown
+
+Ldata_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 register
+
+Ldata_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, lr
+
+Ldata_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, lr
+
+Ldata_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_earlyldrpost
+
+Ldata_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_simple
+
+Ldata_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_earlyldrpost
+
+Ldata_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, ip
+_arm6_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: orr r1, r1, #16 @ Updatable bit is always set on ARM7
+ str r1, [r0]
+ 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
+ mcr p15, 0, r0, c7, c0, 0 @ flush cache
+ mcr p15, 0, r0, c5, c0, 0 @ flush TLB
+ 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
+
+ENTRY(arm6_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
+ .word _arm6_7_flush_cache @ 58
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+_arm7_name: .ascii "arm7\0"
+ .align
+
+ENTRY(arm7_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
+ .word _arm6_7_flush_cache @ 58
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov