/* sds_defs.h: SDS 940 simulator definitions 

   Copyright (c) 2001-2004, Robert M. Supnik

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

   Except as contained in this notice, the name of Robert M Supnik shall not
   be used in advertising or otherwise to promote the sale, use or other dealings
   in this Software without prior written authorization from Robert M Supnik.

   25-Apr-03	RMS	Revised for extended file support
*/

#include "sim_defs.h"					/* simulator defns */

/* Simulator stop codes */

#define STOP_IONRDY	1				/* I/O dev not ready */
#define STOP_HALT	2				/* HALT */
#define STOP_IBKPT	3				/* breakpoint */
#define STOP_INVDEV	4				/* invalid dev */
#define STOP_INVINS	5				/* invalid instr */
#define STOP_INVIOP	6				/* invalid I/O op */
#define STOP_INDLIM	7				/* indirect limit */
#define STOP_EXULIM	8				/* EXU limit */
#define STOP_MMINT	9				/* mm in intr */
#define STOP_MMTRP	10				/* mm in trap */
#define STOP_TRPINS	11				/* trap inst not BRM */
#define STOP_RTCINS	12				/* rtc inst not MIN/SKR */
#define STOP_ILLVEC	13				/* zero vector */
#define STOP_CCT	14				/* runaway CCT */

/* Trap codes */

#define MM_PRVINS	-040				/* privileged */
#define MM_NOACC	-041				/* no access */
#define MM_WRITE	-043				/* write protect */
#define MM_MONUSR	-044				/* mon to user */

/* Conditional error returns */

#define CRETINS		return ((stop_invins)? STOP_INVINS: SCPE_OK)
#define CRETDEV		return ((stop_invdev)? STOP_INVDEV: SCPE_OK)
#define CRETIOP		return ((stop_inviop)? STOP_INVIOP: SCPE_OK)
#define CRETIOE(f,c)	return ((f)? c: SCPE_OK)

/* Architectural constants */

#define SIGN		040000000			/* sign */
#define DMASK		077777777			/* data mask */
#define EXPS		0400				/* exp sign */
#define EXPMASK		0777				/* exp mask */
#define SXT(x)		((int32) (((x) & SIGN)? ((x) | ~DMASK): \
			((x) & DMASK)))
#define SXT_EXP(x)	((int32) (((x) & EXPS)? ((x) | ~EXPMASK): \
			((x) & EXPMASK)))

/* Memory */

#define MAXMEMSIZE	(1 << 16)			/* max memory size */
#define PAMASK		(MAXMEMSIZE - 1)		/* physical addr mask */
#define MEMSIZE		(cpu_unit.capac)		/* actual memory size */
#define MEM_ADDR_OK(x)	(((uint32) (x)) < MEMSIZE)
#define ReadP(x)	M[x]
#define WriteP(x,y)	if (MEM_ADDR_OK (x)) M[x] = y

/* Virtual addressing */

#define VA_SIZE		(1 << 14)			/* virtual addr size */
#define VA_MASK		(VA_SIZE - 1)			/* virtual addr mask */
#define VA_V_PN		11				/* page number */
#define VA_M_PN		07
#define VA_GETPN(x)	(((x) >> VA_V_PN) & VA_M_PN)
#define VA_POFF		((1 << VA_V_PN) - 1)		/* offset */
#define VA_USR		(I_USR)				/* user flag in addr */
#define XVA_MASK	(VA_USR | VA_MASK)

/* Arithmetic */

#define TSTS(x)		((x) & SIGN)
#define NEG(x)		(-((int32) (x)) & DMASK)
#define ABS(x)		(TSTS (x)? NEG(x): (x))

/* Memory map */

#define MAP_PROT	(040 << VA_V_PN)		/* protected */
#define MAP_PAGE	(037 << VA_V_PN)		/* phys page number */

/* Instruction format */

#define I_USR		(1 << 23)			/* user */
#define I_IDX		(1 << 22)			/* indexed */
#define I_POP		(1 << 21)			/* programmed op */
#define I_V_TAG		21				/* tag */
#define I_V_OP		15				/* opcode */
#define I_M_OP		077
#define I_GETOP(x)	(((x) >> I_V_OP) & I_M_OP)
#define I_IND		(1 << 14)			/* indirect */
#define I_V_SHFOP	11				/* shift op */
#define I_M_SHFOP	07
#define I_GETSHFOP(x)	(((x) >> I_V_SHFOP) & I_M_SHFOP)
#define I_SHFMSK	0777				/* shift count */
#define I_V_IOMD	12				/* IO inst mode */
#define I_M_IOMD	03
#define I_GETIOMD(x)	(((x) >> I_V_IOMD) & I_M_IOMD)
#define I_V_SKCND	7				/* SKS skip cond */
#define I_M_SKCND	037
#define I_GETSKCND(x)	(((x) >> I_V_SKCND) & I_M_SKCND)
#define I_EOB2		000400000			/* chan# bit 2 */
#define I_SKB2		000040000			/* skschan# bit 2 */
#define I_EOB1		020000000			/* chan# bit 1 */
#define I_EOB0		000000100			/* chan# bit 0 */
#define I_GETEOCH(x)	((((x) & I_EOB2)? 4: 0) | \
			 (((x) & I_EOB1)? 2: 0) | \
			 (((x) & I_EOB0)? 1: 0))
#define I_SETEOCH(x)	((((x) & 4)? I_EOB2: 0) | \
			 (((x) & 2)? I_EOB1: 0) | \
			 (((x) & 1)? I_EOB0: 0))
#define I_GETSKCH(x)	((((x) & I_SKB2)? 4: 0) | \
			 (((x) & I_EOB1)? 2: 0) | \
			 (((x) & I_EOB0)? 1: 0))
#define I_SETSKCH(x)	((((x) & 4)? I_SKB2: 0) | \
			 (((x) & 2)? I_EOB1: 0) | \
			 (((x) & 1)? I_EOB0: 0))

/* Globally visible flags */

#define UNIT_V_GENIE	(UNIT_V_UF + 0)
#define UNIT_GENIE	(1 << UNIT_V_GENIE)

/* Timers */

#define TMR_RTC		0				/* clock */
#define TMR_MUX		1				/* mux */

/* I/O routine functions */

#define IO_CONN		0				/* connect */
#define IO_EOM1		1				/* EOM mode 1 */
#define IO_DISC		2				/* disconnect */
#define IO_READ		3				/* read */
#define IO_WRITE	4				/* write */
#define IO_WREOR	5				/* write eor */
#define IO_SKS		6				/* skip signal */

/* Dispatch template */

struct sdsdspt {
	uint32	num;					/* # entries */
	uint32	off;					/* offset from base */
	};

typedef struct sdsdspt DSPT;

/* Device information block */

struct sdsdib {
	int32	chan;					/* channel */
	int32	dev;					/* base dev no */
	int32	xfr;					/* xfer flag */
	DSPT	*tplt;					/* dispatch templates */
	t_stat	(*iop) (uint32 fnc, uint32 dev, uint32 *dat);
	};

typedef struct sdsdib DIB;

/* Channels */

#define NUM_CHAN	8				/* max num chan */
#define CHAN_W		0				/* TMCC */
#define CHAN_Y		1
#define CHAN_C		2
#define CHAN_D		3
#define CHAN_E		4				/* DACC */
#define CHAN_F		5
#define CHAN_G		6
#define CHAN_H		7

/* I/O control EOM */

#define CHC_REV		04000				/* reverse */
#define CHC_NLDR	02000				/* no leader */
#define CHC_BIN		01000				/* binary */
#define CHC_V_CPW	7				/* char/word */
#define CHC_M_CPW	03
#define CHC_GETCPW(x)	(((x) >> CHC_V_CPW) & CHC_M_CPW)

/* Buffer control (extended) EOM */

#define CHM_CE		04000				/* compat/ext */
#define CHM_ER		02000				/* end rec int */
#define CHM_ZC		01000				/* zero wc int */
#define CHM_V_FNC	7				/* term func */
#define CHM_M_FNC	03
#define CHM_GETFNC(x)	(((x) & CHM_CE)? (((x) >> CHM_V_FNC) & CHM_M_FNC): CHM_COMP)
#define  CHM_IORD	0				/* record, disc */
#define  CHM_IOSD	1				/* signal, disc */
#define  CHM_IORP	2				/* record, proc */
#define  CHM_IOSP	3				/* signal, proc */
#define  CHM_COMP	5				/* compatible */
#define  CHM_SGNL	1				/* signal bit */
#define  CHM_PROC	2				/* proceed bit */
#define CHM_V_HMA	5				/* hi mem addr */
#define CHM_M_HMA	03
#define CHM_GETHMA(x)	(((x) >> CHM_V_HMA) & CHM_M_HMA)
#define CHM_V_HWC	0				/* hi word count */
#define CHM_M_HWC	037
#define CHM_GETHWC(x)	(((x) >> CHM_V_HWC) & CHM_M_HWC)

/* Channel flags word */

#define CHF_ERR		00001				/* error */
#define CHF_IREC	00002				/* interrecord */
#define CHF_ILCE	00004				/* interlace */
#define CHF_DCHN	00010				/* data chain */
#define CHF_EOR		00020				/* end of record */
#define CHF_12B		00040				/* 12 bit mode */
#define CHF_24B		00100				/* 24 bit mode */
#define CHF_OWAK	00200				/* output wake */
#define CHF_SCAN	00400				/* scan */
#define CHF_TOP		01000				/* TOP pending */
#define CHF_N_FLG	9				/* <= 16 */

/* Interrupts and vectors (0 is reserved), highest bit is highest priority */

#define INT_V_PWRO	31				/* power on */
#define INT_V_PWRF	30				/* power off */
#define INT_V_CPAR	29				/* CPU parity err */
#define INT_V_IPAR	28				/* IO parity err */
#define INT_V_RTCS	27				/* clock sync */
#define INT_V_RTCP	26				/* clock pulse */
#define INT_V_YZWC	25				/* chan Y zero wc */
#define INT_V_WZWC	24				/* chan W zero wc */
#define INT_V_YEOR	23				/* chan Y end rec */
#define INT_V_WEOR	22				/* chan W end rec */
#define INT_V_CZWC	21				/* chan C */
#define INT_V_CEOR	20
#define INT_V_DZWC	19				/* chan D */
#define INT_V_DEOR	18
#define INT_V_EZWC	17				/* chan E */
#define INT_V_EEOR	16
#define INT_V_FZWC	15				/* chan F */
#define INT_V_FEOR	14
#define INT_V_GZWC	13				/* chan G */
#define INT_V_GEOR	12
#define INT_V_HZWC	11				/* chan H */
#define INT_V_HEOR	10
#define INT_V_MUXR	9				/* mux receive */
#define INT_V_MUXT	8				/* mux transmit */
#define INT_V_MUXCO	7				/* SDS carrier on */
#define INT_V_MUXCF	6				/* SDS carrier off */
#define INT_V_DRM	5				/* Genie drum */
#define INT_V_FORK	4				/* fork */

#define INT_PWRO	(1 << INT_V_PWRO)
#define INT_PWRF	(1 << INT_V_PWRF)
#define INT_CPAR	(1 << INT_V_CPAR)
#define INT_IPAR	(1 << INT_V_IPAR)
#define INT_RTCS	(1 << INT_V_RTCS)
#define INT_RTCP	(1 << INT_V_RTCP)
#define INT_YZWC	(1 << INT_V_YZWC)
#define INT_WZWC	(1 << INT_V_WZWC)
#define INT_YEOR	(1 << INT_V_YEOR)
#define INT_WEOR	(1 << INT_V_WEOR)
#define INT_CZWC	(1 << INT_V_CZWC)
#define INT_CEOR	(1 << INT_V_CEOR)
#define INT_DZWC	(1 << INT_V_DZWC)
#define INT_DEOR	(1 << INT_V_DEOR)
#define INT_EZWC	(1 << INT_V_EZWC)
#define INT_EEOR	(1 << INT_V_EEOR)
#define INT_FZWC	(1 << INT_V_FZWC)
#define INT_FEOR	(1 << INT_V_FEOR)
#define INT_GZWC	(1 << INT_V_GZWC)
#define INT_GEOR	(1 << INT_V_GEOR)
#define INT_HZWC	(1 << INT_V_HZWC)
#define INT_HEOR	(1 << INT_V_HEOR)
#define INT_MUXR	(1 << INT_V_MUXR)
#define INT_MUXT	(1 << INT_V_MUXT)
#define INT_MUXCO	(1 << INT_V_MUXCO)
#define INT_MUXCF	(1 << INT_V_MUXCF)
#define INT_DRM		(1 << INT_V_DRM)
#define INT_FORK	(1 << INT_V_FORK)

#define VEC_PWRO	0036
#define VEC_PWRF	0037
#define VEC_CPAR	0056
#define VEC_IPAR	0057
#define VEC_RTCS	0074
#define VEC_RTCP	0075
#define VEC_YZWC	0030
#define VEC_WZWC	0031
#define VEC_YEOR	0032
#define VEC_WEOR	0033
#define VEC_CZWC	0060
#define VEC_CEOR	0061
#define VEC_DZWC	0062
#define VEC_DEOR	0063
#define VEC_EZWC	0064
#define VEC_EEOR	0065
#define VEC_FZWC	0066
#define VEC_FEOR	0067
#define VEC_GZWC	0070
#define VEC_GEOR	0071
#define VEC_HZWC	0072
#define VEC_HEOR	0073
#define VEC_MUXR	0200				/* term mux rcv */
#define VEC_MUXT	0201				/* term mux xmt */
#define VEC_MUXCO	0202				/* SDS: mux carrier on */
#define VEC_MUXCF	0203				/* SDS: mux carrier off */
#define VEC_DRM		0202				/* Genie: drum */
#define VEC_FORK	0216				/* "fork" */

/* Device constants */

#define DEV_MASK	077				/* device mask */
#define DEV_TTI		001				/* teletype */
#define DEV_PTR		004				/* paper tape rdr */
#define DEV_MT		010				/* magtape */
#define DEV_RAD		026				/* fixed head disk */
#define DEV_DSK		026				/* moving head disk */
#define DEV_TTO		041				/* teletype */
#define DEV_PTP		044				/* paper tape punch */
#define DEV_LPT		060				/* line printer */
#define DEV_MTS		020				/* MT scan/erase */
#define DEV_OUT		040				/* output flag */
#define DEV3_GDRM	004				/* Genie drum */
#define DEV3_GMUX	001				/* Genie mux */
#define DEV3_SMUX	(DEV_MASK)			/* standard mux */

#define LPT_WIDTH	132				/* line print width */
#define CCT_LNT		132				/* car ctrl length */

/* Transfer request flags for devices (0 is reserved) */

#define XFR_V_TTI	1				/* console */
#define XFR_V_TTO	2
#define XFR_V_PTR	3				/* paper tape */
#define XFR_V_PTP	4
#define XFR_V_LPT	5				/* line printer */
#define XFR_V_RAD	6				/* fixed hd disk */
#define XFR_V_DSK	7				/* mving hd disk */
#define XFR_V_MT0	8				/* magtape */

#define XFR_TTI		(1 << XFR_V_TTI)
#define XFR_TTO		(1 << XFR_V_TTO)
#define XFR_PTR		(1 << XFR_V_PTR)
#define XFR_PTP		(1 << XFR_V_PTP)
#define XFR_LPT		(1 << XFR_V_LPT)
#define XFR_RAD		(1 << XFR_V_RAD)
#define XFR_DSK		(1 << XFR_V_DSK)
#define XFR_MT0		(1 << XFR_V_MT0)

/* PIN/POT ordinals (0 is reserved) */

#define POT_ILCY	1				/* interlace */
#define POT_DCRY	(POT_ILCY + NUM_CHAN)		/* data chain */
#define POT_ADRY	(POT_DCRY + NUM_CHAN)		/* address reg */
#define POT_RL1		(POT_ADRY + NUM_CHAN)		/* RL1 */
#define POT_RL2		(POT_RL1 + 1)			/* RL2 */
#define POT_RL4		(POT_RL2 + 1)			/* RL4 */
#define POT_RADS	(POT_RL4 + 1)			/* fhd sector */
#define POT_RADA	(POT_RADS + 1)			/* fhd addr */
#define POT_DSK		(POT_RADA + 1)			/* mhd sec/addr */
#define POT_SYSI	(POT_DSK + 1)			/* sys intr */
#define POT_MUX		(POT_SYSI + 1)			/* multiplexor */

/* Opcodes */

enum opcodes {
	HLT, BRU, EOM, EOD = 006,
	MIY = 010, BRI, MIW, POT, ETR, MRG = 016, EOR,
	NOP, OVF = 022, EXU,
	YIM = 030, WIM = 032, PIN, STA = 035, STB, STX,
	SKS, BRX, BRM = 043, RCH = 046,
	SKE = 050, BRR, SKB, SKN, SUB, ADD, SUC, ADC,
	SKR, MIN, XMA, ADM, MUL, DIV, RSH, LSH,
	SKM, LDX, SKA, SKG, SKD, LDB, LDA, EAX };

/* Channel function prototypes */

void chan_set_flag (int32 ch, uint32 fl);
void chan_set_ordy (int32 ch);
void chan_disc (int32 ch);
void chan_set_uar (int32 ch, uint32 dev);
t_stat set_chan (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat chan_process (void);
t_bool chan_testact (void);
