powermac-rom/NanoKernel/NKReplacementInit.s
2018-04-15 17:00:11 +08:00

478 lines
9.2 KiB
ArmAsm

; sprg0 = old KDP/EWA/r1 ptr
; r3 = PA_NanoKernelCode
; r4 = physical base of our global area
; r5 = NoIdeaR23
; r6 = PA_EDP or zero?
; r7 = probably ROMHeader.ROMRelease ('rom vers', e.g. 0x10B5 is 1.0§5)
InitReplacement
crset cr5_eq
li r0, 0
; Position and initialise the kernel globals, IRP to KDP inclusive.
; (subset of builtin kernel)
; Zero from IRP (r4) to KDP (r4 + 10 pages)
lisori r12, kKDPfromIRP
mr r13, r4
@wipeloop
subic. r12, r12, 4
stwx r0, r13, r12
bgt @wipeloop
; Copy the old KDP to r4 + 10 pages.
; (r1 becomes our main ptr and r4 is discarded)
mfsprg r11, 0
lisori r1, kKDPfromIRP
add r1, r1, r4
li r12, 4096
@kdp_copyloop
subic. r12, r12, 4
lwzx r10, r11, r12
stwx r10, r1, r12
bgt @kdp_copyloop
; IRP goes at the base of the area we were given.
; Fill with repeating pattern and point EWA at it.
lisori r12, -kKDPfromIRP
add r12, r12, r1
stw r12, EWA.PA_IRP(r1)
bl InitIRP ; clobbers r10 and r12
; Play with some of the other values we were given
; Leave ROMRelease in r23.
mr r23, r7
; If no EDP (Emulator Data Page) pointer was provided,
; then put the EDP above our new KDP.
cmpwi r6, 0
stw r11, KDP.OldKDP(r1)
stw r9, 0x05a4(r1)
; discarded
bne @emulatordata_ptr_provided
addi r6, r1, 0x1000
@emulatordata_ptr_provided
; Save a few bits
stw r6, 0x05a8(r1)
stw r3, KDP.PA_NanoKernelCode(r1)
stw r5, PSA.NoIdeaR23(r1)
stw r1, EWA.PA_KDP(r1)
addi r12, r1, -0x340 ; get the base of the main CPU struct
li r10, -1
stw r10, CPU.ID(r12)
lwz r3, KDP.PA_ConfigInfo(r1)
bl LookupInterruptHandler
stw r7, KDP.PA_InterruptHandler(r1)
; Clearly changed our mind about where we might be.
bl @x
@x mflr r12
subi r12, r12, @x - NKTop
stw r12, KDP.PA_NanoKernelCode(r1)
; FDP
llabel r10, FDP
add r12, r10, r12
stw r12, KDP.PA_FDP(r1)
; Do something terrible with the CPU features
lwz r12, EWA.Flags(r1)
li r10, 0x00
rlwimi r10, r12, 0, 12, 15
rlwimi r10, r12, 0, 28, 30
stw r10, -0x0968(r1)
; Cook up a MSR:
; MSR_EE = 1
; MSR_PR = 1
; MSR_FP = 0
; MSR_ME = 0
; MSR_FE0 = 0
; MSR_SE = 0
; MSR_BE = 0
; MSR_FE1 = 0
; MSR_IP = preserved
; MSR_IR = 1
; MSR_DR = 1
; MSR_RI = 0
; MSR_LE = 0
mfmsr r12
andi. r12, r12, 0x0040
ori r12, r12, 0xd032
stw r12, PSA.UserModeMSR(r1)
; Set SPRG0 (for this CPU at least)
mtsprg 0, r1
; r11 still contains the OLD EWA ptr (which is also KDP/PSA ptr?)
lhz r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoVer(r11)
cmpwi r12, 0x0101
bgt @replaces_later_than_0101
;
lwz r12, KDP.PA_ECB_Old(r1)
stw r12, EWA.PA_ContextBlock(r1)
lwz r12, 0x660(r1)
oris r12, r12, 0x20
stw r12, EWA.Flags(r1)
lwz r12, 0x0664(r1)
stw r12, EWA.Enables(r1) ; boy, better figure out what this is
b @endif
@replaces_later_than_0101
; Obviously cannot replace a v2 NanoKernel like myself
cmpwi r12, 0x0200
bge CancelReplacement
lwz r12, EWA.PA_ContextBlock(r11)
stw r12, EWA.PA_ContextBlock(r1)
lwz r12, EWA.Flags(r11)
oris r12, r12, 0x20
stw r12, EWA.Flags(r1)
lwz r12, -0x000c(r11)
stw r12, EWA.Enables(r1)
@endif
lwz r12, 0x0340(r11)
lwz r10, KDP.LA_NCB(r11)
cmpw r12, r10
beq replace_old_kernel_0x198
stw r12, KDP.LA_NCB(r1)
stw r0, 0x06b4(r1)
lwz r10, 0x05b0(r11)
stw r10, 0x06c0(r1)
lwz r10, KDP.LA_NCB(r11)
stw r10, 0x06c4(r1)
lwz r10, 0x05b8(r11)
stw r10, 0x06c8(r1)
lwz r10, 0x05bc(r11)
stw r10, 0x06cc(r1)
stw r0, 0x06d0(r1)
stw r0, 0x06d4(r1)
stw r0, 0x06d8(r1)
stw r0, 0x06dc(r1)
stw r0, 0x06e0(r1)
stw r0, 0x06e4(r1)
stw r0, 0x06e8(r1)
stw r0, 0x06ec(r1)
stw r0, 0x06f0(r1)
stw r0, 0x06f4(r1)
stw r0, 0x06f8(r1)
stw r0, 0x06fc(r1)
replace_old_kernel_0x198
; Adjust a few KDP pointers to point into the new KDP
lwz r12, KDP.PA_PageMapStart(r1)
subf r12, r11, r12
add r12, r12, r1
stw r12, KDP.PA_PageMapStart(r1)
lwz r12, KDP.PA_PageMapEnd(r1)
subf r12, r11, r12
add r12, r12, r1
stw r12, KDP.PA_PageMapEnd(r1)
lwz r12, 0x05e8(r1)
subf r12, r11, r12
add r12, r12, r1
stw r12, 0x05e8(r1)
; Wipe KDP's NKInfo and ProcessorInfo
li r12, 0x200
addi r10, r1, KDP.NanoKernelInfo
@wipeloop
subic. r12, r12, 4
stwx r0, r10, r12
bgt @wipeloop
; r9 = physical base of kernel
li r12, 0
addi r10, r1, KDP.InfoRecord
bl MoveRecord ; (NanoKernelCode, NewKDPInfoRecord, OldKDP, 0)
stw r10, KDP.InfoRecord + InfoRecord.InfoRecordPtr(r1)
stw r0, KDP.InfoRecord + InfoRecord.Zero(r1)
lhz r12, KDP.InfoRecord + InfoRecord.NKProcessorStateLen(r1)
addi r10, r1, PSA.ProcessorState
lwz r9, KDP.InfoRecord + InfoRecord.NKProcessorStatePtr(r1)
bl MoveRecord ; (OldProcessorState, NewPSAProcessorState, OldKDP, ProcessorStateLen)
stw r10, KDP.InfoRecord + InfoRecord.NKProcessorStatePtr(r1)
lhz r12, KDP.InfoRecord + InfoRecord.NKHWInfoLen(r1)
lwz r10, EWA.PA_IRP(r1)
addi r10, r10, IRP.HWInfo
lwz r9, KDP.InfoRecord + InfoRecord.NKHWInfoPtr(r1)
bl MoveRecord ; (OldHWInfo, NewIRPHWInfo, OldKDP, HWInfoLen)
stw r10, KDP.InfoRecord + InfoRecord.NKHWInfoPtr(r1)
lhz r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen(r1)
addi r10, r1, KDP.ProcessorInfo
lwz r9, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr(r1)
bl MoveRecord ; (OldProcessorInfo, NewKDPProcessorInfo, OldKDP, ProcessorInfoLen)
stw r10, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr(r1)
stw r10, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr2(r1)
lhz r10, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer(r1)
cmplwi r10, 0x0112
bge @ProcessorInfo_version_already_current
li r12, 160
li r10, 0x0112
sth r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen(r1)
sth r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen2(r1)
sth r10, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer(r1)
sth r10, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer2(r1)
@ProcessorInfo_version_already_current
lhz r12, KDP.InfoRecord + InfoRecord.NKDiagInfoLen(r1)
addi r10, r1, PSA.DiagInfo
lwz r9, KDP.InfoRecord + InfoRecord.NKDiagInfoPtr(r1)
bl MoveRecord ; (OldDiagInfo, NewPSADiagInfo, OldKDP, DiagInfoLen)
stw r10, KDP.InfoRecord + InfoRecord.NKDiagInfoPtr(r1)
lhz r12, KDP.InfoRecord + InfoRecord.NKSystemInfoLen(r1)
lwz r10, EWA.PA_IRP(r1)
addi r10, r10, IRP.SystemInfo
lwz r9, KDP.InfoRecord + InfoRecord.NKSystemInfoPtr(r1)
bl MoveRecord ; (OldSystemInfo, NewIRPSystemInfo, OldKDP, SystemInfoLen)
stw r10, KDP.InfoRecord + InfoRecord.NKSystemInfoPtr(r1)
lhz r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoLen(r1)
addi r10, r1, KDP.NanoKernelInfo
lwz r9, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoPtr(r1)
bl MoveRecord ; (OldNanoKernelInfo, NewKDPNanoKernelInfo, OldKDP, NanoKernelInfoLen)
stw r10, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoPtr(r1)
li r12, 0x160
sth r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoLen(r1)
li r12, kNanoKernelVersion
sth r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoVer(r1)
lwz r8, KDP.ProcessorInfo + NKProcessorInfo.DecClockRateHz(r1)
stw r8, PSA.DecClockRateHzCopy(r1)
; Play with ConfigFlags
lwz r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
_bset r8, r8, 31 ; always set bit 31
if &TYPE('NKShowLog') != 'UNDEFINED'
_bset r8, r8, 28 ; see if someone can test this
endif
cmplwi r23, 0x27f3 ; set bit 27 on ROM 2.7f3 or later
blt @oldrom ; means later than PDM and Cordyceps
_bset r8, r8, 27
@oldrom
stw r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
; Say hello.
bl InitScreenConsole
_log 'Hello from the replacement multitasking NanoKernel. Version: '
mr r8, r12
bl printh
_log '^n Old KDP: '
mr r8, r11
bl printw
_log ' new KDP: '
mr r8, r1
bl printw
_log ' new irp: '
lwz r8, EWA.PA_IRP(r1)
mr r8, r8
bl printw
_log 'ROM vers: '
mr r8, r23
bl printh
_log '^n'
; Jump back into the common code path of Init.s
; The Emulator ContextBlock is expected in r6.
lwz r6, KDP.PA_ECB(r1)
b InitHighLevel
; MoveRecord
; r9 = base of kernel???
; Seems to be code to relocate some old structures.
MoveRecord ; OUTSIDE REFERER
; Check whether the old structure is in KDP
;
lwz r22, KDP.PA_ConfigInfo(r1)
lwz r22, NKConfigurationInfo.LA_InfoRecord(r22)
subf r9, r22, r9 ; r9 = offset of old address in irp
cmplwi r9, 0x1000
bge @kdp
add r21, r9, r11 ; r21 = the old address if it had been in KDP instead?
@0x18
; r9 = offset of old structure in old parent page
; r10 = destination
; r12 = length
;
@loop
subic. r12, r12, 4
blt @exit_loop
lwzx r9, r21, r12
stwx r9, r10, r12
bgt @loop
@exit_loop
lwz r22, KDP.PA_ConfigInfo(r1)
lwz r22, NKConfigurationInfo.LA_KernelData(r22)
subf r10, r1, r10
lisori r21, -9 * 4096
cmpw r10, r21 ; if dest is nearer than 9 pages below kdp...
blt @0x50
add r10, r10, r22
blr
@0x50
lwz r22, KDP.PA_ConfigInfo(r1)
lwz r22, NKConfigurationInfo.LA_InfoRecord(r22)
lwz r21, EWA.PA_IRP(r1)
add r10, r10, r1
subf r10, r21, r10
add r10, r10, r22
blr
@kdp
add r9, r9, r22
lwz r22, KDP.PA_ConfigInfo(r1)
lwz r22, NKConfigurationInfo.LA_KernelData(r22)
subf r9, r22, r9 ; r9 now equals an offset from old_kdp
add r21, r9, r11 ; r21 = address in new_kdp
b @0x18