;	AUTO-GENERATED SYMBOL LIST
;	IMPORTS:
;	  NKConsoleLog
;	    printh
;	  NKInit
;	    FinishInitBuiltin
;	    InitIRP
;	  NKPrimaryIntHandlers
;	    LookupInterruptHandler
;	  NKProcInfoTbl
;	    OverrideProcessorInfo
;	    ProcessorInfoTable
;	  NKScreenConsole
;	    InitScreenConsole
;	  NKTranslation
;	    FDP
;	EXPORTS:
;	  InitBuiltin (=> NKInit)


;	When we receive control:
;		r3 = ConfigInfo
;		r4 = ProcessorInfo
;		r5 = SystemInfo
;		r6 = DiagInfo
;		r7 = RTAS_flag ('RTAS' or 0)
;		r8 = RTAS_proc
;		r9 = HWInfo



InitBuiltin



;	Leave zero in r0 (it is rather a silly place).

	li		r0, 0



;	Initialize segment registers (understand these better!)

	isync
	lis			r12, 0x2000
	mtsr		0, r12
	mtsr		1, r0
	mtsr		2, r0
	mtsr		3, r0
	mtsr		4, r0
	mtsr		5, r0
	mtsr		6, r0
	mtsr		7, r0
	mtsr		8, r0
	mtsr		9, r0
	mtsr		10, r0
	mtsr		11, r0
	mtsr		12, r0
	mtsr		13, r0
	mtsr		14, r0
	mtsr		15, r0
	isync



;	Zero out the timebase (rtc on 601) and upper BAT registers
;	(this is best practice for invalidating BATs)
;	(Interestingly, SheepShaver also uses r12 for this PVR access.)

	mfspr	r12, pvr
	rlwinm.	r12, r12, 0, 0, 14
	bne		@not601

	mtspr	rtcl, r0
	mtspr	rtcu, r0
	mtspr	ibat0l, r0
	mtspr	ibat1l, r0
	mtspr	ibat2l, r0
	mtspr	ibat3l, r0

	b		@endif601
@not601

	mtspr	tbl, r0
	mtspr	tbu, r0
	mtspr	ibat0u, r0
	mtspr	ibat1u, r0
	mtspr	ibat2u, r0
	mtspr	ibat3u, r0
	mtspr	dbat0u, r0
	mtspr	dbat1u, r0
	mtspr	dbat2u, r0
	mtspr	dbat3u, r0

@endif601




;	The Trampoline instructs us to put the base of the blue area at
;	this physical address, which seems always to be the base of the
;	first RAM bank reported by the trampoline. (The kernel is also
;	expected to initialise MacOS LowMemory from a key/valye list.)

	lwz		r12, NKConfigurationInfo.PA_RelocatedLowMemInit(r3)



;	Search SysInfo for the first nonzero size RAM bank.

	addi	r10, r5, NKSystemInfo.Bank0Start - 4
@rambank_loop
	lwzu	r11, 8(r10)		; Bank0Size, Bank1Size...
	cmpwi	r11, 0
	beq		@rambank_loop

	;	r10 points to BankXSize, r11 contains BankXSize



;	DeltaMemory = PA_RelocatedLowMemInit if fits in bank, else 0.

	subf	r11, r12, r11
	srawi	r11, r11, 31	; f... if PA_ > BankSize else 0...
	andc	r12, r12, r11	; zero DeltaMemory if PA_ > BankSize



;	BankSize -= DeltaMemory

	lwz		r11, 0(r10)
	subf	r11, r12, r11
	stw		r11, 0(r10)



;	BankStart += DeltaMemory

	lwz		r11, -4(r10)
	add		r11, r11, r12
	stw		r11, -4(r10)



;	PhysicalMemorySize -= DeltaMemory (+ another page if there is close to 2GB)

	lwz		r11, NKSystemInfo.PhysicalMemorySize(r5)
	addis	r15, r11, 1
	cmpwi	r15, 0
	bgt		@skip_reducing_ram
	addi	r11, r11, -4096
@skip_reducing_ram
	subf	r11, r12, r11
	stw		r11, 0(r5)



;	Load PhysicalMemorySize - 1 into r15.
;
;	Create the HTABMASK for eventual insertion in lo half of SDR1:
;	-	Is number of bits used from hash func to index PTEGs in HTAB.
;	-	Arch allows 10..19 bits.
;		-	Bits 0-9 assumed by architecture.
;		-	Bits 10-18 in the low field of SDR1.
;		-	Bits 19-31 also in low field, but must be zeroed.
;	-	Our r14 "mask" = (future low half of SDR1) || 0xffff.
;		-	Therefore has an extra six ones.
;		-	Therefore equals HTAB size - 1.
;	-	Computed from PhysicalMemorySize as follows:
;
;	---------------------------------------------------------------------
;	Phys RAM		r14			HTABMASK bits	PTEGs in HTAB	HTAB size
;	(MB)						(10-19 allowed)
;	---------------------------------------------------------------------
;	<= 8		0000ffff			10				1k				64k
;	<= 16		0001ffff			11				2k				128k
;	<= 32		0003ffff			12				4k				256k
;	<= 64		0007ffff			13				8k				512k
;	<= 128		000fffff			14				16k				1024k
;	<= 256		001fffff			15				32k				2048k
;	 > 256		003fffff			16				64k				4096k

	lwz		r15, NKSystemInfo.PhysicalMemorySize(r5)
	addi	r15, r15, -1
	cntlzw	r12, r15

	lis		r14, 0x01ff
	srw		r14, r14, r12
	ori		r14, r14, 0xffff
	clrlwi	r14, r14, 10



;	Based on PhysicalMemorySize, guess how much memory the
;	kernel needs, including the HTAB. Leave it in r15.
;
;	-----------------------------
;	Phys RAM	r15			Kern
;	(MB)					pages
;	-----------------------------
;	>=   4		0001d000	  29
;	>=   8		0001e000	  30
;	>=  16		00030000	  48
;	>=  32		00054000	  84
;	>=  64		0009c000	 156
;	>= 128		0012c000	 300
;	>= 256		0024c000	 588
;	>= 512		0048c000	1164
;	>=1024		0050c000	1292
;	>=2048		0060c000	1548

	addis	r15, r15, 0x40
	rlwinm	r15, r15, 22, 10, 19
	add		r15, r15, r14
	lisori	r10, 0x0000c001
	add		r15, r15, r10



;	Search SysInfo backwards for a RAM bank that can fit:
;	-	A HTAB aligned to a multiple of its own length
;	-	An r15-size area immediately below that
;
;	Kernel structures (HTAB at top) will butt up against
;	BankEnd % HTABSIZE. Leave bottom in r13 and top in r12.

	addi	r10, r5, NKSystemInfo.EndOfBanks
@try_another_bank
	lwz		r11, -4(r10)			;	size
	lwzu	r12, -8(r10)			;	start
	add		r11, r12, r11			;	end
	andc	r13, r11, r14			;	end % HTABSIZE
	subf	r13, r15, r13			;	end % HTABSIZE - r15
	cmplw	r13, r12
	blt		@try_another_bank
	cmplw	r13, r11
	bgt		@try_another_bank

	add		r12, r13, r15



;	Populate SDR1 with HTABORG || HTABMASK:
;	-	HTABORG = top_of_bank % HTABSIZE (only top half)
;	-	HTABMASK = top half of r14 (which equals HTABSIZE-1)
;
;	Leave SDR1 in r12 and HTABORG (a full address) in r11.

	subf	r12, r14, r12
	rlwimi r12, r14, 16, 16, 31
	mtspr	sdr1, r12

	rlwinm r11, r12, 0, 0, 15



;	Recap: (matches SheepShaver notes on NKv1)
;		r11		HTABORG
;		r12		SDR1
;		r13		base of "reserved" kernel area
;		r14		HTABSIZE - 1
;		r15		size of "reserved" kernel area



;	Place the kernel data page (KDP) 8k below the HTAB,
;	and point SPRG0 at it. r1 almost always points to KDP.
;
;	Page above KDP becomes emulator data page (EDP).
;	Page below KDP becomes private v2 kernel globals.

	lisori	r1,	-0x2000
	add		r1, r1, r11

	mtsprg	0, r1



;	Init the reserved area to zero, up to the HTAB.
;
;	But if the machine has Thudded and dumped all its registers
;	(as evidenced by a saved SDR1) then don't zero that dump.

	lwz		r11, KDP.ThudSavedSDR1(r1)
	cmpw	r12, r11
	lis		r11, 0x7fff

	bne		@did_not_panic
	subf	r11, r13, r1
	addi	r11, r11, KDP.StartOfPanicArea
@did_not_panic

	subf	r12, r14, r15
	addi	r12, r12, -0x01

@eraseloop
	addic.	r12, r12, -4

	subf	r10, r11, r12
	cmplwi	cr7, r10, KDP.EndOfPanicArea - KDP.StartOfPanicArea - 4

	ble		cr7, @skipwrite
	stwx	r0, r13, r12
@skipwrite

	bne		@eraseloop



;	Put r1 pointer (for indexing PSA/KDP) in CPU-0 EWA 

	stw		r1, EWA.PA_KDP(r1)



;	Set up the interrupt response page (IRP) at KDP - (10 pages).
;
;	(Point CPU-0 EWA to it and fill it with 0x68f168f1.)

	lisori	r12, IRPOffset
	add		r12, r12, r1
	stw		r12, EWA.PA_IRP(r1)

	bl		InitIRP



;	Set up runtime abstraction services (RTAS).
;
;	Kernel argument r7 is either 'RTAS' or zero. If 'RTAS':
;	-	Arg r8 points to RTAS dispatch proc.
;	-	Arg r9 points to HWInfo points to RTAS private data
;	-	Copy HWInfo into IRP
;
;	TODO: neaten, use records!


	lisori	r12, 'RTAS'
	cmpw	r7, r12
	bne		@RTAS_absent

	stw		r8, KDP.RTAS_Proc(r1)

	lwz		r7, NKHWInfo.RTAS_PrivDataArea(r9)
	stw		r7, KDP.RTAS_PrivDataArea(r1)

	lwz		r11, EWA.PA_IRP(r1)
	addi	r11, r11, IRP.HWInfo
	li		r10, 0xc0

@RTAS_copyloop
	addic. r10, r10, -4
	lwzx	r12, r9, r10
	stwx	r12, r11, r10
	bgt		@RTAS_copyloop

	stw		r23, PSA.NoIdeaR23(r1)
	b		@RTAS_done

@RTAS_absent
	stw		r0, KDP.RTAS_Proc(r1)
	stw		r0, KDP.RTAS_PrivDataArea(r1)

@RTAS_done



;	Copy 160 bytes of ProcessorInfo into KDP
;	(Way longer than anything I know about!)

	addi	r11, r1, KDP.ProcessorInfo
	li		r10, 160
@ProcessorInfo_copyloop
	addic. r10, r10, -4
	lwzx	r12, r4, r10
	stwx	r12, r11, r10
	bgt		@ProcessorInfo_copyloop



;	Copy 320 bytes of SystemInfo into IRP

	lwz		r11, EWA.PA_IRP(r1)
	addi	r11, r11, IRP.SystemInfo
	li		r10, 320
@SystemInfo_copyloop
	addic. r10, r10, -4
	lwzx	r12, r5, r10
	stwx	r12, r11, r10
	bgt		@SystemInfo_copyloop



;	If DiagnosticInfo != 0, copy it to PSA

	cmpwi	r6, 0
	beq		@DiagInfo_skipcopy

	addi	r11, r1, PSA.DiagInfo
	li		r10, 256; NKDiagInfo.Size

@DiagInfo_copyloop
	addic. r10, r10, -4
	lwzx	r12, r6, r10
	stwx	r12, r11, r10
	bgt		@DiagInfo_copyloop

@DiagInfo_skipcopy



;	Store a ConfigInfo pointer in KDP

	stw		r3, KDP.PA_ConfigInfo(r1)



;	Add to (presumably empty) ConfigFlags

	lwz		r9, KDP.PA_ConfigInfo(r1)
	lhz		r8, NKConfigurationInfo.Debug(r9)

	;	If CI.Debug >= 257 && CI.DebugFlags & 2 ...
	cmplwi	r8, NKConfigurationInfo.DebugThreshold
	lwz		r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)

	if		&TYPE('NKShowLog') = 'UNDEFINED'
		blt		@no_screen_log
		lwz		r8, NKConfigurationInfo.DebugFlags(r9)
		rlwinm.	r8, r8, 0, NKConfigurationInfo.LogFlagBit, NKConfigurationInfo.LogFlagBit
		lwz		r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
		beq		@no_screen_log
	endif

	;	Enable the screen log
	ori		r8, r8, 1<< 3
@no_screen_log

	;	Switch on two other flags
	ori		r8, r8, 1<< 0		; not sure
	ori		r8, r8, 1<< 4		; to do with interrupts
	stw		r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)



;	Turns out that there was a CPU struct hiding between PSA and KDP,
;	which contains our main CPU ewa

	addi	r9, r1, EWA.CPUBase
	li		r8, -1
	stw		r8, CPU.ID(r9)



; Say hello.

	bl		InitScreenConsole

	_log	'Hello from the builtin multitasking NanoKernel. Version: '

	li		r8, kNanoKernelVersion
	mr		r8, r8
	bl		Printh

	_log	'^n'



;	Save a pointer to the kernel memory area in KDP
;	(will get upped by pool extends?)

	stw		r13, KDP.KernelMemoryBase(r1)



;	PA_NanoKernelCode is uninitialized, but this loaded value gets
;	clobbered straight away anyway. Compiler!

	lwz		r12, KDP.PA_NanoKernelCode(r1)



;	Choose a primary interrupt handler (PIH)
;
	;	ARG		NKConfigurationInfo *r3
	bl		LookupInterruptHandler
	;	RET		InterruptHandler *r7
	;	CLOB	r12

	stw		r7, KDP.PA_InterruptHandler(r1)



;	Store HTABSIZE in the IRP

	lwz		r11, EWA.PA_IRP(r1)
	addi	r12, r14, 1
	stw		r12, IRP.SystemInfo + NKSystemInfo.HashTableSize(r11)



;	Populate KDP...

	;	Place EDP pointer (and leave it in r8).
	addi		r8, r1, 0x1000
	stw		r8, KDP.PA_EmulatorData(r1)


	;	Place pointer to top of reserved kernel area.
	;	(= ptr to top of HTAB)
	add		r12, r13, r15
	stw		r12, KDP.KernelMemoryEnd(r1)


	;	Place PA_RelocatedLowMemInit from ConfigInfo in KDP.
	;	(See note above.)
	lwz		r12, NKConfigurationInfo.PA_RelocatedLowMemInit(r3)
	stw		r12, KDP.PA_RelocatedLowMemInit(r1)


	;	Place something from ConfigInfo in KDP.
	;	This address seems to contain 0x40820160.
	;	Trampoline ns old SharedMemoryAddr, which was 0 anyway.
	lwz		r12, NKConfigurationInfo.SharedMemoryAddr(r3)
	stw		r12, KDP.SharedMemoryAddr(r1)


	;	Place (LA_EmulatorCode + KernelTrapTableOffset) from ConfigInfo in KDP.
	;	(Call this LA_EmulatorKernelTrapTable?)
	lwz		r12, NKConfigurationInfo.LA_EmulatorCode(r3)
	lwz		r11, NKConfigurationInfo.KernelTrapTableOffset(r3)
	add		r12, r12, r11
	stw		r12, KDP.LA_EmulatorKernelTrapTable(r1)


	;	Place "PA_NanoKernelCode" in KDP and leave it in r12.
	bl		* + 4
	mflr	r12
	addi	r12, r12, 4 - *
	stw		r12, KDP.PA_NanoKernelCode(r1)


	;	FDP. Got its name from an embarrassing mistake by me. Needs a better one.
	;	Probably written by Gary, it emulates bad PowerPC instructions.
	llabel	r11, FDP
	add		r12, r11, r12
	stw		r12, KDP.PA_FDP(r1)


	;	Place "LA_ECB" and "PA_ECB" (twice) from ConfigInfo in KDP.
	;	(This gets called the System Context.)
	lwz		r12, NKConfigurationInfo.LA_EmulatorData(r3)
	lwz		r11, NKConfigurationInfo.ECBOffset(r3)
	add		r12, r12, r11
	stw		r12, KDP.LA_ECB(r1)


	add		r12, r8, r11			;	PA_EmulatorData + ECBOffset
	stw		r12, KDP.PA_ECB(r1)
	stw		r12, EWA.PA_ContextBlock(r1)


	;	Place init vals for rupt masks from ConfigInfo in KDP.
	lwz		r12, NKConfigurationInfo.TestIntMaskInit(r3)
	stw		r12, KDP.TestIntMaskInit(r1)
	lwz		r12, NKConfigurationInfo.ClearIntMaskInit(r3)
	stw		r12, KDP.ClearIntMaskInit(r1)
	lwz		r12, NKConfigurationInfo.PostIntMaskInit(r3)
	stw		r12, KDP.PostIntMaskInit(r1)


	;	Place "PA_EmulatorIplValue" from ConfigInfo in KDP.
	lwz		r12, NKConfigurationInfo.IplValueOffset(r3)
	add		r12, r8, r12
	stw		r12, KDP.PA_EmulatorIplValue(r1)


	;	Copy this value from ConfigInfo to KDP *again* (see above).
	;	But this time, add 0x7c to get 0x408201DC.
	lwz		r12, NKConfigurationInfo.SharedMemoryAddr(r3)
	addi	r12, r12, 0x7c
	stw		r12, KDP.SharedMemoryAddrPlus(r1)


	;	Place PageAttributeInit from ConfigInfo in KDP.
	lwz		r12, NKConfigurationInfo.PageAttributeInit(r3)
	stw		r12, KDP.PageAttributeInit(r1)


	;	Make space at KDP + 0x920 for PageMap,
	;	according to ConfigInfo.PageMapInitSize.
	;	0x1b8 might be a typical value
	addi	r13, r1, KDP.PageMap
	lwz		r12, NKConfigurationInfo.PageMapInitSize(r3)
	stw		r13, KDP.PA_PageMapStart(r1)
	add		r13, r13, r12
	stw		r13, KDP.PA_PageMapEnd(r1)


	;	Zero out a word in KDP a bit below &PA_PageMap.
	;	Only NewWorld and Unknown PIHes touch this.
	stw		r0, KDP.ZeroWord(r1)



;	The InfoRecord contains metadata about the Power Mac structures
;	described in PPCInfoRecordsPriv.

;	It lives in the top 64b of the InfoRecord (nee Interrupt Response) Page,
;	which on PCI machines is mapped to 5fffe000 (just under 1.5GB). Here we
;	populate it at the top of our KDP, and later we copy it to our IRP.

	;	Logical self-pointer to the copy of InfoRecord in KDP
	;	(Will this be altered when the InfoRecord is copied to IRP?)
	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, KDP.InfoRecord
	stw		r12, KDP.InfoRecord + InfoRecord.InfoRecordPtr(r1)


	;	Constant
	stw		r0, KDP.InfoRecord + InfoRecord.Zero(r1)


	;	NKProcessorState (created by kernel, lives in PSA)

	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, PSA.ProcessorState
	stw		r12, KDP.InfoRecord + InfoRecord.NKProcessorStatePtr(r1)

	li		r12, 0x0100
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorStateVer(r1)

	li		r12, 128
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorStateLen(r1)


	;	NKHWInfo (created by bootloader, copied to IRP)

	lwz		r11, NKConfigurationInfo.LA_InfoRecord(r3)
	addi	r12, r11, IRP.HWInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKHWInfoPtr(r1)

	li		r12, 0x0108
	sth		r12, KDP.InfoRecord + InfoRecord.NKHWInfoVer(r1)

	li		r12, 192
	sth		r12, KDP.InfoRecord + InfoRecord.NKHWInfoLen(r1)


	;	NKProcessorInfo (created by bootloader, copied to KDP)

	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, KDP.ProcessorInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr(r1)

	li		r12, 0x0112
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer(r1)

	li		r12, 160
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen(r1)


	;	NKNanoKernelInfo (created by kernel, lives in KDP)

	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, KDP.NanoKernelInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoPtr(r1)

	li		r12, kNanoKernelVersion
	sth		r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoVer(r1)

	li		r12, 352
	sth		r12, KDP.InfoRecord + InfoRecord.NKNanoKernelInfoLen(r1)


	;	NKDiagInfo (created by bootloader, copied to PSA)

	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, PSA.DiagInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKDiagInfoPtr(r1)

	li		r12, 0x0100
	sth		r12, KDP.InfoRecord + InfoRecord.NKDiagInfoVer(r1)

	li		r12, 256
	sth		r12, KDP.InfoRecord + InfoRecord.NKDiagInfoLen(r1)


	;	NKSystemInfo (created by bootloader, copied to IRP)

	lwz		r11, NKConfigurationInfo.LA_InfoRecord(r3)
	addi	r12, r11, IRP.SystemInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKSystemInfoPtr(r1)

	li		r12, 0x0107
	sth		r12, KDP.InfoRecord + InfoRecord.NKSystemInfoVer(r1)

	li		r12, 320
	sth		r12, KDP.InfoRecord + InfoRecord.NKSystemInfoLen(r1)


	;	NKProcessorInfo... again!

	lwz		r11, NKConfigurationInfo.LA_KernelData(r3)
	addi	r12, r11, KDP.ProcessorInfo
	stw		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoPtr2(r1)

	li		r12, 0x0112
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoVer2(r1)

	li		r12, 160
	sth		r12, KDP.InfoRecord + InfoRecord.NKProcessorInfoLen2(r1)



;	Populate emulator data page (EDP).

	;	Copy 16-byte BootstrapVersion string from ConfigInfo
	lwz		r11, NKConfigurationInfo.BootVersionOffset(r3)
	lwz		r12, NKConfigurationInfo.BootstrapVersion(r3)
	stwux r12, r11, r8
	lwz		r12, NKConfigurationInfo.BootstrapVersion + 4(r3)
	stw		r12, 4(r11)
	lwz		r12, NKConfigurationInfo.BootstrapVersion + 8(r3)
	stw		r12, 8(r11)
	lwz		r12, NKConfigurationInfo.BootstrapVersion + 12(r3)
	stw		r12, 12(r11)


	;	Place logical pointer to emulator entry point in ContextBlock.
	;	Leave pointer to ECB in r11.
	lwz		r12, NKConfigurationInfo.LA_EmulatorCode(r3)
	lwz		r11, NKConfigurationInfo.EmulatorEntryOffset(r3)
	add		r12, r11, r12
	lwz		r11, NKConfigurationInfo.ECBOffset(r3)
	add		r11, r11, r8
	stw		r12, ContextBlock.LA_EmulatorEntry(r11)


	;	Place LA_EmulatorData from ConfigInfo in ContextBlock.
	lwz		r12, NKConfigurationInfo.LA_EmulatorData(r3)
	stw		r12, ContextBlock.LA_EmulatorData(r11)


	;	Place LA_DispatchTable from ConfigInfo in ContextBlock.
	lwz		r12, NKConfigurationInfo.LA_DispatchTable(r3)
	stw		r12, ContextBlock.LA_DispatchTable(r11)


	;	Place LA_EmulatorKernelTrapTable from KDP in ContextBlock.
	lwz		r12, KDP.LA_EmulatorKernelTrapTable(r1)
	stw		r12, ContextBlock.LA_EmulatorKernelTrapTable(r11)



;	Initialize MacOS LowMem globals at PA_RelocatedLowMemInit

	;	Zero out 8k
	lwz		r10, KDP.PA_RelocatedLowMemInit(r1)
	li		r9, 0x2000
@LowMem_zeroloop
	addic.	r9, r9, -4
	stwx		r0, r10, r9
	bne		@LowMem_zeroloop


	;	Populate from LowMemInit "key-value" table.
	lwz		r11, NKConfigurationInfo.MacLowMemInitOffset(r3)
	lwz		r10, KDP.PA_RelocatedLowMemInit(r1)

	lwzux	r9, r11, r3			;	get first word and point r11 at it
@LowMem_setloop
	mr.		r9, r9
	beq		@LowMem_done
	lwzu	r12, 4(r11)
	stwx	r12, r10, r9
	lwzu		r9, 4(r11)
	b		@LowMem_setloop
@LowMem_done



;	We expect a 'Hnfo' signature (from Trampoline) in HWInfo.
;
;	If HWInfo IS signed, great -- we can move on with the init process,
;	and skip all the nasty cache-probing, table-consulting madness that
;	follows. Just ignore the rest of this file.
;
;	But if HWInfo is unsigned, then this is going to hurt.

	lwz		r11, EWA.PA_IRP(r1)
	lwz		r11, IRP.HWInfo + NKHWInfo.Signature(r11)
	lisori	r12, 'Hnfo'
	cmplw	r12, r11
	beq		FinishInitBuiltin



;	Darn. All right, see if we can copy ProcessorInfo from
;	ProcessorInfoTable.s

	mfpvr	r12
	stw		r12, KDP.ProcessorInfo + NKProcessorInfo.ProcessorVersionReg(r1)
	srwi	r12, r12, 16
	lwz		r11, KDP.PA_NanoKernelCode(r1)
	addi	r10, r1, KDP.ProcessorInfo + NKProcessorInfo.Ovr
	li		r9, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr

;	check for several (some unknown) pre-7410 CPUs, and load their info
	cmpwi	r12, 0x0001												; 601
	addi	r11, r11, ProcessorInfoTable - NKTop
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0003												; 603
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0004												; 604
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0006												; 603e
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0007												; 750FX
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0008												; 750
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x0009												; ???
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo
	cmpwi	r12, 0x000a												; ???
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x000c												; 7400
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo

	cmpwi	r12, 0x000d												; ???
	addi	r11, r11, NKProcessorInfo.OvrEnd - NKProcessorInfo.Ovr
	beq		OverrideProcessorInfo



;	Now things get crazy. Have barely touched this...

;	get base of page table (why?)
	mfsdr1	r22

;	r21 = SDR1 & 0xffff0000
	rlwinm	r21, r22,  0,  0, 15

;	r22 = (SDR1 << 16) & 0x007F0000
	rlwinm	r22, r22, 16,  9, 15
	addis	r22, r22,  0x01
	li		r15,  0x00
	li		r12,  0x1a
	mtctr	r12
	lwz		r12, -0x0020(r1)
	addi	r10, r12,  0xec0

new_world_0x60c
	lwz		r11, -0x0004(r10)
	lwzu	r12, -0x0008(r10)
	subf	r9, r12, r21
	cmplw	r9, r11
	bge		new_world_0x624
	mr		r11, r9

new_world_0x624
	cmplw	r11, r15
	ble		new_world_0x634
	mr		r13, r12
	mr		r15, r11

new_world_0x634
	bdnz	new_world_0x60c
	addi	r12, r22, -0x01
	neg		r11, r13
	and		r12, r11, r12
	add		r13, r13, r12
	subf	r15, r12, r15
	rlwinm	r15, r15,  0,  0, 21
	li		r11,  0x1000
	stw		r11,  0x0f30(r1)
	li		r11, -0x01
	li		r10,  0x400

new_world_0x660
	subic.	r10, r10, 4
	stwx	r11, r21, r10
	bne		new_world_0x660
	dcbz	0, r21

new_world_0x670
	addi	r10, r10,  0x01
	lbzx	r11, r21, r10
	cmpwi	r11,  0x00
	beq		new_world_0x670
	sth		r10,  0x0f3c(r1)
	sth		r10,  0x0f3e(r1)
	sth		r10,  0x0f46(r1)
	sth		r10,  0x0f48(r1)
	sth		r10,  0x0f4a(r1)
	lis		r12, -0x8000
	add		r11, r21, r22
	addi	r11, r11, -0xe6e
	addis	r10, r21,  0x01

new_world_0x6a4
	stwu	r11, -0x0004(r10)
	rlwimi	r12, r10, 29, 29, 31
	stwu	r12, -0x0004(r10)
	cmpw	r10, r21
	rlwinm	r9, r10,  9,  7, 19
	tlbie	r9
	bne		new_world_0x6a4
	sync	
	isync	
	lwz		r11,  0x064c(r1)
	li		r12, (copied_code_1_end - copied_code_1) / 4
	mtctr	r12
	add		r20, r21, r22
	addi	r11, r11, copied_code_1_end - NKTop

new_world_0x6dc
	lwzu	r12, -0x0004(r11)
	stwu	r12, -0x0004(r20)
	dcbst	0, r20
	sync	
	icbi	0, r20
	bdnz	new_world_0x6dc
	sync	
	isync	
	stw		r0,  0x0f34(r1)
	li		r17,  0x00
	li		r18,  0x200
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x720

new_world_0x714
	addi	r17, r17,  0x200
	cmplw	r17, r15
	bge		new_world_0x734

new_world_0x720
	mtlr	r20
	blrl	
	ble		new_world_0x714
	addi	r12, r17, -0x200
	stw		r12,  0x0f34(r1)

new_world_0x734
	li		r12,  0x01
	sth		r12,  0x0f4e(r1)
	lwz		r18,  0x0f34(r1)
	mr		r17, r18
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x75c

new_world_0x750
	add		r17, r17, r18
	cmplw	r17, r15
	bge		new_world_0x774

new_world_0x75c
	mtlr	r20
	blrl	
	ble		new_world_0x750
	subf	r17, r18, r17
	divwu	r12, r17, r18
	sth		r12,  0x0f4e(r1)

new_world_0x774
	lwz		r17,  0x0f34(r1)
	lhz		r18,  0x0f4e(r1)
	slwi	r17, r17,  1
	divwu	r18, r17, r18
	srwi	r19, r18,  1
	li		r14,  0x200
	add		r19, r19, r14
	li		r16, -0x01
	b		new_world_0x7ac

new_world_0x798
	lhz		r12,  0x0f4a(r1)
	cmplw	r14, r12
	ble		new_world_0x7bc
	srwi	r14, r14,  1
	subf	r19, r14, r19

new_world_0x7ac
	mtlr	r20
	blrl	
	ble		new_world_0x798
	slwi	r12, r14,  1

new_world_0x7bc
	sth		r12,  0x0f44(r1)
	mtsdr1	r21
	mr		r14, r13
	li		r13,  0xff0
	sth		r0,  0x0f50(r1)
	li		r17,  0x00
	lwz		r18,  0x0f30(r1)
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x7f4

new_world_0x7e4
	add		r17, r17, r18
	lis		r12,  0x3f
	cmplw	r17, r12
	bge		new_world_0x82c

new_world_0x7f4
	mtlr	r20
	mfmsr	r12
	ori		r12, r12,  0x10
	mtmsr	r12
	isync	
	blrl	
	mfmsr	r12
	rlwinm	r12, r12,  0, 28, 26
	mtmsr	r12
	isync	
	ble		new_world_0x7e4
	subf	r17, r18, r17
	divwu	r12, r17, r18
	sth		r12,  0x0f50(r1)

new_world_0x82c
	li		r12,  0x01
	sth		r12,  0x0f52(r1)
	li		r17,  0x00
	lis		r18,  0x40
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x858

new_world_0x848
	add		r17, r17, r18
	lis		r12,  0x200
	cmplw	r17, r12
	bge		new_world_0x890

new_world_0x858
	mtlr	r20
	mfmsr	r12
	ori		r12, r12,  0x10
	mtmsr	r12
	isync	
	blrl	
	mfmsr	r12
	rlwinm	r12, r12,  0, 28, 26
	mtmsr	r12
	isync	
	ble		new_world_0x848
	subf	r17, r18, r17
	divwu	r12, r17, r18
	sth		r12,  0x0f52(r1)

new_world_0x890
	mr		r13, r14
	addi	r12, r22, -0x01
	srwi	r12, r12, 16
	or		r12, r12, r21
	mtsdr1	r12
	lwz		r12,  0x0f34(r1)
	stw		r12,  0x0f38(r1)
	lhz		r12,  0x0f4e(r1)
	sth		r12,  0x0f4c(r1)
	lhz		r12,  0x0f44(r1)
	sth		r12,  0x0f42(r1)
	lis		r11,  0x3960
	stw		r11,  0x0000(r21)
	lis		r11,  0x4e80
	ori		r11, r11,  0x20
	stw		r11,  0x0004(r21)
	dcbst	0, r21
	sync	
	icbi	0, r21
	sync	
	isync	
	mtlr	r21
	blrl	
	li		r11,  0x01
	sth		r11,  0x0002(r21)
	sync	
	isync	
	mtlr	r21
	blrl	
	sth		r11,  0x0f40(r1)
	cmpwi	r11,  0x01
	beq		skip_cache_hackery_never
	lwz		r11,  0x064c(r1)
	li		r12, (copied_code_2_end - copied_code_2) / 4
	mtctr	r12
	add		r20, r21, r22
	addi	r11, r11, copied_code_2_end - NKTop

new_world_0x924
	lwzu	r12, -0x0004(r11)
	stwu	r12, -0x0004(r20)
	dcbst	0, r20
	sync	
	icbi	0, r20
	bdnz	new_world_0x924
	sync	
	isync	
	subf	r12, r21, r20
	mulli	r12, r12,  0x80
	cmplw	r12, r15
	bge		new_world_0x958
	mr		r15, r12

new_world_0x958
	add		r12, r13, r15
	mr		r11, r20
	lis		r10,  0x4e80
	ori		r10, r10,  0x20

new_world_0x968
	lwzu	r9, -0x0200(r12)
	stw		r10,  0x0000(r12)
	cmpw	r12, r13
	stwu	r9, -0x0004(r11)
	dcbst	0, r12
	sync	
	icbi	0, r12
	bne		new_world_0x968
	sync	
	isync	
	stw		r0,  0x0f38(r1)
	li		r17,  0x00
	li		r18,  0x200
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x9b4

new_world_0x9a8
	addi	r17, r17,  0x200
	cmplw	r17, r15
	bge		new_world_0x9c8

new_world_0x9b4
	mtlr	r20
	blrl	
	ble		new_world_0x9a8
	addi	r12, r17, -0x200
	stw		r12,  0x0f38(r1)

new_world_0x9c8
	li		r12,  0x01
	sth		r12,  0x0f4c(r1)
	lwz		r18,  0x0f38(r1)
	mr		r17, r18
	li		r19,  0x00
	li		r16, -0x01
	b		new_world_0x9f0

new_world_0x9e4
	add		r17, r17, r18
	cmplw	r17, r15
	bge		new_world_0xa08

new_world_0x9f0
	mtlr	r20
	blrl	
	ble		new_world_0x9e4
	subf	r17, r18, r17
	divwu	r12, r17, r18
	sth		r12,  0x0f4c(r1)

new_world_0xa08
	add		r12, r13, r15
	mr		r11, r20

new_world_0xa10
	lwzu	r9, -0x0004(r11)
	stwu	r9, -0x0200(r12)
	cmpw	r12, r13
	dcbst	0, r12
	sync	
	icbi	0, r12
	bne		new_world_0xa10
	sync	
	isync	
	lwz		r17,  0x0f38(r1)
	lhz		r18,  0x0f4c(r1)
	divwu	r18, r17, r18
	slwi	r17, r17,  1
	add		r12, r13, r17
	subi	r11, r21, 4

new_world_0xa4c
	subf	r12, r18, r12
	li		r14,  0x400

new_world_0xa54
	rlwinm.	r14, r14, 31,  0, 28
	lwzx	r9, r12, r14
	lis		r10,  0x4e80
	ori		r10, r10,  0x20
	stwx	r10, r12, r14
	stwu	r9,  0x0004(r11)
	dcbst	r12, r14
	sync	
	icbi	r12, r14
	addi	r14, r14,  0x04
	lwzx	r9, r12, r14
	lis		r10,  0x4bff
	ori		r10, r10,  0xfffc
	stwx	r10, r12, r14
	stwu	r9,  0x0004(r11)
	dcbst	r12, r14
	sync	
	icbi	r12, r14
	bne		new_world_0xa54
	cmpw	r12, r13
	bne		new_world_0xa4c
	sync	
	isync	
	mr		r19, r18
	slwi	r18, r18,  1
	li		r14,  0x200
	add		r19, r19, r14
	li		r16, -0x01
	b		new_world_0xadc

new_world_0xac8
	li		r12,  0x08
	cmplw	r14, r12
	ble		new_world_0xaec
	srwi	r14, r14,  1
	subf	r19, r14, r19

new_world_0xadc
	mtlr	r20
	blrl	
	ble		new_world_0xac8
	slwi	r12, r14,  1

new_world_0xaec
	sth		r12,  0x0f42(r1)
	srwi	r18, r18,  1
	add		r12, r13, r17
	subi	r11, r21, 4

new_world_0xafc
	subf	r12, r18, r12
	li		r14,  0x400

new_world_0xb04
	rlwinm.	r14, r14, 31,  0, 28
	lwzu	r9,  0x0004(r11)
	stwx	r9, r12, r14
	addi	r14, r14,  0x04
	lwzu	r9,  0x0004(r11)
	stwx	r9, r12, r14
	bne		new_world_0xb04
	cmpw	r12, r13
	bne		new_world_0xafc

skip_cache_hackery_never
	;	Clearly can't just fall through
	b		FinishInitBuiltin


;	                     copied_code_1                      

copied_code_1	;	OUTSIDE REFERER
	li		r10,  0x03

copied_code_1_0x4
	li		r12,  0x800
	mtctr	r12
	add		r19, r19, r13
	li		r11,  0x00
	mtdec	r11

copied_code_1_0x18
	subf	r12, r17, r11
	srawi	r12, r12, 31
	and		r11, r11, r12
	lbzx	r12, r13, r11
	add		r12, r12, r12
	lbzx	r12, r19, r11
	add		r12, r12, r12
	add		r11, r11, r18
	bdnz	copied_code_1_0x18
	subf	r19, r13, r19
	mfdec	r12
	neg		r12, r12
	cmplw	r12, r16
	bgt		copied_code_1_0x54
	mr		r16, r12

copied_code_1_0x54
	srwi	r11, r12,  7
	subf	r12, r11, r12
	cmpw	r12, r16
	blelr	
	addic.	r10, r10, -0x01
	bgt		copied_code_1_0x4
	cmpw	r12, r16
	blr		
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
copied_code_1_end	;	OUTSIDE REFERER



;	                     copied_code_2                      

copied_code_2	;	OUTSIDE REFERER
	li		r10,  0x03
	mflr	r9

copied_code_2_0x8
	li		r12,  0x800
	mtctr	r12
	add		r19, r19, r13
	li		r11,  0x00
	mtdec	r11

copied_code_2_0x1c
	subf	r12, r17, r11
	srawi	r12, r12, 31
	and		r11, r11, r12
	add		r12, r13, r11
	mtlr	r12
	blrl	
	add		r12, r19, r11
	mtlr	r12
	blrl	
	add		r11, r11, r18
	bdnz	copied_code_2_0x1c
	subf	r19, r13, r19
	mfdec	r12
	neg		r12, r12
	cmplw	r12, r16
	bgt		copied_code_2_0x60
	mr		r16, r12

copied_code_2_0x60
	srwi	r11, r12,  7
	subf	r12, r11, r12
	cmpw	r12, r16
	mtlr	r9
	blelr	
	addic.	r10, r10, -0x01
	bgt		copied_code_2_0x8
	cmpw	r12, r16
	blr		
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
	isync
copied_code_2_end	;	OUTSIDE REFERER
