powermac-rom/NanoKernel/NKMemory.s
2018-07-28 14:20:23 +08:00

550 lines
18 KiB
ArmAsm

; AUTO-GENERATED SYMBOL LIST
; IMPORTS:
; NKSystemCrash
; SystemCrash
; EXPORTS:
; FlushTLB (=> NKReset)
; GetPhysical (=> MRInterrupts, NKSoftInts)
; PutPTE (=> MRInterrupts, NKColdInts, NKLegacyVM, NKReset)
; SetMap (=> NKReset)
########################################################################
########################################################################
PutPTE ; EA r27 // PTE r30/r31, EQ=Success, GT=Invalid, LT=Fault
lwz r29, KDP.CurMap.SegMapPtr(r1)
rlwinm r28, r27, 7, 0x0000000F << 3 ; convert segment of passed ptr to offset into SegMap
lwzx r29, r29, r28 ; r29 = ptr to start of segment in PageMap
rlwinm r28, r27, 20, 0x0000FFFF ; r27 = page index within SegMap
lhz r30, PME.LBase(r29)
b @find_pme
@try_next_pme ; Point r29 to the PageMapEntry that concerns this page
lhzu r30, 8(r29) ; get another PME.LBase
@find_pme
lhz r31, PME.PageCount(r29)
subf r30, r30, r28 ; r30 = page index within area
cmplw cr7, r30, r31
bgt cr7, @try_next_pme
lwz r28, KDP.HtabTempEntryPtr(r1) ; (remove temp PTE if present)
lwz r31, PME.PBaseAndFlags(r29)
cmpwi cr7, r28, 0 ; (remove temp PTE if present)
extlwi. r26, r31, 2, 20 ; DaddyFlag and CountingFlag in top bits
bne cr7, @remove_temp_pte ; (remove temp PTE if present)
blt @daddy_flag ; >>>>> DaddyFlag = 1
@return_remove_temp_pte ; (optimized: if LT then to jumps to @daddy_flag)
bgt @create_temp_pte ; >>>>> DaddyFlag = 0, CountingFlag = 1
; fallthru ; >>>>> DaddyFlag = 0, CountingFlag = 0
########################################################################
; CODE TO CREATE A PAGE TABLE ENTRY
; <<<<< Fallthru from main entry point (top two flags of PME are zero)
slwi r28, r30, 12
add r31, r31, r28 ; r31 = physical page ptr plus 12 bits of PageMapEntry flags
@return_daddy_flag ; <<<<< @daddy_flag comes here
@return_create_temp_pte ; <<<<< @create_temp_pte comes here (r31=pageptr, r26=0x5A5A)
mfsrin r30, r27 ; HASH FUNCTION: get address of PTEG
rlwinm r28, r27, 26, 10, 25 ; r28 = (1st arg of XOR) * 64b
rlwinm r30, r30, 6, 7, 25 ; r30 = (2nd arg of XOR) * 64b
xor r28, r28, r30 ; r28 (hash output * 64b) = r28 ^ r30
lwz r30, KDP.PTEGMask(r1)
lwz r29, KDP.HTABORG(r1)
and r28, r28, r30
or. r29, r29, r28 ; result (PTEG address) into r29
@retry_other_pteg ; <<<<< @no_blanks_in_pteg can return here after doing sec'dary hash
lwz r30, 0(r29) ; Take address of PTEG in r29, find empty/"invalid" PTE within (optimized!)
lwz r28, 8(r29)
cmpwi cr6, r30, 0
lwz r30, 16(r29)
cmpwi cr7, r28, 0
lwzu r28, 24(r29)
bge cr6, @found_blank_pte
cmpwi cr6, r30, 0
lwzu r30, 8(r29)
bge cr7, @found_blank_pte
cmpwi cr7, r28, 0
lwzu r28, 8(r29)
bge cr6, @found_blank_pte
cmpwi cr6, r30, 0
lwzu r30, 8(r29)
bge cr7, @found_blank_pte
cmpwi cr7, r28, 0
lwzu r28, 8(r29)
bge cr6, @found_blank_pte
cmpwi cr6, r30, 0
addi r29, r29, 8
bge cr7, @found_blank_pte
cmpwi cr7, r28, 0
addi r29, r29, 8
bge cr6, @found_blank_pte
rlwinm r28, r31, 0, 26, 26 ; wImg bit in PTE???
addi r29, r29, 8 ; Leave PTE + 24 in r29
blt cr7, @no_blanks_in_pteg ; >>>>> This might cause PutPTE to return an error (BNE)
@found_blank_pte ; Take PTE address (plus 24) in r29, draft PTE[lo] in r31
cmpwi r26, 0 ; NOTE: top bit of r31 will be set if sec'dary hash func was used
mfsrin r28, r27
extrwi r30, r27, 6, 4 ; PTE[API/26-31] taken from upper 6 bits of offset-within-segment
stw r27, KDP.HtabLastEA(r1)
ori r31, r31, 0x100 ; set PTE[R(eference)]
rlwimi r30, r31, 27, 25, 25 ; set PTE[H(ash func ID)] to cheeky topmost bit of the phys addr in r31
rlwinm r31, r31, 0, 21, 19 ; unset upper reserved bit in PTE[lo]
insrwi r30, r28, 24, 1 ; get PTE[VSID] from segment register
stw r31, -20(r29) ; PTE[lo] = r31
oris r30, r30, 0x8000 ; set PTE[V(alid)]
sync ; because we just wanged the page table
stwu r30, -24(r29) ; PTE[hi] = r30
lwz r28, KDP.NKInfo.HashTableCreateCount(r1)
stw r29, KDP.ApproxCurrentPTEG(r1)
addi r28, r28, 1
stw r28, KDP.NKInfo.HashTableCreateCount(r1)
beqlr ; >>>>> RETURN "BEQ" if we got to "Case 1" directly
cmpwi r26, 0x5A5A ; Special value set so that we take note of this new temporary PTE?
bne @notemp
stw r29, KDP.HtabTempEntryPtr(r1)
cmpw r29, r29 ; >>>>> RETURN "BEQ" if we got to "Case 1" via @create_temp_pte
blr
@notemp
lwz r28, 0(r26) ; Otherwise, we got here via @daddy_flag? Looks nonsensical.
lwz r30, KDP.HTABORG(r1)
ori r28, r28, 0x801
subf r30, r30, r29
cmpw r29, r29
rlwimi r28, r30, 9, 0, 19
stw r28, 0(r26)
blr ; >>>>> RETURN "BEQ" otherwise
########################################################################
; Helpful code that jumps back to roughly where it started
@remove_temp_pte
lwz r28, KDP.NKInfo.HashTableDeleteCount(r1)
lwz r29, KDP.HtabTempEntryPtr(r1)
addi r28, r28, 1
stw r28, KDP.NKInfo.HashTableDeleteCount(r1)
li r28, 0
stw r28, 0(r29)
lwz r29, KDP.HtabTempPage(r1)
stw r28, KDP.HtabTempPage(r1)
stw r28, KDP.HtabTempEntryPtr(r1)
sync
tlbie r29
sync
bge @return_remove_temp_pte ; Optimization: would otherwise branch to a "blt @daddy_flag"
########################################################################
; r30 = page index within area, r31 = PBaseAndFlags
@daddy_flag
extlwi. r28, r31, 2, 21 ; top bits of r28 = CountingFlag, PhysicalIsRelativeFlag
bge @return_via_pf2 ; if !CountingFlag: return (if !PIRFlag: via PF2)
rlwinm r28, r30, 2, 0xFFFFFFFC ; r28 = pageIdxInArea * 4
rlwinm r26, r31, 22, 0xFFFFFFFC ; r26 = PIRFlag << 31 | BtmBit << 22 | physBase * 4
lwzux r28, r26, r28 ; this makes no sense!!
lwz r31, KDP.PageAttributeInit(r1)
andi. r30, r28, 0x881
rlwimi r31, r28, 0, 0xFFFFF000
cmplwi r30, 1
cmplwi cr7, r30, 0x81
ori r31, r31, 0x100
rlwimi r31, r28, 3, 24, 24
rlwimi r31, r28, 31, 26, 26
rlwimi r31, r28, 1, 25, 25
xori r31, r31, 0x40
rlwimi r31, r28, 30, 31, 31
beq @return_daddy_flag
bltlr cr7
bl SystemCrash
########################################################################
; Helpful code that jumps back to roughly where it started
@create_temp_pte ; Make "temp" PageMapEntry, when flags look like 0x800
ori r28, r27, 0xfff ; r27 = passed ptr, r31 = PBaseAndFlags
stw r28, KDP.HtabTempPage(r1)
rlwinm r31, r31, 0, 22, 19 ; clear CountingFlag in r31
li r26, 0x5A5A ; set magic number in r26 so that KDP.HtabTempEntryPtr gets set
b @return_create_temp_pte
########################################################################
; Helpful return code for @daddy_flag
@return_via_pf2
bgtlr
addi r29, r1, KDP.SupervisorMap
b SetMap
########################################################################
; So try the secondary hashing function, if we haven't already
@no_blanks_in_pteg
cmplw cr6, r28, r26
subi r29, r29, 64 + 16
ble cr6, @search_for_matching_pte
crnot cr0_eq, cr0_eq
lwz r30, KDP.PTEGMask(r1)
xori r31, r31, 0x800
xor r29, r29, r30
beq @retry_other_pteg
########################################################################
@search_for_matching_pte ; r29 = full PTEG
lwz r26, KDP.OverflowingPTEG(r1) ; this could be zero
crclr cr6_eq ; prepare to return "failure"
rlwimi r26, r29, 0, -64
addi r29, r26, 8
b @first_pte
@rethink_pte_search
bne cr6, @next_pte
mr r26, r29
@next_pte
cmpw cr6, r29, r26
addi r29, r29, 8
@first_pte
rlwimi r29, r26, 0, 0, 25
lwz r31, 4(r29)
lwz r30, 0(r29)
beq cr6, @got_pte
rlwinm r28, r31, 30, 25, 25
andc. r28, r28, r30 ; R && !H (i.e. page has been read and is not in "secondary hash" PTEG)
bne @next_pte ; if so,
@got_pte
########################################################################
clrlwi r28, r31, 30
cmpwi cr7, r28, 0
clrrwi r28, r31, 12
cmpw r28, r1
lwz r30, KDP.ContextPtr(r1)
beq cr7, @rethink_pte_search
addi r31, r30, 768-1
beq @rethink_pte_search
rlwinm r30, r30, 0, 0xFFFFF000
cmpwi cr7, r28, 30
lwz r30, 0(r29)
rlwinm r31, r31, 0, 0xFFFFF000
cmpwi r28, 31
rlwinm r31, r30, 0, 0x00000040
beq cr7, @rethink_pte_search
extlwi r28, r30, 4, 1
beq @rethink_pte_search
neg r31, r31
insrwi r28, r30, 6, 4
xor r31, r31, r29
rlwimi r28, r30, 5, 10, 19
rlwinm r31, r31, 6, 10, 19
xor r28, r28, r31
lwz r26, KDP.CurMap.SegMapPtr(r1)
rlwinm r30, r28, (32-25), 0x00000078
lwzx r26, r26, r30 ; r26 pts into PageMap @ current segment
@tinyloop ; find the last non-blank PME in the segment
lhz r30, PME.LBase(r26)
rlwinm r31, r28, 20, 0x0000FFFF
subf r30, r30, r31
lhz r31, PME.PageCount(r26)
addi r26, r26, 8
cmplw cr7, r30, r31
lwz r31, PME.PBaseAndFlags - 8(r26)
andi. r31, r31, 0xe01
cmpwi r31, 0xa01
bgt cr7, @tinyloop
beq @tinyloop
lwz r26, PME.PBaseAndFlags - 8(r26) ; got that PME (26)
slwi r30, r30, 2
extrwi r31, r26, 2, 20
cmpwi cr7, r31, 3 ; not a DaddyFlag + CountingFlag? Try again!
lwz r31, KDP.NKInfo.HashTableOverflowCount(r1)
stw r29, KDP.OverflowingPTEG(r1)
addi r31, r31, 1
stw r31, KDP.NKInfo.HashTableOverflowCount(r1)
lwz r31, KDP.NKInfo.HashTableDeleteCount(r1)
stw r30, 0(r29)
addi r31, r31, 1
stw r31, KDP.NKInfo.HashTableDeleteCount(r1)
sync
tlbie r28
sync
_InvalNCBPointerCache scratch=r28
bne cr7, PutPTE ; not a DaddyFlag + CountingFlag? Retriable...
rlwinm r26, r26, 22, 0xFFFFFFFC ; PIRFlag << 31 | BtmBit << 22 | physBase * 4
lwzux r28, r26, r30
lwz r31, 4(r29)
andi. r30, r28, 0x800
rlwinm r30, r28, (32-9), 0x007FFFF8
xor r30, r30, r29
beq SystemCrash
andi. r30, r30, 0xffff
xori r28, r28, 0x800
bne SystemCrash
rlwimi r28, r31, 0, 0, 19 ; r28 = EA of victim of overflow
rlwimi r28, r31, 29, 27, 27
rlwimi r28, r31, 27, 28, 28
stw r28, 0(r26)
b PutPTE
########################################################################
########################################################################
SetMap ; MemMap r29
lwz r28, MemMap.SegMapPtr(r29)
stw r28, KDP.CurMap.SegMapPtr(r1)
addi r28, r28, 16*8 + 4
lis r31, 0
@next_seg ; SEGMENT REGISTERS
lwzu r30, -8(r28)
subis r31, r31, 0x1000
mr. r31, r31
mtsrin r30, r31
bne @next_seg
mfpvr r31
lwz r28, MemMap.BatMap(r29)
andis. r31, r31, 0xFFFE
addi r29, r1, 0
stw r28, KDP.CurMap.BatMap(r1)
beq @601
rlwimi r29, r28, 7, 0x00000078 ; BATS, non-601
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr ibat0u, r30
mtspr ibat0l, r31
stw r30, KDP.CurIBAT0.U(r1)
stw r31, KDP.CurIBAT0.L(r1)
rlwimi r29, r28, 11, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr ibat1u, r30
mtspr ibat1l, r31
stw r30, KDP.CurIBAT1.U(r1)
stw r31, KDP.CurIBAT1.L(r1)
rlwimi r29, r28, 15, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr ibat2u, r30
mtspr ibat2l, r31
stw r30, KDP.CurIBAT2.U(r1)
stw r31, KDP.CurIBAT2.L(r1)
rlwimi r29, r28, 19, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr ibat3u, r30
mtspr ibat3l, r31
stw r30, KDP.CurIBAT3.U(r1)
stw r31, KDP.CurIBAT3.L(r1)
rlwimi r29, r28, 23, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr dbat0u, r30
mtspr dbat0l, r31
stw r30, KDP.CurDBAT0.U(r1)
stw r31, KDP.CurDBAT0.L(r1)
rlwimi r29, r28, 27, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr dbat1u, r30
mtspr dbat1l, r31
stw r30, KDP.CurDBAT1.U(r1)
stw r31, KDP.CurDBAT1.L(r1)
rlwimi r29, r28, 31, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr dbat2u, r30
mtspr dbat2l, r31
stw r30, KDP.CurDBAT2.U(r1)
stw r31, KDP.CurDBAT2.L(r1)
rlwimi r29, r28, 3, 0x00000078
lwz r30, KDP.BATs + BAT.U(r29)
lwz r31, KDP.BATs + BAT.L(r29)
mtspr dbat3u, r30
mtspr dbat3l, r31
stw r30, KDP.CurDBAT3.U(r1)
stw r31, KDP.CurDBAT3.L(r1)
cmpw r29, r29
blr
@601
rlwimi r29, r28, 7, 25, 28
lwz r30, KDP.BATs + 0(r29)
lwz r31, KDP.BATs + 4(r29)
stw r30, 0x0300(r1)
stw r31, 0x0304(r1)
stw r30, 0x0320(r1)
stw r31, 0x0324(r1)
rlwimi r30, r31, 0, 25, 31
mtspr ibat0u, r30
lwz r30, KDP.BATs + 0(r29)
rlwimi r31, r30, 30, 26, 31
rlwimi r31, r30, 6, 25, 25
mtspr ibat0l, r31
rlwimi r29, r28, 11, 25, 28
lwz r30, KDP.BATs + 0(r29)
lwz r31, KDP.BATs + 4(r29)
stw r30, 0x0308(r1)
stw r31, 0x030c(r1)
stw r30, 0x0328(r1)
stw r31, 0x032c(r1)
rlwimi r30, r31, 0, 25, 31
mtspr ibat1u, r30
lwz r30, KDP.BATs + 0(r29)
rlwimi r31, r30, 30, 26, 31
rlwimi r31, r30, 6, 25, 25
mtspr ibat1l, r31
rlwimi r29, r28, 15, 25, 28
lwz r30, KDP.BATs + 0(r29)
lwz r31, KDP.BATs + 4(r29)
stw r30, 0x0310(r1)
stw r31, 0x0314(r1)
stw r30, 0x0330(r1)
stw r31, 0x0334(r1)
rlwimi r30, r31, 0, 25, 31
mtspr ibat2u, r30
lwz r30, KDP.BATs + 0(r29)
rlwimi r31, r30, 30, 26, 31
rlwimi r31, r30, 6, 25, 25
mtspr ibat2l, r31
rlwimi r29, r28, 19, 25, 28
lwz r30, KDP.BATs + 0(r29)
lwz r31, KDP.BATs + 4(r29)
stw r30, 0x0318(r1)
stw r31, 0x031c(r1)
stw r30, 0x0338(r1)
stw r31, 0x033c(r1)
rlwimi r30, r31, 0, 25, 31
mtspr ibat3u, r30
lwz r30, KDP.BATs + 0(r29)
rlwimi r31, r30, 30, 26, 31
rlwimi r31, r30, 6, 25, 25
mtspr ibat3l, r31
cmpw r29, r29
blr
########################################################################
########################################################################
GetPhysical ; EA r27, batPtr r29 // PA r31, EQ=Fail
lwz r30, 0(r29)
li r28, -1
rlwimi r28, r30, 15, 0, 14
xor r31, r27, r30
andc. r31, r31, r28
beq @_54
lwzu r30, 8(r29)
rlwimi r28, r30, 15, 0, 14
xor r31, r27, r30
andc. r31, r31, r28
beq @_54
lwzu r30, 8(r29)
rlwimi r28, r30, 15, 0, 14
xor r31, r27, r30
andc. r31, r31, r28
beq @_54
lwzu r30, 8(r29)
rlwimi r28, r30, 15, 0, 14
xor r31, r27, r30
andc. r31, r31, r28
bne GetPhysicalFromHTAB
@_54
andi. r31, r30, 1
rlwinm r28, r28, 0, 8, 19
lwzu r31, 4(r29)
and r28, r27, r28
or r31, r31, r28
bnelr
GetPhysicalFromHTAB ; EA r27 // PA r31, EQ=Fail
mfsrin r31, r27
rlwinm r30, r27, 10, 26, 31
rlwimi r30, r31, 7, 1, 24
rlwinm r28, r27, 26, 10, 25
oris r30, r30, 0x8000
rlwinm r31, r31, 6, 7, 25
xor r28, r28, r31
lwz r31, KDP.PTEGMask(r1)
lwz r29, KDP.HTABORG(r1)
and r28, r28, r31
or. r29, r29, r28
@_2c
lwz r31, 0(r29)
lwz r28, 8(r29)
cmpw cr6, r30, r31
lwz r31, 16(r29)
cmpw cr7, r30, r28
lwzu r28, 24(r29)
bne cr6, @_50
@_48
lwzu r31, -0x0014(r29)
blr
@_50
cmpw cr6, r30, r31
lwzu r31, 8(r29)
beq cr7, @_48
cmpw cr7, r30, r28
lwzu r28, 8(r29)
beq cr6, @_48
cmpw cr6, r30, r31
lwzu r31, 8(r29)
beq cr7, @_48
cmpw cr7, r30, r28
lwzu r28, 8(r29)
beq cr6, @_48
cmpw cr6, r30, r31
lwzu r31, -0x000c(r29)
beqlr cr7
cmpw cr7, r30, r28
lwzu r31, 8(r29)
beqlr cr6
lwzu r31, 8(r29)
beqlr cr7
lwz r31, KDP.PTEGMask(r1)
xori r30, r30, 0x40
andi. r28, r30, 0x40
addi r29, r29, -0x3c
xor r29, r29, r31
bne @_2c
blr
########################################################################
########################################################################
FlushTLB
lhz r29, KDP.ProcInfo.TransCacheTotalSize(r1)
slwi r29, r29, 11
@loop
subi r29, r29, 4096
cmpwi r29, 0
tlbie r29
bgt @loop
sync
blr