/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:fpa1ops.h 12.0$ */
/* $ACIS:fpa1ops.h 12.0$ */
/* $Source: /ibm/acis/usr/src/usr.lib/libfp/genfp/RCS/fpa1ops.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidfpa1ops = "$Header:fpa1ops.h 12.0$";
#endif

/*
 * OPCODES:
 *	each of the following constants corresponds to an FPA1
 *	'address' shifted right 10 bits and masked to get the
 *	10 bits of code.				
 *
 *	The high 2 bits are really the data source (ds) code
 *	(always 0, 1 or 2, never 3) but are included here as
 *	part of	the opcode to make the case statement easier
 *	to handle, and the default case guaranteed to catch all
 *	invalid addresses.
 */

#define OPFPA1_ABSL	0x074
#define OPFPA1_ABSS	0x075
#define OPFPA1_ADDL	0x040
#define OPFPA1_ADDS	0x041
#define OPFPA2_ATANL	0x0d4		/* no ATANS */
#define OPFPA2_ATAN2L	0x052		/* no ATAN2S */
#define OPFPA1_CLS	0x016
#define OPFPA1_COML	0x048
#define OPFPA1_COMS	0x049
#define OPFPA1_COPL	0x044
#define OPFPA1_COPS	0x045
#define OPFPA2_COSL	0x0c2		/* no COSS */
#define OPFPA1_CSL	0x01b
#define OPFPA1_CWL	0x003
#define OPFPA1_CWS	0x007
#define OPFPA1_DIVL	0x060
#define OPFPA1_DIVS	0x061
#define OPFPA2_EXPL	0x0d8		/* no EXPS */
#define OPFPA1_FLW	0x03b
#define OPFPA1_FSW	0x03f
#define OPFPA2_INTL	0x0ca		/* no INTS */
#define OPFPA2_LOGL	0x0dc		/* no LOGS */
#define OPFPA2_LOGBL	0x056		/* no LOGBS */
#define OPFPA2_LOG10L	0x0de		/* no LOG10S */
#define OPFPA1_MULL	0x070
#define OPFPA1_MULS	0x071
#define OPFPA1_NEGL	0x054
#define OPFPA1_NEGS	0x055
#define OPFPA2_NOOP	0x09f		/* To facilitate DMA read */
#define OPFPA1_RDFR	0x0bc
#define OPFPA1_RDSTR	0x037
#define OPFPA2_REML	0x062		/* no REMS */
#define OPFPA1_RLW	0x023
#define OPFPA1_RSW	0x027
#define OPFPA2_SINL	0x0c0		/* no SINS */
#define OPFPA2_SCALBL	0x072		/* no SCALBS */
#define OPFPA2_SQRL	0x064
#define OPFPA2_SQRS	0x065
#define OPFPA1_SUBL	0x050
#define OPFPA1_SUBS	0x051
#define OPFPA2_TANL	0x0c4		/* no TANS */
#define OPFPA1_TLW	0x02b
#define OPFPA1_TSW	0x02f
#define OPFPA1_WTFR	0x094
#define OPFPA1_WTSTR	0x10f

/*
 * The bit pattern of an FPA1 'address' is as follows:
 *	111111110000ddccccccccaaaabbbb00
 * where				
 *	dd (data source):
 *		00 -no immediate data
 *		01 -immediate data to be stored in op2
 *		10 -immediate data to be stored in op1
 *	cccccccc (code):  see opcodes		
 *	aaaa is operand 1, either one argument of a binary 
 *		operation or the source (single argument) of
 *		an unary operation			
 *	bbbb is operand 2, and destination of result
 */

/*
 * This macro sets up an fpa1 instruction.
 */ 
#define	fpa1inst(fop, ds, dst, src) \
	((0xff000000) | (fop << 10) | (ds << 18) | (dst << 2) | (src << 6))

#define STATUSREG		14	/* fpa1 status register is fr14 */
#define FPAs_RDSTATUS_INSTR	fpa1inst(OPFPA1_RDSTR, 0, STATUSREG, STATUSREG)
#define FPAs_WRSTATUS_INSTR	fpa1inst(OPFPA1_WTSTR, 0, STATUSREG, STATUSREG)

/*
 * fpa1_readstatus
 * Read the value of the fpa1 status register into general register "rx".
 */
#define fpa1_readstatus(newcode, gi, rx) \
		_fp_new_inst_load(newcode, gi, rx, FPAs_RDSTATUS_INSTR)

/*
 * fpa1_writestatus
 * Write the value of general register "rx" into the fpa1 status register.
 */
#define fpa1_writestatus(newcode, gi, rx) \
		_fp_new_inst_store(newcode, gi, rx, FPAs_WRSTATUS_INSTR)

#define FPA1WTFR(freg)		fpa1inst(OPFPA1_WTFR, 0, (freg), 0)
#define FPA1RDFR(freg)		fpa1inst(OPFPA1_RDFR, 0, 0, (freg))

#define USING_FPA1(gi)	(gi->fp_state->fptype == FPA_FPA1)

/*
 * The bit pattern of an FPA2 'address' is as follows:
 *	1111 1110 eerr ddccccccccaaaabbbbgg
 * where					
 *	ee (op1 ext):	Always zero.
 *	rr (op2 ext):
 *		00 -DMA write	
 *		11 -DMA read
 *	dd (data source):
 *		00 -no immediate data	
 *		01 -immediate data to be stored in op2
 *		10 -immediate data to be stored in op1
 *		11 -DMA read from op1 to memory
 *	cccccccc (code):  see opcodes			
 *	aaaa is operand 1, either one argument of a binary
 *		operation or the source (single argument) of
 *		an unary operation	
 *	bbbb is operand 2, and destination of result
 *	gg:
 *		00 -no immediate data (freg op freg)
 *		01 -DMA xfer 1 word (single precision)
 *		10 -DMA xfer 2 words (double precision)
 *		11 -DMA xfer n words (MOVEM, length in ZIC)
 */

/*
 * This macro sets up an fpa2 instruction.
 */ 
#define	fpa2inst(fop, rw, ds, dst, src, len) \
	(0xfe000000 | ((rw) << 20) | ((fop) << 10) | ((ds) << 18) | \
	 ((dst) << 2) | ((src) << 6) | (len))

/* for rw field */
#define DMA_WRITE		0
#define DMA_READ		3

/* for ds field */
#define NO_IMM_DATA		0
#define IMM2OP2			1
#define IMM2OP1			2

/* for len field */
#define ONE_WORD		1		/* single precision */
#define TWO_WORDS		2		/* double precision */
#define N_WORDS			3		/* ZIC xfer */
#define length_of(prec)		(((prec) == DBLETYPE) ? TWO_WORDS : ONE_WORD)

#define fpa2DMAread(freg,len) \
	fpa2inst(OPFPA2_NOOP, DMA_READ, DMA_READ, 0, freg*2, len)
#define fpa2DMAwrite(freg,len) \
	fpa2inst(OPFPA2_NOOP, DMA_WRITE, IMM2OP1, 0, freg*2, len)
#define FPA2_WRITE_ZIC_LENGTH	0xfe1e7c03

#define NO_DMA(gi)		((gi->fp_state->floatstate.hardware_state & \
				(FLOAT_AFPA_DMA | FLOAT_MC881)) == 0)
#define fpas_opcode(op,prec)	(_fpas_ops_tbl[(op)]+((prec)!=DBLETYPE))
