/*
 *	PDP-8 register definitions for PDP-8 emulator.
 *
 *	Author:
 *		Bill Haygood
 *		41832 Ernest Road
 *		Loon Lake, WA 99148-9607
 *		Internet: billh@comtch.iea.com
 *		Voice/AnsMach/FAX \
 *			or	   509-233-2555
 *		  Cellular/Pager  /
 *
 *	Copyright 1992, 1993 by the author with all rights reserved.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define	BYTE	char
#define UBYTE	unsigned char
#define	WORD	short
#define	UWORD	unsigned short
#define	INT	int
#define	UINT	unsigned int
#define	LONG	long
#define	ULONG	unsigned long
#define REG	register
#define DOUBLE	double
#define FLOAT	float
#define	VOID	void
#define STATIC	static

#define	SEEK_SET	0
#define	SEEK_CUR	1
#define	SEEK_END	2

#define	TRUE	(1)
#define	FALSE	(0)

#define	CLKCNT	1000

/*
 *	pdp8 registers.
 */
UINT	DF = 0 ;			/* Data Field register		*/
UINT	IB = 0 ;			/* Inst Buffer			*/
UINT	IF = 0 ;			/* Inst Field register		*/
UINT	PC = 07600 ;			/* PC register			*/
UINT	INST ;				/* Instruction fetched from mem */
UINT	AC = 0 ;			/* Accumulator			*/
UINT	MQ = 0 ;			/* Multiplier-Quotient		*/
UINT	SR = 0 ;			/* Switch register		*/
UBYTE	EAE = FALSE ;			/* EAE presence/mode flag	*/
UBYTE	GTF = FALSE ;			/* EAE Greater Than flag	*/
UINT	SC = 0 ;			/* EAE Step Counter		*/
UBYTE	int_ena = FALSE ;		/* Interrupt Enable Flip-Flop	*/
UBYTE	int_inh = FALSE ;		/* Interrupt Inhibit Flop-Flop	*/
ULONG	io_flags = FALSE ;		/* Interrupt request line	*/
UINT	UB = FALSE ;			/* User Buffer			*/
UINT	UF = FALSE ;			/* User Flag			*/
UINT	SF = 0 ;			/* Save Field			*/

/*
 *	'base' points to pdp8 memory.
 */
UWORD	*base = NULL ;

/*
 *	Processor interrupt enable bits.
 */
#define	userFLAG	1

/*
 *	FPP-8/A Floating Point Processor
 */
#define fppFLAG		(1 << 1)
#define	LEAV		0		/* Run in interleaved mode	*/
#define	LOCK		1		/* Run in lockout mode		*/
#define	DP		2		/* Double precision data mode	*/
#define	FP		3		/* Floating point data mode	*/
#define	EP		6		/* Extended precision data mode	*/
#define	FPP		fpp_data	/* FPP-8/A in/out flag		*/
LONG	fpptotal = 0 ;			/* FPP-8/A inst execution count	*/
UBYTE	fpptrace = FALSE ;		/* FPP instruction trace flag	*/
UBYTE	fpp_mode = FALSE ;		/* Run mode			*/
UBYTE	fpp_data = FALSE ;		/* Data mode			*/
UBYTE	fpp_run = FALSE ;		/* Pause: run = halt = TRUE	*/
UBYTE	fpp_pause = FALSE ;		/* Set by FPHLT (6554)		*/
UINT	fpp_aptp = 0 ;			/* FPP APT pointer		*/
UINT	fpp_command = 0 ;		/* FPP command register		*/
					/* Bit	Meaning			*/
					/*   0	Select DP mode		*/
					/*   1	Exit on exp overflow	*/
					/*   2	Enable memory protection*/
					/*   3	Enable interrupt	*/
					/*   4	No store op address	*/
					/*   5	No store index regs	*/
					/*   6	No store ind ptr list	*/
					/*   7	No store FAC		*/
					/*   8	Unused			*/
					/* 9-11	APT data field		*/
UINT	fpp_stat = 0 ;			/* FPP status register		*/
					/* Bit	Meaning			*/
					/*   0	DP Mode			*/
					/*   1	Instruction Trap	*/
					/*   2	CPU Force Trap		*/
					/*   3	Divide by zero		*/
					/*   4	Frac overflow (DP only)	*/
					/*   5	Exponent overflow	*/
					/*   6	Exponent underflow	*/
					/* 7-10	Unused			*/
					/*  11	Run			*/
UWORD	fpp_ac [6] ;			/* FPP FAC in pdp8 format	*/
UINT	fpp_pc = 0 ;			/* FPP program counter		*/
UINT	fpp_x0 = 0 ;			/* FPP index register location	*/
UINT	fpp_br = 0 ;			/* FPP base register		*/
UINT	fpp_opadd = 0 ;			/* FPP operand address		*/

/*
 *	100 Hz clock (DK8E-C, PDP8-A, VT/78, VT/278)
 */
#define clockFLAG	(1 << 2)
UBYTE	clocktype = 0 ;			/* 1=DK8-EA, 2=DK8-EC, 3-DK8-EP	*/
LONG	tickspersec = 0 ;		/* Real time clock ticks/second	*/

/*
 *	Console VDU
 */
#define coninFLAG	(1 << 3)
#define conoutFLAG	(1 << 4)
UBYTE	coninchar = '\0', conoutchar = '\0' ;

/*
 *	Auxilliary VDU
 */
#define auxinFLAG	(1 << 5)
#define auxoutFLAG	(1 << 6)
UBYTE	aux_vdu = FALSE ;
UBYTE	auxinchar = '\0', auxoutchar = '\0' ;

/*
 *	PT8-E Reader/Punch
 */
#define pt8rdrFLAG	(1 << 7)
FILE	*pt8reader = NULL ;
UBYTE	pt8rdrbuffer = 0377 ;
#define pt8punFLAG	(1 << 8)
FILE	*pt8punch = NULL ;
UBYTE	pt8punbuffer = 0 ;

/*
 *	LP8-E Line Printer
 */
#define lp8doneFLAG	(1 << 9)
/* #define lp8errorFLAG */
FILE	*lp8printer = NULL ;
UBYTE	printCHAR  = 0 ;

/*
 *	RK8-E Disk System Registers
 */
#define rk8FLAG		(1 << 10)
#define RK8BUFSIZ	(32 * 384)
BYTE	*rk8file [4] = { NULL, NULL, NULL, NULL } ;
UINT	rk8command = 0 ;
UINT	rk8curaddr = 0 ;
UINT	rk8block   = 0 ;
UINT	rk8status  = 0 ;
struct
{
    FILE *drive ;
    UBYTE *buff ;
    INT cyl ;
    INT maxcyl ;
    UBYTE dirty ;
} rk8 [4] ;
INT	rk8unit = 0 ;
INT	rk8words ;
INT	rk8count = 0 ;
UBYTE	rk8lock = 0 ;
UBYTE	rk8write = 0 ;

/*
 *	Miscellaneous variables used by the emulator.
 */
BYTE	chrsout [200] = { 0 }, pdp8exec [100] = { 0 } ;
UBYTE	run = FALSE ;
UBYTE	delay = FALSE ;			/* Delay after ION		*/
ULONG	int_mask = 0 ;			/* Interrupt request mask	*/
UBYTE	incrPC = FALSE ;		/* Used by disassem & in pdp8.c	*/
UINT	lastPC = 0 ;			/* Used in tracing		*/
UINT	dateword = 0 ;			/* Used to store OS/8 dateword	*/
UBYTE	traceflag = FALSE ;
UBYTE	breakflag = FALSE ;
UBYTE	tabulate = FALSE ;
UBYTE	profile = FALSE ;
UBYTE	checkvdus = FALSE ;
INT	clkcntr = CLKCNT ;
LONG	curtime, ticks, ticktime ;
UWORD	addrmask = 0177777, instmask = 0177777 ;
UWORD	breakaddr = 0177777, breakinst = 0177777 ;
FILE	*tabfile, *histofile ;
ULONG	*tab = NULL, *histo = NULL ;
UBYTE	total = 0 ;
DOUBLE	pdptotal = 0.0 ;
INT	trace = 16 ;
ULONG	exec = 0 ;
INT	diag = 0 ;
union
{
    DOUBLE d ;
    FLOAT f [2] ;
    ULONG l [2] ;
    UWORD w [4] ;
    UBYTE b [8] ;
} order ;

/*
 *	Various output files.
 */
FILE	*pdp8conout = NULL ;		/* pdp8 console output file	*/
FILE	*pdp8auxout = NULL ;		/* pdp8 aux console output file	*/
FILE	*tracefile = NULL ;		/* pdp8 inst trace output file	*/
FILE	*disassemfile = NULL ;		/* pdp8 disassembly output file	*/

/*
 *	pdp8 memory
 */
FILE	*pdp8file = NULL ;		/* pdp8 memory storage file	*/
UWORD	mem32k [8L * 4096] ;
