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

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