1 /*
2 * vim: filetype=c:tabstop=4:ai:expandtab
3 * SPDX-License-Identifier: ICU
4 * SPDX-License-Identifier: Multics
5 * scspell-id: 7f512181-f62e-11ec-ad25-80ee73e9b8e7
6 *
7 * ---------------------------------------------------------------------------
8 *
9 * Copyright (c) 2007-2013 Michael Mondy
10 * Copyright (c) 2012-2016 Harry Reed
11 * Copyright (c) 2013-2016 Charles Anthony
12 * Copyright (c) 2016 Michal Tomek
13 * Copyright (c) 2021-2023 Jeffrey H. Johnson
14 * Copyright (c) 2021-2025 The DPS8M Development Team
15 *
16 * This software is made available under the terms of the ICU License.
17 * See the LICENSE.md file at the top-level directory of this distribution.
18 *
19 * ---------------------------------------------------------------------------
20 *
21 * This source file may contain code comments that adapt, include, and/or
22 * incorporate Multics program code and/or documentation distributed under
23 * the Multics License. In the event of any discrepancy between code
24 * comments herein and the original Multics materials, the original Multics
25 * materials should be considered authoritative unless otherwise noted.
26 * For more details and historical background, see the LICENSE.md file at
27 * the top-level directory of this distribution.
28 *
29 * ---------------------------------------------------------------------------
30 */
31
32 #include <stdio.h>
33
34 #include "dps8.h"
35 #include "dps8_sys.h"
36 #include "dps8_iom.h"
37 #include "dps8_cable.h"
38 #include "dps8_cpu.h"
39 #include "dps8_addrmods.h"
40 #include "dps8_faults.h"
41 #include "dps8_scu.h"
42 #include "dps8_append.h"
43 #include "dps8_eis.h"
44 #include "dps8_ins.h"
45 #include "dps8_math.h"
46 #include "dps8_opcodetable.h"
47 #include "dps8_decimal.h"
48 #include "dps8_iefp.h"
49 #include "dps8_utils.h"
50
51 #if defined(THREADZ) || defined(LOCKLESS)
52 # include "threadz.h"
53 #endif
54
55 #include "ver.h"
56
57 #define DBG_CTR cpu.cycleCnt
58
59 // Forward declarations
60
61 static int doABSA (cpu_state_t * cpup, word36 * result);
62 HOT static t_stat doInstruction (cpu_state_t * cpup);
63 static int emCall (cpu_state_t * cpup);
64
65 #if BARREL_SHIFTER
66 static word36 barrelLeftMaskTable[37] = {
67 0000000000000ull,
68 0400000000000ull, 0600000000000ull, 0700000000000ull,
69 0740000000000ull, 0760000000000ull, 0770000000000ull,
70 0774000000000ull, 0776000000000ull, 0777000000000ull,
71 0777400000000ull, 0777600000000ull, 0777700000000ull,
72 0777740000000ull, 0777760000000ull, 0777770000000ull,
73 0777774000000ull, 0777776000000ull, 0777777000000ull,
74 0777777400000ull, 0777777600000ull, 0777777700000ull,
75 0777777740000ull, 0777777760000ull, 0777777770000ull,
76 0777777774000ull, 0777777776000ull, 0777777777000ull,
77 0777777777400ull, 0777777777600ull, 0777777777700ull,
78 0777777777740ull, 0777777777760ull, 0777777777770ull,
79 0777777777774ull, 0777777777776ull, 0777777777777ull
80 };
81 static word36 barrelRightMaskTable[37] = {
82 0000000000000ull,
83 0000000000001ull, 0000000000003ull, 0000000000007ull,
84 0000000000017ull, 0000000000037ull, 0000000000077ull,
85 0000000000177ull, 0000000000377ull, 0000000000777ull,
86 0000000001777ull, 0000000003777ull, 0000000007777ull,
87 0000000017777ull, 0000000037777ull, 0000000077777ull,
88 0000000177777ull, 0000000377777ull, 0000000777777ull,
89 0000001777777ull, 0000003777777ull, 0000007777777ull,
90 0000017777777ull, 0000037777777ull, 0000077777777ull,
91 0000177777777ull, 0000377777777ull, 0000777777777ull,
92 0001777777777ull, 0003777777777ull, 0007777777777ull,
93 0017777777777ull, 0037777777777ull, 0077777777777ull,
94 0177777777777ull, 0377777777777ull, 0777777777777ull,
95 };
96 # define BS_COMPL(HI) ((~(HI)) & MASK36)
97 #endif // BARREL_SHIFTER
98
99 #if defined(LOOPTRC)
100 void elapsedtime (void)
/* ![[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)
*/
101 {
102 static bool init = false;
103 static struct timespec t0;
104 struct timespec now, delta;
105
106 if (! init)
107 {
108 init = true;
109 clock_gettime (CLOCK_REALTIME, & t0);
110 }
111 clock_gettime (CLOCK_REALTIME, & now);
112 timespec_diff (& t0, & now, & delta);
113 sim_printf ("%5ld.%03ld", delta.tv_sec, delta.tv_nsec/1000000);
114 }
115 #endif
116
117 // CANFAULT
118 static void writeOperands (cpu_state_t * cpup)
/* ![[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)
*/
119 {
120 char buf [256];
121 CPT (cpt2U, 0); // write operands
122 DCDstruct * i = & cpu.currentInstruction;
123
124 sim_debug (DBG_ADDRMOD, & cpu_dev,
125 "%s (%s):mne=%s flags=%x\r\n",
126 __func__, disassemble (buf, IWB_IRODD), i->info->mne, i->info->flags);
127
128 PNL (cpu.prepare_state |= ps_RAW);
129
130 word6 rTAG = 0;
131 if (! (i->info->flags & NO_TAG))
132 rTAG = GET_TAG (cpu.cu.IWB);
133 word6 Td = GET_TD (rTAG);
134 word6 Tm = GET_TM (rTAG);
135
136 //
137 // IT CI/SC/SCR
138 //
139
140 if (Tm == TM_IT && (Td == IT_CI || Td == IT_SC || Td == IT_SCR))
141 {
142 //
143 // Put the character into the data word
144 //
145
146 #if defined(LOCKLESS)
147 word36 tmpdata;
148 core_read(cpup, cpu.char_word_address, &tmpdata, __func__);
149 if (tmpdata != cpu.ou.character_data)
150 sim_warn("write char: data changed from %llo to %llo at %o\r\n",
151 (long long unsigned int)cpu.ou.character_data,
152 (long long unsigned int)tmpdata, cpu.char_word_address);
153 #endif
154
155 switch (cpu.ou.characterOperandSize)
156 {
157 case TB6:
158 putChar (& cpu.ou.character_data, cpu.CY & 077, cpu.ou.characterOperandOffset);
159 break;
160
161 case TB9:
162 putByte (& cpu.ou.character_data, cpu.CY & 0777, cpu.ou.characterOperandOffset);
163 break;
164 }
165
166 //
167 // Write it
168 //
169
170 PNL (cpu.prepare_state |= ps_SAW);
171
172 #if defined(LOCKLESSXXX)
173 // gives warnings as another lock is acquired in between
174 core_write_unlock (cpup, cpu.char_word_address, cpu.ou.character_data, __func__);
175 #else
176 WriteOperandStore (cpup, cpu.ou.character_address, cpu.ou.character_data);
177 #endif
178
179 sim_debug (DBG_ADDRMOD, & cpu_dev,
180 "%s IT wrote char/byte %012"PRIo64" to %06o "
181 "tTB=%o tCF=%o\r\n",
182 __func__, cpu.ou.character_data, cpu.ou.character_address,
183 cpu.ou.characterOperandSize, cpu.ou.characterOperandOffset);
184
185 // Restore the CA; Read/Write() updates it.
186 //cpu.TPR.CA = indwordAddress;
187 cpu.TPR.CA = cpu.ou.character_address;
188 return;
189 } // IT
190
191 write_operand (cpup, cpu.TPR.CA, OPERAND_STORE);
192
193 return;
194 }
195
196 // CANFAULT
197 static void readOperands (cpu_state_t * cpup)
/* ![[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)
*/
198 {
199 char buf [256];
200 CPT (cpt2U, 3); // read operands
201 DCDstruct * i = & cpu.currentInstruction;
202
203 sim_debug (DBG_ADDRMOD, &cpu_dev,
204 "%s (%s):mne=%s flags=%x\r\n",
205 __func__, disassemble (buf, IWB_IRODD), i->info->mne, i->info->flags);
206 sim_debug (DBG_ADDRMOD, &cpu_dev,
207 "%s a %d address %08o\r\n", __func__, i->b29, cpu.TPR.CA);
208
209 PNL (cpu.prepare_state |= ps_POA);
210
211 word6 rTAG = 0;
212 if (! (i->info->flags & NO_TAG))
213 rTAG = GET_TAG (cpu.cu.IWB);
214 word6 Td = GET_TD (rTAG);
215 word6 Tm = GET_TM (rTAG);
216
217 //
218 // DU
219 //
220
221 if (Tm == TM_R && Td == TD_DU)
222 {
223 cpu.CY = 0;
224 SETHI (cpu.CY, cpu.TPR.CA);
225 sim_debug (DBG_ADDRMOD, & cpu_dev,
226 "%s DU CY=%012"PRIo64"\r\n", __func__, cpu.CY);
227 return;
228 }
229
230 //
231 // DL
232 //
233
234 if (Tm == TM_R && Td == TD_DL)
235 {
236 cpu.CY = 0;
237 SETLO (cpu.CY, cpu.TPR.CA);
238 sim_debug (DBG_ADDRMOD, & cpu_dev,
239 "%s DL CY=%012"PRIo64"\r\n", __func__, cpu.CY);
240 return;
241 }
242
243 //
244 // IT CI/SC/SCR
245 //
246
247 if (Tm == TM_IT && (Td == IT_CI || Td == IT_SC || Td == IT_SCR))
248 {
249 //
250 // Get the character from the data word
251 //
252
253 switch (cpu.ou.characterOperandSize)
254 {
255 case TB6:
256 cpu.CY = GETCHAR (cpu.ou.character_data, cpu.ou.characterOperandOffset);
257 break;
258
259 case TB9:
260 cpu.CY = GETBYTE (cpu.ou.character_data, cpu.ou.characterOperandOffset);
261 break;
262 }
263
264 sim_debug (DBG_ADDRMOD, & cpu_dev,
265 "%s IT read operand %012"PRIo64" from"
266 " %06o char/byte=%"PRIo64"\r\n",
267 __func__, cpu.ou.character_data, cpu.ou.character_address, cpu.CY);
268
269 // Restore the CA; Read/Write() updates it.
270 cpu.TPR.CA = cpu.ou.character_address;
271 return;
272 } // IT
273
274 #if defined(LOCKLESS)
275 if ((i->info->flags & RMW) == RMW)
276 readOperandRMW (cpup, cpu.TPR.CA);
277 else
278 readOperandRead (cpup, cpu.TPR.CA);
279 #else
280 readOperandRead (cpup, cpu.TPR.CA);
281 #endif
282
283 return;
284 }
285
286 static void read_tra_op (cpu_state_t * cpup)
/* ![[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)
*/
287 {
288 if (cpu.TPR.CA & 1)
289 ReadOperandRead (cpup, cpu.TPR.CA, &cpu.CY);
290 else
291 Read2OperandRead (cpup, cpu.TPR.CA, cpu.Ypair);
292 if (! (get_addr_mode (cpup) == APPEND_mode || cpu.cu.TSN_VALID [0] ||
293 cpu.cu.XSF || cpu.currentInstruction.b29 /*get_went_appending ()*/))
294 {
295 if (cpu.currentInstruction.info->flags & TSPN_INS)
296 {
297 word3 n;
298 if (cpu.currentInstruction.opcode <= 0273) //-V536
299 n = (cpu.currentInstruction.opcode & 3);
300 else
301 n = (cpu.currentInstruction.opcode & 3) + 4;
302
303 // C(PPR.PRR) -> C(PRn.RNR)
304 // C(PPR.PSR) -> C(PRn.SNR)
305 // C(PPR.IC) -> C(PRn.WORDNO)
306 // 000000 -> C(PRn.BITNO)
307 cpu.PR[n].RNR = cpu.PPR.PRR;
308 // According the AL39, the PSR is 'undefined' in absolute mode.
309 // ISOLTS thinks it means "don't change the operand"
310 if (get_addr_mode (cpup) == APPEND_mode)
311 cpu.PR[n].SNR = cpu.PPR.PSR;
312 cpu.PR[n].WORDNO = (cpu.PPR.IC + 1) & MASK18;
313 SET_PR_BITNO (n, 0);
314 #if defined(TESTING)
315 HDBGRegPRW (n, "read_tra_op tsp");
316 #endif
317 }
318 cpu.PPR.IC = cpu.TPR.CA;
319 // ISOLTS 870-02f
320 //cpu.PPR.PSR = 0;
321 }
322 sim_debug (DBG_TRACE, & cpu_dev, "%s %05o:%06o\r\n",
323 __func__, cpu.PPR.PSR, cpu.PPR.IC);
324 if (cpu.PPR.IC & 1)
325 {
326 cpu.cu.IWB = cpu.CY;
327 cpu.cu.IRODD = cpu.CY;
328 }
329 else
330 {
331 cpu.cu.IWB = cpu.Ypair[0];
332 cpu.cu.IRODD = cpu.Ypair[1];
333 }
334 }
335
336 static void dump_words (cpu_state_t * cpup, word36 * words)
/* ![[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)
*/
337 {
338 sim_debug (DBG_FAULT, & cpu_dev,
339 "CU: P %d IR %#o PSR %0#o IC %0#o TSR %0#o\r\n",
340 getbits36_1 (words[0], 18), getbits36_18 (words[4], 18),
341 getbits36_15 (words[0], 3), getbits36_18 (words[4], 0), getbits36_15 (words[2], 3));
342 sim_debug (DBG_FAULT, & cpu_dev,
343 "CU: xsf %d rf %d rpt %d rd %d rl %d pot %d xde %d xdo %d itp %d rfi %d its %d fif %d hold %0#o\r\n",
344 getbits36_1 (words[0], 19),
345 getbits36_1 (words[5], 18), getbits36_1 (words[5], 19), getbits36_1 (words[5], 20), getbits36_1 (words[5], 21),
346 getbits36_1 (words[5], 22), getbits36_1 (words[5], 24), getbits36_1 (words[5], 25), getbits36_1 (words[5], 26),
347 getbits36_1 (words[5], 27), getbits36_1 (words[5], 28), getbits36_1 (words[5], 29), getbits36_6 (words[5], 30));
348 sim_debug (DBG_FAULT, & cpu_dev,
349 "CU: iwb %012"PRIo64" irodd %012"PRIo64"\r\n",
350 words[6], words[7]);
351 }
352
353 static void scu2words (cpu_state_t * cpup, word36 *words)
/* ![[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)
*/
354 {
355 CPT (cpt2U, 6); // scu2words
356 (void)memset (words, 0, 8 * sizeof (* words));
357
358 // words[0]
359
360 putbits36_3 (& words[0], 0, cpu.PPR.PRR);
361 putbits36_15 (& words[0], 3, cpu.PPR.PSR);
362 putbits36_1 (& words[0], 18, cpu.PPR.P);
363 putbits36_1 (& words[0], 19, cpu.cu.XSF);
364 // 20, 1 SDWAMM Match on SDWAM
365 putbits36_1 (& words[0], 21, cpu.cu.SD_ON);
366 // 22, 1 PTWAMM Match on PTWAM
367 putbits36_1 (& words[0], 23, cpu.cu.PT_ON);
368
369
370
371
372
373
374
375
376
377
378
379 // XXX Only the top 9 bits are used in APUCycleBits, so this is
380 // zeroing the 3 FTC bits at the end of the word; on the
381 // other hand this keeps the values in apuStatusBits clearer.
382 // If FTC is ever used, be sure to put its save code after this
383 // line.
384 putbits36_12 (& words[0], 24, cpu.cu.APUCycleBits);
385
386
387 // words[1]
388
389 putbits36_1 (& words[1], 0, cpu.cu.IRO_ISN);
390 putbits36_1 (& words[1], 1, cpu.cu.OEB_IOC);
391 putbits36_1 (& words[1], 2, cpu.cu.EOFF_IAIM);
392 putbits36_1 (& words[1], 3, cpu.cu.ORB_ISP);
393 putbits36_1 (& words[1], 4, cpu.cu.ROFF_IPR);
394 putbits36_1 (& words[1], 5, cpu.cu.OWB_NEA);
395 putbits36_1 (& words[1], 6, cpu.cu.WOFF_OOB);
396 putbits36_1 (& words[1], 7, cpu.cu.NO_GA);
397 putbits36_1 (& words[1], 8, cpu.cu.OCB);
398 putbits36_1 (& words[1], 9, cpu.cu.OCALL);
399 putbits36_1 (& words[1], 10, cpu.cu.BOC);
400 putbits36_1 (& words[1], 11, cpu.cu.PTWAM_ER);
401 putbits36_1 (& words[1], 12, cpu.cu.CRT);
402 putbits36_1 (& words[1], 13, cpu.cu.RALR);
403 putbits36_1 (& words[1], 14, cpu.cu.SDWAM_ER);
404 putbits36_1 (& words[1], 15, cpu.cu.OOSB);
405 putbits36_1 (& words[1], 16, cpu.cu.PARU);
406 putbits36_1 (& words[1], 17, cpu.cu.PARL);
407 putbits36_1 (& words[1], 18, cpu.cu.ONC1);
408 putbits36_1 (& words[1], 19, cpu.cu.ONC2);
409 putbits36_4 (& words[1], 20, cpu.cu.IA);
410 putbits36_3 (& words[1], 24, cpu.cu.IACHN);
411 putbits36_3 (& words[1], 27, cpu.cu.CNCHN);
412 putbits36_5 (& words[1], 30, cpu.cu.FI_ADDR);
413 putbits36_1 (& words[1], 35, cpu.cycle == INTERRUPT_cycle ? 0 : 1);
414
415 // words[2]
416
417 putbits36_3 (& words[2], 0, cpu.TPR.TRR);
418 putbits36_15 (& words[2], 3, cpu.TPR.TSR);
419 // 18, 4 PTWAM levels enabled
420 // 22, 4 SDWAM levels enabled
421 // 26, 1 0
422 putbits36_3 (& words[2], 27, (word3) cpu.switches.cpu_num);
423 putbits36_6 (& words[2], 30, cpu.cu.delta);
424
425 // words[3]
426
427 putbits36_3 (& words[3], 18, cpu.cu.TSN_VALID[0] ? cpu.cu.TSN_PRNO[0] : 0);
428 putbits36_1 (& words[3], 21, cpu.cu.TSN_VALID[0]);
429 putbits36_3 (& words[3], 22, cpu.cu.TSN_VALID[1] ? cpu.cu.TSN_PRNO[1] : 0);
430 putbits36_1 (& words[3], 25, cpu.cu.TSN_VALID[1]);
431 putbits36_3 (& words[3], 26, cpu.cu.TSN_VALID[2] ? cpu.cu.TSN_PRNO[2] : 0);
432 putbits36_1 (& words[3], 29, cpu.cu.TSN_VALID[2]);
433 putbits36_6 (& words[3], 30, cpu.TPR.TBR);
434
435 // words[4]
436
437 putbits36_18 (& words[4], 0, cpu.PPR.IC);
438
439 // According the AL39, the Hex Mode bit should be 0, but ISOLTS pas2 exec checks it;
440 // this code does not set it to zero and indicated by AL39.
441
442 putbits36_18 (& words[4], 18, cpu.cu.IR);
443
444 // ISOLTS 887 test-03a
445 // Adding this makes test03 hang instead of erroring;
446 // presumably it's stuck on some later test.
447 // An 'Add Delta' addressing mode will alter the TALLY bit;
448 // restore it.
449
450 // Breaks ISOLTS 768
451 //putbits36_1 (& words[4], 25, cpu.currentInstruction.stiTally);
452
453 //#if defined(ISOLTS)
454 //testing for ipr fault by attempting execution of
455 //the illegal opcode 000 and bit 27 not set
456 //in privileged-append-bar mode.
457 //
458 //expects ABS to be clear....
459 //
460 //testing for ipr fault by attempting execution of
461 //the illegal opcode 000 and bit 27 not set
462 //in absolute-bar mode.
463 //
464 //expects ABS to be set
465
466 //if (cpu.PPR.P && TST_I_NBAR == 0) fails 101007 absolute-bar mode; s/b set
467 //if (cpu.PPR.P == 0 && TST_I_NBAR == 0)
468 //if (TST_I_NBAR == 0 && TST_I_ABS == 1) // If ABS BAR
469 //{
470 //putbits36 (& words[4], 31, 1, 0);
471 // putbits36 (& words[4], 31, 1, cpu.PPR.P ? 0 : 1);
472 //if (current_running_cpu_idx)
473 //sim_printf ("cleared ABS\r\n");
474 //}
475 //#endif
476
477 // words[5]
478
479 putbits36 (& words[5], 0, 18, cpu.TPR.CA);
480 putbits36 (& words[5], 18, 1, cpu.cu.repeat_first);
481 putbits36 (& words[5], 19, 1, cpu.cu.rpt);
482 putbits36 (& words[5], 20, 1, cpu.cu.rd);
483 putbits36 (& words[5], 21, 1, cpu.cu.rl);
484 putbits36 (& words[5], 22, 1, cpu.cu.pot);
485 // 23, 1 PON Prepare operand no tally
486 putbits36_1 (& words[5], 24, cpu.cu.xde);
487 putbits36_1 (& words[5], 25, cpu.cu.xdo);
488 putbits36_1 (& words[5], 26, cpu.cu.itp);
489 putbits36_1 (& words[5], 27, cpu.cu.rfi);
490 putbits36_1 (& words[5], 28, cpu.cu.its);
491 putbits36_1 (& words[5], 29, cpu.cu.FIF);
492 putbits36_6 (& words[5], 30, cpu.cu.CT_HOLD);
493
494 // words[6]
495
496 words[6] = cpu.cu.IWB;
497
498 // words[7]
499
500 words[7] = cpu.cu.IRODD;
501 //sim_printf ("scu2words %lld %012llo\r\n", cpu.cycleCnt, words [6]);
502
503 if_sim_debug (DBG_FAULT, & cpu_dev)
504 dump_words (cpup, words);
505
506 if (cpu.tweaks.isolts_mode)
507 {
508 struct
509 {
510 word36 should_be[8];
511 word36 was[8];
512 char *name;
513 }
514 rewrite_table[] =
515 {
516 { { 0000001400021, 0000000000011, 0000001000100, 0000000000000,
517 0000016400000, 0110015000500, 0110015011000, 0110015011000 },
518 { 0000001400011, 0000000000011, 0000001000100, 0000000000000,
519 0000016400000, 0110015000100, 0110015011000, 0110015011000 },
520 "pa865 test-03a inhibit", // rfi
521 },
522 { { 0000000401001, 0000000000041, 0000001000100, 0000000000000,
523 0101175000220, 0000006000000, 0100006235100, 0100006235100 },
524 { 0000000601001, 0000000000041, 0000001000100, 0000000000000,
525 0101175000220, 0000006000000, 0100006235100, 0100006235100 },
526 "pa870 test-01a dir. fault",
527 },
528 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
529 0000000200200, 0000003000000, 0200003716100, 0000005755000 },
530 { 0000000651001, 0000000000041, 0000001000100, 0000000000000,
531 0000000200200, 0000003000000, 0200003716100, 0000005755000 },
532 "pa885 test-05a xec inst",
533 },
534 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
535 0000000200200, 0000002000000, 0200002717100, 0110002001000 },
536 { 0000000651001, 0000000000041, 0000001000100, 0000000000000,
537 0000000200200, 0000002000000, 0200002717100, 0110002001000 },
538 "pa885 test-05b xed inst",
539 },
540 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
541 0000000200200, 0000004004000, 0200004235100, 0000005755000 },
542 { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
543 0000000200200, 0000004002000, 0200004235100, 0000005755000 },
544 "pa885 test-05c xed inst", // xde/xdo
545 },
546 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
547 0000001200200, 0000004006000, 0200004235100, 0000005755000 },
548 { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
549 0000001200200, 0000004002000, 0200004235100, 0000005755000 },
550 "pa885 test-05d xed inst", // xde/xdo
551 },
552 { { 0000000454201, 0000000000041, 0000000000100, 0000000000000,
553 0001777200200, 0002000000500, 0005600560201, 0005600560201 },
554 { 0000000450201, 0000000000041, 0000000000100, 0000000000000,
555 0001777200200, 0002000000000, 0005600560201, 0005600560201 },
556 "pa885 test-06a rpd inst", // rfi/fif
557 },
558 { { 0000000451001, 0000000000041, 0000001000101, 0000000000000,
559 0002000200200, 0000003500001, 0200003235111, 0002005755012 },
560 { 0000000651001, 0000000000041, 0000001000101, 0000000000000,
561 0002000202200, 0000003500000, 0200003235111, 0002005755012 },
562 "pa885 test-06b rpd inst", // tro ct-hold
563 },
564 { { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
565 0001776200200, 0002015500001, 0002015235031, 0002017755032 },
566 { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
567 0001776202200, 0002015500000, 0002015235031, 0002017755032 },
568 "pa885 test-06c rpd inst", // tro ct-hold
569 },
570 { { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
571 0001776000200, 0002000100012, 0001775235011, 0001775755012 },
572 { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
573 0001776000200, 0002000100000, 0001775235011, 0001775755012 },
574 "pa885 test-06d rpd inst", // ct-hold
575 },
576 { { 0000000404202, 0000000000041, 0000000000100, 0000000000000,
577 0002000202200, 0002000000500, 0001773755000, 0001773755000 },
578 { 0000000400202, 0000000000041, 0000000000100, 0000000000000,
579 0002000202200, 0002000000100, 0001773755000, 0001773755000 },
580 "pa885 test-10a scu snap (acv fault)", // rfi
581 }
582 };
583 int i;
584 for (i=0; i < 11; i++)
585 {
586 if (memcmp (words, rewrite_table[i].was, 8*sizeof (word36)) == 0)
587 {
588 memcpy (words, rewrite_table[i].should_be, 8*sizeof (word36));
589 sim_warn("%s: scu rewrite %d: %s\r\n", __func__, i, rewrite_table[i].name);
590 break;
591 }
592 }
593 }
594 }
595
596 void cu_safe_store (cpu_state_t * cpup)
/* ![[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)
*/
597 {
598 // Save current Control Unit Data in hidden temporary so a later SCU
599 // instruction running in FAULT mode can save the state as it existed at
600 // the time of the fault rather than as it exists at the time the SCU
601 // instruction is executed.
602 scu2words (cpup, cpu.scu_data);
603
604 cpu.cu_data.PSR = cpu.PPR.PSR;
605 cpu.cu_data.PRR = cpu.PPR.PRR;
606 cpu.cu_data.IC = cpu.PPR.IC;
607
608 tidy_cu (cpup);
609 }
610
611 void tidy_cu (cpu_state_t * cpup)
/* ![[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)
*/
612 {
613 // The only places this is called is in fault and interrupt processing;
614 // once the CU is saved, it needs to be set to a usable state. Refactoring
615 // that code here so that there is only a single copy to maintain.
616
617 cpu.cu.delta = 0;
618 cpu.cu.repeat_first = false;
619 cpu.cu.rpt = false;
620 cpu.cu.rd = false;
621 cpu.cu.rl = false;
622 cpu.cu.pot = false;
623 cpu.cu.itp = false;
624 cpu.cu.its = false;
625 cpu.cu.xde = false;
626 cpu.cu.xdo = false;
627 }
628
629 static void words2scu (cpu_state_t * cpup, word36 * words)
/* ![[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)
*/
630 {
631 CPT (cpt2U, 7); // words2scu
632 // BUG: We don't track much of the data that should be tracked
633
634 // words[0]
635
636 cpu.PPR.PRR = getbits36_3 (words[0], 0);
637 cpu.PPR.PSR = getbits36_15 (words[0], 3);
638 cpu.PPR.P = getbits36_1 (words[0], 18);
639 cpu.cu.XSF = getbits36_1 (words[0], 19);
640 sim_debug (DBG_TRACEEXT, & cpu_dev, "%s sets XSF to %o\r\n", __func__, cpu.cu.XSF);
641 //cpu.cu.SDWAMM = getbits36_1 (words[0], 20);
642 //cpu.cu.SD_ON = getbits36_1 (words[0], 21);
643 //cpu.cu.PTWAMM = getbits36_1 (words[0], 22);
644 //cpu.cu.PT_ON = getbits36_1 (words[0], 23);
645
646
647
648
649
650
651
652
653
654
655
656 //cpu.cu.APUCycleBits = getbits36_12 (words[0], 24);
657
658 // The FCT is stored in APUCycleBits
659 cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | (word12) getbits36_3 (words[0], 33));
660
661 // words[1]
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691 // words[2]
692
693 cpu.TPR.TRR = getbits36_3 (words[2], 0);
694 cpu.TPR.TSR = getbits36_15 (words[2], 3);
695 // 18-21 PTW
696 // 22-25 SDW
697 // 26 0
698 // 27-29 CPU number
699 cpu.cu.delta = getbits36_6 (words[2], 30);
700
701 // words[3]
702
703 // 0-17 0
704
705 cpu.cu.TSN_PRNO[0] = getbits36_3 (words[3], 18);
706 cpu.cu.TSN_VALID[0] = getbits36_1 (words[3], 21);
707 cpu.cu.TSN_PRNO[1] = getbits36_3 (words[3], 22);
708 cpu.cu.TSN_VALID[1] = getbits36_1 (words[3], 25);
709 cpu.cu.TSN_PRNO[2] = getbits36_3 (words[3], 26);
710 cpu.cu.TSN_VALID[2] = getbits36_1 (words[3], 29);
711 cpu.TPR.TBR = getbits36_6 (words[3], 30);
712
713 // words[4]
714
715 cpu.cu.IR = getbits36_18 (words[4], 18); // HWR
716 cpu.PPR.IC = getbits36_18 (words[4], 0);
717
718 // words[5]
719
720 // AL39 pg 75, RCU does not restore CA
721 //cpu.TPR.CA = getbits36_18 (words[5], 0);
722 cpu.cu.repeat_first = getbits36_1 (words[5], 18);
723 cpu.cu.rpt = getbits36_1 (words[5], 19);
724 cpu.cu.rd = getbits36_1 (words[5], 20);
725 cpu.cu.rl = getbits36_1 (words[5], 21);
726 cpu.cu.pot = getbits36_1 (words[5], 22);
727 // 23 PON
728 cpu.cu.xde = getbits36_1 (words[5], 24);
729 cpu.cu.xdo = getbits36_1 (words[5], 25);
730 cpu.cu.itp = getbits36_1 (words[5], 26);
731 cpu.cu.rfi = getbits36_1 (words[5], 27);
732 cpu.cu.its = getbits36_1 (words[5], 28);
733 cpu.cu.FIF = getbits36_1 (words[5], 29);
734 cpu.cu.CT_HOLD = getbits36_6 (words[5], 30);
735
736 // words[6]
737
738 cpu.cu.IWB = words[6];
739
740 // words[7]
741
742 cpu.cu.IRODD = words[7];
743 }
744
745 void cu_safe_restore (cpu_state_t * cpup)
/* ![[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)
*/
746 {
747 words2scu (cpup, cpu.scu_data);
748 decode_instruction (cpup, IWB_IRODD, & cpu.currentInstruction);
749 }
750
751 static void du2words (cpu_state_t * cpup, word36 * words)
/* ![[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)
*/
752 {
753 CPT (cpt2U, 7); // du2words
754
755 if (cpu.tweaks.isolts_mode)
756 {
757 for (int i = 0; i < 8; i ++)
758 {
759 words[i] = cpu.du.image[i];
760 }
761 }
762 else
763 {
764 (void)memset (words, 0, 8 * sizeof (* words));
765 }
766
767 // Word 0
768
769 putbits36_1 (& words[0], 9, cpu.du.Z);
770 putbits36_1 (& words[0], 10, cpu.du.NOP);
771 putbits36_24 (& words[0], 12, cpu.du.CHTALLY);
772
773 // Word 1
774
775 if (cpu.tweaks.isolts_mode)
776 words[1] = words[0];
777
778 // Word 2
779
780 putbits36_18 (& words[2], 0, cpu.du.D1_PTR_W);
781 putbits36_6 (& words[2], 18, cpu.du.D1_PTR_B);
782 putbits36_2 (& words[2], 25, cpu.du.TAk[0]);
783 putbits36_1 (& words[2], 31, cpu.du.F1);
784 putbits36_1 (& words[2], 32, cpu.du.Ak[0]);
785
786 // Word 3
787
788 putbits36_10 (& words[3], 0, cpu.du.LEVEL1);
789 putbits36_24 (& words[3], 12, cpu.du.D1_RES);
790
791 // Word 4
792
793 putbits36_18 (& words[4], 0, cpu.du.D2_PTR_W);
794 putbits36_6 (& words[4], 18, cpu.du.D2_PTR_B);
795 putbits36_2 (& words[4], 25, cpu.du.TAk[1]);
796 putbits36_1 (& words[4], 30, cpu.du.R);
797 putbits36_1 (& words[4], 31, cpu.du.F2);
798 putbits36_1 (& words[4], 32, cpu.du.Ak[1]);
799
800 // Word 5
801
802 putbits36_10 (& words[5], 0, cpu.du.LEVEL2);
803 putbits36_24 (& words[5], 12, cpu.du.D2_RES);
804
805 // Word 6
806
807 putbits36_18 (& words[6], 0, cpu.du.D3_PTR_W);
808 putbits36_6 (& words[6], 18, cpu.du.D3_PTR_B);
809 putbits36_2 (& words[6], 25, cpu.du.TAk[2]);
810 putbits36_1 (& words[6], 31, cpu.du.F3);
811 putbits36_1 (& words[6], 32, cpu.du.Ak[2]);
812 putbits36_3 (& words[6], 33, cpu.du.JMP);
813
814 // Word 7
815
816 putbits36_24 (& words[7], 12, cpu.du.D3_RES);
817
818 }
819
820 static void words2du (cpu_state_t * cpup, word36 * words)
/* ![[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)
*/
821 {
822 CPT (cpt2U, 8); // words2du
823 // Word 0
824
825 cpu.du.Z = getbits36_1 (words[0], 9);
826 cpu.du.NOP = getbits36_1 (words[0], 10);
827 cpu.du.CHTALLY = getbits36_24 (words[0], 12);
828 // Word 1
829
830 // Word 2
831
832 cpu.du.D1_PTR_W = getbits36_18 (words[2], 0);
833 cpu.du.D1_PTR_B = getbits36_6 (words[2], 18);
834 cpu.du.TAk[0] = getbits36_2 (words[2], 25);
835 cpu.du.F1 = getbits36_1 (words[2], 31);
836 cpu.du.Ak[0] = getbits36_1 (words[2], 32);
837
838 // Word 3
839
840 cpu.du.LEVEL1 = getbits36_10 (words[3], 0);
841 cpu.du.D1_RES = getbits36_24 (words[3], 12);
842
843 // Word 4
844
845 cpu.du.D2_PTR_W = getbits36_18 (words[4], 0);
846 cpu.du.D2_PTR_B = getbits36_6 (words[4], 18);
847 cpu.du.TAk[1] = getbits36_2 (words[4], 25);
848 cpu.du.F2 = getbits36_1 (words[4], 31);
849 cpu.du.Ak[1] = getbits36_1 (words[4], 32);
850
851 // Word 5
852
853 cpu.du.LEVEL2 = getbits36_1 (words[5], 9);
854 cpu.du.D2_RES = getbits36_24 (words[5], 12);
855
856 // Word 6
857
858 cpu.du.D3_PTR_W = getbits36_18 (words[6], 0);
859 cpu.du.D3_PTR_B = getbits36_6 (words[6], 18);
860 cpu.du.TAk[2] = getbits36_2 (words[6], 25);
861 cpu.du.F3 = getbits36_1 (words[6], 31);
862 cpu.du.Ak[2] = getbits36_1 (words[6], 32);
863 cpu.du.JMP = getbits36_3 (words[6], 33);
864
865 // Word 7
866
867 cpu.du.D3_RES = getbits36_24 (words[7], 12);
868
869 if (cpu.tweaks.isolts_mode)
870 {
871 for (int i = 0; i < 8; i ++)
872 {
873 cpu.du.image[i] = words[i];
874 }
875 }
876 }
877
878 static char *PRalias[] = {"ap", "ab", "bp", "bb", "lp", "lb", "sp", "sb" };
879
880 //=============================================================================
881
882 // illegal modifications for various instructions
883
884 /*
885
886 00 01 02 03 04 05 06 07
887
888 00 -- au qu du ic al ql dl R
889 10 0 1 2 3 4 5 6 7
890
891 20 n* au* qu* -- ic* al* al* -- RI
892 30 0* 1* 2* 3* 4* 5* 6* 7*
893
894 40 f1 itp -- its sd scr f2 f3 IT
895 50 ci i sc ad di dic id idc
896
897 60 *n *au *qu -- *ic *al *al -- IR
898 70 *0 *1 *2 *3 *4 *5 *6 *7
899
900 bool _allowed[] = {
901 // Tm = 0 (register) R
902 // -- au qu du ic al ql dl
903 true, false, false, false, false, false, false, false,
904 // 0 1 2 3 4 5 6 7
905 false, false, false, false, false, false, false, false,
906 // Tm = 1 (register then indirect) RI
907 // n* au* qu* -- ic* al* al* --
908 false, false, false, true, false, false, false, true,
909 // 0* 1* 2* 3* 4* 5* 6* 7*
910 false, false, false, false, false, false, false, false,
911 // Tm = 2 (indirect then tally) IT
912 // f1 itp -- its sd scr f2 f3
913 false, false, true, false, false, false, false, false,
914 // ci i sc ad di dic id idc
915 false, false, false, false, false, false, false, false,
916 // Tm = 3 (indirect then register) IR
917 // *n *au *qu -- *ic *al *al --
918 false, false, false, true, false, false, false, true,
919 // *0 *1 *2 *3 *4 *5 *6 *7
920 false, false, false, false, false, false, false, false,
921 };
922
923 */
924 // No DUDL
925
926 static bool _nodudl[] = {
927 // Tm = 0 (register) R
928 // -- au qu du ic al ql dl
929 false, false, false, true, false, false, false, true,
930 // 0 1 2 3 4 5 6 7
931 false, false, false, false, false, false, false, false,
932 // Tm = 1 (register then indirect) RI
933 // n* au* qu* -- ic* al* al* --
934 false, false, false, true, false, false, false, true,
935 // 0* 1* 2* 3* 4* 5* 6* 7*
936 false, false, false, false, false, false, false, false,
937 // Tm = 2 (indirect then tally) IT
938 // f1 itp -- its sd scr f2 f3
939 false, false, true, false, false, false, false, false,
940 // ci i sc ad di dic id idc
941 false, false, false, false, false, false, false, false,
942 // Tm = 3 (indirect then register) IR
943 // *n *au *qu -- *ic *al *al --
944 false, false, false, true, false, false, false, true,
945 // *0 *1 *2 *3 *4 *5 *6 *7
946 false, false, false, false, false, false, false, false,
947 };
948
949 // No DU
950 // No DL
951
952 // (NO_CI | NO_SC | NO_SCR)
953 static bool _nocss[] = {
954 // Tm = 0 (register) R
955 // * au qu du ic al ql dl
956 false, false, false, false, false, false, false, false,
957 // 0 1 2 3 4 5 6 7
958 false, false, false, false, false, false, false, false,
959 // Tm = 1 (register then indirect) RI
960 // n* au* qu* -- ic* al* al* --
961 false, false, false, true, false, false, false, true,
962 // 0* 1* 2* 3* 4* 5* 6* 7*
963 false, false, false, false, false, false, false, false,
964 // Tm = 2 (indirect then tally) IT
965 // f1 itp -- its sd scr f2 f3
966 false, false, true, false, false, true, false, false,
967 // ci i sc ad di dic id idc
968 true, false, true, false, false, false, false, false,
969 // Tm = 3 (indirect then register) IR
970 // *n *au *qu -- *ic *al *al --
971 false, false, false, true, false, false, false, true,
972 // *0 *1 *2 *3 *4 *5 *6 *7
973 false, false, false, false, false, false, false, false,
974 };
975
976 // (NO_DUDL | NO_CISCSCR)
977 static bool _noddcss[] = {
978 // Tm = 0 (register) R
979 // * au qu du ic al ql dl
980 false, false, false, true, false, false, false, true,
981 // 0 1 2 3 4 5 6 7
982 false, false, false, false, false, false, false, false,
983 // Tm = 1 (register then indirect) RI
984 // n* au* qu* -- ic* al* al* --
985 false, false, false, true, false, false, false, true,
986 // 0* 1* 2* 3* 4* 5* 6* 7*
987 false, false, false, false, false, false, false, false,
988 // Tm = 2 (indirect then tally) IT
989 // f1 itp -- its sd scr f2 f3
990 false, false, true, false, false, true, false, false,
991 // ci i sc ad di dic id idc
992 true, false, true, false, false, false, false, false,
993 // Tm = 3 (indirect then register) IR
994 // *n *au *qu -- *ic *al *al --
995 false, false, false, true, false, false, false, true,
996 // *0 *1 *2 *3 *4 *5 *6 *7
997 false, false, false, false, false, false, false, false,
998 };
999
1000 // (NO_DUDL | NO_CISCSCR)
1001 static bool _nodlcss[] = {
1002 // Tm = 0 (register) R
1003 // * au qu du ic al ql dl
1004 false, false, false, false, false, false, false, true,
1005 // 0 1 2 3 4 5 6 7
1006 false, false, false, false, false, false, false, false,
1007 // Tm = 1 (register then indirect) RI
1008 // n* au* qu* -- ic* al* al* --
1009 false, false, false, true, false, false, false, true,
1010 // 0* 1* 2* 3* 4* 5* 6* 7*
1011 false, false, false, false, false, false, false, false,
1012 // Tm = 2 (indirect then tally) IT
1013 // f1 itp -- its sd scr f2 f3
1014 false, false, true, false, false, true, false, false,
1015 // ci i sc ad di dic id idc
1016 true, false, true, false, false, false, false, false,
1017 // Tm = 3 (indirect then register) IR
1018 // *n *au *qu -- *ic *al *al --
1019 false, false, false, true, false, false, false, true,
1020 // *0 *1 *2 *3 *4 *5 *6 *7
1021 false, false, false, false, false, false, false, false,
1022 };
1023
1024 static bool _onlyaqxn[] = {
1025 // Tm = 0 (register) R
1026 // -- au qu du ic al ql dl
1027 false, false, false, true, true, false, false, true,
1028 // 0 1 2 3 4 5 6 7
1029 false, false, false, false, false, false, false, false,
1030 // Tm = 1 (register then indirect) RI
1031 // n* au* qu* -- ic* al* al* --
1032 false, false, false, true, false, false, false, true,
1033 // 0* 1* 2* 3* 4* 5* 6* 7*
1034 false, false, false, false, false, false, false, false,
1035 // Tm = 2 (indirect then tally) IT
1036 // f1 itp -- its sd scr f2 f3
1037 false, false, true, false, false, false, false, false,
1038 // ci i sc ad di dic id idc
1039 false, false, false, false, false, false, false, false,
1040 // Tm = 3 (indirect then register) IR
1041 // *n *au *qu -- *ic *al *al --
1042 false, false, false, true, false, false, false, true,
1043 // *0 *1 *2 *3 *4 *5 *6 *7
1044 false, false, false, false, false, false, false, false,
1045 };
1046
1047 #if !defined(QUIET_UNUSED)
1048 static bool _illmod[] = {
1049 // Tm = 0 (register) R
1050 // * au qu du ic al ql dl
1051 false, false, false, false, false, false, false, false,
1052 // 0 1 2 3 4 5 6 7
1053 false, false, false, false, false, false, false, false,
1054 // Tm = 1 (register then indirect) RI
1055 // n* au* qu* -- ic* al* al* --
1056 false, false, false, true, false, false, false, true,
1057 // 0* 1* 2* 3* 4* 5* 6* 7*
1058 false, false, false, false, false, false, false, false,
1059 // Tm = 2 (indirect then tally) IT
1060 // f1 itp -- its sd scr f2 f3
1061 false, false, true, false, false, false, false, false,
1062 // ci i sc ad di dic id idc
1063 false, false, false, false, false, false, false, false,
1064 // Tm = 3 (indirect then register) IR
1065 // *n *au *qu -- *ic *al *al --
1066 // *0 *1 *2 *3 *4 *5 *6 *7
1067 false, false, false, true, false, false, false, true,
1068 false, false, false, false, false, false, false, false,
1069 };
1070 #endif
1071
1072 //=============================================================================
1073
1074 #if defined(MATRIX)
1075
1076 static long long theMatrix[1024] // 1024 opcodes (2^10)
1077 [2] // opcode extension
1078 [2] // bit 29
1079 [64]; // Tag
1080
1081 void initializeTheMatrix (void)
/* ![[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)
*/
1082 {
1083 (void)memset (theMatrix, 0, sizeof (theMatrix));
1084 }
1085
1086 void addToTheMatrix (uint32 opcode, bool opcodeX, bool a, word6 tag)
/* ![[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)
*/
1087 {
1088 // safety
1089 uint _opcode = opcode & 01777;
1090 int _opcodeX = opcodeX ? 1 : 0;
1091 int _a = a ? 1 : 0;
1092 int _tag = tag & 077;
1093 theMatrix[_opcode][_opcodeX][_a][_tag] ++;
1094 }
1095
1096 t_stat display_the_matrix (UNUSED int32 arg, UNUSED const char * buf)
/* ![[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)
*/
1097 {
1098 long long count;
1099
1100 for (int opcode = 0; opcode < 01000; opcode ++)
1101 for (int opcodeX = 0; opcodeX < 2; opcodeX ++)
1102 {
1103 long long total = 0;
1104 for (int a = 0; a < 2; a ++)
1105 for (int tag = 0; tag < 64; tag ++)
1106 if ((count = theMatrix[opcode][opcodeX][a][tag]))
1107 {
1108 // disassemble doesn't quite do what we want so copy the good bits
1109 static char result[132] = "???";
1110 strcpy (result, "???");
1111 // get mnemonic ...
1112 if (opcodes10 [opcode | (opcodeX ? 01000 : 0)].mne)
1113 strcpy (result, opcodes10[opcode | (opcodeX ? 01000 : 0)].mne);
1114 if (a)
1115 strcat (result, " prn|nnnn");
1116 else
1117 strcat (result, " nnnn");
1118
1119 // get mod
1120 if (extMods[tag].mod)
1121 {
1122 strcat (result, ",");
1123 strcat (result, extMods[tag].mod);
1124 }
1125 if (result[0] == '?')
1126 sim_printf ("%20"PRId64": ? opcode 0%04o X %d a %d tag 0%02do\r\n",
1127 count, opcode, opcodeX, a, tag);
1128 else
1129 sim_printf ("%20"PRId64": %s\r\n", count, result);
1130 total += count;
1131 }
1132 static char result[132] = "???";
1133 strcpy (result, "???");
1134 if (total) {
1135 // get mnemonic ...
1136 if (opcodes10 [opcode | (opcodeX ? 01000 : 0)].mne)
1137 strcpy (result, opcodes10[opcode | (opcodeX ? 01000 : 0)].mne);
1138 sim_printf ("%20"PRId64": %s\r\n", total, result);
1139 }
1140 }
1141 return SCPE_OK;
1142 }
1143 #endif
1144
1145 // fetch instruction at address
1146 // CANFAULT
1147 void fetchInstruction (cpu_state_t * cpup, word18 addr)
/* ![[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)
*/
1148 {
1149 CPT (cpt2U, 9); // fetchInstruction
1150
1151 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1152 {
1153 cpu.TPR.TRR = 0;
1154 cpu.RSDWH_R1 = 0;
1155 //cpu.PPR.P = 1; // XXX this should be already set by set_addr_mode, so no worry here
1156 }
1157
1158 if (cpu.cu.rd && ((cpu.PPR.IC & 1) != 0))
1159 {
1160 if (cpu.cu.repeat_first)
1161 {
1162 CPT (cpt2U, 10); // fetch rpt odd
1163 //Read (addr, & cpu.cu.IRODD, INSTRUCTION_FETCH);
1164 }
1165 }
1166 else if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1167 {
1168 if (cpu.cu.repeat_first)
1169 {
1170 CPT (cpt2U, 11); // fetch rpt even
1171 if (addr & 1)
1172 ReadInstructionFetch (cpup, addr, & cpu.cu.IWB);
1173 else
1174 {
1175 word36 tmp[2];
1176 /* Read2 (addr, tmp, INSTRUCTION_FETCH); */
1177 /* cpu.cu.IWB = tmp[0]; */
1178 Read2InstructionFetch (cpup, addr, tmp);
1179 cpu.cu.IWB = tmp[0];
1180 cpu.cu.IRODD = tmp[1];
1181 }
1182 }
1183 }
1184 else
1185 {
1186 CPT (cpt2U, 12); // fetch
1187
1188 // ISOLTS test pa870 expects IRODD to be set up.
1189 // If we are fetching an even instruction, also fetch the odd.
1190 // If we are fetching an odd instruction, copy it to IRODD as
1191 // if that was where we got it from.
1192
1193 //Read (addr, & cpu.cu.IWB, INSTRUCTION_FETCH);
1194 if ((cpu.PPR.IC & 1) == 0) // Even
1195 {
1196 word36 tmp[2];
1197 /* Read2 (addr, tmp, INSTRUCTION_FETCH); */
1198 /* cpu.cu.IWB = tmp[0]; */
1199 Read2InstructionFetch (cpup, addr, tmp);
1200 cpu.cu.IWB = tmp[0];
1201 cpu.cu.IRODD = tmp[1];
1202 }
1203 else // Odd
1204 {
1205 ReadInstructionFetch (cpup, addr, & cpu.cu.IWB);
1206 cpu.cu.IRODD = cpu.cu.IWB;
1207 }
1208 }
1209 }
1210
1211 #if defined(TESTING)
1212 void traceInstruction (uint flag)
/* ![[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)
*/
1213 {
1214 cpu_state_t * cpup = _cpup;
1215 char buf [256];
1216 if (! flag) goto force;
1217 if_sim_debug (flag, &cpu_dev)
1218 {
1219 force:;
1220 char * compname;
1221 word18 compoffset;
1222 char * where = lookup_address (cpu.PPR.PSR, cpu.PPR.IC, & compname,
1223 & compoffset);
1224 bool isBAR = TST_I_NBAR ? false : true;
1225 if (where)
1226 {
1227 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1228 {
1229 if (isBAR)
1230 {
1231 sim_debug (flag, &cpu_dev, "%06o|%06o %s\r\n",
1232 cpu.BAR.BASE, cpu.PPR.IC, where);
1233 }
1234 else
1235 {
1236 sim_debug (flag, &cpu_dev, "%06o %s\r\n", cpu.PPR.IC, where);
1237 }
1238 }
1239 else if (get_addr_mode (cpup) == APPEND_mode)
1240 {
1241 if (isBAR)
1242 {
1243 sim_debug (flag, &cpu_dev, "%05o:%06o|%06o %s\r\n",
1244 cpu.PPR.PSR,
1245 cpu.BAR.BASE, cpu.PPR.IC, where);
1246 }
1247 else
1248 {
1249 sim_debug (flag, &cpu_dev, "%05o:%06o %s\r\n",
1250 cpu.PPR.PSR, cpu.PPR.IC, where);
1251 }
1252 }
1253 list_source (compname, compoffset, flag);
1254 }
1255 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1256 {
1257 if (isBAR)
1258 {
1259 sim_debug (flag, &cpu_dev,
1260 "%d: "
1261 "%05o|%06o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1262 current_running_cpu_idx,
1263 cpu.BAR.BASE,
1264 cpu.PPR.IC,
1265 IWB_IRODD,
1266 disassemble (buf, IWB_IRODD),
1267 cpu.currentInstruction.address,
1268 cpu.currentInstruction.opcode,
1269 cpu.currentInstruction.opcodeX,
1270 cpu.currentInstruction.b29,
1271 cpu.currentInstruction.i,
1272 GET_TM (cpu.currentInstruction.tag) >> 4,
1273 GET_TD (cpu.currentInstruction.tag) & 017);
1274 }
1275 else
1276 {
1277 sim_debug (flag, &cpu_dev,
1278 "%d: "
1279 "%06o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1280 current_running_cpu_idx,
1281 cpu.PPR.IC,
1282 IWB_IRODD,
1283 disassemble (buf, IWB_IRODD),
1284 cpu.currentInstruction.address,
1285 cpu.currentInstruction.opcode,
1286 cpu.currentInstruction.opcodeX,
1287 cpu.currentInstruction.b29,
1288 cpu.currentInstruction.i,
1289 GET_TM (cpu.currentInstruction.tag) >> 4,
1290 GET_TD (cpu.currentInstruction.tag) & 017);
1291 }
1292 }
1293 else if (get_addr_mode (cpup) == APPEND_mode)
1294 {
1295 if (isBAR)
1296 {
1297 sim_debug (flag, &cpu_dev,
1298 "%d: "
1299 "%05o:%06o|%06o %o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1300 current_running_cpu_idx,
1301 cpu.PPR.PSR,
1302 cpu.BAR.BASE,
1303 cpu.PPR.IC,
1304 cpu.PPR.PRR,
1305 IWB_IRODD,
1306 disassemble (buf, IWB_IRODD),
1307 cpu.currentInstruction.address,
1308 cpu.currentInstruction.opcode,
1309 cpu.currentInstruction.opcodeX,
1310 cpu.currentInstruction.b29, cpu.currentInstruction.i,
1311 GET_TM (cpu.currentInstruction.tag) >> 4,
1312 GET_TD (cpu.currentInstruction.tag) & 017);
1313 }
1314 else
1315 {
1316 sim_debug (flag, &cpu_dev,
1317 "%d: "
1318 "%05o:%06o %o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1319 current_running_cpu_idx,
1320 cpu.PPR.PSR,
1321 cpu.PPR.IC,
1322 cpu.PPR.PRR,
1323 IWB_IRODD,
1324 disassemble (buf, IWB_IRODD),
1325 cpu.currentInstruction.address,
1326 cpu.currentInstruction.opcode,
1327 cpu.currentInstruction.opcodeX,
1328 cpu.currentInstruction.b29,
1329 cpu.currentInstruction.i,
1330 GET_TM (cpu.currentInstruction.tag) >> 4,
1331 GET_TD (cpu.currentInstruction.tag) & 017);
1332 }
1333 }
1334 }
1335
1336 }
1337 #endif
1338
1339 bool chkOVF (cpu_state_t * cpup)
/* ![[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)
*/
1340 {
1341 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1342 {
1343 // a:AL39/rpd2
1344 // Did the repeat instruction inhibit overflow faults?
1345 if ((cpu.rX[0] & 00001) == 0)
1346 return false;
1347 }
1348 return true;
1349 }
1350
1351 bool tstOVFfault (cpu_state_t * cpup)
/* ![[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)
*/
1352 {
1353 // Masked?
1354 if (TST_I_OMASK)
1355 return false;
1356 // Doing a RPT/RPD?
1357 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1358 {
1359 // a:AL39/rpd2
1360 // Did the repeat instruction inhibit overflow faults?
1361 if ((cpu.rX[0] & 00001) == 0)
1362 return false;
1363 }
1364 return true;
1365 }
1366
1367 #if defined(TESTING)
1368 # include "tracker.h"
1369 #endif
1370
1371 t_stat executeInstruction (cpu_state_t * cpup) {
/* ![[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)
*/
1372 #if defined(TESTING)
1373 trk (cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC, IWB_IRODD);
1374 #endif
1375 CPT (cpt2U, 13); // execute instruction
1376
1377 //
1378 // Decode the instruction
1379 //
1380 // If not restart
1381 // if xec/xed
1382 // check for illegal execute
1383 // if rpt/rpd
1384 // check for illegal rpt/rpd modifiers
1385 // check for illegal modifiers
1386 // check for privilege
1387 // initialize CA
1388 //
1389 // Save tally
1390 // Debug trace instruction
1391 // If not restart
1392 // Initialize TPR
1393 //
1394 // Initialize DU.JMP
1395 // If rpt/rpd
1396 // If first repeat
1397 // Initialize Xn
1398 //
1399 // If EIS instruction
1400 // If not restart
1401 // Initialize DU.CHTALLY, DU.Z
1402 // Read operands
1403 // Parse operands
1404 // Else not EIS instruction
1405 // If not restart
1406 // If B29
1407 // Set TPR from pointer register
1408 // Else
1409 // Setup up TPR
1410 // Initialize CU.CT_HOLD
1411 // If restart and CU.POT
1412 // Restore CA from IWB
1413 // Do CAF if needed
1414 // Read operand if needed
1415 //
1416 // Execute the instruction
1417 //
1418 // Write operand if needed
1419 // Update IT tally if needed
1420 // If XEC/XED, move instructions into IWB/IRODD
1421 // If instruction was repeated
1422 // Update Xn
1423 // Check for repeat termination
1424 // Post-instruction debug
1425
1426 ///
1427 /// executeInstruction: Decode the instruction
1428 ///
1429
1430 DCDstruct * ci = & cpu.currentInstruction;
1431 decode_instruction (cpup, IWB_IRODD, ci);
1432 const struct opcode_s *info = ci->info;
1433
1434 // Local caches of frequently accessed data
1435
1436 const uint ndes = info->ndes;
1437 const bool restart = cpu.cu.rfi; // instruction is to be restarted
1438 cpu.cu.rfi = 0;
1439 const opc_flag flags = info->flags;
1440 const enum opc_mod mods = info->mods;
1441 const uint32 opcode = ci->opcode; // opcode
1442 const bool opcodeX = ci->opcodeX; // opcode extension
1443 const word6 tag = ci->tag; // instruction tag
1444
1445 #if defined(MATRIX)
1446 {
1447 const uint32 opcode = ci->opcode; // opcode
1448 const bool opcodeX = ci->opcodeX; // opcode extension
1449 // XXX replace with rY
1450 const bool b29 = ci->b29; // bit-29 - addressing via pointer
1451 // register
1452 const word6 tag = ci->tag; // instruction tag
1453 // XXX replace withrTAG
1454 addToTheMatrix (opcode, opcodeX, b29, tag);
1455 }
1456 #endif
1457
1458 if (ci->b29)
1459 ci->address = SIGNEXT15_18 (ci->address & MASK15);
1460
1461 L68_ (
1462 CPTUR (cptUseMR);
1463 if (UNLIKELY (cpu.MR.emr && cpu.MR.OC_TRAP)) {
1464 if (cpu.MR.OPCODE == opcode && cpu.MR.OPCODEX == opcodeX) {
1465 if (cpu.MR.ihrrs) {
1466 cpu.MR.ihr = 0;
1467 }
1468 CPT (cpt2U, 14); // opcode trap
1469 //set_FFV_fault (2); // XXX According to AL39
1470 do_FFV_fault (cpup, 1, "OC TRAP");
1471 }
1472 }
1473 )
1474
1475 ///
1476 /// executeInstruction: Non-restart processing
1477 ///
1478
1479 if (LIKELY (!restart) || UNLIKELY (ndes > 0)) { // until we implement EIS restart
1480 cpu.cu.TSN_VALID[0] = 0;
1481 cpu.cu.TSN_VALID[1] = 0;
1482 cpu.cu.TSN_VALID[2] = 0;
1483 cpu.cu.TSN_PRNO[0] = 0;
1484 cpu.cu.TSN_PRNO[1] = 0;
1485 cpu.cu.TSN_PRNO[2] = 0;
1486 }
1487
1488 if (UNLIKELY (restart))
1489 goto restart_1;
1490
1491 //
1492 // not restart
1493 //
1494
1495 cpu.cu.XSF = 0;
1496
1497 cpu.cu.pot = 0;
1498 cpu.cu.its = 0;
1499 cpu.cu.itp = 0;
1500
1501 CPT (cpt2U, 14); // non-restart processing
1502 // Set Address register empty
1503 PNL (L68_ (cpu.AR_F_E = false;))
1504
1505 // Reset the fault counter
1506 cpu.cu.APUCycleBits &= 07770;
1507
1508 //cpu.cu.TSN_VALID[0] = 0;
1509 //cpu.cu.TSN_VALID[1] = 0;
1510 //cpu.cu.TSN_VALID[2] = 0;
1511
1512 // If executing the target of XEC/XED, check the instruction is allowed
1513 if (UNLIKELY (cpu.isXED)) {
1514 if (flags & NO_XED)
1515 doFault (FAULT_IPR, fst_ill_proc,
1516 "Instruction not allowed in XEC/XED");
1517 // The even instruction from C(Y-pair) must not alter
1518 // C(Y-pair)36,71, and must not be another xed instruction.
1519 if (opcode == 0717 && !opcodeX && cpu.cu.xde && cpu.cu.xdo /* even instruction being executed */)
1520 doFault (FAULT_IPR, fst_ill_proc,
1521 "XED of XED on even word");
1522 // ISOLTS 791 03k, 792 03k
1523 if (opcode == 0560 && !opcodeX) {
1524 // To Execute Double (XED) the RPD instruction, the RPD must be the second
1525 // instruction at an odd-numbered address.
1526 if (cpu.cu.xde && cpu.cu.xdo /* even instr being executed */)
1527 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1528 "XED of RPD on even word");
1529 // To execute an instruction pair having an rpd instruction as the odd
1530 // instruction, the xed instruction must be located at an odd address.
1531 if (!cpu.cu.xde && cpu.cu.xdo /* odd instr being executed */ && !(cpu.PPR.IC & 1))
1532 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1533 "XED of RPD on odd word, even IC");
1534 }
1535 } else if (UNLIKELY (cpu.isExec)) {
1536 // To execute a rpd instruction, the xec instruction must be in an odd location.
1537 // ISOLTS 768 01w
1538 if (opcode == 0560 && !opcodeX && cpu.cu.xde && !(cpu.PPR.IC & 1))
1539 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1540 "XEC of RPx on even word");
1541 }
1542
1543 // ISOLTS wants both the not allowed in RPx and RPx illegal modifier
1544 // tested.
1545 fault_ipr_subtype_ RPx_fault = 0;
1546
1547 // RPT/RPD illegal modifiers
1548 // a:AL39/rpd3
1549 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1550 if (! (flags & NO_TAG)) {
1551 // check for illegal modifiers:
1552 // only R & RI are allowed
1553 // only X1..X7
1554 switch (GET_TM (tag)) {
1555 case TM_RI:
1556 if (cpu.cu.rl)
1557 RPx_fault |= FR_ILL_MOD;
1558 break;
1559 case TM_R:
1560 break;
1561 default:
1562 // generate fault. Only R & RI allowed
1563 RPx_fault |= FR_ILL_MOD;
1564 }
1565
1566 word6 Td = GET_TD (tag);
1567 if (Td == TD_X0)
1568 RPx_fault |= FR_ILL_MOD;
1569 if (Td < TD_X0)
1570 RPx_fault |= FR_ILL_MOD;
1571 }
1572
1573 DPS8M_ (
1574 // ISOLTS 792 03e
1575 // this is really strange. possibly a bug in DPS8M HW (L68 handles it the same as all other instructions)
1576 if (RPx_fault && !opcodeX && opcode==0413) // rscr
1577 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=RPx_fault},
1578 "DPS8M rscr early raise");
1579 )
1580
1581 // Instruction not allowed in RPx?
1582
1583 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1584 if (flags & NO_RPT)
1585 RPx_fault |= FR_ILL_PROC;
1586 }
1587
1588 if (UNLIKELY (cpu.cu.rl)) {
1589 if (flags & NO_RPL)
1590 RPx_fault |= FR_ILL_PROC;
1591 }
1592
1593 L68_ (
1594 // ISOLTS 791 03d, 792 03d
1595 // L68 wants ILL_MOD here - stca,stcq,stba,stbq,scpr,lcpr
1596 // all these instructions have a nonstandard TAG field interpretation. probably a HW bug in decoder
1597 if (RPx_fault && !opcodeX && (opcode==0751 || opcode==0752 || opcode==0551 || opcode==0552 || opcode==0452 || opcode==0674))
1598 RPx_fault |= FR_ILL_MOD;
1599 )
1600 }
1601
1602 // PVS-Studio says: Expression 'RPx_fault != 0' is always false.
1603 if (UNLIKELY (RPx_fault != 0)) //-V547
1604 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=RPx_fault},
1605 "RPx test fail");
1606
1607 /// check for illegal addressing mode(s) ...
1608 ///
1609 // ISOLTS wants both the IPR and illegal modifier tested.
1610 fault_ipr_subtype_ mod_fault = 0;
1611
1612 // No CI/SC/SCR allowed
1613 if (mods == NO_CSS) {
1614 if (_nocss[tag])
1615 mod_fault |= FR_ILL_MOD; // "Illegal CI/SC/SCR modification"
1616 }
1617 // No DU/DL/CI/SC/SCR allowed
1618 else if (mods == NO_DDCSS) {
1619 if (_noddcss[tag])
1620 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL/CI/SC/SCR modification"
1621 }
1622 // No DL/CI/SC/SCR allowed
1623 else if (mods == NO_DLCSS) {
1624 if (_nodlcss[tag])
1625 mod_fault |= FR_ILL_MOD; // "Illegal DL/CI/SC/SCR modification"
1626 }
1627 // No DU/DL allowed
1628 else if (mods == NO_DUDL) {
1629 if (_nodudl[tag])
1630 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL modification"
1631 }
1632 else if ((unsigned long long)mods == (unsigned long long)ONLY_AU_QU_AL_QL_XN) {
1633 if (_onlyaqxn[tag])
1634 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL/IC modification"
1635 }
1636
1637 L68_ (
1638 // L68 raises it immediately
1639 if (mod_fault)
1640 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=mod_fault},
1641 "Illegal modifier");
1642 )
1643
1644 // check for priv ins - Attempted execution in normal or BAR modes causes a
1645 // illegal procedure fault.
1646 if (UNLIKELY (flags & PRIV_INS)) {
1647 DPS8M_ (
1648 // DPS8M illegal instructions lptp,lptr,lsdp,lsdr
1649 // ISOLTS 890 05abc
1650 if (((opcode == 0232 || opcode == 0173) && opcodeX ) || (opcode == 0257))
1651 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1652 "Attempted execution of multics privileged instruction.");
1653 )
1654
1655 if (!is_priv_mode (cpup)) {
1656 // Multics privileged instructions: absa,ldbr,lra,rcu,scu,sdbr,ssdp,ssdr,sptp,sptr
1657 // ISOLTS 890 05abc,06abc
1658 bool prv;
1659 DPS8M_ (
1660 prv =((opcode == 0212 || opcode == 0232 || opcode == 0613 || opcode == 0657) && !opcodeX ) ||
1661 ((opcode == 0254 || opcode == 0774) && opcodeX ) ||
1662 (opcode == 0557 || opcode == 0154);
1663 )
1664 L68_ (
1665 // on L68, lptp,lptr,lsdp,lsdr instructions are not illegal, so handle them here
1666 prv = ((opcode == 0212 || opcode == 0232 || opcode == 0613 || opcode == 0657) && !opcodeX ) ||
1667 ((opcode == 0254 || opcode == 0774 || opcode == 0232 || opcode == 0173) && opcodeX ) ||
1668 (opcode == 0557 || opcode == 0154 || opcode == 0257);
1669 )
1670 if (prv) {
1671 if (!get_bar_mode (cpup)) {
1672 // ISOLTS-890 05ab
1673 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1674 "Attempted execution of multics privileged instruction.");
1675 } else {
1676 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1677 "Attempted execution of multics privileged instruction.");
1678 }
1679 }
1680 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1681 "Attempted execution of privileged instruction.");
1682 }
1683 }
1684
1685 if (UNLIKELY (flags & NO_BAR)) {
1686 if (get_bar_mode(cpup)) {
1687 // lbar
1688 // ISOLTS 890 06a
1689 // ISOLTS says that L68 handles this in the same way
1690 if (opcode == 0230 && !opcodeX)
1691 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1692 "Attempted BAR execution of nonprivileged instruction.");
1693 else
1694 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1695 "Attempted BAR execution of nonprivileged instruction.");
1696 }
1697 }
1698
1699 DPS8M_ (
1700 // DPS8M raises it delayed
1701 if (UNLIKELY (mod_fault != 0))
1702 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=mod_fault},
1703 "Illegal modifier");
1704 )
1705
1706 ///
1707 /// executeInstruction: Restart or Non-restart processing
1708 /// Initialize address registers
1709 ///
1710
1711 restart_1:
1712 CPT (cpt2U, 15); // instruction processing
1713
1714 ///
1715 /// executeInstruction: Initialize state saving registers
1716 ///
1717
1718 // XXX this may be wrong; make sure that the right value is used
1719 // if a page fault occurs. (i.e. this may belong above restart_1.
1720 // This is also used by the SCU instruction. ISOLTS tst887 does
1721 // a 'SCU n,ad' with a tally of 1; the tally is decremented, setting
1722 // the IR tally bit as part of the CA calculation; this is not
1723 // the machine conditions that the SCU instruction is saving.
1724
1725 ci->stiTally = TST_I_TALLY; // for sti instruction
1726
1727 ///
1728 /// executeInstruction: scp hooks
1729 ///
1730
1731 #if !defined(SPEED)
1732 // Don't trace Multics idle loop
1733 //if (cpu.PPR.PSR != 061 || cpu.PPR.IC != 0307)
1734
1735 {
1736 traceInstruction (DBG_TRACE);
1737 # if defined(DBGEVENT)
1738 int dbgevt;
1739 if (n_dbgevents && (dbgevt = (dbgevent_lookup (cpu.PPR.PSR, cpu.PPR.IC))) >= 0) {
1740 if (dbgevents[dbgevt].t0)
1741 clock_gettime (CLOCK_REALTIME, & dbgevent_t0);
1742 struct timespec now, delta;
1743 clock_gettime (CLOCK_REALTIME, & now);
1744 timespec_diff (& dbgevent_t0, & now, & delta);
1745 sim_printf ("[%d] %5ld.%03ld %s\r\n", dbgevt, delta.tv_sec, delta.tv_nsec/1000000, dbgevents[dbgevt].tag);
1746 }
1747 # endif
1748 # if defined(TESTING)
1749 HDBGTrace ("");
1750 # endif
1751 }
1752 #else // !SPEED
1753 // Don't trace Multics idle loop
1754 //if (cpu.PPR.PSR != 061 || cpu.PPR.IC != 0307)
1755 # if defined(TESTING)
1756 HDBGTrace ("");
1757 # endif
1758 #endif // !SPEED
1759
1760 ///
1761 /// executeInstruction: Initialize misc.
1762 ///
1763
1764 cpu.du.JMP = (word3) ndes;
1765 cpu.dlyFlt = false;
1766
1767 ///
1768 /// executeInstruction: RPT/RPD/RPL special processing for 'first time'
1769 ///
1770
1771 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1772 CPT (cpt2U, 15); // RPx processing
1773
1774 //
1775 // RPT:
1776 //
1777 // The computed address, y, of the operand (in the case of R modification) or
1778 // indirect word (in the case of RI modification) is determined as follows:
1779 //
1780 // For the first execution of the repeated instruction:
1781 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1782 //
1783 // For all successive executions of the repeated instruction:
1784 // C(Xn) + Delta -> y, y -> C(Xn);
1785 //
1786 //
1787 // RPD:
1788 //
1789 // The computed addresses, y-even and y-odd, of the operands (in the case of
1790 // R modification) or indirect words (in the case of RI modification) are
1791 // determined as follows:
1792 //
1793 // For the first execution of the repeated instruction pair:
1794 // C(C(PPR.IC)+1)0,17 + C(X-even) -> y-even, y-even -> C(X-even)
1795 // C(C(PPR.IC)+2)0,17 + C(X-odd) -> y-odd, y-odd -> C(X-odd)
1796 //
1797 // For all successive executions of the repeated instruction pair:
1798 // if C(X0)8 = 1, then C(X-even) + Delta -> y-even,
1799 // y-even -> C(X-even);
1800 // otherwise, C(X-even) -> y-even
1801 // if C(X0)9 = 1, then C(X-odd) + Delta -> y-odd,
1802 // y-odd -> C(X-odd);
1803 // otherwise, C(X-odd) -> y-odd
1804 //
1805 // C(X0)8,9 correspond to control bits A and B, respectively, of the rpd
1806 // instruction word.
1807 //
1808 //
1809 // RL:
1810 //
1811 // The computed address, y, of the operand is determined as follows:
1812 //
1813 // For the first execution of the repeated instruction:
1814 //
1815 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1816 //
1817 // For all successive executions of the repeated instruction:
1818 //
1819 // C(Xn) -> y
1820 //
1821 // if C(Y)0,17 != 0, then C (y)0,17 -> C(Xn);
1822 //
1823 // otherwise, no change to C(Xn)
1824 //
1825 // C(Y)0,17 is known as the link address and is the computed address of the
1826 // next entry in a threaded list of operands to be referenced by the repeated
1827 // instruction.
1828 //
1829
1830 sim_debug (DBG_TRACEEXT, & cpu_dev,
1831 "RPT/RPD first %d rpt %d rd %d e/o %d X0 %06o a %d b %d\r\n",
1832 cpu.cu.repeat_first, cpu.cu.rpt, cpu.cu.rd, cpu.PPR.IC & 1, cpu.rX[0],
1833 !! (cpu.rX[0] & 01000), !! (cpu.rX[0] & 0400));
1834 sim_debug (DBG_TRACEEXT, & cpu_dev,
1835 "RPT/RPD CA %06o\r\n", cpu.TPR.CA);
1836
1837 // Handle first time of a RPT or RPD
1838
1839 if (cpu.cu.repeat_first) {
1840 CPT (cpt2U, 16); // RPx first processing
1841 // The semantics of these are that even is the first instruction of
1842 // and RPD, and odd the second.
1843
1844 bool icOdd = !! (cpu.PPR.IC & 1);
1845 bool icEven = ! icOdd;
1846
1847 // If RPT or (RPD and the odd instruction)
1848 if (cpu.cu.rpt || (cpu.cu.rd && icOdd) || cpu.cu.rl)
1849 cpu.cu.repeat_first = false;
1850
1851 // a:RJ78/rpd6
1852 // For the first execution of the repeated instruction:
1853 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1854 if (cpu.cu.rpt || // rpt
1855 (cpu.cu.rd && icEven) || // rpd & even
1856 (cpu.cu.rd && icOdd) || // rpd & odd
1857 cpu.cu.rl) { // rl
1858 word18 offset = ci->address;
1859 offset &= AMASK;
1860
1861 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; offset is %06o\r\n", offset);
1862
1863 word6 Td = GET_TD (tag);
1864 uint Xn = X (Td); // Get Xn of next instruction
1865 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; X%d was %06o\r\n", Xn, cpu.rX[Xn]);
1866 // a:RJ78/rpd5
1867 cpu.TPR.CA = (cpu.rX[Xn] + offset) & AMASK;
1868 cpu.rX[Xn] = cpu.TPR.CA;
1869 #if defined(TESTING)
1870 HDBGRegXW (Xn, "rpt 1st");
1871 #endif
1872 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
1873 } // rpt or rd or rl
1874
1875 } // repeat first
1876 } // cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl
1877
1878 ///
1879 /// Restart or Non-restart
1880 ///
1881
1882 ///
1883 /// executeInstruction: EIS operand processing
1884 ///
1885
1886 if (UNLIKELY (ndes > 0)) {
1887 CPT (cpt2U, 27); // EIS operand processing
1888 sim_debug (DBG_APPENDING, &cpu_dev, "initialize EIS descriptors\r\n");
1889 // This must not happen on instruction restart
1890 if (!restart) {
1891 CPT (cpt2U, 28); // EIS not restart
1892 cpu.du.CHTALLY = 0;
1893 cpu.du.Z = 1;
1894 }
1895 for (uint n = 0; n < ndes; n += 1) {
1896 CPT (cpt2U, 29 + n); // EIS operand fetch (29, 30, 31)
1897 // XXX This is a bit of a hack; In general the code is good about
1898 // setting up for bit29 or PR operations by setting up TPR, but
1899 // assumes that the 'else' case can be ignored when it should set
1900 // TPR to the canonical values. Here, in the case of a EIS instruction
1901 // restart after page fault, the TPR is in an unknown state. Ultimately,
1902 // this should not be an issue, as this folderol would be in the DU, and
1903 // we would not be re-executing that code, but until then, set the TPR
1904 // to the condition we know it should be in.
1905 cpu.TPR.TRR = cpu.PPR.PRR;
1906 cpu.TPR.TSR = cpu.PPR.PSR;
1907
1908
1909
1910
1911
1912
1913
1914 // append cycles updates cpu.PPR.IC to TPR.CA
1915 word18 saveIC = cpu.PPR.IC;
1916 //Read (cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n], INSTRUCTION_FETCH);
1917 ReadInstructionFetch (cpup, cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n]);
1918 cpu.PPR.IC = saveIC;
1919 //Read (cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n], APU_DATA_READ);
1920
1921 }
1922 PNL (cpu.IWRAddr = cpu.currentEISinstruction.op[0]);
1923 setupEISoperands (cpup);
1924 }
1925
1926 ///
1927 /// Restart or Non-restart
1928 ///
1929
1930 ///
1931 /// executeInstruction: non-EIS operand processing
1932 ///
1933
1934 else {
1935 CPT (cpt2U, 32); // non-EIS operand processing
1936 CPT (cpt2U, 33); // not restart non-EIS operand processing
1937 if (ci->b29) { // if A bit set set-up TPR stuff ...
1938 CPT (cpt2U, 34); // B29
1939
1940 // AL39 says that RCU does not restore CA, so words to SCU does not.
1941 // So we do it here, even if restart
1942 word3 n = GET_PRN(IWB_IRODD); // get PRn
1943 word15 offset = GET_OFFSET(IWB_IRODD);
1944 CPTUR (cptUsePRn + n);
1945
1946 sim_debug (DBG_APPENDING, &cpu_dev,
1947 "doPtrReg: PR[%o] SNR=%05o RNR=%o WORDNO=%06o " "BITNO=%02o\r\n",
1948 n, cpu.PAR[n].SNR, cpu.PAR[n].RNR, cpu.PAR[n].WORDNO, GET_PR_BITNO (n));
1949
1950 // Fix tst880: 'call6 pr1|0'. The instruction does a DF1; the fault handler
1951 // updates PRR in the CU save data. On restart, TRR is not updated.
1952 // Removing the 'if' appears to resolve the problem without regressions.
1953 //if (!restart) {
1954 // Not EIS, bit 29 set, !restart
1955 cpu.TPR.TBR = GET_PR_BITNO (n);
1956
1957 cpu.TPR.TSR = cpu.PAR[n].SNR;
1958 if (ci->info->flags & TRANSFER_INS)
1959 cpu.TPR.TRR = max (cpu.PAR[n].RNR, cpu.PPR.PRR);
1960 else
1961 cpu.TPR.TRR = max3 (cpu.PAR[n].RNR, cpu.TPR.TRR, cpu.PPR.PRR);
1962
1963 sim_debug (DBG_APPENDING, &cpu_dev,
1964 "doPtrReg: n=%o offset=%05o TPR.CA=%06o " "TPR.TBR=%o TPR.TSR=%05o TPR.TRR=%o\r\n",
1965 n, offset, cpu.TPR.CA, cpu.TPR.TBR, cpu.TPR.TSR, cpu.TPR.TRR);
1966 //}
1967
1968 // Putting the a29 clear here makes sense, but breaks the emulator for unclear
1969 // reasons (possibly ABSA?). Do it in updateIWB instead
1970 // ci->a = false;
1971 // // Don't clear a; it is needed to detect change to appending
1972 // // mode
1973 // //a = false;
1974 // putbits36_1 (& cpu.cu.IWB, 29, 0);
1975 } else {
1976 // not eis, not bit b29
1977 if (!restart) {
1978 CPT (cpt2U, 35); // not B29
1979 cpu.cu.TSN_VALID [0] = 0;
1980 cpu.TPR.TBR = 0;
1981 if (get_addr_mode (cpup) == ABSOLUTE_mode) {
1982 cpu.TPR.TSR = cpu.PPR.PSR;
1983 cpu.TPR.TRR = 0;
1984 cpu.RSDWH_R1 = 0;
1985 }
1986 }
1987 }
1988
1989 // This must not happen on instruction restart
1990 if (!restart)
1991 cpu.cu.CT_HOLD = 0; // Clear interrupted IR mode flag
1992
1993 // These are set by do_caf
1994 cpu.ou.directOperandFlag = false;
1995 cpu.ou.directOperand = 0;
1996 cpu.ou.characterOperandSize = 0;
1997 cpu.ou.characterOperandOffset = 0;
1998 cpu.ou.crflag = false;
1999
2000 if ((flags & PREPARE_CA) || WRITEOP (ci) || READOP (ci)) {
2001 CPT (cpt2L, 1); // CAF
2002 do_caf (cpup);
2003 PNL (L68_ (cpu.AR_F_E = true;))
2004 cpu.iefpFinalAddress = cpu.TPR.CA;
2005 }
2006
2007 if (READOP (ci)) {
2008 CPT (cpt2L, 2); // Read operands
2009 readOperands (cpup);
2010 #if defined(LOCKLESS)
2011 cpu.rmw_address = cpu.iefpFinalAddress;
2012 #endif
2013 if (cpu.cu.rl) {
2014 switch (operand_size (cpup)) {
2015 case 1:
2016 cpu.lnk = GETHI36 (cpu.CY);
2017 cpu.CY &= MASK18;
2018 break;
2019
2020 case 2:
2021 cpu.lnk = GETHI36 (cpu.Ypair[0]);
2022 cpu.Ypair[0] &= MASK18;
2023 break;
2024
2025 default:
2026 break;
2027 }
2028 }
2029 }
2030 PNL (cpu.IWRAddr = 0);
2031 }
2032
2033 // Initialize zone to 'entire word'
2034
2035 cpu.useZone = false;
2036 cpu.zone = MASK36;
2037
2038 ///
2039 /// executeInstruction: Execute the instruction
2040 ///
2041
2042 t_stat ret = doInstruction (cpup);
2043
2044 ///
2045 /// executeInstruction: Write operand
2046 ///
2047
2048 cpu.last_write = 0;
2049 if (WRITEOP (ci)) {
2050 CPT (cpt2L, 3); // Write operands
2051 cpu.last_write = cpu.TPR.CA;
2052 #if defined(LOCKLESS)
2053 if ((ci->info->flags & RMW) == RMW) {
2054 if (operand_size(cpup) != 1)
2055 sim_warn("executeInstruction: operand_size!= 1\r\n");
2056 if (cpu.iefpFinalAddress != cpu.rmw_address)
2057 sim_warn("executeInstruction: write addr changed %o %d\r\n", cpu.iefpFinalAddress, cpu.rmw_address);
2058 core_write_unlock (cpup, cpu.iefpFinalAddress, cpu.CY, __func__);
2059 # if defined(TESTING)
2060 HDBGMWrite (cpu.iefpFinalAddress, cpu.CY, "Write RMW");
2061 # endif
2062 } else
2063 writeOperands (cpup);
2064 #else
2065 writeOperands (cpup);
2066 #endif
2067 }
2068
2069 else if (flags & PREPARE_CA) {
2070 // 'EPP ITS; TRA' confuses the APU by leaving last_cycle
2071 // at INDIRECT_WORD_FETCH; defoobarize the APU:
2072 fauxDoAppendCycle (cpup, OPERAND_READ);
2073 cpu.TPR.TRR = cpu.PPR.PRR;
2074 cpu.TPR.TSR = cpu.PPR.PSR;
2075 cpu.TPR.TBR = 0;
2076 }
2077
2078 ///
2079 /// executeInstruction: RPT/RPD/RPL processing
2080 ///
2081
2082 // The semantics of these are that even is the first instruction of
2083 // and RPD, and odd the second.
2084
2085 bool icOdd = !! (cpu.PPR.IC & 1);
2086 bool icEven = ! icOdd;
2087
2088 // Here, repeat_first means that the instruction just executed was the
2089 // RPT or RPD; but when the even instruction of a RPD is executed,
2090 // repeat_first is still set, since repeat_first cannot be cleared
2091 // until the odd instruction gets its first execution. Put some
2092 // ugly logic in to detect that condition.
2093
2094 bool rf = cpu.cu.repeat_first;
2095 if (rf && cpu.cu.rd && icEven)
2096 rf = false;
2097
2098 if (UNLIKELY ((! rf) && (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl))) {
2099 CPT (cpt2L, 7); // Post execution RPx
2100 // If we get here, the instruction just executed was a
2101 // RPT, RPD or RPL target instruction, and not the RPT or RPD
2102 // instruction itself
2103
2104 if (cpu.cu.rpt || cpu.cu.rd) {
2105 // Add delta to index register.
2106
2107 bool rptA = !! (cpu.rX[0] & 01000);
2108 bool rptB = !! (cpu.rX[0] & 00400);
2109
2110 sim_debug (DBG_TRACEEXT, & cpu_dev,
2111 "RPT/RPD delta first %d rf %d rpt %d rd %d " "e/o %d X0 %06o a %d b %d\r\n",
2112 cpu.cu.repeat_first, rf, cpu.cu.rpt, cpu.cu.rd, icOdd, cpu.rX[0], rptA, rptB);
2113
2114 if (cpu.cu.rpt) { // rpt
2115 CPT (cpt2L, 8); // RPT delta
2116 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2117 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2118 cpu.rX[Xn] = cpu.TPR.CA;
2119 #if defined(TESTING)
2120 HDBGRegXW (Xn, "rpt delta");
2121 #endif
2122 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2123 }
2124
2125 // a:RJ78/rpd6
2126 // We know that the X register is not to be incremented until
2127 // after both instructions have executed, so the following
2128 // if uses icOdd instead of the more sensical icEven.
2129 if (cpu.cu.rd && icOdd && rptA) { // rpd, even instruction
2130 CPT (cpt2L, 9); // RD even
2131 // a:RJ78/rpd7
2132 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2133 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2134 cpu.rX[Xn] = cpu.TPR.CA;
2135 #if defined(TESTING)
2136 HDBGRegXW (Xn, "rpd delta even");
2137 #endif
2138 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2139 }
2140
2141 if (cpu.cu.rd && icOdd && rptB) { // rpdb, odd instruction
2142 CPT (cpt2L, 10); // RD odd
2143 // a:RJ78/rpd8
2144 uint Xn = (uint) getbits36_3 (cpu.cu.IRODD, 36 - 3);
2145 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2146 cpu.rX[Xn] = cpu.TPR.CA;
2147 #if defined(TESTING)
2148 HDBGRegXW (Xn, "rpd delta odd");
2149 #endif
2150 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2151 }
2152 } // rpt || rd
2153
2154 // Check for termination conditions.
2155
2156 ///////
2157 //
2158 // ISOLTS test 769 claims in test-02a that 'rpt;div' with a divide
2159 // fault should delay the divide fault until after the termination
2160 // check (it checks that the tally should be decremented) and in test-02b
2161 // that 'rpl;div' with a divide fault should not due the termination
2162 // check (the tally should not be decremented).
2163 //
2164 // This implies that rpt and rpl are handled differently; as a test
2165 // trying:
2166
2167 bool flt;
2168 if (cpu.tweaks.l68_mode)
2169 flt = (cpu.cu.rl || cpu.cu.rpt || cpu.cu.rd) && cpu.dlyFlt; // L68
2170 else
2171 flt = cpu.cu.rl && cpu.dlyFlt;
2172 if (flt) {
2173 CPT (cpt2L, 14); // Delayed fault
2174 doFault (cpu.dlyFltNum, cpu.dlySubFltNum, cpu.dlyCtx);
2175 }
2176
2177 // Sadly, it fixes ISOLTS 769 test 02a and 02b.
2178 //
2179 ///////
2180
2181 if (cpu.cu.rpt || (cpu.cu.rd && icOdd) || cpu.cu.rl) {
2182 CPT (cpt2L, 12); // RPx termination check
2183 bool exit = false;
2184 // The repetition cycle consists of the following steps:
2185 // a. Execute the repeated instruction
2186 // b. C(X0)0,7 - 1 -> C(X0)0,7
2187 // a:AL39/rpd9
2188 uint x = (uint) getbits18 (cpu.rX[0], 0, 8);
2189 //x -= 1;
2190 // ubsan
2191 x = (uint) (((int) x) - 1);
2192 x &= MASK8;
2193 putbits18 (& cpu.rX[0], 0, 8, x);
2194 #if defined(TESTING)
2195 HDBGRegXW (0, "rpt term");
2196 #endif
2197
2198 // a:AL39/rpd10
2199 // c. If C(X0)0,7 = 0, then set the tally runout indicator ON
2200 // and terminate
2201
2202 sim_debug (DBG_TRACEEXT, & cpu_dev, "tally %d\r\n", x);
2203 if (x == 0) {
2204 sim_debug (DBG_TRACEEXT, & cpu_dev, "tally runout\r\n");
2205 SET_I_TALLY;
2206 exit = true;
2207 } else {
2208 sim_debug (DBG_TRACEEXT, & cpu_dev, "not tally runout\r\n");
2209 CLR_I_TALLY;
2210 }
2211
2212 // d. If a terminate condition has been met, then set
2213 // the tally runout indicator OFF and terminate
2214
2215 if (TST_I_ZERO && (cpu.rX[0] & 0100)) {
2216 sim_debug (DBG_TRACEEXT, & cpu_dev, "is zero terminate\r\n");
2217 CLR_I_TALLY;
2218 exit = true;
2219 }
2220 if (!TST_I_ZERO && (cpu.rX[0] & 040)) {
2221 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not zero terminate\r\n");
2222 CLR_I_TALLY;
2223 exit = true;
2224 }
2225 if (TST_I_NEG && (cpu.rX[0] & 020)) {
2226 sim_debug (DBG_TRACEEXT, & cpu_dev, "is neg terminate\r\n");
2227 CLR_I_TALLY;
2228 exit = true;
2229 }
2230 if (!TST_I_NEG && (cpu.rX[0] & 010)) {
2231 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not neg terminate\r\n");
2232 CLR_I_TALLY;
2233 exit = true;
2234 }
2235 if (TST_I_CARRY && (cpu.rX[0] & 04)) {
2236 sim_debug (DBG_TRACEEXT, & cpu_dev, "is carry terminate\r\n");
2237 CLR_I_TALLY;
2238 exit = true;
2239 }
2240 if (!TST_I_CARRY && (cpu.rX[0] & 02)) {
2241 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not carry terminate\r\n");
2242 CLR_I_TALLY;
2243 exit = true;
2244 }
2245 if (TST_I_OFLOW && (cpu.rX[0] & 01)) {
2246 sim_debug (DBG_TRACEEXT, & cpu_dev, "is overflow terminate\r\n");
2247 // ISOLTS test ps805 says that on overflow the tally should be set.
2248 //CLR_I_TALLY;
2249 SET_I_TALLY;
2250 exit = true;
2251 }
2252
2253 if (exit) {
2254 CPT (cpt2L, 13); // RPx terminated
2255 cpu.cu.rpt = false;
2256 cpu.cu.rd = false;
2257 cpu.cu.rl = false;
2258 } else {
2259 sim_debug (DBG_TRACEEXT, & cpu_dev, "not terminate\r\n");
2260 }
2261 } // if (cpu.cu.rpt || cpu.cu.rd & (cpu.PPR.IC & 1))
2262
2263 if (cpu.cu.rl) {
2264 CPT (cpt2L, 11); // RL
2265 if (cpu.lnk == 0) {
2266 CPT (cpt2L, 13); // RPx terminated
2267 cpu.cu.rpt = false;
2268 cpu.cu.rd = false;
2269 cpu.cu.rl = false;
2270 SET_I_TALLY;
2271 } else {
2272 // C(Xn) -> y
2273 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2274 //word18 lnk = GETHI36 (cpu.CY);
2275 //cpu.CY &= MASK18;
2276 cpu.rX[Xn] = cpu.lnk;
2277 #if defined(TESTING)
2278 HDBGRegXW (Xn, "rl");
2279 #endif
2280 }
2281 } // rl
2282 } // (! rf) && (cpu.cu.rpt || cpu.cu.rd)
2283
2284 if (UNLIKELY (cpu.dlyFlt)) {
2285 CPT (cpt2L, 14); // Delayed fault
2286 doFault (cpu.dlyFltNum, cpu.dlySubFltNum, cpu.dlyCtx);
2287 }
2288
2289 ///
2290 /// executeInstruction: scp hooks
2291 ///
2292
2293 cpu.instrCnt ++;
2294
2295 if_sim_debug (DBG_REGDUMP, & cpu_dev) {
2296 char buf [256];
2297 sim_debug (DBG_REGDUMPAQI, &cpu_dev, "A=%012"PRIo64" Q=%012"PRIo64" IR:%s\r\n",
2298 cpu.rA, cpu.rQ, dump_flags (buf, cpu.cu.IR));
2299 #if !defined(__MINGW64__) || !defined(__MINGW32__)
2300 sim_debug (DBG_REGDUMPFLT, &cpu_dev, "E=%03o A=%012"PRIo64" Q=%012"PRIo64" %.10Lg\r\n",
2301 cpu.rE, cpu.rA, cpu.rQ, EAQToIEEElongdouble (cpup));
2302 #else
2303 sim_debug (DBG_REGDUMPFLT, &cpu_dev, "E=%03o A=%012"PRIo64" Q=%012"PRIo64" %.10g\r\n",
2304 cpu.rE, cpu.rA, cpu.rQ, EAQToIEEEdouble (cpup));
2305 #endif
2306 sim_debug (DBG_REGDUMPIDX, &cpu_dev, "X[0]=%06o X[1]=%06o X[2]=%06o X[3]=%06o\r\n",
2307 cpu.rX[0], cpu.rX[1], cpu.rX[2], cpu.rX[3]);
2308 sim_debug (DBG_REGDUMPIDX, &cpu_dev, "X[4]=%06o X[5]=%06o X[6]=%06o X[7]=%06o\r\n",
2309 cpu.rX[4], cpu.rX[5], cpu.rX[6], cpu.rX[7]);
2310 for (int n = 0 ; n < 8 ; n++) {
2311 sim_debug (DBG_REGDUMPPR, &cpu_dev, "PR%d/%s: SNR=%05o RNR=%o WORDNO=%06o BITNO:%02o ARCHAR:%o ARBITNO:%02o\r\n",
2312 n, PRalias[n], cpu.PR[n].SNR, cpu.PR[n].RNR, cpu.PR[n].WORDNO,
2313 GET_PR_BITNO (n), GET_AR_CHAR (n), GET_AR_BITNO (n));
2314 }
2315 sim_debug (DBG_REGDUMPPPR, &cpu_dev, "PRR:%o PSR:%05o P:%o IC:%06o\r\n",
2316 cpu.PPR.PRR, cpu.PPR.PSR, cpu.PPR.P, cpu.PPR.IC);
2317 sim_debug (DBG_REGDUMPDSBR, &cpu_dev, "ADDR:%08o BND:%05o U:%o STACK:%04o\r\n",
2318 cpu.DSBR.ADDR, cpu.DSBR.BND, cpu.DSBR.U, cpu.DSBR.STACK);
2319 }
2320
2321 ///
2322 /// executeInstruction: done. (Whew!)
2323 ///
2324
2325 return ret;
2326 }
2327
2328 //static t_stat DoBasicInstruction (void);
2329 //static t_stat DoEISInstruction (void);
2330
2331 static inline void overflow (cpu_state_t * cpup, bool ovf, bool dly, const char * msg)
/* ![[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)
*/
2332 {
2333 CPT (cpt2L, 15); // overflow check
2334 // If an overflow occurred and the repeat instruction is not inhibiting
2335 // overflow checking.
2336 if (ovf && chkOVF (cpup))
2337 {
2338 SET_I_OFLOW;
2339 // If overflows are not masked
2340 if (tstOVFfault (cpup))
2341 {
2342 CPT (cpt2L, 16); // overflow
2343 // ISOLTS test ps768: Overflows set TRO.
2344 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
2345 {
2346 SET_I_TALLY;
2347 }
2348 if (dly)
2349 dlyDoFault (FAULT_OFL, fst_zero, msg);
2350 else
2351 doFault (FAULT_OFL, fst_zero, msg);
2352 }
2353 }
2354 }
2355
2356 // Return values
2357 // CONT_TRA
2358 // STOP_UNIMP
2359 // STOP_ILLOP
2360 // emCall()
2361 // STOP_HALT
2362 // scu_sscr()
2363 // STOP_BUG
2364 // STOP_WARN
2365 // scu_rmcm()
2366 // STOP_BUG
2367 // scu_smcm()
2368 // STOP_DIS
2369 // simh_hooks()
2370 // hard to document what this can return....
2371 // 0
2372 //
2373
2374 // CANFAULT
2375 HOT static t_stat doInstruction (cpu_state_t * cpup)
/* ![[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)
*/
2376 {
2377 DCDstruct * i = & cpu.currentInstruction;
2378 // AL39 says it is always cleared, but that makes no sense (what good
2379 // is an indicator bit if it is always 0 when you check it?). Clear it if
2380 // an multiword EIS is at bat.
2381 // NB: Never clearing it renders Multics unbootable.
2382 if (i->info->ndes > 0)
2383 CLR_I_MIF;
2384
2385 L68_ (
2386 cpu.ou.eac = 0;
2387 cpu.ou.RB1_FULL = 0;
2388 cpu.ou.RP_FULL = 0;
2389 cpu.ou.RS_FULL = 0;
2390 cpu.ou.STR_OP = 0;
2391 cpu.ou.cycle = 0;
2392 )
2393 PNL (cpu.ou.RS = (word9) i->opcode);
2394 PNL (L68_ (DU_CYCLE_FDUD;)) // set DU idle
2395 cpu.skip_cu_hist = false;
2396 memcpy (& cpu.MR_cache, & cpu.MR, sizeof (cpu.MR_cache));
2397
2398 // This mapping keeps nonEIS/EIS ordering, making various tables cleaner
2399 #define x0(n) (n)
2400 #define x1(n) (n|01000)
2401
2402 //t_stat ret = i->opcodeX ? DoEISInstruction () : DoBasicInstruction ();
2403 uint32 opcode10 = i->opcode10;
2404
2405 #if defined(PANEL68)
2406 if (insGrp [opcode10])
2407 {
2408 word8 grp = insGrp [opcode10] - 1;
2409 uint row = grp / 36;
2410 uint col = grp % 36;
2411 CPT (cpt3U + row, col); // 3U 0-35, 3L 0-17
2412 }
2413 #endif
2414 bool is_ou = false;
2415 bool is_du = false;
2416 if (cpu.tweaks.l68_mode) { // L68
2417 if (opcodes10[opcode10].reg_use & is_OU) {
2418 is_ou = true;
2419 #if defined(PANEL68)
2420 // XXX Punt on RP FULL, RS FULL
2421 cpu.ou.RB1_FULL = cpu.ou.RP_FULL = cpu.ou.RS_FULL = 1;
2422 cpu.ou.cycle |= ou_GIN;
2423 cpu.ou.opsz = (opcodes10[i->opcode10].reg_use >> 12) & 037;
2424 word10 reguse = (opcodes10[i->opcode10].reg_use) & MASK10;
2425 cpu.ou.reguse = reguse;
2426 if (reguse & ru_A) CPT (cpt5U, 4);
2427 if (reguse & ru_Q) CPT (cpt5U, 5);
2428 if (reguse & ru_X0) CPT (cpt5U, 6);
2429 if (reguse & ru_X1) CPT (cpt5U, 7);
2430 if (reguse & ru_X2) CPT (cpt5U, 8);
2431 if (reguse & ru_X3) CPT (cpt5U, 9);
2432 if (reguse & ru_X4) CPT (cpt5U, 10);
2433 if (reguse & ru_X5) CPT (cpt5U, 11);
2434 if (reguse & ru_X6) CPT (cpt5U, 12);
2435 if (reguse & ru_X7) CPT (cpt5U, 13);
2436 #endif // PANEL68
2437 }
2438 if (opcodes10[opcode10].reg_use & is_DU) {
2439 is_du = true;
2440 PNL (DU_CYCLE_nDUD;) // set not idle
2441 }
2442 }
2443
2444 switch (opcode10)
2445 {
2446 // Operations sorted by frequency of use; should help with caching issues
2447
2448 // Operations counts from booting and build a boot tape from source:
2449 // 1605873148: eppn
2450 // 845109778: sprin
2451 // 702257337: lda
2452 // 637613648: tra
2453 // 555520875: ldq
2454 // 462569862: tze
2455 // 322979813: tnz
2456 // 288200618: stq
2457 // 260400300: cmpq
2458 // 192454329: anaq
2459 // 187283749: sta
2460 // 170691055: lprpn
2461 // 167568868: eaxn
2462 // 166842812: tsxn
2463 // 161542573: stz
2464 // 155129792: epbpn
2465 // 153639462: cmpa
2466 // 144804232: aos
2467 // 133559646: cana
2468 // 127230192: ldaq
2469 // 119988496: tpnz
2470 // 113295654: lxln
2471 // 109645303: staq
2472 // 109417021: tspn
2473 // 108352453: als
2474 // 96267840: rtcd
2475 // 93570029: tmi
2476 // 93161815: stxn
2477 // 90485871: ldi
2478 // 87421892: eraq
2479 // 76632891: ora
2480 // 75372023: adq
2481 // 75036448: tmoz
2482 // 64921645: spbpn
2483 // 63595794: ana
2484 // 62621406: fld
2485 // 57281513: epaq
2486 // 56066122: qls
2487 // 55861962: sti
2488 // 55186331: mlr
2489 // 54388393: call6
2490 // 50000721: lrl
2491 // 49736026: sbq
2492 // 49552594: tpl
2493 // 46097756: cmpb
2494 // 44484993: szn
2495 // 41295856: arl
2496 // 40019677: lrs
2497 // 39386119: sprpn
2498 // 36130580: ldxn
2499 // 32168708: ersa
2500 // 31817270: cmpxn
2501 // 31280696: a9bd
2502 // 29383886: era
2503 // 29282465: lls
2504 // 28714658: mpy
2505 // 28508378: sba
2506 // 24067324: anq
2507 // 23963178: asq
2508 // 23953122: nop
2509 // 23643534: orsa
2510 // 23083282: csl
2511 // 20970795: sbxn
2512 // 20109045: tct
2513 // 18504719: stba
2514 // 18297461: eaq
2515 // 17130040: eaa
2516 // 16035441: cmpc
2517 // 15762874: sxln
2518 // 15109836: lca
2519 // 15013924: adxn
2520 // 14159104: lcq
2521 // 14049597: div
2522 // 14043543: cmpaq
2523 // 13528591: ada
2524 // 12778888: ansa
2525 // 12534711: trc
2526 // 11710149: sbaq
2527 // 11584853: neg
2528 // 11456885: ttn
2529 // 11356918: canq
2530 // 10797383: rccl
2531 // 10743245: asa
2532 // 10100949: ttf
2533 // 9691628: orq
2534 // 9332512: adwp0-3
2535 // 9251904: anxn
2536 // 8076030: ldac
2537 // 8061536: scd
2538 // 7779639: adaq
2539 // 7586713: xec
2540 // 7506406: qrl
2541 // 7442522: adl
2542 // 6535658: stca
2543 // 6359531: adlxn
2544 // 6255134: sbla
2545 // 5936484: stacq
2546 // 5673345: eawp2
2547 // 4671545: tnc
2548 // 4230412: scm
2549 // 4040255: sarn
2550 // 4006015: oraq
2551 // 3918690: adlq
2552 // 3912600: stbq
2553 // 3449053: lcxn
2554 // 3368670: adla
2555 // 3290057: qrs
2556 // 3252438: ars
2557 // 3143543: qlr
2558 // 3098158: stac
2559 // 2838451: mvne
2560 // 2739787: lde
2561 // 2680484: btd
2562 // 2573170: erq
2563 // 2279433: fno
2564 // 2273692: smcm
2565 // 2240713: ersq
2566 // 2173455: sreg
2567 // 2173196: lreg
2568 // 2112784: mrl
2569 // 2030237: mvt
2570 // 2010819: stc2
2571 // 2008675: fmp
2572 // 1981148: llr
2573 // 1915081: mvn
2574 // 1846728: sblxn
2575 // 1820604: fcmp
2576 // 1765253: lcpr
2577 // 1447485: stc1
2578 // 1373184: ansxn
2579 // 1337744: negl
2580 // 1264062: rscr
2581 // 1201563: adwp4-7
2582 // 1198321: rmcm
2583 // 1182814: sznc
2584 // 1171307: sblq
2585 // 1140227: spri
2586 // 1139968: lpri
2587 // 1133946: dvf
2588 // 1059600: scpr
2589 // 958321: stcq
2590 // 837695: tctr
2591 // 820615: s9bd
2592 // 812523: rsw
2593 // 769275: fad
2594 // 729737: orsq
2595 // 651623: scu
2596 // 651612: rcu
2597 // 606518: abd
2598 // 603591: eawp1
2599 // 555935: orsxn
2600 // 525680: scmr
2601 // 467605: spl
2602 // 467405: lpl
2603 // 463927: lra
2604 // 416700: awd
2605 // 384090: dtb
2606 // 383544: cmk
2607 // 382254: fst
2608 // 378820: ssa
2609 // 370308: sra
2610 // 326432: alr
2611 // 321319: ldt
2612 // 319911: ldbr
2613 // 319908: sbar
2614 // 319907: lbar
2615 // 310379: cams
2616 // 303041: eawp7
2617 // 299122: xed
2618 // 294724: easp2
2619 // 270712: sztl
2620 // 252001: dfst
2621 // 241844: ste
2622 // 226970: absa
2623 // 218891: cioc
2624 // 184535: dfld
2625 // 182347: camp
2626 // 174567: ansq
2627 // 169317: rpt
2628 // 124972: erx2
2629 // 121933: fneg
2630 // 114697: cnaaq
2631 // 111728: rpd
2632 // 106892: dis
2633 // 96801: tov
2634 // 92283: fsb
2635 // 86209: erx4
2636 // 80564: eawp3
2637 // 76911: canaq
2638 // 65706: ufa
2639 // 65700: dfcmp
2640 // 64530: fdv
2641 // 48215: ldqc
2642 // 45994: dfad
2643 // 37790: awca
2644 // 27218: asxn
2645 // 23203: eawp5
2646 // 16947: gtb
2647 // 11431: ersxn
2648 // 9527: erx3
2649 // 8888: ssdr
2650 // 8888: ssdp
2651 // 8888: sptr
2652 // 8888: sptp
2653 // 8170: ssq
2654 // 7116: mp3d
2655 // 6969: cmg
2656 // 6878: dv3d
2657 // 5615: eawp6
2658 // 4859: easp1
2659 // 4726: easp3
2660 // 3157: ad2d
2661 // 2807: eawp4
2662 // 2807: easp4
2663 // 2411: cwl
2664 // 1912: teu
2665 // 1912: teo
2666 // 1798: cmpn
2667 // 1625: easp6
2668 // 931: adlaq
2669 // 659: erx1
2670 // 500: ???
2671 // 388: csr
2672 // 215: sb3d
2673 // 176: dfdv
2674 // 93: stcd
2675 // 92: mp2d
2676 // 41: sscr
2677 // 26: dfmp
2678 // 14: ad3d
2679 // 12: mve
2680 // 11: dfsb
2681 // 5: sdbr
2682 // 4: trtf
2683 // 4: orxn
2684 // 3: sb2d
2685 // 2: scdr
2686 // 1: stt
2687 // 1: ret
2688 // 1: drl
2689
2690 case x0 (0350): // epp0
2691 case x1 (0351): // epp1
2692 case x0 (0352): // epp2
2693 case x1 (0353): // epp3
2694 case x0 (0370): // epp4
2695 case x1 (0371): // epp5
2696 case x0 (0372): // epp6
2697 case x1 (0373): // epp7
2698 // For n = 0, 1, ..., or 7 as determined by operation code
2699 // C(TPR.TRR) -> C(PRn.RNR)
2700 // C(TPR.TSR) -> C(PRn.SNR)
2701 // C(TPR.CA) -> C(PRn.WORDNO)
2702 // C(TPR.TBR) -> C(PRn.BITNO)
2703 {
2704 // epp0 0350 101 000
2705 // epp1 1351 101 001
2706 // epp2 0352 101 010
2707 // epp3 1353 101 011
2708 // epp4 0370 111 000
2709 // epp5 1371 111 001
2710 // epp6 0372 111 010
2711 // epp7 1373 111 011
2712 //n = ((opcode10 & 020) ? 4 : 0) + (opcode10 & 03);
2713 uint n = ((opcode10 & 020) >> 2) | (opcode10 & 03);
2714 CPTUR (cptUsePRn + n);
2715 cpu.PR[n].RNR = cpu.TPR.TRR;
2716 cpu.PR[n].SNR = cpu.TPR.TSR;
2717 cpu.PR[n].WORDNO = cpu.TPR.CA;
2718 SET_PR_BITNO (n, cpu.TPR.TBR);
2719 #if defined(TESTING)
2720 HDBGRegPRW (n, "epp");
2721 #endif
2722 }
2723 break;
2724
2725 case x0 (0250): // spri0
2726 case x1 (0251): // spri1
2727 case x0 (0252): // spri2
2728 case x1 (0253): // spri3
2729 case x0 (0650): // spri4
2730 case x1 (0651): // spri5
2731 case x0 (0652): // spri6
2732 case x1 (0653): // spri7
2733
2734 // For n = 0, 1, ..., or 7 as determined by operation code
2735 // 000 -> C(Y-pair)0,2
2736 // C(PRn.SNR) -> C(Y-pair)3,17
2737 // C(PRn.RNR) -> C(Y-pair)18,20
2738 // 00...0 -> C(Y-pair)21,29
2739 // (43)8 -> C(Y-pair)30,35
2740 // C(PRn.WORDNO) -> C(Y-pair)36,53
2741 // 000 -> C(Y-pair)54,56
2742 // C(PRn.BITNO) -> C(Y-pair)57,62
2743 // 00...0 -> C(Y-pair)63,71
2744 {
2745 // spri0 0250 0 010 101 000
2746 // spri1 1251 1 010 101 001
2747 // spri2 0252 0 010 101 010
2748 // spri3 1253 1 010 101 011
2749 // spri4 0650 0 110 101 000
2750 // spri5 1651 1 110 101 001
2751 // spri6 0652 0 110 101 010
2752 // spri7 1653 1 110 101 011
2753 //uint n = ((opcode10 & 0400) ? 4 : 0) + (opcode10 & 03);
2754 uint n = ((opcode10 & 0400) >> 6) | (opcode10 & 03);
2755 CPTUR (cptUsePRn + n);
2756 #if defined(TESTING)
2757 HDBGRegPRR (n, "spri");
2758 #endif
2759 cpu.Ypair[0] = 043;
2760 cpu.Ypair[0] |= ((word36) cpu.PR[n].SNR) << 18;
2761 cpu.Ypair[0] |= ((word36) cpu.PR[n].RNR) << 15;
2762
2763 cpu.Ypair[1] = (word36) cpu.PR[n].WORDNO << 18;
2764 cpu.Ypair[1] |= (word36) GET_PR_BITNO (n) << 9;
2765 }
2766 break;
2767
2768 case x0 (0235): // lda
2769 cpu.rA = cpu.CY;
2770 #if defined(TESTING)
2771 HDBGRegAW ("lda");
2772 #endif
2773 SC_I_ZERO (cpu.rA == 0);
2774 SC_I_NEG (cpu.rA & SIGN36);
2775 break;
2776
2777 case x0 (0710): // tra
2778 // C(TPR.CA) -> C(PPR.IC)
2779 // C(TPR.TSR) -> C(PPR.PSR)
2780 do_caf (cpup);
2781 read_tra_op (cpup);
2782 return CONT_TRA;
2783
2784 case x0 (0236): // ldq
2785 cpu.rQ = cpu.CY;
2786 #if defined(TESTING)
2787 HDBGRegQW ("ldq");
2788 #endif
2789 SC_I_ZERO (cpu.rQ == 0);
2790 SC_I_NEG (cpu.rQ & SIGN36);
2791 break;
2792
2793 case x0 (0600): // tze
2794 // If zero indicator ON then
2795 // C(TPR.CA) -> C(PPR.IC)
2796 // C(TPR.TSR) -> C(PPR.PSR)
2797 // otherwise, no change to C(PPR)
2798 if (TST_I_ZERO)
2799 {
2800 do_caf (cpup);
2801 read_tra_op (cpup);
2802 return CONT_TRA;
2803 }
2804 break;
2805
2806 case x0 (0601): // tnz
2807 // If zero indicator OFF then
2808 // C(TPR.CA) -> C(PPR.IC)
2809 // C(TPR.TSR) -> C(PPR.PSR)
2810 if (!TST_I_ZERO)
2811 {
2812 do_caf (cpup);
2813 read_tra_op (cpup);
2814 return CONT_TRA;
2815 }
2816 break;
2817
2818 case x0 (0756): // stq
2819 cpu.CY = cpu.rQ;
2820 #if defined(TESTING)
2821 HDBGRegQR ("stq");
2822 #endif
2823 break;
2824
2825 case x0 (0116): // cmpq
2826 // C(Q) :: C(Y)
2827 cmp36 (cpup, cpu.rQ, cpu.CY, &cpu.cu.IR);
2828 #if defined(TESTING)
2829 HDBGRegQR ("cmpq");
2830 #endif
2831 break;
2832
2833 case x0 (0377): //< anaq
2834 // C(AQ)i & C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
2835 {
2836 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
2837 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
2838 #if defined(TESTING)
2839 HDBGRegAR ("anaq");
2840 HDBGRegQR ("anaq");
2841 #endif
2842 #if defined(NEED_128)
2843 trAQ = and_128 (trAQ, tmp72);
2844 trAQ = and_128 (trAQ, MASK72);
2845
2846 SC_I_ZERO (iszero_128 (trAQ));
2847 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
2848 #else
2849 trAQ = trAQ & tmp72;
2850 trAQ &= MASK72;
2851
2852 SC_I_ZERO (trAQ == 0);
2853 SC_I_NEG (trAQ & SIGN72);
2854 #endif
2855 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
2856 #if defined(TESTING)
2857 HDBGRegAW ("anaq");
2858 HDBGRegQW ("anaq");
2859 #endif
2860 }
2861 break;
2862
2863 case x0 (0755): // sta
2864 cpu.CY = cpu.rA;
2865 #if defined(TESTING)
2866 HDBGRegAR ("sta");
2867 #endif
2868 break;
2869
2870 // lprpn
2871 case x0 (0760): // lprp0
2872 case x0 (0761): // lprp1
2873 case x0 (0762): // lprp2
2874 case x0 (0763): // lprp3
2875 case x0 (0764): // lprp4
2876 case x0 (0765): // lprp5
2877 case x0 (0766): // lprp6
2878 case x0 (0767): // lprp7
2879 // For n = 0, 1, ..., or 7 as determined by operation code
2880 // C(TPR.TRR) -> C(PRn.RNR)
2881 // If C(Y)0,1 != 11, then
2882 // C(Y)0,5 -> C(PRn.BITNO);
2883 // otherwise,
2884 // generate command fault
2885 // If C(Y)6,17 = 11...1, then 111 -> C(PRn.SNR)0,2
2886 // otherwise,
2887 // 000 -> C(PRn.SNR)0,2
2888 // C(Y)6,17 -> C(PRn.SNR)3,14
2889 // C(Y)18,35 -> C(PRn.WORDNO)
2890 {
2891 uint32 n = opcode10 & 07; // get n
2892 CPTUR (cptUsePRn + n);
2893 cpu.PR[n].RNR = cpu.TPR.TRR;
2894
2895 // [CAC] sprpn says: If C(PRn.SNR) 0,2 are nonzero, and C(PRn.SNR) != 11...1,
2896 // then a store fault (illegal pointer) will occur and C(Y) will not be changed.
2897 // I interpret this has meaning that only the high bits should be set here
2898
2899 if (((cpu.CY >> 34) & 3) != 3)
2900 {
2901 word6 bitno = (cpu.CY >> 30) & 077;
2902 SET_PR_BITNO (n, bitno);
2903 }
2904 else
2905 {
2906 // fim.alm
2907 // command_fault:
2908 // eax7 com assume normal command fault
2909 // ldq bp|mc.scu.port_stat_word check illegal action
2910 // canq scu.ial_mask,dl
2911 // tnz fixindex nonzero, treat as normal case
2912 // ldq bp|scu.even_inst_word check for LPRPxx instruction
2913 // anq =o770400,dl
2914 // cmpq lprp_insts,dl
2915 // tnz fixindex isn't LPRPxx, treat as normal
2916
2917 // ial_mask is checking SCU word 1, field IA: 0 means "no illegal action"
2918
2919 // Therefore the subfault well no illegal action, and
2920 // Multics will peek it the instruction to deduce that it
2921 // is a lprpn fault.
2922 doFault (FAULT_CMD, fst_cmd_lprpn, "lprpn");
2923 }
2924 // The SPRPn instruction stores only the low 12 bits of the 15 bit SNR.
2925 // A special case is made for an SNR of all ones; it is stored as 12 1's.
2926 // The pcode in AL39 handles this awkwardly; I believe this is
2927 // the same, but in a more straightforward manner
2928
2929 // Get the 12 bit operand SNR
2930 word12 oSNR = getbits36_12 (cpu.CY, 6);
2931 // Test for special case
2932 if (oSNR == 07777)
2933 cpu.PR[n].SNR = 077777;
2934 else
2935 cpu.PR[n].SNR = oSNR; // unsigned word will 0-extend.
2936 //C(Y)18,35 -> C(PRn.WORDNO)
2937 cpu.PR[n].WORDNO = GETLO (cpu.CY);
2938
2939 sim_debug (DBG_APPENDING, & cpu_dev,
2940 "lprp%d CY 0%012"PRIo64", PR[n].RNR 0%o, "
2941 "PR[n].BITNO 0%o, PR[n].SNR 0%o, PR[n].WORDNO %o\r\n",
2942 n, cpu.CY, cpu.PR[n].RNR, GET_PR_BITNO (n),
2943 cpu.PR[n].SNR, cpu.PR[n].WORDNO);
2944 #if defined(TESTING)
2945 HDBGRegPRW (n, "lprp");
2946 #endif
2947 }
2948 break;
2949
2950 // eaxn
2951 case x0 (0620): // eax0
2952 case x0 (0621): // eax1
2953 case x0 (0622): // eax2
2954 case x0 (0623): // eax3
2955 case x0 (0624): // eax4
2956 case x0 (0625): // eax5
2957 case x0 (0626): // eax6
2958 case x0 (0627): // eax7
2959 {
2960 uint32 n = opcode10 & 07; // get n
2961 cpu.rX[n] = cpu.TPR.CA;
2962 #if defined(TESTING)
2963 HDBGRegXW (n, "eaxn");
2964 #endif
2965
2966 SC_I_ZERO (cpu.TPR.CA == 0);
2967 SC_I_NEG (cpu.TPR.CA & SIGN18);
2968
2969 }
2970 break;
2971
2972 // tsxn
2973 case x0 (0700): // tsx0
2974 case x0 (0701): // tsx1
2975 case x0 (0702): // tsx2
2976 case x0 (0703): // tsx3
2977 case x0 (0704): // tsx4
2978 case x0 (0705): // tsx5
2979 case x0 (0706): // tsx6
2980 case x0 (0707): // tsx7
2981 // For n = 0, 1, ..., or 7 as determined by operation code
2982 // C(PPR.IC) + 1 -> C(Xn)
2983 // C(TPR.CA) -> C(PPR.IC)
2984 // C(TPR.TSR) -> C(PPR.PSR)
2985 {
2986 // We can't set Xn yet as the CAF may refer to Xn
2987 word18 ret = (cpu.PPR.IC + 1) & MASK18;
2988 do_caf (cpup);
2989 read_tra_op (cpup);
2990 cpu.rX[opcode10 & 07] = ret;
2991 #if defined(TESTING)
2992 HDBGRegXW (opcode10 & 07, "tsxn");
2993 #endif
2994 }
2995 return CONT_TRA;
2996
2997 case x0 (0450): // stz
2998 cpu.CY = 0;
2999 break;
3000
3001 // epbpn
3002 case x1 (0350): // epbp0
3003 case x0 (0351): // epbp1
3004 case x1 (0352): // epbp2
3005 case x0 (0353): // epbp3
3006 case x1 (0370): // epbp4
3007 case x0 (0371): // epbp5
3008 case x1 (0372): // epbp6
3009 case x0 (0373): // epbp7
3010 // For n = 0, 1, ..., or 7 as determined by operation code
3011 // C(TPR.TRR) -> C(PRn.RNR)
3012 // C(TPR.TSR) -> C(PRn.SNR)
3013 // 00...0 -> C(PRn.WORDNO)
3014 // 0000 -> C(PRn.BITNO)
3015 {
3016 // epbp0 1350 101 000
3017 // epbp1 0351 101 000
3018 // epbp2 1352 101 000
3019 // epbp3 0353 101 000
3020 // epbp4 1370 111 000
3021 // epbp4 0371 111 000
3022 // epbp6 1372 111 000
3023 // epbp7 0373 111 000
3024 //n = ((opcode10 & 020) ? 4 : 0) + (opcode10 & 03);
3025 uint n = ((opcode10 & 020) >> 2) | (opcode10 & 03);
3026 CPTUR (cptUsePRn + n);
3027 cpu.PR[n].RNR = cpu.TPR.TRR;
3028 cpu.PR[n].SNR = cpu.TPR.TSR;
3029 cpu.PR[n].WORDNO = 0;
3030 SET_PR_BITNO (n, 0);
3031 #if defined(TESTING)
3032 HDBGRegPRW (n, "epbp");
3033 #endif
3034 }
3035 break;
3036
3037 case x0 (0115): // cmpa
3038 // C(A) :: C(Y)
3039 cmp36 (cpup, cpu.rA, cpu.CY, &cpu.cu.IR);
3040 #if defined(TESTING)
3041 HDBGRegAR ("cmpa");
3042 #endif
3043 break;
3044
3045 case x0 (0054): // aos
3046 {
3047 // C(Y)+1->C(Y)
3048
3049 L68_ (cpu.ou.cycle |= ou_GOS;)
3050 bool ovf;
3051 cpu.CY = Add36b (cpup, cpu.CY, 1, 0, I_ZNOC,
3052 & cpu.cu.IR, & ovf);
3053 overflow (cpup, ovf, true, "aos overflow fault");
3054 }
3055 break;
3056
3057 case x0 (0315): // cana
3058 // C(Z)i = C(A)i & C(Y)i for i = (0, 1, ..., 35)
3059 {
3060 #if defined(TESTING)
3061 HDBGRegAR ("cana");
3062 #endif
3063 word36 trZ = cpu.rA & cpu.CY;
3064 trZ &= MASK36;
3065
3066 SC_I_ZERO (trZ == 0);
3067 SC_I_NEG (trZ & SIGN36);
3068 }
3069 break;
3070
3071 case x0 (0237): // ldaq
3072 cpu.rA = cpu.Ypair[0];
3073 #if defined(TESTING)
3074 HDBGRegAW ("ldaq");
3075 #endif
3076 cpu.rQ = cpu.Ypair[1];
3077 #if defined(TESTING)
3078 HDBGRegQW ("ldaq");
3079 #endif
3080 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0)
3081 SC_I_NEG (cpu.rA & SIGN36);
3082 break;
3083
3084 case x1 (0605): // tpnz
3085 // If negative and zero indicators are OFF then
3086 // C(TPR.CA) -> C(PPR.IC)
3087 // C(TPR.TSR) -> C(PPR.PSR)
3088 if (! (cpu.cu.IR & I_NEG) && ! (cpu.cu.IR & I_ZERO))
3089 {
3090 do_caf (cpup);
3091 read_tra_op (cpup);
3092 return CONT_TRA;
3093 }
3094 break;
3095
3096 // lxln
3097 case x0 (0720): // lxl0
3098 case x0 (0721): // lxl1
3099 case x0 (0722): // lxl2
3100 case x0 (0723): // lxl3
3101 case x0 (0724): // lxl4
3102 case x0 (0725): // lxl5
3103 case x0 (0726): // lxl6
3104 case x0 (0727): // lxl7
3105 {
3106 uint32 n = opcode10 & 07; // get n
3107 cpu.rX[n] = GETLO (cpu.CY);
3108 #if defined(TESTING)
3109 HDBGRegXW (n, "lxln");
3110 #endif
3111 SC_I_ZERO (cpu.rX[n] == 0);
3112 SC_I_NEG (cpu.rX[n] & SIGN18);
3113 }
3114 break;
3115
3116 case x0 (0757): // staq
3117 cpu.Ypair[0] = cpu.rA;
3118 cpu.Ypair[1] = cpu.rQ;
3119 break;
3120
3121 // tspn
3122 case x0 (0270): // tsp0
3123 case x0 (0271): // tsp1
3124 case x0 (0272): // tsp2
3125 case x0 (0273): // tsp3
3126 case x0 (0670): // tsp4
3127 case x0 (0671): // tsp5
3128 case x0 (0672): // tsp6
3129 case x0 (0673): // tsp7
3130 // For n = 0, 1, ..., or 7 as determined by operation code
3131 // C(PPR.PRR) -> C(PRn.RNR)
3132 // C(PPR.PSR) -> C(PRn.SNR)
3133 // C(PPR.IC) + 1 -> C(PRn.WORDNO)
3134 // 00...0 -> C(PRn.BITNO)
3135 // C(TPR.CA) -> C(PPR.IC)
3136 // C(TPR.TSR) -> C(PPR.PSR)
3137 {
3138 #if defined(PANEL68)
3139 uint32 n;
3140 if (opcode10 <= 0273)
3141 n = (opcode10 & 3);
3142 else
3143 n = (opcode10 & 3) + 4;
3144 CPTUR (cptUsePRn + n);
3145 #endif
3146
3147 do_caf (cpup);
3148 // PR[n] is set in read_tra_op().
3149 read_tra_op (cpup);
3150 }
3151 return CONT_TRA;
3152
3153 case x0 (0735): // als
3154 {
3155 #if defined(TESTING)
3156 HDBGRegAR ("als");
3157 #endif
3158 #if BARREL_SHIFTER
3159 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
3160
3161 // Capture the bits shifted through A0
3162 word36 capture;
3163 // If count is > 36, than all of the bits will rotate through A
3164 if (cnt < 36) {
3165 // +1 is A0 plus the bits that will get shifted into A0
3166 capture = cpu.rA & barrelLeftMaskTable[cnt + 1];
3167
3168 // Do the shift
3169 cpu.rA <<= cnt;
3170 cpu.rA &= DMASK; // keep to 36-bits
3171
3172 // If the captured bits are all 0 or all 1, then
3173 // A0 will not have changed during the rotate
3174
3175 } else {
3176 capture = cpu.rA;
3177 cpu.rA = 0;
3178 cnt = 35;
3179 }
3180
3181 if (capture == 0 || capture == (MASK36 & barrelLeftMaskTable[cnt + 1]))
3182 CLR_I_CARRY;
3183 else
3184 SET_I_CARRY;
3185 #else // !BARREL_SHIFTER
3186 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
3187
3188 word36 tmpSign = cpu.rA & SIGN36;
3189 CLR_I_CARRY;
3190
3191 for (uint j = 0; j < tmp36; j ++)
3192 {
3193 cpu.rA <<= 1;
3194 if (tmpSign != (cpu.rA & SIGN36))
3195 SET_I_CARRY;
3196 }
3197 cpu.rA &= DMASK; // keep to 36-bits
3198 #endif // BARREL_SHIFTER
3199 #if defined(TESTING)
3200 HDBGRegAW ("als");
3201 #endif
3202
3203 SC_I_ZERO (cpu.rA == 0);
3204 SC_I_NEG (cpu.rA & SIGN36);
3205 }
3206 break;
3207
3208 case x0 (0610): // rtcd
3209 // If an access violation fault occurs when fetching the SDW for
3210 // the Y-pair, the C(PPR.PSR) and C(PPR.PRR) are not altered.
3211
3212 do_caf (cpup);
3213 Read2RTCDOperandFetch (cpup, cpu.TPR.CA, cpu.Ypair);
3214 // RTCD always ends up in append mode.
3215 set_addr_mode (cpup, APPEND_mode);
3216
3217 return CONT_RET;
3218
3219 case x0 (0604): // tmi
3220 // If negative indicator ON then
3221 // C(TPR.CA) -> C(PPR.IC)
3222 // C(TPR.TSR) -> C(PPR.PSR)
3223 if (TST_I_NEG)
3224 {
3225 do_caf (cpup);
3226 read_tra_op (cpup);
3227 return CONT_TRA;
3228 }
3229 break;
3230
3231 // stxn
3232 case x0 (0740): // stx0
3233 case x0 (0741): // stx1
3234 case x0 (0742): // stx2
3235 case x0 (0743): // stx3
3236 case x0 (0744): // stx4
3237 case x0 (0745): // stx5
3238 case x0 (0746): // stx6
3239 case x0 (0747): // stx7
3240 {
3241 uint32 n = opcode10 & 07; // get n
3242 //SETHI (cpu.CY, cpu.rX[n]);
3243 cpu.CY = ((word36) cpu.rX[n]) << 18;
3244 cpu.zone = 0777777000000;
3245 cpu.useZone = true;
3246 }
3247 break;
3248
3249 case x0 (0634): // ldi
3250 {
3251 CPTUR (cptUseIR);
3252 // C(Y)18,31 -> C(IR)
3253
3254 // Indicators:
3255 // Parity Mask:
3256 // If C(Y)27 = 1, and the processor is in absolute or
3257 // instruction privileged mode, then ON; otherwise OFF.
3258 // This indicator is not affected in the normal or BAR modes.
3259 // Not BAR mode:
3260 // Cannot be changed by the ldi instruction
3261 // MIF:
3262 // If C(Y)30 = 1, and the processor is in absolute or
3263 // instruction privileged mode, then ON; otherwise OFF.
3264 // This indicator is not affected in normal or BAR modes.
3265 // Absolute mode:
3266 // Cannot be changed by the ldi instruction
3267 // All others: If corresponding bit in C(Y) is 1, then ON;
3268 // otherwise, OFF
3269
3270 // upper 14-bits of lower 18-bits
3271
3272 // AL39 ldi says that HEX is ignored, but the mode register
3273 // description says that it isn't
3274 word18 tmp18;
3275 if (cpu.tweaks.l68_mode)
3276 tmp18 = GETLO (cpu.CY) & 0777760; // L68
3277 else
3278 tmp18 = GETLO (cpu.CY) & 0777770; // DPS8M
3279
3280 bool bAbsPriv = is_priv_mode (cpup);
3281
3282 SC_I_ZERO (tmp18 & I_ZERO);
3283 SC_I_NEG (tmp18 & I_NEG);
3284 SC_I_CARRY (tmp18 & I_CARRY);
3285 SC_I_OFLOW (tmp18 & I_OFLOW);
3286 SC_I_EOFL (tmp18 & I_EOFL);
3287 SC_I_EUFL (tmp18 & I_EUFL);
3288 SC_I_OMASK (tmp18 & I_OMASK);
3289 SC_I_TALLY (tmp18 & I_TALLY);
3290 SC_I_PERR (tmp18 & I_PERR);
3291 // I_PMASK handled below
3292 // LDI cannot change I_NBAR
3293 SC_I_TRUNC (tmp18 & I_TRUNC);
3294 // I_MIF handled below
3295 // LDI cannot change I_ABS
3296 DPS8M_ (SC_I_HEX (tmp18 & I_HEX);)
3297
3298 if (bAbsPriv)
3299 {
3300 SC_I_PMASK (tmp18 & I_PMASK);
3301 SC_I_MIF (tmp18 & I_MIF);
3302 }
3303 else
3304 {
3305 CLR_I_PMASK;
3306 CLR_I_MIF;
3307 }
3308 }
3309 break;
3310
3311 case x0 (0677): // eraq
3312 // C(AQ)i XOR C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
3313 {
3314 #if defined(TESTING)
3315 HDBGRegAR ("eraq");
3316 HDBGRegQR ("eraq");
3317 #endif
3318 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
3319 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
3320 #if defined(NEED_128)
3321 trAQ = xor_128 (trAQ, tmp72);
3322 trAQ = and_128 (trAQ, MASK72);
3323
3324 SC_I_ZERO (iszero_128 (trAQ));
3325 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
3326 #else
3327 trAQ = trAQ ^ tmp72;
3328 trAQ &= MASK72;
3329
3330 SC_I_ZERO (trAQ == 0);
3331 SC_I_NEG (trAQ & SIGN72);
3332 #endif
3333
3334 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
3335 #if defined(TESTING)
3336 HDBGRegAW ("eraq");
3337 HDBGRegQW ("eraq");
3338 #endif
3339 }
3340 break;
3341
3342 case x0 (0275): // ora
3343 // C(A)i | C(Y)i -> C(A)i for i = (0, 1, ..., 35)
3344 #if defined(TESTING)
3345 HDBGRegAR ("ora");
3346 #endif
3347 cpu.rA = cpu.rA | cpu.CY;
3348 cpu.rA &= DMASK;
3349 #if defined(TESTING)
3350 HDBGRegAW ("ora");
3351 #endif
3352
3353 SC_I_ZERO (cpu.rA == 0);
3354 SC_I_NEG (cpu.rA & SIGN36);
3355 break;
3356
3357 case x0 (0076): // adq
3358 {
3359 L68_ (cpu.ou.cycle |= ou_GOS;)
3360 bool ovf;
3361 #if defined(TESTING)
3362 HDBGRegQR ("adq");
3363 #endif
3364 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNOC,
3365 & cpu.cu.IR, & ovf);
3366 #if defined(TESTING)
3367 HDBGRegQW ("adq");
3368 #endif
3369 overflow (cpup, ovf, false, "adq overflow fault");
3370 }
3371 break;
3372
3373 case x1 (0604): // tmoz
3374 // If negative or zero indicator ON then
3375 // C(TPR.CA) -> C(PPR.IC)
3376 // C(TPR.TSR) -> C(PPR.PSR)
3377 if (cpu.cu.IR & (I_NEG | I_ZERO))
3378 {
3379 do_caf (cpup);
3380 read_tra_op (cpup);
3381 return CONT_TRA;
3382 }
3383 break;
3384
3385 case x1 (0250): // spbp0
3386 case x0 (0251): // spbp1
3387 case x1 (0252): // spbp2
3388 case x0 (0253): // spbp3
3389 case x1 (0650): // spbp4
3390 case x0 (0651): // spbp5
3391 case x1 (0652): // spbp6
3392 case x0 (0653): // spbp7
3393 // For n = 0, 1, ..., or 7 as determined by operation code
3394 // C(PRn.SNR) -> C(Y-pair)3,17
3395 // C(PRn.RNR) -> C(Y-pair)18,20
3396 // 000 -> C(Y-pair)0,2
3397 // 00...0 -> C(Y-pair)21,29
3398 // (43)8 -> C(Y-pair)30,35
3399 // 00...0 -> C(Y-pair)36,71
3400 {
3401 // spbp0 1250 010 101 000
3402 // spbp1 0251 010 101 001
3403 // spbp2 1252 010 101 010
3404 // spbp3 0253 010 101 011
3405 // spbp4 1650 110 101 000
3406 // spbp5 0651 110 101 001
3407 // spbp6 1652 110 101 010
3408 // spbp8 0653 110 101 011
3409 uint n = ((opcode10 & 0400) >> 6) | (opcode10 & 03);
3410 CPTUR (cptUsePRn + n);
3411 cpu.Ypair[0] = 043;
3412 cpu.Ypair[0] |= ((word36) cpu.PR[n].SNR) << 18;
3413 cpu.Ypair[0] |= ((word36) cpu.PR[n].RNR) << 15;
3414 cpu.Ypair[1] = 0;
3415 }
3416 break;
3417
3418 case x0 (0375): // ana
3419 // C(A)i & C(Y)i -> C(A)i for i = (0, 1, ..., 35)
3420 #if defined(TESTING)
3421 HDBGRegAR ("ana");
3422 #endif
3423 cpu.rA = cpu.rA & cpu.CY;
3424 cpu.rA &= DMASK;
3425 #if defined(TESTING)
3426 HDBGRegAW ("ana");
3427 #endif
3428 SC_I_ZERO (cpu.rA == 0);
3429 SC_I_NEG (cpu.rA & SIGN36);
3430 break;
3431
3432 case x0 (0431): // fld
3433 // C(Y)0,7 -> C(E)
3434 // C(Y)8,35 -> C(AQ)0,27
3435 // 00...0 -> C(AQ)30,71
3436 // Zero: If C(AQ) = 0, then ON; otherwise OFF
3437 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
3438
3439 CPTUR (cptUseE);
3440 cpu.CY &= DMASK;
3441 cpu.rE = (cpu.CY >> 28) & 0377;
3442 cpu.rA = (cpu.CY & FLOAT36MASK) << 8;
3443 #if defined(TESTING)
3444 HDBGRegAW ("fld");
3445 #endif
3446 cpu.rQ = 0;
3447 #if defined(TESTING)
3448 HDBGRegQW ("fld");
3449 #endif
3450
3451 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3452 SC_I_NEG (cpu.rA & SIGN36);
3453 break;
3454
3455 case x0 (0213): // epaq
3456 // 000 -> C(AQ)0,2
3457 // C(TPR.TSR) -> C(AQ)3,17
3458 // 00...0 -> C(AQ)18,32
3459 // C(TPR.TRR) -> C(AQ)33,35
3460
3461 // C(TPR.CA) -> C(AQ)36,53
3462 // 00...0 -> C(AQ)54,65
3463 // C(TPR.TBR) -> C(AQ)66,71
3464
3465 cpu.rA = cpu.TPR.TRR & MASK3;
3466 cpu.rA |= (word36) (cpu.TPR.TSR & MASK15) << 18;
3467 #if defined(TESTING)
3468 HDBGRegAW ("epaq");
3469 #endif
3470
3471 cpu.rQ = cpu.TPR.TBR & MASK6;
3472 cpu.rQ |= (word36) (cpu.TPR.CA & MASK18) << 18;
3473 #if defined(TESTING)
3474 HDBGRegQW ("epaq");
3475 #endif
3476
3477 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3478
3479 break;
3480
3481 case x0 (0736): // qls
3482 // Shift C(Q) left the number of positions given in
3483 // C(TPR.CA)11,17; fill vacated positions with zeros.
3484 {
3485 #if defined(TESTING)
3486 HDBGRegQR ("qls");
3487 #endif
3488 #if BARREL_SHIFTER
3489 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
3490
3491 // Capture the bits shifted through Q0
3492 word36 capture;
3493 // If count is > 36, than all of the bits will rotate through Q
3494 if (cnt < 36) {
3495 // +1 is Q0 plus the bits that will get shifted into Q0
3496 capture = cpu.rQ & barrelLeftMaskTable[cnt + 1];
3497
3498 // Do the shift
3499 cpu.rQ <<= cnt;
3500 cpu.rQ &= DMASK; // keep to 36-bits
3501
3502 // If the captured bits are all 0 or all 1, then
3503 // Q0 will not have changed during the rotate
3504
3505 } else {
3506 capture = cpu.rQ;
3507 cpu.rQ = 0;
3508 }
3509
3510 if (capture == 0 || capture == (MASK36 & barrelLeftMaskTable[cnt + 1]))
3511 CLR_I_CARRY;
3512 else
3513 SET_I_CARRY;
3514 #else // !BARREL_SHIFTER
3515 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
3516 word36 tmpSign = cpu.rQ & SIGN36;
3517 CLR_I_CARRY;
3518
3519 for (uint j = 0; j < tmp36; j ++)
3520 {
3521 cpu.rQ <<= 1;
3522 if (tmpSign != (cpu.rQ & SIGN36))
3523 SET_I_CARRY;
3524 }
3525 cpu.rQ &= DMASK; // keep to 36-bits
3526 #endif // BARREL_SHIFTER
3527 #if defined(TESTING)
3528 HDBGRegQW ("qls");
3529 #endif
3530
3531 SC_I_ZERO (cpu.rQ == 0);
3532 SC_I_NEG (cpu.rQ & SIGN36);
3533 }
3534 break;
3535
3536 case x0 (0754): // sti
3537
3538 // C(IR) -> C(Y)18,31
3539 // 00...0 -> C(Y)32,35
3540
3541 // The contents of the indicator register after address
3542 // preparation are stored in C(Y)18,31 C(Y)18,31 reflects the
3543 // state of the tally runout indicator prior to address
3544 // preparation. The relation between C(Y)18,31 and the indicators
3545 // is given in Table 4-5.
3546
3547 CPTUR (cptUseIR);
3548 // AL39 sti says that HEX is ignored, but the mode register
3549 // description says that it isn't
3550
3551 //SETLO (cpu.CY, (cpu.cu.IR & 0000000777770LL));
3552 DPS8M_ (cpu.CY = cpu.cu.IR & 0000000777770LL; )
3553 //SETLO (cpu.CY, (cpu.cu.IR & 0000000777760LL));
3554 L68_ (cpu.CY = cpu.cu.IR & 0000000777760LL;)
3555
3556 if (cpu.switches.procMode == procModeGCOS)
3557 cpu.CY = cpu.cu.IR & 0000000777600LL;
3558 cpu.zone = 0000000777777;
3559 cpu.useZone = true;
3560 SCF (i->stiTally, cpu.CY, I_TALLY);
3561 break;
3562
3563 /// FIXED-POINT ARITHMETIC INSTRUCTIONS
3564
3565 /// Fixed-Point Data Movement Load
3566
3567 case x0 (0635): // eaa
3568 cpu.rA = 0;
3569 SETHI (cpu.rA, cpu.TPR.CA);
3570 #if defined(TESTING)
3571 HDBGRegAW ("eea");
3572 #endif
3573 SC_I_ZERO (cpu.TPR.CA == 0);
3574 SC_I_NEG (cpu.TPR.CA & SIGN18);
3575
3576 break;
3577
3578 case x0 (0636): // eaq
3579 cpu.rQ = 0;
3580 SETHI (cpu.rQ, cpu.TPR.CA);
3581 #if defined(TESTING)
3582 HDBGRegQW ("eaq");
3583 #endif
3584
3585 SC_I_ZERO (cpu.TPR.CA == 0);
3586 SC_I_NEG (cpu.TPR.CA & SIGN18);
3587
3588 break;
3589
3590 // Optimized to the top of the loop
3591 // case x0 (0620): // eax0
3592 // case x0 (0621): // eax1
3593 // case x0 (0622): // eax2
3594 // case x0 (0623): // eax3
3595 // case x0 (0624): // eax4
3596 // case x0 (0625): // eax5
3597 // case x0 (0626): // eax6
3598 // case x0 (0627): // eax7
3599
3600 case x0 (0335): // lca
3601 {
3602 bool ovf;
3603 cpu.rA = compl36 (cpup, cpu.CY, & cpu.cu.IR, & ovf);
3604 #if defined(TESTING)
3605 HDBGRegAW ("lca");
3606 #endif
3607 overflow (cpup, ovf, false, "lca overflow fault");
3608 }
3609 break;
3610
3611 case x0 (0336): // lcq
3612 {
3613 bool ovf;
3614 cpu.rQ = compl36 (cpup, cpu.CY, & cpu.cu.IR, & ovf);
3615 #if defined(TESTING)
3616 HDBGRegQW ("lcq");
3617 #endif
3618 overflow (cpup, ovf, false, "lcq overflow fault");
3619 }
3620 break;
3621
3622 // lcxn
3623 case x0 (0320): // lcx0
3624 case x0 (0321): // lcx1
3625 case x0 (0322): // lcx2
3626 case x0 (0323): // lcx3
3627 case x0 (0324): // lcx4
3628 case x0 (0325): // lcx5
3629 case x0 (0326): // lcx6
3630 case x0 (0327): // lcx7
3631 {
3632 bool ovf;
3633 uint32 n = opcode10 & 07; // get n
3634 cpu.rX[n] = compl18 (cpup, GETHI (cpu.CY), & cpu.cu.IR, & ovf);
3635 #if defined(TESTING)
3636 HDBGRegXW (n, "lcxn");
3637 #endif
3638 overflow (cpup, ovf, false, "lcxn overflow fault");
3639 }
3640 break;
3641
3642 case x0 (0337): // lcaq
3643 {
3644 // The lcaq instruction changes the number to its negative while
3645 // moving it from Y-pair to AQ. The operation is executed by
3646 // forming the twos complement of the string of 72 bits. In twos
3647 // complement arithmetic, the value 0 is its own negative. An
3648 // overflow condition exists if C(Y-pair) = -2**71.
3649
3650 if (cpu.Ypair[0] == 0400000000000LL && cpu.Ypair[1] == 0)
3651 {
3652 cpu.rA = cpu.Ypair[0];
3653 #if defined(TESTING)
3654 HDBGRegAW ("lcaq");
3655 #endif
3656 cpu.rQ = cpu.Ypair[1];
3657 #if defined(TESTING)
3658 HDBGRegQW ("lcaq");
3659 #endif
3660 SET_I_NEG;
3661 CLR_I_ZERO;
3662 overflow (cpup, true, false, "lcaq overflow fault");
3663 }
3664 else if (cpu.Ypair[0] == 0 && cpu.Ypair[1] == 0)
3665 {
3666 cpu.rA = 0;
3667 #if defined(TESTING)
3668 HDBGRegAW ("lcaq");
3669 #endif
3670 cpu.rQ = 0;
3671 #if defined(TESTING)
3672 HDBGRegQW ("lcaq");
3673 #endif
3674
3675 SET_I_ZERO;
3676 CLR_I_NEG;
3677 }
3678 else
3679 {
3680 word72 tmp72 = convert_to_word72 (cpu.Ypair[0], cpu.Ypair[1]);
3681 #if defined(NEED_128)
3682 tmp72 = negate_128 (tmp72);
3683 #else
3684 tmp72 = ~tmp72 + 1;
3685 #endif
3686 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
3687 #if defined(TESTING)
3688 HDBGRegAW ("lcaq");
3689 HDBGRegQW ("lcaq");
3690 #endif
3691
3692 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3693 SC_I_NEG (cpu.rA & SIGN36);
3694 }
3695 }
3696 break;
3697
3698 // Optimized to the top of the loop
3699 // case x0 (0235): // lda
3700
3701 case x0 (0034): // ldac
3702 cpu.rA = cpu.CY;
3703 #if defined(TESTING)
3704 HDBGRegAW ("ldac");
3705 #endif
3706 SC_I_ZERO (cpu.rA == 0);
3707 SC_I_NEG (cpu.rA & SIGN36);
3708 cpu.CY = 0;
3709 break;
3710
3711 // Optimized to the top of the loop
3712 // case x0 (0237): // ldaq
3713
3714 // Optimized to the top of the loop
3715 // case x0 (0634): // ldi
3716
3717 // Optimized to the top of the loop
3718 // case x0 (0236): // ldq
3719
3720 case x0 (0032): // ldqc
3721 cpu.rQ = cpu.CY;
3722 #if defined(TESTING)
3723 HDBGRegQW ("ldqc");
3724 #endif
3725 SC_I_ZERO (cpu.rQ == 0);
3726 SC_I_NEG (cpu.rQ & SIGN36);
3727 cpu.CY = 0;
3728 break;
3729
3730 // ldxn
3731 case x0 (0220): // ldx0
3732 case x0 (0221): // ldx1
3733 case x0 (0222): // ldx2
3734 case x0 (0223): // ldx3
3735 case x0 (0224): // ldx4
3736 case x0 (0225): // ldx5
3737 case x0 (0226): // ldx6
3738 case x0 (0227): // ldx7
3739 {
3740 uint32 n = opcode10 & 07; // get n
3741 cpu.rX[n] = GETHI (cpu.CY);
3742 #if defined(TESTING)
3743 HDBGRegXW (n, "ldxn");
3744 #endif
3745 SC_I_ZERO (cpu.rX[n] == 0);
3746 SC_I_NEG (cpu.rX[n] & SIGN18);
3747 }
3748 break;
3749
3750 case x0 (0073): // lreg
3751 CPTUR (cptUseE);
3752 L68_ (cpu.ou.cycle |= ou_GOS;)
3753 L68_ (cpu.ou.eac = 0;)
3754 cpu.rX[0] = GETHI (cpu.Yblock8[0]);
3755 #if defined(TESTING)
3756 HDBGRegXW (0, "lreg");
3757 #endif
3758 cpu.rX[1] = GETLO (cpu.Yblock8[0]);
3759 #if defined(TESTING)
3760 HDBGRegXW (1, "lreg");
3761 #endif
3762 L68_ (cpu.ou.eac ++;)
3763 cpu.rX[2] = GETHI (cpu.Yblock8[1]);
3764 #if defined(TESTING)
3765 HDBGRegXW (2, "lreg");
3766 #endif
3767 cpu.rX[3] = GETLO (cpu.Yblock8[1]);
3768 #if defined(TESTING)
3769 HDBGRegXW (3, "lreg");
3770 #endif
3771 L68_ (cpu.ou.eac ++;)
3772 cpu.rX[4] = GETHI (cpu.Yblock8[2]);
3773 #if defined(TESTING)
3774 HDBGRegXW (4, "lreg");
3775 #endif
3776 cpu.rX[5] = GETLO (cpu.Yblock8[2]);
3777 #if defined(TESTING)
3778 HDBGRegXW (5, "lreg");
3779 #endif
3780 L68_ (cpu.ou.eac ++;)
3781 cpu.rX[6] = GETHI (cpu.Yblock8[3]);
3782 #if defined(TESTING)
3783 HDBGRegXW (6, "lreg");
3784 #endif
3785 cpu.rX[7] = GETLO (cpu.Yblock8[3]);
3786 #if defined(TESTING)
3787 HDBGRegXW (7, "lreg");
3788 #endif
3789 L68_ (cpu.ou.eac ++;)
3790 cpu.rA = cpu.Yblock8[4];
3791 #if defined(TESTING)
3792 HDBGRegAW ("lreg");
3793 #endif
3794 cpu.rQ = cpu.Yblock8[5];
3795 #if defined(TESTING)
3796 HDBGRegQW ("lreg");
3797 #endif
3798 cpu.rE = (GETHI (cpu.Yblock8[6]) >> 10) & 0377; // need checking
3799 break;
3800
3801 // Optimized to the top of the loop
3802 // // lxln
3803 // case x0 (0720): // lxl0
3804 // case x0 (0721): // lxl1
3805 // case x0 (0722): // lxl2
3806 // case x0 (0723): // lxl3
3807 // case x0 (0724): // lxl4
3808 // case x0 (0725): // lxl5
3809 // case x0 (0726): // lxl6
3810 // case x0 (0727): // lxl7
3811
3812 /// Fixed-Point Data Movement Store
3813
3814 case x0 (0753): // sreg
3815 CPTUR (cptUseE);
3816 CPTUR (cptUseRALR);
3817 // clear block (changed to memset() per DJ request)
3818 //(void)memset (cpu.Yblock8, 0, sizeof (cpu.Yblock8));
3819 L68_ (cpu.ou.cycle |= ou_GOS;)
3820 L68_ (cpu.ou.eac = 0;)
3821 SETHI (cpu.Yblock8[0], cpu.rX[0]);
3822 SETLO (cpu.Yblock8[0], cpu.rX[1]);
3823 L68_ (cpu.ou.eac ++;)
3824 SETHI (cpu.Yblock8[1], cpu.rX[2]);
3825 SETLO (cpu.Yblock8[1], cpu.rX[3]);
3826 L68_ (cpu.ou.eac ++;)
3827 SETHI (cpu.Yblock8[2], cpu.rX[4]);
3828 SETLO (cpu.Yblock8[2], cpu.rX[5]);
3829 L68_ (cpu.ou.eac ++;)
3830 SETHI (cpu.Yblock8[3], cpu.rX[6]);
3831 SETLO (cpu.Yblock8[3], cpu.rX[7]);
3832 L68_ (cpu.ou.eac ++;)
3833 cpu.Yblock8[4] = cpu.rA;
3834 cpu.Yblock8[5] = cpu.rQ;
3835 cpu.Yblock8[6] = ((word36)(cpu.rE & MASK8)) << 28;
3836 if (cpu.tweaks.isolts_mode)
3837 cpu.Yblock8[7] = (((-- cpu.shadowTR) & MASK27) << 9) | (cpu.rRALR & 07);
3838 else
3839 cpu.Yblock8[7] = ((cpu.rTR & MASK27) << 9) | (cpu.rRALR & 07);
3840 #if defined(TESTING)
3841 HDBGRegXR (0, "sreg");
3842 HDBGRegXR (1, "sreg");
3843 HDBGRegXR (2, "sreg");
3844 HDBGRegXR (3, "sreg");
3845 HDBGRegXR (4, "sreg");
3846 HDBGRegXR (5, "sreg");
3847 HDBGRegXR (6, "sreg");
3848 HDBGRegXR (7, "sreg");
3849 HDBGRegAR ("sreg");
3850 HDBGRegQR ("sreg");
3851 #endif
3852 break;
3853
3854 // Optimized to the top of the loop
3855 // case x0 (0755): // sta
3856
3857 case x0 (0354): // stac
3858 if (cpu.CY == 0)
3859 {
3860 #if defined(TESTING)
3861 HDBGRegAR ("stac");
3862 #endif
3863 SET_I_ZERO;
3864 cpu.CY = cpu.rA;
3865 }
3866 else
3867 CLR_I_ZERO;
3868 break;
3869
3870 case x0 (0654): // stacq
3871 #if defined(TESTING)
3872 HDBGRegQR ("stacq");
3873 #endif
3874 if (cpu.CY == cpu.rQ)
3875 {
3876 #if defined(TESTING)
3877 HDBGRegAR ("stacq");
3878 #endif
3879 cpu.CY = cpu.rA;
3880 SET_I_ZERO;
3881 }
3882 else
3883 CLR_I_ZERO;
3884 break;
3885
3886 // Optimized to the top of the loop
3887 // case x0 (0757): // staq
3888
3889 case x0 (0551): // stba
3890 // 9-bit bytes of C(A) -> corresponding bytes of C(Y), the byte
3891 // positions affected being specified in the TAG field.
3892 // copyBytes ((i->tag >> 2) & 0xf, cpu.rA, &cpu.CY);
3893 #if defined(TESTING)
3894 HDBGRegAR ("stba");
3895 #endif
3896 cpu.CY = cpu.rA;
3897 cpu.zone =
3898 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
3899 ((i->tag & 040) ? 0777000000000u : 0) |
3900 ((i->tag & 020) ? 0000777000000u : 0) |
3901 ((i->tag & 010) ? 0000000777000u : 0) |
3902 ((i->tag & 004) ? 0000000000777u : 0);
3903 cpu.useZone = true;
3904 cpu.ou.crflag = true;
3905 break;
3906
3907 case x0 (0552): // stbq
3908 // 9-bit bytes of C(Q) -> corresponding bytes of C(Y), the byte
3909 // positions affected being specified in the TAG field.
3910 // copyBytes ((i->tag >> 2) & 0xf, cpu.rQ, &cpu.CY);
3911 #if defined(TESTING)
3912 HDBGRegQR ("stbq");
3913 #endif
3914 cpu.CY = cpu.rQ;
3915 cpu.zone =
3916 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
3917 ((i->tag & 040) ? 0777000000000u : 0) |
3918 ((i->tag & 020) ? 0000777000000u : 0) |
3919 ((i->tag & 010) ? 0000000777000u : 0) |
3920 ((i->tag & 004) ? 0000000000777u : 0);
3921 cpu.useZone = true;
3922 cpu.ou.crflag = true;
3923 break;
3924
3925 case x0 (0554): // stc1
3926 // "C(Y)25 reflects the state of the tally runout indicator
3927 // prior to modification.
3928 SETHI (cpu.CY, (cpu.PPR.IC + 1) & MASK18);
3929 // AL39 stc1 says that HEX is ignored, but the mode register
3930 // description says that it isn't
3931 DPS8M_ (SETLO (cpu.CY, cpu.cu.IR & 0777770);)
3932 L68_ (SETLO (cpu.CY, cpu.cu.IR & 0777760);)
3933 SCF (i->stiTally, cpu.CY, I_TALLY);
3934 break;
3935
3936 case x0 (0750): // stc2
3937 // AL-39 doesn't specify if the low half is set to zero,
3938 // set to IR, or left unchanged
3939 // RJ78 specifies unchanged
3940 // SETHI (cpu.CY, (cpu.PPR.IC + 2) & MASK18);
3941 cpu.CY = ((word36) ((cpu.PPR.IC + 2) & MASK18)) << 18;
3942 cpu.zone = 0777777000000;
3943 cpu.useZone = true;
3944 break;
3945
3946 case x0 (0751): // stca
3947 // Characters of C(A) -> corresponding characters of C(Y),
3948 // the character positions affected being specified in the TAG
3949 // field.
3950 // copyChars (i->tag, cpu.rA, &cpu.CY);
3951 #if defined(TESTING)
3952 HDBGRegAR ("stca");
3953 #endif
3954 cpu.CY = cpu.rA;
3955 cpu.zone =
3956 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
3957 ((i->tag & 040) ? 0770000000000u : 0) |
3958 ((i->tag & 020) ? 0007700000000u : 0) |
3959 ((i->tag & 010) ? 0000077000000u : 0) |
3960 ((i->tag & 004) ? 0000000770000u : 0) |
3961 ((i->tag & 002) ? 0000000007700u : 0) |
3962 ((i->tag & 001) ? 0000000000077u : 0);
3963 cpu.useZone = true;
3964 cpu.ou.crflag = true;
3965 break;
3966
3967 case x0 (0752): // stcq
3968 // Characters of C(Q) -> corresponding characters of C(Y), the
3969 // character positions affected being specified in the TAG field.
3970 // copyChars (i->tag, cpu.rQ, &cpu.CY);
3971 #if defined(TESTING)
3972 HDBGRegQR ("stcq");
3973 #endif
3974 cpu.CY = cpu.rQ;
3975 cpu.zone =
3976 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
3977 ((i->tag & 040) ? 0770000000000u : 0) |
3978 ((i->tag & 020) ? 0007700000000u : 0) |
3979 ((i->tag & 010) ? 0000077000000u : 0) |
3980 ((i->tag & 004) ? 0000000770000u : 0) |
3981 ((i->tag & 002) ? 0000000007700u : 0) |
3982 ((i->tag & 001) ? 0000000000077u : 0);
3983 cpu.useZone = true;
3984 cpu.ou.crflag = true;
3985 break;
3986
3987 case x0 (0357): //< stcd
3988 // C(PPR) -> C(Y-pair) as follows:
3989
3990 // 000 -> C(Y-pair)0,2
3991 // C(PPR.PSR) -> C(Y-pair)3,17
3992 // C(PPR.PRR) -> C(Y-pair)18,20
3993 // 00...0 -> C(Y-pair)21,29
3994 // (43)8 -> C(Y-pair)30,35
3995
3996 // C(PPR.IC)+2 -> C(Y-pair)36,53
3997 // 00...0 -> C(Y-pair)54,71
3998
3999 // ISOLTS 880 5a has an STCD in an XED in a fault pair;
4000 // it reports the wrong ring number. This was fixed by
4001 // emulating the SCU instruction (different behavior in fault
4002 // pair).
4003
4004 if (cpu.cycle == EXEC_cycle)
4005 {
4006 cpu.Ypair[0] = 0;
4007 putbits36_15 (& cpu.Ypair[0], 3, cpu.PPR.PSR);
4008 putbits36_3 (& cpu.Ypair[0], 18, cpu.PPR.PRR);
4009 putbits36_6 (& cpu.Ypair[0], 30, 043);
4010
4011 cpu.Ypair[1] = 0;
4012 putbits36_18 (& cpu.Ypair[1], 0, cpu.PPR.IC + 2);
4013 }
4014 else
4015 {
4016 cpu.Ypair[0] = 0;
4017 putbits36_15 (& cpu.Ypair[0], 3, cpu.cu_data.PSR);
4018 putbits36_3 (& cpu.Ypair[0], 18, cpu.cu_data.PRR);
4019 //putbits36_6 (& cpu.Ypair[0], 30, 043);
4020
4021 cpu.Ypair[1] = 0;
4022 putbits36_18 (& cpu.Ypair[1], 0, cpu.cu_data.IC + 2);
4023 }
4024 break;
4025
4026 // Optimized to the top of the loop
4027 // case x0 (0754): // sti
4028
4029 // Optimized to the top of the loop
4030 // case x0 (0756): // stq
4031
4032 case x0 (0454): // stt
4033 CPTUR (cptUseTR);
4034 if (cpu.tweaks.isolts_mode)
4035 //cpu.CY = ((-- cpu.shadowTR) & MASK27) << 9;
4036 // ubsan
4037 cpu.CY = (((uint) (((int) cpu.shadowTR) - 1)) & MASK27) << 9;
4038 else
4039 cpu.CY = (cpu.rTR & MASK27) << 9;
4040 break;
4041
4042 // Optimized to the top of the loop
4043 // // stxn
4044 // case x0 (0740): // stx0
4045 // case x0 (0741): // stx1
4046 // case x0 (0742): // stx2
4047 // case x0 (0743): // stx3
4048 // case x0 (0744): // stx4
4049 // case x0 (0745): // stx5
4050 // case x0 (0746): // stx6
4051 // case x0 (0747): // stx7
4052
4053 // Optimized to the top of the loop
4054 // case x0 (0450): // stz
4055
4056 // sxln
4057 case x0 (0440): // sxl0
4058 case x0 (0441): // sxl1
4059 case x0 (0442): // sxl2
4060 case x0 (0443): // sxl3
4061 case x0 (0444): // sxl4
4062 case x0 (0445): // sxl5
4063 case x0 (0446): // sxl6
4064 case x0 (0447): // sxl7
4065 //SETLO (cpu.CY, cpu.rX[opcode10 & 07]);
4066 cpu.CY = cpu.rX[opcode10 & 07];
4067 cpu.zone = 0000000777777;
4068 cpu.useZone = true;
4069 break;
4070
4071 /// Fixed-Point Data Movement Shift
4072
4073 case x0 (0775): // alr
4074 {
4075 #if defined(TESTING)
4076 HDBGRegAR ("alr");
4077 #endif
4078 #if BARREL_SHIFTER
4079 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4080 cnt %= 36;
4081
4082 word36 highA = cpu.rA & barrelLeftMaskTable[cnt];
4083 cpu.rA <<= cnt;
4084 highA >>= (36 - cnt);
4085 highA &= barrelRightMaskTable[cnt];
4086 cpu.rA |= highA;
4087 cpu.rA &= DMASK; // keep to 36-bits
4088 #else // !BARREL_SHIFTER
4089 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4090 for (uint j = 0 ; j < tmp36 ; j++)
4091 {
4092 bool a0 = cpu.rA & SIGN36; // A0
4093 cpu.rA <<= 1; // shift left 1
4094 if (a0) // rotate A0 -> A35
4095 cpu.rA |= 1;
4096 }
4097 cpu.rA &= DMASK; // keep to 36-bits
4098 #endif // BARREL_SHIFTER
4099 #if defined(TESTING)
4100 HDBGRegAW ("alr");
4101 #endif
4102
4103 SC_I_ZERO (cpu.rA == 0);
4104 SC_I_NEG (cpu.rA & SIGN36);
4105 }
4106 break;
4107
4108 // Optimized to the top of the loop
4109 // case x0 (0735): // als
4110
4111 case x0 (0771): // arl
4112 // Shift C(A) right the number of positions given in
4113 // C(TPR.CA)11,17; filling vacated positions with zeros.
4114 {
4115 #if defined(TESTING)
4116 HDBGRegAR ("arl");
4117 #endif
4118 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4119 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4120
4121 cpu.rA >>= tmp36;
4122 cpu.rA &= DMASK; // keep to 36-bits
4123 #if defined(TESTING)
4124 HDBGRegAW ("arl");
4125 #endif
4126
4127 SC_I_ZERO (cpu.rA == 0);
4128 SC_I_NEG (cpu.rA & SIGN36);
4129 }
4130 break;
4131
4132 case x0 (0731): // ars
4133 {
4134 // Shift C(A) right the number of positions given in
4135 // C(TPR.CA)11,17; filling vacated positions with initial C(A)0.
4136
4137 #if defined(TESTING)
4138 HDBGRegAR ("ars");
4139 #endif
4140 #if BARREL_SHIFTER
4141 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4142 bool A0 = (cpu.rA & SIGN36) != 0;
4143
4144 if (cnt >= 36) {
4145 cpu.rA = A0 ? MASK36 : 0;
4146 } else {
4147 // Shift rA
4148 cpu.rA >>= cnt;
4149 // Mask out the high bits
4150 if (A0) {
4151 cpu.rA |= barrelLeftMaskTable[cnt];
4152 } else {
4153 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4154 }
4155 }
4156 cpu.rA &= DMASK; // keep to 36-bits
4157 #else // !BARREL_SHIFTER
4158 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4159 word18 tmp18 = cpu.TPR.CA & 0177; // CY bits 11-17
4160
4161 bool a0 = cpu.rA & SIGN36; // A0
4162 for (uint j = 0 ; j < tmp18 ; j ++)
4163 {
4164 cpu.rA >>= 1; // shift right 1
4165 if (a0) // propagate sign bit
4166 cpu.rA |= SIGN36;
4167 }
4168 cpu.rA &= DMASK; // keep to 36-bits
4169 #endif // BARREL_SHIFTER
4170 #if defined(TESTING)
4171 HDBGRegAW ("ars");
4172 #endif
4173
4174 SC_I_ZERO (cpu.rA == 0);
4175 SC_I_NEG (cpu.rA & SIGN36);
4176 }
4177 break;
4178
4179 case x0 (0777): // llr
4180 // Shift C(AQ) left by the number of positions given in
4181 // C(TPR.CA)11,17; entering each bit leaving AQ0 into AQ71.
4182
4183 {
4184 #if defined(TESTING)
4185 HDBGRegAR ("llr");
4186 HDBGRegQR ("llr");
4187 #endif
4188 #if BARREL_SHIFTER
4189 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4190 cnt = cnt % 72; // 0-71
4191 if (cnt > 35) {
4192 cnt = cnt - 36;
4193 word36 tmp = cpu.rA;
4194 cpu.rA = cpu.rQ;
4195 cpu.rQ = tmp;
4196 }
4197 word36 highA = cpu.rA & barrelLeftMaskTable[cnt];
4198 word36 lowA = cpu.rA & BS_COMPL(barrelLeftMaskTable[cnt]);
4199 word36 highQ = cpu.rQ & barrelLeftMaskTable[cnt];
4200 word36 lowQ = cpu.rQ & BS_COMPL(barrelLeftMaskTable[cnt]);
4201 cpu.rA = (lowA << cnt) | (highQ >> (36 - cnt));
4202 cpu.rQ = (lowQ << cnt) | (highA >> (36 - cnt));
4203 #else // !BARREL_SHIFTER
4204 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4205 for (uint j = 0 ; j < tmp36 ; j++)
4206 {
4207 bool a0 = cpu.rA & SIGN36; // A0
4208
4209 cpu.rA <<= 1; // shift left 1
4210
4211 bool b0 = cpu.rQ & SIGN36; // Q0
4212 if (b0)
4213 cpu.rA |= 1; // Q0 => A35
4214
4215 cpu.rQ <<= 1; // shift left 1
4216
4217 if (a0) // propagate A sign bit
4218 cpu.rQ |= 1;
4219 }
4220
4221 #endif // BARREL_SHIFTER
4222 cpu.rA &= DMASK; // keep to 36-bits
4223 cpu.rQ &= DMASK;
4224 #if defined(TESTING)
4225 HDBGRegAW ("llr");
4226 HDBGRegQW ("llr");
4227 #endif
4228
4229 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4230 SC_I_NEG (cpu.rA & SIGN36);
4231 }
4232 break;
4233
4234 case x0 (0737): // lls
4235 {
4236 // lls Long Left Shift
4237 // Shift C(AQ) left the number of positions given in
4238 // C(TPR.CA)11,17; filling vacated positions with zeros.
4239 // Zero if C(AQ) == 0 then ON; otherwise OFF:
4240 // Negative if C(AQ)0 == 1 then On; otherwise OFF;
4241 // Carry if C(AQ)0 changes during the shift; then ON; otherwise OFF:
4242 #if BARREL_SHIFTER
4243 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4244
4245
4246 // Sanitize
4247 cpu.rA &= MASK36;
4248 cpu.rQ &= MASK36;
4249
4250 if (cnt >= 72) {
4251 // If the shift is 72 or greater, AQ will be set to zero and
4252 // the carry will be cleared if the initial value of AQ is 0 or
4253 // all ones
4254 bool allz = cpu.rA == 0 && cpu.rQ == 0;
4255 bool all1 = cpu.rA == MASK36 && cpu.rQ == MASK36;
4256 if (allz || all1)
4257 CLR_I_CARRY;
4258 else
4259 SET_I_CARRY;
4260 cpu.rA = 0;
4261 cpu.rQ = 0;
4262
4263 } else if (cnt >= 36) {
4264 // If the shift count is 36 to 71, all of A and some of Q will determine
4265 // the carry; all of A will become Q << (cnt - 36), and Q will become 0.
4266 uint cnt36 = cnt - 36;
4267 // The carry depends on the sign bit changing on the shift;
4268 // add 1 so that the mask includes the sign bit and all of
4269 // the bits that will be shifted in.
4270 word36 lmask = barrelLeftMaskTable[cnt36 + 1];
4271 // Capture all of the bits that will be shifted
4272 word36 captureA = cpu.rA;
4273 word36 captureQ = lmask & cpu.rQ;
4274 bool az = captureA == 0;
4275 bool a1 = captureA == MASK36;
4276 bool qz = captureQ == 0;
4277 bool q1 = captureQ == (MASK36 & lmask);
4278 bool allz = az && qz;
4279 bool all1 = a1 && q1;
4280 if (allz || all1)
4281 CLR_I_CARRY;
4282 else
4283 SET_I_CARRY;
4284
4285 // Shift the bits
4286 cpu.rA = (cpu.rQ << cnt36) & MASK36;
4287 cpu.rQ = 0;
4288 } else { // cnt < 36
4289 // If the count is < 36, carry is determined by the high part of A;
4290 // A is shifted left, and bits shifted out of Q are shifted into A.
4291 // The carry depends on the sign bit changing on the shift;
4292 // add 1 so that the mask includes the sign bit and all of
4293 // the bits that will be shifted in.
4294 word36 lmask = barrelLeftMaskTable[cnt + 1];
4295 word36 captureA = lmask & cpu.rA;
4296 bool allz = captureA == 0;
4297 bool all1 = captureA == (MASK36 & lmask);
4298
4299 if (allz || all1)
4300 CLR_I_CARRY;
4301 else
4302 SET_I_CARRY;
4303
4304 // Shift the bits
4305 cpu.rA = ((cpu.rA << cnt) & MASK36) | (cpu.rQ >> (36 - cnt));
4306 cpu.rQ = (cpu.rQ << cnt) & MASK36;
4307 }
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345 #else // !BARREL_SHIFTER
4346
4347 CLR_I_CARRY;
4348
4349 # if defined(TESTING)
4350 HDBGRegAR ("lls");
4351 HDBGRegQR ("lls");
4352 # endif
4353 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4354 word36 tmpSign = cpu.rA & SIGN36;
4355 for (uint j = 0 ; j < tmp36 ; j ++)
4356 {
4357 cpu.rA <<= 1; // shift left 1
4358
4359 if (tmpSign != (cpu.rA & SIGN36))
4360 SET_I_CARRY;
4361
4362 bool b0 = cpu.rQ & SIGN36; // Q0
4363 if (b0)
4364 cpu.rA |= 1; // Q0 => A35
4365
4366 cpu.rQ <<= 1; // shift left 1
4367 }
4368
4369 cpu.rA &= DMASK; // keep to 36-bits
4370 cpu.rQ &= DMASK;
4371 #endif // BARREL_SHIFTER
4372 #if defined(TESTING)
4373 HDBGRegAW ("lls");
4374 HDBGRegQW ("lls");
4375 #endif
4376
4377 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4378 SC_I_NEG (cpu.rA & SIGN36);
4379 }
4380 break;
4381
4382 case x0 (0773): // lrl
4383 // Shift C(AQ) right the number of positions given in
4384 // C(TPR.CA)11,17; filling vacated positions with zeros.
4385 {
4386 #if defined(TESTING)
4387 HDBGRegAR ("lrl");
4388 HDBGRegQR ("lrl");
4389 #endif
4390 #if BARREL_SHIFTER
4391 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4392 if (cnt >= 72) {
4393 cpu.rA = 0;
4394 cpu.rQ = 0;
4395 } else if (cnt < 36) {
4396 // Shift rQ
4397 cpu.rQ >>= cnt;
4398 // Mask out the high bits
4399 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4400 // Capture the low bits in A
4401 word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4402 // Shift A
4403 cpu.rA >>= cnt;
4404 // Mask out the high bits
4405 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4406 // Move the low A bits left
4407 lowA <<= (36 - cnt);
4408 // Put them in high Q
4409 cpu.rQ |= lowA;
4410 } else { // 36-71
4411 // Shift rQ
4412 cpu.rQ = cpu.rA >> (cnt - 36);
4413 // Mask out the high bits
4414 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4415 cpu.rA = 0;
4416 }
4417 cpu.rA &= DMASK; // keep to 36-bits
4418 cpu.rQ &= DMASK;
4419 #else // !BARREL_SHIFTER
4420 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4421 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4422 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4423 for (uint j = 0 ; j < tmp36 ; j++)
4424 {
4425 bool a35 = cpu.rA & 1; // A35
4426 cpu.rA >>= 1; // shift right 1
4427
4428 cpu.rQ >>= 1; // shift right 1
4429
4430 if (a35) // propagate sign bit
4431 cpu.rQ |= SIGN36;
4432 }
4433 cpu.rA &= DMASK; // keep to 36-bits
4434 cpu.rQ &= DMASK;
4435 #endif // BARREL_SHIFTER
4436 #if defined(TESTING)
4437 HDBGRegAW ("lrl");
4438 HDBGRegQW ("lrl");
4439 #endif
4440
4441 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4442 SC_I_NEG (cpu.rA & SIGN36);
4443 }
4444 break;
4445
4446 case x0 (0733): // lrs
4447 {
4448 // Shift C(AQ) right the number of positions given in
4449 // C(TPR.CA)11,17; filling vacated positions with initial C(AQ)0.
4450
4451 #if defined(TESTING)
4452 HDBGRegAR ("lrs");
4453 HDBGRegQR ("lrs");
4454 #endif
4455 #if BARREL_SHIFTER
4456 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4457 bool AQ0 = (cpu.rA & SIGN36) != 0;
4458 if (cnt >= 72) {
4459 cpu.rA = cpu.rQ = AQ0 ? MASK36 : 0;
4460 } else if (cnt < 36) {
4461 // Shift rQ
4462 cpu.rQ >>= cnt;
4463 // Mask out the high bits
4464 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4465 // Capture the low bits in A
4466 word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4467 // Shift A
4468 cpu.rA >>= cnt;
4469 // Set the high bits to AQ0
4470 if (AQ0)
4471 cpu.rA |= barrelLeftMaskTable[cnt];
4472 else
4473 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4474 // Move the low A bits left
4475 lowA <<= (36 - cnt);
4476 // Put them in high Q
4477 cpu.rQ |= lowA;
4478 } else { // 36-71
4479 // Shift rQ
4480 cpu.rQ = cpu.rA >> (cnt - 36);
4481 // Mask out the high bits
4482 if (AQ0) {
4483 cpu.rQ |= barrelLeftMaskTable[cnt - 36];
4484 cpu.rA = MASK36;
4485 } else {
4486 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4487 cpu.rA = 0;
4488 }
4489 }
4490 cpu.rA &= DMASK; // keep to 36-bits
4491 cpu.rQ &= DMASK;
4492 #else // !BARREL_SHIFTER
4493 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4494 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4495 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4496 bool a0 = cpu.rA & SIGN36; // A0
4497
4498 for (uint j = 0 ; j < tmp36 ; j ++)
4499 {
4500 bool a35 = cpu.rA & 1; // A35
4501
4502 cpu.rA >>= 1; // shift right 1
4503 if (a0)
4504 cpu.rA |= SIGN36;
4505
4506 cpu.rQ >>= 1; // shift right 1
4507 if (a35) // propagate sign bit1
4508 cpu.rQ |= SIGN36;
4509 }
4510 cpu.rA &= DMASK; // keep to 36-bits (probably ain't necessary)
4511 cpu.rQ &= DMASK;
4512 #endif // BARREL_SHIFTER
4513 #if defined(TESTING)
4514 HDBGRegAW ("lrs");
4515 HDBGRegQW ("lrs");
4516 #endif
4517
4518 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4519 SC_I_NEG (cpu.rA & SIGN36);
4520 }
4521 break;
4522
4523 case x0 (0776): // qlr
4524 // Shift C(Q) left the number of positions given in
4525 // C(TPR.CA)11,17; entering each bit leaving Q0 into Q35.
4526 {
4527 #if defined(TESTING)
4528 HDBGRegQR ("qlr");
4529 #endif
4530 #if BARREL_SHIFTER
4531 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4532 cnt %= 36;
4533
4534 word36 highQ = cpu.rQ & barrelLeftMaskTable[cnt];
4535 cpu.rQ <<= cnt;
4536 highQ >>= (36 - cnt);
4537 highQ &= barrelRightMaskTable[cnt];
4538 cpu.rQ |= highQ;
4539 cpu.rQ &= DMASK; // keep to 36-bits
4540 #else // !BARREL_SHIFTER
4541 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4542 for (uint j = 0 ; j < tmp36 ; j++)
4543 {
4544 bool q0 = cpu.rQ & SIGN36; // Q0
4545 cpu.rQ <<= 1; // shift left 1
4546 if (q0) // rotate A0 -> A35
4547 cpu.rQ |= 1;
4548 }
4549 cpu.rQ &= DMASK; // keep to 36-bits
4550 #endif // BARREL_SHIFTER
4551 #if defined(TESTING)
4552 HDBGRegQW ("qlr");
4553 #endif
4554
4555 SC_I_ZERO (cpu.rQ == 0);
4556 SC_I_NEG (cpu.rQ & SIGN36);
4557 }
4558 break;
4559
4560 // Optimized to the top of the loop
4561 // case x0 (0736): // qls
4562
4563 case x0 (0772): // qrl
4564 // Shift C(Q) right the number of positions specified by
4565 // Y11,17; fill vacated positions with zeros.
4566 {
4567 #if defined(TESTING)
4568 HDBGRegQR ("qrl");
4569 #endif
4570 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4571
4572 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4573 cpu.rQ >>= tmp36;
4574 cpu.rQ &= DMASK; // keep to 36-bits
4575 #if defined(TESTING)
4576 HDBGRegQW ("qrl");
4577 #endif
4578
4579 SC_I_ZERO (cpu.rQ == 0);
4580 SC_I_NEG (cpu.rQ & SIGN36);
4581
4582 }
4583 break;
4584
4585 case x0 (0732): // qrs
4586 {
4587 // Shift C(Q) right the number of positions given in
4588 // C(TPR.CA)11,17; filling vacated positions with initial C(Q)0.
4589
4590 #if defined(TESTING)
4591 HDBGRegQR ("qrs");
4592 #endif
4593 #if BARREL_SHIFTER
4594 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4595 bool Q0 = (cpu.rQ & SIGN36) != 0;
4596
4597 if (cnt >= 36) {
4598 cpu.rQ = Q0 ? MASK36 : 0;
4599 } else {
4600 // Shift rQ
4601 cpu.rQ >>= cnt;
4602 // Mask out the high bits
4603 if (Q0) {
4604 cpu.rQ |= barrelLeftMaskTable[cnt];
4605 } else {
4606 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4607 }
4608 }
4609 cpu.rQ &= DMASK; // keep to 36-bits
4610 #else // !BARREL_SHIFTER
4611 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4612 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4613 bool q0 = cpu.rQ & SIGN36; // Q0
4614 for (uint j = 0 ; j < tmp36 ; j++)
4615 {
4616 cpu.rQ >>= 1; // shift right 1
4617 if (q0) // propagate sign bit
4618 cpu.rQ |= SIGN36;
4619 }
4620 cpu.rQ &= DMASK; // keep to 36-bits
4621 #endif // BARREL_SHIFTER
4622 #if defined(TESTING)
4623 HDBGRegQW ("qrs");
4624 #endif
4625
4626 SC_I_ZERO (cpu.rQ == 0);
4627 SC_I_NEG (cpu.rQ & SIGN36);
4628 }
4629 break;
4630
4631 /// Fixed-Point Addition
4632
4633 case x0 (0075): // ada
4634 {
4635 // C(A) + C(Y) -> C(A)
4636 // Modifications: All
4637 //
4638 // (Indicators not listed are not affected)
4639 // ZERO: If C(A) = 0, then ON; otherwise OFF
4640 // NEG: If C(A)0 = 1, then ON; otherwise OFF
4641 // OVR: If range of A is exceeded, then ON
4642 // CARRY: If a carry out of A0 is generated, then ON; otherwise OFF
4643
4644 L68_ (cpu.ou.cycle |= ou_GOS;)
4645 #if defined(TESTING)
4646 HDBGRegAR ("ada");
4647 #endif
4648 bool ovf;
4649 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4650 #if defined(TESTING)
4651 HDBGRegAW ("ada");
4652 #endif
4653 overflow (cpup, ovf, false, "ada overflow fault");
4654 }
4655 break;
4656
4657 case x0 (0077): // adaq
4658 {
4659 // C(AQ) + C(Y-pair) -> C(AQ)
4660 L68_ (cpu.ou.cycle |= ou_GOS;)
4661 #if defined(TESTING)
4662 HDBGRegAR ("adaq");
4663 HDBGRegQR ("adaq");
4664 #endif
4665 bool ovf;
4666 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4667 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4668 tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4669 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4670 #if defined(TESTING)
4671 HDBGRegAW ("adaq");
4672 HDBGRegQW ("adaq");
4673 #endif
4674 overflow (cpup, ovf, false, "adaq overflow fault");
4675 }
4676 break;
4677
4678 case x0 (0033): // adl
4679 {
4680 // C(AQ) + C(Y) sign extended -> C(AQ)
4681 L68_ (cpu.ou.cycle |= ou_GOS;)
4682 #if defined(TESTING)
4683 HDBGRegAR ("adl");
4684 HDBGRegQR ("adl");
4685 #endif
4686 bool ovf;
4687 word72 tmp72 = SIGNEXT36_72 (cpu.CY); // sign extend Cy
4688 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4689 tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4690 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4691 #if defined(TESTING)
4692 HDBGRegAW ("adl");
4693 HDBGRegQW ("adl");
4694 #endif
4695 overflow (cpup, ovf, false, "adl overflow fault");
4696 }
4697 break;
4698
4699 case x0 (0037): // adlaq
4700 {
4701 // The adlaq instruction is identical to the adaq instruction with
4702 // the exception that the overflow indicator is not affected by the
4703 // adlaq instruction, nor does an overflow fault occur. Operands
4704 // and results are treated as unsigned, positive binary integers.
4705 L68_ (cpu.ou.cycle |= ou_GOS;)
4706 #if defined(TESTING)
4707 HDBGRegAR ("adlaq");
4708 HDBGRegQR ("adlaq");
4709 #endif
4710 bool ovf;
4711 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4712
4713 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4714 tmp72, 0, I_ZNC, & cpu.cu.IR, & ovf);
4715 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4716 #if defined(TESTING)
4717 HDBGRegAW ("adlaq");
4718 HDBGRegQW ("adlaq");
4719 #endif
4720 }
4721 break;
4722
4723 case x0 (0035): // adla
4724 {
4725 L68_ (cpu.ou.cycle |= ou_GOS;)
4726 // The adla instruction is identical to the ada instruction with
4727 // the exception that the overflow indicator is not affected by the
4728 // adla instruction, nor does an overflow fault occur. Operands and
4729 // results are treated as unsigned, positive binary integers. */
4730
4731 #if defined(TESTING)
4732 HDBGRegAR ("adla");
4733 #endif
4734 bool ovf;
4735 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4736 #if defined(TESTING)
4737 HDBGRegAW ("adla");
4738 #endif
4739 }
4740 break;
4741
4742 case x0 (0036): // adlq
4743 {
4744 // The adlq instruction is identical to the adq instruction with
4745 // the exception that the overflow indicator is not affected by the
4746 // adlq instruction, nor does an overflow fault occur. Operands and
4747 // results are treated as unsigned, positive binary integers. */
4748
4749 L68_ (cpu.ou.cycle |= ou_GOS;)
4750 #if defined(TESTING)
4751 HDBGRegQR ("adlq");
4752 #endif
4753 bool ovf;
4754 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4755 #if defined(TESTING)
4756 HDBGRegQW ("adlq");
4757 #endif
4758 }
4759 break;
4760
4761 // adlxn
4762 case x0 (0020): // adlx0
4763 case x0 (0021): // adlx1
4764 case x0 (0022): // adlx2
4765 case x0 (0023): // adlx3
4766 case x0 (0024): // adlx4
4767 case x0 (0025): // adlx5
4768 case x0 (0026): // adlx6
4769 case x0 (0027): // adlx7
4770 {
4771 L68_ (cpu.ou.cycle |= ou_GOS;)
4772 uint32 n = opcode10 & 07; // get n
4773 #if defined(TESTING)
4774 HDBGRegXR (n, "adlxn");
4775 #endif
4776 bool ovf;
4777 cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0, I_ZNC,
4778 & cpu.cu.IR, & ovf);
4779 #if defined(TESTING)
4780 HDBGRegXW (n, "adlxn");
4781 #endif
4782 }
4783 break;
4784
4785 // Optimized to the top of the loop
4786 // case x0 (0076): // adq
4787
4788 // adxn
4789 case x0 (0060): // adx0
4790 case x0 (0061): // adx1
4791 case x0 (0062): // adx2
4792 case x0 (0063): // adx3
4793 case x0 (0064): // adx4
4794 case x0 (0065): // adx5
4795 case x0 (0066): // adx6
4796 case x0 (0067): // adx7
4797 {
4798 L68_ (cpu.ou.cycle |= ou_GOS;)
4799 uint32 n = opcode10 & 07; // get n
4800 #if defined(TESTING)
4801 HDBGRegXR (n, "adxn");
4802 #endif
4803 bool ovf;
4804 cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4805 I_ZNOC,
4806 & cpu.cu.IR, & ovf);
4807 #if defined(TESTING)
4808 HDBGRegXW (n, "adxn");
4809 #endif
4810 overflow (cpup, ovf, false, "adxn overflow fault");
4811 }
4812 break;
4813
4814 // Optimized to the top of the loop
4815 // case x0 (0054): // aos
4816
4817 case x0 (0055): // asa
4818 {
4819 // C(A) + C(Y) -> C(Y)
4820
4821 L68_ (cpu.ou.cycle |= ou_GOS;)
4822 #if defined(TESTING)
4823 HDBGRegAR ("asa");
4824 #endif
4825 bool ovf;
4826 cpu.CY = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC,
4827 & cpu.cu.IR, & ovf);
4828 overflow (cpup, ovf, true, "asa overflow fault");
4829 }
4830 break;
4831
4832 case x0 (0056): // asq
4833 {
4834 // C(Q) + C(Y) -> C(Y)
4835 L68_ (cpu.ou.cycle |= ou_GOS;)
4836 #if defined(TESTING)
4837 HDBGRegQR ("asa");
4838 #endif
4839 bool ovf;
4840 cpu.CY = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4841 overflow (cpup, ovf, true, "asq overflow fault");
4842 }
4843 break;
4844
4845 // asxn
4846 case x0 (0040): // asx0
4847 case x0 (0041): // asx1
4848 case x0 (0042): // asx2
4849 case x0 (0043): // asx3
4850 case x0 (0044): // asx4
4851 case x0 (0045): // asx5
4852 case x0 (0046): // asx6
4853 case x0 (0047): // asx7
4854 {
4855 // For n = 0, 1, ..., or 7 as determined by operation code
4856 // C(Xn) + C(Y)0,17 -> C(Y)0,17
4857 L68_ (cpu.ou.cycle |= ou_GOS;)
4858 uint32 n = opcode10 & 07; // get n
4859 #if defined(TESTING)
4860 HDBGRegXR (n, "asxn");
4861 #endif
4862 bool ovf;
4863 word18 tmp18 = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4864 I_ZNOC, & cpu.cu.IR, & ovf);
4865 SETHI (cpu.CY, tmp18);
4866 overflow (cpup, ovf, true, "asxn overflow fault");
4867 }
4868 break;
4869
4870 case x0 (0071): // awca
4871 {
4872 // If carry indicator OFF, then C(A) + C(Y) -> C(A)
4873 // If carry indicator ON, then C(A) + C(Y) + 1 -> C(A)
4874
4875 L68_ (cpu.ou.cycle |= ou_GOS;)
4876 #if defined(TESTING)
4877 HDBGRegAR ("awca");
4878 #endif
4879 bool ovf;
4880 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
4881 I_ZNOC, & cpu.cu.IR, & ovf);
4882 #if defined(TESTING)
4883 HDBGRegAW ("awca");
4884 #endif
4885 overflow (cpup, ovf, false, "awca overflow fault");
4886 }
4887 break;
4888
4889 case x0 (0072): // awcq
4890 {
4891 // If carry indicator OFF, then C(Q) + C(Y) -> C(Q)
4892 // If carry indicator ON, then C(Q) + C(Y) + 1 -> C(Q)
4893
4894 L68_ (cpu.ou.cycle |= ou_GOS;)
4895 #if defined(TESTING)
4896 HDBGRegQR ("awcq");
4897 #endif
4898 bool ovf;
4899 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
4900 I_ZNOC, & cpu.cu.IR, & ovf);
4901 #if defined(TESTING)
4902 HDBGRegQW ("awcq");
4903 #endif
4904 overflow (cpup, ovf, false, "awcq overflow fault");
4905 }
4906 break;
4907
4908 /// Fixed-Point Subtraction
4909
4910 case x0 (0175): // sba
4911 {
4912 // C(A) - C(Y) -> C(A)
4913
4914 L68_ (cpu.ou.cycle |= ou_GOS;)
4915 #if defined(TESTING)
4916 HDBGRegAR ("sba");
4917 #endif
4918 bool ovf;
4919 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
4920 #if defined(TESTING)
4921 HDBGRegAW ("sba");
4922 #endif
4923 overflow (cpup, ovf, false, "sba overflow fault");
4924 }
4925 break;
4926
4927 case x0 (0177): // sbaq
4928 {
4929 // C(AQ) - C(Y-pair) -> C(AQ)
4930 L68_ (cpu.ou.cycle |= ou_GOS;)
4931 #if defined(TESTING)
4932 HDBGRegAR ("sbaq");
4933 HDBGRegQR ("sbaq");
4934 #endif
4935 bool ovf;
4936 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4937 tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
4938 I_ZNOC, & cpu.cu.IR,
4939 & ovf);
4940 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4941 #if defined(TESTING)
4942 HDBGRegAW ("sbaq");
4943 HDBGRegQW ("sbaq");
4944 #endif
4945 overflow (cpup, ovf, false, "sbaq overflow fault");
4946 }
4947 break;
4948
4949 case x0 (0135): // sbla
4950 {
4951 // C(A) - C(Y) -> C(A) logical
4952
4953 L68_ (cpu.ou.cycle |= ou_GOS;)
4954 #if defined(TESTING)
4955 HDBGRegAR ("sbla");
4956 #endif
4957 bool ovf;
4958 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
4959 #if defined(TESTING)
4960 HDBGRegAW ("sbla");
4961 #endif
4962 }
4963 break;
4964
4965 case x0 (0137): // sblaq
4966 {
4967 // The sblaq instruction is identical to the sbaq instruction with
4968 // the exception that the overflow indicator is not affected by the
4969 // sblaq instruction, nor does an overflow fault occur. Operands
4970 // and results are treated as unsigned, positive binary integers.
4971 // C(AQ) - C(Y-pair) -> C(AQ)
4972
4973 L68_ (cpu.ou.cycle |= ou_GOS;)
4974 #if defined(TESTING)
4975 HDBGRegAR ("sblaq");
4976 HDBGRegQR ("sblaq");
4977 #endif
4978 bool ovf;
4979 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4980
4981 tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
4982 I_ZNC, & cpu.cu.IR, & ovf);
4983 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4984 #if defined(TESTING)
4985 HDBGRegAW ("sblaq");
4986 HDBGRegQW ("sblaq");
4987 #endif
4988 }
4989 break;
4990
4991 case x0 (0136): // sblq
4992 {
4993 // C(Q) - C(Y) -> C(Q)
4994 L68_ (cpu.ou.cycle |= ou_GOS;)
4995 #if defined(TESTING)
4996 HDBGRegQR ("sblq");
4997 #endif
4998 bool ovf;
4999 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
5000 #if defined(TESTING)
5001 HDBGRegQW ("sblq");
5002 #endif
5003 }
5004 break;
5005
5006 // sblxn
5007 case x0 (0120): // sblx0
5008 case x0 (0121): // sblx1
5009 case x0 (0122): // sblx2
5010 case x0 (0123): // sblx3
5011 case x0 (0124): // sblx4
5012 case x0 (0125): // sblx5
5013 case x0 (0126): // sblx6
5014 case x0 (0127): // sblx7
5015 {
5016 // For n = 0, 1, ..., or 7 as determined by operation code
5017 // C(Xn) - C(Y)0,17 -> C(Xn)
5018
5019 L68_ (cpu.ou.cycle |= ou_GOS;)
5020 uint32 n = opcode10 & 07; // get n
5021 #if defined(TESTING)
5022 HDBGRegXR (n, "sblxn");
5023 #endif
5024 bool ovf;
5025 cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5026 I_ZNC, & cpu.cu.IR, & ovf);
5027 #if defined(TESTING)
5028 HDBGRegXW (n, "sblxn");
5029 #endif
5030 }
5031 break;
5032
5033 case x0 (0176): // sbq
5034 {
5035 // C(Q) - C(Y) -> C(Q)
5036 L68_ (cpu.ou.cycle |= ou_GOS;)
5037 #if defined(TESTING)
5038 HDBGRegQR ("sbq");
5039 #endif
5040 bool ovf;
5041 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5042 #if defined(TESTING)
5043 HDBGRegQW ("sbq");
5044 #endif
5045 overflow (cpup, ovf, false, "sbq overflow fault");
5046 }
5047 break;
5048
5049 // sbxn
5050 case x0 (0160): // sbx0
5051 case x0 (0161): // sbx1
5052 case x0 (0162): // sbx2
5053 case x0 (0163): // sbx3
5054 case x0 (0164): // sbx4
5055 case x0 (0165): // sbx5
5056 case x0 (0166): // sbx6
5057 case x0 (0167): // sbx7
5058 {
5059 // For n = 0, 1, ..., or 7 as determined by operation code
5060 // C(Xn) - C(Y)0,17 -> C(Xn)
5061
5062 L68_ (cpu.ou.cycle |= ou_GOS;)
5063 uint32 n = opcode10 & 07; // get n
5064 #if defined(TESTING)
5065 HDBGRegXR (n, "sbxn");
5066 #endif
5067 bool ovf;
5068 cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5069 I_ZNOC, & cpu.cu.IR, & ovf);
5070 #if defined(TESTING)
5071 HDBGRegXW (n, "sbxn");
5072 #endif
5073 overflow (cpup, ovf, false, "sbxn overflow fault");
5074 }
5075 break;
5076
5077 case x0 (0155): // ssa
5078 {
5079 // C(A) - C(Y) -> C(Y)
5080
5081 L68_ (cpu.ou.cycle |= ou_GOS;)
5082 #if defined(TESTING)
5083 HDBGRegAR ("ssa");
5084 #endif
5085 bool ovf;
5086 cpu.CY = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5087 overflow (cpup, ovf, true, "ssa overflow fault");
5088 }
5089 break;
5090
5091 case x0 (0156): // ssq
5092 {
5093 // C(Q) - C(Y) -> C(Y)
5094
5095 L68_ (cpu.ou.cycle |= ou_GOS;)
5096 #if defined(TESTING)
5097 HDBGRegQR ("ssq");
5098 #endif
5099 bool ovf;
5100 cpu.CY = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5101 overflow (cpup, ovf, true, "ssq overflow fault");
5102 }
5103 break;
5104
5105 // ssxn
5106 case x0 (0140): // ssx0
5107 case x0 (0141): // ssx1
5108 case x0 (0142): // ssx2
5109 case x0 (0143): // ssx3
5110 case x0 (0144): // ssx4
5111 case x0 (0145): // ssx5
5112 case x0 (0146): // ssx6
5113 case x0 (0147): // ssx7
5114 {
5115 // For uint32 n = 0, 1, ..., or 7 as determined by operation code
5116 // C(Xn) - C(Y)0,17 -> C(Y)0,17
5117
5118 L68_ (cpu.ou.cycle |= ou_GOS;)
5119 uint32 n = opcode10 & 07; // get n
5120 #if defined(TESTING)
5121 HDBGRegXR (n, "ssxn");
5122 #endif
5123 bool ovf;
5124 word18 tmp18 = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5125 I_ZNOC, & cpu.cu.IR, & ovf);
5126 SETHI (cpu.CY, tmp18);
5127 overflow (cpup, ovf, true, "ssxn overflow fault");
5128 }
5129 break;
5130
5131 case x0 (0171): // swca
5132 {
5133 // If carry indicator ON, then C(A)- C(Y) -> C(A)
5134 // If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
5135
5136 L68_ (cpu.ou.cycle |= ou_GOS;)
5137 #if defined(TESTING)
5138 HDBGRegAR ("swca");
5139 #endif
5140 bool ovf;
5141 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
5142 I_ZNOC, & cpu.cu.IR, & ovf);
5143 #if defined(TESTING)
5144 HDBGRegAW ("swca");
5145 #endif
5146 overflow (cpup, ovf, false, "swca overflow fault");
5147 }
5148 break;
5149
5150 case x0 (0172): // swcq
5151 {
5152 // If carry indicator ON, then C(Q) - C(Y) -> C(Q)
5153 // If carry indicator OFF, then C(Q) - C(Y) - 1 -> C(Q)
5154
5155 L68_ (cpu.ou.cycle |= ou_GOS;)
5156 #if defined(TESTING)
5157 HDBGRegQR ("swcq");
5158 #endif
5159 bool ovf;
5160 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
5161 I_ZNOC, & cpu.cu.IR, & ovf);
5162 #if defined(TESTING)
5163 HDBGRegQW ("swcq");
5164 #endif
5165 overflow (cpup, ovf, false, "swcq overflow fault");
5166 }
5167 break;
5168
5169 /// Fixed-Point Multiplication
5170
5171 case x0 (0401): // mpf
5172 {
5173 // C(A) * C(Y) -> C(AQ), left adjusted
5174 //
5175 // Two 36-bit fractional factors (including sign) are multiplied
5176 // to form a 71- bit fractional product (including sign), which
5177 // is stored left-adjusted in the AQ register. AQ71 contains a
5178 // zero. Overflow can occur only in the case of A and Y
5179 // containing negative 1 and the result exceeding the range of
5180 // the AQ register.
5181
5182 L68_ (cpu.ou.cycle |= ou_GD1;)
5183 #if defined(NEED_128)
5184 # if defined(TESTING)
5185 HDBGRegAR ("mpf");
5186 HDBGRegQR ("mpf");
5187 # endif
5188 word72 tmp72 = multiply_128 (SIGNEXT36_72 (cpu.rA), SIGNEXT36_72 (cpu.CY));
5189 tmp72 = and_128 (tmp72, MASK72);
5190 tmp72 = lshift_128 (tmp72, 1);
5191 #else
5192 // word72 tmp72 = SIGNEXT36_72 (cpu.rA) * SIGNEXT36_72 (cpu.CY);
5193 // ubsan
5194 word72 tmp72 = (word72) (((word72s) SIGNEXT36_72 (cpu.rA)) * ((word72s) SIGNEXT36_72 (cpu.CY)));
5195 tmp72 &= MASK72;
5196 tmp72 <<= 1; // left adjust so AQ71 contains 0
5197 #endif
5198 L68_ (cpu.ou.cycle |= ou_GD2;)
5199 // Overflow can occur only in the case of A and Y containing
5200 // negative 1
5201 if (cpu.rA == MAXNEG && cpu.CY == MAXNEG)
5202 {
5203 SET_I_NEG;
5204 CLR_I_ZERO;
5205 overflow (cpup, true, false, "mpf overflow fault");
5206 }
5207
5208 convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5209 #if defined(TESTING)
5210 HDBGRegAW ("mpf");
5211 HDBGRegQW ("mpf");
5212 #endif
5213 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5214 SC_I_NEG (cpu.rA & SIGN36);
5215 }
5216 break;
5217
5218 case x0 (0402): // mpy
5219 // C(Q) * C(Y) -> C(AQ), right adjusted
5220
5221 {
5222 L68_ (cpu.ou.cycle |= ou_GOS;)
5223 #if defined(NEED_128)
5224 # if defined(TESTING)
5225 HDBGRegQR ("mpy");
5226 # endif
5227 int128 prod = multiply_s128 (
5228 SIGNEXT36_128 (cpu.rQ & DMASK),
5229 SIGNEXT36_128 (cpu.CY & DMASK));
5230 convert_to_word36 (cast_128 (prod), &cpu.rA, &cpu.rQ);
5231 #else
5232 int64_t t0 = SIGNEXT36_64 (cpu.rQ & DMASK);
5233 int64_t t1 = SIGNEXT36_64 (cpu.CY & DMASK);
5234
5235 __int128_t prod = (__int128_t) t0 * (__int128_t) t1;
5236
5237 convert_to_word36 ((word72)prod, &cpu.rA, &cpu.rQ);
5238 #endif
5239 #if defined(TESTING)
5240 HDBGRegAW ("mpy");
5241 HDBGRegQW ("mpy");
5242 #endif
5243
5244 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5245 SC_I_NEG (cpu.rA & SIGN36);
5246 }
5247 break;
5248
5249 //#define DIV_TRACE
5250
5251 /// Fixed-Point Division
5252
5253 case x0 (0506): // div
5254 // C(Q) / (Y) integer quotient -> C(Q), integer remainder -> C(A)
5255 //
5256 // A 36-bit integer dividend (including sign) is divided by a
5257 // 36-bit integer divisor (including sign) to form a 36-bit integer
5258 // * quotient (including sign) and a 36-bit integer remainder
5259 // * (including sign). The remainder sign is equal to the dividend
5260 // * sign unless the remainder is zero.
5261 // *
5262 // * If the dividend = -2**35 and the divisor = -1 or if the divisor
5263 // * = 0, then division does not take place. Instead, a divide check
5264 // * fault occurs, C(Q) contains the dividend magnitude, and the
5265 // * negative indicator reflects the dividend sign.
5266
5267 L68_ (cpu.ou.cycle |= ou_GD1;)
5268 // RJ78: If the dividend = -2**35 and the divisor = +/-1, or if
5269 // the divisor is 0
5270
5271 #if defined(TESTING)
5272 HDBGRegQR ("div");
5273 #endif
5274 if ((cpu.rQ == MAXNEG && (cpu.CY == 1 || cpu.CY == NEG136)) ||
5275 (cpu.CY == 0))
5276 {
5277 //sim_printf ("DIV Q %012"PRIo64" Y %012"PRIo64"\r\n", cpu.rQ, cpu.CY);
5278 // case 1 400000000000 000000000000 --> 000000000000
5279 // case 2 000000000000 000000000000 --> 400000000000
5280 //cpu.rA = 0; // works for case 1
5281 cpu.rA = (cpu.rQ & SIGN36) ? 0 : SIGN36; // works for case 1,2
5282 #if defined(TESTING)
5283 HDBGRegAW ("div");
5284 #endif
5285
5286 // no division takes place
5287 SC_I_ZERO (cpu.CY == 0);
5288 SC_I_NEG (cpu.rQ & SIGN36);
5289
5290 if (cpu.rQ & SIGN36)
5291 {
5292 // cpu.rQ = (- cpu.rQ) & MASK36;
5293 // ubsan
5294 cpu.rQ = ((word36) (- (word36s) cpu.rQ)) & MASK36;
5295 #if defined(TESTING)
5296 HDBGRegQW ("div");
5297 #endif
5298 }
5299
5300 dlyDoFault (FAULT_DIV,
5301 fst_ill_op,
5302 "div divide check");
5303 }
5304 else
5305 {
5306 t_int64 dividend = (t_int64) (SIGNEXT36_64 (cpu.rQ));
5307 t_int64 divisor = (t_int64) (SIGNEXT36_64 (cpu.CY));
5308 #if defined(TESTING)
5309 # if defined(DIV_TRACE)
5310 sim_debug (DBG_CAC, & cpu_dev, "\r\n");
5311 sim_debug (DBG_CAC, & cpu_dev,
5312 ">>> dividend cpu.rQ %"PRId64" (%012"PRIo64")\r\n",
5313 dividend, cpu.rQ);
5314 sim_debug (DBG_CAC, & cpu_dev,
5315 ">>> divisor CY %"PRId64" (%012"PRIo64")\r\n",
5316 divisor, cpu.CY);
5317 # endif
5318 #endif
5319
5320 t_int64 quotient = dividend / divisor;
5321 L68_ (cpu.ou.cycle |= ou_GD2;)
5322 t_int64 remainder = dividend % divisor;
5323 #if defined(TESTING)
5324 # if defined(DIV_TRACE)
5325 sim_debug (DBG_CAC, & cpu_dev, ">>> quot 1 %"PRId64"\r\n", quotient);
5326 sim_debug (DBG_CAC, & cpu_dev, ">>> rem 1 %"PRId64"\r\n", remainder);
5327 # endif
5328 #endif
5329
5330 // Evidence is that DPS8M rounds toward zero; if it turns out that it
5331 // rounds toward -inf, try this code:
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349 #if defined(TESTING)
5350 # if defined(DIV_TRACE)
5351 // (a/b)*b + a%b is equal to a.
5352 sim_debug (DBG_CAC, & cpu_dev,
5353 "dividend was = %"PRId64"\r\n", dividend);
5354 sim_debug (DBG_CAC, & cpu_dev,
5355 "quotient * divisor + remainder = %"PRId64"\r\n",
5356 quotient * divisor + remainder);
5357 if (dividend != quotient * divisor + remainder)
5358 {
5359 sim_debug (DBG_CAC, & cpu_dev,
5360 "---------------------------------^^^^^^^^^^^^^^^\r\n");
5361 }
5362 # endif
5363 #endif
5364
5365 if (dividend != quotient * divisor + remainder)
5366 {
5367 sim_debug (DBG_ERR, & cpu_dev,
5368 "Internal division error;"
5369 " rQ %012"PRIo64" CY %012"PRIo64"\r\n", cpu.rQ, cpu.CY);
5370 }
5371
5372 cpu.rA = (word36) remainder & DMASK;
5373 cpu.rQ = (word36) quotient & DMASK;
5374 #if defined(TESTING)
5375 HDBGRegAW ("div");
5376 HDBGRegQW ("div");
5377
5378 # if defined(DIV_TRACE)
5379 sim_debug (DBG_CAC, & cpu_dev, "rA (rem) %012"PRIo64"\r\n", cpu.rA);
5380 sim_debug (DBG_CAC, & cpu_dev, "rQ (quot) %012"PRIo64"\r\n", cpu.rQ);
5381 # endif
5382 #endif
5383
5384 SC_I_ZERO (cpu.rQ == 0);
5385 SC_I_NEG (cpu.rQ & SIGN36);
5386 }
5387
5388 break;
5389
5390 case x0 (0507): // dvf
5391 // C(AQ) / (Y)
5392 // fractional quotient -> C(A)
5393 // fractional remainder -> C(Q)
5394
5395 // A 71-bit fractional dividend (including sign) is divided by a
5396 // 36-bit fractional divisor yielding a 36-bit fractional quotient
5397 // (including sign) and a 36-bit fractional remainder (including
5398 // sign). C(AQ)71 is ignored; bit position 35 of the remainder
5399 // corresponds to bit position 70 of the dividend. The remainder
5400 // sign is equal to the dividend sign unless the remainder is zero.
5401
5402 // If | dividend | >= | divisor | or if the divisor = 0, division
5403 // does not take place. Instead, a divide check fault occurs, C(AQ)
5404 // contains the dividend magnitude in absolute, and the negative
5405 // indicator reflects the dividend sign.
5406
5407 dvf (cpup);
5408
5409 break;
5410
5411 /// Fixed-Point Negate
5412
5413 case x0 (0531): // neg
5414 // -C(A) -> C(A) if C(A) != 0
5415
5416 #if defined(TESTING)
5417 HDBGRegAR ("neg");
5418 #endif
5419 cpu.rA &= DMASK;
5420 if (cpu.rA == 0400000000000ULL)
5421 {
5422 CLR_I_ZERO;
5423 SET_I_NEG;
5424 overflow (cpup, true, false, "neg overflow fault");
5425 }
5426
5427 //cpu.rA = -cpu.rA;
5428 // ubsan
5429 cpu.rA = (word36) (- (word36s) cpu.rA);
5430
5431 cpu.rA &= DMASK; // keep to 36-bits
5432 #if defined(TESTING)
5433 HDBGRegAW ("neg");
5434 #endif
5435
5436 SC_I_ZERO (cpu.rA == 0);
5437 SC_I_NEG (cpu.rA & SIGN36);
5438
5439 break;
5440
5441 case x0 (0533): // negl
5442 // -C(AQ) -> C(AQ) if C(AQ) != 0
5443 {
5444 #if defined(TESTING)
5445 HDBGRegAR ("negl");
5446 HDBGRegQR ("negl");
5447 #endif
5448 cpu.rA &= DMASK;
5449 cpu.rQ &= DMASK;
5450
5451 if (cpu.rA == 0400000000000ULL && cpu.rQ == 0)
5452 {
5453 CLR_I_ZERO;
5454 SET_I_NEG;
5455 overflow (cpup, true, false, "negl overflow fault");
5456 }
5457
5458 word72 tmp72 = convert_to_word72 (cpu.rA, cpu.rQ);
5459 #if defined(NEED_128)
5460 tmp72 = negate_128 (tmp72);
5461
5462 SC_I_ZERO (iszero_128 (tmp72));
5463 SC_I_NEG (isnonzero_128 (and_128 (tmp72, SIGN72)));
5464 #else
5465 //tmp72 = -tmp72;
5466 // ubsan
5467 tmp72 = (word72) (-(word72s) tmp72);
5468
5469 SC_I_ZERO (tmp72 == 0);
5470 SC_I_NEG (tmp72 & SIGN72);
5471 #endif
5472
5473 convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5474 #if defined(TESTING)
5475 HDBGRegAW ("negl");
5476 HDBGRegQW ("negl");
5477 #endif
5478 }
5479 break;
5480
5481 /// Fixed-Point Comparison
5482
5483 case x0 (0405): // cmg
5484 // | C(A) | :: | C(Y) |
5485 // Zero: If | C(A) | = | C(Y) | , then ON; otherwise OFF
5486 // Negative: If | C(A) | < | C(Y) | , then ON; otherwise OFF
5487 {
5488 // This is wrong for MAXNEG
5489 //word36 a = cpu.rA & SIGN36 ? -cpu.rA : cpu.rA;
5490 //word36 y = cpu.CY & SIGN36 ? -cpu.CY : cpu.CY;
5491
5492 // If we do the 64 math, the MAXNEG case works
5493 #if defined(TESTING)
5494 HDBGRegAR ("cmg");
5495 #endif
5496 t_int64 a = SIGNEXT36_64 (cpu.rA);
5497 if (a < 0)
5498 a = -a;
5499 t_int64 y = SIGNEXT36_64 (cpu.CY);
5500 if (y < 0)
5501 y = -y;
5502
5503 SC_I_ZERO (a == y);
5504 SC_I_NEG (a < y);
5505 }
5506 break;
5507
5508 case x0 (0211): // cmk
5509 // For i = 0, 1, ..., 35
5510 // C(Z)i = ~C(Q)i & ( C(A)i XOR C(Y)i )
5511
5512 /*
5513 * The cmk instruction compares the contents of bit positions of A
5514 * and Y for identity that are not masked by a 1 in the
5515 * corresponding bit position of Q.
5516 *
5517 * The zero indicator is set ON if the comparison is successful for
5518 * all bit positions; i.e., if for all i = 0, 1, ..., 35 there is
5519 * either: C(A)i = C(Y)i (the identical case) or C(Q)i = 1 (the
5520 * masked case); otherwise, the zero indicator is set OFF.
5521 *
5522 * The negative indicator is set ON if the comparison is
5523 * unsuccessful for bit position 0; i.e., if C(A)0 XOR C(Y)0 (they
5524 * are nonidentical) as well as C(Q)0 = 0 (they are unmasked);
5525 * otherwise, the negative indicator is set OFF.
5526 */
5527 {
5528 #if defined(TESTING)
5529 HDBGRegAR ("cmk");
5530 HDBGRegQR ("cmk");
5531 HDBGRegYR ("cmk");
5532 #endif
5533 word36 Z = ~cpu.rQ & (cpu.rA ^ cpu.CY);
5534 Z &= DMASK;
5535 #if defined(TESTING)
5536 HDBGRegZW (Z, "cmk");
5537 HDBGRegIR ("cmk");
5538 #endif
5539
5540 // Q A Y ~Q A^Y Z
5541 // 0 0 0 1 0 0
5542 // 0 0 1 1 1 1
5543 // 0 1 0 1 1 1
5544 // 0 1 1 1 0 0
5545 // 1 0 0 0 0 0
5546 // 1 0 1 0 1 0
5547 // 1 1 0 0 1 0
5548 // 1 1 1 0 0 0
5549
5550 SC_I_ZERO (Z == 0);
5551 SC_I_NEG (Z & SIGN36);
5552 }
5553 break;
5554
5555 // Optimized to the top of the loop
5556 // case x0 (0115): // cmpa
5557
5558 case x0 (0117): // cmpaq
5559 // C(AQ) :: C(Y-pair)
5560 {
5561 #if defined(TESTING)
5562 HDBGRegAR ("cmpaq");
5563 HDBGRegQR ("cmpaq");
5564 #endif
5565 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5566 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5567 #if defined(NEED_128)
5568 trAQ = and_128 (trAQ, MASK72);
5569 #else
5570 trAQ &= MASK72;
5571 #endif
5572 cmp72 (cpup, trAQ, tmp72, &cpu.cu.IR);
5573 }
5574 break;
5575
5576 // Optimized to the top of the loop
5577 // case x0 (0116): // cmpq
5578
5579 // cmpxn
5580 case x0 (0100): // cmpx0
5581 case x0 (0101): // cmpx1
5582 case x0 (0102): // cmpx2
5583 case x0 (0103): // cmpx3
5584 case x0 (0104): // cmpx4
5585 case x0 (0105): // cmpx5
5586 case x0 (0106): // cmpx6
5587 case x0 (0107): // cmpx7
5588 // For n = 0, 1, ..., or 7 as determined by operation code
5589 // C(Xn) :: C(Y)0,17
5590 {
5591 uint32 n = opcode10 & 07; // get n
5592 #if defined(TESTING)
5593 HDBGRegXR (n, "cmpxn");
5594 #endif
5595 cmp18 (cpup, cpu.rX[n], GETHI (cpu.CY), &cpu.cu.IR);
5596 }
5597 break;
5598
5599 case x0 (0111): // cwl
5600 // C(Y) :: closed interval [C(A);C(Q)]
5601 /*
5602 * The cwl instruction tests the value of C(Y) to determine if it
5603 * is within the range of values set by C(A) and C(Q). The
5604 * comparison of C(Y) with C(Q) locates C(Y) with respect to the
5605 * interval if C(Y) is not contained within the interval.
5606 */
5607 #if defined(TESTING)
5608 HDBGRegAR ("cwl");
5609 HDBGRegQR ("cwl");
5610 #endif
5611 cmp36wl (cpup, cpu.rA, cpu.CY, cpu.rQ, &cpu.cu.IR);
5612 break;
5613
5614 /// Fixed-Point Miscellaneous
5615
5616 case x0 (0234): // szn
5617 // Set indicators according to C(Y)
5618 cpu.CY &= DMASK;
5619 SC_I_ZERO (cpu.CY == 0);
5620 SC_I_NEG (cpu.CY & SIGN36);
5621 break;
5622
5623 case x0 (0214): // sznc
5624 // Set indicators according to C(Y)
5625 cpu.CY &= DMASK;
5626 SC_I_ZERO (cpu.CY == 0);
5627 SC_I_NEG (cpu.CY & SIGN36);
5628 // ... and clear
5629 cpu.CY = 0;
5630 break;
5631
5632 /// BOOLEAN OPERATION INSTRUCTIONS
5633
5634 /// Boolean And
5635
5636 // Optimized to the top of the loop
5637 // case x0 (0375): // ana
5638
5639 // Optimized to the top of the loop
5640 // case x0 (0377): //< anaq
5641
5642 case x0 (0376): // anq
5643 // C(Q)i & C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5644 #if defined(TESTING)
5645 HDBGRegQR ("anq");
5646 #endif
5647 cpu.rQ = cpu.rQ & cpu.CY;
5648 cpu.rQ &= DMASK;
5649 #if defined(TESTING)
5650 HDBGRegQW ("anq");
5651 #endif
5652
5653 SC_I_ZERO (cpu.rQ == 0);
5654 SC_I_NEG (cpu.rQ & SIGN36);
5655 break;
5656
5657 case x0 (0355): // ansa
5658 // C(A)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5659 {
5660 #if defined(TESTING)
5661 HDBGRegAR ("ansa");
5662 #endif
5663 cpu.CY = cpu.rA & cpu.CY;
5664 cpu.CY &= DMASK;
5665
5666 SC_I_ZERO (cpu.CY == 0);
5667 SC_I_NEG (cpu.CY & SIGN36);
5668 }
5669 break;
5670
5671 case x0 (0356): // ansq
5672 // C(Q)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5673 {
5674 #if defined(TESTING)
5675 HDBGRegQR ("ansq");
5676 #endif
5677 cpu.CY = cpu.rQ & cpu.CY;
5678 cpu.CY &= DMASK;
5679
5680 SC_I_ZERO (cpu.CY == 0);
5681 SC_I_NEG (cpu.CY & SIGN36);
5682 }
5683 break;
5684
5685 // ansxn
5686 case x0 (0340): // ansx0
5687 case x0 (0341): // ansx1
5688 case x0 (0342): // ansx2
5689 case x0 (0343): // ansx3
5690 case x0 (0344): // ansx4
5691 case x0 (0345): // ansx5
5692 case x0 (0346): // ansx6
5693 case x0 (0347): // ansx7
5694 // For n = 0, 1, ..., or 7 as determined by operation code
5695 // C(Xn)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5696 {
5697 uint32 n = opcode10 & 07; // get n
5698 #if defined(TESTING)
5699 HDBGRegXR (n, "ansxn");
5700 #endif
5701 word18 tmp18 = cpu.rX[n] & GETHI (cpu.CY);
5702 tmp18 &= MASK18;
5703
5704 SC_I_ZERO (tmp18 == 0);
5705 SC_I_NEG (tmp18 & SIGN18);
5706
5707 SETHI (cpu.CY, tmp18);
5708 }
5709
5710 break;
5711
5712 // anxn
5713 case x0 (0360): // anx0
5714 case x0 (0361): // anx1
5715 case x0 (0362): // anx2
5716 case x0 (0363): // anx3
5717 case x0 (0364): // anx4
5718 case x0 (0365): // anx5
5719 case x0 (0366): // anx6
5720 case x0 (0367): // anx7
5721 // For n = 0, 1, ..., or 7 as determined by operation code
5722 // C(Xn)i & C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5723 {
5724 uint32 n = opcode10 & 07; // get n
5725 #if defined(TESTING)
5726 HDBGRegXR (n, "anxn");
5727 #endif
5728 cpu.rX[n] &= GETHI (cpu.CY);
5729 cpu.rX[n] &= MASK18;
5730 #if defined(TESTING)
5731 HDBGRegXW (n, "anxn");
5732 #endif
5733
5734 SC_I_ZERO (cpu.rX[n] == 0);
5735 SC_I_NEG (cpu.rX[n] & SIGN18);
5736 }
5737 break;
5738
5739 /// Boolean Or
5740
5741 // Optimized to the top of the loop
5742 // case x0 (0275): // ora
5743
5744 case x0 (0277): // oraq
5745 // C(AQ)i | C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
5746 {
5747 #if defined(TESTING)
5748 HDBGRegAR ("oraq");
5749 HDBGRegQR ("oraq");
5750 #endif
5751 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5752 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5753 #if defined(NEED_128)
5754 trAQ = or_128 (trAQ, tmp72);
5755 trAQ = and_128 (trAQ, MASK72);
5756
5757 SC_I_ZERO (iszero_128 (trAQ));
5758 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
5759 #else
5760 trAQ = trAQ | tmp72;
5761 trAQ &= MASK72;
5762
5763 SC_I_ZERO (trAQ == 0);
5764 SC_I_NEG (trAQ & SIGN72);
5765 #endif
5766 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
5767 #if defined(TESTING)
5768 HDBGRegAW ("oraq");
5769 HDBGRegQW ("oraq");
5770 #endif
5771 }
5772 break;
5773
5774 case x0 (0276): // orq
5775 // C(Q)i | C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5776 #if defined(TESTING)
5777 HDBGRegQR ("orq");
5778 #endif
5779 cpu.rQ = cpu.rQ | cpu.CY;
5780 cpu.rQ &= DMASK;
5781 #if defined(TESTING)
5782 HDBGRegQW ("orq");
5783 #endif
5784
5785 SC_I_ZERO (cpu.rQ == 0);
5786 SC_I_NEG (cpu.rQ & SIGN36);
5787
5788 break;
5789
5790 case x0 (0255): // orsa
5791 // C(A)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5792 #if defined(TESTING)
5793 HDBGRegAR ("orsa");
5794 #endif
5795 cpu.CY = cpu.rA | cpu.CY;
5796 cpu.CY &= DMASK;
5797
5798 SC_I_ZERO (cpu.CY == 0);
5799 SC_I_NEG (cpu.CY & SIGN36);
5800 break;
5801
5802 case x0 (0256): // orsq
5803 // C(Q)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5804 #if defined(TESTING)
5805 HDBGRegQR ("orsq");
5806 #endif
5807 cpu.CY = cpu.rQ | cpu.CY;
5808 cpu.CY &= DMASK;
5809
5810 SC_I_ZERO (cpu.CY == 0);
5811 SC_I_NEG (cpu.CY & SIGN36);
5812 break;
5813
5814 // orsxn
5815 case x0 (0240): // orsx0
5816 case x0 (0241): // orsx1
5817 case x0 (0242): // orsx2
5818 case x0 (0243): // orsx3
5819 case x0 (0244): // orsx4
5820 case x0 (0245): // orsx5
5821 case x0 (0246): // orsx6
5822 case x0 (0247): // orsx7
5823 // For n = 0, 1, ..., or 7 as determined by operation code
5824 // C(Xn)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5825 {
5826 uint32 n = opcode10 & 07; // get n
5827
5828 word18 tmp18 = cpu.rX[n] | GETHI (cpu.CY);
5829 tmp18 &= MASK18;
5830
5831 SC_I_ZERO (tmp18 == 0);
5832 SC_I_NEG (tmp18 & SIGN18);
5833
5834 SETHI (cpu.CY, tmp18);
5835 }
5836 break;
5837
5838 // orxn
5839 case x0 (0260): // orx0
5840 case x0 (0261): // orx1
5841 case x0 (0262): // orx2
5842 case x0 (0263): // orx3
5843 case x0 (0264): // orx4
5844 case x0 (0265): // orx5
5845 case x0 (0266): // orx6
5846 case x0 (0267): // orx7
5847 // For n = 0, 1, ..., or 7 as determined by operation code
5848 // C(Xn)i | C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5849 {
5850 uint32 n = opcode10 & 07; // get n
5851 #if defined(TESTING)
5852 HDBGRegXR (n, "orxn");
5853 #endif
5854 cpu.rX[n] |= GETHI (cpu.CY);
5855 cpu.rX[n] &= MASK18;
5856 #if defined(TESTING)
5857 HDBGRegXW (n, "orxn");
5858 #endif
5859
5860 SC_I_ZERO (cpu.rX[n] == 0);
5861 SC_I_NEG (cpu.rX[n] & SIGN18);
5862 }
5863 break;
5864
5865 /// Boolean Exclusive Or
5866
5867 case x0 (0675): // era
5868 // C(A)i XOR C(Y)i -> C(A)i for i = (0, 1, ..., 35)
5869 #if defined(TESTING)
5870 HDBGRegAR ("era");
5871 #endif
5872 cpu.rA = cpu.rA ^ cpu.CY;
5873 cpu.rA &= DMASK;
5874 #if defined(TESTING)
5875 HDBGRegAW ("era");
5876 #endif
5877
5878 SC_I_ZERO (cpu.rA == 0);
5879 SC_I_NEG (cpu.rA & SIGN36);
5880
5881 break;
5882
5883 // Optimized to the top of the loop
5884 // case x0 (0677): // eraq
5885
5886 case x0 (0676): // erq
5887 // C(Q)i XOR C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5888 #if defined(TESTING)
5889 HDBGRegQR ("eraq");
5890 #endif
5891 cpu.rQ = cpu.rQ ^ cpu.CY;
5892 cpu.rQ &= DMASK;
5893 #if defined(TESTING)
5894 HDBGRegQW ("eraq");
5895 #endif
5896 SC_I_ZERO (cpu.rQ == 0);
5897 SC_I_NEG (cpu.rQ & SIGN36);
5898 break;
5899
5900 case x0 (0655): // ersa
5901 // C(A)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5902 #if defined(TESTING)
5903 HDBGRegAR ("ersa");
5904 #endif
5905 cpu.CY = cpu.rA ^ cpu.CY;
5906 cpu.CY &= DMASK;
5907
5908 SC_I_ZERO (cpu.CY == 0);
5909 SC_I_NEG (cpu.CY & SIGN36);
5910 break;
5911
5912 case x0 (0656): // ersq
5913 // C(Q)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5914 #if defined(TESTING)
5915 HDBGRegQR ("ersq");
5916 #endif
5917 cpu.CY = cpu.rQ ^ cpu.CY;
5918 cpu.CY &= DMASK;
5919
5920 SC_I_ZERO (cpu.CY == 0);
5921 SC_I_NEG (cpu.CY & SIGN36);
5922
5923 break;
5924
5925 // ersxn
5926 case x0 (0640): // ersx0
5927 case x0 (0641): // ersx1
5928 case x0 (0642): // ersx2
5929 case x0 (0643): // ersx3
5930 case x0 (0644): // ersx4
5931 case x0 (0645): // ersx5
5932 case x0 (0646): // ersx6
5933 case x0 (0647): // ersx7
5934 // For n = 0, 1, ..., or 7 as determined by operation code
5935 // C(Xn)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5936 {
5937 uint32 n = opcode10 & 07; // get n
5938 #if defined(TESTING)
5939 HDBGRegXR (n, "ersxn");
5940 #endif
5941
5942 word18 tmp18 = cpu.rX[n] ^ GETHI (cpu.CY);
5943 tmp18 &= MASK18;
5944
5945 SC_I_ZERO (tmp18 == 0);
5946 SC_I_NEG (tmp18 & SIGN18);
5947
5948 SETHI (cpu.CY, tmp18);
5949 }
5950 break;
5951
5952 // erxn
5953 case x0 (0660): // erx0
5954 case x0 (0661): // erx1
5955 case x0 (0662): // erx2
5956 case x0 (0663): // erx3
5957 case x0 (0664): // erx4
5958 case x0 (0665): // erx5
5959 case x0 (0666): // erx6 !!!! Beware !!!!
5960 case x0 (0667): // erx7
5961 // For n = 0, 1, ..., or 7 as determined by operation code
5962 // C(Xn)i XOR C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5963 {
5964 uint32 n = opcode10 & 07; // get n
5965 #if defined(TESTING)
5966 HDBGRegXR (n, "erxn");
5967 #endif
5968 cpu.rX[n] ^= GETHI (cpu.CY);
5969 cpu.rX[n] &= MASK18;
5970 #if defined(TESTING)
5971 HDBGRegXW (n, "erxn");
5972 #endif
5973
5974 SC_I_ZERO (cpu.rX[n] == 0);
5975 SC_I_NEG (cpu.rX[n] & SIGN18);
5976 }
5977 break;
5978
5979 /// Boolean Comparative And
5980
5981 // Optimized to the top of the loop
5982 // case x0 (0315): // cana
5983
5984 case x0 (0317): // canaq
5985 // C(Z)i = C(AQ)i & C(Y-pair)i for i = (0, 1, ..., 71)
5986 {
5987 #if defined(TESTING)
5988 HDBGRegAR ("canaq");
5989 HDBGRegQR ("canaq");
5990 #endif
5991 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5992 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5993 #if defined(NEED_128)
5994 trAQ = and_128 (trAQ, tmp72);
5995 trAQ = and_128 (trAQ, MASK72);
5996
5997 SC_I_ZERO (iszero_128 (trAQ));
5998 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
5999 #else
6000 trAQ = trAQ & tmp72;
6001 trAQ &= MASK72;
6002
6003 SC_I_ZERO (trAQ == 0);
6004 SC_I_NEG (trAQ & SIGN72);
6005 #endif
6006 }
6007 break;
6008
6009 case x0 (0316): // canq
6010 // C(Z)i = C(Q)i & C(Y)i for i = (0, 1, ..., 35)
6011 {
6012 #if defined(TESTING)
6013 HDBGRegQR ("canq");
6014 #endif
6015 word36 trZ = cpu.rQ & cpu.CY;
6016 trZ &= DMASK;
6017
6018 SC_I_ZERO (trZ == 0);
6019 SC_I_NEG (trZ & SIGN36);
6020 }
6021 break;
6022
6023 // canxn
6024 case x0 (0300): // canx0
6025 case x0 (0301): // canx1
6026 case x0 (0302): // canx2
6027 case x0 (0303): // canx3
6028 case x0 (0304): // canx4
6029 case x0 (0305): // canx5
6030 case x0 (0306): // canx6
6031 case x0 (0307): // canx7
6032 // For n = 0, 1, ..., or 7 as determined by operation code
6033 // C(Z)i = C(Xn)i & C(Y)i for i = (0, 1, ..., 17)
6034 {
6035 uint32 n = opcode10 & 07; // get n
6036 #if defined(TESTING)
6037 HDBGRegXR (n, "canxn");
6038 #endif
6039 word18 tmp18 = cpu.rX[n] & GETHI (cpu.CY);
6040 tmp18 &= MASK18;
6041 sim_debug (DBG_TRACEEXT, & cpu_dev,
6042 "n %o rX %06o HI %06o tmp %06o\r\n",
6043 n, cpu.rX[n], (word18) (GETHI (cpu.CY) & MASK18),
6044 tmp18);
6045
6046 SC_I_ZERO (tmp18 == 0);
6047 SC_I_NEG (tmp18 & SIGN18);
6048 }
6049 break;
6050
6051 /// Boolean Comparative Not
6052
6053 case x0 (0215): // cnaa
6054 // C(Z)i = C(A)i & ~C(Y)i for i = (0, 1, ..., 35)
6055 {
6056 #if defined(TESTING)
6057 HDBGRegAR ("cnaa");
6058 #endif
6059 word36 trZ = cpu.rA & ~cpu.CY;
6060 trZ &= DMASK;
6061
6062 SC_I_ZERO (trZ == 0);
6063 SC_I_NEG (trZ & SIGN36);
6064 }
6065 break;
6066
6067 case x0 (0217): // cnaaq
6068 // C(Z)i = C (AQ)i & ~C(Y-pair)i for i = (0, 1, ..., 71)
6069 {
6070 #if defined(TESTING)
6071 HDBGRegAR ("cnaaq");
6072 HDBGRegQR ("cnaaq");
6073 #endif
6074 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
6075
6076 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
6077 #if defined(NEED_128)
6078 trAQ = and_128 (trAQ, complement_128 (tmp72));
6079 trAQ = and_128 (trAQ, MASK72);
6080
6081 SC_I_ZERO (iszero_128 (trAQ));
6082 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
6083 #else
6084 trAQ = trAQ & ~tmp72;
6085 trAQ &= MASK72;
6086
6087 SC_I_ZERO (trAQ == 0);
6088 SC_I_NEG (trAQ & SIGN72);
6089 #endif
6090 }
6091 break;
6092
6093 case x0 (0216): // cnaq
6094 // C(Z)i = C(Q)i & ~C(Y)i for i = (0, 1, ..., 35)
6095 {
6096 #if defined(TESTING)
6097 HDBGRegQR ("cnaq");
6098 #endif
6099 word36 trZ = cpu.rQ & ~cpu.CY;
6100 trZ &= DMASK;
6101 SC_I_ZERO (trZ == 0);
6102 SC_I_NEG (trZ & SIGN36);
6103 }
6104 break;
6105
6106 // cnaxn
6107 case x0 (0200): // cnax0
6108 case x0 (0201): // cnax1
6109 case x0 (0202): // cnax2
6110 case x0 (0203): // cnax3
6111 case x0 (0204): // cnax4
6112 case x0 (0205): // cnax5
6113 case x0 (0206): // cnax6
6114 case x0 (0207): // cnax7
6115 // C(Z)i = C(Xn)i & ~C(Y)i for i = (0, 1, ..., 17)
6116 {
6117 uint32 n = opcode10 & 07; // get n
6118 #if defined(TESTING)
6119 HDBGRegXR (n, "cnaxn");
6120 #endif
6121 word18 tmp18 = cpu.rX[n] & ~GETHI (cpu.CY);
6122 tmp18 &= MASK18;
6123
6124 SC_I_ZERO (tmp18 == 0);
6125 SC_I_NEG (tmp18 & SIGN18);
6126 }
6127 break;
6128
6129 /// FLOATING-POINT ARITHMETIC INSTRUCTIONS
6130
6131 /// Floating-Point Data Movement Load
6132
6133 case x0 (0433): // dfld
6134 // C(Y-pair)0,7 -> C(E)
6135 // C(Y-pair)8,71 -> C(AQ)0,63
6136 // 00...0 -> C(AQ)64,71
6137 // Zero: If C(AQ) = 0, then ON; otherwise OFF
6138 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
6139
6140 CPTUR (cptUseE);
6141 cpu.rE = (cpu.Ypair[0] >> 28) & MASK8;
6142
6143 cpu.rA = (cpu.Ypair[0] & FLOAT36MASK) << 8;
6144 cpu.rA |= (cpu.Ypair[1] >> 28) & MASK8;
6145
6146 cpu.rQ = (cpu.Ypair[1] & FLOAT36MASK) << 8;
6147
6148 #if defined(TESTING)
6149 HDBGRegAW ("dfld");
6150 HDBGRegQW ("dfld");
6151 #endif
6152
6153 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
6154 SC_I_NEG (cpu.rA & SIGN36);
6155 break;
6156
6157 // Optimized to the top of the loop
6158 // case x0 (0431): // fld
6159
6160 /// Floating-Point Data Movement Store
6161
6162 case x0 (0457): // dfst
6163 // C(E) -> C(Y-pair)0,7
6164 // C(AQ)0,63 -> C(Y-pair)8,71
6165
6166 CPTUR (cptUseE);
6167 #if defined(TESTING)
6168 HDBGRegAR ("dfst");
6169 HDBGRegQR ("dfst");
6170 #endif
6171 cpu.Ypair[0] = ((word36)cpu.rE << 28) |
6172 ((cpu.rA & 0777777777400LLU) >> 8);
6173 cpu.Ypair[1] = ((cpu.rA & 0377) << 28) |
6174 ((cpu.rQ & 0777777777400LLU) >> 8);
6175
6176 break;
6177
6178 case x0 (0472): // dfstr
6179
6180 dfstr (cpup, cpu.Ypair);
6181 break;
6182
6183 case x0 (0455): // fst
6184 // C(E) -> C(Y)0,7
6185 // C(A)0,27 -> C(Y)8,35
6186 CPTUR (cptUseE);
6187 #if defined(TESTING)
6188 HDBGRegAR ("fst");
6189 #endif
6190 cpu.rE &= MASK8;
6191 cpu.rA &= DMASK;
6192 cpu.CY = ((word36)cpu.rE << 28) | (((cpu.rA >> 8) & 01777777777LL));
6193 break;
6194
6195 case x0 (0470): // fstr
6196 // The fstr instruction performs a true round and normalization on
6197 // C(EAQ) as it is stored.
6198
6199 // frd ();
6200 //
6201 // // C(E) -> C(Y)0,7
6202 // // C(A)0,27 -> C(Y)8,35
6203 // cpu.CY = ((word36)cpu.rE << 28) |
6204 // (((cpu.rA >> 8) & 01777777777LL));
6205 //
6206 // // Zero: If C(Y) = floating point 0, then ON; otherwise OFF
6207 // //SC_I_ZERO ((cpu.CY & 01777777777LL) == 0);
6208 // bool isZero = cpu.rE == -128 && cpu.rA == 0;
6209 // SC_I_ZERO (isZero);
6210 //
6211 // // Neg: If C(Y)8 = 1, then ON; otherwise OFF
6212 // //SC_I_NEG (cpu.CY & 01000000000LL);
6213 // SC_I_NEG (cpu.rA & SIGN36);
6214 //
6215 // // Exp Ovr: If exponent is greater than +127, then ON
6216 // // Exp Undr: If exponent is less than -128, then ON
6217 // // XXX: not certain how these can occur here ....
6218
6219 fstr (cpup, &cpu.CY);
6220
6221 break;
6222
6223 /// Floating-Point Addition
6224
6225 case x0 (0477): // dfad
6226 // The dfad instruction may be thought of as a dufa instruction
6227 // followed by a fno instruction.
6228
6229 CPTUR (cptUseE);
6230 #if defined(TESTING)
6231 HDBGRegAR ("dfad");
6232 HDBGRegQR ("dfad");
6233 #endif
6234 dufa (cpup, false, true);
6235 #if defined(TESTING)
6236 HDBGRegAW ("dfad");
6237 HDBGRegQW ("dfad");
6238 #endif
6239 break;
6240
6241 case x0 (0437): // dufa
6242 dufa (cpup, false, false);
6243 break;
6244
6245 case x0 (0475): // fad
6246 // The fad instruction may be thought of a an ufa instruction
6247 // followed by a fno instruction.
6248 // (Heh, heh. We'll see....)
6249
6250 CPTUR (cptUseE);
6251 #if defined(TESTING)
6252 HDBGRegAR ("fad");
6253 HDBGRegQR ("fad");
6254 #endif
6255 ufa (cpup, false, true);
6256 #if defined(TESTING)
6257 HDBGRegAW ("fad");
6258 HDBGRegQW ("fad");
6259 #endif
6260
6261 break;
6262
6263 case x0 (0435): // ufa
6264 // C(EAQ) + C(Y) -> C(EAQ)
6265
6266 ufa (cpup, false, false);
6267 break;
6268
6269 /// Floating-Point Subtraction
6270
6271 case x0 (0577): // dfsb
6272 // The dfsb instruction is identical to the dfad instruction with
6273 // the exception that the twos complement of the mantissa of the
6274 // operand from main memory is used.
6275
6276 CPTUR (cptUseE);
6277 #if defined(TESTING)
6278 HDBGRegAR ("dfsb");
6279 HDBGRegQR ("dfsb");
6280 #endif
6281 dufa (cpup, true, true);
6282 #if defined(TESTING)
6283 HDBGRegAW ("dfsb");
6284 HDBGRegQW ("dfsb");
6285 #endif
6286 break;
6287
6288 case x0 (0537): // dufs
6289 dufa (cpup, true, false);
6290 break;
6291
6292 case x0 (0575): // fsb
6293 // The fsb instruction may be thought of as an ufs instruction
6294 // followed by a fno instruction.
6295 #if defined(TESTING)
6296 HDBGRegAR ("fsb");
6297 HDBGRegQR ("fsb");
6298 #endif
6299 CPTUR (cptUseE);
6300 ufa (cpup, true, true);
6301 #if defined(TESTING)
6302 HDBGRegAW ("fsb");
6303 HDBGRegQW ("fsb");
6304 #endif
6305 break;
6306
6307 case x0 (0535): // ufs
6308 // C(EAQ) - C(Y) -> C(EAQ)
6309 ufa (cpup, true, false);
6310 break;
6311
6312 /// Floating-Point Multiplication
6313
6314 case x0 (0463): // dfmp
6315 // The dfmp instruction may be thought of as a dufm instruction
6316 // followed by a fno instruction.
6317
6318 CPTUR (cptUseE);
6319 #if defined(TESTING)
6320 HDBGRegAR ("dfmp");
6321 HDBGRegQR ("dfmp");
6322 #endif
6323 dufm (cpup, true);
6324 #if defined(TESTING)
6325 HDBGRegAW ("dfmp");
6326 HDBGRegQW ("dfmp");
6327 #endif
6328 break;
6329
6330 case x0 (0423): // dufm
6331
6332 dufm (cpup, false);
6333 break;
6334
6335 case x0 (0461): // fmp
6336 // The fmp instruction may be thought of as a ufm instruction
6337 // followed by a fno instruction.
6338
6339 CPTUR (cptUseE);
6340 ufm (cpup, true);
6341 #if defined(TESTING)
6342 HDBGRegAW ("fmp");
6343 HDBGRegQW ("fmp");
6344 #endif
6345 break;
6346
6347 case x0 (0421): // ufm
6348 // C(EAQ)* C(Y) -> C(EAQ)
6349 ufm (cpup, false);
6350 break;
6351
6352 /// Floating-Point Division
6353
6354 case x0 (0527): // dfdi
6355
6356 dfdi (cpup);
6357 break;
6358
6359 case x0 (0567): // dfdv
6360
6361 dfdv (cpup);
6362 break;
6363
6364 case x0 (0525): // fdi
6365 // C(Y) / C(EAQ) -> C(EA)
6366
6367 fdi (cpup);
6368 break;
6369
6370 case x0 (0565): // fdv
6371 // C(EAQ) /C(Y) -> C(EA)
6372 // 00...0 -> C(Q)
6373 fdv (cpup);
6374 break;
6375
6376 /// Floating-Point Negation
6377
6378 case x0 (0513): // fneg
6379 // -C(EAQ) normalized -> C(EAQ)
6380 fneg (cpup);
6381 break;
6382
6383 /// Floating-Point Normalize
6384
6385 case x0 (0573): // fno
6386 // The fno instruction normalizes the number in C(EAQ) if C(AQ)
6387 // != 0 and the overflow indicator is OFF.
6388 //
6389 // A normalized floating number is defined as one whose mantissa
6390 // lies in the interval [0.5,1.0) such that 0.5<= |C(AQ)| <1.0
6391 // which, in turn, requires that C(AQ)0 != C(AQ)1.list
6392 //
6393 // !!!! For personal reasons the following 3 lines of comment must
6394 // never be removed from this program or any code derived
6395 // there from. HWR 25 Aug 2014
6396 ///Charles Is the coolest
6397 ///true story y'all
6398 //you should get me darksisers 2 for christmas
6399
6400 CPTUR (cptUseE);
6401 fno (cpup, & cpu.rE, & cpu.rA, & cpu.rQ);
6402 #if defined(TESTING)
6403 HDBGRegAW ("fno");
6404 HDBGRegQW ("fno");
6405 #endif
6406 break;
6407
6408 /// Floating-Point Round
6409
6410 case x0 (0473): // dfrd
6411 // C(EAQ) rounded to 64 bits -> C(EAQ)
6412 // 0 -> C(AQ)64,71 (See notes in dps8_math.c on dfrd())
6413
6414 dfrd (cpup);
6415 break;
6416
6417 case x0 (0471): // frd
6418 // C(EAQ) rounded to 28 bits -> C(EAQ)
6419 // 0 -> C(AQ)28,71 (See notes in dps8_math.c on frd())
6420
6421 frd (cpup);
6422 break;
6423
6424 /// Floating-Point Compare
6425
6426 case x0 (0427): // dfcmg
6427 // C(E) :: C(Y-pair)0,7
6428 // | C(AQ)0,63 | :: | C(Y-pair)8,71 |
6429
6430 dfcmg (cpup);
6431 break;
6432
6433 case x0 (0517): // dfcmp
6434 // C(E) :: C(Y-pair)0,7
6435 // C(AQ)0,63 :: C(Y-pair)8,71
6436
6437 dfcmp (cpup);
6438 break;
6439
6440 case x0 (0425): // fcmg
6441 // C(E) :: C(Y)0,7
6442 // | C(AQ)0,27 | :: | C(Y)8,35 |
6443
6444 fcmg (cpup);
6445 break;
6446
6447 case x0 (0515): // fcmp
6448 // C(E) :: C(Y)0,7
6449 // C(AQ)0,27 :: C(Y)8,35
6450
6451 fcmp (cpup);
6452 break;
6453
6454 /// Floating-Point Miscellaneous
6455
6456 case x0 (0415): // ade
6457 // C(E) + C(Y)0,7 -> C(E)
6458 {
6459 CPTUR (cptUseE);
6460 int y = SIGNEXT8_int ((cpu.CY >> 28) & 0377);
6461 int e = SIGNEXT8_int (cpu.rE);
6462 e = e + y;
6463
6464 cpu.rE = e & 0377;
6465 CLR_I_ZERO;
6466 CLR_I_NEG;
6467
6468 if (e > 127)
6469 {
6470 SET_I_EOFL;
6471 if (tstOVFfault (cpup))
6472 doFault (FAULT_OFL, fst_zero, "ade exp overflow fault");
6473 }
6474
6475 if (e < -128)
6476 {
6477 SET_I_EUFL;
6478 if (tstOVFfault (cpup))
6479 doFault (FAULT_OFL, fst_zero, "ade exp underflow fault");
6480 }
6481 }
6482 break;
6483
6484 case x0 (0430): // fszn
6485
6486 // Zero: If C(Y)8,35 = 0, then ON; otherwise OFF
6487 // Negative: If C(Y)8 = 1, then ON; otherwise OFF
6488
6489 SC_I_ZERO ((cpu.CY & 001777777777LL) == 0);
6490 SC_I_NEG (cpu.CY & 001000000000LL);
6491
6492 break;
6493
6494 case x0 (0411): // lde
6495 // C(Y)0,7 -> C(E)
6496
6497 CPTUR (cptUseE);
6498 cpu.rE = (cpu.CY >> 28) & 0377;
6499 CLR_I_ZERO;
6500 CLR_I_NEG;
6501
6502 break;
6503
6504 case x0 (0456): // ste
6505 // C(E) -> C(Y)0,7
6506 // 00...0 -> C(Y)8,17
6507
6508 CPTUR (cptUseE);
6509 //putbits36_18 (& cpu.CY, 0, ((word18) (cpu.rE & 0377) << 10));
6510 cpu.CY = ((word36) (cpu.rE & 0377)) << 28;
6511 cpu.zone = 0777777000000;
6512 cpu.useZone = true;
6513 break;
6514
6515 /// TRANSFER INSTRUCTIONS
6516
6517 case x0 (0713): // call6
6518
6519 CPTUR (cptUsePRn + 7);
6520
6521 do_caf (cpup);
6522 read_tra_op (cpup);
6523 sim_debug (DBG_TRACEEXT, & cpu_dev,
6524 "call6 PRR %o PSR %o\r\n", cpu.PPR.PRR, cpu.PPR.PSR);
6525
6526 return CONT_TRA;
6527
6528 case x0 (0630): // ret
6529 {
6530 // Parity mask: If C(Y)27 = 1, and the processor is in absolute or
6531 // mask privileged mode, then ON; otherwise OFF. This indicator is
6532 // not affected in the normal or BAR modes.
6533 // Not BAR mode: Can be set OFF but not ON by the ret instruction
6534 // Absolute mode: Can be set OFF but not ON by the ret instruction
6535 // All other indicators: If corresponding bit in C(Y) is 1, then ON;
6536 // otherwise, OFF
6537
6538 // C(Y)0,17 -> C(PPR.IC)
6539 // C(Y)18,31 -> C(IR)
6540 do_caf (cpup);
6541 ReadOperandRead (cpup, cpu.TPR.CA, & cpu.CY);
6542
6543 cpu.PPR.IC = GETHI (cpu.CY);
6544 word18 tempIR = GETLO (cpu.CY) & 0777770;
6545 // Assuming 'mask privileged mode' is 'temporary absolute mode'
6546 if (is_priv_mode (cpup)) // abs. or temp. abs. or priv.
6547 {
6548 // if abs, copy existing parity mask to tempIR
6549 // According to ISOLTS pm785, not the case.
6550 //SCF (TST_I_PMASK, tempIR, I_PMASK);
6551 // if abs, copy existing I_MIF to tempIR
6552 SCF (TST_I_MIF, tempIR, I_MIF);
6553 }
6554 else
6555 {
6556 CLRF (tempIR, I_MIF);
6557 }
6558 // can be set OFF but not on
6559 // IR ret result
6560 // off off off
6561 // off on off
6562 // on on on
6563 // on off off
6564 // "If it was on, set it to on"
6565 //SCF (TST_I_NBAR, tempIR, I_NBAR);
6566 if (! (TST_I_NBAR && TSTF (tempIR, I_NBAR)))
6567 {
6568 CLRF (tempIR, I_NBAR);
6569 }
6570 if (! (TST_I_ABS && TSTF (tempIR, I_ABS)))
6571 {
6572 CLRF (tempIR, I_ABS);
6573 }
6574
6575 //sim_debug (DBG_TRACEEXT, & cpu_dev,
6576 // "RET NBAR was %d now %d\r\n",
6577 // TST_NBAR ? 1 : 0,
6578 // TSTF (tempIR, I_NBAR) ? 1 : 0);
6579 //sim_debug (DBG_TRACEEXT, & cpu_dev,
6580 // "RET ABS was %d now %d\r\n",
6581 // TST_I_ABS ? 1 : 0,
6582 // TSTF (tempIR, I_ABS) ? 1 : 0);
6583 CPTUR (cptUseIR);
6584 cpu.cu.IR = tempIR;
6585 return CONT_RET;
6586 }
6587
6588 // Optimized to the top of the loop
6589 // case x0 (0610): // rtcd
6590
6591 case x0 (0614): // teo
6592 // If exponent overflow indicator ON then
6593 // C(TPR.CA) -> C(PPR.IC)
6594 // C(TPR.TSR) -> C(PPR.PSR)
6595 // otherwise, no change to C(PPR)
6596 if (TST_I_EOFL)
6597 {
6598 CLR_I_EOFL;
6599 do_caf (cpup);
6600 read_tra_op (cpup);
6601 return CONT_TRA;
6602 }
6603 break;
6604
6605 case x0 (0615): // teu
6606 // If exponent underflow indicator ON then
6607 // C(TPR.CA) -> C(PPR.IC)
6608 // C(TPR.TSR) -> C(PPR.PSR)
6609 if (TST_I_EUFL)
6610 {
6611 CLR_I_EUFL;
6612 do_caf (cpup);
6613 read_tra_op (cpup);
6614 return CONT_TRA;
6615 }
6616 break;
6617
6618 // Optimized to the top of the loop
6619 // case x0 (0604): // tmi
6620
6621 // Optimized to the top of the loop
6622 // case x1 (0604): // tmoz
6623
6624 case x0 (0602): // tnc
6625 // If carry indicator OFF then
6626 // C(TPR.CA) -> C(PPR.IC)
6627 // C(TPR.TSR) -> C(PPR.PSR)
6628 if (!TST_I_CARRY)
6629 {
6630 do_caf (cpup);
6631 read_tra_op (cpup);
6632 return CONT_TRA;
6633 }
6634 break;
6635
6636 // Optimized to the top of the loop
6637 // case x0 (0601): // tnz
6638
6639 case x0 (0617): // tov
6640 // If overflow indicator ON then
6641 // C(TPR.CA) -> C(PPR.IC)
6642 // C(TPR.TSR) -> C(PPR.PSR)
6643 if (TST_I_OFLOW)
6644 {
6645 CLR_I_OFLOW;
6646 do_caf (cpup);
6647 read_tra_op (cpup);
6648 return CONT_TRA;
6649 }
6650 break;
6651
6652 case x0 (0605): // tpl
6653 // If negative indicator OFF, then
6654 // C(TPR.CA) -> C(PPR.IC)
6655 // C(TPR.TSR) -> C(PPR.PSR)
6656 if (! (TST_I_NEG))
6657 {
6658 do_caf (cpup);
6659 read_tra_op (cpup);
6660 return CONT_TRA;
6661 }
6662 break;
6663
6664 // Optimized to the top of the loop
6665 // case x1 (0605): // tpnz
6666
6667 // Optimized to the top of the loop
6668 // case x0 (0710): // tra
6669
6670 case x0 (0603): // trc
6671 // If carry indicator ON then
6672 // C(TPR.CA) -> C(PPR.IC)
6673 // C(TPR.TSR) -> C(PPR.PSR)
6674 if (TST_I_CARRY)
6675 {
6676 do_caf (cpup);
6677 read_tra_op (cpup);
6678 return CONT_TRA;
6679 }
6680 break;
6681
6682 case x1 (0601): // trtf
6683 // If truncation indicator OFF then
6684 // C(TPR.CA) -> C(PPR.IC)
6685 // C(TPR.TSR) -> C(PPR.PSR)
6686 if (!TST_I_TRUNC)
6687 {
6688 do_caf (cpup);
6689 read_tra_op (cpup);
6690 return CONT_TRA;
6691 }
6692 break;
6693
6694 case x1 (0600): // trtn
6695 // If truncation indicator ON then
6696 // C(TPR.CA) -> C(PPR.IC)
6697 // C(TPR.TSR) -> C(PPR.PSR)
6698 if (TST_I_TRUNC)
6699 {
6700 CLR_I_TRUNC;
6701 do_caf (cpup);
6702 read_tra_op (cpup);
6703 return CONT_TRA;
6704 }
6705 break;
6706
6707 // Optimized to the top of the loop
6708 // // tspn
6709 // case x0 (0270): // tsp0
6710 // case x0 (0271): // tsp1
6711 // case x0 (0272): // tsp2
6712 // case x0 (0273): // tsp3
6713 // case x0 (0670): // tsp4
6714 // case x0 (0671): // tsp5
6715 // case x0 (0672): // tsp6
6716 // case x0 (0673): // tsp7
6717
6718 case x0 (0715): // tss
6719 CPTUR (cptUseBAR);
6720 do_caf (cpup);
6721 if (get_bar_mode (cpup))
6722 read_tra_op (cpup);
6723 else
6724 {
6725 cpu.TPR.CA = get_BAR_address (cpup, cpu.TPR.CA);
6726 read_tra_op (cpup);
6727 CLR_I_NBAR;
6728 }
6729 return CONT_TRA;
6730
6731 // Optimized to the top of the loop
6732 // // tsxn
6733 // case x0 (0700): // tsx0
6734 // case x0 (0701): // tsx1
6735 // case x0 (0702): // tsx2
6736 // case x0 (0703): // tsx3
6737 // case x0 (0704): // tsx4
6738 // case x0 (0705): // tsx5
6739 // case x0 (0706): // tsx6
6740 // case x0 (0707): // tsx7
6741
6742 case x0 (0607): // ttf
6743 // If tally runout indicator OFF then
6744 // C(TPR.CA) -> C(PPR.IC)
6745 // C(TPR.TSR) -> C(PPR.PSR)
6746 // otherwise, no change to C(PPR)
6747 if (TST_I_TALLY == 0)
6748 {
6749 do_caf (cpup);
6750 read_tra_op (cpup);
6751 return CONT_TRA;
6752 }
6753 break;
6754
6755 case x1 (0606): // ttn
6756 // If tally runout indicator ON then
6757 // C(TPR.CA) -> C(PPR.IC)
6758 // C(TPR.TSR) -> C(PPR.PSR)
6759 // otherwise, no change to C(PPR)
6760 if (TST_I_TALLY)
6761 {
6762 do_caf (cpup);
6763 read_tra_op (cpup);
6764 return CONT_TRA;
6765 }
6766 break;
6767
6768 // Optimized to the top of the loop
6769 // case x0 (0600): // tze
6770
6771 /// POINTER REGISTER INSTRUCTIONS
6772
6773 /// Pointer Register Data Movement Load
6774
6775 // easpn
6776
6777 case x0 (0311): // easp0
6778 // C(TPR.CA) -> C(PRn.SNR)
6779 CPTUR (cptUsePRn + 0);
6780 cpu.PR[0].SNR = cpu.TPR.CA & MASK15;
6781 #if defined(TESTING)
6782 HDBGRegPRW (0, "easp0");
6783 #endif
6784 break;
6785
6786 case x1 (0310): // easp1
6787 // C(TPR.CA) -> C(PRn.SNR)
6788 CPTUR (cptUsePRn + 1);
6789 cpu.PR[1].SNR = cpu.TPR.CA & MASK15;
6790 #if defined(TESTING)
6791 HDBGRegPRW (1, "easp1");
6792 #endif
6793 break;
6794
6795 case x0 (0313): // easp2
6796 // C(TPR.CA) -> C(PRn.SNR)
6797 CPTUR (cptUsePRn + 2);
6798 cpu.PR[2].SNR = cpu.TPR.CA & MASK15;
6799 #if defined(TESTING)
6800 HDBGRegPRW (2, "easp2");
6801 #endif
6802 break;
6803
6804 case x1 (0312): // easp3
6805 // C(TPR.CA) -> C(PRn.SNR)
6806 CPTUR (cptUsePRn + 3);
6807 cpu.PR[3].SNR = cpu.TPR.CA & MASK15;
6808 #if defined(TESTING)
6809 HDBGRegPRW (3, "easp3");
6810 #endif
6811 break;
6812
6813 case x0 (0331): // easp4
6814 // C(TPR.CA) -> C(PRn.SNR)
6815 CPTUR (cptUsePRn + 4);
6816 cpu.PR[4].SNR = cpu.TPR.CA & MASK15;
6817 #if defined(TESTING)
6818 HDBGRegPRW (4, "easp4");
6819 #endif
6820 break;
6821
6822 case x1 (0330): // easp5
6823 // C(TPR.CA) -> C(PRn.SNR)
6824 CPTUR (cptUsePRn + 5);
6825 cpu.PR[5].SNR = cpu.TPR.CA & MASK15;
6826 #if defined(TESTING)
6827 HDBGRegPRW (5, "easp5");
6828 #endif
6829 break;
6830
6831 case x0 (0333): // easp6
6832 // C(TPR.CA) -> C(PRn.SNR)
6833 CPTUR (cptUsePRn + 6);
6834 cpu.PR[6].SNR = cpu.TPR.CA & MASK15;
6835 #if defined(TESTING)
6836 HDBGRegPRW (6, "easp6");
6837 #endif
6838 break;
6839
6840 case x1 (0332): // easp7
6841 // C(TPR.CA) -> C(PRn.SNR)
6842 CPTUR (cptUsePRn + 7);
6843 cpu.PR[7].SNR = cpu.TPR.CA & MASK15;
6844 #if defined(TESTING)
6845 HDBGRegPRW (7, "easp7");
6846 #endif
6847 break;
6848
6849 // eawpn
6850
6851 case x0 (0310): // eawp0
6852 // For n = 0, 1, ..., or 7 as determined by operation code
6853 // C(TPR.CA) -> C(PRn.WORDNO)
6854 // C(TPR.TBR) -> C(PRn.BITNO)
6855 CPTUR (cptUsePRn + 0);
6856 cpu.PR[0].WORDNO = cpu.TPR.CA;
6857 SET_PR_BITNO (0, cpu.TPR.TBR);
6858 #if defined(TESTING)
6859 HDBGRegPRW (0, "eawp0");
6860 #endif
6861 break;
6862
6863 case x1 (0311): // eawp1
6864 // For n = 0, 1, ..., or 7 as determined by operation code
6865 // C(TPR.CA) -> C(PRn.WORDNO)
6866 // C(TPR.TBR) -> C(PRn.BITNO)
6867 CPTUR (cptUsePRn + 1);
6868 cpu.PR[1].WORDNO = cpu.TPR.CA;
6869 SET_PR_BITNO (1, cpu.TPR.TBR);
6870 #if defined(TESTING)
6871 HDBGRegPRW (1, "eawp1");
6872 #endif
6873 break;
6874
6875 case x0 (0312): // eawp2
6876 // For n = 0, 1, ..., or 7 as determined by operation code
6877 // C(TPR.CA) -> C(PRn.WORDNO)
6878 // C(TPR.TBR) -> C(PRn.BITNO)
6879 CPTUR (cptUsePRn + 2);
6880 cpu.PR[2].WORDNO = cpu.TPR.CA;
6881 SET_PR_BITNO (2, cpu.TPR.TBR);
6882 #if defined(TESTING)
6883 HDBGRegPRW (2, "eawp2");
6884 #endif
6885 break;
6886
6887 case x1 (0313): // eawp3
6888 // For n = 0, 1, ..., or 7 as determined by operation code
6889 // C(TPR.CA) -> C(PRn.WORDNO)
6890 // C(TPR.TBR) -> C(PRn.BITNO)
6891 CPTUR (cptUsePRn + 3);
6892 cpu.PR[3].WORDNO = cpu.TPR.CA;
6893 SET_PR_BITNO (3, cpu.TPR.TBR);
6894 #if defined(TESTING)
6895 HDBGRegPRW (3, "eawp3");
6896 #endif
6897 break;
6898
6899 case x0 (0330): // eawp4
6900 // For n = 0, 1, ..., or 7 as determined by operation code
6901 // C(TPR.CA) -> C(PRn.WORDNO)
6902 // C(TPR.TBR) -> C(PRn.BITNO)
6903 CPTUR (cptUsePRn + 4);
6904 cpu.PR[4].WORDNO = cpu.TPR.CA;
6905 SET_PR_BITNO (4, cpu.TPR.TBR);
6906 #if defined(TESTING)
6907 HDBGRegPRW (4, "eawp4");
6908 #endif
6909 break;
6910
6911 case x1 (0331): // eawp5
6912 // For n = 0, 1, ..., or 7 as determined by operation code
6913 // C(TPR.CA) -> C(PRn.WORDNO)
6914 // C(TPR.TBR) -> C(PRn.BITNO)
6915 CPTUR (cptUsePRn + 5);
6916 cpu.PR[5].WORDNO = cpu.TPR.CA;
6917 SET_PR_BITNO (5, cpu.TPR.TBR);
6918 #if defined(TESTING)
6919 HDBGRegPRW (5, "eawp5");
6920 #endif
6921 break;
6922
6923 case x0 (0332): // eawp6
6924 // For n = 0, 1, ..., or 7 as determined by operation code
6925 // C(TPR.CA) -> C(PRn.WORDNO)
6926 // C(TPR.TBR) -> C(PRn.BITNO)
6927 CPTUR (cptUsePRn + 6);
6928 cpu.PR[6].WORDNO = cpu.TPR.CA;
6929 SET_PR_BITNO (6, cpu.TPR.TBR);
6930 #if defined(TESTING)
6931 HDBGRegPRW (6, "eawp6");
6932 #endif
6933 break;
6934
6935 case x1 (0333): // eawp7
6936 // For n = 0, 1, ..., or 7 as determined by operation code
6937 // C(TPR.CA) -> C(PRn.WORDNO)
6938 // C(TPR.TBR) -> C(PRn.BITNO)
6939 CPTUR (cptUsePRn + 7);
6940 cpu.PR[7].WORDNO = cpu.TPR.CA;
6941 SET_PR_BITNO (7, cpu.TPR.TBR);
6942 #if defined(TESTING)
6943 HDBGRegPRW (7, "eawp7");
6944 #endif
6945 break;
6946
6947 // Optimized to the top of the loop
6948 // case x1 (0350): // epbp0
6949 // case x0 (0351): // epbp1
6950 // case x1 (0352): // epbp2
6951 // case x0 (0353): // epbp3
6952 // case x1 (0370): // epbp4
6953 // case x0 (0371): // epbp5
6954 // case x1 (0372): // epbp6
6955 // case x0 (0373): // epbp7
6956
6957 // Optimized to the top of the switch
6958 // case x0 (0350): // epp0
6959 // case x1 (0351): // epp1
6960 // case x0 (0352): // epp2
6961 // case x1 (0353): // epp3
6962 // case x0 (0374): // epp4
6963 // case x1 (0371): // epp5
6964 // case x0 (0376): // epp6
6965 // case x1 (0373): // epp7
6966
6967 case x0 (0173): // lpri
6968 // For n = 0, 1, ..., 7
6969 // Y-pair = Y-block16 + 2n
6970 // Maximum of C(Y-pair)18,20; C(SDW.R1); C(TPR.TRR) -> C(PRn.RNR)
6971 // C(Y-pair) 3,17 -> C(PRn.SNR)
6972 // C(Y-pair)36,53 -> C(PRn.WORDNO)
6973 // C(Y-pair)57,62 -> C(PRn.BITNO)
6974
6975 for (uint32 n = 0 ; n < 8 ; n ++)
6976 {
6977 CPTUR (cptUsePRn + n);
6978 // Even word of ITS pointer pair
6979 cpu.Ypair[0] = cpu.Yblock16[n * 2 + 0];
6980 // Odd word of ITS pointer pair
6981 cpu.Ypair[1] = cpu.Yblock16[n * 2 + 1];
6982
6983 // RNR from ITS pair
6984 word3 Crr = (GETLO (cpu.Ypair[0]) >> 15) & 07;
6985 if (get_addr_mode (cpup) == APPEND_mode)
6986 cpu.PR[n].RNR = max3 (Crr, cpu.SDW->R1, cpu.TPR.TRR);
6987 else
6988 cpu.PR[n].RNR = Crr;
6989 cpu.PR[n].SNR = (cpu.Ypair[0] >> 18) & MASK15;
6990 cpu.PR[n].WORDNO = GETHI (cpu.Ypair[1]);
6991 word6 bitno = (GETLO (cpu.Ypair[1]) >> 9) & 077;
6992 // According to ISOLTS, loading a 077 into bitno results in 037
6993 // pa851 test-04b lpri test bar-100176
6994 // test start 105321 patch 105461 subtest loop point 105442
6995 // s/b 77777737
6996 // was 77777733
6997 if (bitno == 077)
6998 bitno = 037;
6999 SET_PR_BITNO (n, bitno);
7000 #if defined(TESTING)
7001 HDBGRegPRW (n, "lpri");
7002 #endif
7003 }
7004
7005 break;
7006
7007 // Optimized to the top of the loop
7008 // // lprpn
7009 // case x0 (0760): // lprp0
7010 // case x0 (0761): // lprp1
7011 // case x0 (0762): // lprp2
7012 // case x0 (0763): // lprp3
7013 // case x0 (0764): // lprp4
7014 // case x0 (0765): // lprp5
7015 // case x0 (0766): // lprp6
7016 // case x0 (0767): // lprp7
7017
7018 /// Pointer Register Data Movement Store
7019
7020 // Optimized to the top of the loop
7021 // case x1 (0250): // spbp0
7022 // case x0 (0251): // spbp1
7023 // case x1 (0252): // spbp2
7024 // case x0 (0253): // spbp3
7025 // case x1 (0650): // spbp4
7026 // case x0 (0651): // spbp5
7027 // case x1 (0652): // spbp6
7028 // case x0 (0653): // spbp7
7029
7030 case x0 (0254): // spri
7031 // For n = 0, 1, ..., 7
7032 // Y-pair = Y-block16 + 2n
7033
7034 // 000 -> C(Y-pair)0,2
7035 // C(PRn.SNR) -> C(Y-pair)3,17
7036 // C(PRn.RNR) -> C(Y-pair)18,20
7037 // 00...0 -> C(Y-pair)21,29
7038 // (43)8 -> C(Y-pair)30,35
7039
7040 // C(PRn.WORDNO) -> C(Y-pair)36,53
7041 // 000 -> C(Y-pair)54,56
7042 // C(PRn.BITNO) -> C(Y-pair)57,62
7043 // 00...0 -> C(Y-pair)63,71
7044
7045 for (uint32 n = 0 ; n < 8 ; n++)
7046 {
7047 CPTUR (cptUsePRn + n);
7048 cpu.Yblock16[2 * n] = 043;
7049 cpu.Yblock16[2 * n] |= ((word36) cpu.PR[n].SNR) << 18;
7050 cpu.Yblock16[2 * n] |= ((word36) cpu.PR[n].RNR) << 15;
7051
7052 cpu.Yblock16[2 * n + 1] = (word36) cpu.PR[n].WORDNO << 18;
7053 cpu.Yblock16[2 * n + 1] |= (word36) GET_PR_BITNO(n) << 9;
7054 }
7055
7056 break;
7057
7058 // Optimized to the top of the loop
7059 // case x0 (0250): // spri0
7060 // case x1 (0251): // spri1
7061 // case x0 (0252): // spri2
7062 // case x1 (0253): // spri3
7063 // case x0 (0650): // spri4
7064 // case x1 (0255): // spri5
7065 // case x0 (0652): // spri6
7066 // case x1 (0257): // spri7
7067
7068 // sprpn
7069 case x0 (0540): // sprp0
7070 case x0 (0541): // sprp1
7071 case x0 (0542): // sprp2
7072 case x0 (0543): // sprp3
7073 case x0 (0544): // sprp4
7074 case x0 (0545): // sprp5
7075 case x0 (0546): // sprp6
7076 case x0 (0547): // sprp7
7077 // For n = 0, 1, ..., or 7 as determined by operation code
7078 // C(PRn.BITNO) -> C(Y)0,5
7079 // C(PRn.SNR)3,14 -> C(Y)6,17
7080 // C(PRn.WORDNO) -> C(Y)18,35
7081 {
7082 uint32 n = opcode10 & 07; // get n
7083 CPTUR (cptUsePRn + n);
7084
7085 // If C(PRn.SNR)0,2 are nonzero, and C(PRn.SNR) != 11...1, then
7086 // a store fault (illegal pointer) will occur and C(Y) will not
7087 // be changed.
7088
7089 if ((cpu.PR[n].SNR & 070000) != 0 && cpu.PR[n].SNR != MASK15)
7090 doFault (FAULT_STR, fst_str_ptr, "sprpn");
7091
7092 cpu.CY = ((word36) (GET_PR_BITNO(n) & 077)) << 30;
7093 // lower 12- of 15-bits
7094 cpu.CY |= ((word36) (cpu.PR[n].SNR & 07777)) << 18;
7095 cpu.CY |= cpu.PR[n].WORDNO & PAMASK;
7096 cpu.CY &= DMASK; // keep to 36-bits
7097 }
7098 break;
7099
7100 /// Pointer Register Address Arithmetic
7101
7102 // adwpn
7103 case x0 (0050): // adwp0
7104 case x0 (0051): // adwp1
7105 case x0 (0052): // adwp2
7106 case x0 (0053): // adwp3
7107 // For n = 0, 1, ..., or 7 as determined by operation code
7108 // C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7109 // 00...0 -> C(PRn.BITNO)
7110 {
7111 uint32 n = opcode10 & 03; // get n
7112 CPTUR (cptUsePRn + n);
7113 cpu.PR[n].WORDNO += GETHI (cpu.CY);
7114 cpu.PR[n].WORDNO &= MASK18;
7115 SET_PR_BITNO (n, 0);
7116 #if defined(TESTING)
7117 HDBGRegPRW (n, "adwpn");
7118 #endif
7119 }
7120 break;
7121
7122 case x0 (0150): // adwp4
7123 case x0 (0151): // adwp5
7124 case x0 (0152): // adwp6
7125 case x0 (0153): // adwp7
7126 // For n = 0, 1, ..., or 7 as determined by operation code
7127 // C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7128 // 00...0 -> C(PRn.BITNO)
7129 {
7130 uint32 n = (opcode10 & MASK3) + 4U; // get n
7131 CPTUR (cptUsePRn + n);
7132 cpu.PR[n].WORDNO += GETHI (cpu.CY);
7133 cpu.PR[n].WORDNO &= MASK18;
7134 SET_PR_BITNO (n, 0);
7135 #if defined(TESTING)
7136 HDBGRegPRW (n, "adwpn");
7137 #endif
7138 }
7139 break;
7140
7141 /// Pointer Register Miscellaneous
7142
7143 // Optimized to the top of the loop
7144 // case x0 (0213): // epaq
7145
7146 /// MISCELLANEOUS INSTRUCTIONS
7147
7148 case x0 (0633): // rccl
7149 // 00...0 -> C(AQ)0,19
7150 // C(calendar clock) -> C(AQ)20,71
7151 {
7152 // For the rccl instruction, the first 2 or 3 bits of the addr
7153 // field of the instruction are used to specify which SCU.
7154 // init_processor.alm systematically steps through the SCUs,
7155 // using addresses 000000 100000 200000 300000.
7156 uint cpu_port_num;
7157 if (cpu.tweaks.l68_mode)
7158 cpu_port_num = (cpu.TPR.CA >> 15) & 07;
7159 else
7160 cpu_port_num = (cpu.TPR.CA >> 15) & 03;
7161 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
7162 {
7163 sim_warn ("rccl on CPU %u port %d has no SCU; faulting\r\n",
7164 current_running_cpu_idx, cpu_port_num);
7165 doFault (FAULT_ONC, fst_onc_nem, "(rccl)");
7166 }
7167 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
7168
7169 t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
7170 040, & cpu.rA, & cpu.rQ);
7171 #if defined(TESTING)
7172 HDBGRegAW ("rccl");
7173 HDBGRegQW ("rccl");
7174 #endif
7175 if (rc > 0)
7176 return rc;
7177 #if !defined(SPEED)
7178 if_sim_debug (DBG_TRACEEXT, & cpu_dev)
7179 {
7180 // Clock at initialization
7181 // date -d "Tue Jul 22 16:39:38 PDT 1999" +%s
7182 // 932686778
7183 uint64 UnixSecs = 932686778;
7184 uint64 UnixuSecs = UnixSecs * 1000000LL;
7185 // now determine uSecs since Jan 1, 1901 ...
7186 uint64 MulticsuSecs = 2177452800000000LL + UnixuSecs;
7187
7188 // Back into 72 bits
7189 word72 big = convert_to_word72 (cpu.rA, cpu.rQ);
7190 # if defined(NEED_128)
7191 // Convert to time since boot
7192 big = subtract_128 (big, construct_128 (0, MulticsuSecs));
7193 uint32_t remainder;
7194 uint128 bigsecs = divide_128_32 (big, 1000000u, & remainder);
7195 uint64_t uSecs = remainder;
7196 uint64_t secs = bigsecs.l;
7197 sim_debug (DBG_TRACEEXT, & cpu_dev,
7198 "Clock time since boot %4llu.%06llu seconds\r\n",
7199 secs, uSecs);
7200 # else
7201 // Convert to time since boot
7202 big -= MulticsuSecs;
7203 unsigned long uSecs = big % 1000000u;
7204 unsigned long secs = (unsigned long) (big / 1000000u);
7205 sim_debug (DBG_TRACEEXT, & cpu_dev,
7206 "Clock time since boot %4lu.%06lu seconds\r\n",
7207 secs, uSecs);
7208 # endif
7209 }
7210 #endif
7211 }
7212 break;
7213
7214 case x0 (0002): // drl
7215 // Causes a fault which fetches and executes, in absolute mode, the
7216 // instruction pair at main memory location C+(14)8. The value of C
7217 // is obtained from the FAULT VECTOR switches on the processor
7218 // configuration panel.
7219
7220 if (cpu.tweaks.drl_fatal)
7221 {
7222 return STOP_STOP;
7223 }
7224 doFault (FAULT_DRL, fst_zero, "drl");
7225
7226 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7227 case x0 (0716): // xec
7228 cpu.cu.xde = 1;
7229 cpu.cu.xdo = 0;
7230 // XXX NB. This used to be done in executeInstruction post-execution
7231 // processing; moving it here means that post-execution code cannot inspect IWB
7232 // to determine what the instruction or it flags were.
7233 cpu.cu.IWB = cpu.CY;
7234 return CONT_XEC;
7235
7236 case x0 (0717): // xed
7237 // The xed instruction itself does not affect any indicator.
7238 // However, the execution of the instruction pair from C(Y-pair)
7239 // may affect indicators.
7240 //
7241 // The even instruction from C(Y-pair) must not alter
7242 // C(Y-pair)36,71, and must not be another xed instruction.
7243 //
7244 // If the execution of the instruction pair from C(Y-pair) alters
7245 // C(PPR.IC), then a transfer of control occurs; otherwise, the
7246 // next instruction to be executed is fetched from C(PPR.IC)+1. If
7247 // the even instruction from C(Y-pair) alters C(PPR.IC), then the
7248 // transfer of control is effective immediately and the odd
7249 // instruction is not executed.
7250 //
7251 // To execute an instruction pair having an rpd instruction as the
7252 // odd instruction, the xed instruction must be located at an odd
7253 // address. The instruction pair repeated is that instruction pair
7254 // at C PPR.IC)+1, that is, the instruction pair immediately
7255 // following the xed instruction. C(PPR.IC) is adjusted during the
7256 // execution of the repeated instruction pair so the next
7257 // instruction fetched for execution is from the first word
7258 // following the repeated instruction pair.
7259 //
7260 // The instruction pair at C(Y-pair) may cause any of the processor
7261 // defined fault conditions, but only the directed faults (0,1,2,3)
7262 // and the access violation fault may be restarted successfully by
7263 // the hardware. Note that the software induced fault tag (1,2,3)
7264 // faults cannot be properly restarted.
7265 //
7266 // An attempt to execute an EIS multiword instruction causes an
7267 // illegal procedure fault.
7268 //
7269 // Attempted repetition with the rpt, rpd, or rpl instructions
7270 // causes an illegal procedure fault.
7271
7272 cpu.cu.xde = 1;
7273 cpu.cu.xdo = 1;
7274 // XXX NB. This used to be done in executeInstruction post-execution
7275 // processing; moving it here means that post-execution code cannot inspect IWB
7276 // to determine what the instruction or it flags were.
7277 cpu.cu.IWB = cpu.Ypair[0];
7278 cpu.cu.IRODD = cpu.Ypair[1];
7279 return CONT_XEC;
7280
7281 case x0 (0001): // mme
7282 #if defined(TESTING)
7283 if (sim_deb_mme_cntdwn > 0)
7284 sim_deb_mme_cntdwn --;
7285 #endif
7286 // Causes a fault that fetches and executes, in absolute mode, the
7287 // instruction pair at main memory location C+4. The value of C is
7288 // obtained from the FAULT VECTOR switches on the processor
7289 // configuration panel.
7290 doFault (FAULT_MME, fst_zero, "Master Mode Entry (mme)");
7291
7292 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7293 case x0 (0004): // mme2
7294 // Causes a fault that fetches and executes, in absolute mode, the
7295 // instruction pair at main memory location C+(52)8. The value of C
7296 // is obtained from the FAULT VECTOR switches on the processor
7297 // configuration panel.
7298 doFault (FAULT_MME2, fst_zero, "Master Mode Entry 2 (mme2)");
7299
7300 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7301 case x0 (0005): // mme3
7302 // Causes a fault that fetches and executes, in absolute mode, the
7303 // instruction pair at main memory location C+(54)8. The value of C
7304 // is obtained from the FAULT VECTOR switches on the processor
7305 // configuration panel.
7306 doFault (FAULT_MME3, fst_zero, "Master Mode Entry 3 (mme3)");
7307
7308 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7309 case x0 (0007): // mme4
7310 // Causes a fault that fetches and executes, in absolute mode, the
7311 // instruction pair at main memory location C+(56)8. The value of C
7312 // is obtained from the FAULT VECTOR switches on the processor
7313 // configuration panel.
7314 doFault (FAULT_MME4, fst_zero, "Master Mode Entry 4 (mme4)");
7315
7316 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7317 case x0 (0011): // nop
7318 break;
7319
7320 case x0 (0012): // puls1
7321 break;
7322
7323 case x0 (0013): // puls2
7324 break;
7325
7326 /// Repeat
7327
7328 case x0 (0560): // rpd
7329 {
7330 if ((cpu.PPR.IC & 1) == 0)
7331 doFault (FAULT_IPR, fst_ill_proc, "rpd odd");
7332 cpu.cu.delta = i->tag;
7333 // a:AL39/rpd1
7334 word1 c = (i->address >> 7) & 1;
7335 if (c)
7336 {
7337 cpu.rX[0] = i->address; // Entire 18 bits
7338 #if defined(TESTING)
7339 HDBGRegXW (0, "rpd");
7340 #endif
7341 }
7342 cpu.cu.rd = 1;
7343 cpu.cu.repeat_first = 1;
7344 }
7345 break;
7346
7347 case x0 (0500): // rpl
7348 {
7349 uint c = (i->address >> 7) & 1;
7350 cpu.cu.delta = i->tag;
7351 if (c)
7352 {
7353 cpu.rX[0] = i->address; // Entire 18 bits
7354 #if defined(TESTING)
7355 HDBGRegXW (0, "rpl");
7356 #endif
7357 }
7358 cpu.cu.rl = 1;
7359 cpu.cu.repeat_first = 1;
7360 }
7361 break;
7362
7363 case x0 (0520): // rpt
7364 {
7365 uint c = (i->address >> 7) & 1;
7366 cpu.cu.delta = i->tag;
7367 if (c)
7368 {
7369 cpu.rX[0] = i->address; // Entire 18 bits
7370 #if defined(TESTING)
7371 HDBGRegXW (0, "rpt");
7372 #endif
7373 }
7374 cpu.cu.rpt = 1;
7375 cpu.cu.repeat_first = 1;
7376 }
7377 break;
7378
7379 /// Ring Alarm Register
7380
7381 case x1 (0754): // sra
7382 // 00...0 -> C(Y)0,32
7383 // C(RALR) -> C(Y)33,35
7384
7385 CPTUR (cptUseRALR);
7386 cpu.CY = (word36)cpu.rRALR;
7387
7388 break;
7389
7390 /// Store Base Address Register
7391
7392 case x0 (0550): // sbar
7393 // C(BAR) -> C(Y) 0,17
7394 CPTUR (cptUseBAR);
7395 //SETHI (cpu.CY, (cpu.BAR.BASE << 9) | cpu.BAR.BOUND);
7396 cpu.CY = ((((word36) cpu.BAR.BASE) << 9) | cpu.BAR.BOUND) << 18;
7397 cpu.zone = 0777777000000;
7398 cpu.useZone = true;
7399 break;
7400
7401 /// Translation
7402
7403 case x0 (0505): // bcd
7404 // Shift C(A) left three positions
7405 // | C(A) | / C(Y) -> 4-bit quotient
7406 // C(A) - C(Y) * quotient -> remainder
7407 // Shift C(Q) left six positions
7408 // 4-bit quotient -> C(Q)32,35
7409 // remainder -> C(A)
7410
7411 {
7412 word36 tmp1 = cpu.rA & SIGN36; // A0
7413 word36 tmp36 = (cpu.rA << 3) & DMASK;
7414 word36 tmp36q = tmp36 / cpu.CY; // this may be more than 4 bits, keep it for remainder calculation
7415 word36 tmp36r = 0;
7416 if (!tmp1) {
7417 tmp36r = tmp36 - tmp36q * cpu.CY;
7418 } else {
7419 // ISOLTS-745 05i: bcd when rA is negative.
7420 // Note that this only gets called in the first round of the bcd
7421 // conversion; the rA sign bit will get shifted out.
7422 // Looking at the expected results, it appears that a 'borrow'
7423 // is represented in a residue style notation -- an unborrow
7424 // result is 0-9 (000 - 011), a borrowed digit as 6-15 (006-017)
7425 tmp36q += 6;
7426 tmp36r = tmp36 + tmp36q * cpu.CY;
7427 }
7428
7429 cpu.rQ <<= 6; // Shift C(Q) left six positions
7430 cpu.rQ &= DMASK;
7431
7432 //cpu.rQ &= (word36) ~017; // 4-bit quotient -> C(Q)32,35 lo6 bits already zeroed out
7433 cpu.rQ |= (tmp36q & 017);
7434 #if defined(TESTING)
7435 HDBGRegQW ("bcd");
7436 #endif
7437
7438 cpu.rA = tmp36r & DMASK; // remainder -> C(A)
7439 #if defined(TESTING)
7440 HDBGRegAW ("bcd");
7441 #endif
7442
7443 SC_I_ZERO (cpu.rA == 0); // If C(A) = 0, then ON;
7444 // otherwise OFF
7445 SC_I_NEG (tmp1); // If C(A)0 = 1 before execution,
7446 // then ON; otherwise OFF
7447 }
7448 break;
7449
7450 case x0 (0774): // gtb
7451 // C(A)0 -> C(A)0
7452 // C(A)i XOR C(A)i-1 -> C(A)i for i = 1, 2, ..., 35
7453 {
7454 word36 tmp = cpu.rA & MASK36;
7455 word36 mask = SIGN36;
7456
7457 for (int n=1;n<=35;n++) {
7458 tmp ^= (tmp & mask) >> 1;
7459 mask >>= 1;
7460 }
7461
7462 cpu.rA = tmp;
7463 #if defined(TESTING)
7464 HDBGRegAW ("gtb");
7465 #endif
7466
7467 SC_I_ZERO (cpu.rA == 0); // If C(A) = 0, then ON;
7468 // otherwise OFF
7469 SC_I_NEG (cpu.rA & SIGN36); // If C(A)0 = 1, then ON;
7470 // otherwise OFF
7471 }
7472 break;
7473
7474 /// REGISTER LOAD
7475
7476 case x0 (0230): // lbar
7477 // C(Y)0,17 -> C(BAR)
7478 CPTUR (cptUseBAR);
7479 // BAR.BASE is upper 9-bits (0-8)
7480 cpu.BAR.BASE = (GETHI (cpu.CY) >> 9) & 0777;
7481 // BAR.BOUND is next lower 9-bits (9-17)
7482 cpu.BAR.BOUND = GETHI (cpu.CY) & 0777;
7483 break;
7484
7485 /// PRIVILEGED INSTRUCTIONS
7486
7487 /// Privileged - Register Load
7488
7489 case x0 (0674): // lcpr
7490 // DPS8M interpretation
7491 switch (i->tag)
7492 {
7493 // Extract bits from 'from' under 'mask' shifted to where (where
7494 // is dps8 '0 is the msbit.
7495
7496 case 02: // cache mode register
7497 {
7498 //cpu.CMR = cpu.CY;
7499 // cpu.CMR.cache_dir_address = <ignored for lcpr>
7500 // cpu.CMR.par_bit = <ignored for lcpr>
7501 // cpu.CMR.lev_ful = <ignored for lcpr>
7502
7503 CPTUR (cptUseCMR);
7504 // a:AL39/cmr2 If either cache enable bit c or d changes
7505 // from disable state to enable state, the entire cache is
7506 // cleared.
7507 uint csh1_on = getbits36_1 (cpu.CY, 54 - 36);
7508 uint csh2_on = getbits36_1 (cpu.CY, 55 - 36);
7509 //bool clear = (cpu.CMR.csh1_on == 0 && csh1_on != 0) ||
7510 //(cpu.CMR.csh1_on == 0 && csh1_on != 0);
7511 cpu.CMR.csh1_on = (word1) csh1_on;
7512 cpu.CMR.csh2_on = (word1) csh2_on;
7513 //if (clear) // a:AL39/cmr2
7514 //{
7515 //}
7516 L68_ (cpu.CMR.opnd_on = getbits36_1 (cpu.CY, 56 - 36);)
7517 cpu.CMR.inst_on = getbits36_1 (cpu.CY, 57 - 36);
7518 cpu.CMR.csh_reg = getbits36_1 (cpu.CY, 59 - 36);
7519 if (cpu.CMR.csh_reg)
7520 sim_warn ("LCPR set csh_reg\r\n");
7521 // cpu.CMR.str_asd = <ignored for lcpr>
7522 // cpu.CMR.col_ful = <ignored for lcpr>
7523 // cpu.CMR.rro_AB = getbits36_1 (cpu.CY, 18);
7524 DPS8M_ (cpu.CMR.bypass_cache = getbits36_1 (cpu.CY, 68 - 36);)
7525 cpu.CMR.luf = getbits36_2 (cpu.CY, 70 - 36);
7526 }
7527 break;
7528
7529 case 04: // mode register
7530 {
7531 CPTUR (cptUseMR);
7532 cpu.MR.r = cpu.CY;
7533 // XXX TEST/NORMAL switch is set to NORMAL
7534 putbits36_1 (& cpu.MR.r, 32, 0);
7535 // SBZ
7536 putbits36_2 (& cpu.MR.r, 33, 0);
7537 L68_ (
7538 cpu.MR.FFV = getbits36_15 (cpu.CY, 0);
7539 cpu.MR.OC_TRAP = getbits36_1 (cpu.CY, 16);
7540 cpu.MR.ADR_TRAP = getbits36_1 (cpu.CY, 17);
7541 cpu.MR.OPCODE = getbits36_9 (cpu.CY, 18);
7542 cpu.MR.OPCODEX = getbits36_1 (cpu.CY, 27);
7543 )
7544 cpu.MR.sdpap = getbits36_1 (cpu.CY, 20);
7545 cpu.MR.separ = getbits36_1 (cpu.CY, 21);
7546 cpu.MR.hrhlt = getbits36_1 (cpu.CY, 28);
7547 DPS8M_ (cpu.MR.hrxfr = getbits36_1 (cpu.CY, 29);)
7548 cpu.MR.ihr = getbits36_1 (cpu.CY, 30);
7549 cpu.MR.ihrrs = getbits36_1 (cpu.CY, 31);
7550 cpu.MR.emr = getbits36_1 (cpu.CY, 35);
7551 if (! cpu.tweaks.l68_mode) // DPS8M
7552 cpu.MR.hexfp = getbits36_1 (cpu.CY, 33);
7553 else // L68
7554 cpu.MR.hexfp = 0;
7555
7556 // Stop HR Strobe on HR Counter Overflow. (Setting bit 28
7557 // shall cause the HR counter to be reset to zero.)
7558 // CAC: It is unclear if bit 28 is edge or level
7559 // triggered; assuming level for simplicity.
7560 if (cpu.MR.hrhlt)
7561 {
7562 for (uint hset = 0; hset < N_HIST_SETS; hset ++)
7563 cpu.history_cyclic[hset] = 0;
7564 }
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577 }
7578 break;
7579
7580 case 03: // 0's -> history
7581 {
7582 for (uint i = 0; i < N_HIST_SETS; i ++)
7583 add_history_force (cpup, i, 0, 0);
7584 // XXX ISOLTS pm700 test-01n
7585 // The test clears the history registers but with ihr & emr set, causing
7586 // the registers to fill with alternating 0's and lcpr instructions.
7587 // Set flag to prevent the LCPR from being recorded.
7588 //cpu.MR.ihr = 0;
7589 cpu.skip_cu_hist = true;
7590
7591 }
7592 break;
7593
7594 case 07: // 1's -> history
7595 {
7596 for (uint i = 0; i < N_HIST_SETS; i ++)
7597 add_history_force (cpup, i, MASK36, MASK36);
7598 // XXX ISOLTS pm700 test-01n
7599 // The test clears the history registers but with ihr & emr set, causing
7600 // the registers to fill with alternating 0's and lcpr instructions.
7601 // Set flag to prevent the LCPR from being recorded.
7602 //cpu.MR.ihr = 0;
7603 cpu.skip_cu_hist = true;
7604 }
7605 break;
7606
7607 default:
7608 doFault (FAULT_IPR,
7609 fst_ill_mod,
7610 "lcpr tag invalid");
7611
7612 }
7613 break;
7614
7615 case x0 (0232): // ldbr
7616 do_ldbr (cpup, cpu.Ypair);
7617 ucInvalidate (cpup);
7618 break;
7619
7620 case x0 (0637): // ldt
7621 CPTUR (cptUseTR);
7622 cpu.rTR = (cpu.CY >> 9) & MASK27;
7623 cpu.rTRticks = 0;
7624 if (cpu.tweaks.isolts_mode)
7625 {
7626 cpu.shadowTR = cpu.TR0 = cpu.rTR;
7627 cpu.rTRlsb = 0;
7628 }
7629 sim_debug (DBG_TRACEEXT, & cpu_dev, "ldt TR %d (%o)\r\n",
7630 cpu.rTR, cpu.rTR);
7631 #if defined(LOOPTRC)
7632 elapsedtime ();
7633 sim_printf (" ldt %d PSR:IC %05o:%06o\r\n", cpu.rTR, cpu.PPR.PSR, cpu.PPR.IC);
7634 #endif
7635 // Undocumented feature. return to bce has been observed to
7636 // experience TRO while masked, setting the TR to -1, and
7637 // experiencing an unexpected TRo interrupt when unmasking.
7638 // Reset any pending TRO fault when the TR is loaded.
7639 clearTROFault (cpup);
7640 break;
7641
7642 case x1 (0257): // lptp
7643
7644 if (cpu.tweaks.l68_mode) {
7645 // For i = 0, 1, ..., 15
7646 // m = C(PTWAM(i).USE)
7647 // C(Y-block16+m)0,14 -> C(PTWAM(m).POINTER)
7648 // C(Y-block16+m)15,26 -> C(PTWAM(m).PAGE)
7649 // C(Y-block16+m)27 -> C(PTWAM(m).F)
7650
7651 for (uint i = 0; i < 16; i ++)
7652 {
7653 word4 m = cpu.PTWAM[i].USE;
7654 cpu.PTWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i], 0);
7655 cpu.PTWAM[m].PAGENO = getbits36_12 (cpu.Yblock16[i], 15);
7656 cpu.PTWAM[m].FE = getbits36_1 (cpu.Yblock16[i], 27);
7657 }
7658 }
7659 break;
7660
7661 case x1 (0173): // lptr
7662 if (cpu.tweaks.l68_mode) {
7663 // For i = 0, 1, ..., 15
7664 // m = C(PTWAM(i).USE)
7665 // C(Y-block16+m)0,17 -> C(PTWAM(m).ADDR)
7666 // C(Y-block16+m)29 -> C(PTWAM(m).M)
7667 for (uint i = 0; i < 16; i ++)
7668 {
7669 word4 m = cpu.PTWAM[i].USE;
7670 cpu.PTWAM[m].ADDR = getbits36_18 (cpu.Yblock16[i], 0);
7671 cpu.PTWAM[m].M = getbits36_1 (cpu.Yblock16[i], 29);
7672 }
7673 }
7674 break;
7675
7676 case x1 (0774): // lra
7677 CPTUR (cptUseRALR);
7678 cpu.rRALR = cpu.CY & MASK3;
7679 sim_debug (DBG_TRACEEXT, & cpu_dev, "RALR set to %o\r\n", cpu.rRALR);
7680 #if defined(LOOPTRC)
7681 {
7682 void elapsedtime (void);
7683 elapsedtime ();
7684 sim_printf (" RALR set to %o PSR:IC %05o:%06o\r\n", cpu.rRALR, cpu.PPR.PSR, cpu.PPR.IC);
7685 }
7686 #endif
7687 break;
7688
7689 case x0 (0257): // lsdp
7690 if (cpu.tweaks.l68_mode) {
7691 // For i = 0, 1, ..., 15
7692 // m = C(SDWAM(i).USE)
7693 // C(Y-block16+m)0,14 -> C(SDWAM(m).POINTER)
7694 // C(Y-block16+m)27 -> C(SDWAM(m).F) Note: typo in AL39, P(17) should be F(27)
7695 for (uint i = 0; i < 16; i ++)
7696 {
7697 word4 m = cpu.SDWAM[i].USE;
7698 cpu.SDWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i], 0);
7699 cpu.SDWAM[m].FE = getbits36_1 (cpu.Yblock16[i], 27);
7700 }
7701 }
7702 break;
7703
7704 case x1 (0232): // lsdr
7705 if (cpu.tweaks.l68_mode) {
7706 // For i = 0, 1, ..., 15
7707 // m = C(SDWAM(i).USE)
7708 // C(Y-block32+2m)0,23 -> C(SDWAM(m).ADDR)
7709 // C(Y-block32+2m)24,32 -> C(SDWAM(m).R1, R2, R3)
7710 // C(Y-block32+2m)37,50 -> C(SDWAM(m).BOUND)
7711 // C(Y-block32+2m)51,57 -> C(SDWAM(m).R, E, W, P, U, G, C) Note: typo in AL39, 52 should be 51
7712 // C(Y-block32+2m)58,71 -> C(SDWAM(m).CL)
7713 for (uint i = 0; i < 16; i ++)
7714 {
7715 word4 m = cpu.SDWAM[i].USE;
7716 uint j = (uint)m * 2;
7717 cpu.SDWAM[m].ADDR = getbits36_24 (cpu.Yblock32[j], 0);
7718 cpu.SDWAM[m].R1 = getbits36_3 (cpu.Yblock32[j], 24);
7719 cpu.SDWAM[m].R2 = getbits36_3 (cpu.Yblock32[j], 27);
7720 cpu.SDWAM[m].R3 = getbits36_3 (cpu.Yblock32[j], 30);
7721
7722 cpu.SDWAM[m].BOUND = getbits36_14 (cpu.Yblock32[j + 1], 37 - 36);
7723 cpu.SDWAM[m].R = getbits36_1 (cpu.Yblock32[j + 1], 51 - 36);
7724 cpu.SDWAM[m].E = getbits36_1 (cpu.Yblock32[j + 1], 52 - 36);
7725 cpu.SDWAM[m].W = getbits36_1 (cpu.Yblock32[j + 1], 53 - 36);
7726 cpu.SDWAM[m].P = getbits36_1 (cpu.Yblock32[j + 1], 54 - 36);
7727 cpu.SDWAM[m].U = getbits36_1 (cpu.Yblock32[j + 1], 55 - 36);
7728 cpu.SDWAM[m].G = getbits36_1 (cpu.Yblock32[j + 1], 56 - 36);
7729 cpu.SDWAM[m].C = getbits36_1 (cpu.Yblock32[j + 1], 57 - 36);
7730 cpu.SDWAM[m].EB = getbits36_14 (cpu.Yblock32[j + 1], 58 - 36);
7731 }
7732 }
7733 break;
7734
7735 case x0 (0613): // rcu
7736 doRCU (cpup); // never returns!
7737
7738 /// Privileged - Register Store
7739
7740 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7741 case x0 (0452): // scpr
7742 {
7743 uint tag = (i->tag) & MASK6;
7744 switch (tag)
7745 {
7746 case 000: // C(APU history register#1) -> C(Y-pair)
7747 {
7748 uint reg = cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG;
7749 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7750 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7751 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7752 }
7753 break;
7754
7755 case 001: // C(fault register) -> C(Y-pair)0,35
7756 // 00...0 -> C(Y-pair)36,71
7757 {
7758 CPTUR (cptUseFR);
7759 cpu.Ypair[0] = cpu.faultRegister[0];
7760 cpu.Ypair[1] = cpu.faultRegister[1];
7761 cpu.faultRegister[0] = 0;
7762 cpu.faultRegister[1] = 0;
7763 }
7764 break;
7765
7766 case 006: // C(mode register) -> C(Y-pair)0,35
7767 // C(cache mode register) -> C(Y-pair)36,72
7768 {
7769 CPTUR (cptUseMR);
7770 cpu.Ypair[0] = cpu.MR.r;
7771 putbits36_1 (& cpu.Ypair[0], 20, cpu.MR.sdpap);
7772 putbits36_1 (& cpu.Ypair[0], 21, cpu.MR.separ);
7773 putbits36_1 (& cpu.Ypair[0], 30, cpu.MR.ihr);
7774 DPS8M_ (putbits36_1 (& cpu.Ypair[0], 33, cpu.MR.hexfp);)
7775 CPTUR (cptUseCMR);
7776 cpu.Ypair[1] = 0;
7777 putbits36_15 (& cpu.Ypair[1], 36 - 36,
7778 cpu.CMR.cache_dir_address);
7779 putbits36_1 (& cpu.Ypair[1], 51 - 36, cpu.CMR.par_bit);
7780 putbits36_1 (& cpu.Ypair[1], 52 - 36, cpu.CMR.lev_ful);
7781 putbits36_1 (& cpu.Ypair[1], 54 - 36, cpu.CMR.csh1_on);
7782 putbits36_1 (& cpu.Ypair[1], 55 - 36, cpu.CMR.csh2_on);
7783 L68_ (putbits36_1 (& cpu.Ypair[1], 56 - 36, cpu.CMR.opnd_on);)
7784 putbits36_1 (& cpu.Ypair[1], 57 - 36, cpu.CMR.inst_on);
7785 putbits36_1 (& cpu.Ypair[1], 59 - 36, cpu.CMR.csh_reg);
7786 putbits36_1 (& cpu.Ypair[1], 60 - 36, cpu.CMR.str_asd);
7787 putbits36_1 (& cpu.Ypair[1], 61 - 36, cpu.CMR.col_ful);
7788 putbits36_2 (& cpu.Ypair[1], 62 - 36, cpu.CMR.rro_AB);
7789 DPS8M_ (putbits36_1 (& cpu.Ypair[1], 68 - 36, cpu.CMR.bypass_cache);)
7790 putbits36_2 (& cpu.Ypair[1], 70 - 36, cpu.CMR.luf);
7791 }
7792 break;
7793
7794 case 010: // C(APU history register#2) -> C(Y-pair)
7795 {
7796 uint reg = cpu.tweaks.l68_mode ? L68_DU_HIST_REG : DPS8M_EAPU_HIST_REG;
7797 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7798 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7799 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7800 }
7801 break;
7802
7803 case 020: // C(CU history register) -> C(Y-pair)
7804 {
7805 cpu.Ypair[0] =
7806 cpu.history[CU_HIST_REG]
7807 [cpu.history_cyclic[CU_HIST_REG]][0];
7808 cpu.Ypair[1] =
7809 cpu.history[CU_HIST_REG]
7810 [cpu.history_cyclic[CU_HIST_REG]][1];
7811 cpu.history_cyclic[CU_HIST_REG] =
7812 (cpu.history_cyclic[CU_HIST_REG] + 1) % N_MODEL_HIST_SIZE;
7813 }
7814 break;
7815
7816 case 040: // C(OU/DU history register) -> C(Y-pair)
7817 {
7818 uint reg = cpu.tweaks.l68_mode ? L68_OU_HIST_REG : DPS8M_DU_OU_HIST_REG;
7819 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7820 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7821 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7822 }
7823 break;
7824
7825 default:
7826 {
7827 doFault (FAULT_IPR,
7828 fst_ill_mod,
7829 "SCPR Illegal register select value");
7830 }
7831 }
7832 }
7833 break;
7834
7835 case x0 (0657): // scu
7836 // AL-39 defines the behavior of SCU during fault/interrupt
7837 // processing, but not otherwise.
7838 // The T&D tape uses SCU during normal processing, and apparently
7839 // expects the current CU state to be saved.
7840
7841 if (cpu.cycle == EXEC_cycle)
7842 {
7843 // T&D behavior
7844
7845 // An 'Add Delta' addressing mode will alter the TALLY bit;
7846 // restore it.
7847 //SC_I_TALLY (cpu.currentInstruction.stiTally == 0);
7848
7849 scu2words (cpup, cpu.Yblock8);
7850 }
7851 else
7852 {
7853 // AL-39 behavior
7854 for (int j = 0; j < 8; j ++)
7855 cpu.Yblock8[j] = cpu.scu_data[j];
7856 }
7857 break;
7858
7859 case x0 (0154): // sdbr
7860 {
7861 CPTUR (cptUseDSBR);
7862 // C(DSBR.ADDR) -> C(Y-pair) 0,23
7863 // 00...0 -> C(Y-pair) 24,36
7864 cpu.Ypair[0] = ((word36) (cpu.DSBR.ADDR & PAMASK)) << (35 - 23);
7865
7866 // C(DSBR.BOUND) -> C(Y-pair) 37,50
7867 // 0000 -> C(Y-pair) 51,54
7868 // C(DSBR.U) -> C(Y-pair) 55
7869 // 000 -> C(Y-pair) 56,59
7870 // C(DSBR.STACK) -> C(Y-pair) 60,71
7871 cpu.Ypair[1] = ((word36) (cpu.DSBR.BND & 037777)) << (71 - 50) |
7872 ((word36) (cpu.DSBR.U & 1)) << (71 - 55) |
7873 ((word36) (cpu.DSBR.STACK & 07777)) << (71 - 71);
7874 }
7875 break;
7876
7877 case x1 (0557): // sptp
7878 {
7879 // XXX AL39 The associative memory is ignored (forced to "no match") during address
7880 // preparation.
7881 // Level j is selected by C(TPR.CA)12,13
7882 uint level;
7883 L68_ (level = 0;)
7884 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7885 uint toffset = level * 16;
7886 for (uint j = 0; j < 16; j ++)
7887 {
7888 cpu.Yblock16[j] = 0;
7889 putbits36_15 (& cpu.Yblock16[j], 0,
7890 cpu.PTWAM[toffset + j].POINTER);
7891 DPS8M_ (
7892 putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO & 07760);
7893
7894 uint parity = 0;
7895 if (cpu.PTWAM[toffset + j].FE) {
7896 // calculate parity
7897 // 58009997-040 p.101,111
7898 parity = ((uint) cpu.PTWAM[toffset + j].POINTER << 4) | (cpu.PTWAM[toffset + j].PAGENO >> 8);
7899 parity = parity ^ (parity >>16);
7900 parity = parity ^ (parity >> 8);
7901 parity = parity ^ (parity >> 4);
7902 parity = ~ (0x6996u >> (parity & 0xf));
7903 }
7904 putbits36_1 (& cpu.Yblock16[j], 23, (word1) (parity & 1));
7905 )
7906 L68_ (putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO); )
7907 putbits36_1 (& cpu.Yblock16[j], 27,
7908 cpu.PTWAM[toffset + j].FE);
7909 DPS8M_ (putbits36_6 (& cpu.Yblock16[j], 30, cpu.PTWAM[toffset + j].USE);)
7910 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.PTWAM[toffset + j].USE);)
7911 }
7912 }
7913 break;
7914
7915 case x1 (0154): // sptr
7916 {
7917 // XXX The associative memory is ignored (forced to "no match") during address
7918 // preparation.
7919
7920 // Level j is selected by C(TPR.CA)12,13
7921 uint level;
7922 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7923 L68_ (level = 0;)
7924 uint toffset = level * 16;
7925 for (uint j = 0; j < 16; j ++)
7926 {
7927 cpu.Yblock16[j] = 0;
7928 DPS8M_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR & 0777760);)
7929 L68_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR);)
7930 putbits36_1 (& cpu.Yblock16[j], 29,
7931 cpu.PTWAM[toffset + j].M);
7932 }
7933 }
7934 break;
7935
7936 case x0 (0557): // ssdp
7937 {
7938 // XXX AL39: The associative memory is ignored (forced to "no match")
7939 // during address preparation.
7940 // Level j is selected by C(TPR.CA)12,13
7941 uint level;
7942 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7943 L68_ (level = 0;)
7944 uint toffset = level * 16;
7945 for (uint j = 0; j < 16; j ++)
7946 {
7947 cpu.Yblock16[j] = 0;
7948 putbits36_15 (& cpu.Yblock16[j], 0,
7949 cpu.SDWAM[toffset + j].POINTER);
7950 putbits36_1 (& cpu.Yblock16[j], 27,
7951 cpu.SDWAM[toffset + j].FE);
7952 DPS8M_ (
7953 uint parity = 0;
7954 if (cpu.SDWAM[toffset + j].FE) {
7955 // calculate parity
7956 // 58009997-040 p.112
7957 parity = cpu.SDWAM[toffset + j].POINTER >> 4;
7958 //parity = parity ^ (parity >>16);
7959 parity = parity ^ (parity >> 8);
7960 parity = parity ^ (parity >> 4);
7961 parity = ~ (0x6996u >> (parity & 0xf));
7962 }
7963 putbits36_1 (& cpu.Yblock16[j], 15, (word1) (parity & 1));
7964
7965 putbits36_6 (& cpu.Yblock16[j], 30, cpu.SDWAM[toffset + j].USE);
7966 )
7967 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.SDWAM[toffset + j].USE);)
7968 }
7969 }
7970 break;
7971
7972 case x1 (0254): // ssdr
7973 {
7974 // XXX AL39: The associative memory is ignored (forced to "no match") during
7975 // address preparation.
7976
7977 // Level j is selected by C(TPR.CA)11,12
7978 // Note: not bits 12,13. This is due to operand being Yblock32
7979 uint level = 0;
7980 DPS8M_ (level = (cpu.TPR.CA >> 5) & 03;)
7981 L68_ (level = 0;)
7982 uint toffset = level * 16;
7983 for (uint j = 0; j < 16; j ++)
7984 {
7985 cpu.Yblock32[j * 2] = 0;
7986 putbits36_24 (& cpu.Yblock32[j * 2], 0,
7987 cpu.SDWAM[toffset + j].ADDR);
7988 putbits36_3 (& cpu.Yblock32[j * 2], 24,
7989 cpu.SDWAM[toffset + j].R1);
7990 putbits36_3 (& cpu.Yblock32[j * 2], 27,
7991 cpu.SDWAM[toffset + j].R2);
7992 putbits36_3 (& cpu.Yblock32[j * 2], 30,
7993 cpu.SDWAM[toffset + j].R3);
7994 cpu.Yblock32[j * 2 + 1] = 0;
7995
7996 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 37 - 36,
7997 cpu.SDWAM[toffset + j].BOUND);
7998 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 51 - 36,
7999 cpu.SDWAM[toffset + j].R);
8000 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 52 - 36,
8001 cpu.SDWAM[toffset + j].E);
8002 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 53 - 36,
8003 cpu.SDWAM[toffset + j].W);
8004 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 54 - 36,
8005 cpu.SDWAM[toffset + j].P);
8006 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 55 - 36,
8007 cpu.SDWAM[toffset + j].U);
8008 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 56 - 36,
8009 cpu.SDWAM[toffset + j].G);
8010 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 57 - 36,
8011 cpu.SDWAM[toffset + j].C);
8012 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 58 - 36,
8013 cpu.SDWAM[toffset + j].EB);
8014 }
8015 }
8016 break;
8017
8018 /// Privileged - Clear Associative Memory
8019
8020 case x1 (0532): // camp
8021 {
8022 // C(TPR.CA) 16,17 control disabling or enabling the associative
8023 // memory.
8024 // This may be done to either or both halves.
8025 // The full/empty bit of cache PTWAM register is set to zero and
8026 // the LRU counters are initialized.
8027 if (cpu.tweaks.enable_wam)
8028 { // disabled, do nothing
8029 if (cpu.tweaks.l68_mode || cpu.cu.PT_ON) // only clear when enabled
8030 for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8031 {
8032 cpu.PTWAM[i].FE = 0;
8033 L68_ (cpu.PTWAM[i].USE = (word4) i;)
8034 DPS8M_ (cpu.PTWAM[i].USE = 0;)
8035 }
8036
8037 // 58009997-040 A level of the associative memory is disabled if
8038 // C(TPR.CA) 16,17 = 01
8039 // 58009997-040 A level of the associative memory is enabled if
8040 // C(TPR.CA) 16,17 = 10
8041 // Level j is selected to be enabled/disable if
8042 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8043 // All levels are selected to be enabled/disabled if
8044 // C(TPR.CA) 11,14 = 0
8045 // This is contrary to what AL39 says, so I'm not going to implement it.
8046 // In fact, I'm not even going to implement the halves.
8047
8048 DPS8M_ (if (cpu.TPR.CA != 0000002 && (cpu.TPR.CA & 3) != 0)
8049 sim_warn ("CAMP ignores enable/disable %06o\r\n", cpu.TPR.CA);)
8050 if ((cpu.TPR.CA & 3) == 02)
8051 cpu.cu.PT_ON = 1;
8052 else if ((cpu.TPR.CA & 3) == 01)
8053 cpu.cu.PT_ON = 0;
8054 }
8055 else
8056 {
8057 cpu.PTW0.FE = 0;
8058 cpu.PTW0.USE = 0;
8059 }
8060 }
8061 ucInvalidate (cpup);
8062 break;
8063
8064 case x0 (0532): // cams
8065 {
8066 // The full/empty bit of each SDWAM register is set to zero and the
8067 // LRU counters are initialized. The remainder of the contents of
8068 // the registers are unchanged. If the associative memory is
8069 // disabled, F and LRU are unchanged.
8070 // C(TPR.CA) 16,17 control disabling or enabling the associative
8071 // memory.
8072 // This may be done to either or both halves.
8073 if (cpu.tweaks.enable_wam)
8074 {
8075 if (cpu.tweaks.l68_mode || cpu.cu.SD_ON) // only clear when enabled
8076 for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8077 {
8078 cpu.SDWAM[i].FE = 0;
8079 L68_ (cpu.SDWAM[i].USE = (word4) i;)
8080 DPS8M_ (cpu.SDWAM[i].USE = 0;)
8081 }
8082 // 58009997-040 A level of the associative memory is disabled if
8083 // C(TPR.CA) 16,17 = 01
8084 // 58009997-040 A level of the associative memory is enabled if
8085 // C(TPR.CA) 16,17 = 10
8086 // Level j is selected to be enabled/disable if
8087 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8088 // All levels are selected to be enabled/disabled if
8089 // C(TPR.CA) 11,14 = 0
8090 // This is contrary to what AL39 says, so I'm not going to implement it. In
8091 // fact, I'm not even going to implement the halves.
8092
8093 DPS8M_ (if (cpu.TPR.CA != 0000006 && (cpu.TPR.CA & 3) != 0)
8094 sim_warn ("CAMS ignores enable/disable %06o\r\n", cpu.TPR.CA);)
8095 if ((cpu.TPR.CA & 3) == 02)
8096 cpu.cu.SD_ON = 1;
8097 else if ((cpu.TPR.CA & 3) == 01)
8098 cpu.cu.SD_ON = 0;
8099 }
8100 else
8101 {
8102 cpu.SDW0.FE = 0;
8103 cpu.SDW0.USE = 0;
8104 }
8105 }
8106 ucInvalidate (cpup);
8107 break;
8108
8109 /// Privileged - Configuration and Status
8110
8111 case x0 (0233): // rmcm
8112 {
8113 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8114 // specify which processor port (i.e., which system
8115 // controller) is used.
8116 uint cpu_port_num;
8117 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8118 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8119 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8120 {
8121 sim_warn ("rmcm to non-existent controller on "
8122 "cpu %d port %d\r\n",
8123 current_running_cpu_idx, cpu_port_num);
8124 break;
8125 }
8126 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8127 t_stat rc = scu_rmcm ((uint) scuUnitIdx,
8128 current_running_cpu_idx,
8129 & cpu.rA, & cpu.rQ);
8130 #if defined(TESTING)
8131 HDBGRegAW ("rmcm");
8132 HDBGRegQW ("rmcm");
8133 #endif
8134 if (rc)
8135 return rc;
8136 SC_I_ZERO (cpu.rA == 0);
8137 SC_I_NEG (cpu.rA & SIGN36);
8138 }
8139 break;
8140
8141 case x0 (0413): // rscr
8142 {
8143 // For the rscr instruction, the first 2 (DPS8M) or 3 (L68) bits of
8144 // the addr field of the instruction are used to specify which SCU.
8145 // (2 bits for the DPS8M. (Expect for x6x and x7x below, where
8146 // the selected SCU is the one holding the addressed memory).
8147
8148 // According to DH02:
8149 // XXXXXX0X SCU Mode Register (Level 66 only)
8150 // XXXXXX1X Configuration switches
8151 // XXXXXn2X Interrupt mask port n
8152 // XXXXXX3X Interrupt cells
8153 // XXXXXX4X Elapsed time clock
8154 // XXXXXX5X Elapsed time clock
8155 // XXXXXX6X Mode register
8156 // XXXXXX7X Mode register
8157
8158 // According to privileged_mode_ut,
8159 // port*1024 + scr_input*8
8160
8161 // privileged_mode_ut makes no reference to the special case
8162 // of x6x and x7x.
8163
8164 // According to DH02, RSCR in Slave Mode does the CAF
8165 // without BAR correction, and then forces the CA to 040,
8166 // resulting in a Clock Read from the SCU on port 0.
8167
8168 // According to AL93, RSCR in BAR mode is IPR.
8169
8170 //
8171 // Implementing privileged_mode_ut.alm algorithm
8172 //
8173
8174 // Extract port number
8175 uint cpu_port_num;
8176 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 10) & 03;)
8177 L68_ (cpu_port_num = (cpu.TPR.CA >> 10) & 07;)
8178
8179 // Trace the cable from the port to find the SCU number
8180 // connected to that port
8181 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8182 {
8183 // CPTUR (cptUseFR) -- will be set by doFault
8184
8185 // Set IAn in Fault register
8186 if (cpu_port_num == 0)
8187 putbits36 (& cpu.faultRegister[0], 16, 4, 010);
8188 else if (cpu_port_num == 1)
8189 putbits36 (& cpu.faultRegister[0], 20, 4, 010);
8190 else if (cpu_port_num == 2)
8191 putbits36 (& cpu.faultRegister[0], 24, 4, 010);
8192 else
8193 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8194
8195 doFault (FAULT_CMD, fst_cmd_ctl, "(rscr)");
8196 }
8197 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8198 #if defined(PANEL68)
8199 {
8200 uint function = (cpu.iefpFinalAddress >> 3) & 07;
8201 CPT (cpt13L, function);
8202 }
8203 #endif
8204 t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8205 cpu.iefpFinalAddress & MASK15,
8206 & cpu.rA, & cpu.rQ);
8207 #if defined(TESTING)
8208 HDBGRegAW ("rscr");
8209 HDBGRegQW ("rscr");
8210 #endif
8211 if (rc)
8212 return rc;
8213 }
8214 break;
8215
8216 case x0 (0231): // rsw
8217 {
8218 if (! cpu.tweaks.l68_mode) {
8219 word6 rTAG = GET_TAG (IWB_IRODD);
8220 word6 Td = GET_TD (rTAG);
8221 word6 Tm = GET_TM (rTAG);
8222 if (Tm == TM_R && Td == TD_DL)
8223 {
8224 unsigned char PROM[1024];
8225 setupPROM (current_running_cpu_idx, PROM);
8226 cpu.rA = PROM[cpu.TPR.CA & 1023];
8227 break;
8228 }
8229 } // DPS8M
8230 uint select = cpu.TPR.CA & 0x7;
8231 switch (select)
8232 {
8233 case 0: // data switches
8234 cpu.rA = cpu.switches.data_switches;
8235 break;
8236
8237 case 1: // configuration switches for ports A, B, C, D
8238 // y = 1:
8239 //
8240 // 0 0 0 1 1 2 2 3
8241 // 0 8 9 7 8 6 7 5
8242 // -------------------------------------------------------------------------
8243 // | PORT A | PORT B | PORT C | PORT D |
8244 // -------------------------------------------------------------------------
8245 // | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8246 // -------------------------------------------------------------------------
8247 //
8248 //
8249 // ADR: Address assignment switch setting for port
8250 // This defines the base address for the SCU
8251 // j: port enabled flag
8252 // k: system initialize enabled flag
8253 // l: interface enabled flag
8254 // MEM coded memory size
8255 // 000 32K 2^15
8256 // 001 64K 2^16
8257 // 010 128K 2^17
8258 // 011 256K 2^18
8259 // 100 512K 2^19
8260 // 101 1024K 2^20
8261 // 110 2048K 2^21
8262 // 111 4096K 2^22
8263
8264 cpu.rA = 0;
8265 cpu.rA |= (word36) (cpu.switches.assignment [0] & 07LL)
8266 << (35 - (2 + 0));
8267 cpu.rA |= (word36) (cpu.switches.enable [0] & 01LL)
8268 << (35 - (3 + 0));
8269 cpu.rA |= (word36) (cpu.switches.init_enable [0] & 01LL)
8270 << (35 - (4 + 0));
8271 cpu.rA |= (word36) (cpu.switches.interlace [0] ? 1LL:0LL)
8272 << (35 - (5 + 0));
8273 cpu.rA |= (word36) (cpu.switches.store_size [0] & 07LL)
8274 << (35 - (8 + 0));
8275
8276 cpu.rA |= (word36) (cpu.switches.assignment [1] & 07LL)
8277 << (35 - (2 + 9));
8278 cpu.rA |= (word36) (cpu.switches.enable [1] & 01LL)
8279 << (35 - (3 + 9));
8280 cpu.rA |= (word36) (cpu.switches.init_enable [1] & 01LL)
8281 << (35 - (4 + 9));
8282 cpu.rA |= (word36) (cpu.switches.interlace [1] ? 1LL:0LL)
8283 << (35 - (5 + 9));
8284 cpu.rA |= (word36) (cpu.switches.store_size [1] & 07LL)
8285 << (35 - (8 + 9));
8286
8287 cpu.rA |= (word36) (cpu.switches.assignment [2] & 07LL)
8288 << (35 - (2 + 18));
8289 cpu.rA |= (word36) (cpu.switches.enable [2] & 01LL)
8290 << (35 - (3 + 18));
8291 cpu.rA |= (word36) (cpu.switches.init_enable [2] & 01LL)
8292 << (35 - (4 + 18));
8293 cpu.rA |= (word36) (cpu.switches.interlace [2] ? 1LL:0LL)
8294 << (35 - (5 + 18));
8295 cpu.rA |= (word36) (cpu.switches.store_size [2] & 07LL)
8296 << (35 - (8 + 18));
8297
8298 cpu.rA |= (word36) (cpu.switches.assignment [3] & 07LL)
8299 << (35 - (2 + 27));
8300 cpu.rA |= (word36) (cpu.switches.enable [3] & 01LL)
8301 << (35 - (3 + 27));
8302 cpu.rA |= (word36) (cpu.switches.init_enable [3] & 01LL)
8303 << (35 - (4 + 27));
8304 cpu.rA |= (word36) (cpu.switches.interlace [3] ? 1LL:0LL)
8305 << (35 - (5 + 27));
8306 cpu.rA |= (word36) (cpu.switches.store_size [3] & 07LL)
8307 << (35 - (8 + 27));
8308 break;
8309
8310 case 2: // fault base and processor number switches
8311 // y = 2:
8312 //
8313 // 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3
8314 // 0 3 4 5 6 2 3 4 7 8 9 0 1 2 3 4 5 6 8 9 2 3 5
8315 // --------------------------------------------------------------------------
8316 // |A|B|C|D| | | | | | | | | | | | | | |
8317 // --------- b | FLT BASE |c|0 0 0 0|d|e|f|0 0|g|h|i|0 0 0| SPEED | CPU |
8318 // |a|a|a|a| | | | | | | | | | | | | | |
8319 // --------------------------------------------------------------------------
8320 //
8321
8322 // a: port A-D is 0: 4 word or 1: 2 word
8323 // b: processor type 0:L68 or DPS, 1: DPS8M, 2,3: reserved for future use
8324 // c: id prom 0: not installed, 1: installed
8325 // d: 1: bcd option installed (marketing designation)
8326 // e: 1: dps option installed (marketing designation)
8327 // f: 1: 8k cache installed
8328 // g: processor type designation: 0: dps8/xx, 1: dps8m/xx
8329 // h: gcos/vms switch position: 0:GCOS mode 1: virtual mode
8330 // i: current or new product line peripheral type: 0:CPL, 1:NPL
8331 // SPEED: 0000 = 8/70, 0100 = 8/52
8332 // CPU: Processor number
8333 // DPS 8M processors:
8334 // C(Port interlace, Ports A-D) -> C(A) 0,3
8335 // 01 -> C(A) 4,5
8336 // C(Fault base switches) -> C(A) 6,12
8337 // 1 -> C(A) 13
8338 // 0000 -> C(A) 14,17
8339 // 111 -> C(A) 18,20
8340 // 00 -> C(A) 21,22
8341 // 1 -> C(A) 23
8342 // C(Processor mode sw) -> C(A) 24
8343 // 1 -> C(A) 25
8344 // 000 -> C(A) 26,28
8345 // C(Processor speed) -> C (A) 29,32
8346
8347 // C(Processor number switches) -> C(A) 33,35
8348
8349 // According to bound_gcos_.1.s.archive/gcos_fault_processor_.pl1 (L68/DPS):
8350 //
8351 // /* Set the A register to reflect switch info. */
8352 // mc.regs.a =
8353 //
8354 // /* (A-reg bits) */
8355 // /* (0-3) Port address expansion option: */ (4)"0"b
8356 // /* (4-5) Reserved for future use: */ || (2)"0"b
8357 // /* (6-12) Processor fault base address switches: */ || (7)"0"b
8358 // /* (13-16) L66 peripheral connectability: */ || (4)"0"b
8359 // /* (17) Future use (must be zero): */ || (1)"1"b
8360 // /* (18) BCD option installed: */ || (1)"1"b
8361 // /* (19) DPS type processor: */ || (1)"0"b
8362 // /* (20) 8K cache option installed: */ || (1)"0"b
8363 // /* (21) Gear shift model processor: */ || (1)"0"b
8364 // /* (22) Power patch option installed: */ || (1)"0"b
8365 // /* (23) VMS-CU option installed - 66B' proc: */ || (1)"0"b
8366 // /* (24) VMS-VU option installed - 66B proc: */ || (1)"0"b
8367 // /* (25) Type processor (0) CPL, (1) DPSE-NPL: */ || (1)"0"b
8368 // /* (26) 6025, 6605 or 6610 type processor: */ || (1)"0"b
8369 // /* (27) 2K cache option installed: */ || (1)"0"b
8370 // /* (28) Extended memory option installed: */ || (1)"0"b
8371 // /* (29-30) cabinet (00) 8/70, (01) 8/52, (10) 862, (11) 846: */ || (2)"0"b
8372 // /* (31) EIS option installed: */ || (1)"1"b
8373 // /* (32) (1) slow memory access, (0) fast memory: */ || (1)"0"b
8374 // /* (33) (1) no instruction overlap, (0) overlap: */ || (1)"0"b
8375 // /* (34-35) Processor number: */ ||unspec (mc.cpu_type);
8376
8377 cpu.rA = 0;
8378 DPS8M_ (
8379 cpu.rA |= (word36) ((cpu.switches.interlace[0] == 2 ?
8380 1LL : 0LL) << (35- 0));
8381 cpu.rA |= (word36) ((cpu.switches.interlace[1] == 2 ?
8382 1LL : 0LL) << (35- 1));
8383 cpu.rA |= (word36) ((cpu.switches.interlace[2] == 2 ?
8384 1LL : 0LL) << (35- 2));
8385 cpu.rA |= (word36) ((cpu.switches.interlace[3] == 2 ?
8386 1LL : 0LL) << (35- 3));
8387 )
8388
8389 if (cpu.tweaks.l68_mode)
8390 // NO-OP
8391 // cpu.rA |= (word36) ((00L) /* 0b00 L68/DPS */
8392 // << (35- 5));
8393 ;
8394 else
8395 cpu.rA |= (word36) ((01L) /* 0b01 DPS8M */
8396 << (35- 5));
8397 cpu.rA |= (word36) ((cpu.switches.FLT_BASE & 0177LL)
8398 << (35-12));
8399 DPS8M_ (cpu.rA |= (word36) ((01L) /* 0b1 ID_PROM installed */
8400 << (35-13));)
8401 // NO-OP
8402 // cpu.rA |= (word36) ((00L) // 0b0000
8403 // << (35-17));
8404 //cpu.rA |= (word36) ((0b111L)
8405 //<< (35-20));
8406 // According to rsw.incl.pl1, Multics ignores this bit.
8407 // NO-OP
8408 // cpu.rA |= (word36) ((00L) // 0b0 BCD option off
8409 // << (35-18));
8410 if (cpu.tweaks.l68_mode)
8411 // NO-OP
8412 // cpu.rA |= (word36) ((00L) // 0b0 L68/DPS option: L68
8413 // << (35-19));
8414 ;
8415 else
8416 cpu.rA |= (word36) ((01L) // 0b1 L68/DPS option: DPS
8417 << (35-19));
8418 DPS8M_ (
8419 // 8K cache
8420 // 0b0: not installed
8421 // 0b1: installed
8422 cpu.rA |= (word36) ((cpu.switches.enable_cache ? 1 : 0)
8423 << (35-20));
8424 // NO-OP
8425 // cpu.rA |= (word36) ((00L) // 0b00
8426 // << (35-22));
8427 cpu.rA |= (word36) ((cpu.switches.procMode) /* 0b1 DPS8M */
8428 << (35-23));
8429 cpu.rA |= (word36) ((cpu.switches.procMode & 1U)
8430 << (35-24));
8431 // NO-OP
8432 // cpu.rA |= (word36) ((00L) // 0b0 new product line (CPL/NPL)
8433 // << (35-25));
8434 // NO-OP
8435 // cpu.rA |= (word36) ((00L) // 0b000
8436 // << (35-28));
8437 cpu.rA |= (word36) ((cpu.options.proc_speed & 017LL)
8438 << (35-32));
8439 )
8440
8441 L68_ (
8442 // NO-OP
8443 // cpu.rA |= (word36) ((00L) // 0b0 2K cache disabled
8444 // << (35-27));
8445 // NO-OP
8446 // cpu.rA |= (word36) ((00L) // 0b0 GCOS mode extended memory disabled
8447 // << (35-28));
8448 cpu.rA |= (word36) ((016L) // 0b1110 CPU ID
8449 << (35-32));
8450 )
8451 cpu.rA |= (word36) ((cpu.switches.cpu_num & 07LL)
8452 << (35-35));
8453 break;
8454
8455 case 3: // configuration switches for ports E, F, G, H
8456 if (!cpu.tweaks.l68_mode) { // DPS8M
8457 cpu.rA = 0;
8458 break;
8459 }
8460 // L68
8461 // y = 3:
8462 //
8463 // 0 0 0 1 1 2 2 3
8464 // 0 8 9 7 8 6 7 5
8465 // -------------------------------------------------------------------------
8466 // | PORT E | PORT F | PORT G | PORT H |
8467 // -------------------------------------------------------------------------
8468 // | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8469 // -------------------------------------------------------------------------
8470 //
8471 //
8472 // ADR: Address assignment switch setting for port
8473 // This defines the base address for the SCU
8474 // j: port enabled flag
8475 // k: system initialize enabled flag
8476 // l: interface enabled flag
8477 // MEM coded memory size
8478 // 000 32K 2^15
8479 // 001 64K 2^16
8480 // 010 128K 2^17
8481 // 011 256K 2^18
8482 // 100 512K 2^19
8483 // 101 1024K 2^20
8484 // 110 2048K 2^21
8485 // 111 4096K 2^22
8486
8487 cpu.rA = 0;
8488 cpu.rA |= (word36) (cpu.switches.assignment [4] & 07LL)
8489 << (35 - (2 + 0));
8490 cpu.rA |= (word36) (cpu.switches.enable [4] & 01LL)
8491 << (35 - (3 + 0));
8492 cpu.rA |= (word36) (cpu.switches.init_enable [4] & 01LL)
8493 << (35 - (4 + 0));
8494 cpu.rA |= (word36) (cpu.switches.interlace [4] ? 1LL:0LL)
8495 << (35 - (5 + 0));
8496 cpu.rA |= (word36) (cpu.switches.store_size [4] & 07LL)
8497 << (35 - (8 + 0));
8498
8499 cpu.rA |= (word36) (cpu.switches.assignment [5] & 07LL)
8500 << (35 - (2 + 9));
8501 cpu.rA |= (word36) (cpu.switches.enable [5] & 01LL)
8502 << (35 - (3 + 9));
8503 cpu.rA |= (word36) (cpu.switches.init_enable [5] & 01LL)
8504 << (35 - (4 + 9));
8505 cpu.rA |= (word36) (cpu.switches.interlace [5] ? 1LL:0LL)
8506 << (35 - (5 + 9));
8507 cpu.rA |= (word36) (cpu.switches.store_size [5] & 07LL)
8508 << (35 - (8 + 9));
8509
8510 cpu.rA |= (word36) (cpu.switches.assignment [6] & 07LL)
8511 << (35 - (2 + 18));
8512 cpu.rA |= (word36) (cpu.switches.enable [6] & 01LL)
8513 << (35 - (3 + 18));
8514 cpu.rA |= (word36) (cpu.switches.init_enable [6] & 01LL)
8515 << (35 - (4 + 18));
8516 cpu.rA |= (word36) (cpu.switches.interlace [6] ? 1LL:0LL)
8517 << (35 - (5 + 18));
8518 cpu.rA |= (word36) (cpu.switches.store_size [6] & 07LL)
8519 << (35 - (8 + 18));
8520
8521 cpu.rA |= (word36) (cpu.switches.assignment [7] & 07LL)
8522 << (35 - (2 + 27));
8523 cpu.rA |= (word36) (cpu.switches.enable [7] & 01LL)
8524 << (35 - (3 + 27));
8525 cpu.rA |= (word36) (cpu.switches.init_enable [7] & 01LL)
8526 << (35 - (4 + 27));
8527 cpu.rA |= (word36) (cpu.switches.interlace [7] ? 1LL:0LL)
8528 << (35 - (5 + 27));
8529 cpu.rA |= (word36) (cpu.switches.store_size [7] & 07LL)
8530 << (35 - (8 + 27));
8531 break;
8532
8533 case 4:
8534 // I suspect the this is a L68 only, but AL39 says both
8535 // port interlace and half/full size
8536 // The DPS doesn't seem to have the half/full size switches
8537 // so we'll always report full, and the interlace bits were
8538 // squeezed into RSW 2
8539
8540 // 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3
8541 // 0 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 5
8542 // -------------------------------------------------------------------------
8543 // | | A | B | C | D | E | F | G | H | |
8544 // |0 0 0 0 0 0 0 0 0 0 0 0 0---------------------------------0 0 0 0 0 0 0|
8545 // | |f|g|f|g|f|g|f|g|f|g|f|g|f|g|f|g| |
8546 // -------------------------------------------------------------------------
8547 // 13 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7
8548
8549 cpu.rA = 0;
8550 cpu.rA |= (word36) (cpu.switches.interlace [0] == 2 ?
8551 1LL : 0LL) << (35-13);
8552 cpu.rA |= (word36) (cpu.switches.interlace [1] == 2 ?
8553 1LL : 0LL) << (35-15);
8554 cpu.rA |= (word36) (cpu.switches.interlace [2] == 2 ?
8555 1LL : 0LL) << (35-17);
8556 cpu.rA |= (word36) (cpu.switches.interlace [3] == 2 ?
8557 1LL : 0LL) << (35-19);
8558 L68_ (
8559 cpu.rA |= (word36) (cpu.switches.interlace [4] == 2 ?
8560 1LL : 0LL) << (35-21);
8561 cpu.rA |= (word36) (cpu.switches.interlace [5] == 2 ?
8562 1LL : 0LL) << (35-23);
8563 cpu.rA |= (word36) (cpu.switches.interlace [6] == 2 ?
8564 1LL : 0LL) << (35-25);
8565 cpu.rA |= (word36) (cpu.switches.interlace [7] == 2 ?
8566 1LL : 0LL) << (35-27);
8567 )
8568 break;
8569
8570 default:
8571 // XXX Guessing values; also we don't know if this is actually a fault
8572 doFault (FAULT_IPR,
8573 fst_ill_mod,
8574 "Illegal register select value");
8575 }
8576 #if defined(TESTING)
8577 HDBGRegAW ("rsw");
8578 #endif
8579 SC_I_ZERO (cpu.rA == 0);
8580 SC_I_NEG (cpu.rA & SIGN36);
8581 }
8582 break;
8583
8584 /// Privileged - System Control
8585
8586 case x0 (0015): // cioc
8587 {
8588
8589 #if defined(THREADZ) || defined(LOCKLESS)
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601 #endif
8602
8603 // cioc The system controller addressed by Y (i.e., contains
8604 // the word at Y) sends a connect signal to the port specified
8605 // by C(Y) 33,35.
8606 int cpu_port_num = lookup_cpu_mem_map (cpup, cpu.iefpFinalAddress);
8607 // If there is no port to that memory location, fault
8608 if (cpu_port_num < 0)
8609 {
8610 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8611 }
8612 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8613 {
8614 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8615 }
8616 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8617
8618 // expander word
8619 // dcl 1 scs$reconfig_general_cow aligned external, /* Used during reconfig
8620 // ops. */
8621 // 2 pad bit (36) aligned,
8622 // 2 cow, /* Connect operand word, in odd location. */
8623 // 3 sub_mask bit (8) unaligned, /* Expander sub-port mask */
8624 // 3 mbz1 bit (13) unaligned,
8625 // 3 expander_command bit (3) unaligned, /* Expander command. */
8626 // 3 mbz2 bit (9) unaligned,
8627 // 3 controller_port fixed bin (3) unaligned unsigned;/* controller port for
8628 // this CPU */
8629
8630 word8 sub_mask = getbits36_8 (cpu.CY, 0);
8631 word3 expander_command = getbits36_3 (cpu.CY, 21);
8632 uint scu_port_num = (uint) getbits36_3 (cpu.CY, 33);
8633 scu_cioc (current_running_cpu_idx, (uint) scuUnitIdx, scu_port_num,
8634 expander_command, sub_mask);
8635 }
8636 break;
8637
8638 case x0 (0553): // smcm
8639 {
8640 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8641 // specify which processor port (i.e., which system
8642 // controller) is used.
8643 uint cpu_port_num;
8644 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8645 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8646 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8647 {
8648 sim_warn ("smcm to non-existent controller on "
8649 "cpu %d port %d\r\n",
8650 current_running_cpu_idx, cpu_port_num);
8651 break;
8652 }
8653 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8654 t_stat rc = scu_smcm ((uint) scuUnitIdx,
8655 current_running_cpu_idx, cpu.rA, cpu.rQ);
8656 if (rc)
8657 return rc;
8658 }
8659 break;
8660
8661 case x0 (0451): // smic
8662 {
8663 // For the smic instruction, the first 2 or 3 bits of the addr
8664 // field of the instruction are used to specify which SCU.
8665 // 2 bits for the DPS8M.
8666 //int scuUnitIdx = getbits36_2 (TPR.CA, 0);
8667
8668 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8669 // specify which processor port (i.e., which system
8670 // controller) is used.
8671 uint cpu_port_num;
8672 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8673 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8674 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8675 {
8676 DPS8M_ (return SCPE_OK;)
8677 // L68
8678 // CPTUR (cptUseFR) -- will be set by doFault
8679 if (cpu_port_num == 0)
8680 putbits36_4 (& cpu.faultRegister[0], 16, 010);
8681 else if (cpu_port_num == 1)
8682 putbits36_4 (& cpu.faultRegister[0], 20, 010);
8683 else if (cpu_port_num == 2)
8684 putbits36_4 (& cpu.faultRegister[0], 24, 010);
8685 else if (cpu_port_num == 3)
8686 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8687 // XXX What if the port is > 3?
8688 doFault (FAULT_CMD, fst_cmd_ctl, "(smic)");
8689 }
8690 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8691 t_stat rc = scu_smic (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8692 cpu_port_num, cpu.rA);
8693 if (rc)
8694 return rc;
8695 }
8696 break;
8697
8698 case x0 (0057): // sscr
8699 {
8700 //uint cpu_port_num = (cpu.TPR.CA >> 15) & 03;
8701 // Looking at privileged_mode_ut.alm, shift 10 bits...
8702 uint cpu_port_num;
8703 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 10) & 03;)
8704 L68_ (cpu_port_num = (cpu.TPR.CA >> 10) & 07;)
8705 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8706 {
8707 // CPTUR (cptUseFR) -- will be set by doFault
8708 if (cpu_port_num == 0)
8709 putbits36_4 (& cpu.faultRegister[0], 16, 010);
8710 else if (cpu_port_num == 1)
8711 putbits36_4 (& cpu.faultRegister[0], 20, 010);
8712 else if (cpu_port_num == 2)
8713 putbits36_4 (& cpu.faultRegister[0], 24, 010);
8714 else
8715 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8716 doFault (FAULT_CMD, fst_cmd_ctl, "(sscr)");
8717 }
8718 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8719 t_stat rc = scu_sscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8720 cpu_port_num, cpu.iefpFinalAddress & MASK15,
8721 cpu.rA, cpu.rQ);
8722
8723 if (rc)
8724 return rc;
8725 }
8726 break;
8727
8728 // Privileged - Miscellaneous
8729
8730 case x0 (0212): // absa
8731 {
8732 word36 result;
8733 int rc = doABSA (cpup, & result);
8734 if (rc)
8735 return rc;
8736 cpu.rA = result;
8737 #if defined(TESTING)
8738 HDBGRegAW ("absa");
8739 #endif
8740 SC_I_ZERO (cpu.rA == 0);
8741 SC_I_NEG (cpu.rA & SIGN36);
8742 }
8743 break;
8744
8745 case x0 (0616): // dis
8746
8747 #ifdef SYNCTEST
8748 // Trap the call to sys$trouble
8749 if (cpu.PPR.PSR == 034 && cpu.PPR.IC == 03535) {
8750 # ifdef HDBG
8751 hdbgPrint ();
8752 # endif
8753 sim_printf ("sys$trouble\r\n");
8754 exit (1);
8755 }
8756 #endif
8757
8758 #if defined(THREADZ) || defined(LOCKLESS)
8759 if (cpu.forceRestart) {
8760 cpu.forceRestart = 0;
8761 longjmp (cpu.jmpMain, JMP_FORCE_RESTART);
8762 }
8763 #endif
8764
8765 if (! cpu.tweaks.dis_enable)
8766 {
8767 return STOP_STOP;
8768 }
8769
8770 // XXX This is subtle; g7Pending below won't see the queued
8771 // g7Fault. I don't understand how the real hardware dealt
8772 // with this, but this seems to work. (I would hazard a guess
8773 // that DIS was doing a continuous FETCH/EXECUTE cycle
8774 // ('if !interrupt goto .'))
8775 advanceG7Faults (cpup);
8776
8777 if ((! cpu.tweaks.tro_enable) &&
8778 (! sample_interrupts (cpup)) &&
8779 (sim_qcount () == 0)) // XXX If clk_svc is implemented it will
8780 // break this logic
8781 {
8782 sim_printf ("DIS@0%06o with no interrupts pending and"
8783 " no events in queue\r\n", cpu.PPR.IC);
8784 #if defined(WIN_STDIO)
8785 sim_printf ("\r\nCycles = %llu\r\n",
8786 #else
8787 sim_printf ("\r\nCycles = %'llu\r\n",
8788 #endif /* if defined(WIN_STDIO) */
8789 (unsigned long long)cpu.cycleCnt);
8790 #if defined(WIN_STDIO)
8791 sim_printf ("\r\nInstructions = %llu\r\n",
8792 #else
8793 sim_printf ("\r\nInstructions = %'llu\r\n",
8794 #endif /* if defined(WIN_STDIO) */
8795 (unsigned long long)cpu.cycleCnt);
8796 longjmp (cpu.jmpMain, JMP_STOP);
8797 }
8798
8799 // Multics/BCE halt
8800 if (cpu.PPR.PSR == 0430 && cpu.PPR.IC == 012)
8801 {
8802 sim_printf ("BCE DIS causes CPU halt\r\n");
8803 sim_debug (DBG_MSG, & cpu_dev, "BCE DIS causes CPU halt\r\n");
8804 #if defined(LOCKLESS)
8805 bce_dis_called = true;
8806 #endif // LOCKLESS
8807 longjmp (cpu.jmpMain, JMP_STOP);
8808 }
8809
8810 #if defined(THREADZ) || defined(LOCKLESS)
8811 // RCF halt
8812 // XXX pxss uses a distinctive DIS operation
8813 // for RCF DELETE. If we see it, remember that
8814 // we did.
8815 if (IWB_IRODD == 0000777616207) {
8816 //HDBGNote (cpup, "DIS", "DIS clears inMultics%s", "");
8817 cpu.inMultics = false;
8818 }
8819
8820 // ISOLTS start:
8821 // CPU B thread created.
8822 // DBG(1)> CPU 1 TRACE: 000000 0 000000616000 (DIS 000000)
8823 // DBG(3)> CPU 1 INTR: Interrupt pair address 0
8824 // DBG(3)> CPU 1 FINAL: intr even read 00000000 000000755200
8825 // DBG(3)> CPU 1 FINAL: intr odd read 00000001 000000616200
8826 // DBG(4)> CPU 1 TRACE: 000001 0 000000755200 (STA 000000)
8827 // DBG(4)> CPU 1 REG: sta read A 000000000000
8828 // DBG(4)> CPU 1 IEFP ABS WRITE: :000000
8829 // DBG(4)> CPU 1 FINAL: WriteOperandStore AB write 00000000 000000000000
8830 // DBG(5)> CPU 1 TRACE: 000001 0 000000616200 (DIS 000000)
8831 // There are different behaviors for various configuration errors.
8832 // If ISOLTS mode is not set, we see an IWB_IRODD of 0000000616200
8833 // If set, 0000001616200
8834
8835 // If we do a DIS while sync clock master, and are inMultics,
8836 // cancel sync clock... But not the processor startup DIS
8837
8838 if (UNLIKELY (cpu.syncClockModeMaster) &&
8839 cpu.inMultics &&
8840 (cpu.PPR.PSR !=0 || cpu.PPR.IC != 0)) {
8841 # ifdef SYNCTEST
8842 sim_printf ("CPU%c DIS %o:%o gives up master\r\n", cpu.cpuIdx + 'A', cpu.PPR.PSR, cpu.PPR.IC);
8843 # endif
8844 //HDBGNote (cpup, "DIS", "DIS give up clock master%s", "");
8845 giveupClockMaster (cpup);
8846 }
8847 #endif
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868 sim_debug (DBG_TRACEEXT, & cpu_dev, "entered DIS_cycle\r\n");
8869
8870 // No operation takes place, and the processor does not
8871 // continue with the next instruction; it waits for a
8872 // external interrupt signal.
8873 // AND, according to pxss.alm, TRO
8874
8875 // Bless NovaScale...
8876 // DIS
8877 //
8878 // NOTES:
8879 //
8880 // 1. The inhibit bit in this instruction only affects the recognition
8881 // of a Timer Runout (TROF) fault.
8882 //
8883 // Inhibit ON delays the recognition of a TROF until the processor
8884 // enters Slave mode.
8885 //
8886 // Inhibit OFF allows the TROF to interrupt the DIS state.
8887 //
8888 // 2. For all other faults and interrupts, the inhibit bit is ignored.
8889 //
8890 // 3. The use of this instruction in the Slave or Master mode causes a
8891 // Command fault.
8892
8893 if (sample_interrupts (cpup))
8894 {
8895 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees an interrupt\r\n");
8896 cpu.interrupt_flag = true;
8897 break;
8898 }
8899 // Implementing TRO according to AL39 for the DIS cause the idle systems to
8900 // hang in the DIS instruction. Revert back to the old behavior.
8901
8902 if (GET_I (cpu.cu.IWB) ? bG7PendingNoTRO (cpup) : bG7Pending (cpup))
8903
8904
8905
8906
8907
8908
8909
8910
8911 {
8912 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees a TRO\r\n");
8913 cpu.g7_flag = true;
8914 break;
8915 }
8916 else
8917 {
8918 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS refetches\r\n");
8919 return CONT_DIS;
8920 }
8921
8922 /// POINTER REGISTER INSTRUCTIONS
8923
8924 /// PRIVILEGED INSTRUCTIONS
8925
8926 /// Privileged - Register Load
8927
8928 /// Privileged - Clear Associative Memory
8929
8930 /// EIS - Address Register Load
8931
8932 // aarn
8933 case x1 (0560): // aar0
8934 case x1 (0561): // aar1
8935 case x1 (0562): // aar2
8936 case x1 (0563): // aar3
8937 case x1 (0564): // aar4
8938 case x1 (0565): // aar5
8939 case x1 (0566): // aar6
8940 case x1 (0567): // aar7
8941 {
8942 // For n = 0, 1, ..., or 7 as determined by operation code
8943 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
8944
8945 if (getbits36_1 (cpu.CY, 23) != 0)
8946 doFault (FAULT_IPR,
8947 fst_ill_proc,
8948 "aarn C(Y)23 != 0");
8949
8950 uint32 n = opcode10 & 07; // get
8951 CPTUR (cptUsePRn + n);
8952
8953 // C(Y)0,17 -> C(ARn.WORDNO)
8954 cpu.AR[n].WORDNO = GETHI (cpu.CY);
8955
8956 uint TA = getbits36_2 (cpu.CY, 21);
8957 uint CN = getbits36_3 (cpu.CY, 18);
8958
8959 switch (TA)
8960 {
8961 case CTA4: // 2
8962 // If C(Y)21,22 = 10 (TA code = 2), then
8963 // C(Y)18,20 / 2 -> C(ARn.CHAR)
8964 // 4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
8965
8966 // According to AL39, CN is translated:
8967 // CN CHAR BIT
8968 // 0 0 1
8969 // 1 0 5
8970 // 2 1 1
8971 // 3 1 5
8972 // 4 2 1
8973 // 5 2 5
8974 // 6 3 1
8975 // 7 3 5
8976 //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
8977
8978 // According to ISOLTS ps805
8979 // CN CHAR BIT
8980 // 0 0 0
8981 // 1 0 5
8982 // 2 1 0
8983 // 3 1 5
8984 // 4 2 0
8985 // 5 2 5
8986 // 6 3 0
8987 // 7 3 5
8988 SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
8989
8990 break;
8991
8992 case CTA6: // 1
8993 // If C(Y)21,22 = 01 (TA code = 1) and C(Y)18,20 = 110
8994 // or 111 an illegal procedure fault occurs.
8995 if (CN > 5)
8996 {
8997 cpu.AR[n].WORDNO = 0;
8998 SET_AR_CHAR_BITNO (n, 0, 0);
8999 doFault (FAULT_IPR, fst_ill_proc, "aarn TN > 5");
9000 }
9001
9002 // If C(Y)21,22 = 01 (TA code = 1), then
9003 // (6 * C(Y)18,20) / 9 -> C(ARn.CHAR)
9004 // (6 * C(Y)18,20)mod9 -> C(ARn.BITNO)
9005 SET_AR_CHAR_BITNO (n, (word2) ((6 * CN) / 9),
9006 (6 * CN) % 9);
9007 break;
9008
9009 case CTA9: // 0
9010 // If C(Y)21,22 = 00 (TA code = 0), then
9011 // C(Y)18,19 -> C(ARn.CHAR)
9012 // 0000 -> C(ARn.BITNO)
9013 // remember, 9-bit CN's are funky
9014 SET_AR_CHAR_BITNO (n, (word2) (CN >> 1), 0);
9015 break;
9016
9017 case CTAILL: // 3
9018 // If C(Y)21,22 = 11 (TA code = 3) an illegal procedure
9019 // fault occurs.
9020 cpu.AR[n].WORDNO = 0;
9021 SET_AR_CHAR_BITNO (n, 0, 0);
9022 #if defined(TESTING)
9023 HDBGRegARW (n, "aarn");
9024 #endif
9025 doFault (FAULT_IPR, fst_ill_proc, "aarn TA = 3");
9026 }
9027 #if defined(TESTING)
9028 HDBGRegARW (n, "aarn");
9029 #endif
9030 }
9031 break;
9032
9033 // Load Address Register n
9034 // larn
9035 case x1 (0760): // lar0
9036 case x1 (0761): // lar1
9037 case x1 (0762): // lar2
9038 case x1 (0763): // lar3
9039 case x1 (0764): // lar4
9040 case x1 (0765): // lar5
9041 case x1 (0766): // lar6
9042 case x1 (0767): // lar7
9043 {
9044 // For n = 0, 1, ..., or 7 as determined by operation code
9045 // C(Y)0,23 -> C(ARn)
9046 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9047
9048 uint32 n = opcode10 & 07; // get n
9049 CPTUR (cptUsePRn + n);
9050 cpu.AR[n].WORDNO = GETHI (cpu.CY);
9051 // AL-38 implies CHAR/BITNO, but ISOLTS requires PR.BITNO.
9052 SET_AR_CHAR_BITNO (n, getbits36_2 (cpu.CY, 18),
9053 getbits36_4 (cpu.CY, 20));
9054 #if defined(TESTING)
9055 HDBGRegARW (n, "larn");
9056 #endif
9057 }
9058 break;
9059
9060 // lareg - Load Address Registers
9061
9062 case x1 (0463): // lareg
9063 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9064
9065 for (uint32 n = 0 ; n < 8 ; n += 1)
9066 {
9067 CPTUR (cptUsePRn + n);
9068 word36 tmp36 = cpu.Yblock8[n];
9069 cpu.AR[n].WORDNO = getbits36_18 (tmp36, 0);
9070 SET_AR_CHAR_BITNO (n, getbits36_2 (tmp36, 18),
9071 getbits36_4 (tmp36, 20));
9072 #if defined(TESTING)
9073 HDBGRegARW (n, "lareg");
9074 #endif
9075 }
9076 break;
9077
9078 // lpl - Load Pointers and Lengths
9079
9080 case x1 (0467): // lpl
9081 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9082 words2du (cpup, cpu.Yblock8);
9083 break;
9084
9085 // narn - (G'Kar?) Numeric Descriptor to Address Register n
9086 // narn
9087 case x1 (0660): // nar0
9088 case x1 (0661): // nar1
9089 case x1 (0662): // nar2
9090 case x1 (0663): // nar3
9091 case x1 (0664): // nar4
9092 case x1 (0665): // nar5
9093 case x1 (0666): // nar6 beware!!!! :-)
9094 case x1 (0667): // nar7
9095 {
9096 // For n = 0, 1, ..., or 7 as determined by operation code
9097 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9098
9099 uint32 n = opcode10 & 07; // get
9100 CPTUR (cptUsePRn + n);
9101
9102 // C(Y)0,17 -> C(ARn.WORDNO)
9103 cpu.AR[n].WORDNO = GETHI (cpu.CY);
9104
9105 uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9106 uint CN = getbits36_3 (cpu.CY, 18); // C(Y) 18-20
9107
9108 switch(TN)
9109 {
9110 case CTN4: // 1
9111 // If C(Y)21 = 1 (TN code = 1), then
9112 // (C(Y)18,20) / 2 -> C(ARn.CHAR)
9113 // 4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
9114
9115 // According to AL39, CN is translated:
9116 // CN CHAR BIT
9117 // 0 0 1
9118 // 1 0 5
9119 // 2 1 1
9120 // 3 1 5
9121 // 4 2 1
9122 // 5 2 5
9123 // 6 3 1
9124 // 7 3 5
9125 //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
9126
9127 // According to ISOLTS ps805
9128 // CN CHAR BIT
9129 // 0 0 0
9130 // 1 0 5
9131 // 2 1 0
9132 // 3 1 5
9133 // 4 2 0
9134 // 5 2 5
9135 // 6 3 0
9136 // 7 3 5
9137 SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
9138
9139 break;
9140
9141 case CTN9: // 0
9142 // If C(Y)21 = 0 (TN code = 0) and C(Y)20 = 1 an
9143 // illegal procedure fault occurs.
9144 if ((CN & 1) != 0)
9145 doFault (FAULT_IPR, fst_ill_proc, "narn N9 and CN odd");
9146 // The character number is in bits 18-19; recover it
9147 CN >>= 1;
9148 // If C(Y)21 = 0 (TN code = 0), then
9149 // C(Y)18,20 -> C(ARn.CHAR)
9150 // 0000 -> C(ARn.BITNO)
9151 SET_AR_CHAR_BITNO (n, (word2) CN, 0);
9152 break;
9153 }
9154 #if defined(TESTING)
9155 HDBGRegARW (n, "narn");
9156 #endif
9157 }
9158 break;
9159
9160 /// EIS - Address Register Store
9161
9162 // aran Address Register n to Alphanumeric Descriptor
9163
9164 // aran
9165 case x1 (0540): // ara0
9166 case x1 (0541): // ara1
9167 case x1 (0542): // ara2
9168 case x1 (0543): // ara3
9169 case x1 (0544): // ara4
9170 case x1 (0545): // ara5
9171 case x1 (0546): // ara6
9172 case x1 (0547): // ara7
9173 {
9174 // The alphanumeric descriptor is fetched from Y and C(Y)21,22
9175 // (TA field) is examined to determine the data type described.
9176 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9177
9178 uint TA = getbits36_2 (cpu.CY, 21);
9179
9180 // If C(Y)21,22 = 11 (TA code = 3) or C(Y)23 = 1 (unused bit),
9181 // an illegal procedure fault occurs.
9182 if (TA == 03) {
9183 dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn tag == 3");
9184 break;
9185 }
9186 if (getbits36_1 (cpu.CY, 23) != 0) {
9187 dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn b23 == 1");
9188 break;
9189 }
9190
9191 uint32 n = opcode10 & 07; // get
9192 CPTUR (cptUsePRn + n);
9193 // For n = 0, 1, ..., or 7 as determined by operation code
9194
9195 // C(ARn.WORDNO) -> C(Y)0,17
9196 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9197
9198 // If TA = 1 (6-bit data) or TA = 2 (4-bit data), C(ARn.CHAR)
9199 // and C(ARn.BITNO) are translated to an equivalent character
9200 // position that goes to C(Y)18,20.
9201
9202 int CN = 0;
9203
9204 switch (TA)
9205 {
9206 case CTA4: // 2
9207 // If C(Y)21,22 = 10 (TA code = 2), then
9208 // (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 -> C(Y)18,20
9209 CN = (9 * GET_AR_CHAR (n) + GET_AR_BITNO (n) - 1) / 4;
9210 putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9211 break;
9212
9213 case CTA6: // 1
9214 // If C(Y)21,22 = 01 (TA code = 1), then
9215 // (9 * C(ARn.CHAR) + C(ARn.BITNO)) / 6 -> C(Y)18,20
9216 CN = (9 * GET_AR_CHAR (n) + GET_AR_BITNO (n)) / 6;
9217 putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9218 break;
9219
9220 case CTA9: // 0
9221 // If C(Y)21,22 = 00 (TA code = 0), then
9222 // C(ARn.CHAR) -> C(Y)18,19
9223 // 0 -> C(Y)20
9224 putbits36_3 (& cpu.CY, 18,
9225 (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9226 break;
9227 }
9228 cpu.zone = 0777777700000;
9229 cpu.useZone = true;
9230 }
9231 break;
9232
9233 // arnn Address Register n to Numeric Descriptor
9234
9235 // aarn
9236 case x1 (0640): // aar0
9237 case x1 (0641): // aar1
9238 case x1 (0642): // aar2
9239 case x1 (0643): // aar3
9240 case x1 (0644): // aar4
9241 case x1 (0645): // aar5
9242 case x1 (0646): // aar6
9243 case x1 (0647): // aar7
9244 {
9245 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9246 uint32 n = opcode10 & 07; // get register #
9247 CPTUR (cptUsePRn + n);
9248
9249 // The Numeric descriptor is fetched from Y and C(Y)21,22 (TA
9250 // field) is examined to determine the data type described.
9251
9252 uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9253
9254 // For n = 0, 1, ..., or 7 as determined by operation code
9255 // C(ARn.WORDNO) -> C(Y)0,17
9256 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9257
9258 switch (TN)
9259 {
9260 case CTN4: // 1
9261 {
9262 // If C(Y)21 = 1 (TN code = 1) then
9263 // (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 ->
9264 // C(Y)18,20
9265 word3 CN = (9 * GET_AR_CHAR (n) +
9266 GET_AR_BITNO (n) - 1) / 4;
9267 putbits36_3 (& cpu.CY, 18, CN & MASK3);
9268 break;
9269 }
9270 case CTN9: // 0
9271 // If C(Y)21 = 0 (TN code = 0), then
9272 // C(ARn.CHAR) -> C(Y)18,19
9273 // 0 -> C(Y)20
9274 putbits36_3 (& cpu.CY, 18,
9275 (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9276 break;
9277 }
9278 cpu.zone = 0777777700000;
9279 cpu.useZone = true;
9280 }
9281 break;
9282
9283 // sarn Store Address Register n
9284
9285 // sarn
9286 case x1 (0740): // sar0
9287 case x1 (0741): // sar1
9288 case x1 (0742): // sar2
9289 case x1 (0743): // sar3
9290 case x1 (0744): // sar4
9291 case x1 (0745): // sar5
9292 case x1 (0746): // sar6
9293 case x1 (0747): // sar7
9294 //For n = 0, 1, ..., or 7 as determined by operation code
9295 // C(ARn) -> C(Y)0,23
9296 // C(Y)24,35 -> unchanged
9297 {
9298 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9299 uint32 n = opcode10 & 07; // get n
9300 CPTUR (cptUsePRn + n);
9301 putbits36 (& cpu.CY, 0, 18, cpu.PR[n].WORDNO);
9302 // AL-39 implies CHAR/BITNO, but ISOLTS test 805 requires BITNO
9303 putbits36 (& cpu.CY, 18, 2, GET_AR_CHAR (n));
9304 putbits36 (& cpu.CY, 20, 4, GET_AR_BITNO (n));
9305 //putbits36 (& cpu.CY, 18, 6, GET_PR_BITNO (n));
9306 cpu.zone = 0777777770000;
9307 cpu.useZone = true;
9308 }
9309 break;
9310
9311 // sareg Store Address Registers
9312
9313 case x1 (0443): // sareg
9314 // a:AL39/ar1 According to ISOLTS ps805, the BITNO data is stored
9315 // in BITNO format, not CHAR/BITNO.
9316 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9317 (void)memset (cpu.Yblock8, 0, sizeof (cpu.Yblock8));
9318 for (uint32 n = 0 ; n < 8 ; n += 1)
9319 {
9320 CPTUR (cptUsePRn + n);
9321 word36 arx = 0;
9322 putbits36 (& arx, 0, 18, cpu.PR[n].WORDNO);
9323 putbits36 (& arx, 18, 2, GET_AR_CHAR (n));
9324 putbits36 (& arx, 20, 4, GET_AR_BITNO (n));
9325 cpu.Yblock8[n] = arx;
9326 }
9327 break;
9328
9329 // spl Store Pointers and Lengths
9330
9331 case x1 (0447): // spl
9332 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9333 du2words (cpup, cpu.Yblock8);
9334 break;
9335
9336 /// EIS - Address Register Special Arithmetic
9337
9338 // a4bd Add 4-bit Displacement to Address Register 5
9339
9340 case x1 (0502): // a4bd
9341 asxbd (cpup, 4, false);
9342 break;
9343
9344 // a6bd Add 6-bit Displacement to Address Register
9345
9346 case x1 (0501): // a6bd
9347 asxbd (cpup, 6, false);
9348 break;
9349
9350 // a9bd Add 9-bit Displacement to Address Register
9351
9352 case x1 (0500): // a9bd
9353 asxbd (cpup, 9, false);
9354 break;
9355
9356 // abd Add Bit Displacement to Address Register
9357
9358 case x1 (0503): // abd
9359 asxbd (cpup, 1, false);
9360 break;
9361
9362 // awd Add Word Displacement to Address Register
9363
9364 case x1 (0507): // awd
9365 asxbd (cpup, 36, false);
9366 break;
9367
9368 // s4bd Subtract 4-bit Displacement from Address Register
9369
9370 case x1 (0522): // s4bd
9371 asxbd (cpup, 4, true);
9372 break;
9373
9374 // s6bd Subtract 6-bit Displacement from Address Register
9375
9376 case x1 (0521): // s6bd
9377 asxbd (cpup, 6, true);
9378 break;
9379
9380 // s9bd Subtract 9-bit Displacement from Address Register
9381
9382 case x1 (0520): // s9bd
9383 asxbd (cpup, 9, true);
9384 break;
9385
9386 // sbd Subtract Bit Displacement from Address Register
9387
9388 case x1 (0523): // sbd
9389 asxbd (cpup, 1, true);
9390 break;
9391
9392 // swd Subtract Word Displacement from Address Register
9393
9394 case x1 (0527): // swd
9395 asxbd (cpup, 36, true);
9396 break;
9397
9398 /// EIS = Alphanumeric Compare
9399
9400 case x1 (0106): // cmpc
9401 cmpc (cpup);
9402 break;
9403
9404 case x1 (0120): // scd
9405 scd (cpup);
9406 break;
9407
9408 case x1 (0121): // scdr
9409 scdr (cpup);
9410 break;
9411
9412 case x1 (0124): // scm
9413 scm (cpup);
9414 break;
9415
9416 case x1 (0125): // scmr
9417 scmr (cpup);
9418 break;
9419
9420 case x1 (0164): // tct
9421 tct (cpup);
9422 break;
9423
9424 case x1 (0165): // tctr
9425 tctr (cpup);
9426 break;
9427
9428 /// EIS - Alphanumeric Move
9429
9430 case x1 (0100): // mlr
9431 mlr (cpup);
9432 break;
9433
9434 case x1 (0101): // mrl
9435 mrl (cpup);
9436 break;
9437
9438 case x1 (0020): // mve
9439 mve (cpup);
9440 break;
9441
9442 case x1 (0160): // mvt
9443 mvt (cpup);
9444 break;
9445
9446 /// EIS - Numeric Compare
9447
9448 case x1 (0303): // cmpn
9449 cmpn (cpup);
9450 break;
9451
9452 /// EIS - Numeric Move
9453
9454 case x1 (0300): // mvn
9455 mvn (cpup);
9456 break;
9457
9458 case x1 (0024): // mvne
9459 mvne (cpup);
9460 break;
9461
9462 /// EIS - Bit String Combine
9463
9464 case x1 (0060): // csl
9465 csl (cpup);
9466 break;
9467
9468 case x1 (0061): // csr
9469 csr (cpup);
9470 break;
9471
9472 /// EIS - Bit String Compare
9473
9474 case x1 (0066): // cmpb
9475 cmpb (cpup);
9476 break;
9477
9478 /// EIS - Bit String Set Indicators
9479
9480 case x1 (0064): // sztl
9481 // The execution of this instruction is identical to the Combine
9482 // Bit Strings Left (csl) instruction except that C(BOLR)m is
9483 // not placed into C(Y-bit2)i-1.
9484 sztl (cpup);
9485 break;
9486
9487 case x1 (0065): // sztr
9488 // The execution of this instruction is identical to the Combine
9489 // Bit Strings Left (csr) instruction except that C(BOLR)m is
9490 // not placed into C(Y-bit2)i-1.
9491 sztr (cpup);
9492 break;
9493
9494 /// EIS -- Data Conversion
9495
9496 case x1 (0301): // btd
9497 btd (cpup);
9498 break;
9499
9500 case x1 (0305): // dtb
9501 dtb (cpup);
9502 break;
9503
9504 /// EIS - Decimal Addition
9505
9506 case x1 (0202): // ad2d
9507 ad2d (cpup);
9508 break;
9509
9510 case x1 (0222): // ad3d
9511 ad3d (cpup);
9512 break;
9513
9514 /// EIS - Decimal Subtraction
9515
9516 case x1 (0203): // sb2d
9517 sb2d (cpup);
9518 break;
9519
9520 case x1 (0223): // sb3d
9521 sb3d (cpup);
9522 break;
9523
9524 /// EIS - Decimal Multiplication
9525
9526 case x1 (0206): // mp2d
9527 mp2d (cpup);
9528 break;
9529
9530 case x1 (0226): // mp3d
9531 mp3d (cpup);
9532 break;
9533
9534 /// EIS - Decimal Division
9535
9536 case x1 (0207): // dv2d
9537 dv2d (cpup);
9538 break;
9539
9540 case x1 (0227): // dv3d
9541 dv3d (cpup);
9542 break;
9543
9544 case x1 (0420): // emcall instruction Custom, for an emulator call for scp
9545 {
9546 if (cpu.tweaks.enable_emcall) {
9547 int ret = emCall (cpup);
9548 if (ret)
9549 return ret;
9550 break;
9551 }
9552 goto unimp;
9553 }
9554
9555 default:
9556 unimp:
9557 if (cpu.tweaks.halt_on_unimp)
9558 return STOP_STOP;
9559 doFault (FAULT_IPR,
9560 fst_ill_op,
9561 "Illegal instruction");
9562 }
9563 L68_ (
9564 cpu.ou.STR_OP = (is_ou && (i->info->flags & (STORE_OPERAND | STORE_YPAIR))) ? 1 : 0;
9565 cpu.ou.cycle |= ou_GOF;
9566 if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_ou)
9567 add_l68_OU_history (cpup);
9568 if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_du)
9569 add_l68_DU_history (cpup);
9570 )
9571 return SCPE_OK;
9572 }
9573
9574 #include <ctype.h>
9575 #include <time.h>
9576
9577 /*
9578 * emulator call instruction. Do whatever address field sez' ....
9579 */
9580
9581 //static clockid_t clockID;
9582 //static struct timespec startTime;
9583 static uv_rusage_t startTime;
9584 static unsigned long long startInstrCnt;
9585
9586 static int emCall (cpu_state_t * cpup)
/* ![[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)
*/
9587 {
9588 #if defined(THREADZ) || defined(LOCKLESS)
9589 atomic_thread_fence (memory_order_seq_cst);
9590 #endif /* defined(THREADZ) || defined(LOCKLESS) */
9591
9592 DCDstruct * i = & cpu.currentInstruction;
9593
9594 // The address is absolute address of a structure consisting of a
9595 // operation code word and optional following words containing
9596 // data for the operation.
9597
9598 word36 op = M[i->address];
9599 switch (op)
9600 {
9601 // OP 1: Print the unsigned decimal representation of the first data
9602 // word.
9603 case 1:
9604 sim_printf ("%lld\r\n", (long long int) M[i->address+1]);
9605 break;
9606
9607 // OP 2: Halt the simulation
9608 case 2:
9609 #if defined(LOCKLESS)
9610 bce_dis_called = true;
9611 #endif
9612 return STOP_STOP;
9613
9614 #define UV_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
9615
9616 // OP 3: Start CPU clock
9617 case 3:
9618 startInstrCnt = cpu.instrCnt;
9619 uv_getrusage (& startTime);
9620 #if UV_VERSION_HEX >= UV_VERSION(1, 50, 0)
9621 if (uv_getrusage_thread(& startTime) == UV_ENOTSUP) {
9622 uv_getrusage (& startTime);
9623 }
9624 #else
9625 uv_getrusage (& startTime);
9626 #endif
9627 break;
9628
9629 // OP 4: Report CPU clock
9630 case 4:
9631 {
9632 #define ns_sec (1000000000L)
9633 #define ns_msec (1000000000L / 1000L)
9634 #define ns_usec (1000000000L / 1000L / 1000L)
9635 uv_rusage_t now;
9636 #if UV_VERSION_HEX >= UV_VERSION(1, 50, 0)
9637 if (uv_getrusage_thread(& now) == UV_ENOTSUP) {
9638 uv_getrusage (& now);
9639 }
9640 #else
9641 uv_getrusage (& now);
9642 #endif
9643 uint64_t u_start = (uint64_t)((uint64_t)(startTime.ru_utime.tv_usec * 1000ULL) +
9644 (uint64_t)(startTime.ru_utime.tv_sec * (uint64_t)ns_sec));
9645 uint64_t s_start = (uint64_t)((uint64_t)(startTime.ru_stime.tv_usec * 1000ULL) +
9646 (uint64_t)(startTime.ru_stime.tv_sec * (uint64_t)ns_sec));
9647 uint64_t u_stop = (uint64_t)((uint64_t)(now.ru_utime.tv_usec * 1000ULL) +
9648 (uint64_t)(now.ru_utime.tv_sec * (uint64_t)ns_sec));
9649 uint64_t s_stop = (uint64_t)((uint64_t)(now.ru_stime.tv_usec * 1000ULL) +
9650 (uint64_t)(now.ru_stime.tv_sec * (uint64_t)ns_sec));
9651 uint64_t u_delta = u_stop - u_start;
9652 uint64_t s_delta = s_stop - s_start;
9653 uint64_t u_seconds = u_delta / ns_sec;
9654 uint64_t s_seconds = s_delta / ns_sec;
9655 uint64_t u_milliseconds = (u_delta / ns_msec) % 1000ULL;
9656 uint64_t s_milliseconds = (s_delta / ns_msec) % 1000ULL;
9657 uint64_t u_microseconds = (u_delta / ns_usec) % 1000ULL;
9658 uint64_t s_microseconds = (s_delta / ns_usec) % 1000ULL;
9659 unsigned long long nInsts = (unsigned long long)((unsigned long long)cpu.instrCnt -
9660 (unsigned long long)startInstrCnt);
9661 double u_secs = (double)(((long double) u_delta) / ((long double) ns_sec));
9662 double s_secs = (double)(((long double) s_delta) / ((long double) ns_sec));
9663 long double ips = (long double)(((long double) nInsts) /
9664 (((long double) u_secs) + ((long double) s_secs)));
9665 long double mips = (long double)(ips / 1000000.0L);
9666
9667 struct tm tm = {0};
9668 char elapsed_time[64];
9669
9670 tm.tm_hour = u_seconds / 3600;
9671 tm.tm_min = (u_seconds % 3600) / 60;
9672 tm.tm_sec = u_seconds % 60;
9673 strftime(elapsed_time, sizeof(elapsed_time), "%H:%M:%S", &tm);
9674
9675 sim_printf ("\rUser time elapsed : %s.%03llu%03llu\r\n",
9676 elapsed_time, (unsigned long long)u_milliseconds, (unsigned long long)u_microseconds);
9677
9678 tm.tm_hour = s_seconds / 3600;
9679 tm.tm_min = (s_seconds % 3600) / 60;
9680 tm.tm_sec = s_seconds % 60;
9681 strftime(elapsed_time, sizeof(elapsed_time), "%H:%M:%S", &tm);
9682
9683 sim_printf ("\rSystem time elapsed: %s.%03llu%03llu\r\n",
9684 elapsed_time, (unsigned long long)s_milliseconds, (unsigned long long)s_microseconds);
9685 #if defined(WIN_STDIO)
9686 sim_printf ("\rInstructions : %llu\r\n", (unsigned long long) nInsts);
9687 sim_printf ("\rPerformance : %f MIPS\r\n\r\n", (double) mips);
9688 #else
9689 sim_printf ("\rInstructions : %'llu\r\n", (unsigned long long) nInsts);
9690 sim_printf ("\rPerformance : %'f MIPS\r\n", (double) mips);
9691 #endif /* if defined(WIN_STDIO) */
9692 break;
9693 }
9694 default:
9695 sim_printf ("emcall unknown op %llo\r\n", (unsigned long long)op);
9696 }
9697 return 0;
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889 }
9890
9891 // CANFAULT
9892 static int doABSA (cpu_state_t * cpup, word36 * result)
/* ![[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)
*/
9893 {
9894 word36 res;
9895 sim_debug (DBG_APPENDING, & cpu_dev, "absa CA:%08o\r\n", cpu.TPR.CA);
9896
9897 //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.isb29)
9898 //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.went_appending) // ISOLTS-860
9899 if (get_addr_mode (cpup) == ABSOLUTE_mode && ! (cpu.cu.XSF || cpu.currentInstruction.b29)) // ISOLTS-860
9900 {
9901 * result = ((word36) (cpu.TPR.CA & MASK18)) << 12; // 24:12 format
9902 return SCPE_OK;
9903 }
9904
9905 // ABSA handles directed faults differently, so a special append cycle is
9906 // needed.
9907 // do_append_cycle also provides WAM support, which is required by
9908 // ISOLTS-860 02
9909 // res = (word36) do_append_cycle (cpu.TPR.CA & MASK18, ABSA_CYCLE, NULL,
9910 // 0) << 12;
9911 //res = (word36) do_append_cycle (ABSA_CYCLE, NULL, 0) << 12;
9912 res = (word36) doAppendCycleABSA (cpup, NULL, 0) << 12;
9913
9914 * result = res;
9915
9916 return SCPE_OK;
9917 }
9918
9919 void doRCU (cpu_state_t * cpup)
/* ![[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)
*/
9920 {
9921 #if defined(LOOPTRC)
9922 elapsedtime ();
9923 sim_printf (" rcu to %05o:%06o PSR:IC %05o:%06o\r\n",
9924 (cpu.Yblock8[0]>>18)&MASK15, (cpu.Yblock8[4]>>18)&MASK18, cpu.PPR.PSR, cpu.PPR.IC);
9925 #endif
9926
9927 if_sim_debug (DBG_FAULT, & cpu_dev)
9928 {
9929 dump_words(cpup, cpu.Yblock8);
9930 //for (int i = 0; i < 8; i ++)
9931 // {
9932 // sim_debug (DBG_FAULT, & cpu_dev, "RCU %d %012"PRIo64"\r\n", i,
9933 // cpu.Yblock8[i]);
9934 // }
9935 }
9936
9937 words2scu (cpup, cpu.Yblock8);
9938 decode_instruction (cpup, IWB_IRODD, & cpu.currentInstruction);
9939
9940 // Restore addressing mode
9941
9942 word1 saveP = cpu.PPR.P; // ISOLTS-870 02m
9943 if (TST_I_ABS == 0)
9944 set_addr_mode (cpup, APPEND_mode);
9945 else
9946 set_addr_mode (cpup, ABSOLUTE_mode);
9947 cpu.PPR.P = saveP;
9948
9949 if (getbits36_1 (cpu.Yblock8[1], 35) == 0) // cpu.cu.FLT_INT is interrupt, not fault
9950 {
9951 sim_debug (DBG_FAULT, & cpu_dev, "RCU interrupt return\r\n");
9952 longjmp (cpu.jmpMain, JMP_REFETCH);
9953 }
9954
9955 // Resync the append unit
9956 fauxDoAppendCycle (cpup, INSTRUCTION_FETCH);
9957
9958 // All of the faults list as having handlers have actually
9959 // been encountered in Multics operation and are believed
9960 // to be being handled correctly. The handlers in
9961 // parenthesis are speculative and untested.
9962 //
9963 // Unhandled:
9964 //
9965 // SDF Shutdown: Why would you RCU from a shutdown fault?
9966 // STR Store:
9967 // AL39 is contradictory or vague about store fault subfaults and store
9968 // faults in general. They are mentioned:
9969 // SPRPn: store fault (illegal pointer) (assuming STR:ISN)
9970 // SMCM: store fault (not control) -
9971 // SMIC: store fault (not control) > I believe that these should be
9972 // SSCR: store fault (not control) - command fault
9973 // TSS: STR:OOB
9974 // Bar mode out-of-bounds: STR:OOB
9975 // The SCU register doesn't define which bit is "store fault (not control)"
9976 // STR:ISN - illegal segment number
9977 // STR:NEA - nonexistent address
9978 // STR:OOB - bar mode out-of-bounds
9979 //
9980 // decimal octal
9981 // fault fault mnemonic name priority group handler
9982 // number address
9983 // 0 0 sdf Shutdown 27 7
9984 // 1 2 str Store 10 4 get_BAR_address, instruction execution
9985 // 2 4 mme Master mode entry 1 11 5 JMP_SYNC_FAULT_RETURN instruction execution
9986 // 3 6 f1 Fault tag 1 17 5 (JMP_REFETCH/JMP_RESTART) do_caf
9987 // 4 10 tro Timer runout 26 7 JMP_REFETCH FETCH_cycle
9988 // 5 12 cmd Command 9 4 JMP_REFETCH/JMP_RESTART instruction execution
9989 // 6 14 drl Derail 15 5 JMP_REFETCH/JMP_RESTART instruction execution
9990 // 7 16 luf Lockup 5 4 JMP_REFETCH do_caf, FETCH_cycle
9991 // 8 20 con Connect 25 7 JMP_REFETCH FETCH_cycle
9992 // 9 22 par Parity 8 4
9993 // 10 24 ipr Illegal procedure 16 5 doITSITP, do_caf, instruction execution
9994 // 11 26 onc Operation not complete 4 2 nem_check, instruction execution
9995 // 12 30 suf Startup 1 1
9996 // 13 32 ofl Overflow 7 3 JMP_REFETCH/JMP_RESTART instruction execution
9997 // 14 34 div Divide check 6 3 instruction execution
9998 // 15 36 exf Execute 2 1 JMP_REFETCH/JMP_RESTART FETCH_cycle
9999 // 16 40 df0 Directed fault 0 20 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10000 // 17 42 df1 Directed fault 1 21 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10001 // 18 44 df2 Directed fault 2 22 6 (JMP_REFETCH/JMP_RESTART) getSDW, do_append_cycle
10002 // 19 46 df3 Directed fault 3 23 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10003 // 20 50 acv Access violation 24 6 JMP_REFETCH/JMP_RESTART fetchDSPTW, modifyDSPTW, fetchNSDW,
10004 // do_append_cycle, EXEC_cycle (ring alarm)
10005 // 21 52 mme2 Master mode entry 2 12 5 JMP_SYNC_FAULT_RETURN instruction execution
10006 // 22 54 mme3 Master mode entry 3 13 5 (JMP_SYNC_FAULT_RETURN) instruction execution
10007 // 23 56 mme4 Master mode entry 4 14 5 (JMP_SYNC_FAULT_RETURN) instruction execution
10008 // 24 60 f2 Fault tag 2 18 5 JMP_REFETCH/JMP_RESTART do_caf
10009 // 25 62 f3 Fault tag 3 19 5 JMP_REFETCH/JMP_RESTART do_caf
10010 // 26 64 Unassigned
10011 // 27 66 Unassigned
10012 // 28 70 Unassigned
10013 // 29 72 Unassigned
10014 // 30 74 Unassigned
10015 // 31 76 trb Trouble 3 2 FETCH_cycle, doRCU
10016
10017 // Reworking logic
10018
10019 #define rework
10020 #if defined(rework)
10021 if (cpu.cu.FIF) // fault occurred during instruction fetch
10022 {
10023 //if (cpu.cu.rfi) sim_printf ( "RCU FIF refetch return caught rfi\r\n");
10024 // I am misusing this bit; on restart I want a way to tell the
10025 // CPU state machine to restart the instruction, which is not
10026 // how Multics uses it. I need to pick a different way to
10027 // communicate; for now, turn it off on refetch so the state
10028 // machine doesn't become confused.
10029 cpu.cu.rfi = 0;
10030 sim_debug (DBG_FAULT, & cpu_dev, "RCU FIF REFETCH return\r\n");
10031 longjmp (cpu.jmpMain, JMP_REFETCH);
10032 }
10033
10034 // RFI means 'refetch this instruction'
10035 if (cpu.cu.rfi)
10036 {
10037 //sim_printf ( "RCU rfi refetch return\r\n");
10038 sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi refetch return\r\n");
10039 // Setting the to RESTART causes ISOLTS 776 to report unexpected
10040 // trouble faults.
10041 // Without clearing rfi, ISOLTS pm776-08i LUFs.
10042 cpu.cu.rfi = 0;
10043 longjmp (cpu.jmpMain, JMP_REFETCH);
10044 }
10045
10046 // The debug command uses MME2 to implement breakpoints, but it is not
10047 // clear what it does to the MC data to signal RFI behavior.
10048
10049 word5 fi_addr = getbits36_5 (cpu.Yblock8[1], 30);
10050 if (fi_addr == FAULT_MME ||
10051 fi_addr == FAULT_MME2 ||
10052 fi_addr == FAULT_MME3 ||
10053 fi_addr == FAULT_MME4 ||
10054 fi_addr == FAULT_DRL)
10055 //if (fi_addr == FAULT_MME2)
10056 {
10057 //sim_printf ("MME2 restart\r\n");
10058 sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\r\n");
10059 cpu.cu.rfi = 0;
10060 longjmp (cpu.jmpMain, JMP_RESTART);
10061 }
10062 #else
10063 if (cpu.cu.rfi || // S/W asked for the instruction to be started
10064 cpu.cu.FIF) // fault occurred during instruction fetch
10065 {
10066 // I am misusing this bit; on restart I want a way to tell the
10067 // CPU state machine to restart the instruction, which is not
10068 // how Multics uses it. I need to pick a different way to
10069 // communicate; for now, turn it off on refetch so the state
10070 // machine doesn't become confused.
10071
10072 cpu.cu.rfi = 0;
10073 sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi/FIF REFETCH return\r\n");
10074 longjmp (cpu.jmpMain, JMP_REFETCH);
10075 }
10076
10077 // It seems obvious that MMEx should do a JMP_SYNC_FAULT_RETURN, but doing
10078 // a JMP_RESTART makes 'debug' work. (The same change to DRL does not make
10079 // 'gtss' work, tho.
10080
10081 if (fi_addr == FAULT_MME2)
10082 {
10083 //sim_printf ("MME2 restart\r\n");
10084 sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\r\n");
10085 cpu.cu.rfi = 1;
10086 longjmp (cpu.jmpMain, JMP_RESTART);
10087 }
10088 #endif
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108 // MME faults resume with the next instruction
10109
10110 #if defined(rework)
10111 if (fi_addr == FAULT_DIV ||
10112 fi_addr == FAULT_OFL ||
10113 fi_addr == FAULT_IPR)
10114 {
10115 sim_debug (DBG_FAULT, & cpu_dev, "RCU sync fault return\r\n");
10116 cpu.cu.rfi = 0;
10117 longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10118 }
10119 #else
10120 if (fi_addr == FAULT_MME ||
10121 /* fi_addr == FAULT_MME2 || */
10122 fi_addr == FAULT_MME3 ||
10123 fi_addr == FAULT_MME4 ||
10124 fi_addr == FAULT_DRL ||
10125 fi_addr == FAULT_DIV ||
10126 fi_addr == FAULT_OFL ||
10127 fi_addr == FAULT_IPR)
10128 {
10129 sim_debug (DBG_FAULT, & cpu_dev, "RCU MMEx sync fault return\r\n");
10130 cpu.cu.rfi = 0;
10131 longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10132 }
10133 #endif
10134
10135 // LUF can happen during fetch or CAF. If fetch, handled above
10136 if (fi_addr == FAULT_LUF)
10137 {
10138 cpu.cu.rfi = 1;
10139 sim_debug (DBG_FAULT, & cpu_dev, "RCU LUF RESTART return\r\n");
10140 longjmp (cpu.jmpMain, JMP_RESTART);
10141 }
10142
10143 if (fi_addr == FAULT_DF0 ||
10144 fi_addr == FAULT_DF1 ||
10145 fi_addr == FAULT_DF2 ||
10146 fi_addr == FAULT_DF3 ||
10147 fi_addr == FAULT_ACV ||
10148 fi_addr == FAULT_F1 ||
10149 fi_addr == FAULT_F2 ||
10150 fi_addr == FAULT_F3 ||
10151 fi_addr == FAULT_CMD ||
10152 fi_addr == FAULT_EXF)
10153 {
10154 // If the fault occurred during fetch, handled above.
10155 cpu.cu.rfi = 1;
10156 sim_debug (DBG_FAULT, & cpu_dev, "RCU ACV RESTART return\r\n");
10157 longjmp (cpu.jmpMain, JMP_RESTART);
10158 }
10159 sim_printf ("doRCU dies with unhandled fault number %d\r\n", fi_addr);
10160 doFault (FAULT_TRB,
10161 (_fault_subtype) {.bits=fi_addr},
10162 "doRCU dies with unhandled fault number");
10163 }