*======================================================================
*
*	FastROM 040 V1.0 by Greg Tibbs Rev a.01 1 Nov 91
*       From SetCpu V1.4
*	by Dave Haynie (released to the public domain)
*
*	68040 Assembly Function Module
*
*	This module contains functions that access functions in the 68040.
*
*======================================================================

*======================================================================
*
*	Macros & constants used herein...
*
*======================================================================


CALLSYS macro   *
	jsr     LVO\1(A6)
	endm


AFB_68040	EQU	3

ATNFLGS		EQU	$129

LVOSupervisor	EQU	-30

	cseg

	XDEF	_GetCPUType	* ID the CPU
	XDEF	_GetCACR	* Get 040 CACR register
	XDEF	_SetCACR	* Set 040 CACR register
	XDEF	_GetCRP		* Gets MMU URP register
        XDEF    _GetSRP		* Gets MMU SRP register
	XDEF	_SetCRP		* Sets MMU SRP & URP register
	XDEF	_GetTC		* Gets MMU TC register
	XDEF	_SetTC		* Gets MMU TC register
	XDEF    _DumpCache	* Dumps All 040 Caches
	XDEF    _GetDTT0	* Gets data translation reg 0
	XDEF    _GetDTT1	* Gets data translation reg 1
	XDEF	_GetITT0	* Gets instruction translation reg 0  
	XDEF	_GetITT1	* Gets instruction translation reg 1
	XDEF    _SetDTT0	* Save data translation reg 0
	XDEF    _SetDTT1	* Save data translation reg 1
	XDEF	_SetITT0	* Save instruction translation reg 0  
	XDEF	_SetITT1	* Save instruction translation reg 1
        XDEF    _GetVBR		* Get the Vector Base Register
        XDEF	_SetVBR		* Set the Vector Base Register
        XDEF    _GetMMUStatus   * Get MMU Status Register

*======================================================================
*
*	This function returns the type of the CPU in the system if it is
*	a 68040, 0 otherwise. Expects Exec to have 040 flag set (DOS 2.0+)
*
*	ULONG GetCPUType()
*
*======================================================================

_GetCPUType:
	movem.l	a4/a5,-(sp)		* Save this register
	move.l	4,a6			* Get ExecBase
	btst.b	#AFB_68040,ATNFLGS(a6)	* Does the OS think an '040 is here?
	beq	0$
	move.l	#68040,d0		* Sure does...
	movem.l	(sp)+,a4/a5
	rts

0$	move.l	#0,d0			* Not an '040
	movem.l	(sp)+,a4/a5
	rts

*======================================================================
*
*	This function returns the 68040 CACR register.  
*
*	ULONG GetCACR()
*
*======================================================================

_GetCACR:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	1$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
1$
*	movec	cacr,d0			* Make CACR the return value
        dc.w    $4e7a
        dc.w    $0002
	rte

*======================================================================
*
*	This function sets the value of the 68040 CACR register.  
*
*	void SetCACR(cacr)
*	ULONG cacr
*
*======================================================================

_SetCACR:
	move.l	4(sp),d0		* New CACR is on stack
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	2$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back register
	rts
2$
*	movec	d0,cacr			* Set the CACR
   	dc.w	$4e7b
	dc.w	$0002
	rte

*======================================================================
*
*	This function returns the MMU URP register.  It assumes a 68040 
*	Note that the CRP register is two longwords long. This code
*       assumes that the SRP and URP point to the same table.
*
*	ULONG GetCRP()
*
*======================================================================

_GetCRP:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	3$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
3$
	dc.w	$4E7A			* MOVEC URP,D0
	dc.w	$0806
	rte
*======================================================================
*
*	This function returns the MMU SRP register.  It assumes a 68040 
*	Note that the CRP register is two longwords long. This code
*       assumes that the SRP and URP point to the same table.
*
*	ULONG GetCRP()
*
*======================================================================

_GetSRP:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	3$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
3$
	dc.w	$4E7A			* MOVEC SRP,D0
	dc.w	$0807
	rte

*======================================================================
*
*	This function sets both the MMU SRP and URP registers.  It 
*	assumes a 68040 based system  Note that the 68030 CRP register is 
*	two longwords long but that the 040 SRP & URP are only one longword long.
*
*	void SetCRP(ULONG)
*
*======================================================================

_SetCRP:
	move.l	4(sp),d0		* Load URP data
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	4$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
4$
	dc.w	$4e7b			* MOVEC D0,URP
	dc.w	$0806
        dc.w    $4e7b			* MOVEC D0,SRP
        dc.w    $0807
	rte				

*======================================================================
*
*	This function returns the MMU TC register.  It assumes a 68040 
*	system.  
*
*	ULONG GetTC()
*
*======================================================================

_GetTC:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	5$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
5$
	dc.w	$4e7a			* 040 MOVEC TC,D0 
	dc.w	$0003
	rte

*======================================================================
*
*	This function sets the MMU TC register.  It assumes a 68040. 
*
*	void SetTC(ULONG)
*
*======================================================================

_SetTC:
	move.l	4(sp),d0		* Get address of our new TC value
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	6$,a5			* Get the start of the supervisor code
 	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
6$
	dc.w	$4e7b			* 040 MOVEC D0,TC 
	dc.w	$0003
	rte

*======================================================================
*
*	This function Dumps the Data, Instruction and Address Translation
*       Caches  It assumes a 68040 system. You should have all caches turned  
* 	off first before calling this function or they will refill before
*       you can reprogram the MMU!
*
*	void DumpCache()
*
*======================================================================

_DumpCache:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	6$,a5			* Get the start of the supervisor code
 	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
6$
	dc.w	$f518			* PFLUSHA (BC) - Invalidate ATC
        dc.w	$f4f8			* CPUSHA (BC) - Force Cache flush
	dc.w	$f4d8			* CINVA (BC) - Invalidate I & D Caches
	rte
*======================================================================
*
*	ULONG GetITT0()
*
*======================================================================

_GetITT0:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	7$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
7$
*	movec	itt0,d0			* Make ITT0 the return value
        dc.w    $4e7a
        dc.w    $0004
	rte

*======================================================================
*
*	ULONG GetITT1()
*
*======================================================================

_GetITT1:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	8$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
8$
*	movec	itt1,d0			* Make ITT1 the return value
        dc.w    $4e7a
        dc.w    $0005
	rte

*======================================================================
*
*	ULONG GetDTT0()
*
*======================================================================

_GetDTT0:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	9$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
9$
*	movec	dtt0,d0			* Make DTT0 the return value
        dc.w    $4e7a
        dc.w    $0006
	rte

*======================================================================
*
*	ULONG GetDTT1()
*
*======================================================================

_GetDTT1:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)		* Save this register
	lea	10$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
10$
*	movec	dtt1,d0			* Make DTT1 the return value
        dc.w    $4e7a
        dc.w    $0007
	rte

*======================================================================
*
*	void SetITT0(ULONG)
*
*======================================================================

_SetITT0:
	move.l	4(sp),d0		* Load ITT0 data
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	11$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
11$
	dc.w	$4e7b			* MOVEC D0,ITT0
	dc.w	$0004
	rte				

*======================================================================
*
*	void SetITT1(ULONG)
*
*======================================================================

_SetITT1:
	move.l	4(sp),d0		* Load ITT1 data
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	12$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
12$
	dc.w	$4e7b			* MOVEC D0,ITT1
	dc.w	$0005
	rte				

*======================================================================
*
*	void SetDTT0(ULONG)
*
*======================================================================

_SetDTT0:
	move.l	4(sp),d0		* Load DTT0 data
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	13$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
13$
	dc.w	$4e7b			* MOVEC D0,DTT0
	dc.w	$0006
	rte				

*======================================================================
*
*	void SetDTT1(ULONG)
*
*======================================================================

_SetDTT1:
	move.l	4(sp),d0		* Load DTT1 data
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	14$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		* Give back registers
	rts
14$
	dc.w	$4e7b			* MOVEC D0,DTT1
	dc.w	$0007
	rte				
*======================================================================
*
*	This function returns the VBR register.  It assumes > 68000 
*	system.  
*
*	ULONG GetTC()
*
*======================================================================

_GetVBR:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	15$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
15$
	dc.w	$4e7a			* 040 MOVEC VBR,D0 
	dc.w	$0801
	rte

*======================================================================
*
*	This function sets the VBR register.  It assumes > 68000. 
*
*	void SetTC(ULONG)
*
*======================================================================

_SetVBR:
	move.l	4(sp),d0		* Get address of our new TC value
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	16$,a5			* Get the start of the supervisor code
 	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
16$
	dc.w	$4e7b			* 040 MOVEC D0,VBR 
	dc.w	$0801
	rte
*======================================================================
*
*	This function returns the MMU TC register.  It assumes a 68040 
*	system.  
*
*	ULONG GetMMUStatus()
*
*======================================================================

_GetMMUStatus:
	move.l	4,a6			* Get ExecBase
	move.l	a5,-(sp)
	lea	17$,a5			* Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
17$
	dc.w	$4e7a			* 040 MOVEC MMUSR,D0 
	dc.w	$0805
	rte

        END
