*/beginfile PROCESSOR_asm
; --------------------------------------------------------------
; PROCESSOR_asm - QDOS processor specific routines
;	       - last modified 04/02/98
; QDOS-Amiga sources by Rainer Kowallik
;    ...latest changes by Mark J Swift
;    ...68040/68060 changes by SNG, 16/8/94
; --------------------------------------------------------------
;*/beginoverlay
; -------------------------------------------------------------
;    check attn flags for 68000/008 processor. Returns Z if so

CHK6800X:
	movem.l	d1/a6,-(a7)

	bsr	GET_ATTN
	btst	#0,d1

	movem.l	(a7)+,d1/a6
	rts

; -------------------------------------------------------------
;    set attn flags for processor.

SET_ATTN:
	movem.l	d0/a6,-(a7)

	move.l	a7,d1		; Calculate start of
	andi.w	#-$8000,d1	; system variables
	move.l	d1,a6

	bsr	ATTN_FLGS
	move.w	d0,d1
	move.w	d1,SV_IDENT+2(a6) ; set attn flags

	movem.l	(a7)+,d0/a6
	rts

; -------------------------------------------------------------
;    get attn flags for processor.

GET_ATTN:
	movem.l	d0/a6,-(a7)

	move.l	a7,d1		; Calculate start of
	andi.w	#-$8000,d1	; system variables
	move.l	d1,a6
	move.w	SV_IDENT+2(a6),d1 ; get attn flags

	movem.l	(a7)+,d0/a6
	rts

; -------------------------------------------------------------
;    create attention flags (check processor type)

;    bit 0 - at least 68010
;    bit 1 - at least 68020
;    bit 2 - at least 68030
;    bit 3 - at least 68040
;    bit 4 - at least 68881 (possibly 68882)
;    bit 5 - 68882 present (or emulation)
;    bit 6 - 68040 or 68060 on-chip FPU enabled
;    bit 7 - at least 68060
;
; Note: If the MC68060 FPU has been turned off in software since
; the last reset (which enables it) bit 6 is zero, as if the FPU
; was not present and we were using an EC or LC processor.
;
ATTN_FLGS:
	movem.l	d1/a0-a3,-(a7)

	dc.w	$2078,$0010	; move.l  $10.w,a0
	dc.w	$2478,$002C	; move.l  $2C.w,a2

	lea	LF80C18(pc),a1
	dc.w	$21C9,$0010	; move.l  a1,$10.w
				; (ILLEGAL INSTRUCTION vector)
	dc.w	$21C9,$002C	; move.l  a1,$2C.w
				; (F-LINE EMULATION vector)

	move.l	a7,a1

	moveq	#$0,d0		; initialise attn flags
	move.b	#0,161(a6)	; ditto for QDOS

	dc.w	$4E7B,$0801	; movec	d0,vbr
	bset	#$0,d0		; vbr present - 68010 at least

;		      Clear Data cache
;		      | Freeze Data cache
;		      | |Enable Data cache (off)
;		      | ||    Clear Instruction cache
;		      | ||    |  Enable Instruction cache
;		      | ||    |  |
	move.l	#%0000101000001001,d1

	dc.w	$4E7B,$1002	; movec	d1,cacr
	dc.w	$4E7A,$1002	; movec	cacr,d1
	bset	#$1,d0		; cacr present - 68020 at least
	move.b	#$20,161(a6)	; store for QDOS

	btst	#$9,d1
	beq.s	LF80BB4		; no data cache - not a 68030

	bset	#$2,d0		; definitely a 68030
	move.b	#$30,161(a6)	; store for QDOS

LF80BB4:
	btst	#$0,d1
	bne.s	LF80BDC		; cacr present and (EI) bit
				; operative - not a 68040

	or.w	#$C,d0		; 68040 at least!
	move.b	#$40,161(a6)	; store for QDOS

	dc.w	$F4D8		; CINVA ic/dc - inavalidate caches

	moveq	#0,d1		; MMU off
	dc.w	$4E7B,$1003	; movec d1,TCR

; This code set up the TTR/ACU registers to stop data cacheing of memory
; in the first 16 Mb. This is not needed under Amiga Qdos as the cache is
; explicitly cleared when necessary after DMA - SNG

;	 move.l	 #$0000C000,d1	 ; Write Through to Chip memory

; However, enabling caching on first 16 megs causes problems with IDE
; hardware which is in this address range, so lets disable caching. If
; we want a better solution, think about using the MMU - MJS

	move.l	#$0000C040,d1	; Serialize 0-16 Mb
	dc.w	$4E7B,$1006	; movec d1,(006) DTT0

	move.l	#$00FFC000,d1	; ACU/TTU off
;	 dc.w	 $4E7B,$1007	 ; movec d1,(007)
	dc.w	$4E7B,$1004	; movec d1,(004)
	dc.w	$4E7B,$1005	; movec d1,(005)

	move.l	#$00FFC020,d1	; Copyback on all memory
	dc.w	$4E7B,$1007	; movec d1,(007) DTT1

	move.l	#$80008000,d1	; Both caches on, for 040+
	bra.s	SetCACR

LF80BDC:
;		  Enable Instruction cache >=040 (1=ON)
;		  | Write Allocation (1=ON)
;		  | | Clear Data cache
;		  | | |	Enable Data cache (1=ON)
;		  | | |	|    Clear Instruction cache
;		  | | |	|    |  Enable Instruction cache
;		  | | |	|    |  |
	move.l	#%1010100100001001,d1

SetCACR	dc.w	$4E7B,$1002	; movec	   d1,cacr

	btst	#$3,d0
	beq.s	LF80BF6		; skip if not a 68040 or later
;
; 68060 initialisation added here
;
; Note this tests the new PCR register to find out if we're on
; an 060. If this fails, the routine returns after checking for
; a 68040 FPU. Otherwise it turns on the 060 accelerators and
; reports the presence of an enabled FPU, if it finds one.
;
	lea	NoPCR(pc),a3	; Continuation if PCR absent
	dc.w	$21CB,$0010	; move.l  a3,$10.w
				; (ILLEGAL INSTRUCTION vector)

	dc.w	$4E7A,$1808	; 68060 PCR to D1 or illegal
	swap	d1
	cmp.w	#$0431,d1
	beq.s	No60FPU		; No FPU!
;	cmp.w	#$0430,d1	; The only other possibility
;	bne.s	Unknown		; at the time of writing...
	btst	#17,d1		; Test swapped DFP flag bit
	bne.s	No60FPU		; If FPU is disabled, leave off

	bset	#6,d0		; Note 68060 FPU is available

	dc.w	$F37A,NULL-*	; FRESTORE NULL

No60FPU	bset	#7,d0		; Set 060 bit in ATTN flags
	move.b	#$60,161(a6)	; Tell Qdos we're on an 060
	swap	d1
	bset	#0,d1		; Ensure SOEP is on
	dc.w	$4E7B,$1808	; Store updated PCR
;
; Enable store buffer, code, data and (cleared) branch cache
;
	move.l	#$A0C08000,d1	; EDC+ESB+EBC+CABC+EIC
	dc.w	$4E7B,$1002	; movec	   d1,cacr
	bra.s	LF80C18
;
; The old code to check for the 040 FPU always failed because the
; 68040 does not support cpSAVE and cpRESTORE! Substitute FNOP
;
;	dc.w	$F327		; cpSAVE
;	dc.w	$F35F		; cpRESTORE

TryFPU:

	dc.w	$F37A,NULL-*	; FRESTORE NULL

	dc.w	$F280,0		; FNOP sifts out ECs and LCs


	bset	#$6,d0		; 68040 FPU present
	bra.s	LF80C18

NoPCR	movea.l	a1,a7		; Tidy stacked exception frame
	bra.s	TryFPU
;
; Test for an off-CPU co-processor
;
LF80BF6:
	dc.w	$F37A,NULL-*	; FRESTORE NULL

	moveq	#$0,d1

	dc.w	$F201,$9000	; FMOVE D1 to FPU
	dc.w	$F201,$B000	; FMOVE FPU to D1

	tst.l	d1		; A most unlikely case
	bne.s	LF80C18		; Something strange has happened

	bset	#$4,d0		; 68881 at least

	dc.w	$F327		; cpSAVE -(A7)

	cmpi.b	#$18,$1(a7)	; Check for 68882 frame
	beq.s	LF80C16

	bset	#$5,d0		; 68882 at least

LF80C16:
	dc.w	$F35F		; cpRESTORE (A7)+

LF80C18:
	move.l	a1,a7		; clean-up stack

	dc.w	$21C8,$0010	; move.l  a0,$10.w
	dc.w	$21CA,$002C	; move.l  a2,$2C.w

	movem.l	(a7)+,d1/a0-a3
	rts

NULL:
	DC.L	0,0,0,0

; -------------------------------------------------------------
;  clear data and instruction caches

CLRALL:
	movem.l	d0-d1/d4/a0,-(a7)
	movea.l	a7,a0
	trap	#0
	move.w	sr,-(a7)

	move.l	#$808,d1

; -------------------------------------------------------------
;  clear cache(s). d1=$800 - clear data cache
;		 d1=$808 - clear data and instruction caches

;		 and on 68040/060 - update memory from caches

L0000C3E:
	subq.l	#2,a0
	cmpa.l	a0,a7
	beq.s	CLRC00

	bclr	#5,0(a7) 	; User mode upon return

CLRC00:
	ori.w	#$0700,sr	; interrupts off

	exg	d1,d4
	bsr	GET_ATTN
	exg	d1,d4

	btst	#$1,d4		; exit if < '020
	beq.s	CLRCACHEX

L0000C48:
	btst	#$3,d4
	bne.s	L0000C68 	; '040 ?
;
; No explicit test for the 060 is needed as long as the 040
; bit remains set by tests on a 68060.
;
;	btst	#$7,d4		; Check for '060
;	bne.s	L0000C68

	and.l	#$808,d1
	ori	#$700,sr
	dc.w	$4E7A,$0002	; movec	cacr,d0
	or.l	d1,d0
	dc.w	$4E7B,$0002	; movec	d0,cacr

	bra.s	CLRCACHEX

L0000C68:
	btst	#$3,d1
	bne.s	L0000C74

	dc.w	$F478		; CPUSHA dc ('040 only)
				; update memory from cache
	bra.s	L0000C76

L0000C74:
	dc.w	$F4F8		; CPUSHA ic/dc ('040 only)
				; update memory from caches

	dc.w	$F478
	dc.w	$F498		; CINVA	ic ('040 only)
				; invalidate instruction cache
L0000C76:

CLRCACHEX:
	move.w	(a7)+,sr
	movem.l	(a7)+,d0-d1/d4/a0
	rts

;*/endoverlay
; --------------------------------------------------------------
;*/endfile
