📄 mmumacro.s
字号:
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;
; Use of this source code is subject to the terms of the Microsoft end-user
; license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
; If you did not accept the terms of the EULA, you are not authorized to use
; this source code. For a copy of the EULA, please see the LICENSE.RTF on your
; install media.
;
;
; Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
;
;
; Use of this source code is subject to the terms of the Microsoft end-user
; license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
; If you did not accept the terms of the EULA, you are not authorized to use
; this source code. For a copy of the EULA, please see the LICENSE.RTF on your
; install media.
;
; -*-Asm-*-
;
; $Revision: 1.2 $
; $Author: kwelton $
; $Date: 1999/10/25 21:40:55 $
;
; Copyright (c) ARM Limited 1998, 1999.
; All Rights Reserved.
;
; mmumacro.s - Generic aliases for COPROCESSOR access macros for
; ARM processors.
;
; $Id: mmumacro.s,v 1.2 1999/10/25 21:40:55 kwelton Exp $
;
IF :LNOT: :DEF: __mmumacros
__mmumacros EQU 1
; Bit definitions are here
INCLUDE mmu_h.s
; Dummy macros for processors without MMU/MPU etc.
INCLUDE nommu.s
; NOTE: Most (all?) macros call the NO_* macro first. These macros must
; be non-destructive on passed parameters, as one (or more) of
; the processor-specific macros may be called next.
IF FORCE_TGTCPU = "ARM7"
INCLUDE mmu7T.s
ENDIF
IF FORCE_TGTCPU = "ARM720"
INCLUDE mmu720T.s
ENDIF
IF FORCE_TGTCPU = "ARM740"
INCLUDE mmu740T.s
ENDIF
IF FORCE_TGTCPU = "ARM920"
INCLUDE mmu920T.s
ENDIF
IF FORCE_TGTCPU = "ARM940"
INCLUDE mmu940T.s
ENDIF
IF FORCE_TGTCPU = "SA110"
INCLUDE mmu110.s
ENDIF
;------------------------------------------------------------------
;Macro to test that the given address has a 1-to-1 mapping between
;physical and virtual memory
MACRO
TEST_121MAP $addr, $tmp1, $tmp2
RDMMU_TTBase $tmp1
MOV $tmp1, $tmp1, LSR #14 ; Clear bottom 14 bits
MOV $tmp1, $tmp1, LSL #14
ADD $tmp2, $tmp1, $addr, LSR #(20-2) ; page table entry
LDR $tmp1, [$tmp2] ; read the entry
MOV $tmp2, $addr, LSR #20 ; addr in MB
SUBS $tmp2, $tmp2, $tmp1, LSR #20 ; entry in
MEND
;------------------------------------------------------------------
; For executables which are linked for a different address to the
; physically executed address:
;
; Need to adjust from the linked address of the table to a relative
; offset from here. First, work out the offset from the RO$$Base,
; then find out how far we are from our actual start. Lastly, add
; the difference to the current pc.
MACRO
FIND_TABLEADDR $tmp3, $tmp4, $addr
LDR $tmp4, =|Image$$RO$$Base| ; get linked location of code
SUB $addr, $addr, $tmp4 ; A. table offset from start
LDR $tmp3, =%F79
SUB $tmp3, $tmp3, $tmp4 ; B. Offset to next label
SUB $addr, $addr, $tmp3 ; A-B
; ----------------------------------------------------
; Note: no more than 2 instructions between here and
; the label. Since pc is here + 8, add A-B to get
; current table address
MOV $tmp3, pc
ADD $addr, $addr, $tmp3
79
MEND
; Macro to read the MPU MappingTable and build the region, cache, buffer
; and permissions before setting up the MPU as required
;
MACRO
SETUP_MPU $tmp1, $size, $tmp2, $tmp3, $tmp4, $addr, $offset
IF :LNOT: :DEF: MPUMaptab
IMPORT MPUMaptab
ENDIF
; Flush MPU Map to invalid
LDR $tmp2, =MPUMaptab
ADD $tmp1, $tmp2, $offset ; Real address of Level1 TTB
MOV $tmp3, #0 ; Invalid
LDR $tmp4, =MPU_TABLE_ENTRIES
70
STR $tmp3, [$tmp1], #4
SUBS $tmp4, $tmp4, #1 ; decrement loop count
BNE %B70
; If not executing from linked address, adjust $addr
FIND_TABLEADDR $tmp3, $tmp4, $addr
ADD $tmp1, $tmp2, $offset ; Real address of Mapping Table
71
LDR $offset, [$addr], #4 ; Read the region
LDR $tmp2, [$addr], #4 ; Base address
LDR $tmp3, [$addr], #4 ; Area size
CMP $tmp3, #0 ; All done if size is zero
BEQ %F74
; Make sure address is correctly aligned (a multiple of size)
MOV $tmp4, #2
MOV $tmp4, $tmp4, LSL $tmp3
SUB $tmp4, $tmp4, #1
ANDS $tmp4, $tmp2, $tmp4
BNE %F80 ; Failed, stop.
; Build the region value, strip bottom 12 bits
MOV $tmp3, $tmp3, LSL #1 ; Size is used x 2
MOV $tmp2, $tmp2, LSR #12
MOV $tmp2, $tmp2, LSL #12
ADD $tmp2, $tmp2, $tmp3 ; Add in size
ADD $tmp2, $tmp2, #1 ; Enable this region
MOV $tmp3, $offset, LSL #2 ; Sotre in region * 4
STR $tmp2, [$tmp1, $tmp3] ; Save the region base address
; Now add in access permissions for cache etc.
LDR $tmp4, [$addr], #4 ; Access permissions
MOV $tmp4, $tmp4, LSR #2 ; Access >> 2
AND $tmp3, $tmp4, #1
MOV $tmp2, $tmp3, LSL $offset
LDR $tmp3, [$tmp1, #MPU_BUFFER_OFFSET]
ORR $tmp2, $tmp2, $tmp3
STR $tmp2, [$tmp1, #MPU_BUFFER_OFFSET]
MOV $tmp4, $tmp4, LSR #1 ; Access >> 3
AND $tmp3, $tmp4, #1
MOV $tmp2, $tmp3, LSL $offset
LDR $tmp3, [$tmp1, #MPU_CACHE_OFFSET]
ORR $tmp2, $tmp2, $tmp3
STR $tmp2, [$tmp1, #MPU_CACHE_OFFSET]
MOV $tmp4, $tmp4, LSR #7 ; Access >> 10
AND $tmp3, $tmp4, #3
MOV $tmp3, $tmp3, LSL $offset
MOV $tmp2, $tmp3, LSL $offset ; region x 2
LDR $tmp3, [$tmp1, #MPU_ACCESS_OFFSET]
ORR $tmp2, $tmp2, $tmp3
STR $tmp2, [$tmp1, #MPU_ACCESS_OFFSET]
B %B71 ; Next..
72 ; MPU Mapping Table failure..
B .
74
; The table is built, so now write the values to the MPU
LDR $tmp2, [$tmp1], #4
WRMPU_Region 0, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 1, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 2, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 3, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 4, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 5, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 6, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_Region 7, $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_CacheBits $tmp2
LDR $tmp2, [$tmp1], #4
WRMPU_BufferBits $tmp2
LDR $tmp2, [$tmp1]
WRMPU_AccessBits $tmp2
MEND
; Simple macro to clear all page table entries.
;
MACRO
$label INIT_PGTABLE $count, $val, $ptr, $offset
LDR $ptr, =Level2tab_ROM
ADD $ptr, $ptr, $offset ; Real address of Level2 TTB
LDR $count, =L2_TABLE_ENTRIES
CMP $count, #0 ; Check for no Level2 table
BEQ %F77
LDR $val, =L2_ENTRY_SIZE
MUL $count, $val, $count
MOV $val, #0 ; Invalid
76
STR $val, [$ptr], #4
SUBS $count, $count, #1 ; decrement loop count
BGE %B76
77
LDR $ptr, =Level1tab
ADD $ptr, $ptr, $offset ; Real address of Level1 TTB
MOV $val, #0 ; Invalid
LDR $count, =L1_TABLE_ENTRIES
78
STR $val, [$ptr], #4
SUBS $count, $count, #1 ; decrement loop count
BGE %B78
MEND
; Build a page table from the supplied address map table.
;
; $tmp2 size of memory If this platform supports auto-memory sizing
; $addr pointer to memory map table
; $offset offset between physical addr & virtual addr of TTBs
;
MACRO
$label BUILD_PGTABLE $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $addr, $offset
; ----------------------------------------------------
; First clear all TT entries - FAULT
; ----------------------------------------------------
INIT_PGTABLE $tmp3, $tmp4, $tmp5, $offset
; If not executing from linked address, adjust $addr
FIND_TABLEADDR $tmp3, $tmp4, $addr
; ----------------------------------------------------
; Check $size parameter.
; If non-zero, size of first memory area is taken from
; target-specific memory sizing code rather than $size
CMP $tmp2, #0
BEQ %F81 ; Not autosizing, read all params
; ----------------------------------------------------
; Make sure given memory size is a multiple of 1MB
; tmp3 is no. of 1MB segments
MOV $tmp3, $tmp2, LSR #20
MOV $tmp4, $tmp3, LSL #20
CMP $tmp4, $tmp2
ADDNE $tmp3, $tmp3, #1
; Read 1st Entry from MMU table seperately to allow
; memory sizing.
; NOTE: 1st entry cannot abort & can't be Level2 !!
LDR $tmp4, =Level1tab
ADD $tmp4, $tmp4, $offset
; Virtual base address -> Level1 offset in tmp2
LDR $tmp5, [$addr], #4
ADD $tmp2, $tmp4, $tmp5, LSR #(20-2)
; Physical base address -> tmp4
LDR $tmp1, [$addr], #4
; Access permissions etc -> tmp3 (NOTE: Size is skipped!)
LDR $tmp5, [$addr], #8
CMP $tmp5, #0
BEQ %F80 ; Halt if access is zero
TST $tmp1, #PT_PAGE
BNE %F80 ; Halt if Level2 table
ADD $tmp1, $tmp1, $tmp5 ; Level1 Table Entry
; Registers set, so build 1st entry & rest of TLB.
B %F83
; All causes for error end up here
80
IF FORCE_TGTCPU = "ARM7"
B %F90 ; No Page Table if no MMU
ENDIF
B .
81
LDR $tmp4, =Level1tab
ADD $tmp4, $tmp4, $offset
82
; Calculate offset to virtual base address entry -> tmp2
LDR $tmp1, [$addr], #4 ; Virtual address
ADD $tmp2, $tmp4, $tmp1, LSR #(20-2)
; Physical base address -> tmp1
LDR $tmp1, [$addr], #4
; Access permissions etc -> tmp3
LDR $tmp3, [$addr], #4
CMP $tmp3, #0 ; All done if access is zero
BEQ %F90
TST $tmp1, #PT_PAGE ; Check for Level2 table
BNE %F84 ; Yes, do it
; ----------------------------------------------------
; Level 1 Entries, calculate size & fill table
; ----------------------------------------------------
ADD $tmp1, $tmp1, $tmp3 ; Level1 Table Entry
LDR $tmp3, [$addr], #4 ; area size
MOV $tmp3, $tmp3, LSR #20 ; no. of 1MB segments
83
STR $tmp1, [$tmp2], #4 ; store Table Entry
ADD $tmp1, $tmp1, #SZ_1M ; add section number field
SUBS $tmp3, $tmp3, #1 ; decrement loop count
BGT %B83
B %B82 ; Repeat until done
84
; Convert logical addresses to real addresses
ADD $tmp1, $tmp1, $offset ; Pointer to Level2 table
; ----------------------------------------------------
; Check for Fine table and process seperately
; ----------------------------------------------------
TST $tmp3, #(PT_FINE - PT_PAGE)
; Read size!
LDR $tmp5, [$addr], #4
BIC $tmp4, $tmp1, #0x0ff
BNE %F87
; ----------------------------------------------------
; Large Level2: Strip address of Level2 Table -> tmp4
; ----------------------------------------------------
BIC $tmp4, $tmp4, #0x0300
MOV $tmp5, $tmp5, LSR #16 ; no. of 64KB segments
MOV $tmp5, $tmp5, LSL #4 ; no. of 4KB aliases
85
STR $tmp1, [$tmp2], #4 ; Level1 points to Level2 entry
86
; Add each entry aliased 16 times (64KB/4KB, so $tmp3 & 0xF == 0)
STR $tmp3, [$tmp4], #4 ; store large L2 TT entry
SUB $tmp5, $tmp5, #1 ; decrement page count
TST $tmp5, #0xF
BNE %B86 ; upto 16 L2 entries
; Add 16 L2 entries per L1 entry (1MB/64KB, so $tmp3 & 0xF0 == 0)
ADD $tmp3, $tmp3, #SZ_64K ; next page field
TST $tmp5, #0xf0
BNE %B86 ; upto 16 L2 entries
CMP $tmp5, #0 ; All done?
ADD $tmp1, $tmp1, #0x400 ; Next 1MB is 256 entries further down
BNE %B85 ; No, do another L1 entry.
B %B81
87
; ----------------------------------------------------
; Fine Level2: Strip address of Level2 Table -> tmp4
; ----------------------------------------------------
BIC $tmp4, $tmp4, #0x0f00
MOV $tmp5, $tmp5, LSR #16 ; no. of 64KB segments
MOVEQ $tmp5, $tmp5, LSL #8 ; no. of 1KB aliases
MOVNE $tmp5, $tmp5, LSL #4 ; no. of 4KB aliases
88
STR $tmp1, [$tmp2], #4 ; Level1 points to Level2 entry
89
STR $tmp3, [$tmp4], #4 ; store fine L2 TT entry
SUBS $tmp5, $tmp5, #1 ; decrement page count
ADD $tmp3, $tmp3, #SZ_1K ; next page field
TST $tmp5, #0x0ff
BNE %B89 ; 4 x 256 L2 entries
TST $tmp5, #0x300
BNE %B89 ; 3ff won't fit inside an instruction
CMP $tmp5, #0 ; All done?
ADD $tmp1, $tmp1, #0x4000 ; Next 1MB is 1K entries further down
BNE %B88 ; No, do another L1 entry.
B %B81
90
MEND
;------------------------------------------------------------------
; Compulsory Macros:
;
; These are the macros which must be defined, even for processors
; without any memory management capabilities.
;
; CHECK_FOR_MMU - return TRUE if CPU has an MMU
; CHECK_FOR_MPU - return TRUE if CPU has an MPU
; CHECK_CACHE - return TRUE if CPU has a Cache
; CHECK_UNIFIED - return TRUE if CPU has a Unified Cache
; CHECK_CPUID - return TRUE if CPU matches the expected ID
; CHECK_VENDOR - return TRUE if CPU matches the expected Vendor ID
MACRO
CHECK_FOR_MMU $reg
NO_CHECK_FOR_MMU $reg
IF FORCE_TGTCPU = "ARM7"
CHECK_FOR_MMU_7T $reg
ENDIF
IF FORCE_TGTCPU = "ARM720"
CHECK_FOR_MMU_720T $reg
ENDIF
IF FORCE_TGTCPU = "ARM740"
CHECK_FOR_MMU_740T $reg
ENDIF
IF FORCE_TGTCPU = "ARM920"
CHECK_FOR_MMU_920T $reg
ENDIF
IF FORCE_TGTCPU = "ARM940"
CHECK_FOR_MMU_940T $reg
ENDIF
IF FORCE_TGTCPU = "SA110"
CHECK_FOR_MMU_110 $reg
ENDIF
MEND
;Macro to signal if this processor has an MPU
;
MACRO
CHECK_FOR_MPU $reg
NO_CHECK_FOR_MPU $reg
IF FORCE_TGTCPU = "ARM7"
CHECK_FOR_MPU_7T $reg
ENDIF
IF FORCE_TGTCPU = "ARM720"
CHECK_FOR_MPU_720T $reg
ENDIF
IF FORCE_TGTCPU = "ARM740"
CHECK_FOR_MPU_740T $reg
ENDIF
IF FORCE_TGTCPU = "ARM920"
CHECK_FOR_MPU_920T $reg
ENDIF
IF FORCE_TGTCPU = "ARM940"
CHECK_FOR_MPU_940T $reg
ENDIF
IF FORCE_TGTCPU = "SA110"
CHECK_FOR_MPU_110 $reg
ENDIF
MEND
;Macro to signal if this processor has a Cache
;
MACRO
CHECK_CACHE $reg
NO_CHECK_CACHE $reg
IF FORCE_TGTCPU = "ARM7"
CHECK_CACHE_7T $reg
ENDIF
IF FORCE_TGTCPU = "ARM720"
CHECK_CACHE_720T $reg
ENDIF
IF FORCE_TGTCPU = "ARM740"
CHECK_CACHE_740T $reg
ENDIF
IF FORCE_TGTCPU = "ARM920"
CHECK_CACHE_920T $reg
ENDIF
IF FORCE_TGTCPU = "ARM940"
CHECK_CACHE_940T $reg
ENDIF
IF FORCE_TGTCPU = "SA110"
CHECK_CACHE_110 $reg
ENDIF
MEND
;Macro to signal if this processor has a unified cache
;
MACRO
CHECK_UNIFIED $reg
NO_CHECK_UNIFIED $reg
IF FORCE_TGTCPU = "ARM7"
CHECK_UNIFIED_7T $reg
ENDIF
IF FORCE_TGTCPU = "ARM720"
CHECK_UNIFIED_720T $reg
ENDIF
IF FORCE_TGTCPU = "ARM740"
CHECK_UNIFIED_740T $reg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -