root/src/dps8/dps8_ins.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. elapsedtime
  2. writeOperands
  3. readOperands
  4. read_tra_op
  5. dump_words
  6. scu2words
  7. cu_safe_store
  8. tidy_cu
  9. words2scu
  10. cu_safe_restore
  11. du2words
  12. words2du
  13. initializeTheMatrix
  14. addToTheMatrix
  15. display_the_matrix
  16. fetchInstruction
  17. traceInstruction
  18. chkOVF
  19. tstOVFfault
  20. executeInstruction
  21. overflow
  22. doInstruction
  23. emCall
  24. doABSA
  25. doRCU

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

/* [previous][next][first][last][top][bottom][index][help] */