;======================================================================
;
;	CacheCard V1.0
;	Copyright 1989 by Dave Haynie
;
;	68030 Assembly Function Module
;
;	This module contains MMU access functions.
;
;======================================================================

;======================================================================
;
;	Macros & constants used herein...
;
;======================================================================

CALLSYS macro   *
	jsr     LVO\1(A6)
	endm

AFB_68030	EQU	2

ATNFLGS		EQU	$129

LVOSupervisor	EQU	-30
LVOFindTask	EQU	-294

;======================================================================
;
;	Need just a little more stuff
;
;======================================================================

	NOLIST
	include "exec/execbase.i"
	include "exec/tasks.i"
	LIST

	machine mc68020
		mc68881
	cseg

;**********************************************************************
;
;	This section contains functions that identify and operate on
;	MMU things.  Unfortunately, there aren't any MMU op-codes in
;	the Manx assembler yet, so I have to fudge them here.
;
;**********************************************************************

	public _GetMMUType	; Returns the type of MMU
	public _GetCRP		; Gets MMU CRP register
	public _GetTC		; Gets MMU TC register

;======================================================================
;
;	This function returns 0L if the system contains no MMU, 
;	68851L if the system does contain an 68851, or 68030L if the
;	system contains a 68030.
;
;	This routine seems to lock up on at least some CSA 68020 
;	boards, though it runs just fine on those from Ronin and 
;	Commodore, as well as all 68030 boards it's been tested on.
;
;	ULONG GetMMUType()
;
;======================================================================

_GetMMUType:
	move.l	4,a6			; Get ExecBase
	movem.l	a3/a4/a5,-(sp)		; Save this stuff
	move.l	#0,a1	
	CALLSYS	FindTask		; Call FindTask(0L)
	move.l	d0,a3

	move.l	TC_TRAPCODE(a3),a4	; Change the exception vector
	move.l	#2$,TC_TRAPCODE(a3)
	
	move.l	#-1,d0			; Try to detect undecode FPU
	subq.l	#4,sp			; Let's try an MMU instruction
	dc.w	$f017			; Slimey PMOVE tc,(sp)
	dc.w	$4200
	cmpi	#0,d0			; Any MMU here?
	beq	1$
	cmpi	#-1,d0			; Hardware bugs?
	beq	1$
	btst.b	#AFB_68030,ATNFLGS(a6)	; Does the OS think an '030 is here?
	beq	1$
	move.l	#68030,d0

1$
	addq.l	#4,sp			; Return that local
	move.l	a4,TC_TRAPCODE(a3)	; Reset exception stuff
	movem.l	(sp)+,a3/a4/a5		; and return the registers
	rts

	; This is the exception code.  No matter what machine we're on,
	; we get an exception.  If the MMU's in place, we should get a
	; privilige violation; if not, an F-Line emulation exception.
2$
	move.l	(sp)+,d0		; Get Amiga supplied exception #
	cmpi	#11,d0			; Is it an F-Line?
	beq	3$			; If so, go to the fail routine
	move.l	#68851,d0		; We have MMU
	addq.l	#4,2(sp)		; Skip the MMU instruction
	rte
3$
	moveq.l	#0,d0			; It dinna woik,
	addq.l	#4,2(sp)		; Skip the MMU instruction
	rte

;======================================================================
;
;	This function returns the MMU CRP register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  Note that the
;	CRP register is two longwords long.
;
;	void GetCRP(ULONG *)
;
;======================================================================

_GetCRP:
	move.l	4(sp),a0		; Pointer to the CRP storage area
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	lea	2$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
2$
	dc.w	$f010			; PMOVE CRP,(a0)
	dc.w	$4e00
	rte

;======================================================================
;
;	This function returns the MMU TC register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  
;
;	ULONG GetTC()
;
;======================================================================

_GetTC:
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	subq.l	#4,sp			; Make a place to dump TC
	move.l	sp,a0
	lea	2$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp),d0			; Here's the result
	addq.l	#4,sp
	move.l	(sp)+,a5
	rts
2$
	dc.w	$f010			; PMOVE TC,(a0)
	dc.w	$4200
	rte

	end

