/* pdp10_defs.h: PDP-10 simulator definitions

   Copyright (c) 1993-2017, 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.

   19-Jan-17    RMS     Fixed CD11 definition (Mark Pizzolato)
   30-Jun-13    RMS     Fixed IPL4 mask definition (Tim Litt)
   22-May-10    RMS     Added check for 64b addresses
   01-Feb-07    RMS     Added CD support
   29-Oct-06    RMS     Added clock coscheduling function
   29-Dec-03    RMS     Added Q18 definition for PDP11 compatibility
   19-May-03    RMS     Revised for new conditional compilation scheme
   09-Jan-03    RMS     Added DEUNA/DELUA support
   29-Sep-02    RMS     Added variable vector, RX211 support
   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
*/

#ifndef PDP10_DEFS_H_
#define PDP10_DEFS_H_  0

#ifndef VM_PDP10
#define VM_PDP10        0
#endif

#include "sim_defs.h"                                   /* simulator defns */
#include <setjmp.h>

#if defined(USE_ADDR64)
#error "PDP-10 does not support 64b addresses!"
#endif

/* 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_CONSOLE    12                              /* FE halt */
#define STOP_IOALIGN    13                              /* DMA word access to odd address */
#define STOP_UNKNOWN    14                              /* 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_V_T20      (UNIT_V_UF + 1)                 /* TOPS-20 */
#define UNIT_V_KLAD     (UNIT_V_UF + 2)                 /* diagnostics */
#define UNIT_ITS        (1 << UNIT_V_ITS)
#define UNIT_T20        (1 << UNIT_V_T20)
#define UNIT_KLAD       (1 << UNIT_V_KLAD)
#define Q_T10           ((cpu_unit.flags & (UNIT_ITS|UNIT_T20|UNIT_KLAD)) == 0)
#define Q_ITS           (cpu_unit.flags & UNIT_ITS)
#define Q_T20           (cpu_unit.flags & UNIT_T20)
#define Q_KLAD          (cpu_unit.flags & UNIT_KLAD)

/* 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           INT64_C(0777777000000)          /* left mask */
#define LSIGN           INT64_C(0400000000000)          /* left sign */
#define RMASK           INT64_C(0000000777777)          /* right mask */
#define RSIGN           INT64_C(0000000400000)          /* right sign */
#define DMASK           INT64_C(0777777777777)          /* data mask */
#define SIGN            INT64_C(0400000000000)          /* sign */
#define MMASK           INT64_C(0377777777777)          /* magnitude mask */
#define ONES            INT64_C(0777777777777)
#define MAXPOS          INT64_C(0377777777777)
#define MAXNEG          INT64_C(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          INT64_C(077)
#define BP_P            INT64_C(0770000000000)
#define BP_V_S          24                              /* size */
#define BP_M_S          INT64_C(077)
#define BP_S            INT64_C(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   INT64_C(33)                     /* T20: pointer type */
#define PTE_T20_M_TYP   INT64_C(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       INT64_C(0020000000000)          /* T20: writeable */
#define PTE_T20_C       INT64_C(0004000000000)          /* T20: cacheable */
#define PTE_T20_STM     INT64_C(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         INT64_C(0770000000000)          /* age field */
#define CST_M           INT64_C(0000000000001)          /* modified */

/* Page fail word, DEC paging */

#define PF_USER         INT64_C(0400000000000)          /* user mode */
#define PF_HARD         INT64_C(0200000000000)          /* nx I/O reg */
#define PF_NXM          INT64_C(0370000000000)          /* nx memory */
#define PF_T10_A        INT64_C(0100000000000)          /* T10: pte A bit */
#define PF_T10_W        INT64_C(0040000000000)          /* T10: pte W bit */
#define PF_T10_S        INT64_C(0020000000000)          /* T10: pte S bit */
#define PF_T20_DN       INT64_C(0100000000000)          /* T20: eval done */
#define PF_T20_M        INT64_C(0040000000000)          /* T20: modified */
#define PF_T20_W        INT64_C(0020000000000)          /* T20: writeable */
#define PF_WRITE        INT64_C(0010000000000)          /* write reference */
#define PF_PUB          INT64_C(0004000000000)          /* pte public bit */
#define PF_C            INT64_C(0002000000000)          /* pte C bit */
#define PF_VIRT         INT64_C(0001000000000)          /* pfl: virt ref */
#define PF_NXMP         INT64_C(0001000000000)          /* nxm: phys ref */
#define PF_IO           INT64_C(0000200000000)          /* I/O reference */
#define PF_BYTE         INT64_C(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    INT64_C(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      INT64_C(0400000000000)          /* set AC blocks */
#define UBR_SETUBR      INT64_C(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     INT64_C(0007700000000)
#define UBR_V_UBR       0                               /* user base register */
#define UBR_N_UBR       11
#define UBR_M_UBR       03777
#define UBR_UBRMASK     INT64_C(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 T20PAG          (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       INT64_C(0400000000000)          /* inhibit CST update */
#define UC_UBABLT       INT64_C(0040000000000)          /* BLTBU and BLTUB */
#define UC_KIPAGE       INT64_C(0020000000000)          /* "KI" paging */
#define UC_KLPAGE       INT64_C(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)
#define UC_AIDITS       (UC_KIPAGE | UC_VERITS)

#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 */

#define VEC_DEVMAX      8                               /* max device vec */

struct pdp_dib {
    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);
    int32               vnum;                           /* vectors: number */
    int32               vloc;                           /* locator */
    int32               vec;                            /* value */
    int32               (*ack[VEC_DEVMAX])(void);       /* ack routines */
    uint32              ulnt;                           /* IO length per unit */
    uint32              flags;                          /* Special flags */
#define DIB_M_REGSIZE   03                              /* Device register size */
#define DIB_REG16BIT     00
#define DIB_REG18BIT     01
};

typedef struct pdp_dib DIB;

/* I/O system parameters */

#define DZ_MUXES        4                               /* default # of muxes */
#define MAX_DZ_MUXES    4                               /* max # of muxes */
#define KMC_UNITS       1                               /* max # of KMCs */
#define INITIAL_KMCS    0                               /* Number initially enabled */
#define DUP_LINES       4                               /* max # of DUP11's */
#define DIB_MAX         100                             /* max DIBs */

#define DEV_V_UBUS      (DEV_V_UF + 0)                  /* Unibus */
#define DEV_V_QBUS      (DEV_V_UF + 1)                  /* Qbus */
#define DEV_V_Q18       (DEV_V_UF + 2)                  /* Qbus, mem <= 256KB */
#define DEV_UBUS        (1u << DEV_V_UBUS)
#define DEV_QBUS        (1u << DEV_V_QBUS)
#define DEV_Q18         (1u << DEV_V_Q18)

#define UNIBUS          TRUE                            /* 18b only */

#define DEV_RDX         8                               /* default device radix */

/* I/O page layout */

#define IOPAGEBASE      (IO_UBA3 + 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_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_AUTO       0                               /* Set by Auto Configure */

/* 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_KMCA      8                               /* KMC11 */
#define INT_V_KMCB      9
#define INT_V_DMCRX     10                              /* DMC11/DMR11 */
#define INT_V_DMCTX     11
#define INT_V_XU        15                              /* DEUNA/DELUA */
#define INT_V_DZRX      16                              /* DZ11 */
#define INT_V_DZTX      17
#define INT_V_RY        18                              /* RX211 */
#define INT_V_PTR       24                              /* PC11 */
#define INT_V_PTP       25
#define INT_V_LP20      26                              /* LPT20 */
#define INT_V_CR        27                              /* CD20 (CD11) */
#define INT_V_DUPRX     28                              /* DUP11 */
#define INT_V_DUPTX     29
#define INT_V_CH        30                              /* CH11 Chaosnet */

#define INT_RP          (1u << INT_V_RP)
#define INT_TU          (1u << INT_V_TU)
#define INT_KMCA        (1u << INT_V_KMCA)
#define INT_KMCB        (1u << INT_V_KMCB)
#define INT_DMCRX       (1u << INT_V_DMCRX)
#define INT_DMCTX       (1u << INT_V_DMCTX)
#define INT_XU          (1u << INT_V_XU)
#define INT_DZRX        (1u << INT_V_DZRX)
#define INT_DZTX        (1u << INT_V_DZTX)
#define INT_RY          (1u << INT_V_RY)
#define INT_PTR         (1u << INT_V_PTR)
#define INT_PTP         (1u << INT_V_PTP)
#define INT_LP20        (1u << INT_V_LP20)
#define INT_CR          (1u << INT_V_CD)
#define INT_DUPRX       (1u << INT_V_DUPRX)
#define INT_DUPTX       (1u << INT_V_DUPTX)
#define INT_CH          (1u << INT_V_CH)

#define IPL_RP          6                               /* int levels */
#define IPL_TU          6
#define IPL_KMCA        5
#define IPL_KMCB        5
#define IPL_DMCRX       5
#define IPL_DMCTX       5
#define IPL_DZRX        5
#define IPL_DZTX        5
#define IPL_RY          5
#define IPL_DUPRX       5
#define IPL_DUPTX       5
#define IPL_PTR         4
#define IPL_PTP         4
#define IPL_LP20        4
#define IPL_CR          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        0x7FF00000

#define VEC_TU          0224                            /* interrupt vectors */
#define VEC_RP          0254
#define VEC_LP20        0754
#define VEC_AUTO        0                               /* Set by Auto Configure */

#define IVCL(dv)        (INT_V_##dv)
#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 */

int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
int32 Map_ReadW18 (uint32 ba, int32 bc, uint32 *buf);
int32 Map_WriteB (uint32 ba, int32 bc, const uint8 *buf);
int32 Map_WriteW (uint32 ba, int32 bc, const uint16 *buf);
int32 Map_WriteW18 (uint32 ba, int32 bc, const uint32 *buf);
void uba_debug_dma_in (uint32 ba, a10 pa_start, a10 pa_end);
void uba_debug_dma_out (uint32 ba, a10 pa_start, a10 pa_end);
void uba_debug_dma_nxm (const char *msg, a10 pa10, uint32 ba, int32 bc);

extern d10 Read (a10 ea, int32 prv);                    /* read, read check */
extern d10 ReadM (a10 ea, int32 prv);                   /* read, write check */
extern d10 ReadE (a10 ea);                              /* read, exec */
extern d10 ReadP (a10 ea);                              /* read, physical */
extern void Write (a10 ea, d10 val, int32 prv);         /* write */
extern void WriteE (a10 ea, d10 val);                   /* write, exec */
extern void WriteP (a10 ea, d10 val);                   /* write, physical */
extern t_bool AccViol (a10 ea, int32 prv, int32 mode);  /* access check */

t_stat set_addr (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat set_addr_flt (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat set_vec (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat show_vec_mux (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat auto_config (const char *name, int32 num);

extern d10 *ac_cur;                                     /* current AC block */
extern int32 flags;                                     /* flags */
extern const int32 pi_l2bit[8];
extern const d10 bytemask[64];
extern int32 int_req;
extern d10 *M;                                          /* memory */
extern a10 pager_PC;                                    /* pager: saved PC */
extern d10 pager_word;                                  /* pager: error word */
extern UNIT cpu_unit;
extern int32 apr_flg;
extern jmp_buf save_env;

#endif
