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

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

#include <machine/rtflops.h>
#include <machine/float.h>

#define u_char		unsigned char
#define u_short		unsigned short
#define u_int		unsigned int
#define u_long		unsigned long
#define MAX_OPERAND	3
#define UIF_MAX_SIZE	120

typedef struct {
	u_long	HI,LO;
} lg_type;				/* packed long type */

typedef struct {
	u_short HI,LO;
} sh_type;				/* packed short type */

typedef struct {
	u_char	HI,LO;
} ch_type;				/* packed char type */

typedef union {
	double	D;
	lg_type lg;	 		/* dimm is treated as two ULs */
} dimm_type;				/* double precision imm val oper type */

typedef union {
	u_long	L;
	sh_type	sh;			/* a long is treated as two USs */
} addr_type;				/* for addr and inst offset */

typedef union {
	u_short S;
	ch_type	ch;
} opt_type;				/* typenum and regnum form a halfword */

typedef union {
	int	I;
	float	F;
	u_long	UL;			/* dimm is treated as two ULs */
} operand_type;				/* word operand type */

typedef union {
	opt_type	opt[MAX_OPERAND];
	operand_type	operand[(MAX_OPERAND * 2) + ((MAX_OPERAND + 1) >> 1)];
} opr_type;				/* 2nd half of the uif */

typedef struct {
	u_short	saver15;
	u_short	bala1;
	u_short	bala2;
	u_char	opcode;
	u_char	numopnds;
	u_short	scratchg;
	u_char	mysize;
	u_char	scratchf;
	opr_type	opr;
} uif_type;				/* uinversal instruction format */

typedef struct {
	struct  floatstate floatstate;  /* fp hardware state structure  */
	int	firsttime;		/* version#, !=0 first time	*/
	u_long 	(*fp_MachRegs);		/* pointer to emul fp regs	*/
	int	fptype;			/* type of "hardware" being used*/
	int	env_fpa;		/* environment variable FPA	*/
	int	env_prec;		/* environment variable PREC...	*/
	int	*compat;		/* ptr to value of mixed .o's	*/
	char	*(*fpalloc)();		/* ptr to fn. to allocate space */
	void	(*fpabort)();		/* ptr to fn. to call if errors	*/
	int	(*fpblock)();		/* ptr to fn. to mask signals	*/
	int	(*fpsetfloatstate)();
	int	f881_scr_holder;	/* access mc881 SCR via DMA	*/
	int	f881_cmp_NAN_code;	/* addr of cmp with NAN handler	*/
	int	holder_r13,		/* scratch regs for 		*/
		holder_r14,		/* f881_cmp_NAN_code		*/
		holder_r15,
		hi_2to31,		/* 0x41e00000 */
		lo_2to31,		/* 0x00000000 */
		f_2to31,		/* 0x4f000000 */
		scratch_1,
		scratch_2,
		scratch_3,
		scratch_4,
		reserved[25];
} state_type;				/* general info from fpglue     */
#define VERSION	3			/* NOTE: any time state_type	*/
					/* changes; fpglue's firsttime	*/
					/* and VERSION must match	*/
/*
 * In VERSION_881NAN or later, the fp_state struct in fpglue.s 
 * is changed: serveral variables are added to handle NAN's for
 * MC881, also, MC881 will handle single precision numbers correctly.
 * Most important is that 32 reserved words are added to the end of
 * fp_state for future expansion.  They are initialized to 0.
 */
#define VERSION_881NAN		5

/*
 * In VERSION_UNSIGNED or later, 7 of the 32 reserved words are used
 * to handle unsign int type (when convert to float or double).  See
 * changes in the state_type struct above. 
 *
 * The user space in old a.out's are OK. But the old a.out's don't work
 * right because hc.1.41 or earlier didn't handle conversion from unsigned
 * int to float or double.  One need to recompile source module using hc2
 * for them to work correctly.
 */
#define VERSION_UNSIGNED	6

typedef struct {
	uif_type	*data;		/* pointer to data block	*/
	int	last_instr_len;		/* num of half-words in last instr */
	int	stack_offset;		/* neg value, point to avail word */
	int	wordopnd[MAX_OPERAND];	/* index, where word opnds are in UI */
					/* to get at the word opnd of the */
					/* i th optype, do this:	*/
					/* data->opr.operand[wordopnd[i]] */
	int	immcode[MAX_OPERAND];	/* index, where in the generated */
					/* codes should the offset of the */
					/* imm value be plugged in */
	u_short	avail_genr;		/* available general registers mask */
	u_short	pushable_genr;		/* pushable gr in case none is avail */
	u_short	pushed_genr;		/* pushed gr mask */
	u_char	avail_fltr;		/* available flt pt registers mask */
	u_char	pushable_fltr;		/* pushable fr in case none is avail */
	u_char	pushed_fltr;		/* pushed fr mask */
 
	state_type *fp_state;		/* pointer to fp hardware state struct*/
	int	pushed_genr_count;
	int	pushed_fltr_count;
	u_long 	*fp_RegSave;		/* pointer to save user regs   	*/
	u_long	*emul_cstat;	        /* fp emulator condition status */
	int	pushing_fltr_flag;	/* set to MAGIC_NUMBER before	*/
					/* calling storem/loadm to	*/
					/* push/pop fp scratch regs	*/
} global_info_type;

typedef struct {
	char	numopnds;
	char	alt_required;
	char	speed;
	} opinfo_type;

extern opinfo_type _opinfo[NUM_OPCODES];
typedef int	(*operations[NUM_OPCODES])();

/***********************
 * RTFL Opcode types
 ***********************
 */
#define	SPEC	0
#define MONAD	1
#define	DYAD	2
#define	NOALT	0
#define	ALT	1
#define FAST	0
#define SLOW	1

/***********************
 * FP Hardware types
 ***********************
 */
#define	FPA_EMUL	0
#define	FPA_FPA1	1
#define	FPA_68881	2
#define	FPA_FPA2	3
#define NUM_FPAS	4

#define	FAST_PREC	0
#define	SINGLE_PREC	1
#define	DOUBLE_PREC	2
#define	PRECISE_PREC	3
#define	DEFAULT_PREC	FAST_PREC
