root/src/dps8/dps8_cpu.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. SET_PR_BITNO
  2. SET_AR_CHAR_BITNO
  3. trackport
  4. doFault
  5. core_write
  6. core_write_zone
  7. core_read2
  8. core_write2
  9. core_readN
  10. core_writeN

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 72d91a53-f62d-11ec-a98f-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2022 Charles Anthony
  11  * Copyright (c) 2015-2021 Eric Swenson
  12  * Copyright (c) 2021-2022 The DPS8M Development Team
  13  *
  14  * All rights reserved.
  15  *
  16  * This software is made available under the terms of the ICU
  17  * License, version 1.8.1 or later.  For more details, see the
  18  * LICENSE.md file at the top-level directory of this distribution.
  19  *
  20  * ---------------------------------------------------------------------------
  21  */
  22 
  23 #ifndef __STDC_WANT_IEC_60559_BFP_EXT__
  24 # define __STDC_WANT_IEC_60559_BFP_EXT__ 1
  25 #endif /* ifndef __STDC_WANT_IEC_60559_BFP_EXT__ */
  26 
  27 #include <sys/types.h>
  28 
  29 #ifdef __APPLE__
  30 # undef SCHED_NEVER_YIELD
  31 # define SCHED_NEVER_YIELD 1
  32 # include <mach/thread_policy.h>
  33 # include <mach/task_info.h>
  34 # include <sys/types.h>
  35 # include <sys/sysctl.h>
  36 # include <mach/thread_policy.h>
  37 # include <mach/thread_act.h>
  38 #endif /* ifdef __APPLE__ */
  39 
  40 #include "../simh/sim_timer.h"
  41 #include "hdbg.h"
  42 
  43 #define N_CPU_UNITS 1 // Default
  44 
  45 // JMP_ENTRY must be 0, which is the return value of the setjmp initial
  46 // entry
  47 #define JMP_ENTRY             0
  48 #define JMP_REENTRY           1
  49 #define JMP_STOP              2
  50 #define JMP_SYNC_FAULT_RETURN 3
  51 #define JMP_REFETCH           4
  52 #define JMP_RESTART           5
  53 
  54 // The CPU supports 3 addressing modes
  55 // [CAC] I tell a lie: 4 modes...
  56 // [CAC] I tell another lie: 5 modes...
  57 
  58 typedef enum
  59   {
  60     ABSOLUTE_mode,
  61     APPEND_mode,
  62   } addr_modes_e;
  63 
  64 // The control unit of the CPU is always in one of several states. We
  65 // don't currently use all of the states used in the physical CPU.
  66 // The FAULT_EXEC cycle did not exist in the physical hardware.
  67 
  68 typedef enum
  69   {
  70     FAULT_cycle,
  71     EXEC_cycle,
  72     FAULT_EXEC_cycle,
  73     INTERRUPT_cycle,
  74     INTERRUPT_EXEC_cycle,
  75     FETCH_cycle,
  76     PSEUDO_FETCH_cycle,
  77     SYNC_FAULT_RTN_cycle,
  78   } cycles_e;
  79 
  80 struct tpr_s
  81   {
  82     word3   TRR; // The current effective ring number
  83     word15  TSR; // The current effective segment number
  84     word6   TBR; // The current bit offset as calculated from ITS and ITP
  85                  // pointer pairs.
  86     word18  CA;  // The current computed address relative to the origin of the
  87                  // segment whose segment number is in TPR.TSR
  88   };
  89 
  90 struct ppr_s
  91   {
  92     word3   PRR; // The number of the ring in which the process is executing.
  93                  // It is set to the effective ring number of the procedure
  94                  // segment when control is transferred to the procedure.
  95     word15  PSR; // The segment number of the procedure being executed.
  96     word1   P;   // A flag controlling execution of privileged instructions.
  97                  // Its value is 1 (permitting execution of privileged
  98                  // instructions) if PPR.PRR is 0 and the privileged bit in
  99                  // the segment descriptor word (SDW.P) for the procedure is
 100                  // 1; otherwise, its value is 0.
 101     word18  IC;  // The word offset from the origin of the procedure segment
 102                  //  to the current instruction. (same as PPR.IC)
 103   };
 104 
 105 /////
 106 // The terms "pointer register" and "address register" both apply to the same
 107 // physical hardware. The distinction arises from the manner in which the
 108 // register is used and in the interpretation of the register contents.
 109 // "Pointer register" refers to the register as used by the appending unit and
 110 // "address register" refers to the register as used by the decimal unit.
 111 //
 112 // The three forms are compatible and may be freely intermixed. For example,
 113 // PRn may be loaded in pointer register form with the Effective Pointer to
 114 // Pointer Register n (eppn) instruction, then modified in pointer register
 115 // form with the Effective Address to Word/Bit Number of Pointer Register n
 116 // (eawpn) instruction, then further modified in address register form
 117 // (assuming character size k) with the Add k-Bit Displacement to Address
 118 // Register (akbd) instruction, and finally invoked in operand descriptor form
 119 // by the use of MF.AR in an EIS multiword instruction .
 120 //
 121 // The reader's attention is directed to the presence of two bit number
 122 // registers, PRn.BITNO and ARn.BITNO. Because the Multics processor was
 123 // implemented as an enhancement to an existing design, certain apparent
 124 // anomalies appear. One of these is the difference in the handling of
 125 // unaligned data items by the appending unit and decimal unit. The decimal
 126 // unit handles all unaligned data items with a 9-bit byte number and bit
 127 // offset within the byte. Conversion from the description given in the EIS
 128 // operand descriptor is done automatically by the hardware. The appending unit
 129 // maintains compatibility with the earlier generation Multics processor by
 130 // handling all unaligned data items with a bit offset from the prior word
 131 // boundary; again with any necessary conversion done automatically by the
 132 // hardware. Thus, a pointer register, PRn, may be loaded from an ITS pointer
 133 // pair having a pure bit offset and modified by one of the EIS address
 134 // register instructions (a4bd, s9bd, etc.) using character displacement
 135 // counts. The automatic conversion performed ensures that the pointer
 136 // register, PRi, and its matching address register, ARi, both describe the
 137 // same physical bit in main memory.
 138 //
 139 // N.B. Subtle differences between the interpretation of PR/AR. Need to take
 140 // this into account.
 141 //
 142 //     * For Pointer Registers:
 143 //       - PRn.WORDNO The offset in words from the base or origin of the
 144 //                    segment to the data item.
 145 //       - PRn.BITNO  The number of the bit within PRn.WORDNO that is the
 146 //                    first bit of the data item. Data items aligned on word
 147 //                    boundaries always have the value 0. Unaligned data items
 148 //                    may have any value in the range [1,35].
 149 //
 150 //     * For Address Registers:
 151 //       - ARn.WORDNO The offset in words relative to the current addressing
 152 //                    base referent (segment origin, BAR.BASE, or absolute 0
 153 //                    depending on addressing mode) to the word containing the
 154 //                    next data item element.
 155 //       - ARn.CHAR   The number of the 9-bit byte within ARn.WORDNO
 156 //                    containing the first bit of the next data item element.
 157 //       - ARn.BITNO  The number of the bit within ARn.CHAR that is the
 158 //                    first bit of the next data item element.
 159 /////
 160 
 161 struct par_s
 162   {
 163     word15  SNR;      // The segment number of the segment containing the data
 164                       // item described by the pointer register.
 165     word3   RNR;      // The final effective ring number value calculated during
 166                       // execution of the instruction that last loaded the PR.
 167 
 168     word6  PR_BITNO;  // The number of the bit within PRn.WORDNO that is the
 169                       // first bit of the data item. Data items aligned on word
 170                       // boundaries always have the value 0. Unaligned data
 171                       //  items may have any value in the range [1,35].
 172     word2   AR_CHAR;
 173     word4   AR_BITNO;
 174 
 175     word18  WORDNO;   // The offset in words from the base or origin of the
 176                       // segment to the data item.
 177   };
 178 
 179 // N.B. remember there are subtle differences between AR/PR.BITNO
 180 
 181 #define AR    PAR
 182 #define PR    PAR
 183 
 184 struct bar_s
 185   {
 186     word9 BASE;     // Contains the 9 high-order bits of an 18-bit address
 187                     // relocation constant. The low-order bits are generated
 188                     // as zeros.
 189     word9 BOUND;    // Contains the 9 high-order bits of the unrelocated
 190                     // address limit. The low- order bits are generated as
 191                     // zeros. An attempt to access main memory beyond this
 192                     // limit causes a store fault, out of bounds. A value of
 193                     // 0 is truly 0, indicating a null memory range.
 194   };
 195 
 196 struct dsbr_s
 197   {
 198     word24  ADDR;   // If DSBR.U = 1, the 24-bit absolute main memory address
 199                     //  of the origin of the current descriptor segment;
 200                     //  otherwise, the 24-bit absolute main memory address of
 201                     //  the page table for the current descriptor segment.
 202     word14  BND;    // The 14 most significant bits of the highest Y-block16
 203                     //  address of the descriptor segment that can be
 204                     //  addressed without causing an access violation, out of
 205                     //  segment bounds, fault.
 206     word1   U;      // A flag specifying whether the descriptor segment is
 207                     // unpaged (U = 1) or paged (U = 0).
 208     word12  STACK;  // The upper 12 bits of the 15-bit stack base segment
 209                     // number. It is used only during the execution of the
 210                     // call6 instruction. (See Section 8 for a discussion
 211                     //  of generation of the stack segment number.)
 212   };
 213 
 214 // The segment descriptor word (SDW) pair contains information that controls
 215 // the access to a segment. The SDW for segment n is located at offset 2n in
 216 // the descriptor segment whose description is currently loaded into the
 217 // descriptor segment base register (DSBR).
 218 
 219 struct sdw_s
 220   {
 221     word24  ADDR;    // The 24-bit absolute main memory address of the page
 222                      //  table for the target segment if SDWAM.U = 0;
 223                      //  otherwise, the 24-bit absolute main memory address
 224                      //  of the origin of the target segment.
 225     word3   R1;      // Upper limit of read/write ring bracket
 226     word3   R2;      // Upper limit of read/execute ring bracket
 227     word3   R3;      // Upper limit of call ring bracket
 228     word14  BOUND;   // The 14 high-order bits of the last Y-block16 address
 229                      //  within the segment that can be referenced without an
 230                      //  access violation, out of segment bound, fault.
 231     word1   R;       // Read permission bit. If this bit is set ON, read
 232                      //  access requests are allowed.
 233     word1   E;       // Execute permission bit. If this bit is set ON, the SDW
 234                      //  may be loaded into the procedure pointer register
 235                      //  (PPR) and instructions fetched from the segment for
 236                      //  execution.
 237     word1   W;       // Write permission bit. If this bit is set ON, write
 238                      //  access requests are allowed.
 239     word1   P;       // Privileged flag bit. If this bit is set ON, privileged
 240                      //  instructions from the segment may be executed if
 241                      //  PPR.PRR is 0.
 242     word1   U;       // Unpaged flag bit. If this bit is set ON, the segment
 243                      //  is unpaged and SDWAM.ADDR is the 24-bit absolute
 244                      //  main memory address of the origin of the segment. If
 245                      //  this bit is set OFF, the segment is paged andis
 246                      //  SDWAM.ADDR the 24-bit absolute main memory address of
 247                      //  the page table for the segment.
 248     word1   G;       // Gate control bit. If this bit is set OFF, calls and
 249                      //  transfers into the segment must be to an offset no
 250                      //  greater than the value of SDWAM.CL as described
 251                      //  below.
 252     word1   C;       // Cache control bit. If this bit is set ON, data and/or
 253                      //  instructions from the segment may be placed in the
 254                      //  cache memory.
 255     word14  EB;      // Call limiter (entry bound) value. If SDWAM.G is set
 256                      //  OFF, transfers of control into the segment must be to
 257                      //  segment addresses no greater than this value.
 258     word15  POINTER; // The effective segment number used to fetch this SDW
 259                      //  from main memory.
 260     word1   DF;      // Directed fault flag (called F in AL39).
 261                      //  * 0 = page not in main memory; execute directed fault
 262                      //        FC
 263                      //  * 1 = page is in main memory
 264     word2   FC;      // Directed fault number for page fault.
 265     word1   FE;      // Full/empty bit. If this bit is set ON, the SDW in the
 266                      //  register is valid. If this bit is set OFF, a hit is
 267                      //  not possible. All SDWAM.F bits are set OFF by the
 268                      //  instructions that clear the SDWAM.
 269     // L68: word4
 270     // DPS8M: word6
 271     word6   USE;
 272                      // Usage count for the register. The SDWAM.USE field is
 273                      //  used to maintain a strict FIFO queue order among the
 274                      //  SDWs. When an SDW is matched, its USE value is set to
 275                      //  15 (newest) on the DPS/L68 and to 63 on the DPS 8M,
 276                      //  and the queue is reordered. SDWs newly fetched from
 277                      //  main memory replace the SDW with USE value 0 (oldest)
 278                      //  and the queue is reordered.
 279   };
 280 
 281 typedef struct sdw_s sdw_s;
 282 typedef struct sdw_s sdw0_s;
 283 
 284 
 285 
 286 
 287 
 288 
 289 
 290 
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306 
 307 
 308 
 309 
 310 
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 
 321 
 322 
 323 
 324 
 325 
 326 
 327 
 328 
 329 
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 // PTW as used by APU
 339 
 340 struct ptw_s
 341  {
 342     word18  ADDR;    // The 18 high-order bits of the 24-bit absolute
 343                      //  main memory address of the page.
 344     word1   U;       // * 1 = page has been used (referenced)
 345     word1   M;       // Page modified flag bit. This bit is set ON whenever
 346                      //  the PTW is used for a store type instruction. When
 347                      //  the bit changes value from 0 to 1, a special
 348                      //  extra cycle is generated to write it back into the
 349                      //  PTW in the page table in main memory.
 350     word1   DF;      // Directed fault flag
 351                      // * 0 = page not in main memory; execute directed fault FC
 352                      // * 1 = page is in main memory
 353     word2   FC;      // Directed fault number for page fault.
 354     word15  POINTER; // The effective segment number used to fetch this PTW
 355                      //  from main memory.
 356     word12  PAGENO;  // The 12 high-order bits of the 18-bit computed
 357                      //  address (TPR.CA) used to fetch this PTW from main
 358                      //  memory.
 359     word1   FE;      // Full/empty bit. If this bit is set ON, the PTW in
 360                      //  the register is valid. If this bit is set OFF, a
 361                      //  hit is not possible. All PTWAM.F bits are set OFF
 362                      //  by the instructions that clear the PTWAM.
 363     // DPS8M: word6
 364     // L68: word4
 365     word6   USE;
 366                      // Usage count for the register. The PTWAM.USE field
 367                      //  is used to maintain a strict FIFO queue order
 368                      //  among the PTWs. When an PTW is matched its USE
 369                      // value is set to 15 (newest) on the DPS/L68 and to
 370                      //  63 on the DPS 8M, and the queue is reordered.
 371                      //  PTWs newly fetched from main memory replace the
 372                      //  PTW with USE value 0 (oldest) and the queue is
 373                      //  reordered.
 374   };
 375 
 376 typedef struct ptw_s ptw_s;
 377 typedef struct ptw_s ptw0_s;
 378 
 379 
 380 
 381 
 382 
 383 
 384 
 385 
 386 
 387 
 388 
 389 
 390 
 391 
 392 
 393 
 394 
 395 
 396 
 397 
 398 //
 399 // Cache Mode Register
 400 //
 401 
 402 struct cache_mode_register_s
 403   {
 404     word15   cache_dir_address;
 405     word1    par_bit;
 406     word1    lev_ful;
 407     word1    csh1_on; // 1: The lower half of the cache memory is active and
 408                       // enabled as per the state of inst_on
 409     word1    csh2_on; // 1: The upper half of the cache memory is active and
 410                       // enabled as per the state of inst_on
 411     // L68 only
 412     word1    opnd_on; // 1: The cache memory (if active) is used for operands.
 413 
 414     word1    inst_on; // 1: The cache memory (if active) is used for
 415                       //  instructions.
 416     // When the cache-to-register mode flag (bit 59 of the cache mode register)
 417     // is set ON, the processor is forced to fetch the operands of all
 418     // double-precision operations unit load operations from the cache memory.
 419     // Y0,12 are ignored, Y15,21 select a column, and Y13,14 select a level.
 420     // All other operations (e.g., instruction fetches, single-precision
 421     // operands, etc.) are treated normally.
 422     word1    csh_reg;
 423     word1    str_asd;
 424     word1    col_ful;
 425     word2    rro_AB;
 426     word1    bypass_cache; // DPS8M only
 427     word2    luf;       // LUF value
 428                         // 0   1   2   3
 429                         // Lockup time
 430                         // 2ms 4ms 8ms 16ms
 431                         // The lockup timer is set to 16ms when the
 432                         // processor is initialized.
 433   };
 434 
 435 typedef struct cache_mode_register_s cache_mode_register_s;
 436 
 437 typedef struct mode_register_s
 438   {
 439     word36 r;
 440     // L68 only
 441                     //  8M      L68
 442     word15 FFV;     //  0       FFV     0 - 14
 443     word1 OC_TRAP;  //  0       a           16
 444     word1 ADR_TRAP; //  0       b           17
 445     word9 OPCODE;   //  0       OPCODE 18 - 26
 446     word1 OPCODEX;  //  0       OPCODE      27
 447 
 448  // word1 cuolin;   //  a       c           18 control unit overlap inhibit
 449  // word1 solin;    //  b       d           19 store overlap inhibit
 450     word1 sdpap;    //  c       e           20 store incorrect data parity
 451     word1 separ;    //  d       f           21 store incorrect ZAC
 452  // word2 tm;       //  e       g      22 - 23 timing margins
 453  // word2 vm;       //  f       h      24 - 25 voltage margins
 454                     //  0       0           26 history register overflow trap
 455                     //  0       0           27 strobe HR on opcode match
 456     word1 hrhlt;    //  g       i           28 history register overflow trap
 457 
 458     // DPS8M only
 459     word1 hrxfr;    //  h       j           29 strobe HR on transfer made
 460     // L68 only
 461                     //  h       j           29 strobe HR on opcode match
 462     word1 ihr;      //  i       k           30 Enable HR
 463     word1 ihrrs;    //  j                   31 HR reset options
 464                     //          l           31 HR lock control
 465                     //  k                   32 margin control
 466                     //          m           32 test mode indicator
 467     // DPS8M only
 468     word1 hexfp;    //  l       0           33 hex mode
 469                     //  0       0           34
 470      word1 emr;     //  m       n           35 enable MR
 471   } mode_register_s;
 472 
 473 extern DEVICE cpu_dev;
 474 
 475 typedef struct MOP_struct_s
 476   {
 477     char * mopName;     // name of microoperation
 478     int (* f) (void);   // pointer to mop() [returns character to be stored]
 479   } MOP_struct;
 480 
 481 // address of an EIS operand
 482 typedef struct EISaddr_s
 483   {
 484 #ifndef EIS_PTR
 485     word18  address;    // 18-bit virtual address
 486 #endif
 487 
 488     word36  data;
 489     word1    bit;
 490     eRW     mode;
 491 
 492     int     last_bit_posn;  // track for caching tests
 493 
 494     // for type of data being address by this object
 495 
 496     // eisDataType _type;   // type of data - alphanumeric/numeric
 497 
 498 #ifndef EIS_PTR3
 499     int     TA;    // type of Alphanumeric chars in src
 500 #endif
 501     int     TN;    // type of Numeric chars in src
 502     int     cPos;
 503     int     bPos;
 504 
 505 #ifndef EIS_PTR4
 506     // for when using AR/PR register addressing
 507     word15  SNR;        // The segment number of the segment containing the
 508                         //  data item described by the pointer register.
 509     word3   RNR;        // The effective ring number value calculated during
 510                         //  execution of the instruction that last loaded
 511     MemoryAccessType    mat;    // memory access type for operation
 512 #endif
 513 
 514     // Cache
 515 
 516     // There is a cache for each operand, but they do not cross check;
 517     // this means that if one of them has a cached dirty word, the
 518     // others will not check for a hit, and will use the old value.
 519     // AL39 warns that overlapping operands can cause unexpected behavior
 520     // due to caching issues, so the this behavior is closer to the actual
 521     // h/w then to the theoretical need for cache consistency.
 522 
 523     // We don't need to cache mat or TPR because they will be constant
 524     // across an instruction.
 525 
 526     bool cacheValid;
 527     bool cacheDirty;
 528 #define paragraphSz 8
 529 #define paragraphMask 077777770
 530 #define paragraphOffsetMask 07
 531     word36 cachedParagraph [paragraphSz];
 532     bool wordDirty [paragraphSz];
 533     word18 cachedAddr;
 534 
 535   } EISaddr;
 536 
 537 typedef struct EISstruct_s
 538   {
 539     word36  op [3];         // raw operand descriptors
 540 #define OP1 op [0]          // 1st descriptor (2nd ins word)
 541 #define OP2 op [1]          // 2nd descriptor (3rd ins word)
 542 #define OP3 op [2]          // 3rd descriptor (4th ins word)
 543 
 544     bool     P;             // 4-bit data sign character control
 545 
 546     uint    MF [3];
 547 #define MF1 MF [0]          // Modification field for operand descriptor 1
 548 #define MF2 MF [1]          // Modification field for operand descriptor 2
 549 #define MF3 MF [2]          // Modification field for operand descriptor 3
 550 
 551     uint    CN [3];
 552 #define CN1 CN [0]
 553 #define CN2 CN [1]
 554 #define CN3 CN [2]
 555 
 556     uint    WN [3];
 557 #define WN1 WN [0]
 558 #define WN2 WN [1]
 559 #define WN3 CN [2]
 560 
 561    uint     C [3];
 562 #define C1  C [0]
 563 #define C2  C [1]
 564 #define C3  C [2]
 565 
 566    uint     B [3];
 567 #define B1  B [0]
 568 #define B2  B [1]
 569 #define B3  B [2]
 570 
 571    uint     N [3];
 572 #define N1  N [0]
 573 #define N2  N [1]
 574 #define N3  N [2]
 575 
 576     uint    TN [3];         // type numeric
 577 #define TN1 TN [0]
 578 #define TN2 TN [1]
 579 #define TN3 TN [2]
 580 
 581 #ifdef EIS_PTR3
 582 # define TA1 cpu.du.TAk[0]
 583 # define TA2 cpu.du.TAk[1]
 584 # define TA3 cpu.du.TAk[2]
 585 #else
 586 
 587     uint     TA [3];        // type alphanumeric
 588 # define TA1 TA [0]
 589 # define TA2 TA [1]
 590 # define TA3 TA [2]
 591 #endif
 592 
 593    uint     S [3];          // Sign and decimal type of number
 594 #define S1  S [0]
 595 #define S2  S [1]
 596 #define S3  S [2]
 597 
 598     int     SF [3];         // scale factor
 599 #define SF1 SF [0]
 600 #define SF2 SF [1]
 601 #define SF3 SF [2]
 602 
 603     word18 _flags;          // flags set during operation
 604     word18 _faults;         // faults generated by instruction
 605 
 606     word72s x;              // a signed, 128-bit integers for playing with ...
 607 
 608     // Stuff for Micro-operations and Edit instructions...
 609 
 610     word9   editInsertionTable [8];     // 8 9-bit chars
 611 
 612     int     mopIF;          // current micro-operation IF field
 613     MOP_struct *m;          // pointer to current MOP struct
 614 
 615     word9   inBuffer [64];  // decimal unit input buffer
 616     word9   *in;            // pointer to current read position in inBuffer
 617     uint    inBufferCnt;    // number of characters in inBuffer
 618     word9   outBuffer [64]; // output buffer
 619     word9   *out;           // pointer to current write position in outBuffer;
 620 
 621     int     exponent;       // For decimal floating-point (evil)
 622     int     sign;           // For signed decimal (1, -1)
 623 
 624 #ifdef EIS_PTR2
 625 # define KMOP 1
 626 #else
 627     EISaddr *mopAddress;    // mopAddress, pointer to addr [0], [1], or [2]
 628 #endif
 629 
 630     int     mopTally;       // number of micro-ops
 631     int     mopPos;         // current mop char posn
 632 
 633     // Edit Flags
 634     // The processor provides the following four edit flags for use by the
 635     // micro operations.
 636 
 637     bool    mopES;          // End Suppression flag; initially OFF, set ON by
 638                             //  a micro operation when zero-suppression ends.
 639     bool    mopSN;          // Sign flag; initially set OFF if the sending
 640                             //  string has an alphanumeric descriptor or an
 641                             //  unsigned numeric descriptor. If the sending
 642                             //  string has a signed numeric descriptor, the
 643                             //  sign is initially read from the sending string
 644                             //  from the digit position defined by the sign
 645                             //  and the decimal type field (S); SN is set
 646                             //  OFF if positive, ON if negative. If all
 647                             //  digits are zero, the data is assumed positive
 648                             //  and the SN flag is set OFF, even when the
 649                             //  sign is negative.
 650     bool    mopZ;           // Zero flag; initially set ON. It is set OFF
 651                             //  whenever a sending string character that is not
 652                             //  decimal zero is moved into the receiving string.
 653     bool    mopBZ;          // Blank-when-zero flag; initially set OFF and
 654                             //  set ON by either the ENF or SES micro
 655                             //  operation. If, at the completion of a move
 656                             //  (L1 exhausted), both the Z and BZ flags are
 657                             //  ON, the receiving string is filled with
 658                             //  character 1 of the edit insertion table.
 659 
 660     EISaddr addr [3];
 661 
 662 #define ADDR1       addr [0]
 663     int     srcTally;       // number of chars in src (max 63)
 664     int     srcTA;          // type of Alphanumeric chars in src
 665     int     srcSZ;          // size of chars in src (4-, 6-, or 9-bits)
 666 
 667 #define ADDR2       addr [1]
 668 
 669 #define ADDR3       addr [2]
 670     int     dstTally;       // number of chars in dst (max 63)
 671     int     dstSZ;          // size of chars in dst (4-, 6-, or 9-bits)
 672 
 673     bool    mvne;           // for MSES micro-op. True when mvne, false when mve
 674   } EISstruct;
 675 
 676 // Instruction decode structure. Used to represent instruction information
 677 
 678 typedef struct DCDstruct_s
 679   {
 680     struct opcode_s * info; // opcode_s *
 681     uint32 opcode;          // opcode
 682     bool   opcodeX;         // opcode extension
 683     uint32 opcode10;        // opcode | (opcodeX ? 01000 : 0)
 684     word18 address;         // bits 0-17 of instruction
 685     word1  b29;             // bit-29 - address via pointer register. Usually.
 686     bool   i;               // interrupt inhibit bit.
 687     word6  tag;             // instruction tag
 688 
 689     bool stiTally;          // for sti instruction
 690     bool restart;           // instruction is to be restarted
 691   } DCDstruct;
 692 
 693 // Emulator-only interrupt and fault info
 694 
 695 typedef struct
 696   {
 697     vol int fault [N_FAULT_GROUPS];
 698                             // only one fault in groups 1..6 can be pending
 699     vol bool XIP [N_SCU_UNITS_MAX];
 700   } events_t;
 701 
 702 // Physical Switches
 703 
 704 enum procModeSettings { procModeGCOS = 1, procModeMultics = 0 };
 705 
 706 // Switches on the Processor's maintenance and configuration panels
 707 typedef struct
 708   {
 709     uint FLT_BASE; // normally 7 MSB of 12bit fault base addr
 710     uint cpu_num;  // zero for CPU 'A', one for 'B' etc.
 711     word36 data_switches;
 712     word18 addr_switches;
 713     uint assignment [N_CPU_PORTS];
 714     uint interlace [N_CPU_PORTS];    // 0/2/4
 715     uint enable [N_CPU_PORTS];
 716     uint init_enable [N_CPU_PORTS];
 717     uint store_size [N_CPU_PORTS];   // 0-7 encoding 32K-4M
 718     enum procModeSettings procMode;  // 1 bit  Read by rsw instruction; format unknown
 719 
 720     bool enable_cache;   // Enable 8K cache
 721     bool sdwam_enable;   // Enable Segment Descriptor WAM
 722     bool ptwam_enable;   // Enable Page Table WAM
 723 
 724     // CPU serial number; not strictly a switch; on DPS8/M, burned into the CPU PROM
 725     uint serno;
 726   } switches_t;
 727 
 728 // Optional H/W
 729 typedef struct {
 730   uint proc_speed; // 4 bits Read by rsw instruction; format unknown
 731   bool hex_mode_installed;
 732   bool prom_installed;
 733   bool cache_installed;
 734   bool clock_slave_installed;
 735 } optionsType;
 736 
 737 // Hardware tweaks
 738 typedef struct {
 739     uint report_faults;   // If set, faults are reported and ignored
 740     uint tro_enable;      // If set, Timer runout faults are generated.
 741     uint drl_fatal;       // If set, DRL instructions halt the CPU
 742     bool useMap;          // If set, consult memory configuration switches to translate memory addresses to SCU memory banks
 743     uint dis_enable;      // If non-zero, DIS instruction works
 744     uint halt_on_unimp;   // If non-zero, halt CPU on unimplemented instruction instead of faulting
 745     bool isolts_mode;     // If true, CPU is configured to run ISOLTS.
 746     uint enable_wam;      // If zero, the simulated cache is ignored and always returns "miss"; turning it on incurs a large performance hit.
 747     bool enable_emcall;   // If set, the instruction set is extended with simulator debugging instructions
 748     bool nodis;           // If true, start CPU in FETCH cycle; else start in DIS instruction
 749     bool l68_mode;      // False: DPS8/M; True: 6180
 750 } tweaksType;
 751 
 752 enum ou_cycle_e
 753   {
 754     ou_GIN = 0400,
 755     ou_GOS = 0200,
 756     ou_GD1 = 0100,
 757     ou_GD2 = 0040,
 758     ou_GOE = 0020,
 759     ou_GOA = 0010,
 760     ou_GOM = 0004,
 761     ou_GON = 0002,
 762     ou_GOF = 0001
 763   };
 764 
 765 typedef struct
 766   {
 767     // Operations Unit/Address Modification
 768     bool   directOperandFlag;
 769     word36 directOperand;
 770     word6  characterOperandSize; // just the left most bit
 771     word3  characterOperandOffset;
 772     word18 character_address;
 773     word36 character_data;
 774     bool crflag;
 775 
 776     // L68 only
 777     word2 eac;
 778     word1 RB1_FULL;
 779     word1 RP_FULL;
 780     word1 RS_FULL;
 781     word9 cycle;
 782     word1 STR_OP;
 783     // End L68 only
 784 
 785 #ifdef PANEL68
 786     word9 RS;
 787     word4 opsz;
 788     word10 reguse;
 789 #endif
 790   } ou_unit_data_t;
 791 
 792 // APU history operation parameter
 793 
 794 enum APUH_e
 795   {
 796     APUH_FDSPTW = 1llu << (35 - 17),
 797     APUH_MDSPTW = 1llu << (35 - 18),
 798     APUH_FSDWP =  1llu << (35 - 19),
 799     APUH_FPTW =   1llu << (35 - 20),
 800     APUH_FPTW2 =  1llu << (35 - 21),
 801     APUH_MPTW =   1llu << (35 - 22),
 802     APUH_FANP =   1llu << (35 - 23),
 803     APUH_FAP =    1llu << (35 - 24)
 804   };
 805 
 806 enum {
 807 //   AL39 pg 64 APU hist.
 808     apu_FLT = 1ll << (33 - 0),    //  0   l FLT Access violation or directed
 809                                   //            fault on this cycle
 810                                   //  1-2 a BSY    Data source for ESN
 811     apu_ESN_PSR = 0,              //                  00 PPR.PSR
 812     apu_ESN_SNR = 1ll << (33- 1), //                  01 PRn.SNR
 813     apu_ESN_TSR = 1ll << (33- 2), //                  10 TPR.TSR
 814                                   //                  11 not used
 815                                   //  3     PRAP
 816     apu_HOLD = 1ll <<  (33- 4),   //  4     HOLD  An access violation or
 817                                   //              directed fault is waiting
 818                                   //  5     FRIW
 819                                   //  6     XSF
 820                                   //  7     STF
 821     apu_TP_P = 1ll <<  (33- 8),   //  8     TP P    Guessing PPR.p set from
 822                                   //                SDW.P
 823     apu_PP_P = 1ll <<  (33- 9),   //  9     PP P    PPR.P?
 824                                   // 10     ?
 825                                   // 11     S-ON   Segment on?
 826                                   // 12     ZMAS
 827                                   // 13     SDMF   Seg. Descr. Modify?
 828                                   // 14     SFND
 829                                   // 15     ?
 830                                   // 16     P-ON   Page on?
 831                                   // 17     ZMAP
 832                                   // 18     PTMF
 833                                   // 19     PFND
 834     apu_FDPT = 1ll << (33-20),    // 20   b FDPT   Fetch descriptor segment PTW
 835     apu_MDPT = 1ll << (33-21),    // 21   c MDPT   Modify descriptor segment PTW
 836     apu_FSDP = 1ll << (33-22),    // 22   d FSDP   Fetch SDW paged descr. seg.
 837     apu_FSDN = 1ll << (33-23),    // 23     FSDN   Fetch SDW non-paged
 838     apu_FPTW = 1ll << (33-24),    // 24   e FPTW   Fetch PTW
 839     apu_MPTW = 1ll << (33-25),    // 25   g MPTW   Modify PTW
 840     apu_FPTW2 = 1ll << (33-26),   // 26   f FPT2   // Fetch prepage
 841     apu_FAP  = 1ll << (33-27),    // 27   i FAP    Final address fetch from
 842                                   //               paged seg.
 843     apu_FANP = 1ll << (33-28),    // 28   h FANP   Final address fetch from
 844                                   //               non-paged segment
 845                                   // 29     FAAB   Final address absolute?
 846     apu_FA   = 1ll << (33-30),    // 30     FA     Final address?
 847                                   // 31     EAAU
 848     apu_PIAU = 1ll << (33-32)     // 32     PIAU   Instruction fetch?
 849                                   // 33     TGAU
 850   };
 851 
 852 typedef struct
 853   {
 854     processor_cycle_type lastCycle;
 855 #ifdef PANEL68
 856     word34 state;
 857 #endif
 858   } apu_unit_data_t;
 859 
 860 typedef struct
 861   {
 862     // NB: Some of the data normally stored here is represented
 863     // elsewhere -- e.g.,the PPR is a variable outside of this
 864     // struct.   Other data is live and only stored here.
 865 
 866     // This is a collection of flags and registers from the
 867     // appending unit and the control unit.  The scu and rcu
 868     // instructions store and load these values to an 8 word
 869     // memory block.
 870     //
 871     // The CU data may only be valid for use with the scu and
 872     // rcu instructions.
 873     //
 874     // Comments indicate format as stored in 8 words by the scu
 875     // instruction.
 876 
 877     // NOTE: PPR (procedure pointer register) is a combination of registers:
 878     //   From the Appending Unit
 879     //     PRR bits [0..2] of word 0
 880     //     PSR bits [3..17] of word 0
 881     //     P   bit 18 of word 0
 882     //   From the Control Unit
 883     //     IC  bits [0..17] of word 4
 884 
 885     /* word 0 */
 886                    // 0-2   PRR is stored in PPR
 887                    // 3-17  PSR is stored in PPR
 888                    // 18    P   is stored in PPR
 889     word1 XSF;     // 19    XSF External segment flag
 890     word1 SDWAMM;  // 20    SDWAMM Match on SDWAM
 891     word1 SD_ON;   // 21    SDWAM enabled
 892     word1 PTWAMM;  // 22    PTWAMM Match on PTWAM
 893     word1 PT_ON;   // 23    PTWAM enabled
 894 
 895 
 896 
 897 
 898 
 899 
 900 
 901 
 902 
 903 
 904 
 905 
 906 
 907     word12 APUCycleBits;
 908 
 909 
 910     /* word 1 */
 911                    //               AVF Access Violation Fault
 912                    //               SF  Store Fault
 913                    //               IPF Illegal Procedure Fault
 914                    //
 915     word1 IRO_ISN; //  0    IRO       AVF Illegal Ring Order
 916                    //       ISN       SF  Illegal segment number
 917     word1 OEB_IOC; //  1    ORB       AVF Out of execute bracket [sic] should
 918                    //                     be OEB?
 919                    //       IOC       IPF Illegal op code
 920     word1 EOFF_IAIM;
 921                    //  2    E-OFF     AVF Execute bit is off
 922                    //       IA+IM     IPF Illegal address of modifier
 923     word1 ORB_ISP; //  3    ORB       AVF Out of read bracket
 924                    //       ISP       IPF Illegal slave procedure
 925     word1 ROFF_IPR;//  4    R-OFF     AVF Read bit is off
 926                    //       IPR       IPF Illegal EIS digit
 927     word1 OWB_NEA; //  5    OWB       AVF Out of write bracket
 928                    //       NEA       SF  Nonexistent address
 929     word1 WOFF_OOB;//  6    W-OFF     AVF Write bit is off
 930                    //       OOB       SF  Out of bounds (BAR mode)
 931     word1 NO_GA;   //  7    NO GA     AVF Not a gate
 932     word1 OCB;     //  8    OCB       AVF Out of call bracket
 933     word1 OCALL;   //  9    OCALL     AVF Outward call
 934     word1 BOC;     // 10    BOC       AVF Bad outward call
 935 // PTWAM error is DPS8M only
 936     word1 PTWAM_ER;// 11    PTWAM_ER  AVF PTWAM error // inward return
 937     word1 CRT;     // 12    CRT       AVF Cross ring transfer
 938     word1 RALR;    // 13    RALR      AVF Ring alarm
 939 // On DPS8M a SDWAM error, on DP8/L68 a WAM error
 940     word1 SDWAM_ER;// 14    SWWAM_ER  AVF SDWAM error
 941     word1 OOSB;    // 15    OOSB      AVF Out of segment bounds
 942     word1 PARU;    // 16    PARU      Parity fault - processor parity upper
 943     word1 PARL;    // 17    PARL      Parity fault - processor parity lower
 944     word1 ONC1;    // 18    ONC1      Operation not complete fault error #1
 945     word1 ONC2;    // 19    ONC2      Operation not complete fault error #2
 946     word4 IA;      // 20-23 IA        System control illegal action lines
 947     word3 IACHN;   // 24-26 IACHN     Illegal action processor port
 948     word3 CNCHN;   // 27-29 CNCHN     Connect fault - connect processor port
 949     word5 FI_ADDR; // 30-34 F/I ADDR  Modulo 2 fault/interrupt vector address
 950     word1 FLT_INT; // 35    F/I       0 = interrupt; 1 = fault
 951 
 952     /* word 2 */
 953                    //  0- 2 TRR
 954                    //  3-17 TSR
 955                    // 18-21 PTW
 956                    //                  18  PTWAM levels A, B enabled
 957                    //                  19  PTWAM levels C, D enabled
 958                    //                  20  PTWAM levels A, B match
 959                    //                  21  PTWAM levels C, D match
 960                    // 22-25 SDW
 961                    //                  22  SDWAM levels A, B enabled
 962                    //                  23  SDWAM levels C, D enabled
 963                    //                  24  SDWAM levels A, B match
 964                    //                  25  SDWAM levels C, D match
 965                    // 26             0
 966                    // 27-29 CPU      CPU Number
 967     word6 delta;   // 30-35 DELTA    addr increment for repeats
 968 
 969     /* word 3 */
 970                    //  0-17          0
 971                    // 18-21 TSNA     Pointer register number for non-EIS
 972                    //                operands or EIS Operand #1
 973                    //                  18-20 PRNO Pointer register number
 974                    //                  21       PRNO is valid
 975                    // 22-25 TSNB     Pointer register number for EIS operand #2
 976                    //                  22-24 PRNO Pointer register number
 977                    //                  25       PRNO is valid
 978                    // 26-29 TSNC     Pointer register number for EIS operand #2
 979                    //                  26-28 PRNO Pointer register number
 980                    //                  29       PRNO is valid
 981     word3 TSN_PRNO [3];
 982     word1 TSN_VALID [3];
 983 
 984                    // 30-35 TEMP BIT Current bit offset (TPR.TBR)
 985 
 986     /* word 4 */
 987                    //  0-17 PPR.IC
 988     word18 IR;     // 18-35 Indicator register
 989                    //    18 ZER0
 990                    //    19 NEG
 991                    //    20 CARY
 992                    //    21 OVFL
 993                    //    22 EOVF
 994                    //    23 EUFL
 995                    //    24 OFLM
 996                    //    25 TRO
 997                    //    26 PAR
 998                    //    27 PARM
 999                    //    28 -BM
1000                    //    29 TRU
1001                    //    30 MIF
1002                    //    31 ABS
1003                    //    32 HEX [sic] Figure 3-32 is wrong.
1004                    // 33-35 0
1005 
1006     /* word 5 */
1007 
1008                    //  0-17 COMPUTED ADDRESS (TPR.CA)
1009     word1 repeat_first;
1010                    // 18    RF  First cycle of all repeat instructions
1011     word1 rpt;     // 19    RPT Execute an Repeat (rpt) instruction
1012     word1 rd;      // 20    RD  Execute an Repeat Double (rpd) instruction
1013     word1 rl;      // 21    RL  Execute a Repeat Link (rpl) instruction
1014     word1 pot;     // 22    POT Prepare operand tally
1015                    // 23    PON Prepare operand no tally
1016     //xde xdo
1017     // 0   0   no execute           -> 0 0
1018     // 1   0   execute XEC          -> 0 0
1019     // 1   1   execute even of XED  -> 0 1
1020     // 0   1   execute odd of XED   -> 0 0
1021     word1 xde;     // 24    XDE Execute instruction from Execute Double even
1022                    //       pair
1023     word1 xdo;     // 25    XDO Execute instruction from Execute Double odd pair
1024     word1 itp;     // 26    ITP Execute ITP indirect cycle
1025     word1 rfi;     // 27    RFI Restart this instruction
1026     word1 its;     // 28    ITS Execute ITS indirect cycle
1027     word1 FIF;     // 29    FIF Fault occurred during instruction fetch
1028     word6 CT_HOLD; // 30-35 CT HOLD contents of the "remember modifier" register
1029 
1030     /* word 6 */
1031     word36 IWB;
1032 
1033     /* word 7 */
1034     word36 IRODD; /* Instr holding register; odd word of last pair fetched */
1035  } ctl_unit_data_t;
1036 
1037 #define USE_IRODD (cpu.cu.rd && ((cpu. PPR.IC & 1) != 0))
1038 #define IWB_IRODD (USE_IRODD ? cpu.cu.IRODD : cpu.cu.IWB)
1039 
1040 // L68 only
1041 enum du_cycle1_e
1042   {
1043     //  0 -FPOL Prepare operand length
1044     du1_nFPOL        = 0400000000000ll,
1045     //  1 -FPOP Prepare operand pointer
1046     du1_nFPOP        = 0200000000000ll,
1047     //  2 -NEED-DESC Need descriptor
1048     du1_nNEED_DESC   = 0100000000000ll,
1049     //  3 -SEL-ADR Select address register
1050     du1_nSEL_DIR     = 0040000000000ll,
1051     //  4 -DLEN=DIRECT Length equals direct
1052     du1_nDLEN_DIRECT = 0020000000000ll,
1053     //  5 -DFRST Descriptor processed for first time
1054     du1_nDFRST       = 0010000000000ll,
1055     //  6 -FEXR Extended register modification
1056     du1_nFEXR        = 0004000000000ll,
1057     //  7 -DLAST-FRST Last cycle of DFRST
1058     du1_nLAST_DFRST  = 0002000000000ll,
1059     //  8 -DDU-LDEA Decimal unit load  (lpl?)
1060     du1_nDDU_LDEA    = 0001000000000ll,
1061     //  9 -DDU-STAE Decimal unit store (spl?)
1062     du1_nDDU_STEA    = 0000400000000ll,
1063     // 10 -DREDO Redo operation without pointer and length update
1064     du1_nDREDO       = 0000200000000ll,
1065     // 11 -DLVL<WD-SZ Load with count less than word size
1066     du1_nDLVL_WD_SZ  = 0000100000000ll,
1067     // 12 -EXH Exhaust
1068     du1_nEXH         = 0000040000000ll,
1069     // 13 DEND-SEQ End of sequence
1070     du1_DEND_SEQ     = 0000020000000ll,
1071     // 14 -DEND End of instruction
1072     du1_nEND         = 0000010000000ll,
1073     // 15 -DU=RD+WRT Decimal unit write-back
1074     du1_nDU_RD_WRT   = 0000004000000ll,
1075     // 16 -PTRA00 PR address bit 0
1076     du1_nPTRA00      = 0000002000000ll,
1077     // 17 -PTRA01 PR address bit 1
1078     du1_nPTRA01      = 0000001000000ll,
1079     // 18 FA/Il Descriptor l active
1080     du1_FA_I1        = 0000000400000ll,
1081     // 19 FA/I2 Descriptor 2 active
1082     du1_FA_I2        = 0000000200000ll,
1083     // 20 FA/I3 Descriptor 3 active
1084     du1_FA_I3        = 0000000100000ll,
1085     // 21 -WRD Word operation
1086     du1_nWRD         = 0000000040000ll,
1087     // 22 -NINE 9-bit character operation
1088     du1_nNINE        = 0000000020000ll,
1089     // 23 -SIX 6-bit character operation
1090     du1_nSIX         = 0000000010000ll,
1091     // 24 -FOUR 4-bit character operation
1092     du1_nFOUR        = 0000000004000ll,
1093     // 25 -BIT Bit operation
1094     du1_nBIT         = 0000000002000ll,
1095     // 26 Unused
1096     //               = 0000000001000ll,
1097     // 27 Unused
1098     //               = 0000000000400ll,
1099     // 28 Unused
1100     //               = 0000000000200ll,
1101     // 29 Unused
1102     //               = 0000000000100ll,
1103     // 30 FSAMPL Sample for mid-instruction interrupt
1104     du1_FSAMPL       = 0000000000040ll,
1105     // 31 -DFRST-CT Specified first count of a sequence
1106     du1_nDFRST_CT    = 0000000000020ll,
1107     // 32 -ADJ-LENGTH Adjust length
1108     du1_nADJ_LENTGH  = 0000000000010ll,
1109     // 33 -INTRPTD Mid-instruction interrupt
1110     du1_nINTRPTD     = 0000000000004ll,
1111     // 34 -INHIB Inhibit STC1 (force "STC0")
1112     du1_nINHIB       = 0000000000002ll,
1113     // 35 Unused
1114     //               = 0000000000001ll,
1115   };
1116 
1117 // L68 only
1118 enum du_cycle2_e
1119   {
1120     // 36 DUD Decimal unit idle
1121     du2_DUD          = 0400000000000ll,
1122     // 37 -GDLDA Descriptor load gate A
1123     du2_nGDLDA       = 0200000000000ll,
1124     // 38 -GDLDB Descriptor load gate B
1125     du2_nGDLDB       = 0100000000000ll,
1126     // 39 -GDLDC Descriptor load gate C
1127     du2_nGDLDC       = 0040000000000ll,
1128     // 40 NLD1 Prepare alignment count for first numeric operand load
1129     du2_NLD1         = 0020000000000ll,
1130     // 41 GLDP1 Numeric operand one load gate
1131     du2_GLDP1        = 0010000000000ll,
1132     // 42 NLD2 Prepare alignment count for second numeric operand load
1133     du2_NLD2         = 0004000000000ll,
1134     // 43 GLDP2 Numeric operand two load gate
1135     du2_GLDP2        = 0002000000000ll,
1136     // 44 ANLD1 Alphanumeric operand one load gate
1137     du2_ANLD1        = 0001000000000ll,
1138     // 45 ANLD2 Alphanumeric operand two load gate
1139     du2_ANLD2        = 0000400000000ll,
1140     // 46 LDWRT1 Load rewrite register one gate (XXX Guess indirect desc. MFkID)
1141     du2_LDWRT1       = 0000200000000ll,
1142     // 47 LDWRT2 Load rewrite register two gate (XXX Guess indirect desc. MFkID)
1143     du2_LDWRT2       = 0000100000000ll,
1144     // 50 -DATA-AVLDU Decimal unit data available
1145     du2_nDATA_AVLDU  = 0000040000000ll,
1146     // 49 WRT1 Rewrite register one loaded
1147     du2_WRT1         = 0000020000000ll,
1148     // 50 GSTR Numeric store gate
1149     du2_GSTR         = 0000010000000ll,
1150     // 51 ANSTR Alphanumeric store gate
1151     du2_ANSTR        = 0000004000000ll,
1152     // 52 FSTR-OP-AV Operand available to be stored
1153     du2_FSTR_OP_AV   = 0000002000000ll,
1154     // 53 -FEND-SEQ End sequence flag
1155     du2_nFEND_SEQ    = 0000001000000ll,
1156     // 54 -FLEN<128 Length less than 128
1157     du2_nFLEN_128    = 0000000400000ll,
1158     // 55 FGCH Character operation gate
1159     du2_FGCH         = 0000000200000ll,
1160     // 56 FANPK Alphanumeric packing cycle gate
1161     du2_FANPK        = 0000000100000ll,
1162     // 57 FEXMOP Execute MOP gate
1163     du2_FEXOP        = 0000000040000ll,
1164     // 58 FBLNK Blanking gate
1165     du2_FBLNK        = 0000000020000ll,
1166     // 59 Unused
1167     //               = 0000000010000ll,
1168     // 60 DGBD Binary to decimal execution gate
1169     du2_DGBD         = 0000000004000ll,
1170     // 61 DGDB Decimal to binary execution gate
1171     du2_DGDB         = 0000000002000ll,
1172     // 62 DGSP Shift procedure gate
1173     du2_DGSP         = 0000000001000ll,
1174     // 63 FFLTG Floating result flag
1175     du2_FFLTG        = 0000000000400ll,
1176     // 64 FRND Rounding flag
1177     du2_FRND         = 0000000000200ll,
1178     // 65 DADD-GATE Add/subtract execute gate
1179     du2_DADD_GATE    = 0000000000100ll,
1180     // 66 DMP+DV-GATE Multiply/divide execution gate
1181     du2_DMP_DV_GATE  = 0000000000040ll,
1182     // 67 DXPN-GATE Exponent network execution gate
1183     du2_DXPN_GATE    = 0000000000020ll,
1184     // 68 Unused
1185     //               = 0000000000010ll,
1186     // 69 Unused
1187     //               = 0000000000004ll,
1188     // 70 Unused
1189     //               = 0000000000002ll,
1190     // 71 Unused
1191     //               = 0000000000001ll,
1192   };
1193 
1194 // L68 only
1195 #define DU_CYCLE_GDLDA { clrmask (& cpu.du.cycle2, du2_nGDLDA);               \
1196                         setmask (& cpu.du.cycle2, du2_nGDLDB | du2_nGDLDC); }
1197 #define DU_CYCLE_GDLDB { clrmask (& cpu.du.cycle2, du2_nGDLDB);               \
1198                         setmask (& cpu.du.cycle2, du2_nGDLDA | du2_nGDLDC); }
1199 #define DU_CYCLE_GDLDC { clrmask (& cpu.du.cycle2, du2_nGDLDC);               \
1200                         setmask (& cpu.du.cycle2, du2_nGDLDA | du2_nGDLDB); }
1201 #define DU_CYCLE_FA_I1     setmask (& cpu.du.cycle1, du1_FA_I1)
1202 #define DU_CYCLE_FA_I2     setmask (& cpu.du.cycle1, du1_FA_I2)
1203 #define DU_CYCLE_FA_I3     setmask (& cpu.du.cycle1, du1_FA_I3)
1204 #define DU_CYCLE_ANLD1     setmask (& cpu.du.cycle2, du2_ANLD1)
1205 #define DU_CYCLE_ANLD2     setmask (& cpu.du.cycle2, du2_ANLD2)
1206 #define DU_CYCLE_NLD1      setmask (& cpu.du.cycle2, du2_NLD1)
1207 #define DU_CYCLE_NLD2      setmask (& cpu.du.cycle2, du2_NLD2)
1208 #define DU_CYCLE_FRND      setmask (& cpu.du.cycle2, du2_FRND)
1209 #define DU_CYCLE_DGBD      setmask (& cpu.du.cycle2, du2_DGBD)
1210 #define DU_CYCLE_DGDB      setmask (& cpu.du.cycle2, du2_DGDB)
1211 #define DU_CYCLE_DDU_LDEA  clrmask (& cpu.du.cycle1, du1_nDDU_LDEA)
1212 #define DU_CYCLE_DDU_STEA  clrmask (& cpu.du.cycle1, du1_nDDU_STEA)
1213 #define DU_CYCLE_END       clrmask (& cpu.du.cycle1, du1_nEND)
1214 #define DU_CYCLE_LDWRT1    setmask (& cpu.du.cycle2, du2_LDWRT1)
1215 #define DU_CYCLE_LDWRT2    setmask (& cpu.du.cycle2, du2_LDWRT2)
1216 #define DU_CYCLE_FEXOP     setmask (& cpu.du.cycle2, du2_FEXOP)
1217 #define DU_CYCLE_ANSTR     setmask (& cpu.du.cycle2, du2_ANSTR)
1218 #define DU_CYCLE_GSTR      setmask (& cpu.du.cycle2, du2_GSTR)
1219 #define DU_CYCLE_FLEN_128  clrmask (& cpu.du.cycle2, du2_nFLEN_128)
1220 #define DU_CYCLE_FDUD  { cpu.du.cycle1 = \
1221                       du1_nFPOL        | \
1222                       du1_nFPOP        | \
1223                       du1_nNEED_DESC   | \
1224                       du1_nSEL_DIR     | \
1225                       du1_nDLEN_DIRECT | \
1226                       du1_nDFRST       | \
1227                       du1_nFEXR        | \
1228                       du1_nLAST_DFRST  | \
1229                       du1_nDDU_LDEA    | \
1230                       du1_nDDU_STEA    | \
1231                       du1_nDREDO       | \
1232                       du1_nDLVL_WD_SZ  | \
1233                       du1_nEXH         | \
1234                       du1_nEND         | \
1235                       du1_nDU_RD_WRT   | \
1236                       du1_nWRD         | \
1237                       du1_nNINE        | \
1238                       du1_nSIX         | \
1239                       du1_nFOUR        | \
1240                       du1_nBIT         | \
1241                       du1_nINTRPTD     | \
1242                       du1_nINHIB;        \
1243                     cpu.du.cycle2 =      \
1244                       du2_DUD          | \
1245                       du2_nGDLDA       | \
1246                       du2_nGDLDB       | \
1247                       du2_nGDLDC       | \
1248                       du2_nDATA_AVLDU  | \
1249                       du2_nFEND_SEQ    | \
1250                       du2_nFLEN_128;     \
1251                   }
1252 #define DU_CYCLE_nDUD clrmask (& cpu.du.cycle2, du2_DUD)
1253 
1254 #ifdef PANEL68
1255 // Control points
1256 
1257 # define CPT(R,C) cpu.cpt[R][C]=1
1258 # define CPTUR(C) cpu.cpt[cpt5L][C]=1
1259 #else
1260 # define CPT(R,C)
1261 # define CPTUR(C)
1262 #endif
1263 
1264 
1265 
1266 
1267 
1268 
1269 
1270 
1271 
1272 
1273 
1274 
1275 
1276 
1277 
1278 
1279 
1280 
1281 
1282 
1283 
1284 
1285 
1286 
1287 
1288 
1289 
1290 
1291 
1292 
1293 
1294 
1295 
1296 
1297 
1298 
1299 
1300 
1301 
1302 
1303 
1304 
1305 
1306 
1307 
1308 
1309 
1310 
1311 
1312 
1313 
1314 
1315 
1316 
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 
1333 
1334 
1335 
1336 
1337 
1338 
1339 
1340 
1341 
1342 
1343 
1344 
1345 
1346 
1347 
1348 
1349 
1350 
1351 
1352 
1353 
1354 
1355 typedef struct du_unit_data_t
1356   {
1357     // Word 0
1358 
1359                       //  0- 8  9   Zeros
1360     word1 Z;          //     9  1   Z       All bit-string instruction results
1361                       //                      are zero
1362     word1 NOP;        //    10  1   0       Negative overpunch found in 6-4
1363                       //                      expanded move
1364     word24 CHTALLY;   // 12-35 24   CHTALLY The number of characters examined
1365                       //                      by the scm, scmr, scd,
1366                       //                      scdr, tct, or tctr instructions
1367                       //                      (up to the interrupt or match)
1368 
1369     // Word 1
1370 
1371                       //  0-35 26   Zeros
1372 
1373     // Word 2
1374 
1375     // word24 D1_PTR; //  0-23 24   D1 PTR  Address of the last double-word
1376                       //                      accessed by operand descriptor 1;
1377                       //                      bits 17-23 (bit-address) valid
1378                       //                      only for initial access
1379                       //    24  1   Zero
1380     // word2 TA1;     // 25-26  2   TA1     Alphanumeric type of operand
1381                       //                      descriptor 1
1382                       // 27-29  3   Zeroes
1383                       //    30  1   I       Decimal unit interrupted flag; a
1384                       //                      copy of the mid-instruction
1385                       //                      interrupt fault indicator
1386     // word1 F1;      //    31  1   F1      First time; data in operand
1387                       //                      descriptor 1 is valid
1388     // word1 A1;      //    32  1   A1      Operand descriptor 1 is active
1389                       // 33-35  3   Zeroes
1390 
1391     // Word 3
1392 
1393     word10 LEVEL1;    //  0- 9 10   LEVEL 1 Difference in the count of
1394                       //                      characters loaded into the and
1395                       //                      processor characters not acted
1396                       //                      upon
1397     // word24 D1_RES; // 12-35 24   D1 RES  Count of characters remaining in
1398                       //                      operand descriptor 1
1399 
1400     // Word 4
1401 
1402     // word24 D2_PTR; //  0-23 24   D2 PTR  Address of the last double-word
1403                       //                      accessed by operand descriptor 2;
1404                       //                      bits 17-23 (bit-address) valid
1405                       //                      only for initial access
1406                       //    24  1   Zero
1407     // word2 TA2;     // 25-26  2   TA2     Alphanumeric type of operand
1408                       //                      descriptor 2
1409                       // 27-29  3   Zeroes
1410     word1 R;          //    30  1   R       Last cycle performed must be
1411                       //                    repeated
1412     // word1 F2;      //    31  1   F2      First time; data in operand
1413                       //                      descriptor 2 is valid
1414     // word1 A2;      //    32  1   A2      Operand descriptor 2 is active
1415                       // 33-35  3   Zeroes
1416 
1417     // Word 5
1418 
1419     word10 LEVEL2;    //  0- 9 10   LEVEL 2 Same as LEVEL 1, but used mainly
1420                       //                      for OP 2 information
1421     // word24 D2_RES; // 12-35 24   D2 RES  Count of characters remaining in
1422                       //                      operand descriptor 2
1423 
1424     // Word 6
1425 
1426     // word24 D3_PTR; //  0-23 24   D3 PTR  Address of the last double-word
1427                       //                      accessed by operand descriptor 3;
1428                       //                      bits 17-23 (bit-address) valid
1429                       //                      only for initial access
1430                       //    24  1   Zero
1431     // word2 TA3;     // 25-26  2   TA3     Alphanumeric type of operand
1432                       //                      descriptor 3
1433                       // 27-29  3   Zeroes
1434                       //    30  1   R       Last cycle performed must be
1435                       //                      repeated
1436                       //                    [XXX: what is the difference between
1437                       //                      this and word4.R]
1438     // word1 F3;      //    31  1   F3      First time; data in operand
1439                       //                      descriptor 3 is valid
1440     // word1 A3;      //    32  1   A3      Operand descriptor 3 is active
1441     word3 JMP;        // 33-35  3   JMP     Descriptor count; number of words
1442                       //                      to skip to find the next
1443                       //                      instruction following this
1444                       //                      multiword instruction
1445 
1446     // Word 7
1447 
1448                       //  0-12 12   Zeroes
1449     // word24 D3_RES; // 12-35 24   D3 RES  Count of characters remaining in
1450                       //                      operand descriptor 3
1451 
1452     // Fields from above reorganized for generality
1453     word2 TAk [3];
1454 
1455 // D_PTR is a word24 divided into a 18 bit address, and a 6-bit bitno/char
1456 // field
1457 
1458     word18 Dk_PTR_W [3];
1459 #define D1_PTR_W Dk_PTR_W [0]
1460 #define D2_PTR_W Dk_PTR_W [1]
1461 #define D3_PTR_W Dk_PTR_W [2]
1462 
1463     word6 Dk_PTR_B [3];
1464 #define D1_PTR_B Dk_PTR_B [0]
1465 #define D2_PTR_B Dk_PTR_B [1]
1466 #define D3_PTR_B Dk_PTR_B [2]
1467 
1468     word24 Dk_RES [3];
1469 #define D_RES Dk_RES
1470 #define D1_RES Dk_RES [0]
1471 #define D2_RES Dk_RES [1]
1472 #define D3_RES Dk_RES [2]
1473 
1474     word1 Fk [3];
1475 //#define F Fk
1476 #define F1 Fk [0]
1477 #define F2 Fk [0]
1478 #define F3 Fk [0]
1479 
1480     word1 Ak [3];
1481 
1482     // Working storage for EIS instruction processing.
1483 
1484     // These values must be restored on instruction restart
1485     word7 MF [3]; // Modifier fields for each instruction.
1486 
1487     // Image of LPL/SPL for ISOLTS compliance
1488     word36 image [8];
1489 
1490 #ifdef PANEL68
1491     word37 cycle1;
1492     word37 cycle2;
1493     word1 POL; // Prepare operand length
1494     word1 POP; // Prepare operand pointer
1495 #endif
1496   } du_unit_data_t;
1497 
1498 #ifdef PANEL68
1499 // prepare_state bits
1500 enum
1501   {
1502     ps_PIA = 0200,
1503     ps_POA = 0100,
1504     ps_RIW = 0040,
1505     ps_SIW = 0020,
1506     ps_POT = 0010,
1507     ps_PON = 0004,
1508     ps_RAW = 0002,
1509     ps_SAW = 0001
1510   };
1511 #endif
1512 
1513 // History registers
1514 
1515 // CU History register flag2 field bit
1516 
1517 enum { CUH_XINT = 0100, CUH_IFT = 040, CUH_CRD = 020, CUH_MRD = 010,
1518        CUH_MSTO = 04, CUH_PIB = 02 };
1519 
1520 #define N_DPS8M_WAM_ENTRIES 64
1521 #define N_DPS8M_WAM_MASK   077
1522 #define N_L68_WAM_ENTRIES   16
1523 #define N_L68_WAM_MASK     017
1524 #define N_NAX_WAM_ENTRIES   64
1525 #define N_MODEL_WAM_ENTRIES (cpu.tweaks.l68_mode ? N_L68_WAM_ENTRIES : N_DPS8M_WAM_ENTRIES)
1526 
1527 typedef struct
1528   {
1529 
1530     EISstruct currentEISinstruction;
1531 
1532     unsigned long long cycleCnt;
1533     unsigned long long instrCnt;
1534     unsigned long long instrCntT0;
1535     unsigned long long instrCntT1;
1536     unsigned long long lockCnt;
1537     unsigned long long lockImmediate;
1538     unsigned long long lockWait;
1539     unsigned long long lockWaitMax;
1540 #ifndef SCHED_NEVER_YIELD
1541     unsigned long long lockYield;
1542 #endif /* ifndef SCHED_NEVER_YIELD */
1543 
1544     // From the control unit history register:
1545     _fault_subtype subFault; // saved by doFault
1546 
1547     word36   rA;     // accumulator
1548     word36   rQ;     // quotient
1549 
1550     fault_acv_subtype_  acvFaults;   // pending ACV faults
1551 
1552     sdw_s * SDW; // working SDW
1553 
1554     // Zone mask
1555     word36 zone;
1556 
1557     ptw_s * PTW;
1558 
1559     word36 CY;              // C(Y) operand data from memory
1560 
1561     uint64 lufCounter;
1562 
1563     _fault_subtype dlySubFltNum;
1564 
1565     const char * dlyCtx;
1566 
1567     word36 faultRegister [2];
1568 
1569     word36 itxPair [2];
1570 
1571 //#if defined(THREADZ) || defined(LOCKLESS)
1572 //    struct timespec rTRTime; // time when rTR was set
1573 //#endif
1574 
1575     mode_register_s MR;
1576     // Changes to the mode register history bits do not take affect until
1577     // the next instruction (ISOLTS 700 2a). Cache the values here so
1578     // that post register updates can see the old values.
1579     mode_register_s MR_cache;
1580 
1581     DCDstruct currentInstruction;
1582 
1583     ou_unit_data_t ou;
1584 
1585     word36 Ypair[2];        // 2-words
1586     word36 Yblock8[8];      // 8-words
1587     word36 Yblock16[16];    // 16-words
1588     word36 Yblock32[32];    // 32-words
1589 
1590     word36 scu_data[8];     // For SCU instruction
1591 
1592     ctl_unit_data_t cu;
1593     du_unit_data_t du;
1594 
1595     switches_t switches;
1596     optionsType options;
1597     tweaksType tweaks;
1598     switches_t isolts_switches_save;
1599 
1600     jmp_buf jmpMain; // This is the entry to the CPU state machine
1601 
1602     unsigned long      faultCnt [N_FAULTS];
1603 
1604     _fault_subtype  g7SubFaults [N_FAULTS];
1605 
1606     word36 history [N_HIST_SETS] [N_MAX_HIST_SIZE] [2];
1607 
1608     cycles_e cycle;
1609 
1610     _fault faultNumber;      // fault number saved by doFault
1611 
1612     apu_unit_data_t apu;
1613 
1614     word27   rTR;    // timer [map: TR, 9 0's]
1615 #if defined(THREADZ) || defined(LOCKLESS)
1616     uint     rTRsample;
1617 #endif
1618 
1619     word24   rY;       // address operand
1620 
1621     word18 lnk;  // rpl link value
1622 
1623     uint g7FaultsPreset;
1624     uint g7Faults;
1625 
1626     word24 iefpFinalAddress;
1627 
1628     // ISOLTS fine grain TR estimation
1629     uint rTRlsb;
1630     uint shadowTR;
1631     uint TR0; // The value that the TR was set to.
1632 
1633     // Arguments for delayed overflow fault
1634     _fault dlyFltNum;
1635 
1636     word18 last_write;
1637 
1638 #ifdef LOCKLESS
1639     word24 locked_addr;
1640     word24 char_word_address;
1641 #endif
1642 
1643     word24 rmw_address;
1644 
1645     uint restart_address;
1646 
1647     struct
1648       {
1649         word15 PSR;
1650         word3  PRR;
1651         word18 IC;
1652       } cu_data;            // For STCD instruction
1653     uint rTRticks;
1654 
1655     struct tpr_s TPR;     // Temporary Pointer Register
1656     struct ppr_s PPR;     // Procedure Pointer Register
1657     struct dsbr_s DSBR;   // Descriptor Segment Base Register
1658     ptw0_s PTW0; // a PTW not in PTWAM (PTWx1)
1659 
1660     uint history_cyclic [N_HIST_SETS]; // 0..63
1661 
1662     sdw_s SDW0;  // a SDW not in SDWAM
1663     sdw_s _s;
1664 
1665     word18   rX [8]; // index
1666 
1667     // Nmber of banks in each SCU
1668     uint sc_num_banks [N_SCU_UNITS_MAX];
1669 
1670     // Caching some cabling data for interrupt handling.
1671     // When a CPU calls get_highest_intr(), it needs to know
1672     // what port on the SCU it is attached to. Because of port
1673     // expanders several CPUs can be attached to an SCU port,
1674     // mapping from the CPU to the SCU is easier to query
1675     uint scu_port[N_SCU_UNITS_MAX];
1676 
1677     // L68 FFV faults
1678 
1679      uint FFV_faults_preset;
1680      uint FFV_faults;
1681      uint FFV_fault_number;
1682 
1683 #ifdef AFFINITY
1684     uint affinity;
1685 #endif
1686 
1687     events_t events;
1688 
1689     word24 pad[16];
1690 
1691     struct par_s PAR [8]; // pointer/address registers
1692 
1693     ptw_s PTWAM [N_NAX_WAM_ENTRIES];
1694 
1695     // Map memory address through memory configuration switches
1696     // Minimum allocation chunk is 64K (SCBANK_SZ)
1697     // addr / SCBANK_SZ => bank_number
1698     // scbank_map[bank_number] is address of the bank in M. -1 is unmapped.
1699     int sc_addr_map [N_SCBANKS];
1700     // The SCU number holding each bank
1701     int sc_scu_map [N_SCBANKS];
1702 
1703     sdw_s SDWAM [N_NAX_WAM_ENTRIES]; // Segment Descriptor Word Associative Memory
1704 
1705     // Address Modification tally
1706     word12 AM_tally;
1707 
1708     struct bar_s BAR;     // Base Address Register
1709 
1710     cache_mode_register_s CMR;
1711 
1712     // The following are all from the control unit history register:
1713 
1714     bool interrupt_flag;     // an interrupt is pending in this cycle
1715     bool g7_flag;            // a g7 fault is pending in this cycle;
1716 
1717     bool wasXfer;      // The previous instruction was a transfer
1718 
1719     bool wasInhibited; // One or both of the previous instruction
1720                        // pair was interrupt inhibited.
1721 
1722     bool isExec;  // The instruction being executed is the target of
1723                   // an XEC or XED instruction
1724     bool isXED;   // The instruction being executed is the target of an
1725                   // XEC instruction
1726 
1727     bool  isolts_switches_saved;
1728 
1729     word8    rE;     // exponent [map: rE, 28 0's]
1730 
1731     word6    rTAG;     // instruction tag
1732     word3    rRALR;    // ring alarm [3b] [map: 33 0's, RALR]
1733     word3    RSDWH_R1; // Track the ring number of the last SDW
1734 
1735     // L68: word4
1736     // DPS8M: word6
1737     word6 SDWAMR;
1738 
1739     // Zone mask
1740     bool useZone;
1741 
1742     // L68: word4
1743     // DPS8M: word6
1744     word6 PTWAMR;
1745 
1746     // G7 faults
1747     bool bTroubleFaultCycle;
1748 
1749     bool lufOccurred;
1750     bool secret_addressing_mode;
1751     // Used by LCPR to prevent the LCPR instruction from being recorded
1752     // in the CU.
1753     bool skip_cu_hist;
1754 
1755     // If the instruction wants overflow thrown after operand write
1756     bool dlyFlt;
1757 
1758     bool restart;
1759 
1760     // L68 FFV faults
1761     bool is_FFV;
1762 
1763 #ifdef ROUND_ROBIN
1764     bool isRunning;
1765 #endif
1766 
1767 #ifdef AFFINITY
1768     bool set_affinity;
1769 #endif
1770 
1771 #ifdef SPEED
1772 # define SC_MAP_ADDR(addr,real_addr)                           \
1773    if (cpu.tweaks.useMap)                                      \
1774       {                                                        \
1775         uint pgnum = addr / SCBANK_SZ;                         \
1776         uint os = addr % SCBANK_SZ;                            \
1777         int base = cpu.sc_addr_map[pgnum];                     \
1778         if (base < 0)                                          \
1779           {                                                    \
1780             doFault (FAULT_STR, fst_str_nea,  __func__);       \
1781           }                                                    \
1782         real_addr = (uint) base + os;                          \
1783       }                                                        \
1784     else                                                       \
1785       real_addr = addr;
1786 #else
1787 # define SC_MAP_ADDR(addr,real_addr)                           \
1788    if (cpu.tweaks.useMap)                                      \
1789       {                                                        \
1790         uint pgnum = addr / SCBANK_SZ;                         \
1791         uint os = addr % SCBANK_SZ;                            \
1792         int base = cpu.sc_addr_map[pgnum];                     \
1793         if (base < 0)                                          \
1794           {                                                    \
1795             doFault (FAULT_STR, fst_str_nea,  __func__);       \
1796           }                                                    \
1797         real_addr = (uint) base + os;                          \
1798       }                                                        \
1799     else                                                       \
1800       {                                                        \
1801         nem_check (addr, __func__);                            \
1802         real_addr = addr;                                      \
1803       }
1804 #endif
1805 
1806 #ifdef PANEL68
1807     // Intermediate data collection for APU SCROLL
1808     word18 lastPTWOffset;
1809 // The L68 APU SCROLL 4U has an entry "ACSD"; I am interpreting it as
1810 //  on: lastPTRAddr was a DSPTW
1811 //  off: lastPTRAddr was a PTW
1812     bool lastPTWIsDS;
1813     word18 APUDataBusOffset;
1814     word24 APUDataBusAddr;
1815     word24 APUMemAddr;
1816     word1 panel4_red_ready_light_state;
1817     word1 panel7_enabled_light_state;
1818 // The state of the panel switches
1819     volatile word15 APU_panel_segno_sw;
1820     volatile word1  APU_panel_enable_match_ptw_sw;  // lock
1821     volatile word1  APU_panel_enable_match_sdw_sw;  // lock
1822     volatile word1  APU_panel_scroll_select_ul_sw;
1823     volatile word4  APU_panel_scroll_select_n_sw;
1824     volatile word4  APU_panel_scroll_wheel_sw;
1825     //volatile word18 APU_panel_addr_sw;
1826     volatile word18 APU_panel_enter_sw;
1827     volatile word18 APU_panel_display_sw;
1828     volatile word4  CP_panel_wheel_sw;
1829     volatile word4  DATA_panel_ds_sw;
1830     volatile word4  DATA_panel_d1_sw;
1831     volatile word4  DATA_panel_d2_sw;
1832     volatile word4  DATA_panel_d3_sw;
1833     volatile word4  DATA_panel_d4_sw;
1834     volatile word4  DATA_panel_d5_sw;
1835     volatile word4  DATA_panel_d6_sw;
1836     volatile word4  DATA_panel_d7_sw;
1837     volatile word4  DATA_panel_wheel_sw;
1838     volatile word4  DATA_panel_addr_stop_sw;
1839     volatile word1  DATA_panel_enable_sw;
1840     volatile word1  DATA_panel_validate_sw;
1841     volatile word1  DATA_panel_auto_fast_sw;  // lock
1842     volatile word1  DATA_panel_auto_slow_sw;  // lock
1843     volatile word4  DATA_panel_cycle_sw;      // lock
1844     volatile word1  DATA_panel_step_sw;       // lock
1845     volatile word1  DATA_panel_s_trig_sw;
1846     volatile word1  DATA_panel_execute_sw;    // lock
1847     volatile word1  DATA_panel_scope_sw;
1848     volatile word1  DATA_panel_init_sw;       // lock
1849     volatile word1  DATA_panel_exec_sw;       // lock
1850     volatile word4  DATA_panel_hr_sel_sw;
1851     volatile word4  DATA_panel_trackers_sw;
1852     volatile bool panelInitialize;
1853 
1854     // Intermediate data collection for DATA SCROLL
1855     bool portBusy;
1856     word2 portSelect;
1857     word36 portAddr [N_CPU_PORTS];
1858     word36 portData [N_CPU_PORTS];
1859     // Intermediate data collection for CU
1860     word36 IWRAddr;
1861     word7 dataMode; // 0100  9 bit
1862                     // 0040  6 bit
1863                     // 0020  4 bit
1864                     // 0010  1 bit
1865                     // 0004  36 bit
1866                     // 0002  alphanumeric
1867                     // 0001  numeric
1868     word8 prepare_state;
1869     bool DACVpDF;
1870     bool AR_F_E;
1871     bool INS_FETCH;
1872     // Control Points data acquisition
1873     word1 cpt [28] [36];
1874 #endif
1875 #define cpt1U  0  // Instruction processing tracking
1876 #define cpt1L  1  // Instruction processing tracking
1877 #define cpt2U  2  // Instruction execution tracking
1878 #define cpt2L  3  // Instruction execution tracking
1879 #define cpt3U  4  // Register usage
1880 #define cpt3L  5  // Register usage
1881 #define cpt4U  6
1882 #define cpt4L  7
1883 #define cpt5U  8
1884 #define cpt5L  9
1885 #define cpt6U  10
1886 #define cpt6L  11
1887 #define cpt7U  12
1888 #define cpt7L  13
1889 #define cpt8U  14
1890 #define cpt8L  15
1891 #define cpt9U  16
1892 #define cpt9L  17
1893 #define cpt10U 18
1894 #define cpt10L 19
1895 #define cpt11U 20
1896 #define cpt11L 21
1897 #define cpt12U 22
1898 #define cpt12L 23
1899 #define cpt13U 24
1900 #define cpt13L 25
1901 #define cpt14U 26
1902 #define cpt14L 27
1903 
1904 #define cptUseE    0
1905 #define cptUseBAR  1
1906 #define cptUseTR   2
1907 #define cptUseRALR 3
1908 #define cptUsePRn  4  // 4 - 11
1909 #define cptUseDSBR 12
1910 #define cptUseFR   13
1911 #define cptUseMR   14
1912 #define cptUseCMR  15
1913 #define cptUseIR   16
1914   } cpu_state_t;
1915 
1916 #ifdef M_SHARED
1917 extern cpu_state_t * cpus;
1918 #else
1919 extern cpu_state_t cpus [N_CPU_UNITS_MAX];
1920 #endif
1921 
1922 #if defined(THREADZ) || defined(LOCKLESS)
1923 extern __thread cpu_state_t * restrict cpup;
1924 #else
1925 extern cpu_state_t * restrict cpup;
1926 #endif
1927 #define cpu (* cpup)
1928 
1929 #define N_STALL_POINTS 16
1930 struct stall_point_s
1931   {
1932     word15 segno;
1933     word18 offset;
1934     useconds_t time;
1935   };
1936 extern struct stall_point_s stall_points [N_STALL_POINTS];
1937 extern bool stall_point_active;
1938 
1939 uint set_cpu_idx (uint cpuNum);
1940 #if defined(THREADZ) || defined(LOCKLESS)
1941 extern __thread uint current_running_cpu_idx;
1942 extern bool bce_dis_called;
1943 #else
1944 # ifdef ROUND_ROBIN
1945 extern uint current_running_cpu_idx;
1946 # else
1947 #  define current_running_cpu_idx 0
1948 # endif
1949 #endif
1950 
1951 // Support code to access ARn.BITNO, ARn.CHAR, PRn.BITNO
1952 
1953 #define GET_PR_BITNO(n) (cpu.PAR[n].PR_BITNO)
1954 #define GET_AR_BITNO(n) (cpu.PAR[n].AR_BITNO)
1955 #define GET_AR_CHAR(n) (cpu.PAR[n].AR_CHAR)
1956 static inline void SET_PR_BITNO (uint n, word6 b)
     /* [previous][next][first][last][top][bottom][index][help] */
1957   {
1958      cpu.PAR[n].PR_BITNO = b;
1959      cpu.PAR[n].AR_BITNO = (b % 9) & MASK4;
1960      cpu.PAR[n].AR_CHAR = (b / 9) & MASK2;
1961   }
1962 static inline void SET_AR_CHAR_BITNO (uint n, word2 c, word4 b)
     /* [previous][next][first][last][top][bottom][index][help] */
1963   {
1964      cpu.PAR[n].PR_BITNO = c * 9 + b;
1965      cpu.PAR[n].AR_BITNO = b & MASK4;
1966      cpu.PAR[n].AR_CHAR = c & MASK2;
1967   }
1968 
1969 bool sample_interrupts (void);
1970 t_stat simh_hooks (void);
1971 int operand_size (void);
1972 t_stat read_operand (word18 addr, processor_cycle_type cyctyp);
1973 t_stat write_operand (word18 addr, processor_cycle_type acctyp);
1974 
1975 #ifdef PANEL68
1976 static inline void trackport (word24 a, word36 d)
     /* [previous][next][first][last][top][bottom][index][help] */
1977   {
1978     // Simplifying assumption: 4 * 4MW SCUs
1979     word2 port = (a >> 22) & MASK2;
1980     cpu.portSelect = port;
1981     cpu.portAddr [port] = a;
1982     cpu.portData [port] = d;
1983     cpu.portBusy = false;
1984   }
1985 #endif
1986 
1987 #if defined(SPEED) && defined(INLINE_CORE)
1988 // Ugh. Circular dependencies XXX
1989 void doFault (_fault faultNumber, _fault_subtype faultSubtype,
     /* [previous][next][first][last][top][bottom][index][help] */
1990               const char * faultMsg) NO_RETURN;
1991 extern const _fault_subtype fst_str_nea;
1992 
1993 static inline int core_read (word24 addr, word36 *data, \
1994   UNUSED const char * ctx)
1995   {
1996     PNL (cpu.portBusy = true;)
1997     SC_MAP_ADDR (addr, addr);
1998     * data = M[addr] & DMASK;
1999 # ifdef TR_WORK_MEM
2000     cpu.rTRticks ++;
2001 # endif
2002     PNL (trackport (addr, * data);)
2003     return 0;
2004   }
2005 
2006 static inline int core_write (word24 addr, word36 data, \
     /* [previous][next][first][last][top][bottom][index][help] */
2007   UNUSED const char * ctx)
2008   {
2009     PNL (cpu.portBusy = true;)
2010     SC_MAP_ADDR (addr, addr);
2011     if (cpu.tweaks.isolts_mode)
2012       {
2013         if (cpu.MR.sdpap)
2014           {
2015             sim_warn ("failing to implement sdpap\n");
2016             cpu.MR.sdpap = 0;
2017           }
2018         if (cpu.MR.separ)
2019           {
2020             sim_warn ("failing to implement separ\n");
2021             cpu.MR.separ = 0;
2022           }
2023      }
2024     M[addr] = data & DMASK;
2025 # ifdef TR_WORK_MEM
2026     cpu.rTRticks ++;
2027 # endif
2028     PNL (trackport (addr, data);)
2029     return 0;
2030   }
2031 
2032 static inline int core_write_zone (word24 addr, word36 data, \
     /* [previous][next][first][last][top][bottom][index][help] */
2033   UNUSED const char * ctx)
2034   {
2035     PNL (cpu.portBusy = true;)
2036     SC_MAP_ADDR (addr, addr);
2037     if (cpu.tweaks.isolts_mode)
2038       {
2039         if (cpu.MR.sdpap)
2040           {
2041             sim_warn ("failing to implement sdpap\n");
2042             cpu.MR.sdpap = 0;
2043           }
2044         if (cpu.MR.separ)
2045           {
2046             sim_warn ("failing to implement separ\n");
2047             cpu.MR.separ = 0;
2048           }
2049       }
2050     M[addr] = (M[addr] & ~cpu.zone) | (data & cpu.zone);
2051     cpu.useZone = false; // Safety
2052 # ifdef TR_WORK_MEM
2053     cpu.rTRticks ++;
2054 # endif
2055     PNL (trackport (addr, data);)
2056     return 0;
2057   }
2058 
2059 static inline int core_read2 (word24 addr, word36 *even, word36 *odd,
     /* [previous][next][first][last][top][bottom][index][help] */
2060                               UNUSED const char * ctx)
2061   {
2062     PNL (cpu.portBusy = true;)
2063     SC_MAP_ADDR (addr, addr);
2064     *even = M[addr++] & DMASK;
2065     *odd = M[addr] & DMASK;
2066 # ifdef TR_WORK_MEM
2067     cpu.rTRticks ++;
2068 # endif
2069     PNL (trackport (addr - 1, * even);)
2070     return 0;
2071   }
2072 
2073 static inline int core_write2 (word24 addr, word36 even, word36 odd,
     /* [previous][next][first][last][top][bottom][index][help] */
2074                                UNUSED const char * ctx)
2075   {
2076     PNL (cpu.portBusy = true;)
2077     SC_MAP_ADDR (addr, addr);
2078     if (cpu.tweaks.isolts_mode)
2079       {
2080         if (cpu.MR.sdpap)
2081           {
2082             sim_warn ("failing to implement sdpap\n");
2083             cpu.MR.sdpap = 0;
2084           }
2085         if (cpu.MR.separ)
2086           {
2087             sim_warn ("failing to implement separ\n");
2088             cpu.MR.separ = 0;
2089           }
2090       }
2091     M[addr++] = even;
2092     M[addr] = odd;
2093     PNL (trackport (addr - 1, even);)
2094 # ifdef TR_WORK_MEM
2095     cpu.rTRticks ++;
2096 # endif
2097     return 0;
2098   }
2099 #else
2100 int core_read (word24 addr, word36 *data, const char * ctx);
2101 int core_write (word24 addr, word36 data, const char * ctx);
2102 int core_write_zone (word24 addr, word36 data, const char * ctx);
2103 int core_read2 (word24 addr, word36 *even, word36 *odd, const char * ctx);
2104 int core_write2 (word24 addr, word36 even, word36 odd, const char * ctx);
2105 #endif // defined(SPEED) && defined(INLINE_CORE)
2106 
2107 #ifdef LOCKLESS
2108 
2109 /*
2110  * Atomic operations to use defined as follows:
2111  *
2112  *  AIX_ATOMICS  -  IBM AIX atomics
2113  *  BSD_ATOMICS  -  FreeBSD atomics
2114  *  GNU_ATOMICS  -  GNU atomics
2115  * SYNC_ATOMICS  -  GNU sync-style atomics
2116  *
2117  * The following are reserved and not yet implemented:
2118  *
2119  *  ISO_ATOMICS  -  ISO/IEC 9899:2011 (C11) atomics
2120  *   NT_ATOMICS  -  Microsoft Windows NT atomics
2121  *
2122  * For further details, see:
2123  *
2124  * AIX_ATOMICS:
2125  *  https://www.ibm.com/docs/en/aix/7.3?topic=services-atomic-operations
2126  *
2127  * BSD_ATOMICS:
2128  *  https://www.freebsd.org/cgi/man.cgi?query=atomic&sektion=9&format=html
2129  *  https://man.dragonflybsd.org/?command=atomic&section=9
2130  *
2131  * GNU_ATOMICS:
2132  *  https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
2133  *
2134  * SYNC_ATOMICS:
2135  *  https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
2136  *
2137  * ISO_ATOMICS:
2138  *  https://en.cppreference.com/w/c/atomic
2139  *
2140  * NT_ATOMICS:
2141  *  https://docs.microsoft.com/en-us/windows/win32/sync/synchronization-functions
2142  *  https://docs.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access
2143  */
2144 
2145 // AIX_ATOMICS are SYNC_ATOMICS (for now)
2146 # if ( defined (AIX_ATOMICS) && \
2147    (! (defined (SYNC_ATOMICS))))
2148 #  define SYNC_ATOMICS 1
2149 # endif
2150 
2151 // FreeBSD atomics (default on for FreeBSD)
2152 # if (! defined (GNU_ATOMICS)) && (! defined (SYNC_ATOMICS)) && \
2153      (! defined (BSD_ATOMICS)) && (! defined (AIX_ATOMICS))
2154 #  if defined(__FreeBSD__) \
2155   || defined(__FreeBSD_kernel__) \
2156   || defined(__DragonFly__)
2157 #   undef BSD_ATOMICS
2158 #   define BSD_ATOMICS 1
2159 #  endif
2160 # endif
2161 
2162 // Otherwise, default to GNU_ATOMICS
2163 # if (! defined (GNU_ATOMICS)) && (! defined (BSD_ATOMICS)) && \
2164      (! defined (SYNC_ATOMICS)) && (! defined (AIX_ATOMICS))
2165 #  undef GNU_ATOMICS
2166 #  define GNU_ATOMICS 1
2167 # endif
2168 
2169 int core_read_lock (word24 addr, word36 *data, const char * ctx);
2170 int core_write_unlock (word24 addr, word36 data, const char * ctx);
2171 int core_unlock_all(void);
2172 
2173 # define DEADLOCK_DETECT   0x40000000U
2174 # define MEM_LOCKED_BIT    61
2175 # define MEM_LOCKED        (1LLU<<MEM_LOCKED_BIT)
2176 
2177 # ifndef SCHED_NEVER_YIELD
2178 #  undef SCHED_YIELD
2179 #  define SCHED_YIELD                                                    \
2180   do                                                                     \
2181     {                                                                    \
2182       if ((i & 0xff) == 0)                                               \
2183         {                                                                \
2184           sched_yield();                                                 \
2185           cpu.lockYield++;                                               \
2186         }                                                                \
2187     }                                                                    \
2188   while(0)
2189 # else
2190 #  undef SCHED_YIELD
2191 #  define SCHED_YIELD                                                    \
2192   do                                                                     \
2193     {                                                                    \
2194     }                                                                    \
2195   while(0)
2196 # endif /* ifndef SCHED_NEVER_YIELD */
2197 
2198 # if defined (BSD_ATOMICS)
2199 #  include <machine/atomic.h>
2200 
2201 #  define LOCK_CORE_WORD(addr)                                           \
2202   do                                                                     \
2203     {                                                                    \
2204       unsigned int i = DEADLOCK_DETECT;                                  \
2205       while ( atomic_testandset_64((volatile uint64_t *)&M[addr],        \
2206             MEM_LOCKED_BIT) == 1 && i > 0)                               \
2207         {                                                                \
2208           i--;                                                           \
2209           SCHED_YIELD;                                                   \
2210         }                                                                \
2211       if (i == 0)                                                        \
2212         {                                                                \
2213           sim_warn ("%s: locked %x addr %x deadlock\n", __func__,        \
2214               cpu.locked_addr, addr);                                    \
2215         }                                                                \
2216       cpu.lockCnt++;                                                     \
2217       if (i == DEADLOCK_DETECT)                                          \
2218         cpu.lockImmediate++;                                             \
2219       cpu.lockWait += (DEADLOCK_DETECT-i);                               \
2220       cpu.lockWaitMax = ((DEADLOCK_DETECT-i) > cpu.lockWaitMax) ?        \
2221           (DEADLOCK_DETECT-i) : cpu.lockWaitMax;                         \
2222     }                                                                    \
2223   while (0)
2224 
2225 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2226   do                                                                     \
2227     {                                                                    \
2228       res = atomic_load_acq_64((volatile uint64_t *)&M[addr]);           \
2229     }                                                                    \
2230   while (0)
2231 
2232 #  define STORE_REL_CORE_WORD(addr, data)                                \
2233   do                                                                     \
2234     {                                                                    \
2235       atomic_store_rel_64((volatile uint64_t *)&M[addr], data & DMASK);  \
2236     }                                                                    \
2237   while (0)
2238 
2239 # endif // BSD_ATOMICS
2240 
2241 # if defined(GNU_ATOMICS)
2242 
2243 #  define LOCK_CORE_WORD(addr)                                           \
2244   do                                                                     \
2245     {                                                                    \
2246       unsigned int i = DEADLOCK_DETECT;                                  \
2247       while ((__atomic_fetch_or((volatile uint64_t *)&M[addr],           \
2248         MEM_LOCKED, __ATOMIC_ACQ_REL) & MEM_LOCKED)                      \
2249                 && i > 0)                                                \
2250     {                                                                    \
2251       i--;                                                               \
2252       SCHED_YIELD;                                                       \
2253     }                                                                    \
2254       if (i == 0)                                                        \
2255         {                                                                \
2256           sim_warn ("%s: locked %x addr %x deadlock\n",                  \
2257             __func__, cpu.locked_addr, addr);                            \
2258         }                                                                \
2259       cpu.lockCnt++;                                                     \
2260       if (i == DEADLOCK_DETECT)                                          \
2261           cpu.lockImmediate++;                                           \
2262       cpu.lockWait += (DEADLOCK_DETECT-i);                               \
2263       cpu.lockWaitMax = ((DEADLOCK_DETECT-i) >                           \
2264           cpu.lockWaitMax) ? (DEADLOCK_DETECT-i) :                       \
2265               cpu.lockWaitMax;                                           \
2266     }                                                                    \
2267   while (0)
2268 
2269 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2270   do                                                                     \
2271     {                                                                    \
2272       res = __atomic_load_n((volatile uint64_t *)&M[addr],               \
2273           __ATOMIC_ACQUIRE);                                             \
2274     }                                                                    \
2275   while (0)
2276 
2277 #  define STORE_REL_CORE_WORD(addr, data)                                \
2278   do                                                                     \
2279     {                                                                    \
2280       __atomic_store_n((volatile uint64_t *)&M[addr], data &             \
2281           DMASK, __ATOMIC_RELEASE);                                      \
2282     }                                                                    \
2283   while (0)
2284 
2285 # endif // GNU_ATOMICS
2286 
2287 # if defined(SYNC_ATOMICS)
2288 #  ifdef MEMORY_ACCESS_NOT_STRONGLY_ORDERED
2289 #   define MEM_BARRIER()   do { __sync_synchronize(); } while (0)
2290 #  else
2291 #   define MEM_BARRIER()   do {} while (0)
2292 #  endif
2293 
2294 #  define LOCK_CORE_WORD(addr)                                           \
2295      do                                                                  \
2296        {                                                                 \
2297          unsigned int i = DEADLOCK_DETECT;                               \
2298          while ((__sync_fetch_and_or((volatile uint64_t *)&M[addr],      \
2299              MEM_LOCKED) & MEM_LOCKED) && i > 0)                         \
2300            {                                                             \
2301             i--;                                                         \
2302             SCHED_YIELD;                                                 \
2303            }                                                             \
2304          if (i == 0)                                                     \
2305            {                                                             \
2306             sim_warn ("%s: locked %x addr %x deadlock\n", __func__,      \
2307                 cpu.locked_addr, addr);                                  \
2308             }                                                            \
2309          cpu.lockCnt++;                                                  \
2310          if (i == DEADLOCK_DETECT)                                       \
2311            cpu.lockImmediate++;                                          \
2312          cpu.lockWait += (DEADLOCK_DETECT-i);                            \
2313          cpu.lockWaitMax = ((DEADLOCK_DETECT-i) > cpu.lockWaitMax) ?     \
2314              (DEADLOCK_DETECT-i) : cpu.lockWaitMax;                      \
2315        }                                                                 \
2316      while (0)
2317 
2318 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2319      do                                                                  \
2320        {                                                                 \
2321          res = M[addr];                                                  \
2322          MEM_BARRIER();                                                  \
2323        }                                                                 \
2324      while (0)
2325 
2326 #  define STORE_REL_CORE_WORD(addr, data)                                \
2327   do                                                                     \
2328     {                                                                    \
2329       MEM_BARRIER();                                                     \
2330       M[addr] = data & DMASK;                                            \
2331     }                                                                    \
2332   while (0)
2333 
2334 # endif  // SYNC_ATOMICS
2335 #endif  // LOCKLESS
2336 
2337 static inline void core_readN (word24 addr, word36 * data, uint n,
     /* [previous][next][first][last][top][bottom][index][help] */
2338                                UNUSED const char * ctx)
2339   {
2340     for (uint i = 0; i < n; i ++)
2341       {
2342         core_read (addr + i, data + i, ctx);
2343         //HDBGMRead (addr + i, * (data + i), __func__);
2344       }
2345   }
2346 
2347 static inline void core_writeN (word24 addr, word36 * data, uint n,
     /* [previous][next][first][last][top][bottom][index][help] */
2348                                 UNUSED const char * ctx)
2349   {
2350     for (uint i = 0; i < n; i ++)
2351       {
2352         core_write (addr + i, data [i], ctx);
2353         //HDBGMWrite (addr + i, * (data + i), __func__);
2354       }
2355   }
2356 
2357 int is_priv_mode (void);
2358 //void set_went_appending (void);
2359 //void clr_went_appending (void);
2360 //bool get_went_appending (void);
2361 bool get_bar_mode (void);
2362 addr_modes_e get_addr_mode (void);
2363 void set_addr_mode (addr_modes_e mode);
2364 void decode_instruction (word36 inst, DCDstruct * p);
2365 #ifndef SPEED
2366 t_stat set_mem_watch (int32 arg, const char * buf);
2367 #endif
2368 char *str_SDW0 (char * buf, sdw_s *SDW);
2369 int lookup_cpu_mem_map (word24 addr);
2370 void cpu_init (void);
2371 void setup_scbank_map (void);
2372 void add_dps8m_CU_history (void);
2373 void add_dps8m_DUOU_history (word36 flags, word18 ICT, word9 RS_REG, word9 flags2);
2374 void add_dps8m_APU_history (word15 ESN, word21 flags, word24 RMA, word3 RTRR, word9 flags2);
2375 void add_dps8m_EAPU_history (word18 ZCA, word18 opcode);
2376 void add_l68_CU_history (void);
2377 void add_l68_OU_history (void);
2378 void add_l68_DU_history (void);
2379 void add_l68_APU_history (enum APUH_e op);
2380 void add_history_force (uint hset, word36 w0, word36 w1);
2381 void printPtid(pthread_t pt);
2382 word18 get_BAR_address(word18 addr);
2383 #if defined(THREADZ) || defined(LOCKLESS)
2384 t_stat threadz_sim_instr (void);
2385 void * cpu_thread_main (void * arg);
2386 #endif
2387 void cpu_reset_unit_idx (UNUSED uint cpun, bool clear_mem);
2388 void setupPROM (uint cpuNo, unsigned char * PROM);

/* [previous][next][first][last][top][bottom][index][help] */