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