;FPP.68K	DEC-16-86
;FLOATING POINT PACKAGE
;WRITTEN BY LOREN BLANEY FOR DFM ENGINEERING
;
;REVISION HISTORY:
;APR-02-86, ORIGINAL
;SEP-OCT-86, CONVERTED TO ASM68K CONVENTIONS, AND MODIFIED
;
;NOTES:
;In addition to Motorola's and National's documentation, see "Stride 400
; Series Owner's Manual", page 250.
;
;This floating point package uses the National 32081 chip to emulate
; the Motorola 68881 chip (as ridiculous as this may seem). This package
; only emulates those features required by the XPL compiler. For
; example, only double precision is used, only MOVE instructions may
; reference memory, and many of the 68881 opcodes and addressing modes
; are not implemented.
;
;Motorola's 80-bit registers correspond to pairs of National's 32-bit
; registers. Thus, all internal calculations are done to 64 bits of
; precision.
;
;		Motorola	National (low word, high word)
;		  FP0		 R0,R1
;		  FP1		 R2,R3
;		  FP2		 R4,R5
;		  FP3		 R6,R7
;		  FP4 *		 R0,R1
;		  FP5 *		 R2,R3
;		  FP6 *		 R4,R5
;		  FP7 *		 R6,R7
;
; * FP4 through FP7 are not used here and represent a pseudo-stack
; overflow. FP0 is used as scratch and to return values from functions.
;
;Most of the Motorola opcodes operate register-to-register and have the
; following format:
;
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 1   1   1   1 | 0   0   1   0 | 0   0   0   0 | 0   0   0   0 |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 0   0   0   S | S   S   D   D | D   X   X   X | X   X   X   X |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;
;The MOVE double precision from memory to register opcode has the format
;
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 1   1   1   1 | 0   0   1   0 | 0   0   M   M | M   A   A   A |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 0   1   0   1 | 0   1   D   D | D   0   0   0 | 0   0   0   0 |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;
;The MOVE double precision from register to memory opcode has the format
;
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 1   1   1   1 | 0   0   1   0 | 0   0   M   M | M   A   A   A |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | 0   1   1   1 | 0   1   S   S | S   0   0   0 | 0   0   0   0 |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;
;Where:
;	S = Source floating point register (FP0-FP7)
;	D = Destination floating point register (FP0-FP7)
;	X = Opcode type
;	M = Effective address mode
;	A = Effective address register
;
;
;
;All calculations are done using double precision, 64-bit, arithmetic,
; which is represented as follows:
;
;	63  62          52  51                                       0
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;      | S |Biased exponent|		      Mantissa		       |
;      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
;	 1	   11			         52
;
; S = Sign of the Mantissa (8 = positive)
; Biased exponent. The bias = 1023 (= $3FF), approximately = 1E308.
; Mantissa. There is an implied "1." in front of these mantissa bits.
;	52 bits gives 15.6 decimal digits of precision.
;
;Some examples of how decimal numbers are represented makes this clear:
;
;	Decimal		S	Exponent	    Mantissa
;
;	  1.0		0	  $3FF		$0 0000 0000 0000
;	  2.0		0	  $400		$0 0000 0000 0000
;	  1.5		0	  $3FF		$8 0000 0000 0000
;	  2.5		0	  $400		$4 0000 0000 0000
;	  3.0		0	  $400		$8 0000 0000 0000
;	   .75		0	  $3FE		$8 0000 0000 0000
;	  0.0		0	  $000		$0 0000 0000 0000
;	 -1.5		1	  $3FF		$8 0000 0000 0000
;	 -6.5		1	  $401		$A 0000 0000 0000
;	 10.0		0	  $402		$4 0000 0000 0000
;

	NOLIST
	INCLUDE	SYSPAG		;GET THE SYSTEM PAGE DEFINITIONS
	LIST

;NATIONAL'S 32081 FLOATING POINT UNIT (FPU) REGISTER ADDRESSES:
FPU1	EQU	$FFFFC010	;I/O PORT FOR OPERATION WORD & OPERANDS
FPU2	EQU	$FFFFC020	;INPUT PORT FOR PSR (STATUS REG WORD)
FPU3	EQU	$FFFFC030	;OUTPUT PORT FOR ID BYTE
FPUSTAT	EQU	$FFFFC041	;INPUT BIT 0 (TRUE HIGH)
				; = OPERATION COMPLETE
FPURSET	EQU	$FFFFC1C5	;OUTPUT BIT 1 (TRUE LOW)
				; = FPU HARDWARE RESET

	ORG	$2C		;POINT LINE "F" EMULATOR TO THIS ROUTINE
	DC.L	FLINE

	ORG	$20000

;;=======================================================================
;F-LINE EXCEPTION HANDLER
;
;If the 68000 tries to execute a floating point instruction (and there
; is no 68881 coprocessor) an F-line exception will occur which vectors
; to this routine.
;
;After the exception and register save (MOVEM.L), the stack looks like
; this:
;
; addresses increase
; going down  |
;	      |
;	      V
;		|		|
;		+-------+-------+
;		| D0 (hi)	|	<-- final SP
;		+-------+-------+
;		| D0 (lo)	|	2
;		+-------+-------+
;		| D1 (hi)	|	4
;		+-------+-------+
;		| D1 (lo)	|	6
;		+-------+-------+
;		| A6 (hi)	|	8
;		+-------+-------+
;		| A6 (lo)	|	10
;		+-------+-------+
;		| status reg	|	12
;		+-------+-------+
;		| ret addr (hi)	|	14
;		+-------+-------+
;		| ret addr (lo)	|	16
;		+-------+-------+
;initial SP --> |		|	18
;
;
;Initially, the return address on the stack points directly to the first
; word of the floating point instruction, the word that caused the
; F-line trap. In some places BRAs have been used in place of BSRs to
; make the stack offsets less confusing and to speed things up slightly.
;
TEMP	DS.L	2		;TEMPORARY SCRATCH FOR (SP)+ OPERATION

FLINE	MOVEM.L	D0/D1/A6,-(SP)	;SAVE REGISTERS

	MOVEA.L	14(SP),A6	;GET THE RETURN ADDRESS
	ADDQ.L	#2,A6		;POINT TO SECOND WORD OF INSTRUCTION
	MOVE.W	(A6)+,D0	;GET THE SECOND WORD AND POINT A6 TO
				; THE THIRD WORD
	MOVE.L	A6,14(SP)	;FIX THE RETURN ADDRESS TO SKIP THE
				; FIRST AND SECOND WORDS
	ORI	#$0700,SR	;32081 CHIP CANNOT BE INTERRUPTED
	BTST	#14,D0		;IS IT A MEMORY-REFERENCE INSTRUCTION?
	BEQ.S	FLINE40		;BRANCH IF NOT -- IT'S A CALCULATION

	BTST	#12,D0		;IS IT A FIX OR FLOAT INSTRUCTION?
				;I.E. IS THE SOURCE SPECIFIER (OR THE
				; DESTINATION FORMAT) LONG WORD?
	BNE.S	FLINE10		;BRANCH IF NOT

	BTST	#13,D0		;IS IT A FLOAT (MEMORY-TO-REGISTER)
	BNE.S	FLINE05		; INSTRUCTION?  BRANCH IF NOT
	BRA	FLOAT		;FMOVE.L D0,FP0

FLINE05	BRA	FIX		;FMOVE.L FP0,D0

;DISPATCH TO ROUTINE TO COMPUTE EFFECTIVE ADDRESS, WHICH IS PUT INTO A6
FLINE10	MOVE.W	-4(A6),D1	;GET FIRST WORD OF OPCODE
	ANDI.W	#$003F,D1	;MASK OFF THE EFFECTIVE ADDRESS BITS
	ADD.B	D1,D1		;TIMES 2 FOR WORD ENTRIES IN JUMP TABLE
	LEA	EATBL-@-2(PC),A6 ;GET THE ADDRESS OF THE JUMP TABLE
	MOVEA.W	0(A6,D1),A6	;GET THE RELATIVE ADDRESS OF THE ROUTINE
	JMP	EATBL-@-2(PC,A6) ;JUMP TO ROUTINE TO COMPUTE EFFECTIVE
				; ADDRESS
FLINE15	MOVEA.L	14(SP),A6	;GET "RETURN ADDR", WHICH POINTS TO
				; DISPLACEMENT
	ADD.W	(A6)+,D1	;ADD DISPLACEMENT (d) FROM OPCODE
	MOVE.L	A6,14(SP)	;ADJUST RETURN ADDRESS TO SKIP
	MOVEA.L	D1,A6		; DISPLACEMENT

FLINE20	ADDQ.L	#8,A6		;POINT A6 TO LAST MEMORY LOCATION +1

	BTST	#13,D0		;IS IT A MEMORY-TO-REGISTER OPCODE?
	BNE	MOVRM		;BRANCH IF NOT; MOVE REGISTER TO MEMORY
	BRA	MOVMR		;MOVE VALUE IN MEMORY INTO A REGISTER

FLINE40	MOVEQ	#0,D1		;CLEAR HIGH-ORDER BYTE FOR INDEX INSTR.
	MOVE.B	D0,D1		;SAVE FUNCTION CODE BITS IN D1

	LSR.W	#6,D0		;CONVERT MOTOROLA SOURCE AND DESTINATION
	ANDI.W	#$003E,D0	; BITS INTO NATIONAL "GEN" BITS
	LEA	GENTBL-@-2(PC),A6 ;GET ADDRESS OF TABLE
	MOVE.W	0(A6,D0),D0	;GET "GEN" BITS FROM TABLE

;DISPATCH TO ROUTINE TO HANDLE OPCODE
	ADD.B	D1,D1		;TIMES 2 FOR WORD ENTRIES 
	BPL.S	FLINE50		;BRANCH IF BIT 7 IS CLEAR
	JSR	VERROR		;EXTENSION CODES $40-$7F ARE UNUSED
	ASCII	'140 - ILLEGAL FLOATING INSTRUCTIO'
	DC.B	'N'+$80
	BRA.S	FLINE90		;EXIT

FLINE50	LEA	OPTBL-@-2(PC),A6 ;GET THE ADDRESS OF THE JUMP TABLE
	MOVEA.W	0(A6,D1),A6	;GET THE RELATIVE ADDRESS OF THE ROUTINE
	ADDA.L	#OPTBL,A6	;ADD "OPTBL" TO GET THE ABSOLUTE ADDRESS
								;??????
	JMP	(A6)		;JUMP TO ROUTINE TO HANDLE OPCODE

FLINE90	MOVEM.L	(SP)+,D0/D1/A6	;RESTORE REGISTERS
	RTE			;RETURN FROM F-LINE EXCEPTION

;----------------------------------------------------------------------
;TABLE TO DISPATCH TO EFFECTIVE ADDRESS ROUTINE
;
EATBL	DC.W	EA00 -EATBL	;%00	(% = OCTAL)
	DC.W	EA01 -EATBL	;%01
	DC.W	EA02 -EATBL	;%02
	DC.W	EA03 -EATBL	;%03
	DC.W	EA04 -EATBL	;%04
	DC.W	EA05 -EATBL	;%05
	DC.W	EA06 -EATBL	;%06
	DC.W	EA07 -EATBL	;%07

	DC.W	EA10 -EATBL	;%10
	DC.W	EA11 -EATBL	;%11
	DC.W	EA12 -EATBL	;%12
	DC.W	EA13 -EATBL	;%13
	DC.W	EA14 -EATBL	;%14
	DC.W	EA15 -EATBL	;%15
	DC.W	EA16 -EATBL	;%16
	DC.W	EA17 -EATBL	;%17

	DC.W	EA20 -EATBL	;%20
	DC.W	EA21 -EATBL	;%21
	DC.W	EA22 -EATBL	;%22
	DC.W	EA23 -EATBL	;%23
	DC.W	EA24 -EATBL	;%24
	DC.W	EA25 -EATBL	;%25
	DC.W	EA26 -EATBL	;%26
	DC.W	EA27 -EATBL	;%27

	DC.W	EA30 -EATBL	;%30
	DC.W	EA31 -EATBL	;%31
	DC.W	EA32 -EATBL	;%32
	DC.W	EA33 -EATBL	;%33
	DC.W	EA34 -EATBL	;%34
	DC.W	EA35 -EATBL	;%35
	DC.W	EA36 -EATBL	;%36
	DC.W	EA37 -EATBL	;%37

	DC.W	EA40 -EATBL	;%40
	DC.W	EA41 -EATBL	;%41
	DC.W	EA42 -EATBL	;%42
	DC.W	EA43 -EATBL	;%43
	DC.W	EA44 -EATBL	;%44
	DC.W	EA45 -EATBL	;%45
	DC.W	EA46 -EATBL	;%46
	DC.W	EA47 -EATBL	;%47

	DC.W	EA50 -EATBL	;%50
	DC.W	EA51 -EATBL	;%51
	DC.W	EA52 -EATBL	;%52
	DC.W	EA53 -EATBL	;%53
	DC.W	EA54 -EATBL	;%54
	DC.W	EA55 -EATBL	;%55
	DC.W	EA56 -EATBL	;%56
	DC.W	EA57 -EATBL	;%57

	DC.W	EA60 -EATBL	;%60
	DC.W	EA61 -EATBL	;%61
	DC.W	EA62 -EATBL	;%62
	DC.W	EA63 -EATBL	;%63
	DC.W	EA64 -EATBL	;%64
	DC.W	EA65 -EATBL	;%65
	DC.W	EA66 -EATBL	;%66
	DC.W	EA67 -EATBL	;%67

	DC.W	EA70 -EATBL	;%70
	DC.W	EA71 -EATBL	;%71
	DC.W	EA72 -EATBL	;%72
	DC.W	EA73 -EATBL	;%73
	DC.W	EA74 -EATBL	;%74
	DC.W	EA75 -EATBL	;%75
	DC.W	EA76 -EATBL	;%76
	DC.W	EA77 -EATBL	;%77

;-----------------------------------------------------------------------
;TABLE FOR CONVERTING MOTOROLA SOURCE AND DESTINATION REGISTER BITS INTO
; NATIONAL "GEN1" AND "GEN2" COMMAND WORDS.
;				SSS DDD	     GEN1 GEN2
GENTBL	DC.W	$0000		;0/4 0		0 0
	DC.W	$8000		;0/4 1		0 2
	DC.W	$0001		;0/4 2		0 4
	DC.W	$8001		;0/4 3		0 6
	DC.W	$0000		;0/4 4		0 0
	DC.W	$8000		;0/4 5		0 2
	DC.W	$0001		;0/4 6		0 4
	DC.W	$8001		;0/4 7		0 6

	DC.W	$0010		;1/5 0		2 0
	DC.W	$8010		;1/5 1		2 2
	DC.W	$0011		;1/5 2		2 4
	DC.W	$8011		;1/5 3		2 6
	DC.W	$0010		;1/5 4		2 0
	DC.W	$8010		;1/5 5		2 2
	DC.W	$0011		;1/5 6		2 4
	DC.W	$8011		;1/5 7		2 6

	DC.W	$0020		;2/6 0		4 0
	DC.W	$8020		;2/6 1		4 2
	DC.W	$0021		;2/6 2		4 4
	DC.W	$8021		;2/6 3		4 6
	DC.W	$0020		;2/6 4		4 0
	DC.W	$8020		;2/6 5		4 2
	DC.W	$0021		;2/6 6		4 4
	DC.W	$8021		;2/6 7		4 6

	DC.W	$0030		;3/7 0		6 0
	DC.W	$8030		;3/7 1		6 2
	DC.W	$0031		;3/7 2		6 4
	DC.W	$8031		;3/7 3		6 6
	DC.W	$0030		;3/7 4		6 0
	DC.W	$8030		;3/7 5		6 2
	DC.W	$0031		;3/7 6		6 4
	DC.W	$8031		;3/7 7		6 6

;-----------------------------------------------------------------------
;JUMP TABLE FOR MOTOROLA 68881 OPCODES:
;
OPTBL	DC.W	MOVE -OPTBL	;$00
	DC.W	INT -OPTBL	;$01
	DC.W	SINH -OPTBL	;$02
	DC.W	INTRZ -OPTBL	;$03
	DC.W	SQRT -OPTBL	;$04
	DC.W	BAD -OPTBL	;$05
	DC.W	LOGNP1 -OPTBL	;$06
	DC.W	BAD -OPTBL	;$07
	DC.W	ETOXM1 -OPTBL	;$08
	DC.W	TANH -OPTBL	;$09
	DC.W	ATAN -OPTBL	;$0A
	DC.W	BAD -OPTBL	;$0B
	DC.W	ASIN -OPTBL	;$0C
	DC.W	ATANH -OPTBL	;$0D
	DC.W	SIN -OPTBL	;$0E
	DC.W	TAN -OPTBL	;$0F

	DC.W	ETOX -OPTBL	;$10
	DC.W	TWOTOX -OPTBL	;$11
	DC.W	TENTOX -OPTBL	;$12
	DC.W	BAD -OPTBL	;$13
	DC.W	LOGN -OPTBL	;$14
	DC.W	LOG10 -OPTBL	;$15
	DC.W	LOG2 -OPTBL	;$16
	DC.W	BAD -OPTBL	;$17
	DC.W	ABS -OPTBL	;$18
	DC.W	COSH -OPTBL	;$19
	DC.W	NEG -OPTBL	;$1A
	DC.W	BAD -OPTBL	;$1B
	DC.W	ACOS -OPTBL	;$1C
	DC.W	COS -OPTBL	;$1D
	DC.W	GETEXP -OPTBL	;$1E
	DC.W	GETMAN -OPTBL	;$1F

	DC.W	DIV -OPTBL	;$20
	DC.W	MOD -OPTBL	;$21
	DC.W	ADD -OPTBL	;$22
	DC.W	MUL -OPTBL	;$23
	DC.W	SGLDIV -OPTBL	;$24
	DC.W	REM -OPTBL	;$25
	DC.W	SCALE -OPTBL	;$26
	DC.W	SGLMUL -OPTBL	;$27
	DC.W	SUB -OPTBL	;$28
	DC.W	BAD -OPTBL	;$29
	DC.W	BAD -OPTBL	;$2A
	DC.W	BAD -OPTBL	;$2B
	DC.W	BAD -OPTBL	;$2C
	DC.W	BAD -OPTBL	;$2D
	DC.W	BAD -OPTBL	;$2E
	DC.W	BAD -OPTBL	;$2F

	DC.W	SINCOS -OPTBL	;$30
	DC.W	SINCOS -OPTBL	;$31
	DC.W	SINCOS -OPTBL	;$32
	DC.W	SINCOS -OPTBL	;$33
	DC.W	SINCOS -OPTBL	;$34
	DC.W	SINCOS -OPTBL	;$35
	DC.W	SINCOS -OPTBL	;$36
	DC.W	SINCOS -OPTBL	;$37
	DC.W	CMP -OPTBL	;$38
	DC.W	BAD -OPTBL	;$39
	DC.W	TST -OPTBL	;$3A
	DC.W	BAD -OPTBL	;$3B
	DC.W	BAD -OPTBL	;$3C
	DC.W	BAD -OPTBL	;$3D
	DC.W	BAD -OPTBL	;$3E
	DC.W	BAD -OPTBL	;$3F

;=======================================================================
;EFFECTIVE ADDRESS = D0-D7
;
EA00
EA01
EA02
EA03
EA04
EA05
EA06
EA07	JSR	VERROR
	ASCII	'141 - UNIMPLEMENTED ADDR MODE, D'
	DC.B	'n'+$80
	BRA	FLINE90		;EXIT

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = A0-A7
;
EA10
EA11
EA12
EA13
EA14
EA15
EA16
EA17	JSR	VERROR
	ASCII	'142 - UNIMPLEMENTED ADDR MODE, A'
	DC.B	'n'+$80
	BRA	FLINE90		;EXIT

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = (An)
; RETURN EFFECTIVE ADDRESS IN A6
;
EA20	MOVEA.L	A0,A6
	BRA	FLINE20

EA21	MOVEA.L	A1,A6
	BRA	FLINE20

EA22	MOVEA.L	A2,A6
	BRA	FLINE20

EA23	MOVEA.L	A3,A6
	BRA	FLINE20

EA24	MOVEA.L	A4,A6
	BRA	FLINE20

EA25	MOVEA.L	A5,A6
	BRA	FLINE20

EA26	MOVEA.L	8(SP),A6	;GET A6 AS SAVED ON THE STACK
	BRA	FLINE20

EA27	LEA	18(SP),A6	;IF WE WERE IN SUPERVISOR MODE
	BRA	FLINE20		;ADJUST SP TO VALUE BEFORE THE EXCEPTION

;EA27	MOVE	USP,A6		;IF WE WERE IN USRE MODE
;	BRA	FLINE20

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = (An)+
; RETURN EFFECTIVE ADDRESS IN A6
; D1 MAY BE DESTROYED
;
EA30	MOVEA.L	A0,A6
	ADDQ.L	#8,A0
	BRA	FLINE20

EA31	MOVEA.L	A1,A6
	ADDQ.L	#8,A1
	BRA	FLINE20

EA32	MOVEA.L	A2,A6
	ADDQ.L	#8,A2
	BRA	FLINE20

EA33	MOVEA.L	A3,A6
	ADDQ.L	#8,A3
	BRA	FLINE20

EA34	MOVEA.L	A4,A6
	ADDQ.L	#8,A4
	BRA	FLINE20

EA35	MOVEA.L	A5,A6
	ADDQ.L	#8,A5
	BRA	FLINE20

EA36	MOVEA.L	8(SP),A6
	ADDQ.L	#8,8(SP)
	BRA	FLINE20

;This is a pull operation: We discard the real value that is on the
; stack just after this exception stuff. (A real mess.)
;WARNING: This assumes the exception occurred while in supervisor mode
EA37	MOVEM.L	18(SP),D1/A6	;GET THE REAL VALUE
	MOVE.L	14(SP),22(SP)	;MOVE THE EXCEPTION INFO AHEAD,
	MOVE.L	10(SP),18(SP)	; EFFECTIVELY PULLING THE REAL VALUE
	MOVE.L	6(SP),14(SP)
	MOVE.L	2(SP),10(SP)
	MOVE.W	(SP),8(SP)
	MOVEM.L	D1/A6,TEMP.L	;NEED TO PUT VALUE SOMEWHERE
	LEA	TEMP.L,A6	;POINT TO VALUE
	ADDQ.L	#8,SP		;ADJUST SP FOR PULL
	BRA	FLINE20

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = -(An)
; RETURN EFFECTIVE ADDRESS IN A6
; D1 MAY BE DESTROYED
;
EA40	SUBQ.L	#8,A0
	MOVEA.L	A0,A6
	BRA	FLINE20

EA41	SUBQ.L	#8,A1
	MOVEA.L	A1,A6
	BRA	FLINE20

EA42	SUBQ.L	#8,A2
	MOVEA.L	A2,A6
	BRA	FLINE20

EA43	SUBQ.L	#8,A3
	MOVEA.L	A3,A6
	BRA	FLINE20

EA44	SUBQ.L	#8,A4
	MOVEA.L	A4,A6
	BRA	FLINE20

EA45	SUBQ.L	#8,A5
	MOVEA.L	A5,A6
	BRA	FLINE20

EA46	SUBQ.L	#8,8(SP)
	MOVEA.L	8(SP),A6
	BRA	FLINE20

;This is a push operation: We must load a real value such that it will
; be at the top of the stack after the exception stuff goes away.
;WARNING: This assumes the exception occurred while in supervisor mode.
EA47	MOVEM.L	(SP),D1/A6	;MOVE THE EXCEPTION STUFF BACK 8 BYTES
	SUBQ.L	#8,SP
	MOVEM.L	D1/A6,(SP)
	MOVEM.L	16(SP),D1/A6
	MOVEM.L	D1/A6,8(SP)
	MOVE.W	24(SP),16(SP)
	LEA	18(SP),A6	;POINT TO THE HOLE IN THE STACK
	BRA	FLINE20

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = d(An)
; RETURN EFFECTIVE ADDRESS IN D1
;
EA50	MOVE.L	A0,D1
	BRA	FLINE15

EA51	MOVE.L	A1,D1
	BRA	FLINE15

EA52	MOVE.L	A2,D1
	BRA	FLINE15

EA53	MOVE.L	A3,D1
	BRA	FLINE15

EA54	MOVE.L	A4,D1
	BRA	FLINE15

EA55	MOVE.L	A5,D1
	BRA	FLINE15

EA56	MOVE.L	8(SP),D1	;GET A6 AS SAVED ON THE STACK
	BRA	FLINE15

EA57	MOVEQ	#18,D1		;IF WE WERE IN SUPERVISOR MODE
	ADD.L	SP,D1		;ADJUST SP TO VALUE BEFORE THE EXCEPTION
	BRA	FLINE15

;EA57	MOVE	USP,D1		;IF WE WERE IN USER MODE (WON'T WORK IN
; MOTOROLA'S "ORTHORGONAL" INSTRUCTION SET)
;	BRA	FLINE15

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = d(An,Xn)
;
EA60
EA61
EA62
EA63
EA64
EA65
EA66
EA67	JSR	VERROR
	ASCII	'145 - UNIMPLEMENTED ADDR MODE, d(An,Xn'
	DC.B	')'+$80
	BRA	FLINE90		;EXIT

;-----------------------------------------------------------------------
;EFFECTIVE ADDRESS = MISCELLANEA
;
EA70	MOVEA.L	14(SP),A6	;(xxx).W
	MOVE.W	(A6)+,D1	;GET EFFECTIVE ADDRESS INTO D1
	MOVE.L	A6,14(SP)	;ADJUST RETURN ADDRESS TO SKIP EXTENSION
	MOVEA.W	D1,A6		;RETURN SIGN EXTENDED <EA> IN A6
	BRA	FLINE20

EA71	MOVEA.L	14(SP),A6	;(xxx).L
	MOVE.L	(A6)+,D1	;GET EFFECTIVE ADDRESS INTO D1
	MOVE.L	A6,14(SP)	;ADJUST RETURN ADDRESS TO SKIP EXTENSION
	MOVEA.W	D1,A6		;RETURN <EA> IN A6
	BRA	FLINE20

EA74	MOVEA.L	14(SP),A6	;#<data>
	ADDQ.L	#8,A6		;POINT A6 TO END OF IMMEDIATE DATA (+1)
	MOVE.L	A6,14(SP)	;ADJUST RETURN ADDRESS TO SKIP EXTENSION
	BRA	MOVMR		;MOVE IMMEDIATE DATA INTO REGISTER

EA72				;d(PC)
EA73				;d(PC,Xn)
EA75
EA76
EA77	JSR	VERROR
	ASCII	'146 - UNIMPLEMENTED ADDR MOD'
	DC.B	'E'+$80
	BRA	FLINE90		;EXIT

;=======================================================================
;FLOAT INSTRUCTION
; FMOVE.L D0,FP0
; NOTE THAT THIS ONLY WORKS FOR THE REGISTERS D0 AND FP0 AS SHOW.
;
FLOAT	MOVE.W	#$003E,FPU3	;ID BYTE FOR FORMAT 9
	MOVE.W	#$0340,FPU1	;OPERATION WORD: GEN1 = "MEMORY",
				; GEN2 = R0, OP = MOVfi, i = D, f = L
				;NOTE: OPERATION WORDS ARE BYTE SWAPPED
	MOVE.W	2(SP),FPU1	;MOVE D0 INTO FPU1, LOW WORD FIRST
	MOVE.W	(SP),FPU1

FLOAT10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	FLOAT10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	FLOAT90
	JSR	VERROR
	ASCII	'121 - FLOAT (FMOVE.L D0,FP0'
	DC.B	')'+$80

FLOAT90	BRA	FLINE90

;-----------------------------------------------------------------------
;FIX INSTRUCTION
; FMOVE.L FP0,D0
; NOTE THAT THIS ONLY WORKS FOR THE REGISTERS INDICATED.
;
FIX	MOVE.W	#$003E,FPU3	;ID BYTE FOR FORMAT 9
	MOVE.W	#$2302,FPU1	;OPERATION WORD: GEN1 = R0, GEN2 =
				; "MEMORY", OP = ROUNDfi, i = D, f = L
				;NOTE: OPERATION WORDS ARE BYTE SWAPPED
FIX10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	FIX10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	FIX20
	JSR	VERROR
	ASCII	'121 - FIX (FMOVE.L FP0,D0'
	DC.B	')'+$80

FIX20	MOVE.W	FPU1,2(SP)	;MOVE RESULT INTO D0, LOW WORD FIRST
	MOVE.W	FPU1,(SP)
	BRA	FLINE90

;-----------------------------------------------------------------------
;DOUBLE PRECISION MOVE FROM MEMORY TO A FLOATING-POINT REGISTER
; FMOVE.D <ea>,FPn
; INPUTS: A6 - POINTS TO MEMORY LOCATION.
;	  D0 - SECOND WORD OF INSTRUCTION
; DESTROYS REGISTERS D0 AND A6.
;
MOVMR	MOVE.L	A5,-(SP)	;SAVE A5

	LSR.W	#6,D0		;D0 = DESTINATION REGISTER *2
	ANDI.W	#$0006,D0
	LEA	MOVMRTB.L,A5
	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	MOVE.W	0(A5,D0),FPU1	;LOAD OPERATION WORD FROM TABLE

	MOVE.W	-(A6),FPU1	;MOVE 4-WORD, DOUBLE-PRECISION VALUE
	MOVE.W	-(A6),FPU1	; STARTING WITH THE LEAST SIGNIFICANT
	MOVE.W	-(A6),FPU1	; WORD INTO FPU1
	MOVE.W	-(A6),FPU1

MOVMR10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	MOVMR10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	MOVMR90
	JSR	VERROR
	ASCII	'120 - FLOATING MOVE MEM TO RE'
	DC.B	'G'+$80

MOVMR90	MOVEA.L	(SP)+,A5
	BRA	FLINE90

;OPERATON WORD TABLE.  NOTE BYTE SWAPPED ORDER.
MOVMRTB	DC.W	$0440		;R0
	DC.W	$8440		;R2
	DC.W	$0441		;R4
	DC.W	$8441		;R6

;-----------------------------------------------------------------------
;DOUBLE PRECISION MOVE FROM A FLOATING-POINT REGISTER TO MEMORY
; FMOVE.D FPm,<ea>
; INPUTS: A6 - POINTS TO MEMORY LOCATION.
;	  D0 - SECOND WORD OF INSTRUCTION
; DESTROYS REGISTERS D0 AND A6
;
MOVRM	MOVE.L	A5,-(SP)	;SAVE A5

	LSR.W	#6,D0		;D0 = SOURCE REGISTER *2
	ANDI.W	#$0006,D0
	LEA	MOVRMTB.L,A5
	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	MOVE.W	0(A5,D0),FPU1	;LOAD OPERATION WORD FROM TABLE

MOVRM10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	MOVRM10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	MOVRM20
	JSR	VERROR
	ASCII	'121 - FLOATING MOVE REG TO ME'
	DC.B	'M'+$80

MOVRM20	MOVE.W	FPU1,-(A6)	;READ RESULT, LEAST SIGNIFICANT WORD 1ST
	MOVE.W	FPU1,-(A6)
	MOVE.W	FPU1,-(A6)
	MOVE.W	FPU1,-(A6)

	MOVEA.L	(SP)+,A5	;RESTORE A5
	BRA	FLINE90

;OPERATON WORD TABLE.  NOTE BYTE SWAPPED ORDER.
MOVRMTB	DC.W	$0402		;R0
	DC.W	$0412		;R2
	DC.W	$0422		;R4
	DC.W	$0432		;R6

;=======================================================================
;HANDLER FOR UNIMPLEMENTED OR ILLEGAL INSTRUCTIONS
;
BAD	JSR	VERROR
	ASCII	'130 - UNIMPLEMENTED FLOAT INSTRUCTIO'
	DC.B	'N'+$80
	RTS

;-----------------------------------------------------------------------
;$00
;DOUBLE PRECISION MOVE FROM REGISTER TO REGISTER
; FMOVE FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
MOVE	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$0400,D0	;OR IN "MOVE" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

MOV0R10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	MOV0R10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	MOV0R90
	JSR	VERROR
	ASCII	'122 - FLOATING MOVE TO RE'
	DC.B	'G'+$80

MOV0R90	BRA	FLINE90

;-----------------------------------------------------------------------
;$01
;INTEGER PART
; FINT FPn
;
INT	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$02
;HYPERBOLIC SINE
; FSINH FPn
;
SINH	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$03
;INTEGER PART, ROUND TO ZERO
; FINTRZ FPn
;
INTRZ	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$04
;SQUARE ROOT
; FSQRT FPn
;
SQRT	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$05
;LOG TO THE BASE E OF X PLUS 1.  LOGe(X+1)
; FLOGNP1 FPn
;
LOGNP1	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$08
;E TO THE X MINUS 1. e^x -1
; FETOXM1 FPn
;
ETOXM1	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$09
;HYPERBOLIC TANGENT
; FTANH FPn
;
TANH	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$0A
;ARC TANGENT
; FATAN FPn
;
ATAN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$0C
;ARC SINE
; FASIN FPn
;
ASIN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$0D
;HYPERBOLIC ARC TANGENT
; FATANH FPn
;
ATANH	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$0E
;SINE
; FSIN FPn
;
SIN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$0F
;TANGENT
; FTAN FPn
;
TAN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$10
;E TO THE X POWER. e^X
; FETOX FPn
;
ETOX	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$11
;2^X
; FTWOTOX FPn
;
TWOTOX	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$12
;10^X
; FTENTOX FPn
;
TENTOX	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$14
;NATURAL LOG. LOG TO THE BASE e
; FLOGN FPn
;
LOGN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$15
;LOG TO THE BASE 10. Log10
; FLOG10 FPn
;
LOG10	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$16
;LOG TO THE BASE 2. Log 2
; FLOG2 FPn
;
LOG2	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$18
;ABSOLUTE VALUE
; FABS FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
ABS	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$3400,D0	;OR IN "ABS" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

ABS10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	ABS10
;
	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	ABS90
	JSR	VERROR
	ASCII	'123 - FLOATING ABSOLUTE VALU'
	DC.B	'E'+$80
ABS90	BRA	FLINE90

;-----------------------------------------------------------------------
;$19
;HYPERBOLIC COSINE
; FCOSH FPn
;
COSH	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$1A
;NEGATE
; FNEG FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
NEG	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$1400,D0	;OR IN "NEG" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

NEG10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	NEG10
;
	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	NEG90
	JSR	VERROR
	ASCII	'124 - FLOATING NEGAT'
	DC.B	'E'+$80
NEG90	BRA	FLINE90

;-----------------------------------------------------------------------
;$1C
;ARC COSINE
; FACOS FPn
;
ACOS	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$1D
;COSINE
; FCOS FPn
;
COS	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$1E
;GET EXPONENT
; FGETEXP FPn
;
GETEXP	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$1F
;GET MANITSSA
; FGETMAN FPn
;
GETMAN	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$20
;DIVIDE
; FDIV FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
DIV	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$2000,D0	;OR IN "DIV" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

DIV10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	DIV10
;
	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	DIV90
	JSR	VERROR
	ASCII	'125 - FLOATING DIVID'
	DC.B	'E'+$80
DIV90	BRA	FLINE90

;-----------------------------------------------------------------------
;$21
;MODULO REMAINDER
; FMOD FPm,FPn
;
MOD	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$22
;ADD
; FADD FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
ADD	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
;	ORI.W	#$0000,D0	;OR IN "ADD" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

ADD10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	ADD10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	ADD90
	JSR	VERROR
	ASCII	'126 - FLOATING AD'
	DC.B	'D'+$80
ADD90	BRA	FLINE90

;-----------------------------------------------------------------------
;$23
;MULTIPLY
; FMUL FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
MUL	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$3000,D0	;OR IN "MUL" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

MUL10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	MUL10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	MUL90
	JSR	VERROR
	ASCII	'127 - FLOATING MULTIPL'
	DC.B	'Y'+$80
MUL90	BRA	FLINE90

;-----------------------------------------------------------------------
;$24
;SINGLE PRECISION DIVIDE
; FSGLDIV FPm,FPn
;
SGLDIV	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$25
;IEEE REMAINDER
; FREM FPm,FPn
;
REM	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$26
;SCALE EXPONENT
; FSCALE FPm,FPn
;
SCALE	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$27
;SINGLE PRECISION MULTIPLY
; FSGLMUL FPm,FPn
;
SGLMUL	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$28
;SUBTRACT
; FSUB FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
;
SUB	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$1000,D0	;OR IN "SUB" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

SUB10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	SUB10

	BTST	#0,FPU2		;READ STATUS WORD (MANDATORY)
	BEQ.S	SUB90
	JSR	VERROR
	ASCII	'128 - FLOATING SUBTRAC'
	DC.B	'T'+$80
SUB90	BRA	FLINE90

;-----------------------------------------------------------------------
;$30
;SIMUTANEOUS SINE AND COSINE
; FSINCOS FPm,FPc:FPs
;
SINCOS	BSR	BAD
	BRA	FLINE90

;-----------------------------------------------------------------------
;$38
;COMPARE FPn TO FPm 
; FCMP FPm,FPn
; INPUTS: D0 - "GEN" BITS
; DESTROYS REGISTER D0
; THIS IS A KLUDGE: THE 68881 DOES NOT ACTUALLY SET THE CONDITION CODES
; IN THE 68020.
;
CMP	MOVE.W	#$00BE,FPU3	;ID BYTE FOR FORMAT 11
	ORI.W	#$0800,D0	;OR IN "CMP" OPCODE (BYTE SWAPPED)
	MOVE.W	D0,FPU1		;LOAD OPERATION WORD

CMP10	BTST	#0,FPUSTAT	;WAIT FOR OPERATION COMPLETE
	BEQ.S	CMP10

	MOVE.W	FPU2,D0		;READ STATUS *WORD* (MANDATORY)
	BTST	#0,D0
	BRA.S	CMP20		;IGNORE ERROR CONDITION
;	BEQ.S	CMP20
	JSR	VERROR
	ASCII	'128 - FLOATING COMPAR'
	DC.B	'E'+$80

CMP20	ANDI.B	#$C0,D0		;GET STATUS BITS 7=N, 6=Z
	LSR.B	#4,D0		;SHIFT DOWN TO 3=N, 2=Z
	MOVE.B	D0,13(SP)	;PUT IN STATUS REGISTER (VIA STACK)
	BRA	FLINE90		;OTHER CONDITION BITS (X, V, C) ARE 0

;-----------------------------------------------------------------------
;$3A
;TEST OPERAND
; FTST FPm
;
TST	BSR	BAD
	BRA	FLINE90

	END
------------------------------------------------------
;$3A
;TEST OPERAND
; FTST FPm
;
TST	BSR	BAD
	BRA	FLINE90

	EN