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§ion=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