/* pdp10_defs.h: PDP-10 simulator definitions | |
Copyright (c) 1993-2002, 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. | |
22-Apr-02 RMS Removed magtape record length error | |
20-Jan-02 RMS Added multiboard DZ11 support | |
23-Oct-01 RMS New IO page address constants | |
19-Oct-01 RMS Added DZ11 definitions | |
07-Sep-01 RMS Revised for PDP-11 multi-level interrupts | |
31-Aug-01 RMS Changed int64 to t_int64 for Windoze | |
29-Aug-01 RMS Corrected models and dates (found by Lars Brinkhoff) | |
01-Jun-01 RMS Updated DZ11 vector definitions | |
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug | |
*/ | |
#include "sim_defs.h" /* simulator defns */ | |
/* Digital Equipment Corporation's 36b family had six implementations: | |
name mips comments | |
PDP-6 0.25 Original 36b implementation, 1964 | |
KA10 0.38 First PDP-10, flip chips, 1967 | |
KI10 0.72 First paging system, flip chip + MSI, 1972 | |
KL10 1.8 First ECL system, ECL 10K, 1975 | |
KL10B 1.8 Expanded addressing, ECL 10K, 1978 | |
KS10 0.3 Last 36b system, 2901 based, 1979 | |
In addition, it ran four major (incompatible) operating systems: | |
name company comments | |
TOPS-10 DEC Original timesharing system | |
ITS MIT "Incompatible Timesharing System" | |
TENEX BBN ARPA-sponsored, became | |
TOPS-20 DEC Commercial version of TENEX | |
All of the implementations differ from one another, in instruction set, | |
I/O structure, and memory management. Further, each of the operating | |
systems customized the microcode of the paging systems (KI10, KL10, KS10) | |
for additional instructions and specialized memory management. As a | |
result, there is no "reference implementation" for the 36b family that | |
will run all programs and all operating systems. The conditionalization | |
and generality needed to support the full matrix of models and operating | |
systems, and to support 36b hardware on 32b data types, is beyond the | |
scope of this project. | |
Instead, this simulator emulates one model -- the KS10. It has the best | |
documentation and allows reuse of some of the Unibus peripheral emulators | |
written for the PDP-11 simulator. Further, the simulator requires that | |
the underlying compiler support 64b integer data types, allowing 36b data | |
to be maintained in a single data item. Lastly, the simulator implements | |
the maximum memory size, so that NXM's never happen. | |
*/ | |
/* Data types */ | |
typedef int32 a10; /* PDP-10 addr (30b) */ | |
typedef t_int64 d10; /* PDP-10 data (36b) */ | |
/* Abort codes, used to sort out longjmp's back to the main loop | |
Codes > 0 are simulator stop codes | |
Codes < 0 are internal aborts | |
Code = 0 stops execution for an interrupt check | |
*/ | |
#define STOP_HALT 1 /* halted */ | |
#define STOP_IBKPT 2 /* breakpoint */ | |
#define STOP_ILLEG 3 /* illegal instr */ | |
#define STOP_ILLINT 4 /* illegal intr inst */ | |
#define STOP_PAGINT 5 /* page fail in intr */ | |
#define STOP_ZERINT 6 /* zero vec in intr */ | |
#define STOP_NXMPHY 7 /* nxm on phys ref */ | |
#define STOP_IND 8 /* indirection loop */ | |
#define STOP_XCT 9 /* XCT loop */ | |
#define STOP_ILLIOC 10 /* invalid UBA num */ | |
#define STOP_ASTOP 11 /* address stop */ | |
#define STOP_UNKNOWN 12 /* unknown stop */ | |
#define PAGE_FAIL -1 /* page fail */ | |
#define INTERRUPT -2 /* interrupt */ | |
#define ABORT(x) longjmp (save_env, (x)) /* abort */ | |
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ | |
/* Return codes from eXTEND */ | |
#define XT_MUUO 0 /* invalid operation */ | |
#define XT_SKIP 1 /* skip return */ | |
#define XT_NOSK 2 /* no skip return */ | |
/* Operating system flags, kept in cpu_unit.flags */ | |
#define UNIT_V_ITS (UNIT_V_UF) /* ITS */ | |
#define UNIT_ITS (1 << UNIT_V_ITS) | |
#define UNIT_V_T20V41 (UNIT_V_UF + 1) /* TOPS-20 V4.1 */ | |
#define UNIT_T20V41 (1 << UNIT_V_T20V41) | |
#define ITS (cpu_unit.flags & UNIT_ITS) | |
/* Architectural constants */ | |
#define PASIZE 20 /* phys addr width */ | |
#define MAXMEMSIZE (1 << PASIZE) /* maximum memory */ | |
#define PAMASK ((1 << PASIZE) - 1) | |
#define MEMSIZE MAXMEMSIZE /* fixed, KISS */ | |
#define MEM_ADDR_NXM(x) ((x) >= MEMSIZE) | |
#define VASIZE 18 /* virtual addr width */ | |
#define AMASK ((1 << VASIZE) - 1) /* virtual addr mask */ | |
#define LMASK 0777777000000 /* left mask */ | |
#define LSIGN 0400000000000 /* left sign */ | |
#define RMASK 0000000777777 /* right mask */ | |
#define RSIGN 0000000400000 /* right sign */ | |
#define DMASK 0777777777777 /* data mask */ | |
#define SIGN 0400000000000 /* sign */ | |
#define MMASK 0377777777777 /* magnitude mask */ | |
#define ONES 0777777777777 | |
#define MAXPOS 0377777777777 | |
#define MAXNEG 0400000000000 | |
/* Instruction format */ | |
#define INST_V_OP 27 /* opcode */ | |
#define INST_M_OP 0777 | |
#define INST_V_DEV 26 | |
#define INST_M_DEV 0177 /* device */ | |
#define INST_V_AC 23 /* AC */ | |
#define INST_M_AC 017 | |
#define INST_V_IND 22 /* indirect */ | |
#define INST_IND (1 << INST_V_IND) | |
#define INST_V_XR 18 /* index */ | |
#define INST_M_XR 017 | |
#define OP_JRST 0254 /* JRST */ | |
#define AC_XPCW 07 /* XPCW */ | |
#define OP_JSR 0264 /* JSR */ | |
#define GET_OP(x) ((int32) (((x) >> INST_V_OP) & INST_M_OP)) | |
#define GET_DEV(x) ((int32) (((x) >> INST_V_DEV) & INST_M_DEV)) | |
#define GET_AC(x) ((int32) (((x) >> INST_V_AC) & INST_M_AC)) | |
#define TST_IND(x) ((x) & INST_IND) | |
#define GET_XR(x) ((int32) (((x) >> INST_V_XR) & INST_M_XR)) | |
#define GET_ADDR(x) ((a10) ((x) & AMASK)) | |
/* Byte pointer format */ | |
#define BP_V_P 30 /* position */ | |
#define BP_M_P 077 | |
#define BP_P 0770000000000 | |
#define BP_V_S 24 /* size */ | |
#define BP_M_S 077 | |
#define BP_S 0007700000000 | |
#define GET_P(x) ((int32) (((x) >> BP_V_P) & BP_M_P)) | |
#define GET_S(x) ((int32) (((x) >> BP_V_S) & BP_M_S)) | |
#define PUT_P(b,x) (((b) & ~BP_P) | ((((t_int64) (x)) & BP_M_P) << BP_V_P)) | |
/* Flags (stored in their own halfword) */ | |
#define F_V_AOV 17 /* arithmetic ovflo */ | |
#define F_V_C0 16 /* carry 0 */ | |
#define F_V_C1 15 /* carry 1 */ | |
#define F_V_FOV 14 /* floating ovflo */ | |
#define F_V_FPD 13 /* first part done */ | |
#define F_V_USR 12 /* user mode */ | |
#define F_V_UIO 11 /* user I/O mode */ | |
#define F_V_PUB 10 /* public mode */ | |
#define F_V_AFI 9 /* addr fail inhibit */ | |
#define F_V_T2 8 /* trap 2 */ | |
#define F_V_T1 7 /* trap 1 */ | |
#define F_V_FXU 6 /* floating exp unflo */ | |
#define F_V_DCK 5 /* divide check */ | |
#define F_AOV (1 << F_V_AOV) | |
#define F_C0 (1 << F_V_C0) | |
#define F_C1 (1 << F_V_C1) | |
#define F_FOV (1 << F_V_FOV) | |
#define F_FPD (1 << F_V_FPD) | |
#define F_USR (1 << F_V_USR) | |
#define F_UIO (1 << F_V_UIO) | |
#define F_PUB (1 << F_V_PUB) | |
#define F_AFI (1 << F_V_AFI) | |
#define F_T2 (1 << F_V_T2) | |
#define F_T1 (1 << F_V_T1) | |
#define F_TR (F_T1 | F_T2) | |
#define F_FXU (1 << F_V_FXU) | |
#define F_DCK (1 << F_V_DCK) | |
#define F_1PR (F_AFI) /* ITS: 1-proceed */ | |
#define F_MASK 0777740 /* all flags */ | |
#define SETF(x) flags = flags | (x) | |
#define CLRF(x) flags = flags & ~(x) | |
#define TSTF(x) (flags & (x)) | |
#define GET_TRAPS(x) (((x) & (F_T2 | F_T1)) >> F_V_T1) | |
/* Priority interrupt system */ | |
#define PI_CPRQ 020000 /* drop prog req */ | |
#define PI_INIT 010000 /* clear pi system */ | |
#define PI_SPRQ 004000 /* set prog req */ | |
#define PI_SENB 002000 /* set enables */ | |
#define PI_CENB 001000 /* clear enables */ | |
#define PI_CON 000400 /* turn off pi system */ | |
#define PI_SON 000200 /* turn on pi system */ | |
#define PI_M_LVL 000177 /* level mask */ | |
#define PI_V_PRQ 18 /* in CONI */ | |
#define PI_V_ACT 8 | |
#define PI_V_ON 7 | |
#define PI_V_ENB 0 | |
/* Arithmetic processor flags */ | |
#define APR_SENB 0100000 /* set enable */ | |
#define APR_CENB 0040000 /* clear enable */ | |
#define APR_CFLG 0020000 /* clear flag */ | |
#define APR_SFLG 0010000 /* set flag */ | |
#define APR_IRQ 0000010 /* int request */ | |
#define APR_M_LVL 0000007 /* pi level */ | |
#define APR_V_FLG 4 /* system flags */ | |
#define APR_M_FLG 0377 | |
#define APRF_ITC (002000 >> APR_V_FLG) /* int console flag */ | |
#define APRF_NXM (000400 >> APR_V_FLG) /* nxm flag */ | |
#define APRF_TIM (000040 >> APR_V_FLG) /* timer request */ | |
#define APRF_CON (000020 >> APR_V_FLG) /* console int */ | |
#define APR_GETF(x) (((x) >> APR_V_FLG) & APR_M_FLG) | |
/* Virtual address, DEC paging */ | |
#define PAG_V_OFF 0 /* offset - must be 0 */ | |
#define PAG_N_OFF 9 /* page offset width */ | |
#define PAG_SIZE 01000 /* page offset size */ | |
#define PAG_M_OFF 0777 /* mask for offset */ | |
#define PAG_V_PN PAG_N_OFF /* page number */ | |
#define PAG_N_PPN (PASIZE - PAG_N_OFF) /* phys pageno width */ | |
#define PAG_M_PPN 03777 /* phys pageno mask */ | |
#define PAG_PPN 03777000 | |
#define PAG_N_VPN (VASIZE - PAG_N_OFF) /* virt pageno width */ | |
#define PAG_M_VPN 0777 /* virt pageno mask */ | |
#define PAG_VPN 0777000 | |
#define PAG_GETOFF(x) ((x) & PAG_M_OFF) | |
#define PAG_GETVPN(x) (((x) >> PAG_V_PN) & PAG_M_VPN) | |
#define PAG_XPTEPA(p,x) (((p) + PAG_GETOFF (x)) & PAMASK) | |
#define PAG_PTEPA(p,x) (((((int32) (p)) & PTE_PPMASK) << PAG_V_PN) + PAG_GETOFF (x)) | |
/* Page table entry, TOPS-10 paging */ | |
#define PTE_T10_A 0400000 /* T10: access */ | |
#define PTE_T10_P 0200000 /* T10: public */ | |
#define PTE_T10_W 0100000 /* T10: writeable */ | |
#define PTE_T10_S 0040000 /* T10: software */ | |
#define PTE_T10_C 0020000 /* T10: cacheable */ | |
#define PTE_PPMASK PAG_M_PPN | |
/* Page table entry, TOPS-20 paging */ | |
#define PTE_T20_V_TYP 33 /* T20: pointer type */ | |
#define PTE_T20_M_TYP 07 | |
#define T20_NOA 0 /* no access */ | |
#define T20_IMM 1 /* immediate */ | |
#define T20_SHR 2 /* shared */ | |
#define T20_IND 3 /* indirect */ | |
#define PTE_T20_W 0020000000000 /* T20: writeable */ | |
#define PTE_T20_C 0004000000000 /* T20: cacheable */ | |
#define PTE_T20_STM 0000077000000 /* T20: storage medium */ | |
#define PTE_T20_V_PMI 18 /* page map index */ | |
#define PTE_T20_M_PMI 0777 | |
#define T20_GETTYP(x) ((int32) (((x) >> PTE_T20_V_TYP) & PTE_T20_M_TYP)) | |
#define T20_GETPMI(x) ((int32) (((x) >> PTE_T20_V_PMI) & PTE_T20_M_PMI)) | |
/* CST entry, TOPS-20 paging */ | |
#define CST_AGE 0770000000000 /* age field */ | |
#define CST_M 0000000000001 /* modified */ | |
/* Page fail word, DEC paging */ | |
#define PF_USER 0400000000000 /* user mode */ | |
#define PF_HARD 0200000000000 /* nx I/O reg */ | |
#define PF_NXM 0370000000000 /* nx memory */ | |
#define PF_T10_A 0100000000000 /* T10: pte A bit */ | |
#define PF_T10_W 0040000000000 /* T10: pte W bit */ | |
#define PF_T10_S 0020000000000 /* T10: pte S bit */ | |
#define PF_T20_DN 0100000000000 /* T20: eval done */ | |
#define PF_T20_M 0040000000000 /* T20: modified */ | |
#define PF_T20_W 0020000000000 /* T20: writeable */ | |
#define PF_WRITE 0010000000000 /* write reference */ | |
#define PF_PUB 0004000000000 /* pte public bit */ | |
#define PF_C 0002000000000 /* pte C bit */ | |
#define PF_VIRT 0001000000000 /* pfl: virt ref */ | |
#define PF_NXMP 0001000000000 /* nxm: phys ref */ | |
#define PF_IO 0000200000000 /* I/O reference */ | |
#define PF_BYTE 0000020000000 /* I/O byte ref */ | |
/* Virtual address, ITS paging */ | |
#define ITS_V_OFF 0 /* offset - must be 0 */ | |
#define ITS_N_OFF 10 /* page offset width */ | |
#define ITS_SIZE 02000 /* page offset size */ | |
#define ITS_M_OFF 01777 /* mask for offset */ | |
#define ITS_V_PN ITS_N_OFF /* page number */ | |
#define ITS_N_PPN (PASIZE- ITS_N_OFF) /* phys pageno width */ | |
#define ITS_M_PPN 01777 /* phys pageno mask */ | |
#define ITS_PPN 03776000 | |
#define ITS_N_VPN (VASIZE - ITS_N_OFF) /* virt pageno width */ | |
#define ITS_M_VPN 0377 /* virt pageno mask */ | |
#define ITS_VPN 0776000 | |
#define ITS_GETVPN(x) (((x) >> ITS_V_PN) & ITS_M_VPN) | |
/* Page table entry, ITS paging */ | |
#define PTE_ITS_V_ACC 16 /* access field */ | |
#define PTE_ITS_M_ACC 03 | |
#define ITS_ACC_NO 0 /* no access */ | |
#define ITS_ACC_RO 1 /* read only */ | |
#define ITS_ACC_RWF 2 /* read-write first */ | |
#define ITS_ACC_RW 3 /* read write */ | |
#define PTE_ITS_AGE 0020000 /* age */ | |
#define PTE_ITS_C 0010000 /* cacheable */ | |
#define PTE_ITS_PPMASK ITS_M_PPN | |
#define ITS_GETACC(x) (((x) >> PTE_ITS_V_ACC) & PTE_ITS_M_ACC) | |
/* Page fail word, ITS paging */ | |
#define PF_ITS_WRITE 0010000000000 /* write reference */ | |
#define PF_ITS_V_ACC 28 /* access from PTE */ | |
/* Page table fill operations */ | |
#define PTF_RD 0 /* read check */ | |
#define PTF_WR 1 /* write check */ | |
#define PTF_MAP 2 /* map instruction */ | |
#define PTF_CON 4 /* console access */ | |
/* User base register */ | |
#define UBR_SETACB 0400000000000 /* set AC blocks */ | |
#define UBR_SETUBR 0100000000000 /* set UBR */ | |
#define UBR_V_CURAC 27 /* current AC block */ | |
#define UBR_V_PRVAC 24 /* previous AC block */ | |
#define UBR_M_AC 07 | |
#define UBR_ACBMASK 0007700000000 | |
#define UBR_V_UBR 0 /* user base register */ | |
#define UBR_N_UBR 11 | |
#define UBR_M_UBR 03777 | |
#define UBR_UBRMASK 0000000003777 | |
#define UBR_GETCURAC(x) ((int32) (((x) >> UBR_V_CURAC) & UBR_M_AC)) | |
#define UBR_GETPRVAC(x) ((int32) (((x) >> UBR_V_PRVAC) & UBR_M_AC)) | |
#define UBR_GETUBR(x) ((int32) (((x) >> UBR_V_UBR) & PAG_M_PPN)) | |
#define UBRWORD (ubr | UBR_SETACB | UBR_SETUBR) | |
/* Executive base register */ | |
#define EBR_V_T20P 14 /* TOPS20 paging */ | |
#define EBR_T20P (1u << EBR_V_T20P) | |
#define EBR_V_PGON 13 /* enable paging */ | |
#define EBR_PGON (1u << EBR_V_PGON) | |
#define EBR_V_EBR 0 /* exec base register */ | |
#define EBR_N_EBR 11 | |
#define EBR_M_EBR 03777 | |
#define EBR_MASK (EBR_T20P | EBR_PGON | (EBR_M_EBR << EBR_V_EBR)) | |
#define EBR_GETEBR(x) ((int32) (((x) >> EBR_V_EBR) & PAG_M_PPN)) | |
#define PAGING (ebr & EBR_PGON) | |
#define T20 (ebr & EBR_T20P) | |
/* AC and mapping contexts | |
There are only two real contexts for selecting the AC block and | |
the memory map: current and previous. However, PXCT allows the | |
choice of current versus previous to be made selectively for | |
various parts of an instruction. The PXCT flags are kept in a | |
dynamic CPU variable. | |
*/ | |
#define EA_PXCT 010 /* eff addr calc */ | |
#define OPND_PXCT 004 /* operand, bdst */ | |
#define EABP_PXCT 002 /* bp eff addr calc */ | |
#define BSTK_PXCT 001 /* stk, bp op, bsrc */ | |
#define XSRC_PXCT 002 /* extend source */ | |
#define XDST_PXCT 001 /* extend destination */ | |
#define MM_CUR 000 /* current context */ | |
#define MM_EA (pflgs & EA_PXCT) | |
#define MM_OPND (pflgs & OPND_PXCT) | |
#define MM_EABP (pflgs & EABP_PXCT) | |
#define MM_BSTK (pflgs & BSTK_PXCT) | |
/* Accumulator access. The AC blocks are kept in array acs[AC_NBLK * AC_NUM]. | |
Two pointers are provided to the bases of the current and previous blocks. | |
Macro AC selects the current AC block; macro XR selects current or previous, | |
depending on whether the selected bit in the "pxct in progress" flag is set. | |
*/ | |
#define AC_NUM 16 /* # AC's/block */ | |
#define AC_NBLK 8 /* # AC blocks */ | |
#define AC(r) (ac_cur[r]) /* AC select current */ | |
#define XR(r,prv) ((prv)? ac_prv[r]: ac_cur[r]) /* AC select context */ | |
#define ADDAC(x,i) (((x) + (i)) & INST_M_AC) | |
#define P1 ADDAC (ac, 1) | |
/* User process table entries */ | |
#define UPT_T10_UMAP 0000 /* T10: user map */ | |
#define UPT_T10_X340 0400 /* T10: exec 340-377 */ | |
#define UPT_TRBASE 0420 /* trap base */ | |
#define UPT_MUUO 0424 /* MUUO block */ | |
#define UPT_MUPC 0425 /* caller's PC */ | |
#define UPT_T10_CTX 0426 /* T10: context */ | |
#define UPT_T20_UEA 0426 /* T20: address */ | |
#define UPT_T20_CTX 0427 /* T20: context */ | |
#define UPT_ENPC 0430 /* MUUO new PC, exec */ | |
#define UPT_1PO 0432 /* ITS 1-proc: old PC */ | |
#define UPT_1PN 0433 /* ITS 1-proc: new PC */ | |
#define UPT_UNPC 0434 /* MUUO new PC, user */ | |
#define UPT_NPCT 1 /* PC offset if trap */ | |
#define UPT_T10_PAG 0500 /* T10: page fail blk */ | |
#define UPT_T20_PFL 0500 /* T20: page fail wd */ | |
#define UPT_T20_OFL 0501 /* T20: flags */ | |
#define UPT_T20_OPC 0502 /* T20: old PC */ | |
#define UPT_T20_NPC 0503 /* T20: new PC */ | |
#define UPT_T20_SCTN 0540 /* T20: section 0 ptr */ | |
/* Exec process table entries */ | |
#define EPT_PIIT 0040 /* PI interrupt table */ | |
#define EPT_UBIT 0100 /* Unibus intr table */ | |
#define EPT_T10_X400 0200 /* T10: exec 400-777 */ | |
#define EPT_TRBASE 0420 /* trap base */ | |
#define EPT_ITS_PAG 0440 /* ITS: page fail blk */ | |
#define EPT_T20_SCTN 0540 /* T20: section 0 ptr */ | |
#define EPT_T10_X000 0600 /* T10: exec 0 - 337 */ | |
/* Microcode constants */ | |
#define UC_INHCST 0400000000000 /* inhibit CST update */ | |
#define UC_UBABLT 0040000000000 /* BLTBU and BLTUB */ | |
#define UC_KIPAGE 0020000000000 /* "KI" paging */ | |
#define UC_KLPAGE 0010000000000 /* "KL" paging */ | |
#define UC_VERDEC (0130 << 18) /* ucode version */ | |
#define UC_VERITS (262u << 18) | |
#define UC_SERDEC 4097 /* serial number */ | |
#define UC_SERITS 1729 | |
#define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ | |
UC_VERDEC | UC_SERDEC) | |
#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) | |
#define UC_HSBDEC 0376000 /* DEC initial HSB */ | |
#define UC_HSBITS 0000500 /* ITS initial HSB */ | |
/* Front end communications region */ | |
#define FE_SWITCH 030 /* halt switch */ | |
#define FE_KEEPA 031 /* keep alive */ | |
#define FE_CTYIN 032 /* console in */ | |
#define FE_CTYOUT 033 /* console out */ | |
#define FE_KLININ 034 /* KLINIK in */ | |
#define FE_KLINOUT 035 /* KLINIK out */ | |
#define FE_RHBASE 036 /* boot: RH11 addr */ | |
#define FE_UNIT 037 /* boot: unit num */ | |
#define FE_MTFMT 040 /* boot: magtape params */ | |
#define FE_CVALID 0400 /* char valid flag */ | |
/* Halfword operations */ | |
#define ADDL(x,y) (((x) + ((y) << 18)) & LMASK) | |
#define ADDR(x,y) (((x) + (y)) & RMASK) | |
#define INCL(x) ADDL (x, 1) | |
#define INCR(x) ADDR (x, 1) | |
#define AOB(x) (INCL (x) | INCR(x)) | |
#define SUBL(x,y) (((x) - ((y) << 18)) & LMASK) | |
#define SUBR(x,y) (((x) - (y)) & RMASK) | |
#define DECL(x) SUBL (x, 1) | |
#define DECR(x) SUBR (x, 1) | |
#define SOB(x) (DECL (x) | DECR(x)) | |
#define LLZ(x) ((x) & LMASK) | |
#define RLZ(x) (((x) << 18) & LMASK) | |
#define RRZ(x) ((x) & RMASK) | |
#define LRZ(x) (((x) >> 18) & RMASK) | |
#define LIT8(x) (((x) & RSIGN)? \ | |
(((x) & 0377)? (-(x) & 0377): 0400): ((x) & 0377)) | |
/* Fullword operations */ | |
#define INC(x) (((x) + 1) & DMASK) | |
#define DEC(x) (((x) - 1) & DMASK) | |
#define SWP(x) ((((x) << 18) & LMASK) | (((x) >> 18) & RMASK)) | |
#define XWD(x,y) (((((d10) (x)) << 18) & LMASK) | (((d10) (y)) & RMASK)) | |
#define SETS(x) ((x) | SIGN) | |
#define CLRS(x) ((x) & ~SIGN) | |
#define TSTS(x) ((x) & SIGN) | |
#define NEG(x) (-(x) & DMASK) | |
#define ABS(x) (TSTS (x)? NEG(x): (x)) | |
#define SXT(x) (TSTS (x)? (x) | ~DMASK: (x)) | |
/* Doubleword operations (on 2-word arrays) */ | |
#define DMOVN(rs) rs[1] = (-rs[1]) & MMASK; \ | |
rs[0] = (~rs[0] + (rs[1] == 0)) & DMASK | |
#define MKDNEG(rs) rs[1] = SETS (-rs[1]) & DMASK; \ | |
rs[0] = (~rs[0] + (rs[1] == MAXNEG)) & DMASK | |
#define DCMPGE(a,b) ((a[0] > b[0]) || ((a[0] == b[0]) && (a[1] >= b[1]))) | |
/* Address operations */ | |
#define ADDA(x,i) (((x) + (i)) & AMASK) | |
#define INCA(x) ADDA (x, 1) | |
/* Unibus adapter control/status register */ | |
#define UBCS_TMO 0400000 /* timeout */ | |
#define UBCS_BMD 0200000 /* bad mem data NI */ | |
#define UBCS_PAR 0100000 /* parity error NI */ | |
#define UBCS_NXD 0040000 /* nx device */ | |
#define UBCS_HI 0004000 /* irq on BR7 or BR6 */ | |
#define UBCS_LO 0002000 /* irq on BR5 or BR4 */ | |
#define UBCS_PWR 0001000 /* power low NI */ | |
#define UBCS_DXF 0000200 /* disable xfer NI*/ | |
#define UBCS_INI 0000100 /* Unibus init */ | |
#define UBCS_RDZ 0030500 /* read as zero */ | |
#define UBCS_RDW 0000277 /* read/write bits */ | |
#define UBCS_V_LHI 3 /* hi pri irq level */ | |
#define UBCS_V_LLO 0 /* lo pri irq level */ | |
#define UBCS_M_PRI 07 | |
#define UBCS_GET_HI(x) (((x) >> UBCS_V_LHI) & UBCS_M_PRI) | |
#define UBCS_GET_LO(x) (((x) >> UBCS_V_LLO) & UBCS_M_PRI) | |
/* Unibus adapter page map */ | |
#define UBANUM 2 /* # of Unibus adapters */ | |
#define UMAP_ASIZE 6 /* address size */ | |
#define UMAP_MEMSIZE (1 << UMAP_ASIZE) /* length */ | |
#define UMAP_AMASK (UMAP_MEMSIZE - 1) | |
#define UMAP_V_RRV 30 /* read reverse */ | |
#define UMAP_V_DSB 29 /* 16b on NPR read */ | |
#define UMAP_V_FST 28 /* fast transfer */ | |
#define UMAP_V_VLD 27 /* valid flag */ | |
#define UMAP_RRV (1 << UMAP_V_RRV) | |
#define UMAP_DSB (1 << UMAP_V_DSB) | |
#define UMAP_FST (1 << UMAP_V_FST) | |
#define UMAP_VLD (1 << UMAP_V_VLD) | |
#define UMAP_V_FLWR 14 /* flags as written */ | |
#define UMAP_V_FLRD 27 /* flags as stored */ | |
#define UMAP_M_FL 017 | |
#define UMAP_V_PNWR 0 /* page num, write */ | |
#define UMAP_V_PNRD 9 /* page num, read */ | |
#define UMAP_M_PN 03777 | |
#define UMAP_MASK ((UMAP_M_FL << UMAP_V_FLRD) | (UMAP_M_PN << UMAP_V_PNRD)) | |
#define UMAP_POSFL(x) (((x) & (UMAP_M_FL << UMAP_V_FLWR)) \ | |
<< (UMAP_V_FLRD - UMAP_V_FLWR)) | |
#define UMAP_POSPN(x) (((x) & (UMAP_M_PN << UMAP_V_PNWR)) \ | |
<< (UMAP_V_PNRD - UMAP_V_PNWR)) | |
/* Unibus I/O constants */ | |
#define READ 0 /* PDP11 compatible */ | |
/* #define READC 1 /* console read */ | |
#define WRITE 2 | |
/* #define WRITEC 3 /* console write */ | |
#define WRITEB 4 | |
#define IO_V_UBA 18 /* UBA in I/O addr */ | |
#define IO_N_UBA 16 /* max num of UBA's */ | |
#define IO_M_UBA (IO_N_UBA - 1) | |
#define IO_UBA1 (1 << IO_V_UBA) | |
#define IO_UBA3 (3 << IO_V_UBA) | |
#define GET_IOUBA(x) (((x) >> IO_V_UBA) & IO_M_UBA) | |
/* Device information block */ | |
struct pdp_dib { | |
uint32 enb; /* enabled */ | |
uint32 ba; /* base addr */ | |
uint32 lnt; /* length */ | |
t_stat (*rd)(int32 *dat, int32 ad, int32 md); | |
t_stat (*wr)(int32 dat, int32 ad, int32 md); }; | |
typedef struct pdp_dib DIB; | |
/* DZ11 parameters */ | |
#define DZ_MUXES 4 /* max # of muxes */ | |
#define DZ_LINES 8 /* lines per mux */ | |
/* I/O page layout */ | |
#define IOPAGEBASE 0760000 /* I/O page base */ | |
#define IOBA_UBMAP 0763000 | |
#define IOBA_UBMAP1 (IO_UBA1 + IOBA_UBMAP) /* Unibus 1 map */ | |
#define IOLN_UBMAP1 0100 | |
#define IOBA_UBCS1 (IO_UBA1 + 0763100) /* Unibus 1 c/s reg */ | |
#define IOLN_UBCS1 001 | |
#define IOBA_UBMNT1 (IO_UBA1 + 0763101) /* Unibus 1 maint reg */ | |
#define IOLN_UBMNT1 001 | |
#define IOBA_RP (IO_UBA1 + 0776700) /* RH11/disk */ | |
#define IOLN_RP 050 | |
#define IOBA_DZ (IO_UBA3 + 0760010) /* DZ11 */ | |
#define IOLN_DZ 010 | |
#define IOBA_TCU (IO_UBA3 + 0760770) /* TCU150 */ | |
#define IOLN_TCU 006 | |
#define IOBA_UBMAP3 (IO_UBA3 + IOBA_UBMAP) /* Unibus 3 map */ | |
#define IOLN_UBMAP3 0100 | |
#define IOBA_UBCS3 (IO_UBA3 + 0763100) /* Unibus 3 c/s reg */ | |
#define IOLN_UBCS3 001 | |
#define IOBA_UBMNT3 (IO_UBA3 + 0763101) /* Unibus 3 maint reg */ | |
#define IOLN_UBMNT3 001 | |
#define IOBA_TU (IO_UBA3 + 0772440) /* RH11/tape */ | |
#define IOLN_TU 034 | |
#define IOBA_LP20 (IO_UBA3 + 0775400) /* LP20 */ | |
#define IOLN_LP20 020 | |
#define IOBA_PT (IO_UBA3 + 0777550) /* PC11 */ | |
#define IOLN_PT 010 | |
/* Common Unibus CSR flags */ | |
#define CSR_V_GO 0 /* go */ | |
#define CSR_V_IE 6 /* interrupt enable */ | |
#define CSR_V_DONE 7 /* done */ | |
#define CSR_V_BUSY 11 /* busy */ | |
#define CSR_V_ERR 15 /* error */ | |
#define CSR_GO (1u << CSR_V_GO) | |
#define CSR_IE (1u << CSR_V_IE) | |
#define CSR_DONE (1u << CSR_V_DONE) | |
#define CSR_BUSY (1u << CSR_V_BUSY) | |
#define CSR_ERR (1u << CSR_V_ERR) | |
/* I/O system definitions, lifted from the PDP-11 simulator | |
Interrupt assignments, priority is right to left | |
<3:0> = BR7 | |
<7:4> = BR6 | |
<19:8> = BR5 | |
<30:20> = BR4 | |
*/ | |
#define INT_V_RP 6 /* RH11/RP,RM drives */ | |
#define INT_V_TU 7 /* RH11/TM03/TU45 */ | |
#define INT_V_DZRX 16 /* DZ11 */ | |
#define INT_V_DZTX 17 | |
#define INT_V_PTR 24 /* PC11 */ | |
#define INT_V_PTP 25 | |
#define INT_V_LP20 26 /* LPT20 */ | |
#define INT_RP (1u << INT_V_RP) | |
#define INT_TU (1u << INT_V_TU) | |
#define INT_DZRX (1u << INT_V_DZRX) | |
#define INT_DZTX (1u << INT_V_DZTX) | |
#define INT_PTR (1u << INT_V_PTR) | |
#define INT_PTP (1u << INT_V_PTP) | |
#define INT_LP20 (1u << INT_V_LP20) | |
#define IPL_RP 6 /* int levels */ | |
#define IPL_TU 6 | |
#define IPL_DZRX 5 | |
#define IPL_DZTX 5 | |
#define IPL_PTR 4 | |
#define IPL_PTP 4 | |
#define IPL_LP20 4 | |
#define INT_UB1 INT_RP /* on Unibus 1 */ | |
#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */ | |
#define INT_IPL7 0x0000000F /* int level masks */ | |
#define INT_IPL6 0x000000F0 | |
#define INT_IPL5 0x000FFF00 | |
#define INT_IPL4 0x3FF00000 | |
#define VEC_PTR 0070 /* interrupt vectors */ | |
#define VEC_PTP 0074 | |
#define VEC_TU 0224 | |
#define VEC_RP 0254 | |
#define VEC_DZRX 0340 | |
#define VEC_DZTX 0344 | |
#define VEC_LP20 0754 | |
#define IREQ(dv) int_req | |
#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv) | |
#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv) | |
/* Function prototypes */ | |
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); | |
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); | |
t_stat set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); | |
t_bool dev_conflict (uint32 nba, DIB *curr); |