/* $Header:fpemul.h 12.0$ */
/* $ACIS:fpemul.h 12.0$ */
/* $Source: /ibm/acis/usr/src/usr.lib/libfp/emulfp/RCS/fpemul.h,v $ */

#ifndef aiws
#if !defined(lint) && !defined(LOCORE)  && defined(RCS_HDRS)
static char *rcsidfpemul = "$Header:fpemul.h 12.0$";
#endif
#endif aiws

/************************************************************************/
/* The bit pattern of an FPA '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 codes below			*/
/*		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		*/
/* The following macros pull the important parts out of an FPA 'address'*/
/************************************************************************/

#define OPCODE(addr) ((addr >> 10) & 0x3ff)
#define DATASRC(addr) ((addr >> 18) & 0x3)
#define OPERAND1(addr) ((addr >> 6) & 0xf)
#define OPERAND2(addr) ((addr >> 2) & 0xf)

#define STATUSREG 14			/* FPA reg14 is the status reg	*/
#define SEARREG   15			/* FPA reg15 is the sear	*/

/************************************************************************/
/* OPCODES: 	each of the following constants corresponds to an FPA	*/
/*		'address' shifted right 10 bits and masked to get the 	*/
/*		10 bits of code.					*/
/*		The high 2 bits are really the data source 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 ABSL	0x074
#define ABSS	0x075
#define ADDL	0x040
#define ADDLI	0x140
#define ADDIL	0x240
#define ADDS	0x041
#define ADDSI	0x141
#define ADDIS	0x241
#define CLS	0x016
#define CLIS	0x216
#define COML	0x048
#define COMLI	0x148
#define COMIL	0x248
#define COMS	0x049
#define COMSI	0x149
#define COMIS	0x249
#define COMTL	0x04a
#define COMTLI	0x14a
#define COMTIL	0x24a
#define COMTS	0x04b
#define COMTSI	0x14b
#define COMTIS	0x24b
#define COPL	0x044
#define COPS	0x045
#define CSL	0x01b
#define CSIL	0x21b
#define CWL	0x203
#define CWS	0x207
#define DIVL	0x060
#define DIVLI	0x160
#define DIVIL	0x260
#define DIVS	0x061
#define DIVSI	0x161
#define DIVIS	0x261
#define FLW	0x03b
#define FSW	0x03f
#define MULL	0x070
#define MULLI	0x170
#define MULIL	0x270
#define MULS	0x071
#define MULSI	0x171
#define MULIS	0x271
#define NEGL	0x054
#define NEGS	0x055
#define RDFR	0x0bc
#define RDSTR	0x037
#define RLW	0x023
#define RSW	0x027
#define SUBL	0x050
#define SUBLI	0x150
#define SUBIL	0x250
#define SUBS	0x051
#define SUBSI	0x151
#define SUBIS	0x251
#define TLW	0x02b
#define TSW	0x02f
#define WTFR	0x094
#define WTSTR	0x10f

    /*
     * lar -- Thu Dec  5 15:16:29 PST 1985
     * todo -- the following should simulate what the FPA does when
     * 		given an invalid address (instruction) but until we can
     *		do that, we will simply print a message and return.
     */
#define INVALIDFPAOP \
		{  printf("Invalid FPA operation! opcode = %x\n",opcode); \
		   set_stat(EM_INV_OPER);\
		   return;}

    /*
     * lar -- Thu Dec  5 15:56:16 PST 1985
     * todo -- the following should give some kind of warning that
     * 		the emulator can't operate on odd registers, and then
     *		cause some kind of error (like INVALIDFPAOP?) or just return.
     */
#define INVALIDEMOP \
		{  printf("Emulator can only operate on even registers,\n"); \
		   printf("or, in the immortal words of Doug Jewett,\n"); \
		   printf("Shut 'er down, Clancey, she's a-pumpin' mud!\n"); \
		   return;}

    /*
     * The following copying instructions should probably be
     * calls to _FPcpd and _FPcpf, formally, but in the interest
     * of speed, I have made them explicit.  If it is decided
     * best that the official routines are called, changing
     * these macros should make it easy.
     * I have defined the macros as (arg2 <- arg1), but calls would be:
     *		_FPcpd(reg2,reg1) or _FPcpf(reg2,reg1) 
     * because those copy routines do (arg1 <- arg2).
     * lar -- Thu Dec  5 15:11:36 PST 1985
     */
#define COPYDOUBLE(reg1,reg2) \
	machine.dreg[reg2] = machine.dreg[reg1]

#define COPYFLOAT(reg1,reg2) \
	machine.dreg[reg2].dfracth = machine.dreg[reg1].dfracth
