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