#ifndef	EXCEPTIONFRAME_ALREADY_DEFINED
#define	EXCEPTIONFRAME_ALREADY_DEFINED

#include	"../h/types.h"

/*
 * Structure of the various stack frames
 * which the {M68000,M68010,M68020} microprocessors present
 * upon exception.  These exceptions include address error,
 * bus error, and s/w trap.
 */
typedef	struct exceptionFrame {

  /*
   * The "commonFrame" is the same for all
   * of the {M68000,M68010,M68020} processors.
   */
  struct commonFrame_t {

#if	1
	u_long	E_ssr;		/* Status Register (long-align'd)(PS) */
#else
	u_short	E_ssr;		/* Status Register (real...)	(PS) */
#endif
	u_long	E_pc;		/* Program Counter		(PC) */
	u_short	E_effnVector;	/* 4-bit Effn + 12-bit Vector Offset */
  } commonFrame;
#define	e_ssr		commonFrame.E_ssr
#define	e_ps		e_ssr
#define	e_pc		commonFrame.E_pc
#define	e_effnVector	commonFrame.E_effnVector

#define	e_effn(_efp)	((_efp->e_effnVector & 0xf000) >> 12)
#define	e_Vector(_efp)	 (_efp->e_effnVector & 0x0fff)


  /*
   * The "variableFrame" is the locus
   * of any processor incompatiblities.
   */
  union variableFrame_t {

	struct	effn0Frame_t {	/* "Four Word" */
		u_long	E_dummy;	/* Nonexistent: syntactic sugar */
	} effn0Frame;


	struct	effn1Frame_t {	/* "Throwaway Four Word" */
		u_long	E_dummy;	/* Nonexistent: syntactic sugar */
	} effn1Frame;


	struct	effn2Frame_t {	/* "Six Word" */
		caddr_t	E_instrAddr;		/* Instruction address */
	} effn2Frame;
#define	e_instrAddr		variableFrame.effn2Frame.E_instrAddr


	/*
	 * This (effn==8) and the effn==0 are
	 * the only 68010 exception stack frames.
	 */
	struct	effn8Frame_t {	/* "68010 bus & addr exception" (29 words) */
		u_short	E_ssw;		/* Special Status Word (ssw) */
		caddr_t	E_faultAddr;		/* Instruction address */
		u_short	E_dummy0;		/* Internal register */
		u_short	E_dataOutBuf;		/* Data output buffer */
		u_short	E_dummy1;		/* Internal register */
		u_short	E_dataInBuf;		/* Data output buffer */
		u_short	E_iReg;		/* Instr. input buffer */
		u_short	E_unDef[16];		/* Internal registers */
	} effn8Frame;
#define	e_ssw_68010		variableFrame.effn8Frame.E_ssw
#define	e_faultAddr		variableFrame.effn8Frame.E_faultAddr
#define	e_DOB_68010		variableFrame.effn8Frame.E_dataOutBuf
#define	e_DIB_68010		variableFrame.effn8Frame.E_dataInBuf
#define	e_iReg_68010		variableFrame.effn8Frame.E_iReg


	struct	effn9Frame_t {	/* "Coprocessor Mid-Instruction" (10 words) */
		caddr_t	E_instrAddr;		/* Instruction address */
		u_short	E_CoProcUnDef[4];	/* Internal registers */
	} effn9Frame;
#define	e_instrAddr9	variableFrame.effn9Frame.E_instrAddr
#define	e_CoProcUnDef	variableFrame.effn9Frame.E_CoProcUnDef


	struct	common10_11Frame_t {/* Preamble: Short & Long Bus-Cycle Fault */
		u_short	E_dummy0;		/* Internal register */
		u_short	E_ssw;			/* Special Status Word (ssw) */
		u_short	E_iStageC;		/* Instruction pipe stage C */
		u_short	E_iStageB;		/* Instruction pipe stage B */
		caddr_t	E_dataFaultAddr;	/* Data cycle fault address */
#define	e_ssw_68020	variableFrame.common10_11Frame.E_ssw
#define	e_iStageC	variableFrame.common10_11Frame.E_iStageC
#define	e_iStageB	variableFrame.common10_11Frame.E_iStageB
#define	e_dataFaultAddr	variableFrame.common10_11Frame.E_dataFaultAddr

	  union	effn10subFrame_t {/* "Short Bus-Cycle Fault" (16 words, total)*/
		u_short	E_dummy1;		/* Internal register */
		u_short	E_dummy2;		/* Internal register */
		u_long	E_dataOutBuf;		/* Data output buffer */
		u_short	E_dummy3;		/* Internal register */
		u_short	E_dummy4;		/* Internal register */
	  } effn10subFrame;
#define	e_DOB_68020_f10	variableFrame.common10_11Frame.effn10subFrame.E_dataOutBuf

	  union	effn11subFrame_t {/* "Long Bus-Cycle Fault" (44 words, total) */
		caddr_t	E_pendingDataCycleAddr;	/* Pending data cycle address */
		u_short	E_dummy2[4];		/* Internal registers */
		caddr_t	E_stageBAddr;		/* Instruction stage B addr */
		u_short	E_dummy3[2];		/* Internal registers */
		u_long	E_dataOutBuf;		/* Data output buffer (DOB) */
		u_long	E_dataInBuf;		/* Data  input buffer (DIB) */
		u_short	E_dummy4[18];		/* Internal registers */
		caddr_t	E_pc2;			/* Observed 1st push: PC */
	  } effn11subFrame;
#define	e_pendingDataCycleAddr	variableFrame.common10_11Frame.effn11subFrame.E_pendingDataCycleAddr
#define	e_stageBAddr		variableFrame.common10_11Frame.effn11subFrame.E_stageBAddr
#define	e_DOB_68020_f11		variableFrame.common10_11Frame.effn11subFrame.E_dataOutBuf
#define	e_DIB_68020_f11		variableFrame.common10_11Frame.effn11subFrame.E_dataInBuf
#define	e_DIB_68020		e_DIB_68020_f11

	} common10_11Frame;


#define	e_DOB_68020(_efp)	((e_effn(_efp)==10)		\
				   ? _efp->e_DOB_68020_f10	\
				   : ((e_effn(_efp)==11)	\
					? _efp->e_DOB_68020_f11	\
					: panic("e_DOB_68020")))

  }	variableFrame;

} exceptionFrame_t;

#endif	EXCEPTIONFRAME_ALREADY_DEFINED
