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