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

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