*/beginfile PROCESSOR_asm
; --------------------------------------------------------------
; PROCESSOR_asm - QDOS processor specific routines
;	       - last modified 04/08/95
; 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
;
; 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	#$C040,d1	; Serialize 0-16 Mb
; moved: dc.w	$4E7B,$1006	; movec d1,(006)

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

	move.l	#$FFC000,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)
	dc.w	$4E7B,$1006	; movec d1,(006) - moved by SNG

	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

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	$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:
	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

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

CLRALL:
	movem.l	d0-d1/d4,-(a7)

	move.l	#$808,d1
	bra.s	L0000C3E

; -------------------------------------------------------------
;  clear data caches

CLRDATA:
	movem.l	d0-d1/d4,-(a7)

	moveq	#$8,d1
	rol.l	#8,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:
	move.w	sr,-(a7)
	ori.w	#$0700,sr	; interrupts off

	exg	d1,d4
	bsr	GET_ATTN
	exg	d1,d4

	btst	#$1,d4		; branch if '020 or more
	bne.s	L0000C48

	ifd	ShoCach
	move.l	d7,-(a7)
	move.w	#$8000,d7
WAITBLU:
	move.w	#$000F,$DFF180
	move.w	#0,$DFF180
	dbra	d7,WAITBLU
	move.l	(a7)+,d7
	endif

	bra.s	CLRCACHEX	; ...otherwise exit

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

	ifd	ShoCach
	move.l	d7,-(a7)
	move.w	#$8000,d7
WAITRED:
	move.w	#$0F00,$DFF180
	move.w	#0,$DFF180
	dbra	d7,WAITRED
	move.l	(a7)+,d7
	endif

	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
L0000C76:
	ifd	ShoCach
	move.l	d7,-(a7)
	move.w	#$8000,d7
WAITGRN:
	move.w	#$00F0,$DFF180
	move.w	#0,$DFF180
	dbra	d7,WAITGRN
	move.l	(a7)+,d7
	endif

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

	rts

; -------------------------------------------------------------
;  set bits in cacr d0=bits to set d1=bits to clear/alter
; This assumes 030 control register bits and tries to rework
; them for the 040. It fails, and won't suit 060 either. Luckily
; Mark says it is not used or needed in current Qdos versions.

	ifne	0		; Ignore this code block

L0000C8E:
	movem.l	d2-d4,-(a7)

	moveq	#$0,d3

	exg	d1,d4
	bsr	GET_ATTN
	exg	d1,d4

	btst	#$1,d4		; exit if not at least '020
	beq.s	L0000CAE

	and.l	d1,d0
	or.w	#$808,d0 	; signal always clear caches
	not.l	d1

L0000CB6:
	ori	#$700,sr ; DODGY? Not restored later
	dc.w	$4E7A,$2002	; movec	cacr,d2
	btst	#$3,d4
	beq.s	L0000CD0 	; skip if not '040
;
; Attempts to convert 040 CACR to 030 form;
;

	move.l	d2,d3
	andi.l	#$7FFF0000,d3	; keep '060 bits...

				; mimick ED & EI

	swap	d2		;		8000 8000
	ror.w	#8,d2		;		8000 0080
	rol.l	#1,d2		;		0000 0101
	andi.w	#$0101,d2	; ...only relevant bits

	move.w	d2,d3		; mimick DBE & IBE
	rol.w	#4,d3		;		0000 1010
	or.l	d3,d2		;		0000 1111

L0000CD0:
	move.l	d2,d3		; cache register to d3
	and.l	d1,d2		; mask off changed bits
	or.l	d0,d2		; or in set bits
	btst	#$3,d4
	beq.s	L0000CEC 	; skip if not '040

				;		0000 0101
	ror.l	#1,d2		;		8000 0080
	rol.w	#8,d2		;		8000 8000
	and.l	#$80008000,d2	;

	swap	d3
	or.w	d3,d2		; keep '060 bits...
	swap	d3
	swap	d2		;		8000 8000

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

L0000CEC:
	nop
	dc.w	$4E7B,$2002	; movec	d2,cacr
	nop

L0000CAE:
	move.l	d3,d0		; return old bits in d0

	movem.l	(a7)+,d2-d4
	rts

	endif			; End of commented out lump

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