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

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