asm {
// $LK,"::/Doc/MemoryOverview.DD"$

USE32
SYS_INIT_PAGE_TABLES::
//Check 1Gig page capability and set page size.
				MOV 		EAX, 0x80000001
				CPUID
				MOV 		EAX, 1 << 21
				BT			EDX, 26
				JNC 		@@05
				MOV 		EAX, 1 << 30
@@05:			MOV 		U32 [MEM_PAGE_SIZE], EAX

//Set mapped space limit
				MOV 		EAX, [MEM_PHYSICAL_SPACE]
				MOV 		EDX, [MEM_PHYSICAL_SPACE + 4]
				BT			U32 [MEM_PAGE_SIZE], 30 //Round-up to 1Gig boundary?
				JNC 		@@10
				ADD 		EAX, 0x3FFFFFFF
				ADC 		EDX, 0
				AND 		EAX, ~0x3FFFFFFF
@@10:			INC 		EDX 		//Need 4Gig extra for uncached alias up at top of space.
				MOV 		[MEM_MAPPED_SPACE],     EAX
				MOV 		[MEM_MAPPED_SPACE + 4], EDX

//How many 2Meg pages?
				MOV 		CL,  21
				ADD 		EAX, 0x1FFFFF
				ADC 		EDX, 0
				SHRD		EAX, EDX
				SHR 		EDX, CL
				MOV 		[MEM_2MEG_NUM],     EAX
				MOV 		[MEM_2MEG_NUM + 4], EDX

//How many 1Gig pages?
				MOV 		CL,  9
				ADD 		EAX, 0x1FF
				ADC 		EDX, 0
				SHRD		EAX, EDX
				SHR 		EDX, CL
				MOV 		[MEM_1GIG_NUM],     EAX
				MOV 		[MEM_1GIG_NUM + 4], EDX

//How many 512Gig pages?
				MOV 		CL,  9
				ADD 		EAX, 0x1FF
				ADC 		EDX, 0
				SHRD		EAX, EDX
				SHR 		EDX, CL
				MOV 		[MEM_512GIG_NUM],     EAX
				MOV 		[MEM_512GIG_NUM + 4], EDX

//Set $LK,"CSysFixedArea",A="MN:CSysFixedArea"$ to zero
				MOV 		EDI, SYS_FIXED_AREA
				XOR 		EAX, EAX
				MOV 		ECX, sizeof(CSysFixedArea) / 4
				REP_STOSD

				MOV 		U32 [MEM_PML2], EDI
//Check for 1Gig page capability.
				BT			U32 [MEM_PAGE_SIZE], 30
				JC			@@15
//Find PML2 Size
				MOV 		EAX, U32 [MEM_2MEG_NUM]
				ADD 		EAX, 0x1FF
				AND 		EAX, ~0x1FF
				SHL 		EAX, 3
				ADD 		EDI, EAX

//Find PML3 Size
@@15:			MOV 		U32 [MEM_PML3], EDI
				MOV 		EAX, U32 [MEM_1GIG_NUM]
				ADD 		EAX, 0x1FF
				AND 		EAX, ~0x1FF
				SHL 		EAX, 3
				ADD 		EDI, EAX

//Find PML4 Size
				MOV 		U32 [MEM_PML4], EDI
				MOV 		EAX, U32 [MEM_512GIG_NUM]
				ADD 		EAX, 0x1FF
				AND 		EAX, ~0x1FF
				SHL 		EAX, 3
				ADD 		EAX, EDI

				MOV 		U32 [MEM_HEAP_BASE], EAX

//Set page tables to zero
				MOV 		EDI, U32 [MEM_PML2]
				SUB 		EAX, EDI
				MOV 		ECX, EAX
				SHR 		ECX, 2
				XOR 		EAX, EAX
				REP_STOSD

//Check for 1Gig page capability.
				BT			U32 [MEM_PAGE_SIZE], 30
				JC			@@30

//PML2: Use 2Meg Pages
				MOV 		EAX, 0x87 //bit 7 is page size (2Meg)
				XOR 		EDX, EDX
				MOV 		EDI, [MEM_PML2]
				MOV 		ECX, [MEM_2MEG_NUM]
@@20:			MOV 		U32 [EDI], EAX
				ADD 		EDI, 4
				MOV 		U32 [EDI], EDX
				ADD 		EDI, 4
				ADD 		EAX, 0x200000
				ADC 		EDX, 0
				LOOP		@@20
//PML3: Use 2Meg Pages
				MOV 		EAX, [MEM_PML2]
				OR			EAX, 7
				XOR 		EDX, EDX
				MOV 		EDI, [MEM_PML3]
				MOV 		ECX, [MEM_1GIG_NUM]
@@25:			MOV 		U32 [EDI], EAX
				ADD 		EDI, 4
				MOV 		U32 [EDI], EDX
				ADD 		EDI, 4
				ADD 		EAX, 0x1000
				ADC 		EDX, 0
				LOOP		@@25
				JMP 		@@40

//PML3: Use 1Gig Pages
@@30:			MOV 		EAX, 0x87 //bit 7 is page size (1Gig)
				XOR 		EDX, EDX
				MOV 		EDI, [MEM_PML3]
				MOV 		ECX, [MEM_1GIG_NUM]
@@35:			MOV 		U32 [EDI], EAX
				ADD 		EDI, 4
				MOV 		U32 [EDI], EDX
				ADD 		EDI, 4
				ADD 		EAX, 0x40000000
				ADC 		EDX, 0
				LOOP		@@35

//PML4
@@40:			MOV 		EAX, [MEM_PML3]
				OR			EAX, 7
				XOR 		EDX, EDX
				MOV 		EDI, [MEM_PML4]
				MOV 		ECX, [MEM_512GIG_NUM]
@@45:			MOV 		U32 [EDI], EAX
				ADD 		EDI, 4
				MOV 		U32 [EDI], EDX
				ADD 		EDI, 4
				ADD 		EAX, 0x1000
				ADC 		EDX, 0
				LOOP		@@45
				RET

SYS_INIT_16MEG_SYS_CODE_BP::
// Init sys_code_bp to BIOS E801 lowest 16Meg val.
// $LK,"BlkPoolsInit",A="MN:BlkPoolsInit"$() adds the rest.
				MOV 		U32 [SYS_CODE_BP],     SYS_FIXED_AREA + CSysFixedArea.sys_code_bp
				MOV 		U32 [SYS_CODE_BP + 4], 0

				MOV 		U32 [SYS_DATA_BP],     0
				MOV 		U32 [SYS_DATA_BP + 4], 0

				XOR 		EAX, EAX
				MOV 		AX,  U16 [MEM_E801] //1 Kb blks between 1M and 16M
				SHL 		EAX, 10
				ADD 		EAX, 0x100000
				MOV 		EDI, U32 [MEM_HEAP_BASE]
				SUB 		EAX, EDI

//EDI=BASE EAX=SIZE
				TEST		U8 [SYS_MEM_INIT_FLAG], 1
				JZ			@@05
				PUSH		EAX
				PUSH		EDI
				MOV 		ECX, EAX
				MOV 		AL,  U8 [SYS_MEM_INIT_VAL]
				REP_STOSB
				POP 		EDI
				POP 		EAX

@@05:			SHR 		EAX, MEM_PAG_BITS
				MOV 		ESI, SYS_FIXED_AREA + CSysFixedArea.sys_code_bp
				MOV 		EBX, U32 CBlkPool.mem_free_list[ESI]
				MOV 		U32 CMemBlk.next     [EDI], EBX
				MOV 		U32 CMemBlk.next + 4 [EDI], 0
				MOV 		U32 CBlkPool.mem_free_list     [ESI], EDI
				MOV 		U32 CBlkPool.mem_free_list + 4 [ESI], 0
				MOV 		U32 CMemBlk.mb_signature[EDI], MBS_UNUSED_SIGNATURE_VAL
				MOV 		U32 CMemBlk.pags[EDI], EAX
				SHL 		EAX, MEM_PAG_BITS
				ADD 		U32 CBlkPool.alloced_u8s[ESI], EAX

				BTS 		U32 [SYS_RUN_LEVEL], RLf_16MEG_SYS_CODE_BP
				RET
}

I64 *MemPageTable(U8 *a)
{//Point to page table entry for addr.
	if (Bt(&mem_page_size, 30))
		return *MEM_PML3(U64 *) + a >> 30 * 8;
	else
		return *MEM_PML2(U64 *) + a >> 21 * 8;
}
