/* hp2100_cpu.h: HP 2100 CPU declarations

   Copyright (c) 2005-2016, Robert M. Supnik
   Copyright (c) 2017,      J. David Bryan

   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 THE
   AUTHORS 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 names of the authors shall not be
   used in advertising or otherwise to promote the sale, use or other dealings
   in this Software without prior written authorization from the authors.

   22-Jul-17    JDB     Renamed "intaddr" to CIR; added IR
   14-Jul-17    JDB     Removed calc_defer() prototype
   11-Jul-17    JDB     Moved "ibl_copy" and renamed to "cpu_ibl"
   10-Jul-17    JDB     Renamed the global routine "iogrp" to "cpu_iog"
   07-Jul-17    JDB     Changed "iotrap" from uint32 to t_bool
   07-Jun-17    JDB     Added maximum instruction length for sim_emax definition
   06-Jun-17    JDB     Added instruction group decoding macros
   04-Apr-17    JDB     Added "cpu_configuration" for symbolic ex/dep validation
   08-Mar-17    JDB     Added "cpu_speed" for TBG service access
   15-Feb-17    JDB     Deleted unneeded guard macro definition
   05-Aug-16    JDB     Renamed the P register from "PC" to "PR"
   24-Dec-14    JDB     Added casts for explicit downward conversions
   18-Mar-13    JDB     Added declarations for the MP abort handler and CPU registers
   14-Mar-13    MP      Changed guard macro name to avoid reserved namespace
   03-Jan-10    RMS     Changed declarations of mp_control, mp_mefvv, for VMS compiler
   15-Jul-08    JDB     Rearranged declarations with hp2100_cpu.c and hp2100_defs.h
   26-Jun-08    JDB     Added mp_control to CPU state externals
   24-Apr-08    JDB     Added calc_defer() prototype
   20-Apr-08    JDB     Added DEB_VIS and DEB_SIG debug flags
   26-Nov-07    JDB     Added extern sim_deb, cpu_dev, DEB flags for debug printouts
   05-Nov-07    JDB     Added extern intaddr, mp_viol, mp_mevff, calc_int, dev_ctl,
                        ReadIO, WriteIO for RTE-6/VM microcode support
   16-Dec-06    JDB     Added UNIT_2115 and UNIT_2114
   16-Oct-06    JDB     Moved ReadF to hp2100_cpu1.c
   26-Sep-06    JDB     Added CPU externs for microcode simulators
   16-Aug-06    JDB     Added UNIT_EMA for future RTE-4 EMA microcode
                        Added UNIT_VMA for future RTE-6 VMA and OS microcode
                        Added UNIT_1000_F for future F-Series support
   09-Aug-06    JDB     Added UNIT_DBI for double integer microcode
   21-Jan-05    JDB     Reorganized CPU option flags
   14-Jan-05    RMS     Cloned from hp2100_cpu.c

   CPU models are broken down into family, type, and series to facilitate option
   validation.  Bit 3 encodes the family, bit 2 encodes the type, and bits 1:0
   encode the series within the type.
*/



#include <setjmp.h>



/* Memory access macros.

   These macros provide simplified function call sequences for memory reads and
   writes by the CPU.  They supply the correct access classification.  The
   following macro routines are provided:

     Name     Action
     -------  ------------------------------------------------------------
     ReadF    Read an instruction word using the current map
     ReadW    Read a data word using the current map
     ReadWA   Read a data word using the alternate map
     ReadS    Read a data word using the system map
     ReadU    Read a data word using the user map

     ReadB    Read a data byte using the current map
     ReadBA   Read a data byte using the alternate map

     WriteW   Write a data word using the current map
     WriteWA  Write a data word using the alternate map
     WriteS   Write a data word using the system map
     WriteU   Write a data word using the user map

     WriteB   Write a data byte using the current map
     WriteBA  Write a data byte using the alternate map

   The MP_ABORT macro performs a "longjmp" to the memory protect handler in the
   instruction execution loop.  The parameter is the address of the violation.
   The conditions that initiate a MP abort must be tested explicitly before
   calling MP_ABORT.
*/

#define ReadF(a)            mem_read (&cpu_dev, Fetch, a)
#define ReadW(a)            mem_read (&cpu_dev, Data, a)
#define ReadWA(a)           mem_read (&cpu_dev, Data_Alternate, a)
#define ReadS(a)            mem_read (&cpu_dev, Data_System, a)
#define ReadU(a)            mem_read (&cpu_dev, Data_User, a)

#define ReadB(a)            mem_read_byte (&cpu_dev, Data, a)
#define ReadBA(a)           mem_read_byte (&cpu_dev, Data_Alternate, a)

#define WriteW(a,v)         mem_write (&cpu_dev, Data, a, v)
#define WriteWA(a,v)        mem_write (&cpu_dev, Data_Alternate, a, v)
#define WriteS(a,v)         mem_write (&cpu_dev, Data_System, a, v)
#define WriteU(a,v)         mem_write (&cpu_dev, Data_User, a, v)

#define WriteB(a,v)         mem_write_byte (&cpu_dev, Data, a, v)
#define WriteBA(a,v)        mem_write_byte (&cpu_dev, Data_Alternate, a, v)

#define MP_ABORT(va)        longjmp (save_env, (va))


/* CPU tracing flags */

#define DEBUG_NOOS          (1u << 0)           /* configure RTE-6/VM not to use OS firmware */

#define TRACE_INSTR         (1u << 1)           /* trace instruction executions */
#define TRACE_DATA          (1u << 2)           /* trace memory data accesses */
#define TRACE_FETCH         (1u << 3)           /* trace memory instruction fetches */
#define TRACE_REG           (1u << 4)           /* trace register values */
#define TRACE_OPND          (1u << 5)           /* trace instruction operands */
#define TRACE_EXEC          (1u << 6)           /* trace matching instruction execution states */
#define TRACE_SR            (1u << 7)           /* trace service requests received */

#define TRACE_ALL           ~DEBUG_NOOS         /* trace everything */

#define DMS_FORMAT          "%c %04o %05o  %06o  "      /* map | physical page | logical address | value format */
#define REGA_FORMAT         "%c **** %05o  %06o  "      /* protection | fence | S register format for working registers */
#define REGB_FORMAT         "%c **** *****  ******  "   /* protection format for MP/MEM registers */
#define OPND_FORMAT         "* **** %05o  %06o  "       /* address | data format for operands */
#define EXEC_FORMAT         "********************  "    /* null format for EXEC separation */


/* CPU stop flags */

#define SS_INHIBIT          (t_stat) (~0u)              /* inhibit stops for the first instruction executed */

#define STOP(s)             ((s) & ~cpu_ss_inhibit)     /* stop if the condition is enabled and not inhibited */


/* Supported breakpoint switches */

#define BP_EXEC             (SWMASK ('E'))      /* an execution breakpoint */
#define BP_ENONE            (SWMASK ('N'))      /* an execution breakpoint when mapping is off */
#define BP_ESYS             (SWMASK ('S'))      /* an execution breakpoint in the system map */
#define BP_EUSER            (SWMASK ('U'))      /* an execution breakpoint in the user map */

#define BP_SUPPORTED        (BP_EXEC | BP_ENONE | BP_ESYS | BP_EUSER)


/* CPU unit flags.

      31  30  29  28  27  26  25  24  23  22  21  20  19  18  17  16
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | R | - | G | V | O | E | D | F | M | I | P | U |   CPU model   |
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
                                                     | f | t | series|
                                                     +---+---+---+---+

   Where:

     R = reserved
     G = SIGNAL/1000 firmware is present
     V = Vector Instruction Set firmware is present
     O = RTE-6/VM VMA and OS firmware is present
     E = RTE-IV EMA firmware is present
     D = Double Integer firmware is present
     F = Fast FORTRAN Processor firmware is present
     M = Dynamic Mapping System firmware is present
     I = 2000 I/O Processor firmware is present
     P = Floating Point hardware or firmware is present
     U = Extended Arithmetic Unit is present
     f = CPU family
     t = CPU type

   CPU Models:

     0 0 00 = HP 2116
     0 0 01 = HP 2115
     0 0 10 = HP 2114
     0 0 11 = unused

     0 1 00 = HP 2100
     0 1 01 = unused
     0 1 10 = unused
     0 1 11 = unused

     1 0 00 = HP 1000 M-Series
     1 0 01 = HP 1000 E-Series
     1 0 10 = HP 1000 F-Series
     1 0 11 = unused

     1 1 00 = unused (1000 A-Series)
     1 1 01 = unused (1000 A-Series)
     1 1 10 = unused (1000 A-Series)
     1 1 11 = unused (1000 A-Series)

*/

#define CPU_V_SERIES        0
#define CPU_V_TYPE          2
#define CPU_V_FAMILY        3

#define FAMILY_21XX         (0 << CPU_V_FAMILY)
#define FAMILY_1000         (1 << CPU_V_FAMILY)

#define TYPE_211X           (0 << CPU_V_TYPE)       /* 2114, 2115, 2116 */
#define TYPE_2100           (1 << CPU_V_TYPE)       /* 2100A, 2100S */
#define TYPE_1000MEF        (0 << CPU_V_TYPE)       /* 1000-M, 1000-E, 1000-F */
#define TYPE_1000AL         (1 << CPU_V_TYPE)       /* 1000-L, A600, A700, A900, A990 */

#define SERIES_16           (0 << CPU_V_SERIES)     /* 211X */
#define SERIES_15           (1 << CPU_V_SERIES)     /* 211X */
#define SERIES_14           (2 << CPU_V_SERIES)     /* 211X */
#define SERIES_00           (0 << CPU_V_SERIES)     /* 2100 */
#define SERIES_M            (0 << CPU_V_SERIES)     /* 1000 */
#define SERIES_E            (1 << CPU_V_SERIES)     /* 1000 */
#define SERIES_F            (2 << CPU_V_SERIES)     /* 1000 */


/* CPU unit flags */

#define UNIT_M_CPU          017                     /* CPU model mask  [3:0] */
#define UNIT_M_TYPE         014                     /* CPU type mask   [3:2] */
#define UNIT_M_FAMILY       010                     /* CPU family mask [3:3] */

#define UNIT_V_CPU          (UNIT_V_UF + 0)         /* CPU model bits 0-3 */
#define UNIT_V_EAU          (UNIT_V_UF + 4)         /* EAU installed */
#define UNIT_V_FP           (UNIT_V_UF + 5)         /* FP installed */
#define UNIT_V_IOP          (UNIT_V_UF + 6)         /* IOP installed */
#define UNIT_V_DMS          (UNIT_V_UF + 7)         /* DMS installed */
#define UNIT_V_FFP          (UNIT_V_UF + 8)         /* FFP installed */
#define UNIT_V_DBI          (UNIT_V_UF + 9)         /* DBI installed */
#define UNIT_V_EMA          (UNIT_V_UF + 10)        /* RTE-4 EMA installed */
#define UNIT_V_VMAOS        (UNIT_V_UF + 11)        /* RTE-6 VMA/OS installed */
#define UNIT_V_VIS          (UNIT_V_UF + 12)        /* VIS installed */
#define UNIT_V_SIGNAL       (UNIT_V_UF + 13)        /* SIGNAL/1000 installed */
/* Future microcode expansion; reuse flags bottom-up if needed */
#define UNIT_V_DS           (UNIT_V_UF + 14)        /* DS installed */


/* Unit models */

#define UNIT_MODEL_MASK     (UNIT_M_CPU << UNIT_V_CPU)

#define UNIT_2116           ((FAMILY_21XX | TYPE_211X    | SERIES_16) << UNIT_V_CPU)
#define UNIT_2115           ((FAMILY_21XX | TYPE_211X    | SERIES_15) << UNIT_V_CPU)
#define UNIT_2114           ((FAMILY_21XX | TYPE_211X    | SERIES_14) << UNIT_V_CPU)
#define UNIT_2100           ((FAMILY_21XX | TYPE_2100    | SERIES_00) << UNIT_V_CPU)
#define UNIT_1000_M         ((FAMILY_1000 | TYPE_1000MEF | SERIES_M)  << UNIT_V_CPU)
#define UNIT_1000_E         ((FAMILY_1000 | TYPE_1000MEF | SERIES_E)  << UNIT_V_CPU)
#define UNIT_1000_F         ((FAMILY_1000 | TYPE_1000MEF | SERIES_F)  << UNIT_V_CPU)


/* Unit types */

#define UNIT_TYPE_MASK      (UNIT_M_TYPE << UNIT_V_CPU)

#define UNIT_TYPE_211X      ((FAMILY_21XX | TYPE_211X)    << UNIT_V_CPU)
#define UNIT_TYPE_2100      ((FAMILY_21XX | TYPE_2100)    << UNIT_V_CPU)
#define UNIT_TYPE_1000      ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)


/* Unit families */

#define UNIT_FAMILY_MASK    (UNIT_M_FAMILY << UNIT_V_CPU)

#define UNIT_FAMILY_21XX    (FAMILY_21XX << UNIT_V_CPU)
#define UNIT_FAMILY_1000    (FAMILY_1000 << UNIT_V_CPU)


/* Unit accessors */

#define UNIT_CPU_MODEL      (cpu_unit.flags & UNIT_MODEL_MASK)
#define UNIT_CPU_TYPE       (cpu_unit.flags & UNIT_TYPE_MASK)
#define UNIT_CPU_FAMILY     (cpu_unit.flags & UNIT_FAMILY_MASK)

#define CPU_MODEL_INDEX     (UNIT_CPU_MODEL >> UNIT_V_CPU)


/* Unit features */

#define UNIT_EAU            (1u << UNIT_V_EAU)
#define UNIT_FP             (1u << UNIT_V_FP)
#define UNIT_IOP            (1u << UNIT_V_IOP)
#define UNIT_DMS            (1u << UNIT_V_DMS)
#define UNIT_FFP            (1u << UNIT_V_FFP)
#define UNIT_DBI            (1u << UNIT_V_DBI)
#define UNIT_EMA            (1u << UNIT_V_EMA)
#define UNIT_VMAOS          (1u << UNIT_V_VMAOS)
#define UNIT_VIS            (1u << UNIT_V_VIS)
#define UNIT_DS             (1u << UNIT_V_DS)
#define UNIT_SIGNAL         (1u << UNIT_V_SIGNAL)

#define UNIT_EMA_VMA        (UNIT_EMA | UNIT_VMAOS)

#define UNIT_OPTS           (UNIT_EAU | UNIT_FP    | UNIT_IOP | \
                             UNIT_DMS | UNIT_FFP   | UNIT_DBI | \
                             UNIT_EMA | UNIT_VMAOS | \
                             UNIT_VIS | UNIT_DS    | UNIT_SIGNAL)

/* "Pseudo-option" flags used only for option testing; never set into UNIT structure. */

#define UNIT_V_PFAIL        (UNIT_V_UF - 1)                 /* Power fail installed */
#define UNIT_V_DMA          (UNIT_V_UF - 2)                 /* DMA installed */
#define UNIT_V_MP           (UNIT_V_UF - 3)                 /* Memory protect installed */

#define UNIT_PFAIL          (1 << UNIT_V_PFAIL)
#define UNIT_DMA            (1 << UNIT_V_DMA)
#define UNIT_MP             (1 << UNIT_V_MP)

#define UNIT_NONE           0                               /* no options */


/* CPU configuration model flags */

#define CPU_MASK            D16_MASK

#define CPU_2116            (1u << (FAMILY_21XX | TYPE_211X    | SERIES_16))
#define CPU_2115            (1u << (FAMILY_21XX | TYPE_211X    | SERIES_15))
#define CPU_2114            (1u << (FAMILY_21XX | TYPE_211X    | SERIES_14))
#define CPU_2100            (1u << (FAMILY_21XX | TYPE_2100    | SERIES_00))
#define CPU_1000_M          (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_M))
#define CPU_1000_E          (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_E))
#define CPU_1000_F          (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_F))

#define CPU_1000            (CPU_1000_M | CPU_1000_E | CPU_1000_F)

#define CPU_ALL             (CPU_2116   | CPU_2115   | CPU_2114 |  \
                             CPU_2100   |                          \
                             CPU_1000_M | CPU_1000_E | CPU_1000_F)

/* PC queue. */

#define PCQ_SIZE        64                              /* must be 2**n */
#define PCQ_MASK        (PCQ_SIZE - 1)
#define PCQ_ENTRY       pcq [pcq_p = (pcq_p - 1) & PCQ_MASK] = (uint16) err_PC


/* Maximum instruction length.

   This value is the length in words of the longest machine instruction.  It is
   used to set "sim_emax", which, in turn, is used to allocate the "sim_eval"
   array.  This array holds the words of a machine instruction to be formatted
   and printed or to be parsed and stored.

   The longest instruction in the 21xx/1000 family is the [D]VPIV (vector pivot)
   instruction in the Vector Instruction Set.
*/

#define MAX_INSTR_LENGTH    10


/* Instruction group decoding.

   The HP 21xx/1000 instruction set consists of five groups: the Memory
   Reference Group (MRG), the Shift-Rotate Group (SRG), the Alter-Skip Group
   (ASG), the I/O Group (IOG), and the Macro Group (MAC).  Group membership is
   determined by a multi-level decoding of bits 15-10, as follows:

      Bits
     15-10   Group
     ------  -----
     xnnnx    MRG
     00000    SRG
     00001    ASG
     10001    IOG
     10000    MAC

   Where:

     x = 0 or 1
     n = any collective value other than 0

   The MAC group is subdivided into the Extended Arithmetic Group (EAG), the
   first User Instruction Group (UIG-0), and the second User Instruction Group
   (UIG-1).  Decoding is by bits 11-8, as follows (note that bit 10 = 0 for the
   MAC group):

     Bits
     11-8  Group
     ----  -----
     0000  EAG
     0001  EAG
     0010  EAG
     0011  UIG-1
     1000  EAG
     1001  EAG
     1010  UIG-0
     1011  UIG-1

   Bits 7-4 further decode the UIG instruction feature group.
*/

#define GROUP_MASK          0172000u            /* instruction group mask */

#define MRG                 0070000u            /* Memory Reference Group indicator */
#define SRG                 0000000u            /* Shift-Rotate Group indicator */
#define ASG                 0002000u            /* Alter-Skip Group indicator */
#define IOG                 0102000u            /* I/O Group indicator */

#define MRGOP(v)            (((v) & MRG) != 0)          /* MRG membership test */
#define SRGOP(v)            (((v) & GROUP_MASK) == SRG) /* SRG membership test */
#define ASGOP(v)            (((v) & GROUP_MASK) == ASG) /* ASG membership test */
#define IOGOP(v)            (((v) & GROUP_MASK) == IOG) /* IOG membership test */

#define SRG_CLE             0000040u            /* SRG CLE opcode */
#define SRG_SLx             0000010u            /* SRG SLA/SLB opcode */
#define SRG_NOP             0000000u            /* SRG no-operation opcode */

#define SRG1_DE_MASK        0001000u            /* SRG disable/enable first micro-op field bit */
#define SRG1_MASK           0001700u
#define SRG1_SHIFT          6

#define SRG2_DE_MASK        0000020u            /* SRG disable/enable second micro-op field bit */
#define SRG2_MASK           0000027u
#define SRG2_SHIFT          0

#define SRG1(u)             (((u) & SRG1_MASK) >> SRG1_SHIFT)
#define SRG2(u)             (((u) & SRG2_MASK) >> SRG2_SHIFT)

#define UIG_MASK            0000360u            /* UIG feature group mask */
#define UIG_SHIFT           4                   /* UIG feature group alignment shift */

#define UIG(i)              (((i) & UIG_MASK) >> UIG_SHIFT)

#define UIG_0_MASK          0177400u            /* UIG-0 opcode mask */
#define UIG_0_RANGE         0105000u            /* UIG-0 opcode range */

#define UIG_1_MASK          0173400u            /* UIG-1 opcode mask */
#define UIG_1_RANGE         0101400u            /* UIG-1 opcode range */

#define UIG_0_OP(i)         (((i) & UIG_0_MASK) == UIG_0_RANGE) /* UIG-0 membership test */
#define UIG_1_OP(i)         (((i) & UIG_1_MASK) == UIG_1_RANGE) /* UIG-1 membership test */

#define RTE_IRQ_RANGE       0105354             /* RTE-6/VM interrupt request instructions range */


/* Memory Reference Group instructions */

#define I_IA                0100000u            /* indirect address */
#define I_AB                0004000u            /* A/B select */
#define I_CP                0002000u            /* current page */
#define I_DISP              0001777u            /* page displacement */
#define I_PAGENO            0076000u            /* page number */

/* Alter/Skip Group instructions */

#define I_CMx               0001000u            /* CMA/B */
#define I_CLx               0000400u            /* CLA/B */
#define I_CME               0000200u            /* CME */
#define I_CLE               0000100u            /* CLE */
#define I_SEZ               0000040u            /* SEZ */
#define I_SSx               0000020u            /* SSA/B */
#define I_SLx               0000010u            /* SLA/B */
#define I_INx               0000004u            /* INA/B */
#define I_SZx               0000002u            /* SZA/B */
#define I_RSS               0000001u            /* RSS */

#define I_SSx_SLx_RSS       (I_SSx | I_SLx | I_RSS)         /* a special case */
#define I_ALL_SKIPS         (I_SEZ | I_SZx | I_SSx_SLx_RSS) /* another special case */

/* Shift/Rotate Group micro-ops */

#define I_xLS               0000000u            /* ALS/BLS */
#define I_xRS               0000001u            /* ARS/BRS */
#define I_RxL               0000002u            /* RAL/RBL */
#define I_RxR               0000003u            /* RAR/RBR */
#define I_xLR               0000004u            /* ALR/BLR */
#define I_ERx               0000005u            /* ERA/ERB */
#define I_ELx               0000006u            /* ELA/ELB */
#define I_xLF               0000007u            /* ALF/BLF */

#define SRG_DIS             0000000u
#define SRG1_EN             0000010u
#define SRG2_EN             0000020u

/* Other instructions */

#define I_NOP           0000000u                        /* no operation */
#define I_NMRMASK       0172000u                        /* non-mrf opcode */
#define I_ASKP          0002000u                        /* alter/skip */
#define I_IO            0102000u                        /* I/O */
#define I_CTL           0004000u                        /* CTL on/off */
#define I_HC            0001000u                        /* hold/clear */
#define I_DEVMASK       0000077u                        /* device select code mask */
#define I_GETIOOP(x)    (((x) >> 6) & 07u)              /* I/O sub op */

/* Instruction masks */

#define I_MRG           0074000u                        /* MRG instructions */
#define I_MRG_I         (I_MRG | I_IA)                  /* MRG indirect instruction group */
#define I_JSB           0014000u                        /* JSB instruction */
#define I_JSB_I         (I_JSB | I_IA)                  /* JSB,I instruction */
#define I_JMP           0024000u                        /* JMP instruction */
#define I_ISZ           0034000u                        /* ISZ instruction */

#define I_IOG           0107700u                        /* I/O group instruction */
#define I_SFS           0102300u                        /* SFS instruction */
#define I_STF           0102100u                        /* STF instruction */

/* IBL assignments */

#define IBL_V_SEL       14                              /* ROM select <15:14> */
#define IBL_M_SEL       03
#define IBL_PTR         0000000u                        /* ROM 0: 12992K paper tape reader (PTR) */
#define IBL_DP          0040000u                        /* ROM 1: 12992A 7900 disc (DP) */
#define IBL_DQ          0060000u                        /* ROM 1: 12992A 2883 disc (DQ) */
#define IBL_MS          0100000u                        /* ROM 2: 12992D 7970 tape (MS) */
#define IBL_DS          0140000u                        /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
#define IBL_MAN         0010000u                        /* RPL/manual boot <13:12> */
#define IBL_V_DEV       6                               /* select code <11:6> */
#define IBL_OPT         0000070u                        /* options in <5:3> */
#define IBL_DP_REM      0000001u                        /* DP removable <0:0> */
#define IBL_DS_HEAD     0000003u                        /* DS head number <1:0> */
#define IBL_LNT         64                              /* boot ROM length in words */
#define IBL_MASK        (IBL_LNT - 1)                   /* boot length mask */
#define IBL_DPC         (IBL_LNT - 2)                   /* DMA ctrl word */
#define IBL_END         (IBL_LNT - 1)                   /* last location */

#define IBL_S_CLR       0000000u                        /* cpu_ibl mask to clear the S register */
#define IBL_S_NOCLR     0177777u                        /* cpu_ibl mask to preserve the S register */
#define IBL_S_NOSET     0000000u                        /* cpu_ibl mask to preserve the S register */

#define IBL_SET_SC(s)   ((HP_WORD) ((s) << IBL_V_DEV))  /* position the select code in the S register */

typedef MEMORY_WORD BOOT_ROM [IBL_LNT];                 /* boot ROM data */


/* Memory management */

#define VA_N_OFF        10                              /* offset width */
#define VA_M_OFF        ((1 << VA_N_OFF) - 1)           /* offset mask */
#define VA_GETOFF(x)    ((x) & VA_M_OFF)
#define VA_N_PAG        (VA_N_SIZE - VA_N_OFF)          /* page width */
#define VA_V_PAG        (VA_N_OFF)                      /* page offset */
#define VA_M_PAG        ((1 << VA_N_PAG) - 1)           /* page mask */
#define VA_GETPAG(x)    (((x) >> VA_V_PAG) & VA_M_PAG)

/* Maps */

#define MAP_NUM         4                               /* num maps */
#define MAP_LNT         (1 << VA_N_PAG)                 /* map length */
#define MAP_MASK        ((MAP_NUM * MAP_LNT) - 1)
#define SMAP            0                               /* system map */
#define UMAP            (SMAP + MAP_LNT)                /* user map */
#define PAMAP           (UMAP + MAP_LNT)                /* port A map */
#define PBMAP           (PAMAP + MAP_LNT)               /* port B map */

/* DMS map entries */

#define MAP_V_RPR       15                              /* read prot */
#define MAP_V_WPR       14                              /* write prot */
#define RDPROT          (1 << MAP_V_RPR)                /* read access check */
#define WRPROT          (1 << MAP_V_WPR)                /* write access check */
#define NOPROT          0                               /* no access check */
#define MAP_RSVD        0036000                         /* reserved bits */
#define MAP_N_PAG       (PA_N_SIZE - VA_N_OFF)          /* page width */
#define MAP_V_PAG       (VA_N_OFF)
#define MAP_M_PAG       ((1 << MAP_N_PAG) - 1)

#define MAP_PAGE(r)     ((r) & MAP_M_PAG)               /* extract the page number from a map register */
#define TO_PAGE(n)      ((n) << MAP_V_PAG)              /* position the page number in a physical address */

/* MEM status register */

#define MST_ENBI        0100000u                        /* MEM enabled at interrupt */
#define MST_UMPI        0040000u                        /* User map selected at interrupt */
#define MST_ENB         0020000u                        /* MEM enabled currently */
#define MST_UMP         0010000u                        /* User map selected currently */
#define MST_PRO         0004000u                        /* Protected mode enabled currently */
#define MST_FLT         0002000u                        /* Base page portion mapped */
#define MST_FENCE       0001777u                        /* Base page fence */

/* MEM violation register */

#define MVI_V_RPR       15                              /* must be same as */
#define MVI_V_WPR       14                              /* MAP_V_xPR */
#define MVI_RPR         (1 << MVI_V_RPR)                /* rd viol */
#define MVI_WPR         (1 << MVI_V_WPR)                /* wr viol */
#define MVI_BPG         0020000u                        /* base page viol */
#define MVI_PRV         0010000u                        /* priv viol */
#define MVI_MEB         0000200u                        /* me bus enb @ viol */
#define MVI_MEM         0000100u                        /* mem enb @ viol */
#define MVI_UMP         0000040u                        /* usr map @ viol */
#define MVI_PAG         0000037u                        /* pag sel */

/* CPU registers */

#define AR              ABREG [0]               /* A = reg 0 */
#define BR              ABREG [1]               /* B = reg 1 */

extern HP_WORD ABREG [2];                       /* A/B regs (use AR/BR) */
extern HP_WORD PR;                              /* P register */
extern HP_WORD SR;                              /* S register */
extern HP_WORD MR;                              /* M register */
extern HP_WORD TR;                              /* T register */
extern HP_WORD XR;                              /* X register */
extern HP_WORD YR;                              /* Y register */
extern uint32  E;                               /* E register */
extern uint32  O;                               /* O register */

extern HP_WORD IR;                              /* Instruction Register */
extern HP_WORD CIR;                             /* Central Interrupt Register */


/* CPU state */

extern HP_WORD   err_PC;
extern uint32    dms_enb;
extern uint32    dms_ump;
extern HP_WORD   dms_sr;
extern FLIP_FLOP mp_control;
extern HP_WORD   mp_fence;
extern HP_WORD   mp_viol;
extern FLIP_FLOP mp_mevff;
extern HP_WORD   iop_sp;
extern t_bool    ion_defer;
extern uint16    pcq [PCQ_SIZE];
extern uint32    pcq_p;
extern UNIT      cpu_unit;
extern DEVICE    cpu_dev;
extern jmp_buf   save_env;
extern t_bool    mp_mem_changed;

extern t_stat    cpu_ss_unimpl;                 /* status return for unimplemented instruction execution */
extern t_stat    cpu_ss_undef;                  /* status return for undefined instruction execution */
extern t_stat    cpu_ss_unsc;                   /* status return for I/O to an unassigned select code */
extern t_stat    cpu_ss_ioerr;                  /* status return for an unreported I/O error */
extern t_stat    cpu_ss_indir;                  /* status return for indirect loop execution */
extern t_stat    cpu_ss_inhibit;                /* simulation stop inhibition mask */
extern UNIT      *cpu_ioerr_uptr;               /* pointer to a unit with an unreported I/O error */

extern uint32    cpu_configuration;             /* the current CPU option set and model */
extern uint32    cpu_speed;                     /* the CPU speed, expressed as a multiplier of a real machine */


/* CPU global SCP support routines declared in scp.h

extern t_stat sim_instr (void);
*/


/* CPU global SCP support routines */

extern void cpu_post_cmd (t_bool from_scp);


/* CPU global utility routines */

extern void    cpu_ibl    (const BOOT_ROM rom, int32 dev, HP_WORD sr_clear, HP_WORD sr_set);
extern t_stat  cpu_iog    (HP_WORD IR, t_bool iotrap);
extern uint32  calc_int   (void);
extern t_stat  resolve    (HP_WORD MA, HP_WORD *address, uint32 irq);


/* Memory global utility routines */

extern HP_WORD mem_read       (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address);
extern void    mem_write      (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address, HP_WORD value);
extern uint8   mem_read_byte  (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address);
extern void    mem_write_byte (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address, uint8 value);

extern HP_WORD mem_fast_read  (HP_WORD address, uint32 map);
extern HP_WORD mem_examine    (uint32 address);
extern void    mem_deposit    (uint32 address, HP_WORD value);


/* Memory Expansion Unit global utility routines */

extern uint16  dms_rmap   (uint32 mapi);
extern void    dms_wmap   (uint32 mapi, uint32 dat);
extern void    dms_viol   (uint32 va, HP_WORD st);
extern HP_WORD dms_upd_vr (uint32 va);
extern HP_WORD dms_upd_sr (void);


/* Memory Protect global utility routines */

extern void mp_dms_jmp (uint32 va, uint32 plb);
