
	INCLUDE	"MAC:sysmacs.i"

	STDOPT	;DEBUG
	INCEQUS	ALL

CALL	MACRO
	XREF	_LVO\1
	JSR	_LVO\1(A6)
	ENDM

MemHeader	EQUR	A2
HighMem		EQUR	D2
MemBase		EQUR	D3
VBRstore	EQUR	D4
LoMem		EQUR	D5
HiMem		EQUR	D6
Size		EQUR	D7

; Check if we live in kick 1.2 or higher.

	move.l	$4.w,A6
	cmp.w	#33,LIB_VERSION(A6)
	bls	KickTooOld

; Find the premier memlist entry, check if fast & set the highmem pointer.

	move.l	MemList(A6),MemHeader
	btst.b	#MEMB_FAST,MH_ATTRIBUTES+1(MemHeader)
	beq	NoFastMem
	move.l	MH_UPPER(MemHeader),HighMem
	add.l	#$8000,HighMem
	clr.w	HighMem

; Check if this is a 68010 or higher.

	btst.b	#AFB_68010,AttnFlags+1(A6)
	beq.s	DoNotChangeVBR

; Get the vector base register and check if it's already set.

	lea	GetVBR(PC),A5
	CALL	Supervisor
	tst.l	VBRstore
	bne.s	DoNotChangeVBR

; Allocate memory for the vector table

	move.l	#$400,D0
	bsr	AllocHighMem
	beq	NoFastMem
	move.l	D0,MemBase

; Copy the vector table.

	sub.l	A0,A0
	move.l	MemBase,A1
	move.l	#$400,D0
	CALL	CopyMemQuick

; Now change the vector base register.

	move.l	MemBase,VBRstore
	lea	SetVBR(PC),A5
	CALL	Supervisor
DoNotChangeVBR:

;
; ** The section below deals with moving the supervisor stack to fastmem **
;

; Check if system stack already moved

	move.l	SysStkLower(A6),LoMem
	cmp.l	MH_LOWER(MemHeader),LoMem
	blo.s	SysStackNotMovedYet
	cmp.l	HighMem,LoMem
	blo.s	Exit
SysStackNotMovedYet:

; Compute the size of the supervisor stack.

	move.l	SysStkUpper(A6),HiMem
	move.l	HiMem,Size
	sub.l	LoMem,Size

; Allocate memory for the new supervisor stack.

	move.l	Size,D0
	bsr.s	AllocHighMem
	beq.s	NoFastMem
	move.l	D0,MemBase

; Disable interrupts and copy the contents of the supervisor stack.

	CALL	Disable

	move.l	LoMem,A0
	move.l	MemBase,A1
	move.l	Size,D0
	CALL	CopyMem

; Fix up execbase

	move.l	MemBase,HiMem
	add.l	Size,HiMem

	move.l	MemBase,SysStkLower(A6)
	move.l	HiMem,SysStkUpper(A6)

; Fix supervisor stack pointer and re-enable interrupts.

	CALL	SuperState
	sub.l	LoMem,D0
	add.l	MemBase,D0
	CALL	UserState

; Recalculate checksum

	LEA	$22(a6),a0
	MOVEQ 	#$16,d0
	MOVEQ	#0,d1
sumloop:ADD.W	(a0)+,d1
	DBRA	d0,sumloop
	NOT.W	d1
	MOVE.W	d1,ChkSum(a6)

; Adjust memlist and free the old system stack, gives us 6K additional chip.

	cmp.w	#36,LIB_VERSION(A6)
	bhs.s	KickTooNew

	lea	MemList(A6),A0
FetchMextMemHeader:
	move.l	(A0),A0
	tst.l	(A0)
	beq.s	NoFreePossible
	cmp.l	MH_UPPER(A0),LoMem
	bne	FetchMextMemHeader
	add.l	Size,MH_UPPER(A0)

KickTooNew:
	move.l	LoMem,A1
	move.l	Size,D0
	CALL	FreeMem
NoFreePossible:

	CALL	Enable

; Done

Exit:
NoFastMem:
KickTooOld:
	MOVEQ	#0,D0
	RTS

; Subroutine section

; This func tries to allocate high memory at $A00000, $800000, $600000 or
; $400000. If it doesn't succeed, it will try to fetch any fast memory it
; can get its hands on.
; I : D0.L
;   : A6's gotta point to exec base.
; O : D0.L = Membase if succeeded. 0 if failed. Z=1 if failed.

AllocHighMem:
	move.l	D0,-(SP)
	sub.l	D0,HighMem

; Try to allocate at the end of the premier mem chunk.

	move.l	HighMem,A1
	CALL	AllocAbs
	tst.l	D0
	bne.s	AllocatedMem

; Try to fetch any fastmem.

	move.l	(SP),D0
	move.l	#MEMF_FAST,D1
	CALL	AllocMem
	tst.l	D0
AllocatedMem:
	addq.l	#4,SP
	rts

; These are the VBR get 'n set super-routines

GetVBR:
	DC.W	$4E7A,$4801		;  movec.l VBR,D4
	rte
SetVBR:
	DC.W	$4E7B,$4801		;  movec.l D4,VBR
	rte

	END
