root/src/dps8/dps8_cpu.h

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

INCLUDED FROM


DEFINITIONS

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

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 72d91a53-f62d-11ec-a98f-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2022 Charles Anthony
  11  * Copyright (c) 2015-2021 Eric Swenson
  12  * Copyright (c) 2021-2025 The DPS8M Development Team
  13  *
  14  * This software is made available under the terms of the ICU License.
  15  * See the LICENSE.md file at the top-level directory of this distribution.
  16  *
  17  * ---------------------------------------------------------------------------
  18  */
  19 
  20 #if !defined(__STDC_WANT_IEC_60559_BFP_EXT__)
  21 # define __STDC_WANT_IEC_60559_BFP_EXT__ 1
  22 #endif /* if !defined(__STDC_WANT_IEC_60559_BFP_EXT__) */
  23 
  24 #include <sys/types.h>
  25 
  26 #if defined(__APPLE__)
  27 # undef SCHED_NEVER_YIELD
  28 # define SCHED_NEVER_YIELD 1
  29 # include <mach/thread_policy.h>
  30 # include <mach/task_info.h>
  31 # include <sys/types.h>
  32 # include <sys/sysctl.h>
  33 # include <mach/thread_policy.h>
  34 # include <mach/thread_act.h>
  35 #endif /* if defined(__APPLE__) */
  36 
  37 #include "../simh/sim_timer.h"
  38 #include "hdbg.h"
  39 
  40 extern unsigned int nprocs;
  41 
  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     volAtomic int fault [N_FAULT_GROUPS];
 691                             // only one fault in groups 1..6 can be pending
 692     volAtomic 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 } tweaksType;
 746 
 747 enum ou_cycle_e
 748   {
 749     ou_GIN = 0400,
 750     ou_GOS = 0200,
 751     ou_GD1 = 0100,
 752     ou_GD2 = 0040,
 753     ou_GOE = 0020,
 754     ou_GOA = 0010,
 755     ou_GOM = 0004,
 756     ou_GON = 0002,
 757     ou_GOF = 0001
 758   };
 759 
 760 typedef struct
 761   {
 762     // Operations Unit/Address Modification
 763     bool   directOperandFlag;
 764     word36 directOperand;
 765     word6  characterOperandSize; // just the left most bit
 766     word3  characterOperandOffset;
 767     word18 character_address;
 768     word36 character_data;
 769     bool crflag;
 770 
 771     // L68 only
 772     word2 eac;
 773     word1 RB1_FULL;
 774     word1 RP_FULL;
 775     word1 RS_FULL;
 776     word9 cycle;
 777     word1 STR_OP;
 778     // End L68 only
 779 
 780 #if defined(PANEL68)
 781     word9 RS;
 782     word4 opsz;
 783     word10 reguse;
 784 #endif /* if defined(PANEL68) */
 785   } ou_unit_data_t;
 786 
 787 // APU history operation parameter
 788 
 789 enum APUH_e
 790   {
 791     APUH_FDSPTW = 1llu << (35 - 17),
 792     APUH_MDSPTW = 1llu << (35 - 18),
 793     APUH_FSDWP  = 1llu << (35 - 19),
 794     APUH_FPTW   = 1llu << (35 - 20),
 795     APUH_FPTW2  = 1llu << (35 - 21),
 796     APUH_MPTW   = 1llu << (35 - 22),
 797     APUH_FANP   = 1llu << (35 - 23),
 798     APUH_FAP    = 1llu << (35 - 24)
 799   };
 800 
 801 enum {
 802 //   AL39 pg 64 APU hist.
 803         apu_FLT = 1ll << (33 -  0), //  0   l FLT Access violation or directed
 804                                     //            fault on this cycle
 805                                     //  1-2 a BSY    Data source for ESN
 806     apu_ESN_PSR = 0,                //                  00 PPR.PSR
 807     apu_ESN_SNR = 1ll << (33 -  1), //                  01 PRn.SNR
 808     apu_ESN_TSR = 1ll << (33 -  2), //                  10 TPR.TSR
 809                                     //                  11 not used
 810                                     //  3     PRAP
 811        apu_HOLD = 1ll << (33 -  4), //  4     HOLD  An access violation or
 812                                     //              directed fault is waiting
 813                                     //  5     FRIW
 814                                     //  6     XSF
 815                                     //  7     STF
 816        apu_TP_P = 1ll << (33 -  8), //  8     TP P    Guessing PPR.p set from
 817                                     //                SDW.P
 818        apu_PP_P = 1ll << (33 -  9), //  9     PP P    PPR.P?
 819                                     // 10     ?
 820                                     // 11     S-ON   Segment on?
 821                                     // 12     ZMAS
 822                                     // 13     SDMF   Seg. Descr. Modify?
 823                                     // 14     SFND
 824                                     // 15     ?
 825                                     // 16     P-ON   Page on?
 826                                     // 17     ZMAP
 827                                     // 18     PTMF
 828                                     // 19     PFND
 829       apu_FDPT  = 1ll << (33 - 20), // 20   b FDPT   Fetch descriptor segment PTW
 830       apu_MDPT  = 1ll << (33 - 21), // 21   c MDPT   Modify descriptor segment PTW
 831       apu_FSDP  = 1ll << (33 - 22), // 22   d FSDP   Fetch SDW paged descr. seg.
 832       apu_FSDN  = 1ll << (33 - 23), // 23     FSDN   Fetch SDW non-paged
 833       apu_FPTW  = 1ll << (33 - 24), // 24   e FPTW   Fetch PTW
 834       apu_MPTW  = 1ll << (33 - 25), // 25   g MPTW   Modify PTW
 835       apu_FPTW2 = 1ll << (33 - 26), // 26   f FPT2   // Fetch prepage
 836       apu_FAP   = 1ll << (33 - 27), // 27   i FAP    Final address fetch from
 837                                     //               paged seg.
 838       apu_FANP  = 1ll << (33 - 28), // 28   h FANP   Final address fetch from
 839                                     //               non-paged segment
 840                                     // 29     FAAB   Final address absolute?
 841       apu_FA    = 1ll << (33 - 30), // 30     FA     Final address?
 842                                     // 31     EAAU
 843       apu_PIAU  = 1ll << (33 - 32)  // 32     PIAU   Instruction fetch?
 844                                     // 33     TGAU
 845   };
 846 
 847 typedef struct
 848   {
 849     processor_cycle_type lastCycle;
 850 #if defined(PANEL68)
 851     word34 state;
 852 #endif /* if defined(PANEL68) */
 853   } apu_unit_data_t;
 854 
 855 typedef struct
 856   {
 857     // NB: Some of the data normally stored here is represented
 858     // elsewhere -- e.g.,the PPR is a variable outside of this
 859     // struct.   Other data is live and only stored here.
 860 
 861     // This is a collection of flags and registers from the
 862     // appending unit and the control unit.  The scu and rcu
 863     // instructions store and load these values to an 8 word
 864     // memory block.
 865     //
 866     // The CU data may only be valid for use with the scu and
 867     // rcu instructions.
 868     //
 869     // Comments indicate format as stored in 8 words by the scu
 870     // instruction.
 871 
 872     // NOTE: PPR (procedure pointer register) is a combination of registers:
 873     //   From the Appending Unit
 874     //     PRR bits [0..2] of word 0
 875     //     PSR bits [3..17] of word 0
 876     //     P   bit 18 of word 0
 877     //   From the Control Unit
 878     //     IC  bits [0..17] of word 4
 879 
 880     /* word 0 */
 881                    // 0-2   PRR is stored in PPR
 882                    // 3-17  PSR is stored in PPR
 883                    // 18    P   is stored in PPR
 884     word1 XSF;     // 19    XSF External segment flag
 885     word1 SDWAMM;  // 20    SDWAMM Match on SDWAM
 886     word1 SD_ON;   // 21    SDWAM enabled
 887     word1 PTWAMM;  // 22    PTWAMM Match on PTWAM
 888     word1 PT_ON;   // 23    PTWAM enabled
 889 
 890 
 891 
 892 
 893 
 894 
 895 
 896 
 897 
 898 
 899 
 900 
 901 
 902     word12 APUCycleBits;
 903 
 904 
 905     /* word 1 */
 906                    //                 AVF Access Violation Fault
 907                    //                 SF  Store Fault
 908                    //                 IPF Illegal Procedure Fault
 909                    //
 910     word1 IRO_ISN; //  0    IRO       AVF Illegal Ring Order
 911                    //       ISN       SF  Illegal segment number
 912     word1 OEB_IOC; //  1    ORB       AVF Out of execute bracket [sic] should
 913                    //                     be OEB?
 914                    //       IOC       IPF Illegal op code
 915     word1 EOFF_IAIM;
 916                    //  2    E-OFF     AVF Execute bit is off
 917                    //       IA+IM     IPF Illegal address of modifier
 918     word1 ORB_ISP; //  3    ORB       AVF Out of read bracket
 919                    //       ISP       IPF Illegal slave procedure
 920     word1 ROFF_IPR;//  4    R-OFF     AVF Read bit is off
 921                    //       IPR       IPF Illegal EIS digit
 922     word1 OWB_NEA; //  5    OWB       AVF Out of write bracket
 923                    //       NEA       SF  Nonexistent address
 924     word1 WOFF_OOB;//  6    W-OFF     AVF Write bit is off
 925                    //       OOB       SF  Out of bounds (BAR mode)
 926     word1 NO_GA;   //  7    NO GA     AVF Not a gate
 927     word1 OCB;     //  8    OCB       AVF Out of call bracket
 928     word1 OCALL;   //  9    OCALL     AVF Outward call
 929     word1 BOC;     // 10    BOC       AVF Bad outward call
 930 // PTWAM error is DPS8M only
 931     word1 PTWAM_ER;// 11    PTWAM_ER  AVF PTWAM error // inward return
 932     word1 CRT;     // 12    CRT       AVF Cross ring transfer
 933     word1 RALR;    // 13    RALR      AVF Ring alarm
 934 // On DPS8M a SDWAM error, on DP8/L68 a WAM error
 935     word1 SDWAM_ER;// 14    SWWAM_ER  AVF SDWAM error
 936     word1 OOSB;    // 15    OOSB      AVF Out of segment bounds
 937     word1 PARU;    // 16    PARU      Parity fault - processor parity upper
 938     word1 PARL;    // 17    PARL      Parity fault - processor parity lower
 939     word1 ONC1;    // 18    ONC1      Operation not complete fault error #1
 940     word1 ONC2;    // 19    ONC2      Operation not complete fault error #2
 941     word4 IA;      // 20-23 IA        System control illegal action lines
 942     word3 IACHN;   // 24-26 IACHN     Illegal action processor port
 943     word3 CNCHN;   // 27-29 CNCHN     Connect fault - connect processor port
 944     word5 FI_ADDR; // 30-34 F/I ADDR  Modulo 2 fault/interrupt vector address
 945     word1 FLT_INT; // 35    F/I       0 = interrupt; 1 = fault
 946 
 947     /* word 2 */
 948                    //  0- 2 TRR
 949                    //  3-17 TSR
 950                    // 18-21 PTW
 951                    //                  18  PTWAM levels A, B enabled
 952                    //                  19  PTWAM levels C, D enabled
 953                    //                  20  PTWAM levels A, B match
 954                    //                  21  PTWAM levels C, D match
 955                    // 22-25 SDW
 956                    //                  22  SDWAM levels A, B enabled
 957                    //                  23  SDWAM levels C, D enabled
 958                    //                  24  SDWAM levels A, B match
 959                    //                  25  SDWAM levels C, D match
 960                    // 26             0
 961                    // 27-29 CPU      CPU Number
 962     word6 delta;   // 30-35 DELTA    addr increment for repeats
 963 
 964     /* word 3 */
 965                    //  0-17          0
 966                    // 18-21 TSNA     Pointer register number for non-EIS
 967                    //                operands or EIS Operand #1
 968                    //                  18-20 PRNO Pointer register number
 969                    //                  21       PRNO is valid
 970                    // 22-25 TSNB     Pointer register number for EIS operand #2
 971                    //                  22-24 PRNO Pointer register number
 972                    //                  25       PRNO is valid
 973                    // 26-29 TSNC     Pointer register number for EIS operand #2
 974                    //                  26-28 PRNO Pointer register number
 975                    //                  29       PRNO is valid
 976     word3 TSN_PRNO [3];
 977     word1 TSN_VALID [3];
 978 
 979                    // 30-35 TEMP BIT Current bit offset (TPR.TBR)
 980 
 981     /* word 4 */
 982                    //  0-17 PPR.IC
 983     word18 IR;     // 18-35 Indicator register
 984                    //    18 ZER0
 985                    //    19 NEG
 986                    //    20 CARY
 987                    //    21 OVFL
 988                    //    22 EOVF
 989                    //    23 EUFL
 990                    //    24 OFLM
 991                    //    25 TRO
 992                    //    26 PAR
 993                    //    27 PARM
 994                    //    28 -BM
 995                    //    29 TRU
 996                    //    30 MIF
 997                    //    31 ABS
 998                    //    32 HEX [sic] Figure 3-32 is wrong.
 999                    // 33-35 0
1000 
1001     /* word 5 */
1002 
1003                    //  0-17 COMPUTED ADDRESS (TPR.CA)
1004     word1 repeat_first;
1005                    // 18    RF  First cycle of all repeat instructions
1006     word1 rpt;     // 19    RPT Execute an Repeat (rpt) instruction
1007     word1 rd;      // 20    RD  Execute an Repeat Double (rpd) instruction
1008     word1 rl;      // 21    RL  Execute a Repeat Link (rpl) instruction
1009     word1 pot;     // 22    POT Prepare operand tally
1010                    // 23    PON Prepare operand no tally
1011     //xde xdo
1012     // 0   0   no execute           -> 0 0
1013     // 1   0   execute XEC          -> 0 0
1014     // 1   1   execute even of XED  -> 0 1
1015     // 0   1   execute odd of XED   -> 0 0
1016     word1 xde;     // 24    XDE Execute instruction from Execute Double even
1017                    //       pair
1018     word1 xdo;     // 25    XDO Execute instruction from Execute Double odd pair
1019     word1 itp;     // 26    ITP Execute ITP indirect cycle
1020     word1 rfi;     // 27    RFI Restart this instruction
1021     word1 its;     // 28    ITS Execute ITS indirect cycle
1022     word1 FIF;     // 29    FIF Fault occurred during instruction fetch
1023     word6 CT_HOLD; // 30-35 CT HOLD contents of the "remember modifier" register
1024 
1025     /* word 6 */
1026     word36 IWB;
1027 
1028     /* word 7 */
1029     word36 IRODD; /* Instr holding register; odd word of last pair fetched */
1030  } ctl_unit_data_t;
1031 
1032 #define USE_IRODD (cpu.cu.rd && ((cpu. PPR.IC & 1) != 0))
1033 #define IWB_IRODD (USE_IRODD ? cpu.cu.IRODD : cpu.cu.IWB)
1034 
1035 // L68 only
1036 enum du_cycle1_e
1037   {
1038     //  0 -FPOL Prepare operand length
1039     du1_nFPOL        = 0400000000000ull,
1040     //  1 -FPOP Prepare operand pointer
1041     du1_nFPOP        = 0200000000000ull,
1042     //  2 -NEED-DESC Need descriptor
1043     du1_nNEED_DESC   = 0100000000000ull,
1044     //  3 -SEL-ADR Select address register
1045     du1_nSEL_DIR     = 0040000000000ull,
1046     //  4 -DLEN=DIRECT Length equals direct
1047     du1_nDLEN_DIRECT = 0020000000000ull,
1048     //  5 -DFRST Descriptor processed for first time
1049     du1_nDFRST       = 0010000000000ull,
1050     //  6 -FEXR Extended register modification
1051     du1_nFEXR        = 0004000000000ull,
1052     //  7 -DLAST-FRST Last cycle of DFRST
1053     du1_nLAST_DFRST  = 0002000000000ull,
1054     //  8 -DDU-LDEA Decimal unit load  (lpl?)
1055     du1_nDDU_LDEA    = 0001000000000ull,
1056     //  9 -DDU-STAE Decimal unit store (spl?)
1057     du1_nDDU_STEA    = 0000400000000ull,
1058     // 10 -DREDO Redo operation without pointer and length update
1059     du1_nDREDO       = 0000200000000ull,
1060     // 11 -DLVL<WD-SZ Load with count less than word size
1061     du1_nDLVL_WD_SZ  = 0000100000000ull,
1062     // 12 -EXH Exhaust
1063     du1_nEXH         = 0000040000000ull,
1064     // 13 DEND-SEQ End of sequence
1065     du1_DEND_SEQ     = 0000020000000ull,
1066     // 14 -DEND End of instruction
1067     du1_nEND         = 0000010000000ull,
1068     // 15 -DU=RD+WRT Decimal unit write-back
1069     du1_nDU_RD_WRT   = 0000004000000ull,
1070     // 16 -PTRA00 PR address bit 0
1071     du1_nPTRA00      = 0000002000000ull,
1072     // 17 -PTRA01 PR address bit 1
1073     du1_nPTRA01      = 0000001000000ull,
1074     // 18 FA/Il Descriptor l active
1075     du1_FA_I1        = 0000000400000ull,
1076     // 19 FA/I2 Descriptor 2 active
1077     du1_FA_I2        = 0000000200000ull,
1078     // 20 FA/I3 Descriptor 3 active
1079     du1_FA_I3        = 0000000100000ull,
1080     // 21 -WRD Word operation
1081     du1_nWRD         = 0000000040000ull,
1082     // 22 -NINE 9-bit character operation
1083     du1_nNINE        = 0000000020000ull,
1084     // 23 -SIX 6-bit character operation
1085     du1_nSIX         = 0000000010000ull,
1086     // 24 -FOUR 4-bit character operation
1087     du1_nFOUR        = 0000000004000ull,
1088     // 25 -BIT Bit operation
1089     du1_nBIT         = 0000000002000ull,
1090     // 26 Unused
1091     //               = 0000000001000ull,
1092     // 27 Unused
1093     //               = 0000000000400ull,
1094     // 28 Unused
1095     //               = 0000000000200ull,
1096     // 29 Unused
1097     //               = 0000000000100ull,
1098     // 30 FSAMPL Sample for mid-instruction interrupt
1099     du1_FSAMPL       = 0000000000040ull,
1100     // 31 -DFRST-CT Specified first count of a sequence
1101     du1_nDFRST_CT    = 0000000000020ull,
1102     // 32 -ADJ-LENGTH Adjust length
1103     du1_nADJ_LENTGH  = 0000000000010ull,
1104     // 33 -INTRPTD Mid-instruction interrupt
1105     du1_nINTRPTD     = 0000000000004ull,
1106     // 34 -INHIB Inhibit STC1 (force "STC0")
1107     du1_nINHIB       = 0000000000002ull,
1108     // 35 Unused
1109     //               = 0000000000001ull,
1110   };
1111 
1112 // L68 only
1113 enum du_cycle2_e
1114   {
1115     // 36 DUD Decimal unit idle
1116     du2_DUD          = 0400000000000ull,
1117     // 37 -GDLDA Descriptor load gate A
1118     du2_nGDLDA       = 0200000000000ull,
1119     // 38 -GDLDB Descriptor load gate B
1120     du2_nGDLDB       = 0100000000000ull,
1121     // 39 -GDLDC Descriptor load gate C
1122     du2_nGDLDC       = 0040000000000ull,
1123     // 40 NLD1 Prepare alignment count for first numeric operand load
1124     du2_NLD1         = 0020000000000ull,
1125     // 41 GLDP1 Numeric operand one load gate
1126     du2_GLDP1        = 0010000000000ull,
1127     // 42 NLD2 Prepare alignment count for second numeric operand load
1128     du2_NLD2         = 0004000000000ull,
1129     // 43 GLDP2 Numeric operand two load gate
1130     du2_GLDP2        = 0002000000000ull,
1131     // 44 ANLD1 Alphanumeric operand one load gate
1132     du2_ANLD1        = 0001000000000ull,
1133     // 45 ANLD2 Alphanumeric operand two load gate
1134     du2_ANLD2        = 0000400000000ull,
1135     // 46 LDWRT1 Load rewrite register one gate (XXX Guess indirect desc. MFkID)
1136     du2_LDWRT1       = 0000200000000ull,
1137     // 47 LDWRT2 Load rewrite register two gate (XXX Guess indirect desc. MFkID)
1138     du2_LDWRT2       = 0000100000000ull,
1139     // 50 -DATA-AVLDU Decimal unit data available
1140     du2_nDATA_AVLDU  = 0000040000000ull,
1141     // 49 WRT1 Rewrite register one loaded
1142     du2_WRT1         = 0000020000000ull,
1143     // 50 GSTR Numeric store gate
1144     du2_GSTR         = 0000010000000ull,
1145     // 51 ANSTR Alphanumeric store gate
1146     du2_ANSTR        = 0000004000000ull,
1147     // 52 FSTR-OP-AV Operand available to be stored
1148     du2_FSTR_OP_AV   = 0000002000000ull,
1149     // 53 -FEND-SEQ End sequence flag
1150     du2_nFEND_SEQ    = 0000001000000ull,
1151     // 54 -FLEN<128 Length less than 128
1152     du2_nFLEN_128    = 0000000400000ull,
1153     // 55 FGCH Character operation gate
1154     du2_FGCH         = 0000000200000ull,
1155     // 56 FANPK Alphanumeric packing cycle gate
1156     du2_FANPK        = 0000000100000ull,
1157     // 57 FEXMOP Execute MOP gate
1158     du2_FEXOP        = 0000000040000ull,
1159     // 58 FBLNK Blanking gate
1160     du2_FBLNK        = 0000000020000ull,
1161     // 59 Unused
1162     //               = 0000000010000ull,
1163     // 60 DGBD Binary to decimal execution gate
1164     du2_DGBD         = 0000000004000ull,
1165     // 61 DGDB Decimal to binary execution gate
1166     du2_DGDB         = 0000000002000ull,
1167     // 62 DGSP Shift procedure gate
1168     du2_DGSP         = 0000000001000ull,
1169     // 63 FFLTG Floating result flag
1170     du2_FFLTG        = 0000000000400ull,
1171     // 64 FRND Rounding flag
1172     du2_FRND         = 0000000000200ull,
1173     // 65 DADD-GATE Add/subtract execute gate
1174     du2_DADD_GATE    = 0000000000100ull,
1175     // 66 DMP+DV-GATE Multiply/divide execution gate
1176     du2_DMP_DV_GATE  = 0000000000040ull,
1177     // 67 DXPN-GATE Exponent network execution gate
1178     du2_DXPN_GATE    = 0000000000020ull,
1179     // 68 Unused
1180     //               = 0000000000010ull,
1181     // 69 Unused
1182     //               = 0000000000004ull,
1183     // 70 Unused
1184     //               = 0000000000002ull,
1185     // 71 Unused
1186     //               = 0000000000001ull,
1187   };
1188 
1189 // L68 only
1190 #define DU_CYCLE_GDLDA {   clrmask (& cpu.du.cycle2, du2_nGDLDA);              \
1191                            setmask (& cpu.du.cycle2, du2_nGDLDB | du2_nGDLDC); }
1192 #define DU_CYCLE_GDLDB {   clrmask (& cpu.du.cycle2, du2_nGDLDB);              \
1193                            setmask (& cpu.du.cycle2, du2_nGDLDA | du2_nGDLDC); }
1194 #define DU_CYCLE_GDLDC {   clrmask (& cpu.du.cycle2, du2_nGDLDC);              \
1195                            setmask (& cpu.du.cycle2, du2_nGDLDA | du2_nGDLDB); }
1196 #define DU_CYCLE_FA_I1     setmask (& cpu.du.cycle1, du1_FA_I1)
1197 #define DU_CYCLE_FA_I2     setmask (& cpu.du.cycle1, du1_FA_I2)
1198 #define DU_CYCLE_FA_I3     setmask (& cpu.du.cycle1, du1_FA_I3)
1199 #define DU_CYCLE_ANLD1     setmask (& cpu.du.cycle2, du2_ANLD1)
1200 #define DU_CYCLE_ANLD2     setmask (& cpu.du.cycle2, du2_ANLD2)
1201 #define DU_CYCLE_NLD1      setmask (& cpu.du.cycle2, du2_NLD1)
1202 #define DU_CYCLE_NLD2      setmask (& cpu.du.cycle2, du2_NLD2)
1203 #define DU_CYCLE_FRND      setmask (& cpu.du.cycle2, du2_FRND)
1204 #define DU_CYCLE_DGBD      setmask (& cpu.du.cycle2, du2_DGBD)
1205 #define DU_CYCLE_DGDB      setmask (& cpu.du.cycle2, du2_DGDB)
1206 #define DU_CYCLE_DDU_LDEA  clrmask (& cpu.du.cycle1, du1_nDDU_LDEA)
1207 #define DU_CYCLE_DDU_STEA  clrmask (& cpu.du.cycle1, du1_nDDU_STEA)
1208 #define DU_CYCLE_END       clrmask (& cpu.du.cycle1, du1_nEND)
1209 #define DU_CYCLE_LDWRT1    setmask (& cpu.du.cycle2, du2_LDWRT1)
1210 #define DU_CYCLE_LDWRT2    setmask (& cpu.du.cycle2, du2_LDWRT2)
1211 #define DU_CYCLE_FEXOP     setmask (& cpu.du.cycle2, du2_FEXOP)
1212 #define DU_CYCLE_ANSTR     setmask (& cpu.du.cycle2, du2_ANSTR)
1213 #define DU_CYCLE_GSTR      setmask (& cpu.du.cycle2, du2_GSTR)
1214 #define DU_CYCLE_FLEN_128  clrmask (& cpu.du.cycle2, du2_nFLEN_128)
1215 #define DU_CYCLE_FDUD  { cpu.du.cycle1 = \
1216                       du1_nFPOL        | \
1217                       du1_nFPOP        | \
1218                       du1_nNEED_DESC   | \
1219                       du1_nSEL_DIR     | \
1220                       du1_nDLEN_DIRECT | \
1221                       du1_nDFRST       | \
1222                       du1_nFEXR        | \
1223                       du1_nLAST_DFRST  | \
1224                       du1_nDDU_LDEA    | \
1225                       du1_nDDU_STEA    | \
1226                       du1_nDREDO       | \
1227                       du1_nDLVL_WD_SZ  | \
1228                       du1_nEXH         | \
1229                       du1_nEND         | \
1230                       du1_nDU_RD_WRT   | \
1231                       du1_nWRD         | \
1232                       du1_nNINE        | \
1233                       du1_nSIX         | \
1234                       du1_nFOUR        | \
1235                       du1_nBIT         | \
1236                       du1_nINTRPTD     | \
1237                       du1_nINHIB;        \
1238                     cpu.du.cycle2 =      \
1239                       du2_DUD          | \
1240                       du2_nGDLDA       | \
1241                       du2_nGDLDB       | \
1242                       du2_nGDLDC       | \
1243                       du2_nDATA_AVLDU  | \
1244                       du2_nFEND_SEQ    | \
1245                       du2_nFLEN_128;     \
1246                   }
1247 #define DU_CYCLE_nDUD clrmask (& cpu.du.cycle2, du2_DUD)
1248 
1249 #if defined(PANEL68)
1250 // Control points
1251 # define CPT(R,C) cpu.cpt[R][C]=1
1252 # define CPTUR(C) cpu.cpt[cpt5L][C]=1
1253 #else
1254 # define CPT(R,C)
1255 # define CPTUR(C)
1256 #endif /* if defined(PANEL68) */
1257 
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 typedef struct du_unit_data_t
1350   {
1351     // Word 0
1352 
1353                       //  0- 8  9   Zeros
1354     word1 Z;          //     9  1   Z       All bit-string instruction results
1355                       //                      are zero
1356     word1 NOP;        //    10  1   0       Negative overpunch found in 6-4
1357                       //                      expanded move
1358     word24 CHTALLY;   // 12-35 24   CHTALLY The number of characters examined
1359                       //                      by the scm, scmr, scd,
1360                       //                      scdr, tct, or tctr instructions
1361                       //                      (up to the interrupt or match)
1362 
1363     // Word 1
1364 
1365                       //  0-35 26   Zeros
1366 
1367     // Word 2
1368 
1369     // word24 D1_PTR; //  0-23 24   D1 PTR  Address of the last double-word
1370                       //                      accessed by operand descriptor 1;
1371                       //                      bits 17-23 (bit-address) valid
1372                       //                      only for initial access
1373                       //    24  1   Zero
1374     // word2 TA1;     // 25-26  2   TA1     Alphanumeric type of operand
1375                       //                      descriptor 1
1376                       // 27-29  3   Zeroes
1377                       //    30  1   I       Decimal unit interrupted flag; a
1378                       //                      copy of the mid-instruction
1379                       //                      interrupt fault indicator
1380     // word1 F1;      //    31  1   F1      First time; data in operand
1381                       //                      descriptor 1 is valid
1382     // word1 A1;      //    32  1   A1      Operand descriptor 1 is active
1383                       // 33-35  3   Zeroes
1384 
1385     // Word 3
1386 
1387     word10 LEVEL1;    //  0- 9 10   LEVEL 1 Difference in the count of
1388                       //                      characters loaded into the and
1389                       //                      processor characters not acted
1390                       //                      upon
1391     // word24 D1_RES; // 12-35 24   D1 RES  Count of characters remaining in
1392                       //                      operand descriptor 1
1393 
1394     // Word 4
1395 
1396     // word24 D2_PTR; //  0-23 24   D2 PTR  Address of the last double-word
1397                       //                      accessed by operand descriptor 2;
1398                       //                      bits 17-23 (bit-address) valid
1399                       //                      only for initial access
1400                       //    24  1   Zero
1401     // word2 TA2;     // 25-26  2   TA2     Alphanumeric type of operand
1402                       //                      descriptor 2
1403                       // 27-29  3   Zeroes
1404     word1 R;          //    30  1   R       Last cycle performed must be
1405                       //                    repeated
1406     // word1 F2;      //    31  1   F2      First time; data in operand
1407                       //                      descriptor 2 is valid
1408     // word1 A2;      //    32  1   A2      Operand descriptor 2 is active
1409                       // 33-35  3   Zeroes
1410 
1411     // Word 5
1412 
1413     word10 LEVEL2;    //  0- 9 10   LEVEL 2 Same as LEVEL 1, but used mainly
1414                       //                      for OP 2 information
1415     // word24 D2_RES; // 12-35 24   D2 RES  Count of characters remaining in
1416                       //                      operand descriptor 2
1417 
1418     // Word 6
1419 
1420     // word24 D3_PTR; //  0-23 24   D3 PTR  Address of the last double-word
1421                       //                      accessed by operand descriptor 3;
1422                       //                      bits 17-23 (bit-address) valid
1423                       //                      only for initial access
1424                       //    24  1   Zero
1425     // word2 TA3;     // 25-26  2   TA3     Alphanumeric type of operand
1426                       //                      descriptor 3
1427                       // 27-29  3   Zeroes
1428                       //    30  1   R       Last cycle performed must be
1429                       //                      repeated
1430                       //                    [XXX: what is the difference between
1431                       //                      this and word4.R]
1432     // word1 F3;      //    31  1   F3      First time; data in operand
1433                       //                      descriptor 3 is valid
1434     // word1 A3;      //    32  1   A3      Operand descriptor 3 is active
1435     word3 JMP;        // 33-35  3   JMP     Descriptor count; number of words
1436                       //                      to skip to find the next
1437                       //                      instruction following this
1438                       //                      multiword instruction
1439 
1440     // Word 7
1441 
1442                       //  0-12 12   Zeroes
1443     // word24 D3_RES; // 12-35 24   D3 RES  Count of characters remaining in
1444                       //                      operand descriptor 3
1445 
1446     // Fields from above reorganized for generality
1447     word2 TAk [3];
1448 
1449 // D_PTR is a word24 divided into a 18 bit address, and a 6-bit bitno/char
1450 // field
1451 
1452     word18 Dk_PTR_W [3];
1453 #define D1_PTR_W Dk_PTR_W [0]
1454 #define D2_PTR_W Dk_PTR_W [1]
1455 #define D3_PTR_W Dk_PTR_W [2]
1456 
1457     word6 Dk_PTR_B [3];
1458 #define D1_PTR_B Dk_PTR_B [0]
1459 #define D2_PTR_B Dk_PTR_B [1]
1460 #define D3_PTR_B Dk_PTR_B [2]
1461 
1462     word24 Dk_RES [3];
1463 #define D_RES Dk_RES
1464 #define D1_RES Dk_RES [0]
1465 #define D2_RES Dk_RES [1]
1466 #define D3_RES Dk_RES [2]
1467 
1468     word1 Fk [3];
1469 //#define F Fk
1470 #define F1 Fk [0]
1471 #define F2 Fk [0]
1472 #define F3 Fk [0]
1473 
1474     word1 Ak [3];
1475 
1476     // Working storage for EIS instruction processing.
1477 
1478     // These values must be restored on instruction restart
1479     word7 MF [3]; // Modifier fields for each instruction.
1480 
1481     // Image of LPL/SPL for ISOLTS compliance
1482     word36 image [8];
1483 
1484 #if defined(PANEL68)
1485     word37 cycle1;
1486     word37 cycle2;
1487     word1 POL; // Prepare operand length
1488     word1 POP; // Prepare operand pointer
1489 #endif /* if defined(PANEL68) */
1490   } du_unit_data_t;
1491 
1492 #if defined(PANEL68)
1493 // prepare_state bits
1494 enum
1495   {
1496     ps_PIA = 0200,
1497     ps_POA = 0100,
1498     ps_RIW = 0040,
1499     ps_SIW = 0020,
1500     ps_POT = 0010,
1501     ps_PON = 0004,
1502     ps_RAW = 0002,
1503     ps_SAW = 0001
1504   };
1505 #endif /* if defined(PANEL68) */
1506 
1507 // History registers
1508 
1509 // CU History register flag2 field bit
1510 
1511 enum
1512   {
1513     CUH_XINT = 0100,
1514     CUH_IFT  =  040,
1515     CUH_CRD  =  020,
1516     CUH_MRD  =  010,
1517     CUH_MSTO =   04,
1518     CUH_PIB  =   02
1519 };
1520 
1521 #define N_DPS8M_WAM_ENTRIES 64
1522 #define N_DPS8M_WAM_MASK   077
1523 #define N_L68_WAM_ENTRIES   16
1524 #define N_L68_WAM_MASK     017
1525 #define N_NAX_WAM_ENTRIES   64
1526 #define N_MODEL_WAM_ENTRIES (cpu.tweaks.l68_mode ? N_L68_WAM_ENTRIES : N_DPS8M_WAM_ENTRIES)
1527 
1528 #include "ucache.h"
1529 
1530 typedef struct coreLockState_s {
1531     uint64_t lockCnt;
1532     uint64_t lockImmediate;
1533     uint64_t lockWait;
1534     uint64_t lockWaitMax;
1535 #if !defined(SCHED_NEVER_YIELD)
1536     uint64_t lockYield;
1537 #endif /* if !defined(SCHED_NEVER_YIELD) */
1538     word24 locked_addr;
1539 } coreLockState_t;
1540 
1541 typedef struct cpu_state_s
1542   {
1543 
1544 #if defined(THREADZ) || defined(LOCKLESS)
1545     // Set when sim_instr starts fetching and executing; used to improve
1546     // thread creation lag time issues.
1547     volAtomic bool executing;
1548     volAtomic bool forceRestart;
1549     // CPU is running Multics: it has been booted or added, and not deleted,
1550     //  and not an ISOLTS test cpu.
1551     // ISOLTS test CPUs can be master, but never slave.
1552     volAtomic bool inMultics;
1553     bool syncClockModeMaster; // It set, this CPU is the master
1554     volAtomic long int workAllocation; // If in sync clock mode, this is
1555                                            // the amount of work we have
1556                                            // been allocated
1557     // How many cycles has the master held the clock
1558     int masterCycleCnt;
1559     //volatile atomic_bool rcfDelete;  // Set if the CPU was halted by a RCF DELETE
1560     bool syncClockModeCache; // Thread copy of syncClockMode
1561     int syncClockModePoll; // Poll syncClockMode
1562     volAtomic atomic_bool isSlave;
1563     bool becomeSlave;
1564 #endif
1565 
1566     EISstruct currentEISinstruction;
1567 
1568     uCache_t uCache;
1569 
1570     unsigned long long cycleCnt;
1571     unsigned long long instrCnt;
1572     unsigned long long instrCntT0;
1573     unsigned long long instrCntT1;
1574 
1575     coreLockState_t coreLockState;
1576 
1577     // From the control unit history register:
1578     _fault_subtype subFault; // saved by doFault
1579 
1580     word36   rA;     // accumulator
1581     word36   rQ;     // quotient
1582 
1583     fault_acv_subtype_  acvFaults;   // pending ACV faults
1584 
1585     sdw_s * SDW; // working SDW
1586 
1587     // Zone mask
1588     word36 zone;
1589 
1590     ptw_s * PTW;
1591 
1592     word36 CY;              // C(Y) operand data from memory
1593 
1594     uint64 lufCounter;
1595 
1596     _fault_subtype dlySubFltNum;
1597 
1598     const char * dlyCtx;
1599 
1600     word36 faultRegister [2];
1601 
1602     word36 itxPair [2];
1603 
1604 //#if defined(THREADZ) || defined(LOCKLESS)
1605 //    struct timespec rTRTime; // time when rTR was set
1606 //#endif
1607 
1608     mode_register_s MR;
1609     // Changes to the mode register history bits do not take affect until
1610     // the next instruction (ISOLTS 700 2a). Cache the values here so
1611     // that post register updates can see the old values.
1612     mode_register_s MR_cache;
1613 
1614     DCDstruct currentInstruction;
1615 
1616     ou_unit_data_t ou;
1617 
1618     word36 Ypair[2];        //  2-words
1619     word36 Yblock8[8];      //  8-words
1620     word36 Yblock16[16];    // 16-words
1621     word36 Yblock32[32];    // 32-words
1622 
1623     word36 scu_data[8];     // For SCU instruction
1624 
1625     ctl_unit_data_t cu;
1626     du_unit_data_t du;
1627 
1628     switches_t switches;
1629     optionsType options;
1630     tweaksType tweaks;
1631     switches_t isolts_switches_save;
1632 
1633     jmp_buf jmpMain; // This is the entry to the CPU state machine
1634 
1635     unsigned long      faultCnt [N_FAULTS];
1636 
1637     word36 history [N_HIST_SETS] [N_MAX_HIST_SIZE] [2];
1638 
1639     cycles_e cycle;
1640 
1641     _fault faultNumber;      // fault number saved by doFault
1642 
1643     apu_unit_data_t apu;
1644 
1645     word27   rTR;    // timer [map: TR, 9 0's]
1646 #if defined(THREADZ) || defined(LOCKLESS)
1647     uint     rTRsample;
1648 #endif
1649     word24   rY;     // address operand
1650 
1651     word18  lnk;     // rpl link value
1652 
1653     volAtomic uint g7FaultsPreset;
1654     uint g7Faults;
1655 
1656     word24 iefpFinalAddress;
1657 
1658     // ISOLTS fine grain TR estimation
1659     uint rTRlsb;
1660     uint shadowTR;
1661     uint TR0; // The value that the TR was set to.
1662 
1663     // Arguments for delayed overflow fault
1664     _fault dlyFltNum;
1665 
1666     word18 last_write;
1667 
1668 #if defined(LOCKLESS)
1669     word24 char_word_address;
1670 #endif /* if defined(LOCKLESS) */
1671 
1672     word24 rmw_address;
1673 
1674     uint restart_address;
1675 
1676     struct
1677       {
1678         word15 PSR;
1679         word3  PRR;
1680         word18 IC;
1681       } cu_data;            // For STCD instruction
1682     uint rTRticks;
1683 
1684     struct tpr_s TPR;     // Temporary Pointer Register
1685     struct ppr_s PPR;     // Procedure Pointer Register
1686     struct dsbr_s DSBR;   // Descriptor Segment Base Register
1687     ptw0_s PTW0; // a PTW not in PTWAM (PTWx1)
1688 
1689     uint history_cyclic [N_HIST_SETS]; // 0..63
1690 
1691     sdw_s SDW0;  // a SDW not in SDWAM
1692     sdw_s _s;
1693 
1694     word18   rX [8]; // index
1695 
1696     // Number of banks in each SCU
1697     uint sc_num_banks [N_SCU_UNITS_MAX];
1698 
1699     // Caching some cabling data for interrupt handling.
1700     // When a CPU calls get_highest_intr(), it needs to know
1701     // what port on the SCU it is attached to. Because of port
1702     // expanders several CPUs can be attached to an SCU port,
1703     // mapping from the CPU to the SCU is easier to query
1704     uint scu_port[N_SCU_UNITS_MAX];
1705 
1706     // L68 FFV faults
1707 
1708      uint FFV_faults_preset;
1709      uint FFV_faults;
1710      uint FFV_fault_number;
1711 
1712 #if defined(AFFINITY)
1713     uint affinity;
1714 #endif /* if defined(AFFINITY) */
1715 
1716     events_t events;
1717 
1718     word24 pad[16];
1719 
1720     struct par_s PAR [8]; // pointer/address registers
1721 
1722     ptw_s PTWAM [N_NAX_WAM_ENTRIES];
1723 
1724     // Map memory address through memory configuration switches
1725     // Minimum allocation chunk is 64K (SCBANK_SZ)
1726     // addr / SCBANK_SZ => bank_number
1727     // scbank_map[bank_number] is address of the bank in M. -1 is unmapped.
1728     int sc_addr_map [N_SCBANKS];
1729     // The SCU number holding each bank
1730     int sc_scu_map [N_SCBANKS];
1731 
1732     sdw_s SDWAM [N_NAX_WAM_ENTRIES]; // Segment Descriptor Word Associative Memory
1733 
1734     // Address Modification tally
1735     word12 AM_tally;
1736 
1737     struct bar_s BAR;     // Base Address Register
1738 
1739     cache_mode_register_s CMR;
1740 
1741     // The following are all from the control unit history register:
1742 
1743     bool interrupt_flag;     // an interrupt is pending in this cycle
1744     bool g7_flag;            // a g7 fault is pending in this cycle;
1745 
1746     bool wasXfer;      // The previous instruction was a transfer
1747 
1748     bool wasInhibited; // One or both of the previous instruction
1749                        // pair was interrupt inhibited.
1750 
1751     bool isExec;  // The instruction being executed is the target of
1752                   // an XEC or XED instruction
1753     bool isXED;   // The instruction being executed is the target of an
1754                   // XEC instruction
1755 
1756     word8    rE;       // exponent [map: rE, 28 0's]
1757 
1758     word6    rTAG;     // instruction tag
1759     word3    rRALR;    // ring alarm [3b] [map: 33 0's, RALR]
1760     word3    RSDWH_R1; // Track the ring number of the last SDW
1761 
1762     // L68: word4
1763     // DPS8M: word6
1764     word6 SDWAMR;
1765 
1766     // Zone mask
1767     bool useZone;
1768 
1769     // L68: word4
1770     // DPS8M: word6
1771     word6 PTWAMR;
1772 
1773     // G7 faults
1774     bool bTroubleFaultCycle;
1775 
1776     bool lufOccurred;
1777     bool secret_addressing_mode;
1778     // Used by LCPR to prevent the LCPR instruction from being recorded
1779     // in the CU.
1780     bool skip_cu_hist;
1781 
1782     // If the instruction wants overflow thrown after operand write
1783     bool dlyFlt;
1784 
1785     bool restart;
1786 
1787     // L68 FFV faults
1788     bool is_FFV;
1789 
1790 #if defined(ROUND_ROBIN)
1791     bool isRunning;
1792 #endif /* if defined(ROUND_ROBIN) */
1793 
1794 #if defined(AFFINITY)
1795     bool set_affinity;
1796 #endif /* if defined(AFFINITY) */
1797 
1798 #if defined(SPEED)
1799 # define SC_MAP_ADDR(addr,real_addr)                           \
1800    if (cpu.tweaks.useMap)                                      \
1801       {                                                        \
1802         uint pgnum = addr / SCBANK_SZ;                         \
1803         uint os = addr % SCBANK_SZ;                            \
1804         int base = cpu.sc_addr_map[pgnum];                     \
1805         if (base < 0)                                          \
1806           {                                                    \
1807             doFault (FAULT_STR, fst_str_nea,  __func__);       \
1808           }                                                    \
1809         real_addr = (uint) base + os;                          \
1810       }                                                        \
1811     else                                                       \
1812       real_addr = addr;
1813 #else
1814 # define SC_MAP_ADDR(addr,real_addr)                           \
1815    if (cpu.tweaks.useMap)                                      \
1816       {                                                        \
1817         uint pgnum = addr / SCBANK_SZ;                         \
1818         uint os = addr % SCBANK_SZ;                            \
1819         int base = cpu.sc_addr_map[pgnum];                     \
1820         if (base < 0)                                          \
1821           {                                                    \
1822             doFault (FAULT_STR, fst_str_nea,  __func__);       \
1823           }                                                    \
1824         real_addr = (uint) base + os;                          \
1825       }                                                        \
1826     else                                                       \
1827       {                                                        \
1828         nem_check (addr, __func__);                            \
1829         real_addr = addr;                                      \
1830       }
1831 #endif /* if defined(SPEED) */
1832 
1833 #if defined(PANEL68)
1834     // Intermediate data collection for APU SCROLL
1835     word18 lastPTWOffset;
1836 // The L68 APU SCROLL 4U has an entry "ACSD"; I am interpreting it as
1837 //   on: lastPTRAddr was a DSPTW
1838 //  off: lastPTRAddr was a PTW
1839     bool lastPTWIsDS;
1840     word18 APUDataBusOffset;
1841     word24 APUDataBusAddr;
1842     word24 APUMemAddr;
1843     word1 panel4_red_ready_light_state;
1844     word1 panel7_enabled_light_state;
1845 // The state of the panel switches
1846     volAtomic word15 APU_panel_segno_sw;
1847     volAtomic word1  APU_panel_enable_match_ptw_sw;  // lock
1848     volAtomic word1  APU_panel_enable_match_sdw_sw;  // lock
1849     volAtomic word1  APU_panel_scroll_select_ul_sw;
1850     volAtomic word4  APU_panel_scroll_select_n_sw;
1851     volAtomic word4  APU_panel_scroll_wheel_sw;
1852     //volAtomic word18 APU_panel_addr_sw;
1853     volAtomic word18 APU_panel_enter_sw;
1854     volAtomic word18 APU_panel_display_sw;
1855     volAtomic word4  CP_panel_wheel_sw;
1856     volAtomic word4  DATA_panel_ds_sw;
1857     volAtomic word4  DATA_panel_d1_sw;
1858     volAtomic word4  DATA_panel_d2_sw;
1859     volAtomic word4  DATA_panel_d3_sw;
1860     volAtomic word4  DATA_panel_d4_sw;
1861     volAtomic word4  DATA_panel_d5_sw;
1862     volAtomic word4  DATA_panel_d6_sw;
1863     volAtomic word4  DATA_panel_d7_sw;
1864     volAtomic word4  DATA_panel_wheel_sw;
1865     volAtomic word4  DATA_panel_addr_stop_sw;
1866     volAtomic word1  DATA_panel_enable_sw;
1867     volAtomic word1  DATA_panel_validate_sw;
1868     volAtomic word1  DATA_panel_auto_fast_sw;  // lock
1869     volAtomic word1  DATA_panel_auto_slow_sw;  // lock
1870     volAtomic word4  DATA_panel_cycle_sw;      // lock
1871     volAtomic word1  DATA_panel_step_sw;       // lock
1872     volAtomic word1  DATA_panel_s_trig_sw;
1873     volAtomic word1  DATA_panel_execute_sw;    // lock
1874     volAtomic word1  DATA_panel_scope_sw;
1875     volAtomic word1  DATA_panel_init_sw;       // lock
1876     volAtomic word1  DATA_panel_exec_sw;       // lock
1877     volAtomic word4  DATA_panel_hr_sel_sw;
1878     volAtomic word4  DATA_panel_trackers_sw;
1879     volAtomic bool panelInitialize;
1880 
1881     // Intermediate data collection for DATA SCROLL
1882     bool portBusy;
1883     word2 portSelect;
1884     word36 portAddr [N_CPU_PORTS];
1885     word36 portData [N_CPU_PORTS];
1886     // Intermediate data collection for CU
1887     word36 IWRAddr;
1888     word7 dataMode; // 0100  9 bit
1889                     // 0040  6 bit
1890                     // 0020  4 bit
1891                     // 0010  1 bit
1892                     // 0004  36 bit
1893                     // 0002  alphanumeric
1894                     // 0001  numeric
1895     word8 prepare_state;
1896     bool DACVpDF;
1897     bool AR_F_E;
1898     bool INS_FETCH;
1899     // Control Points data acquisition
1900     word1 cpt [28] [36];
1901 #endif /* if defined(PANEL68) */
1902 #define cpt1U   0  // Instruction processing tracking
1903 #define cpt1L   1  // Instruction processing tracking
1904 #define cpt2U   2  // Instruction execution tracking
1905 #define cpt2L   3  // Instruction execution tracking
1906 #define cpt3U   4  // Register usage
1907 #define cpt3L   5  // Register usage
1908 #define cpt4U   6
1909 #define cpt4L   7
1910 #define cpt5U   8
1911 #define cpt5L   9
1912 #define cpt6U  10
1913 #define cpt6L  11
1914 #define cpt7U  12
1915 #define cpt7L  13
1916 #define cpt8U  14
1917 #define cpt8L  15
1918 #define cpt9U  16
1919 #define cpt9L  17
1920 #define cpt10U 18
1921 #define cpt10L 19
1922 #define cpt11U 20
1923 #define cpt11L 21
1924 #define cpt12U 22
1925 #define cpt12L 23
1926 #define cpt13U 24
1927 #define cpt13L 25
1928 #define cpt14U 26
1929 #define cpt14L 27
1930 
1931 #define cptUseE     0
1932 #define cptUseBAR   1
1933 #define cptUseTR    2
1934 #define cptUseRALR  3
1935 #define cptUsePRn   4  // 4 - 11
1936 #define cptUseDSBR 12
1937 #define cptUseFR   13
1938 #define cptUseMR   14
1939 #define cptUseCMR  15
1940 #define cptUseIR   16
1941   } cpu_state_t;
1942 
1943 typedef struct MOP_struct_s
1944   {
1945     char * mopName;     // name of microoperation
1946     int (* f) (cpu_state_t *);   // pointer to mop() [returns character to be stored]
1947   } MOP_struct;
1948 
1949 #if defined(M_SHARED)
1950 extern cpu_state_t * cpus;
1951 #else
1952 extern cpu_state_t cpus [N_CPU_UNITS_MAX];
1953 #endif /* if defined(M_SHARED) */
1954 
1955 #if defined(THREADZ) || defined(LOCKLESS)
1956 extern __thread cpu_state_t * restrict _cpup;
1957 #else
1958 extern cpu_state_t * restrict _cpup;
1959 #endif /* if defined(THREADZ) || defined(LOCKLESS) */
1960 
1961 #define cpu (* cpup)
1962 
1963 #define N_STALL_POINTS 16
1964 struct stall_point_s
1965   {
1966     word15 segno;
1967     word18 offset;
1968     useconds_t time;
1969   };
1970 extern struct stall_point_s stall_points [N_STALL_POINTS];
1971 extern bool stall_point_active;
1972 
1973 uint set_cpu_idx (uint cpuNum);
1974 #if defined(THREADZ) || defined(LOCKLESS)
1975 extern __thread uint current_running_cpu_idx;
1976 extern bool bce_dis_called;
1977 #else
1978 # if defined(ROUND_ROBIN)
1979 extern uint current_running_cpu_idx;
1980 # else
1981 #  define current_running_cpu_idx 0
1982 # endif /* if defined(ROUND_ROBIN) */
1983 #endif /* if defined(THREADZ) || defined(LOCKLESS) */
1984 
1985 // Support code to access ARn.BITNO, ARn.CHAR, PRn.BITNO
1986 
1987 #define GET_PR_BITNO(n) (cpu.PAR[n].PR_BITNO)
1988 #define GET_AR_BITNO(n) (cpu.PAR[n].AR_BITNO)
1989 #define GET_AR_CHAR(n)  (cpu.PAR[n].AR_CHAR)
1990 static inline void SET_PR_BITNO (cpu_state_t * restrict cpup, uint n, word6 b)
     /* [previous][next][first][last][top][bottom][index][help] */
1991   {
1992      cpu.PAR[n].PR_BITNO = b;
1993      cpu.PAR[n].AR_BITNO = (b % 9) & MASK4;
1994      cpu.PAR[n].AR_CHAR = (b / 9) & MASK2;
1995   }
1996 #define SET_PR_BITNO(n, b) SET_PR_BITNO(cpup, n, b)
1997 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] */
1998   {
1999      cpu.PAR[n].PR_BITNO = c * 9 + b;
2000      cpu.PAR[n].AR_BITNO = b & MASK4;
2001      cpu.PAR[n].AR_CHAR = c & MASK2;
2002   }
2003 #define SET_AR_CHAR_BITNO(n, c, b) SET_AR_CHAR_BITNO(cpup, n, c, b)
2004 
2005 bool sample_interrupts (cpu_state_t * cpup);
2006 t_stat simh_hooks (cpu_state_t * cpup);
2007 int operand_size (cpu_state_t * cpup);
2008 //void read_operand (word18 addr, processor_cycle_type cyctyp);
2009 void readOperandRead (cpu_state_t * cpup, word18 addr);
2010 void readOperandRMW (cpu_state_t * cpup, word18 addr);
2011 t_stat write_operand (cpu_state_t * cpup, word18 addr, processor_cycle_type acctyp);
2012 
2013 #if defined(PANEL68)
2014 static inline void trackport (word24 a, word36 d)
     /* [previous][next][first][last][top][bottom][index][help] */
2015   {
2016     cpu_state_t * cpup = _cpup;
2017     // Simplifying assumption: 4 * 4MW SCUs
2018     word2 port = (a >> 22) & MASK2;
2019     cpu.portSelect = port;
2020     cpu.portAddr [port] = a;
2021     cpu.portData [port] = d;
2022     cpu.portBusy = false;
2023   }
2024 #endif /* if defined(PANEL68) */
2025 
2026 #if defined(SPEED) && defined(INLINE_CORE)
2027 # error INLINE_CORE has known issues.
2028 // Ugh. Circular dependencies XXX
2029 NO_RETURN void doFault (_fault faultNumber, _fault_subtype faultSubtype,
2030               const char * faultMsg);
2031 extern const _fault_subtype fst_str_nea;
2032 
2033 static inline int core_read (word24 addr, word36 *data, \
     /* [previous][next][first][last][top][bottom][index][help] */
2034   UNUSED const char * ctx)
2035   {
2036     PNL (cpu.portBusy = true;)
2037     SC_MAP_ADDR (addr, addr);
2038     * data = M[addr] & DMASK;
2039     DO_WORK_MEM;
2040     PNL (trackport (addr, * data);)
2041     return 0;
2042   }
2043 
2044 static inline int core_write (word24 addr, word36 data, \
     /* [previous][next][first][last][top][bottom][index][help] */
2045   UNUSED const char * ctx)
2046   {
2047     PNL (cpu.portBusy = true;)
2048     SC_MAP_ADDR (addr, addr);
2049     if (cpu.tweaks.isolts_mode)
2050       {
2051         if (cpu.MR.sdpap)
2052           {
2053             sim_warn ("failing to implement sdpap\n");
2054             cpu.MR.sdpap = 0;
2055           }
2056         if (cpu.MR.separ)
2057           {
2058             sim_warn ("failing to implement separ\n");
2059             cpu.MR.separ = 0;
2060           }
2061      }
2062     M[addr] = data & DMASK;
2063     DO_WORK_MEM;
2064     PNL (trackport (addr, data);)
2065     return 0;
2066   }
2067 
2068 static inline int core_write_zone (word24 addr, word36 data, \
     /* [previous][next][first][last][top][bottom][index][help] */
2069   UNUSED const char * ctx)
2070   {
2071     PNL (cpu.portBusy = true;)
2072     SC_MAP_ADDR (addr, addr);
2073     if (cpu.tweaks.isolts_mode)
2074       {
2075         if (cpu.MR.sdpap)
2076           {
2077             sim_warn ("failing to implement sdpap\n");
2078             cpu.MR.sdpap = 0;
2079           }
2080         if (cpu.MR.separ)
2081           {
2082             sim_warn ("failing to implement separ\n");
2083             cpu.MR.separ = 0;
2084           }
2085       }
2086     M[addr] = (M[addr] & ~cpu.zone) | (data & cpu.zone);
2087     cpu.useZone = false; // Safety
2088     DO_WORK_MEM;
2089     PNL (trackport (addr, data);)
2090     return 0;
2091   }
2092 
2093 static inline int core_read2 (word24 addr, word36 *even, word36 *odd,
     /* [previous][next][first][last][top][bottom][index][help] */
2094                               UNUSED const char * ctx)
2095   {
2096     PNL (cpu.portBusy = true;)
2097     SC_MAP_ADDR (addr, addr);
2098     *even = M[addr++] & DMASK;
2099     *odd = M[addr] & DMASK;
2100     DO_WORK_MEM;
2101     PNL (trackport (addr - 1, * even);)
2102     return 0;
2103   }
2104 
2105 static inline int core_write2 (word24 addr, word36 even, word36 odd,
     /* [previous][next][first][last][top][bottom][index][help] */
2106                                UNUSED const char * ctx)
2107   {
2108     PNL (cpu.portBusy = true;)
2109     SC_MAP_ADDR (addr, addr);
2110     if (cpu.tweaks.isolts_mode)
2111       {
2112         if (cpu.MR.sdpap)
2113           {
2114             sim_warn ("failing to implement sdpap\n");
2115             cpu.MR.sdpap = 0;
2116           }
2117         if (cpu.MR.separ)
2118           {
2119             sim_warn ("failing to implement separ\n");
2120             cpu.MR.separ = 0;
2121           }
2122       }
2123     M[addr++] = even;
2124     M[addr] = odd;
2125     PNL (trackport (addr - 1, even);)
2126     DO_WORK_MEM;
2127     return 0;
2128   }
2129 #else
2130 int core_read (cpu_state_t * cpup, word24 addr, word36 *data, const char * ctx);
2131 int core_write (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx);
2132 int core_write_zone (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx);
2133 int core_read2 (cpu_state_t * cpup, word24 addr, word36 *even, word36 *odd, const char * ctx);
2134 int core_write2 (cpu_state_t * cpup, word24 addr, word36 even, word36 odd, const char * ctx);
2135 #endif /* if defined(SPEED) && defined(INLINE_CORE) */
2136 
2137 #if defined(LOCKLESS)
2138 
2139 /*
2140  * Atomic operations to use defined as follows:
2141  *
2142  *  AIX_ATOMICS  -  IBM AIX atomics
2143  *  BSD_ATOMICS  -  FreeBSD atomics
2144  *  GNU_ATOMICS  -  GNU atomics
2145  * SYNC_ATOMICS  -  GNU sync-style atomics
2146  *
2147  * The following are reserved and not yet implemented:
2148  *
2149  *  ISO_ATOMICS  -  ISO/IEC 9899:2011 (C11) atomics
2150  *   NT_ATOMICS  -  Microsoft Windows NT atomics
2151  *
2152  * For further details, see:
2153  *
2154  * AIX_ATOMICS:
2155  *  https://www.ibm.com/docs/en/aix/7.3?topic=services-atomic-operations
2156  *
2157  * BSD_ATOMICS:
2158  *  https://www.freebsd.org/cgi/man.cgi?query=atomic&sektion=9&format=html
2159  *  https://man.dragonflybsd.org/?command=atomic&section=9
2160  *
2161  * GNU_ATOMICS:
2162  *  https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
2163  *
2164  * SYNC_ATOMICS:
2165  *  https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
2166  *
2167  * ISO_ATOMICS:
2168  *  https://en.cppreference.com/w/c/atomic
2169  *
2170  * NT_ATOMICS:
2171  *  https://docs.microsoft.com/en-us/windows/win32/sync/synchronization-functions
2172  *  https://docs.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access
2173  */
2174 
2175 // AIX_ATOMICS are SYNC_ATOMICS (for now)
2176 # if ( defined (AIX_ATOMICS) && \
2177    (! (defined (SYNC_ATOMICS))))
2178 #  define SYNC_ATOMICS 1
2179 # endif
2180 
2181 // FreeBSD atomics (default on for FreeBSD)
2182 # if (! defined (GNU_ATOMICS)) && (! defined (SYNC_ATOMICS)) && \
2183      (! defined (BSD_ATOMICS)) && (! defined (AIX_ATOMICS))
2184 #  if defined(__FreeBSD__) \
2185    || defined(__DragonFly__)
2186 #   undef BSD_ATOMICS
2187 #   define BSD_ATOMICS 1
2188 #  endif
2189 # endif
2190 
2191 // Otherwise, default to GNU_ATOMICS
2192 # if (! defined (GNU_ATOMICS)) && (! defined (BSD_ATOMICS)) && \
2193      (! defined (SYNC_ATOMICS)) && (! defined (AIX_ATOMICS))
2194 #  undef GNU_ATOMICS
2195 #  define GNU_ATOMICS 1
2196 # endif
2197 
2198 int core_read_lock (cpu_state_t * cpup, word24 addr, word36 *data, const char * ctx);
2199 int core_write_unlock (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx);
2200 int core_unlock_all(cpu_state_t * cpup);
2201 
2202 # define DEADLOCK_DETECT   0x40000000U
2203 # define MEM_LOCKED_BIT    61
2204 # define MEM_LOCKED        (1LLU<<MEM_LOCKED_BIT)
2205 
2206 # if !defined(SCHED_NEVER_YIELD)
2207 #  undef SCHED_YIELD
2208 #  define SCHED_YIELD(lockStatePtr)                                      \
2209   do                                                                     \
2210     {                                                                    \
2211       if ((i & 0xff) == 0)                                               \
2212         {                                                                \
2213           sched_yield();                                                 \
2214           (lockStatePtr)->lockYield++;                                   \
2215         }                                                                \
2216     }                                                                    \
2217   while(0)
2218 # else
2219 #  undef SCHED_YIELD
2220 #  define SCHED_YIELD(lockStatePtr)                                      \
2221   do                                                                     \
2222     {                                                                    \
2223     }                                                                    \
2224   while(0)
2225 # endif /* if !defined(SCHED_NEVER_YIELD) */
2226 
2227 # if defined (BSD_ATOMICS)
2228 #  include <machine/atomic.h>
2229 
2230 #  define LOCK_CORE_WORD(addr,lockStatePtr)                              \
2231   do                                                                     \
2232     {                                                                    \
2233       unsigned int i = DEADLOCK_DETECT;                                  \
2234       while ( atomic_testandset_64((volatile uint64_t *)&M[addr],        \
2235             MEM_LOCKED_BIT) == 1 && i > 0)                               \
2236         {                                                                \
2237           i--;                                                           \
2238           SCHED_YIELD(lockStatePtr);                                     \
2239         }                                                                \
2240       if (i == 0)                                                        \
2241         {                                                                \
2242           sim_warn ("%s: locked %x addr %x deadlock\n", __func__,        \
2243               (lockStatePtr)->locked_addr, addr);                        \
2244         }                                                                \
2245       (lockStatePtr)->lockCnt++;                                         \
2246       if (i == DEADLOCK_DETECT)                                          \
2247         (lockStatePtr)->lockImmediate++;                                 \
2248       (lockStatePtr)->lockWait += (DEADLOCK_DETECT-i);                   \
2249       (lockStatePtr)->lockWaitMax = ((DEADLOCK_DETECT-i) >               \
2250           (lockStatePtr)->lockWaitMax) ?                                 \
2251               (DEADLOCK_DETECT-i) : (lockStatePtr)->lockWaitMax;         \
2252     }                                                                    \
2253   while (0)
2254 
2255 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2256   do                                                                     \
2257     {                                                                    \
2258       res = atomic_load_acq_64((volatile uint64_t *)&M[addr]);           \
2259     }                                                                    \
2260   while (0)
2261 
2262 #  define STORE_REL_CORE_WORD(addr, data)                                \
2263   do                                                                     \
2264     {                                                                    \
2265       atomic_store_rel_64((volatile uint64_t *)&M[addr], data & DMASK);  \
2266     }                                                                    \
2267   while (0)
2268 
2269 # endif // BSD_ATOMICS
2270 
2271 # if defined(GNU_ATOMICS)
2272 
2273 #  define LOCK_CORE_WORD(addr,lockStatePtr)                              \
2274   do                                                                     \
2275     {                                                                    \
2276       unsigned int i = DEADLOCK_DETECT;                                  \
2277       while ((__atomic_fetch_or((volatile uint64_t *)&M[addr],           \
2278         MEM_LOCKED, __ATOMIC_ACQ_REL) & MEM_LOCKED)                      \
2279                 && i > 0)                                                \
2280     {                                                                    \
2281       i--;                                                               \
2282       SCHED_YIELD(lockStatePtr);                                         \
2283     }                                                                    \
2284       if (i == 0)                                                        \
2285         {                                                                \
2286           sim_warn ("%s: locked %x addr %x deadlock\n",                  \
2287             __func__, (lockStatePtr)->locked_addr, addr);                \
2288         }                                                                \
2289       (lockStatePtr)->lockCnt++;                                         \
2290       if (i == DEADLOCK_DETECT)                                          \
2291           (lockStatePtr)->lockImmediate++;                               \
2292       (lockStatePtr)->lockWait += (DEADLOCK_DETECT-i);                   \
2293       (lockStatePtr)->lockWaitMax = ((DEADLOCK_DETECT-i) >               \
2294           (lockStatePtr)->lockWaitMax) ? (DEADLOCK_DETECT-i) :           \
2295               (lockStatePtr)->lockWaitMax;                               \
2296     }                                                                    \
2297   while (0)
2298 
2299 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2300   do                                                                     \
2301     {                                                                    \
2302       res = __atomic_load_n((volatile uint64_t *)&M[addr],               \
2303           __ATOMIC_ACQUIRE);                                             \
2304     }                                                                    \
2305   while (0)
2306 
2307 #  define STORE_REL_CORE_WORD(addr, data)                                \
2308   do                                                                     \
2309     {                                                                    \
2310       __atomic_store_n((volatile uint64_t *)&M[addr], data &             \
2311           DMASK, __ATOMIC_RELEASE);                                      \
2312     }                                                                    \
2313   while (0)
2314 
2315 # endif // GNU_ATOMICS
2316 
2317 # if defined(SYNC_ATOMICS)
2318 #  if defined(MEMORY_ACCESS_NOT_STRONGLY_ORDERED)
2319 #   define MEM_BARRIER()   do { __sync_synchronize(); } while (0)
2320 #  else
2321 #   define MEM_BARRIER()   do {} while (0)
2322 #  endif
2323 
2324 #  define LOCK_CORE_WORD(addr,lockStatePtr)                              \
2325      do                                                                  \
2326        {                                                                 \
2327          unsigned int i = DEADLOCK_DETECT;                               \
2328          while ((__sync_fetch_and_or((volatile uint64_t *)&M[addr],      \
2329              MEM_LOCKED) & MEM_LOCKED) && i > 0)                         \
2330            {                                                             \
2331             i--;                                                         \
2332             SCHED_YIELD(lockStatePtr);                                   \
2333            }                                                             \
2334          if (i == 0)                                                     \
2335            {                                                             \
2336             sim_warn ("%s: locked %x addr %x deadlock\n", __func__,      \
2337                 (lockStatePtr)->locked_addr, addr);                      \
2338             }                                                            \
2339          (lockStatePtr)->lockCnt++;                                      \
2340          if (i == DEADLOCK_DETECT)                                       \
2341            (lockStatePtr)->lockImmediate++;                              \
2342          (lockStatePtr)->lockWait += (DEADLOCK_DETECT-i);                \
2343          (lockStatePtr)->lockWaitMax = ((DEADLOCK_DETECT-i) >            \
2344              (lockStatePtr)->lockWaitMax) ?                              \
2345                  (DEADLOCK_DETECT-i) : (lockStatePtr)->lockWaitMax;      \
2346        }                                                                 \
2347      while (0)
2348 
2349 #  define LOAD_ACQ_CORE_WORD(res, addr)                                  \
2350      do                                                                  \
2351        {                                                                 \
2352          res = M[addr];                                                  \
2353          MEM_BARRIER();                                                  \
2354        }                                                                 \
2355      while (0)
2356 
2357 #  define STORE_REL_CORE_WORD(addr, data)                                \
2358   do                                                                     \
2359     {                                                                    \
2360       MEM_BARRIER();                                                     \
2361       M[addr] = data & DMASK;                                            \
2362     }                                                                    \
2363   while (0)
2364 
2365 # endif  // SYNC_ATOMICS
2366 #endif  // LOCKLESS
2367 
2368 static inline void core_readN (cpu_state_t * cpup, word24 addr, word36 * data, uint n,
     /* [previous][next][first][last][top][bottom][index][help] */
2369                                UNUSED const char * ctx)
2370   {
2371     for (uint i = 0; i < n; i ++)
2372       {
2373         core_read (cpup, addr + i, data + i, ctx);
2374         //HDBGMRead (addr + i, * (data + i), __func__);
2375       }
2376   }
2377 
2378 static inline void core_writeN (cpu_state_t * cpup, word24 addr, word36 * data, uint n,
     /* [previous][next][first][last][top][bottom][index][help] */
2379                                 UNUSED const char * ctx)
2380   {
2381     for (uint i = 0; i < n; i ++)
2382       {
2383         core_write (cpup, addr + i, data [i], ctx);
2384         //HDBGMWrite (addr + i, * (data + i), __func__);
2385       }
2386   }
2387 
2388 int is_priv_mode (cpu_state_t * cpup);
2389 //void set_went_appending (void);
2390 //void clr_went_appending (void);
2391 //bool get_went_appending (void);
2392 bool get_bar_mode (cpu_state_t * cpup);
2393 addr_modes_e get_addr_mode (cpu_state_t * cpup);
2394 void set_addr_mode (cpu_state_t * cpup, addr_modes_e mode);
2395 void decode_instruction (cpu_state_t * cpup, word36 inst, DCDstruct * p);
2396 #if !defined(SPEED)
2397 t_stat set_mem_watch (int32 arg, const char * buf);
2398 #endif /* if !defined(SPEED) */
2399 char *str_SDW0 (char * buf, sdw_s *SDW);
2400 int lookup_cpu_mem_map (cpu_state_t * cpup, word24 addr);
2401 void cpu_init (void);
2402 void setup_scbank_map (cpu_state_t * cpup);
2403 void add_dps8m_CU_history (cpu_state_t * cpup);
2404 void add_dps8m_DUOU_history (word36 flags, word18 ICT, word9 RS_REG, word9 flags2);
2405 void add_dps8m_APU_history (word15 ESN, word21 flags, word24 RMA, word3 RTRR, word9 flags2);
2406 void add_dps8m_EAPU_history (word18 ZCA, word18 opcode);
2407 void add_l68_CU_history (cpu_state_t * cpup);
2408 void add_l68_OU_history (cpu_state_t * cpup);
2409 void add_l68_DU_history (cpu_state_t * cpup);
2410 void add_l68_APU_history (cpu_state_t * cpup, enum APUH_e op);
2411 void add_history_force (cpu_state_t * cpup, uint hset, word36 w0, word36 w1);
2412 word18 get_BAR_address(cpu_state_t * cpup, word18 addr);
2413 #if defined(THREADZ) || defined(LOCKLESS)
2414 t_stat threadz_sim_instr (void);
2415 void * cpu_thread_main (void * arg);
2416 void perfTest (char * testName);
2417 #endif
2418 void cpu_reset_unit_idx (UNUSED uint cpun, bool clear_mem);
2419 void setupPROM (uint cpuNo, unsigned char * PROM);
2420 void cpuStats (uint cpuNo);
2421 #if defined(THREADZ) || defined(LOCKLESS)
2422 void becomeClockMaster (uint cpuNum);
2423 void giveupClockMaster (cpu_state_t * cpup);
2424 #endif
2425 char * cycle_str (cycles_e cycle);

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