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