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-2025 The DPS8M Development Team
  15  *
  16  * This software is made available under the terms of the ICU License.
  17  * See the LICENSE.md file at the top-level directory of this distribution.
  18  *
  19  * ---------------------------------------------------------------------------
  20  *
  21  * This source file may contain code comments that adapt, include, and/or
  22  * incorporate Multics program code and/or documentation distributed under
  23  * the Multics License.  In the event of any discrepancy between code
  24  * comments herein and the original Multics materials, the original Multics
  25  * materials should be considered authoritative unless otherwise noted.
  26  * For more details and historical background, see the LICENSE.md file at
  27  * the top-level directory of this distribution.
  28  *
  29  * ---------------------------------------------------------------------------
  30  */
  31 
  32 #include <stdio.h>
  33 
  34 #include "dps8.h"
  35 #include "dps8_sys.h"
  36 #include "dps8_iom.h"
  37 #include "dps8_cable.h"
  38 #include "dps8_cpu.h"
  39 #include "dps8_addrmods.h"
  40 #include "dps8_faults.h"
  41 #include "dps8_scu.h"
  42 #include "dps8_append.h"
  43 #include "dps8_eis.h"
  44 #include "dps8_ins.h"
  45 #include "dps8_math.h"
  46 #include "dps8_opcodetable.h"
  47 #include "dps8_decimal.h"
  48 #include "dps8_iefp.h"
  49 #include "dps8_utils.h"
  50 
  51 #if defined(THREADZ) || defined(LOCKLESS)
  52 # include "threadz.h"
  53 #endif
  54 
  55 #include "ver.h"
  56 
  57 #define DBG_CTR cpu.cycleCnt
  58 
  59 // Forward declarations
  60 
  61 static int doABSA (cpu_state_t * cpup, word36 * result);
  62 HOT static t_stat doInstruction (cpu_state_t * cpup);
  63 static int emCall (cpu_state_t * cpup);
  64 
  65 #if BARREL_SHIFTER
  66 static word36 barrelLeftMaskTable[37] = {
  67               0000000000000ull,
  68               0400000000000ull, 0600000000000ull, 0700000000000ull,
  69               0740000000000ull, 0760000000000ull, 0770000000000ull,
  70               0774000000000ull, 0776000000000ull, 0777000000000ull,
  71               0777400000000ull, 0777600000000ull, 0777700000000ull,
  72               0777740000000ull, 0777760000000ull, 0777770000000ull,
  73               0777774000000ull, 0777776000000ull, 0777777000000ull,
  74               0777777400000ull, 0777777600000ull, 0777777700000ull,
  75               0777777740000ull, 0777777760000ull, 0777777770000ull,
  76               0777777774000ull, 0777777776000ull, 0777777777000ull,
  77               0777777777400ull, 0777777777600ull, 0777777777700ull,
  78               0777777777740ull, 0777777777760ull, 0777777777770ull,
  79               0777777777774ull, 0777777777776ull, 0777777777777ull
  80             };
  81 static word36 barrelRightMaskTable[37] = {
  82               0000000000000ull,
  83               0000000000001ull, 0000000000003ull, 0000000000007ull,
  84               0000000000017ull, 0000000000037ull, 0000000000077ull,
  85               0000000000177ull, 0000000000377ull, 0000000000777ull,
  86               0000000001777ull, 0000000003777ull, 0000000007777ull,
  87               0000000017777ull, 0000000037777ull, 0000000077777ull,
  88               0000000177777ull, 0000000377777ull, 0000000777777ull,
  89               0000001777777ull, 0000003777777ull, 0000007777777ull,
  90               0000017777777ull, 0000037777777ull, 0000077777777ull,
  91               0000177777777ull, 0000377777777ull, 0000777777777ull,
  92               0001777777777ull, 0003777777777ull, 0007777777777ull,
  93               0017777777777ull, 0037777777777ull, 0077777777777ull,
  94               0177777777777ull, 0377777777777ull, 0777777777777ull,
  95             };
  96 # define BS_COMPL(HI) ((~(HI)) & MASK36)
  97 #endif // BARREL_SHIFTER
  98 
  99 #if defined(LOOPTRC)
 100 void elapsedtime (void)
     /* [previous][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             // lls Long Left Shift
4237             // Shift C(AQ) left the number of positions given in
4238             // C(TPR.CA)11,17; filling vacated positions with zeros.
4239             // Zero       if C(AQ) == 0 then ON; otherwise OFF:
4240             // Negative   if C(AQ)0 == 1 then On; otherwise OFF;
4241             // Carry      if C(AQ)0 changes during the shift; then ON; otherwise OFF:
4242 #if BARREL_SHIFTER
4243             uint cnt = (uint) cpu.TPR.CA & 0177;   // 0-127
4244 
4245 
4246             // Sanitize
4247             cpu.rA &= MASK36;
4248             cpu.rQ &= MASK36;
4249 
4250             if (cnt >= 72) {
4251               // If the shift is 72 or greater, AQ will be set to zero and
4252               // the carry will be cleared if the initial value of AQ is 0 or
4253               // all ones
4254               bool allz = cpu.rA == 0 && cpu.rQ == 0;
4255               bool all1 = cpu.rA == MASK36 && cpu.rQ == MASK36;
4256               if (allz || all1)
4257                 CLR_I_CARRY;
4258               else
4259                 SET_I_CARRY;
4260               cpu.rA = 0;
4261               cpu.rQ = 0;
4262 
4263             } else if (cnt >= 36) {
4264               // If the shift count is 36 to 71, all of A and some of Q will determine
4265               // the carry; all of A will become Q << (cnt - 36), and Q will become 0.
4266               uint cnt36 = cnt - 36;
4267               // The carry depends on the sign bit changing on the shift;
4268               // add 1 so that the mask includes the sign bit and all of
4269               // the bits that will be shifted in.
4270               word36 lmask = barrelLeftMaskTable[cnt36 + 1];
4271               // Capture all of the bits that will be shifted
4272               word36 captureA = cpu.rA;
4273               word36 captureQ = lmask & cpu.rQ;
4274               bool az = captureA == 0;
4275               bool a1 = captureA == MASK36;
4276               bool qz = captureQ == 0;
4277               bool q1 = captureQ == (MASK36 & lmask);
4278               bool allz = az && qz;
4279               bool all1 = a1 && q1;
4280               if (allz || all1)
4281                 CLR_I_CARRY;
4282               else
4283                 SET_I_CARRY;
4284 
4285               // Shift the bits
4286               cpu.rA = (cpu.rQ << cnt36) & MASK36;
4287               cpu.rQ = 0;
4288             } else { // cnt < 36
4289               // If the count is < 36, carry is determined by the high part of A;
4290               // A is shifted left, and bits shifted out of Q are shifted into A.
4291               // The carry depends on the sign bit changing on the shift;
4292               // add 1 so that the mask includes the sign bit and all of
4293               // the bits that will be shifted in.
4294               word36 lmask = barrelLeftMaskTable[cnt + 1];
4295               word36 captureA = lmask & cpu.rA;
4296               bool allz = captureA == 0;
4297               bool all1 = captureA == (MASK36 & lmask);
4298 
4299               if (allz || all1)
4300                 CLR_I_CARRY;
4301               else
4302                 SET_I_CARRY;
4303 
4304               // Shift the bits
4305               cpu.rA = ((cpu.rA << cnt) & MASK36) | (cpu.rQ >> (36 - cnt));
4306               cpu.rQ = (cpu.rQ << cnt) & MASK36;
4307             }
4308 
4309 
4310 
4311 
4312 
4313 
4314 
4315 
4316 
4317 
4318 
4319 
4320 
4321 
4322 
4323 
4324 
4325 
4326 
4327 
4328 
4329 
4330 
4331 
4332 
4333 
4334 
4335 
4336 
4337 
4338 
4339 
4340 
4341 
4342 
4343 
4344 
4345 #else // !BARREL_SHIFTER
4346 
4347             CLR_I_CARRY;
4348 
4349 # if defined(TESTING)
4350             HDBGRegAR ("lls");
4351             HDBGRegQR ("lls");
4352 # endif
4353             word36 tmp36   = cpu.TPR.CA & 0177;   // CY bits 11-17
4354             word36 tmpSign = cpu.rA & SIGN36;
4355             for (uint j = 0 ; j < tmp36 ; j ++)
4356               {
4357                 cpu.rA <<= 1;               // shift left 1
4358 
4359                 if (tmpSign != (cpu.rA & SIGN36))
4360                   SET_I_CARRY;
4361 
4362                 bool b0 = cpu.rQ & SIGN36;    // Q0
4363                 if (b0)
4364                   cpu.rA |= 1;            // Q0 => A35
4365 
4366                 cpu.rQ <<= 1;               // shift left 1
4367               }
4368 
4369             cpu.rA &= DMASK;    // keep to 36-bits
4370             cpu.rQ &= DMASK;
4371 #endif // BARREL_SHIFTER
4372 #if defined(TESTING)
4373             HDBGRegAW ("lls");
4374             HDBGRegQW ("lls");
4375 #endif
4376 
4377             SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4378             SC_I_NEG (cpu.rA & SIGN36);
4379           }
4380           break;
4381 
4382         case x0 (0773):  // lrl
4383           // Shift C(AQ) right the number of positions given in
4384           // C(TPR.CA)11,17; filling vacated positions with zeros.
4385           {
4386 #if defined(TESTING)
4387             HDBGRegAR ("lrl");
4388             HDBGRegQR ("lrl");
4389 #endif
4390 #if BARREL_SHIFTER
4391             uint cnt = (uint) cpu.TPR.CA & 0177;   // 0-127
4392             if (cnt >= 72) {
4393                cpu.rA = 0;
4394                cpu.rQ = 0;
4395             } else if (cnt < 36) {
4396               // Shift rQ
4397               cpu.rQ >>= cnt;
4398               // Mask out the high bits
4399               cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4400               // Capture the low bits in A
4401               word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4402               // Shift A
4403               cpu.rA >>= cnt;
4404               // Mask out the high bits
4405               cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4406               // Move the low A bits left
4407               lowA <<= (36 - cnt);
4408               // Put them in high Q
4409               cpu.rQ |= lowA;
4410             } else { // 36-71
4411               // Shift rQ
4412               cpu.rQ = cpu.rA >> (cnt - 36);
4413               // Mask out the high bits
4414               cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4415               cpu.rA = 0;
4416             }
4417             cpu.rA &= DMASK;    // keep to 36-bits
4418             cpu.rQ &= DMASK;
4419 #else // !BARREL_SHIFTER
4420             cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4421             cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4422             word36 tmp36 = cpu.TPR.CA & 0177;   // CY bits 11-17
4423             for (uint j = 0 ; j < tmp36 ; j++)
4424               {
4425                 bool a35 = cpu.rA & 1;      // A35
4426                 cpu.rA >>= 1;               // shift right 1
4427 
4428                 cpu.rQ >>= 1;               // shift right 1
4429 
4430                 if (a35)                // propagate sign bit
4431                   cpu.rQ |= SIGN36;
4432               }
4433             cpu.rA &= DMASK;    // keep to 36-bits
4434             cpu.rQ &= DMASK;
4435 #endif // BARREL_SHIFTER
4436 #if defined(TESTING)
4437             HDBGRegAW ("lrl");
4438             HDBGRegQW ("lrl");
4439 #endif
4440 
4441             SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4442             SC_I_NEG (cpu.rA & SIGN36);
4443           }
4444           break;
4445 
4446         case x0 (0733):  // lrs
4447           {
4448             // Shift C(AQ) right the number of positions given in
4449             // C(TPR.CA)11,17; filling vacated positions with initial C(AQ)0.
4450 
4451 #if defined(TESTING)
4452             HDBGRegAR ("lrs");
4453             HDBGRegQR ("lrs");
4454 #endif
4455 #if BARREL_SHIFTER
4456             uint cnt = (uint) cpu.TPR.CA & 0177;   // 0-127
4457             bool AQ0 = (cpu.rA & SIGN36) != 0;
4458             if (cnt >= 72) {
4459                cpu.rA = cpu.rQ = AQ0 ? MASK36 : 0;
4460             } else if (cnt < 36) {
4461               // Shift rQ
4462               cpu.rQ >>= cnt;
4463               // Mask out the high bits
4464               cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4465               // Capture the low bits in A
4466               word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4467               // Shift A
4468               cpu.rA >>= cnt;
4469               // Set the high bits to AQ0
4470               if (AQ0)
4471                 cpu.rA |= barrelLeftMaskTable[cnt];
4472               else
4473                 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4474               // Move the low A bits left
4475               lowA <<= (36 - cnt);
4476               // Put them in high Q
4477               cpu.rQ |= lowA;
4478             } else { // 36-71
4479               // Shift rQ
4480               cpu.rQ = cpu.rA >> (cnt - 36);
4481               // Mask out the high bits
4482               if (AQ0) {
4483                 cpu.rQ |= barrelLeftMaskTable[cnt - 36];
4484                 cpu.rA = MASK36;
4485               } else {
4486                 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4487                 cpu.rA = 0;
4488               }
4489             }
4490             cpu.rA &= DMASK;    // keep to 36-bits
4491             cpu.rQ &= DMASK;
4492 #else // !BARREL_SHIFTER
4493             word36 tmp36  = cpu.TPR.CA & 0177;   // CY bits 11-17
4494             cpu.rA       &= DMASK; // Make sure the shifted in bits are 0
4495             cpu.rQ       &= DMASK; // Make sure the shifted in bits are 0
4496             bool a0       = cpu.rA & SIGN36;    // A0
4497 
4498             for (uint j = 0 ; j < tmp36 ; j ++)
4499               {
4500                 bool a35 = cpu.rA & 1;      // A35
4501 
4502                 cpu.rA >>= 1;               // shift right 1
4503                 if (a0)
4504                   cpu.rA |= SIGN36;
4505 
4506                 cpu.rQ >>= 1;               // shift right 1
4507                 if (a35)                // propagate sign bit1
4508                   cpu.rQ |= SIGN36;
4509               }
4510             cpu.rA &= DMASK;    // keep to 36-bits (probably ain't necessary)
4511             cpu.rQ &= DMASK;
4512 #endif // BARREL_SHIFTER
4513 #if defined(TESTING)
4514             HDBGRegAW ("lrs");
4515             HDBGRegQW ("lrs");
4516 #endif
4517 
4518             SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4519             SC_I_NEG (cpu.rA & SIGN36);
4520           }
4521           break;
4522 
4523         case x0 (0776):  // qlr
4524           // Shift C(Q) left the number of positions given in
4525           // C(TPR.CA)11,17; entering each bit leaving Q0 into Q35.
4526           {
4527 #if defined(TESTING)
4528             HDBGRegQR ("qlr");
4529 #endif
4530 #if BARREL_SHIFTER
4531             uint cnt = (uint) cpu.TPR.CA & 0177;   // 0-127
4532             cnt %= 36;
4533 
4534             word36 highQ = cpu.rQ & barrelLeftMaskTable[cnt];
4535             cpu.rQ <<= cnt;
4536             highQ >>= (36 - cnt);
4537             highQ &= barrelRightMaskTable[cnt];
4538             cpu.rQ |= highQ;
4539             cpu.rQ &= DMASK;    // keep to 36-bits
4540 #else // !BARREL_SHIFTER
4541             word36 tmp36 = cpu.TPR.CA & 0177;   // CY bits 11-17
4542             for (uint j = 0 ; j < tmp36 ; j++)
4543               {
4544                 bool q0 = cpu.rQ & SIGN36;    // Q0
4545                 cpu.rQ <<= 1;               // shift left 1
4546                 if (q0)                 // rotate A0 -> A35
4547                   cpu.rQ |= 1;
4548               }
4549             cpu.rQ &= DMASK;    // keep to 36-bits
4550 #endif // BARREL_SHIFTER
4551 #if defined(TESTING)
4552             HDBGRegQW ("qlr");
4553 #endif
4554 
4555             SC_I_ZERO (cpu.rQ == 0);
4556             SC_I_NEG (cpu.rQ & SIGN36);
4557           }
4558           break;
4559 
4560 // Optimized to the top of the loop
4561 //        case x0 (0736):  // qls
4562 
4563         case x0 (0772):  // qrl
4564           // Shift C(Q) right the number of positions specified by
4565           // Y11,17; fill vacated positions with zeros.
4566           {
4567 #if defined(TESTING)
4568             HDBGRegQR ("qrl");
4569 #endif
4570             word36 tmp36 = cpu.TPR.CA & 0177;   // CY bits 11-17
4571 
4572             cpu.rQ  &= DMASK;    // Make sure the shifted in bits are 0
4573             cpu.rQ >>= tmp36;
4574             cpu.rQ  &= DMASK;    // keep to 36-bits
4575 #if defined(TESTING)
4576             HDBGRegQW ("qrl");
4577 #endif
4578 
4579             SC_I_ZERO (cpu.rQ == 0);
4580             SC_I_NEG (cpu.rQ & SIGN36);
4581 
4582           }
4583           break;
4584 
4585         case x0 (0732):  // qrs
4586           {
4587             // Shift C(Q) right the number of positions given in
4588             // C(TPR.CA)11,17; filling vacated positions with initial C(Q)0.
4589 
4590 #if defined(TESTING)
4591             HDBGRegQR ("qrs");
4592 #endif
4593 #if BARREL_SHIFTER
4594             uint cnt = (uint) cpu.TPR.CA & 0177;   // 0-127
4595             bool Q0 = (cpu.rQ & SIGN36) != 0;
4596 
4597             if (cnt >= 36) {
4598               cpu.rQ = Q0 ? MASK36 : 0;
4599             } else {
4600               // Shift rQ
4601               cpu.rQ >>= cnt;
4602               // Mask out the high bits
4603               if (Q0) {
4604                 cpu.rQ |= barrelLeftMaskTable[cnt];
4605               } else {
4606                 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4607               }
4608             }
4609             cpu.rQ &= DMASK;    // keep to 36-bits
4610 #else // !BARREL_SHIFTER
4611             cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4612             word36 tmp36 = cpu.TPR.CA & 0177;   // CY bits 11-17
4613             bool q0 = cpu.rQ & SIGN36;    // Q0
4614             for (uint j = 0 ; j < tmp36 ; j++)
4615               {
4616                 cpu.rQ >>= 1;               // shift right 1
4617                 if (q0)                 // propagate sign bit
4618                   cpu.rQ |= SIGN36;
4619               }
4620             cpu.rQ &= DMASK;    // keep to 36-bits
4621 #endif // BARREL_SHIFTER
4622 #if defined(TESTING)
4623             HDBGRegQW ("qrs");
4624 #endif
4625 
4626             SC_I_ZERO (cpu.rQ == 0);
4627             SC_I_NEG (cpu.rQ & SIGN36);
4628           }
4629           break;
4630 
4631         /// Fixed-Point Addition
4632 
4633         case x0 (0075):  // ada
4634           {
4635             // C(A) + C(Y) -> C(A)
4636             // Modifications: All
4637             //
4638             //  (Indicators not listed are not affected)
4639             //  ZERO: If C(A) = 0, then ON; otherwise OFF
4640             //  NEG: If C(A)0 = 1, then ON; otherwise OFF
4641             //  OVR: If range of A is exceeded, then ON
4642             //  CARRY: If a carry out of A0 is generated, then ON; otherwise OFF
4643 
4644             L68_ (cpu.ou.cycle |= ou_GOS;)
4645 #if defined(TESTING)
4646             HDBGRegAR ("ada");
4647 #endif
4648             bool ovf;
4649             cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4650 #if defined(TESTING)
4651             HDBGRegAW ("ada");
4652 #endif
4653             overflow (cpup, ovf, false, "ada overflow fault");
4654           }
4655           break;
4656 
4657         case x0 (0077):   // adaq
4658           {
4659             // C(AQ) + C(Y-pair) -> C(AQ)
4660             L68_ (cpu.ou.cycle |= ou_GOS;)
4661 #if defined(TESTING)
4662             HDBGRegAR ("adaq");
4663             HDBGRegQR ("adaq");
4664 #endif
4665             bool ovf;
4666             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4667             tmp72        = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4668                                    tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4669             convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4670 #if defined(TESTING)
4671             HDBGRegAW ("adaq");
4672             HDBGRegQW ("adaq");
4673 #endif
4674             overflow (cpup, ovf, false, "adaq overflow fault");
4675           }
4676           break;
4677 
4678         case x0 (0033):   // adl
4679           {
4680             // C(AQ) + C(Y) sign extended -> C(AQ)
4681             L68_ (cpu.ou.cycle |= ou_GOS;)
4682 #if defined(TESTING)
4683             HDBGRegAR ("adl");
4684             HDBGRegQR ("adl");
4685 #endif
4686             bool ovf;
4687             word72 tmp72 = SIGNEXT36_72 (cpu.CY); // sign extend Cy
4688             tmp72        = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4689                                    tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4690             convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4691 #if defined(TESTING)
4692             HDBGRegAW ("adl");
4693             HDBGRegQW ("adl");
4694 #endif
4695             overflow (cpup, ovf, false, "adl overflow fault");
4696           }
4697           break;
4698 
4699         case x0 (0037):   // adlaq
4700           {
4701             // The adlaq instruction is identical to the adaq instruction with
4702             // the exception that the overflow indicator is not affected by the
4703             // adlaq instruction, nor does an overflow fault occur. Operands
4704             // and results are treated as unsigned, positive binary integers.
4705             L68_ (cpu.ou.cycle |= ou_GOS;)
4706 #if defined(TESTING)
4707             HDBGRegAR ("adlaq");
4708             HDBGRegQR ("adlaq");
4709 #endif
4710             bool ovf;
4711             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4712 
4713             tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4714                             tmp72, 0, I_ZNC, & cpu.cu.IR, & ovf);
4715             convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4716 #if defined(TESTING)
4717             HDBGRegAW ("adlaq");
4718             HDBGRegQW ("adlaq");
4719 #endif
4720           }
4721           break;
4722 
4723         case x0 (0035):   // adla
4724           {
4725             L68_ (cpu.ou.cycle |= ou_GOS;)
4726             // The adla instruction is identical to the ada instruction with
4727             // the exception that the overflow indicator is not affected by the
4728             // adla instruction, nor does an overflow fault occur. Operands and
4729             // results are treated as unsigned, positive binary integers. */
4730 
4731 #if defined(TESTING)
4732             HDBGRegAR ("adla");
4733 #endif
4734             bool ovf;
4735             cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4736 #if defined(TESTING)
4737             HDBGRegAW ("adla");
4738 #endif
4739           }
4740           break;
4741 
4742         case x0 (0036):   // adlq
4743           {
4744             // The adlq instruction is identical to the adq instruction with
4745             // the exception that the overflow indicator is not affected by the
4746             // adlq instruction, nor does an overflow fault occur. Operands and
4747             // results are treated as unsigned, positive binary integers. */
4748 
4749             L68_ (cpu.ou.cycle |= ou_GOS;)
4750 #if defined(TESTING)
4751             HDBGRegQR ("adlq");
4752 #endif
4753             bool ovf;
4754             cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4755 #if defined(TESTING)
4756             HDBGRegQW ("adlq");
4757 #endif
4758           }
4759           break;
4760 
4761                           // adlxn
4762         case x0 (0020):   // adlx0
4763         case x0 (0021):   // adlx1
4764         case x0 (0022):   // adlx2
4765         case x0 (0023):   // adlx3
4766         case x0 (0024):   // adlx4
4767         case x0 (0025):   // adlx5
4768         case x0 (0026):   // adlx6
4769         case x0 (0027):   // adlx7
4770           {
4771             L68_ (cpu.ou.cycle |= ou_GOS;)
4772             uint32 n = opcode10 & 07;  // get n
4773 #if defined(TESTING)
4774             HDBGRegXR (n, "adlxn");
4775 #endif
4776             bool ovf;
4777             cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0, I_ZNC,
4778                              & cpu.cu.IR, & ovf);
4779 #if defined(TESTING)
4780             HDBGRegXW (n, "adlxn");
4781 #endif
4782           }
4783           break;
4784 
4785 // Optimized to the top of the loop
4786 //        case x0 (0076):   // adq
4787 
4788                           // adxn
4789         case x0 (0060):   // adx0
4790         case x0 (0061):   // adx1
4791         case x0 (0062):   // adx2
4792         case x0 (0063):   // adx3
4793         case x0 (0064):   // adx4
4794         case x0 (0065):   // adx5
4795         case x0 (0066):   // adx6
4796         case x0 (0067):   // adx7
4797           {
4798             L68_ (cpu.ou.cycle |= ou_GOS;)
4799             uint32 n = opcode10 & 07;  // get n
4800 #if defined(TESTING)
4801             HDBGRegXR (n, "adxn");
4802 #endif
4803             bool ovf;
4804             cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4805                                  I_ZNOC,
4806                                  & cpu.cu.IR, & ovf);
4807 #if defined(TESTING)
4808             HDBGRegXW (n, "adxn");
4809 #endif
4810             overflow (cpup, ovf, false, "adxn overflow fault");
4811           }
4812           break;
4813 
4814 // Optimized to the top of the loop
4815 //        case x0 (0054):   // aos
4816 
4817         case x0 (0055):   // asa
4818           {
4819             // C(A) + C(Y) -> C(Y)
4820 
4821             L68_ (cpu.ou.cycle |= ou_GOS;)
4822 #if defined(TESTING)
4823             HDBGRegAR ("asa");
4824 #endif
4825             bool ovf;
4826             cpu.CY = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC,
4827                              & cpu.cu.IR, & ovf);
4828             overflow (cpup, ovf, true, "asa overflow fault");
4829           }
4830           break;
4831 
4832         case x0 (0056):   // asq
4833           {
4834             // C(Q) + C(Y) -> C(Y)
4835             L68_ (cpu.ou.cycle |= ou_GOS;)
4836 #if defined(TESTING)
4837             HDBGRegQR ("asa");
4838 #endif
4839             bool ovf;
4840             cpu.CY = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4841             overflow (cpup, ovf, true, "asq overflow fault");
4842           }
4843           break;
4844 
4845                           // asxn
4846         case x0 (0040):   // asx0
4847         case x0 (0041):   // asx1
4848         case x0 (0042):   // asx2
4849         case x0 (0043):   // asx3
4850         case x0 (0044):   // asx4
4851         case x0 (0045):   // asx5
4852         case x0 (0046):   // asx6
4853         case x0 (0047):   // asx7
4854           {
4855             // For n = 0, 1, ..., or 7 as determined by operation code
4856             //    C(Xn) + C(Y)0,17 -> C(Y)0,17
4857             L68_ (cpu.ou.cycle |= ou_GOS;)
4858             uint32 n = opcode10 & 07;  // get n
4859 #if defined(TESTING)
4860             HDBGRegXR (n, "asxn");
4861 #endif
4862             bool ovf;
4863             word18 tmp18 = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4864                                    I_ZNOC, & cpu.cu.IR, & ovf);
4865             SETHI (cpu.CY, tmp18);
4866             overflow (cpup, ovf, true, "asxn overflow fault");
4867           }
4868           break;
4869 
4870         case x0 (0071):   // awca
4871           {
4872             // If carry indicator OFF, then C(A) + C(Y) -> C(A)
4873             // If carry indicator ON, then C(A) + C(Y) + 1 -> C(A)
4874 
4875             L68_ (cpu.ou.cycle |= ou_GOS;)
4876 #if defined(TESTING)
4877             HDBGRegAR ("awca");
4878 #endif
4879             bool ovf;
4880             cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
4881                                  I_ZNOC, & cpu.cu.IR, & ovf);
4882 #if defined(TESTING)
4883             HDBGRegAW ("awca");
4884 #endif
4885             overflow (cpup, ovf, false, "awca overflow fault");
4886           }
4887           break;
4888 
4889         case x0 (0072):   // awcq
4890           {
4891             // If carry indicator OFF, then C(Q) + C(Y) -> C(Q)
4892             // If carry indicator ON, then C(Q) + C(Y) + 1 -> C(Q)
4893 
4894             L68_ (cpu.ou.cycle |= ou_GOS;)
4895 #if defined(TESTING)
4896             HDBGRegQR ("awcq");
4897 #endif
4898             bool ovf;
4899             cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
4900                              I_ZNOC, & cpu.cu.IR, & ovf);
4901 #if defined(TESTING)
4902             HDBGRegQW ("awcq");
4903 #endif
4904             overflow (cpup, ovf, false, "awcq overflow fault");
4905           }
4906           break;
4907 
4908         /// Fixed-Point Subtraction
4909 
4910         case x0 (0175):  // sba
4911           {
4912             // C(A) - C(Y) -> C(A)
4913 
4914             L68_ (cpu.ou.cycle |= ou_GOS;)
4915 #if defined(TESTING)
4916             HDBGRegAR ("sba");
4917 #endif
4918             bool ovf;
4919             cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
4920 #if defined(TESTING)
4921             HDBGRegAW ("sba");
4922 #endif
4923             overflow (cpup, ovf, false, "sba overflow fault");
4924           }
4925           break;
4926 
4927         case x0 (0177):  // sbaq
4928           {
4929             // C(AQ) - C(Y-pair) -> C(AQ)
4930             L68_ (cpu.ou.cycle |= ou_GOS;)
4931 #if defined(TESTING)
4932             HDBGRegAR ("sbaq");
4933             HDBGRegQR ("sbaq");
4934 #endif
4935             bool ovf;
4936             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4937             tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
4938                             I_ZNOC, & cpu.cu.IR,
4939                             & ovf);
4940             convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4941 #if defined(TESTING)
4942             HDBGRegAW ("sbaq");
4943             HDBGRegQW ("sbaq");
4944 #endif
4945             overflow (cpup, ovf, false, "sbaq overflow fault");
4946           }
4947           break;
4948 
4949         case x0 (0135):  // sbla
4950           {
4951             // C(A) - C(Y) -> C(A) logical
4952 
4953             L68_ (cpu.ou.cycle |= ou_GOS;)
4954 #if defined(TESTING)
4955             HDBGRegAR ("sbla");
4956 #endif
4957             bool ovf;
4958             cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
4959 #if defined(TESTING)
4960             HDBGRegAW ("sbla");
4961 #endif
4962           }
4963           break;
4964 
4965         case x0 (0137):  // sblaq
4966           {
4967             // The sblaq instruction is identical to the sbaq instruction with
4968             // the exception that the overflow indicator is not affected by the
4969             // sblaq instruction, nor does an overflow fault occur. Operands
4970             // and results are treated as unsigned, positive binary integers.
4971             // C(AQ) - C(Y-pair) -> C(AQ)
4972 
4973             L68_ (cpu.ou.cycle |= ou_GOS;)
4974 #if defined(TESTING)
4975             HDBGRegAR ("sblaq");
4976             HDBGRegQR ("sblaq");
4977 #endif
4978             bool ovf;
4979             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4980 
4981             tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
4982                             I_ZNC, & cpu.cu.IR, & ovf);
4983             convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4984 #if defined(TESTING)
4985             HDBGRegAW ("sblaq");
4986             HDBGRegQW ("sblaq");
4987 #endif
4988           }
4989           break;
4990 
4991         case x0 (0136):  // sblq
4992           {
4993             // C(Q) - C(Y) -> C(Q)
4994             L68_ (cpu.ou.cycle |= ou_GOS;)
4995 #if defined(TESTING)
4996             HDBGRegQR ("sblq");
4997 #endif
4998             bool ovf;
4999             cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
5000 #if defined(TESTING)
5001             HDBGRegQW ("sblq");
5002 #endif
5003           }
5004           break;
5005 
5006                          // sblxn
5007         case x0 (0120):  // sblx0
5008         case x0 (0121):  // sblx1
5009         case x0 (0122):  // sblx2
5010         case x0 (0123):  // sblx3
5011         case x0 (0124):  // sblx4
5012         case x0 (0125):  // sblx5
5013         case x0 (0126):  // sblx6
5014         case x0 (0127):  // sblx7
5015           {
5016             // For n = 0, 1, ..., or 7 as determined by operation code
5017             // C(Xn) - C(Y)0,17 -> C(Xn)
5018 
5019             L68_ (cpu.ou.cycle |= ou_GOS;)
5020             uint32 n = opcode10 & 07;  // get n
5021 #if defined(TESTING)
5022             HDBGRegXR (n, "sblxn");
5023 #endif
5024             bool ovf;
5025             cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5026                              I_ZNC, & cpu.cu.IR, & ovf);
5027 #if defined(TESTING)
5028             HDBGRegXW (n, "sblxn");
5029 #endif
5030           }
5031           break;
5032 
5033         case x0 (0176):  // sbq
5034           {
5035             // C(Q) - C(Y) -> C(Q)
5036             L68_ (cpu.ou.cycle |= ou_GOS;)
5037 #if defined(TESTING)
5038             HDBGRegQR ("sbq");
5039 #endif
5040             bool ovf;
5041             cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5042 #if defined(TESTING)
5043             HDBGRegQW ("sbq");
5044 #endif
5045             overflow (cpup, ovf, false, "sbq overflow fault");
5046           }
5047           break;
5048 
5049                          // sbxn
5050         case x0 (0160):  // sbx0
5051         case x0 (0161):  // sbx1
5052         case x0 (0162):  // sbx2
5053         case x0 (0163):  // sbx3
5054         case x0 (0164):  // sbx4
5055         case x0 (0165):  // sbx5
5056         case x0 (0166):  // sbx6
5057         case x0 (0167):  // sbx7
5058           {
5059             // For n = 0, 1, ..., or 7 as determined by operation code
5060             // C(Xn) - C(Y)0,17 -> C(Xn)
5061 
5062             L68_ (cpu.ou.cycle |= ou_GOS;)
5063             uint32 n = opcode10 & 07;  // get n
5064 #if defined(TESTING)
5065             HDBGRegXR (n, "sbxn");
5066 #endif
5067             bool ovf;
5068             cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5069                                  I_ZNOC, & cpu.cu.IR, & ovf);
5070 #if defined(TESTING)
5071             HDBGRegXW (n, "sbxn");
5072 #endif
5073             overflow (cpup, ovf, false, "sbxn overflow fault");
5074           }
5075           break;
5076 
5077         case x0 (0155):  // ssa
5078           {
5079             // C(A) - C(Y) -> C(Y)
5080 
5081             L68_ (cpu.ou.cycle |= ou_GOS;)
5082 #if defined(TESTING)
5083             HDBGRegAR ("ssa");
5084 #endif
5085             bool ovf;
5086             cpu.CY = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5087             overflow (cpup, ovf, true, "ssa overflow fault");
5088           }
5089           break;
5090 
5091         case x0 (0156):  // ssq
5092           {
5093             // C(Q) - C(Y) -> C(Y)
5094 
5095             L68_ (cpu.ou.cycle |= ou_GOS;)
5096 #if defined(TESTING)
5097             HDBGRegQR ("ssq");
5098 #endif
5099             bool ovf;
5100             cpu.CY = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5101             overflow (cpup, ovf, true, "ssq overflow fault");
5102           }
5103           break;
5104 
5105                          // ssxn
5106         case x0 (0140):  // ssx0
5107         case x0 (0141):  // ssx1
5108         case x0 (0142):  // ssx2
5109         case x0 (0143):  // ssx3
5110         case x0 (0144):  // ssx4
5111         case x0 (0145):  // ssx5
5112         case x0 (0146):  // ssx6
5113         case x0 (0147):  // ssx7
5114           {
5115             // For uint32 n = 0, 1, ..., or 7 as determined by operation code
5116             // C(Xn) - C(Y)0,17 -> C(Y)0,17
5117 
5118             L68_ (cpu.ou.cycle |= ou_GOS;)
5119             uint32 n = opcode10 & 07;  // get n
5120 #if defined(TESTING)
5121             HDBGRegXR (n, "ssxn");
5122 #endif
5123             bool ovf;
5124             word18 tmp18 = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5125                                    I_ZNOC, & cpu.cu.IR, & ovf);
5126             SETHI (cpu.CY, tmp18);
5127             overflow (cpup, ovf, true, "ssxn overflow fault");
5128           }
5129           break;
5130 
5131         case x0 (0171):  // swca
5132           {
5133             // If carry indicator ON, then C(A)- C(Y) -> C(A)
5134             // If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
5135 
5136             L68_ (cpu.ou.cycle |= ou_GOS;)
5137 #if defined(TESTING)
5138             HDBGRegAR ("swca");
5139 #endif
5140             bool ovf;
5141             cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
5142                              I_ZNOC, & cpu.cu.IR, & ovf);
5143 #if defined(TESTING)
5144             HDBGRegAW ("swca");
5145 #endif
5146             overflow (cpup, ovf, false, "swca overflow fault");
5147           }
5148           break;
5149 
5150         case x0 (0172):  // swcq
5151           {
5152             // If carry indicator ON, then C(Q) - C(Y) -> C(Q)
5153             // If carry indicator OFF, then C(Q) - C(Y) - 1 -> C(Q)
5154 
5155             L68_ (cpu.ou.cycle |= ou_GOS;)
5156 #if defined(TESTING)
5157             HDBGRegQR ("swcq");
5158 #endif
5159             bool ovf;
5160             cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
5161                                  I_ZNOC, & cpu.cu.IR, & ovf);
5162 #if defined(TESTING)
5163             HDBGRegQW ("swcq");
5164 #endif
5165             overflow (cpup, ovf, false, "swcq overflow fault");
5166           }
5167           break;
5168 
5169         /// Fixed-Point Multiplication
5170 
5171         case x0 (0401):  // mpf
5172           {
5173             // C(A) * C(Y) -> C(AQ), left adjusted
5174             //
5175             // Two 36-bit fractional factors (including sign) are multiplied
5176             // to form a 71- bit fractional product (including sign), which
5177             // is stored left-adjusted in the AQ register. AQ71 contains a
5178             // zero. Overflow can occur only in the case of A and Y
5179             // containing negative 1 and the result exceeding the range of
5180             // the AQ register.
5181 
5182             L68_ (cpu.ou.cycle |= ou_GD1;)
5183 #if defined(NEED_128)
5184 # if defined(TESTING)
5185             HDBGRegAR ("mpf");
5186             HDBGRegQR ("mpf");
5187 # endif
5188             word72 tmp72 = multiply_128 (SIGNEXT36_72 (cpu.rA), SIGNEXT36_72 (cpu.CY));
5189             tmp72        = and_128 (tmp72, MASK72);
5190             tmp72        = lshift_128 (tmp72, 1);
5191 #else
5192             // word72 tmp72 = SIGNEXT36_72 (cpu.rA) * SIGNEXT36_72 (cpu.CY);
5193             // ubsan
5194             word72 tmp72 = (word72) (((word72s) SIGNEXT36_72 (cpu.rA)) * ((word72s) SIGNEXT36_72 (cpu.CY)));
5195             tmp72 &= MASK72;
5196             tmp72 <<= 1;    // left adjust so AQ71 contains 0
5197 #endif
5198             L68_ (cpu.ou.cycle |= ou_GD2;)
5199             // Overflow can occur only in the case of A and Y containing
5200             // negative 1
5201             if (cpu.rA == MAXNEG && cpu.CY == MAXNEG)
5202               {
5203                 SET_I_NEG;
5204                 CLR_I_ZERO;
5205                 overflow (cpup, true, false, "mpf overflow fault");
5206               }
5207 
5208             convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5209 #if defined(TESTING)
5210             HDBGRegAW ("mpf");
5211             HDBGRegQW ("mpf");
5212 #endif
5213             SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5214             SC_I_NEG (cpu.rA & SIGN36);
5215           }
5216           break;
5217 
5218         case x0 (0402):  // mpy
5219           // C(Q) * C(Y) -> C(AQ), right adjusted
5220 
5221           {
5222             L68_ (cpu.ou.cycle |= ou_GOS;)
5223 #if defined(NEED_128)
5224 # if defined(TESTING)
5225             HDBGRegQR ("mpy");
5226 # endif
5227             int128 prod = multiply_s128 (
5228               SIGNEXT36_128 (cpu.rQ & DMASK),
5229               SIGNEXT36_128 (cpu.CY & DMASK));
5230             convert_to_word36 (cast_128 (prod), &cpu.rA, &cpu.rQ);
5231 #else
5232             int64_t t0 = SIGNEXT36_64 (cpu.rQ & DMASK);
5233             int64_t t1 = SIGNEXT36_64 (cpu.CY & DMASK);
5234 
5235             __int128_t prod = (__int128_t) t0 * (__int128_t) t1;
5236 
5237             convert_to_word36 ((word72)prod, &cpu.rA, &cpu.rQ);
5238 #endif
5239 #if defined(TESTING)
5240             HDBGRegAW ("mpy");
5241             HDBGRegQW ("mpy");
5242 #endif
5243 
5244             SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5245             SC_I_NEG (cpu.rA & SIGN36);
5246           }
5247           break;
5248 
5249 //#define DIV_TRACE
5250 
5251         /// Fixed-Point Division
5252 
5253         case x0 (0506):  // div
5254           // C(Q) / (Y) integer quotient -> C(Q), integer remainder -> C(A)
5255           //
5256           // A 36-bit integer dividend (including sign) is divided by a
5257           // 36-bit integer divisor (including sign) to form a 36-bit integer
5258           // * quotient (including sign) and a 36-bit integer remainder
5259           // * (including sign). The remainder sign is equal to the dividend
5260           // * sign unless the remainder is zero.
5261           // *
5262           // * If the dividend = -2**35 and the divisor = -1 or if the divisor
5263           // * = 0, then division does not take place. Instead, a divide check
5264           // * fault occurs, C(Q) contains the dividend magnitude, and the
5265           // * negative indicator reflects the dividend sign.
5266 
5267           L68_ (cpu.ou.cycle |= ou_GD1;)
5268           // RJ78: If the dividend = -2**35 and the divisor = +/-1, or if
5269           // the divisor is 0
5270 
5271 #if defined(TESTING)
5272           HDBGRegQR ("div");
5273 #endif
5274           if ((cpu.rQ == MAXNEG && (cpu.CY == 1 || cpu.CY == NEG136)) ||
5275               (cpu.CY == 0))
5276             {
5277 //sim_printf ("DIV Q %012"PRIo64" Y %012"PRIo64"\n", cpu.rQ, cpu.CY);
5278 // case 1  400000000000 000000000000 --> 000000000000
5279 // case 2  000000000000 000000000000 --> 400000000000
5280               //cpu.rA = 0;  // works for case 1
5281               cpu.rA = (cpu.rQ & SIGN36) ? 0 : SIGN36; // works for case 1,2
5282 #if defined(TESTING)
5283               HDBGRegAW ("div");
5284 #endif
5285 
5286               // no division takes place
5287               SC_I_ZERO (cpu.CY == 0);
5288               SC_I_NEG (cpu.rQ & SIGN36);
5289 
5290               if (cpu.rQ & SIGN36)
5291                 {
5292                   // cpu.rQ = (- cpu.rQ) & MASK36;
5293                   // ubsan
5294                   cpu.rQ = ((word36) (- (word36s) cpu.rQ)) & MASK36;
5295 #if defined(TESTING)
5296                   HDBGRegQW ("div");
5297 #endif
5298                 }
5299 
5300               dlyDoFault (FAULT_DIV,
5301                           fst_ill_op,
5302                           "div divide check");
5303             }
5304           else
5305             {
5306               t_int64 dividend = (t_int64) (SIGNEXT36_64 (cpu.rQ));
5307               t_int64 divisor  = (t_int64) (SIGNEXT36_64 (cpu.CY));
5308 #if defined(TESTING)
5309 # if defined(DIV_TRACE)
5310               sim_debug (DBG_CAC, & cpu_dev, "\n");
5311               sim_debug (DBG_CAC, & cpu_dev,
5312                          ">>> dividend cpu.rQ %"PRId64" (%012"PRIo64")\n",
5313                          dividend, cpu.rQ);
5314               sim_debug (DBG_CAC, & cpu_dev,
5315                          ">>> divisor  CY %"PRId64" (%012"PRIo64")\n",
5316                          divisor, cpu.CY);
5317 # endif
5318 #endif
5319 
5320               t_int64 quotient = dividend / divisor;
5321               L68_ (cpu.ou.cycle |= ou_GD2;)
5322               t_int64 remainder = dividend % divisor;
5323 #if defined(TESTING)
5324 # if defined(DIV_TRACE)
5325               sim_debug (DBG_CAC, & cpu_dev, ">>> quot 1 %"PRId64"\n", quotient);
5326               sim_debug (DBG_CAC, & cpu_dev, ">>> rem 1 %"PRId64"\n", remainder);
5327 # endif
5328 #endif
5329 
5330 // Evidence is that DPS8M rounds toward zero; if it turns out that it
5331 // rounds toward -inf, try this code:
5332 
5333 
5334 
5335 
5336 
5337 
5338 
5339 
5340 
5341 
5342 
5343 
5344 
5345 
5346 
5347 
5348 
5349 #if defined(TESTING)
5350 # if defined(DIV_TRACE)
5351               //  (a/b)*b + a%b is equal to a.
5352               sim_debug (DBG_CAC, & cpu_dev,
5353                          "dividend was                   = %"PRId64"\n", dividend);
5354               sim_debug (DBG_CAC, & cpu_dev,
5355                          "quotient * divisor + remainder = %"PRId64"\n",
5356                          quotient * divisor + remainder);
5357               if (dividend != quotient * divisor + remainder)
5358                 {
5359                   sim_debug (DBG_CAC, & cpu_dev,
5360                      "---------------------------------^^^^^^^^^^^^^^^\n");
5361                 }
5362 # endif
5363 #endif
5364 
5365               if (dividend != quotient * divisor + remainder)
5366                 {
5367                   sim_debug (DBG_ERR, & cpu_dev,
5368                              "Internal division error;"
5369                              " rQ %012"PRIo64" CY %012"PRIo64"\n", cpu.rQ, cpu.CY);
5370                 }
5371 
5372               cpu.rA = (word36) remainder & DMASK;
5373               cpu.rQ = (word36) quotient & DMASK;
5374 #if defined(TESTING)
5375               HDBGRegAW ("div");
5376               HDBGRegQW ("div");
5377 
5378 # if defined(DIV_TRACE)
5379               sim_debug (DBG_CAC, & cpu_dev, "rA (rem)  %012"PRIo64"\n", cpu.rA);
5380               sim_debug (DBG_CAC, & cpu_dev, "rQ (quot) %012"PRIo64"\n", cpu.rQ);
5381 # endif
5382 #endif
5383 
5384               SC_I_ZERO (cpu.rQ == 0);
5385               SC_I_NEG (cpu.rQ & SIGN36);
5386             }
5387 
5388           break;
5389 
5390         case x0 (0507):  // dvf
5391           // C(AQ) / (Y)
5392           //  fractional quotient -> C(A)
5393           //  fractional remainder -> C(Q)
5394 
5395           // A 71-bit fractional dividend (including sign) is divided by a
5396           // 36-bit fractional divisor yielding a 36-bit fractional quotient
5397           // (including sign) and a 36-bit fractional remainder (including
5398           // sign). C(AQ)71 is ignored; bit position 35 of the remainder
5399           // corresponds to bit position 70 of the dividend. The remainder
5400           // sign is equal to the dividend sign unless the remainder is zero.
5401 
5402           // If | dividend | >= | divisor | or if the divisor = 0, division
5403           // does not take place. Instead, a divide check fault occurs, C(AQ)
5404           // contains the dividend magnitude in absolute, and the negative
5405           // indicator reflects the dividend sign.
5406 
5407           dvf (cpup);
5408 
5409           break;
5410 
5411         /// Fixed-Point Negate
5412 
5413         case x0 (0531):  // neg
5414           // -C(A) -> C(A) if C(A) != 0
5415 
5416 #if defined(TESTING)
5417           HDBGRegAR ("neg");
5418 #endif
5419           cpu.rA &= DMASK;
5420           if (cpu.rA == 0400000000000ULL)
5421             {
5422               CLR_I_ZERO;
5423               SET_I_NEG;
5424               overflow (cpup, true, false, "neg overflow fault");
5425             }
5426 
5427           //cpu.rA = -cpu.rA;
5428           // ubsan
5429           cpu.rA = (word36) (- (word36s) cpu.rA);
5430 
5431           cpu.rA &= DMASK;    // keep to 36-bits
5432 #if defined(TESTING)
5433           HDBGRegAW ("neg");
5434 #endif
5435 
5436           SC_I_ZERO (cpu.rA == 0);
5437           SC_I_NEG (cpu.rA & SIGN36);
5438 
5439           break;
5440 
5441         case x0 (0533):  // negl
5442           // -C(AQ) -> C(AQ) if C(AQ) != 0
5443           {
5444 #if defined(TESTING)
5445             HDBGRegAR ("negl");
5446             HDBGRegQR ("negl");
5447 #endif
5448             cpu.rA &= DMASK;
5449             cpu.rQ &= DMASK;
5450 
5451             if (cpu.rA == 0400000000000ULL && cpu.rQ == 0)
5452             {
5453                 CLR_I_ZERO;
5454                 SET_I_NEG;
5455                 overflow (cpup, true, false, "negl overflow fault");
5456             }
5457 
5458             word72 tmp72 = convert_to_word72 (cpu.rA, cpu.rQ);
5459 #if defined(NEED_128)
5460             tmp72 = negate_128 (tmp72);
5461 
5462             SC_I_ZERO (iszero_128 (tmp72));
5463             SC_I_NEG (isnonzero_128 (and_128 (tmp72, SIGN72)));
5464 #else
5465             //tmp72 = -tmp72;
5466             // ubsan
5467             tmp72 = (word72) (-(word72s) tmp72);
5468 
5469             SC_I_ZERO (tmp72 == 0);
5470             SC_I_NEG (tmp72 & SIGN72);
5471 #endif
5472 
5473             convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5474 #if defined(TESTING)
5475             HDBGRegAW ("negl");
5476             HDBGRegQW ("negl");
5477 #endif
5478           }
5479           break;
5480 
5481         /// Fixed-Point Comparison
5482 
5483         case x0 (0405):  // cmg
5484           // | C(A) | :: | C(Y) |
5485           // Zero:     If | C(A) | = | C(Y) | , then ON; otherwise OFF
5486           // Negative: If | C(A) | < | C(Y) | , then ON; otherwise OFF
5487           {
5488             // This is wrong for MAXNEG
5489             //word36 a = cpu.rA & SIGN36 ? -cpu.rA : cpu.rA;
5490             //word36 y = cpu.CY & SIGN36 ? -cpu.CY : cpu.CY;
5491 
5492               // If we do the 64 math, the MAXNEG case works
5493 #if defined(TESTING)
5494               HDBGRegAR ("cmg");
5495 #endif
5496               t_int64 a = SIGNEXT36_64 (cpu.rA);
5497               if (a < 0)
5498                 a = -a;
5499               t_int64 y = SIGNEXT36_64 (cpu.CY);
5500               if (y < 0)
5501                 y = -y;
5502 
5503               SC_I_ZERO (a == y);
5504               SC_I_NEG (a < y);
5505           }
5506           break;
5507 
5508         case x0 (0211):  // cmk
5509           // For i = 0, 1, ..., 35
5510           // C(Z)i = ~C(Q)i & ( C(A)i XOR C(Y)i )
5511 
5512           /*
5513            * The cmk instruction compares the contents of bit positions of A
5514            * and Y for identity that are not masked by a 1 in the
5515            * corresponding bit position of Q.
5516            *
5517            * The zero indicator is set ON if the comparison is successful for
5518            * all bit positions; i.e., if for all i = 0, 1, ..., 35 there is
5519            * either: C(A)i = C(Y)i (the identical case) or C(Q)i = 1 (the
5520            * masked case); otherwise, the zero indicator is set OFF.
5521            *
5522            * The negative indicator is set ON if the comparison is
5523            * unsuccessful for bit position 0; i.e., if C(A)0 XOR C(Y)0 (they
5524            * are nonidentical) as well as C(Q)0 = 0 (they are unmasked);
5525            * otherwise, the negative indicator is set OFF.
5526            */
5527           {
5528 #if defined(TESTING)
5529             HDBGRegAR ("cmk");
5530             HDBGRegQR ("cmk");
5531             HDBGRegYR ("cmk");
5532 #endif
5533             word36 Z = ~cpu.rQ & (cpu.rA ^ cpu.CY);
5534             Z &= DMASK;
5535 #if defined(TESTING)
5536             HDBGRegZW (Z, "cmk");
5537             HDBGRegIR ("cmk");
5538 #endif
5539 
5540 // Q  A  Y   ~Q   A^Y   Z
5541 // 0  0  0    1     0   0
5542 // 0  0  1    1     1   1
5543 // 0  1  0    1     1   1
5544 // 0  1  1    1     0   0
5545 // 1  0  0    0     0   0
5546 // 1  0  1    0     1   0
5547 // 1  1  0    0     1   0
5548 // 1  1  1    0     0   0
5549 
5550             SC_I_ZERO (Z == 0);
5551             SC_I_NEG (Z & SIGN36);
5552           }
5553           break;
5554 
5555 // Optimized to the top of the loop
5556 //        case x0 (0115):  // cmpa
5557 
5558         case x0 (0117):  // cmpaq
5559           // C(AQ) :: C(Y-pair)
5560           {
5561 #if defined(TESTING)
5562             HDBGRegAR ("cmpaq");
5563             HDBGRegQR ("cmpaq");
5564 #endif
5565             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5566             word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5567 #if defined(NEED_128)
5568             trAQ = and_128 (trAQ, MASK72);
5569 #else
5570             trAQ &= MASK72;
5571 #endif
5572             cmp72 (cpup, trAQ, tmp72, &cpu.cu.IR);
5573           }
5574           break;
5575 
5576 // Optimized to the top of the loop
5577 //         case x0 (0116):  // cmpq
5578 
5579                          // cmpxn
5580         case x0 (0100):  // cmpx0
5581         case x0 (0101):  // cmpx1
5582         case x0 (0102):  // cmpx2
5583         case x0 (0103):  // cmpx3
5584         case x0 (0104):  // cmpx4
5585         case x0 (0105):  // cmpx5
5586         case x0 (0106):  // cmpx6
5587         case x0 (0107):  // cmpx7
5588           // For n = 0, 1, ..., or 7 as determined by operation code
5589           // C(Xn) :: C(Y)0,17
5590           {
5591             uint32 n = opcode10 & 07;  // get n
5592 #if defined(TESTING)
5593             HDBGRegXR (n, "cmpxn");
5594 #endif
5595             cmp18 (cpup, cpu.rX[n], GETHI (cpu.CY), &cpu.cu.IR);
5596           }
5597           break;
5598 
5599         case x0 (0111):  // cwl
5600           // C(Y) :: closed interval [C(A);C(Q)]
5601           /*
5602            * The cwl instruction tests the value of C(Y) to determine if it
5603            * is within the range of values set by C(A) and C(Q). The
5604            * comparison of C(Y) with C(Q) locates C(Y) with respect to the
5605            * interval if C(Y) is not contained within the interval.
5606            */
5607 #if defined(TESTING)
5608           HDBGRegAR ("cwl");
5609           HDBGRegQR ("cwl");
5610 #endif
5611           cmp36wl (cpup, cpu.rA, cpu.CY, cpu.rQ, &cpu.cu.IR);
5612           break;
5613 
5614         /// Fixed-Point Miscellaneous
5615 
5616         case x0 (0234):  // szn
5617           // Set indicators according to C(Y)
5618           cpu.CY &= DMASK;
5619           SC_I_ZERO (cpu.CY == 0);
5620           SC_I_NEG (cpu.CY & SIGN36);
5621           break;
5622 
5623         case x0 (0214):  // sznc
5624           // Set indicators according to C(Y)
5625           cpu.CY &= DMASK;
5626           SC_I_ZERO (cpu.CY == 0);
5627           SC_I_NEG (cpu.CY & SIGN36);
5628           // ... and clear
5629           cpu.CY = 0;
5630           break;
5631 
5632         /// BOOLEAN OPERATION INSTRUCTIONS
5633 
5634         /// Boolean And
5635 
5636 // Optimized to the top of the loop
5637 //        case x0 (0375):  // ana
5638 
5639 // Optimized to the top of the loop
5640 //        case x0 (0377):  //< anaq
5641 
5642         case x0 (0376):  // anq
5643           // C(Q)i & C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5644 #if defined(TESTING)
5645           HDBGRegQR ("anq");
5646 #endif
5647           cpu.rQ  = cpu.rQ & cpu.CY;
5648           cpu.rQ &= DMASK;
5649 #if defined(TESTING)
5650           HDBGRegQW ("anq");
5651 #endif
5652 
5653           SC_I_ZERO (cpu.rQ == 0);
5654           SC_I_NEG (cpu.rQ & SIGN36);
5655           break;
5656 
5657         case x0 (0355):  // ansa
5658           // C(A)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5659           {
5660 #if defined(TESTING)
5661             HDBGRegAR ("ansa");
5662 #endif
5663             cpu.CY  = cpu.rA & cpu.CY;
5664             cpu.CY &= DMASK;
5665 
5666             SC_I_ZERO (cpu.CY == 0);
5667             SC_I_NEG (cpu.CY & SIGN36);
5668           }
5669           break;
5670 
5671         case x0 (0356):  // ansq
5672           // C(Q)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5673           {
5674 #if defined(TESTING)
5675             HDBGRegQR ("ansq");
5676 #endif
5677             cpu.CY  = cpu.rQ & cpu.CY;
5678             cpu.CY &= DMASK;
5679 
5680             SC_I_ZERO (cpu.CY == 0);
5681             SC_I_NEG (cpu.CY & SIGN36);
5682           }
5683           break;
5684 
5685                          // ansxn
5686         case x0 (0340):  // ansx0
5687         case x0 (0341):  // ansx1
5688         case x0 (0342):  // ansx2
5689         case x0 (0343):  // ansx3
5690         case x0 (0344):  // ansx4
5691         case x0 (0345):  // ansx5
5692         case x0 (0346):  // ansx6
5693         case x0 (0347):  // ansx7
5694           // For n = 0, 1, ..., or 7 as determined by operation code
5695           // C(Xn)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5696           {
5697             uint32 n = opcode10 & 07;  // get n
5698 #if defined(TESTING)
5699             HDBGRegXR (n, "ansxn");
5700 #endif
5701             word18 tmp18 = cpu.rX[n] & GETHI (cpu.CY);
5702             tmp18 &= MASK18;
5703 
5704             SC_I_ZERO (tmp18 == 0);
5705             SC_I_NEG (tmp18 & SIGN18);
5706 
5707             SETHI (cpu.CY, tmp18);
5708           }
5709 
5710           break;
5711 
5712                          // anxn
5713         case x0 (0360):  // anx0
5714         case x0 (0361):  // anx1
5715         case x0 (0362):  // anx2
5716         case x0 (0363):  // anx3
5717         case x0 (0364):  // anx4
5718         case x0 (0365):  // anx5
5719         case x0 (0366):  // anx6
5720         case x0 (0367):  // anx7
5721           // For n = 0, 1, ..., or 7 as determined by operation code
5722           // C(Xn)i & C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5723           {
5724               uint32 n = opcode10 & 07;  // get n
5725 #if defined(TESTING)
5726               HDBGRegXR (n, "anxn");
5727 #endif
5728               cpu.rX[n] &= GETHI (cpu.CY);
5729               cpu.rX[n] &= MASK18;
5730 #if defined(TESTING)
5731               HDBGRegXW (n, "anxn");
5732 #endif
5733 
5734               SC_I_ZERO (cpu.rX[n] == 0);
5735               SC_I_NEG (cpu.rX[n] & SIGN18);
5736           }
5737           break;
5738 
5739         /// Boolean Or
5740 
5741 // Optimized to the top of the loop
5742 //        case x0 (0275):  // ora
5743 
5744         case x0 (0277):  // oraq
5745           // C(AQ)i | C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
5746           {
5747 #if defined(TESTING)
5748               HDBGRegAR ("oraq");
5749               HDBGRegQR ("oraq");
5750 #endif
5751               word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5752               word72 trAQ  = convert_to_word72 (cpu.rA, cpu.rQ);
5753 #if defined(NEED_128)
5754               trAQ = or_128 (trAQ, tmp72);
5755               trAQ = and_128 (trAQ, MASK72);
5756 
5757               SC_I_ZERO (iszero_128 (trAQ));
5758               SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
5759 #else
5760               trAQ  = trAQ | tmp72;
5761               trAQ &= MASK72;
5762 
5763               SC_I_ZERO (trAQ == 0);
5764               SC_I_NEG (trAQ & SIGN72);
5765 #endif
5766               convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
5767 #if defined(TESTING)
5768               HDBGRegAW ("oraq");
5769               HDBGRegQW ("oraq");
5770 #endif
5771           }
5772           break;
5773 
5774         case x0 (0276):  // orq
5775           // C(Q)i | C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5776 #if defined(TESTING)
5777           HDBGRegQR ("orq");
5778 #endif
5779           cpu.rQ  = cpu.rQ | cpu.CY;
5780           cpu.rQ &= DMASK;
5781 #if defined(TESTING)
5782           HDBGRegQW ("orq");
5783 #endif
5784 
5785           SC_I_ZERO (cpu.rQ == 0);
5786           SC_I_NEG (cpu.rQ & SIGN36);
5787 
5788           break;
5789 
5790         case x0 (0255):  // orsa
5791           // C(A)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5792 #if defined(TESTING)
5793           HDBGRegAR ("orsa");
5794 #endif
5795           cpu.CY  = cpu.rA | cpu.CY;
5796           cpu.CY &= DMASK;
5797 
5798           SC_I_ZERO (cpu.CY == 0);
5799           SC_I_NEG (cpu.CY & SIGN36);
5800           break;
5801 
5802         case x0 (0256):  // orsq
5803           // C(Q)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5804 #if defined(TESTING)
5805           HDBGRegQR ("orsq");
5806 #endif
5807           cpu.CY  = cpu.rQ | cpu.CY;
5808           cpu.CY &= DMASK;
5809 
5810           SC_I_ZERO (cpu.CY == 0);
5811           SC_I_NEG (cpu.CY & SIGN36);
5812           break;
5813 
5814                          // orsxn
5815         case x0 (0240):  // orsx0
5816         case x0 (0241):  // orsx1
5817         case x0 (0242):  // orsx2
5818         case x0 (0243):  // orsx3
5819         case x0 (0244):  // orsx4
5820         case x0 (0245):  // orsx5
5821         case x0 (0246):  // orsx6
5822         case x0 (0247):  // orsx7
5823           // For n = 0, 1, ..., or 7 as determined by operation code
5824           // C(Xn)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5825           {
5826             uint32 n = opcode10 & 07;  // get n
5827 
5828             word18 tmp18  = cpu.rX[n] | GETHI (cpu.CY);
5829             tmp18        &= MASK18;
5830 
5831             SC_I_ZERO (tmp18 == 0);
5832             SC_I_NEG (tmp18 & SIGN18);
5833 
5834             SETHI (cpu.CY, tmp18);
5835           }
5836           break;
5837 
5838                          // orxn
5839         case x0 (0260):  // orx0
5840         case x0 (0261):  // orx1
5841         case x0 (0262):  // orx2
5842         case x0 (0263):  // orx3
5843         case x0 (0264):  // orx4
5844         case x0 (0265):  // orx5
5845         case x0 (0266):  // orx6
5846         case x0 (0267):  // orx7
5847           // For n = 0, 1, ..., or 7 as determined by operation code
5848           // C(Xn)i | C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5849           {
5850               uint32 n = opcode10 & 07;  // get n
5851 #if defined(TESTING)
5852               HDBGRegXR (n, "orxn");
5853 #endif
5854               cpu.rX[n] |= GETHI (cpu.CY);
5855               cpu.rX[n] &= MASK18;
5856 #if defined(TESTING)
5857               HDBGRegXW (n, "orxn");
5858 #endif
5859 
5860               SC_I_ZERO (cpu.rX[n] == 0);
5861               SC_I_NEG (cpu.rX[n] & SIGN18);
5862           }
5863           break;
5864 
5865         /// Boolean Exclusive Or
5866 
5867         case x0 (0675):  // era
5868           // C(A)i XOR C(Y)i -> C(A)i for i = (0, 1, ..., 35)
5869 #if defined(TESTING)
5870           HDBGRegAR ("era");
5871 #endif
5872           cpu.rA  = cpu.rA ^ cpu.CY;
5873           cpu.rA &= DMASK;
5874 #if defined(TESTING)
5875           HDBGRegAW ("era");
5876 #endif
5877 
5878           SC_I_ZERO (cpu.rA == 0);
5879           SC_I_NEG (cpu.rA & SIGN36);
5880 
5881           break;
5882 
5883 // Optimized to the top of the loop
5884 //        case x0 (0677):  // eraq
5885 
5886         case x0 (0676):  // erq
5887           // C(Q)i XOR C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5888 #if defined(TESTING)
5889           HDBGRegQR ("eraq");
5890 #endif
5891           cpu.rQ  = cpu.rQ ^ cpu.CY;
5892           cpu.rQ &= DMASK;
5893 #if defined(TESTING)
5894           HDBGRegQW ("eraq");
5895 #endif
5896           SC_I_ZERO (cpu.rQ == 0);
5897           SC_I_NEG (cpu.rQ & SIGN36);
5898           break;
5899 
5900         case x0 (0655):  // ersa
5901           // C(A)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5902 #if defined(TESTING)
5903           HDBGRegAR ("ersa");
5904 #endif
5905           cpu.CY  = cpu.rA ^ cpu.CY;
5906           cpu.CY &= DMASK;
5907 
5908           SC_I_ZERO (cpu.CY == 0);
5909           SC_I_NEG (cpu.CY & SIGN36);
5910           break;
5911 
5912         case x0 (0656):  // ersq
5913           // C(Q)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5914 #if defined(TESTING)
5915           HDBGRegQR ("ersq");
5916 #endif
5917           cpu.CY  = cpu.rQ ^ cpu.CY;
5918           cpu.CY &= DMASK;
5919 
5920           SC_I_ZERO (cpu.CY == 0);
5921           SC_I_NEG (cpu.CY & SIGN36);
5922 
5923           break;
5924 
5925                           // ersxn
5926         case x0 (0640):   // ersx0
5927         case x0 (0641):   // ersx1
5928         case x0 (0642):   // ersx2
5929         case x0 (0643):   // ersx3
5930         case x0 (0644):   // ersx4
5931         case x0 (0645):   // ersx5
5932         case x0 (0646):   // ersx6
5933         case x0 (0647):   // ersx7
5934           // For n = 0, 1, ..., or 7 as determined by operation code
5935           // C(Xn)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5936           {
5937             uint32 n = opcode10 & 07;  // get n
5938 #if defined(TESTING)
5939             HDBGRegXR (n, "ersxn");
5940 #endif
5941 
5942             word18 tmp18  = cpu.rX[n] ^ GETHI (cpu.CY);
5943             tmp18        &= MASK18;
5944 
5945             SC_I_ZERO (tmp18 == 0);
5946             SC_I_NEG (tmp18 & SIGN18);
5947 
5948             SETHI (cpu.CY, tmp18);
5949           }
5950           break;
5951 
5952                          // erxn
5953         case x0 (0660):  // erx0
5954         case x0 (0661):  // erx1
5955         case x0 (0662):  // erx2
5956         case x0 (0663):  // erx3
5957         case x0 (0664):  // erx4
5958         case x0 (0665):  // erx5
5959         case x0 (0666):  // erx6  !!!! Beware !!!!
5960         case x0 (0667):  // erx7
5961           // For n = 0, 1, ..., or 7 as determined by operation code
5962           // C(Xn)i XOR C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5963           {
5964             uint32 n = opcode10 & 07;  // get n
5965 #if defined(TESTING)
5966             HDBGRegXR (n, "erxn");
5967 #endif
5968             cpu.rX[n] ^= GETHI (cpu.CY);
5969             cpu.rX[n] &= MASK18;
5970 #if defined(TESTING)
5971             HDBGRegXW (n, "erxn");
5972 #endif
5973 
5974             SC_I_ZERO (cpu.rX[n] == 0);
5975             SC_I_NEG (cpu.rX[n] & SIGN18);
5976           }
5977           break;
5978 
5979         /// Boolean Comparative And
5980 
5981 // Optimized to the top of the loop
5982 //        case x0 (0315):  // cana
5983 
5984         case x0 (0317):  // canaq
5985           // C(Z)i = C(AQ)i & C(Y-pair)i for i = (0, 1, ..., 71)
5986           {
5987 #if defined(TESTING)
5988             HDBGRegAR ("canaq");
5989             HDBGRegQR ("canaq");
5990 #endif
5991             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5992             word72 trAQ  = convert_to_word72 (cpu.rA, cpu.rQ);
5993 #if defined(NEED_128)
5994             trAQ = and_128 (trAQ, tmp72);
5995             trAQ = and_128 (trAQ, MASK72);
5996 
5997             SC_I_ZERO (iszero_128 (trAQ));
5998             SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
5999 #else
6000             trAQ = trAQ & tmp72;
6001             trAQ &= MASK72;
6002 
6003             SC_I_ZERO (trAQ == 0);
6004             SC_I_NEG (trAQ & SIGN72);
6005 #endif
6006           }
6007             break;
6008 
6009         case x0 (0316):  // canq
6010           // C(Z)i = C(Q)i & C(Y)i for i = (0, 1, ..., 35)
6011           {
6012 #if defined(TESTING)
6013             HDBGRegQR ("canq");
6014 #endif
6015             word36 trZ = cpu.rQ & cpu.CY;
6016             trZ &= DMASK;
6017 
6018             SC_I_ZERO (trZ == 0);
6019             SC_I_NEG (trZ & SIGN36);
6020           }
6021           break;
6022 
6023                          // canxn
6024         case x0 (0300):  // canx0
6025         case x0 (0301):  // canx1
6026         case x0 (0302):  // canx2
6027         case x0 (0303):  // canx3
6028         case x0 (0304):  // canx4
6029         case x0 (0305):  // canx5
6030         case x0 (0306):  // canx6
6031         case x0 (0307):  // canx7
6032           // For n = 0, 1, ..., or 7 as determined by operation code
6033           // C(Z)i = C(Xn)i & C(Y)i for i = (0, 1, ..., 17)
6034           {
6035             uint32 n = opcode10 & 07;  // get n
6036 #if defined(TESTING)
6037             HDBGRegXR (n, "canxn");
6038 #endif
6039             word18 tmp18  = cpu.rX[n] & GETHI (cpu.CY);
6040             tmp18        &= MASK18;
6041             sim_debug (DBG_TRACEEXT, & cpu_dev,
6042                        "n %o rX %06o HI %06o tmp %06o\n",
6043                        n, cpu.rX[n], (word18) (GETHI (cpu.CY) & MASK18),
6044                        tmp18);
6045 
6046             SC_I_ZERO (tmp18 == 0);
6047             SC_I_NEG (tmp18 & SIGN18);
6048           }
6049           break;
6050 
6051         /// Boolean Comparative Not
6052 
6053         case x0 (0215):  // cnaa
6054           // C(Z)i = C(A)i & ~C(Y)i for i = (0, 1, ..., 35)
6055           {
6056 #if defined(TESTING)
6057             HDBGRegAR ("cnaa");
6058 #endif
6059             word36 trZ = cpu.rA & ~cpu.CY;
6060             trZ &= DMASK;
6061 
6062             SC_I_ZERO (trZ == 0);
6063             SC_I_NEG (trZ & SIGN36);
6064           }
6065           break;
6066 
6067         case x0 (0217):  // cnaaq
6068           // C(Z)i = C (AQ)i & ~C(Y-pair)i for i = (0, 1, ..., 71)
6069           {
6070 #if defined(TESTING)
6071             HDBGRegAR ("cnaaq");
6072             HDBGRegQR ("cnaaq");
6073 #endif
6074             word72 tmp72 = YPAIRTO72 (cpu.Ypair);
6075 
6076             word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
6077 #if defined(NEED_128)
6078             trAQ = and_128 (trAQ, complement_128 (tmp72));
6079             trAQ = and_128 (trAQ, MASK72);
6080 
6081             SC_I_ZERO (iszero_128 (trAQ));
6082             SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
6083 #else
6084             trAQ = trAQ & ~tmp72;
6085             trAQ &= MASK72;
6086 
6087             SC_I_ZERO (trAQ == 0);
6088             SC_I_NEG (trAQ & SIGN72);
6089 #endif
6090           }
6091           break;
6092 
6093         case x0 (0216):  // cnaq
6094           // C(Z)i = C(Q)i & ~C(Y)i for i = (0, 1, ..., 35)
6095           {
6096 #if defined(TESTING)
6097             HDBGRegQR ("cnaq");
6098 #endif
6099             word36 trZ = cpu.rQ & ~cpu.CY;
6100             trZ &= DMASK;
6101             SC_I_ZERO (trZ == 0);
6102             SC_I_NEG (trZ & SIGN36);
6103           }
6104           break;
6105 
6106                          // cnaxn
6107         case x0 (0200):  // cnax0
6108         case x0 (0201):  // cnax1
6109         case x0 (0202):  // cnax2
6110         case x0 (0203):  // cnax3
6111         case x0 (0204):  // cnax4
6112         case x0 (0205):  // cnax5
6113         case x0 (0206):  // cnax6
6114         case x0 (0207):  // cnax7
6115           // C(Z)i = C(Xn)i & ~C(Y)i for i = (0, 1, ..., 17)
6116           {
6117             uint32 n = opcode10 & 07;  // get n
6118 #if defined(TESTING)
6119             HDBGRegXR (n, "cnaxn");
6120 #endif
6121             word18 tmp18 = cpu.rX[n] & ~GETHI (cpu.CY);
6122             tmp18 &= MASK18;
6123 
6124             SC_I_ZERO (tmp18 == 0);
6125             SC_I_NEG (tmp18 & SIGN18);
6126           }
6127           break;
6128 
6129         /// FLOATING-POINT ARITHMETIC INSTRUCTIONS
6130 
6131         /// Floating-Point Data Movement Load
6132 
6133         case x0 (0433):  // dfld
6134           // C(Y-pair)0,7 -> C(E)
6135           // C(Y-pair)8,71 -> C(AQ)0,63
6136           // 00...0 -> C(AQ)64,71
6137           // Zero: If C(AQ) = 0, then ON; otherwise OFF
6138           // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
6139 
6140           CPTUR (cptUseE);
6141           cpu.rE  = (cpu.Ypair[0] >> 28) & MASK8;
6142 
6143           cpu.rA  = (cpu.Ypair[0] & FLOAT36MASK) << 8;
6144           cpu.rA |= (cpu.Ypair[1] >> 28) & MASK8;
6145 
6146           cpu.rQ  = (cpu.Ypair[1] & FLOAT36MASK) << 8;
6147 
6148 #if defined(TESTING)
6149           HDBGRegAW ("dfld");
6150           HDBGRegQW ("dfld");
6151 #endif
6152 
6153           SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
6154           SC_I_NEG (cpu.rA & SIGN36);
6155           break;
6156 
6157 // Optimized to the top of the loop
6158 //        case x0 (0431):  // fld
6159 
6160         /// Floating-Point Data Movement Store
6161 
6162         case x0 (0457):  // dfst
6163           // C(E) -> C(Y-pair)0,7
6164           // C(AQ)0,63 -> C(Y-pair)8,71
6165 
6166           CPTUR (cptUseE);
6167 #if defined(TESTING)
6168           HDBGRegAR ("dfst");
6169           HDBGRegQR ("dfst");
6170 #endif
6171           cpu.Ypair[0] = ((word36)cpu.rE << 28) |
6172                          ((cpu.rA & 0777777777400LLU) >> 8);
6173           cpu.Ypair[1] = ((cpu.rA & 0377) << 28) |
6174                          ((cpu.rQ & 0777777777400LLU) >> 8);
6175 
6176           break;
6177 
6178         case x0 (0472):  // dfstr
6179 
6180           dfstr (cpup, cpu.Ypair);
6181           break;
6182 
6183         case x0 (0455):  // fst
6184           // C(E) -> C(Y)0,7
6185           // C(A)0,27 -> C(Y)8,35
6186           CPTUR (cptUseE);
6187 #if defined(TESTING)
6188           HDBGRegAR ("fst");
6189 #endif
6190           cpu.rE &= MASK8;
6191           cpu.rA &= DMASK;
6192           cpu.CY = ((word36)cpu.rE << 28) | (((cpu.rA >> 8) & 01777777777LL));
6193           break;
6194 
6195         case x0 (0470):  // fstr
6196           // The fstr instruction performs a true round and normalization on
6197           // C(EAQ) as it is stored.
6198 
6199 //            frd ();
6200 //
6201 //            // C(E) -> C(Y)0,7
6202 //            // C(A)0,27 -> C(Y)8,35
6203 //            cpu.CY = ((word36)cpu.rE << 28) |
6204 //                     (((cpu.rA >> 8) & 01777777777LL));
6205 //
6206 //            // Zero: If C(Y) = floating point 0, then ON; otherwise OFF
6207 //            //SC_I_ZERO ((cpu.CY & 01777777777LL) == 0);
6208 //            bool isZero = cpu.rE == -128 && cpu.rA == 0;
6209 //            SC_I_ZERO (isZero);
6210 //
6211 //            // Neg: If C(Y)8 = 1, then ON; otherwise OFF
6212 //            //SC_I_NEG (cpu.CY & 01000000000LL);
6213 //            SC_I_NEG (cpu.rA & SIGN36);
6214 //
6215 //            // Exp Ovr: If exponent is greater than +127, then ON
6216 //            // Exp Undr: If exponent is less than -128, then ON
6217 //            // XXX: not certain how these can occur here ....
6218 
6219           fstr (cpup, &cpu.CY);
6220 
6221           break;
6222 
6223         /// Floating-Point Addition
6224 
6225         case x0 (0477):  // dfad
6226           // The dfad instruction may be thought of as a dufa instruction
6227           // followed by a fno instruction.
6228 
6229           CPTUR (cptUseE);
6230 #if defined(TESTING)
6231           HDBGRegAR ("dfad");
6232           HDBGRegQR ("dfad");
6233 #endif
6234           dufa (cpup, false, true);
6235 #if defined(TESTING)
6236           HDBGRegAW ("dfad");
6237           HDBGRegQW ("dfad");
6238 #endif
6239           break;
6240 
6241         case x0 (0437):  // dufa
6242           dufa (cpup, false, false);
6243           break;
6244 
6245         case x0 (0475):  // fad
6246           // The fad instruction may be thought of a an ufa instruction
6247           // followed by a fno instruction.
6248           // (Heh, heh. We'll see....)
6249 
6250           CPTUR (cptUseE);
6251 #if defined(TESTING)
6252           HDBGRegAR ("fad");
6253           HDBGRegQR ("fad");
6254 #endif
6255           ufa (cpup, false, true);
6256 #if defined(TESTING)
6257           HDBGRegAW ("fad");
6258           HDBGRegQW ("fad");
6259 #endif
6260 
6261           break;
6262 
6263         case x0 (0435):  // ufa
6264             // C(EAQ) + C(Y) -> C(EAQ)
6265 
6266           ufa (cpup, false, false);
6267           break;
6268 
6269         /// Floating-Point Subtraction
6270 
6271         case x0 (0577):  // dfsb
6272           // The dfsb instruction is identical to the dfad instruction with
6273           // the exception that the twos complement of the mantissa of the
6274           // operand from main memory is used.
6275 
6276           CPTUR (cptUseE);
6277 #if defined(TESTING)
6278           HDBGRegAR ("dfsb");
6279           HDBGRegQR ("dfsb");
6280 #endif
6281           dufa (cpup, true, true);
6282 #if defined(TESTING)
6283           HDBGRegAW ("dfsb");
6284           HDBGRegQW ("dfsb");
6285 #endif
6286           break;
6287 
6288         case x0 (0537):  // dufs
6289           dufa (cpup, true, false);
6290           break;
6291 
6292         case x0 (0575):  // fsb
6293           // The fsb instruction may be thought of as an ufs instruction
6294           // followed by a fno instruction.
6295 #if defined(TESTING)
6296           HDBGRegAR ("fsb");
6297           HDBGRegQR ("fsb");
6298 #endif
6299           CPTUR (cptUseE);
6300           ufa (cpup, true, true);
6301 #if defined(TESTING)
6302           HDBGRegAW ("fsb");
6303           HDBGRegQW ("fsb");
6304 #endif
6305           break;
6306 
6307         case x0 (0535):  // ufs
6308           // C(EAQ) - C(Y) -> C(EAQ)
6309           ufa (cpup, true, false);
6310           break;
6311 
6312         /// Floating-Point Multiplication
6313 
6314         case x0 (0463):  // dfmp
6315           // The dfmp instruction may be thought of as a dufm instruction
6316           // followed by a fno instruction.
6317 
6318           CPTUR (cptUseE);
6319 #if defined(TESTING)
6320           HDBGRegAR ("dfmp");
6321           HDBGRegQR ("dfmp");
6322 #endif
6323           dufm (cpup, true);
6324 #if defined(TESTING)
6325           HDBGRegAW ("dfmp");
6326           HDBGRegQW ("dfmp");
6327 #endif
6328           break;
6329 
6330         case x0 (0423):  // dufm
6331 
6332           dufm (cpup, false);
6333           break;
6334 
6335         case x0 (0461):  // fmp
6336           // The fmp instruction may be thought of as a ufm instruction
6337           // followed by a fno instruction.
6338 
6339           CPTUR (cptUseE);
6340           ufm (cpup, true);
6341 #if defined(TESTING)
6342           HDBGRegAW ("fmp");
6343           HDBGRegQW ("fmp");
6344 #endif
6345           break;
6346 
6347         case x0 (0421):  // ufm
6348           // C(EAQ)* C(Y) -> C(EAQ)
6349           ufm (cpup, false);
6350           break;
6351 
6352         /// Floating-Point Division
6353 
6354         case x0 (0527):  // dfdi
6355 
6356           dfdi (cpup);
6357           break;
6358 
6359         case x0 (0567):  // dfdv
6360 
6361           dfdv (cpup);
6362           break;
6363 
6364         case x0 (0525):  // fdi
6365           // C(Y) / C(EAQ) -> C(EA)
6366 
6367           fdi (cpup);
6368           break;
6369 
6370         case x0 (0565):  // fdv
6371           // C(EAQ) /C(Y) -> C(EA)
6372           // 00...0 -> C(Q)
6373           fdv (cpup);
6374           break;
6375 
6376         /// Floating-Point Negation
6377 
6378         case x0 (0513):  // fneg
6379           // -C(EAQ) normalized -> C(EAQ)
6380           fneg (cpup);
6381           break;
6382 
6383         /// Floating-Point Normalize
6384 
6385         case x0 (0573):  // fno
6386           // The fno instruction normalizes the number in C(EAQ) if C(AQ)
6387           // != 0 and the overflow indicator is OFF.
6388           //
6389           // A normalized floating number is defined as one whose mantissa
6390           // lies in the interval [0.5,1.0) such that 0.5<= |C(AQ)| <1.0
6391           // which, in turn, requires that C(AQ)0 != C(AQ)1.list
6392           //
6393           // !!!! For personal reasons the following 3 lines of comment must
6394           // never be removed from this program or any code derived
6395           // there from. HWR 25 Aug 2014
6396           ///Charles Is the coolest
6397           ///true story y'all
6398           //you should get me darksisers 2 for christmas
6399 
6400           CPTUR (cptUseE);
6401           fno (cpup, & cpu.rE, & cpu.rA, & cpu.rQ);
6402 #if defined(TESTING)
6403           HDBGRegAW ("fno");
6404           HDBGRegQW ("fno");
6405 #endif
6406           break;
6407 
6408         /// Floating-Point Round
6409 
6410         case x0 (0473):  // dfrd
6411           // C(EAQ) rounded to 64 bits -> C(EAQ)
6412           // 0 -> C(AQ)64,71 (See notes in dps8_math.c on dfrd())
6413 
6414           dfrd (cpup);
6415           break;
6416 
6417         case x0 (0471):  // frd
6418           // C(EAQ) rounded to 28 bits -> C(EAQ)
6419           // 0 -> C(AQ)28,71 (See notes in dps8_math.c on frd())
6420 
6421           frd (cpup);
6422           break;
6423 
6424         /// Floating-Point Compare
6425 
6426         case x0 (0427):  // dfcmg
6427           // C(E) :: C(Y-pair)0,7
6428           // | C(AQ)0,63 | :: | C(Y-pair)8,71 |
6429 
6430           dfcmg (cpup);
6431           break;
6432 
6433         case x0 (0517):  // dfcmp
6434           // C(E) :: C(Y-pair)0,7
6435           // C(AQ)0,63 :: C(Y-pair)8,71
6436 
6437           dfcmp (cpup);
6438           break;
6439 
6440         case x0 (0425):  // fcmg
6441           // C(E) :: C(Y)0,7
6442           // | C(AQ)0,27 | :: | C(Y)8,35 |
6443 
6444           fcmg (cpup);
6445           break;
6446 
6447         case x0 (0515):  // fcmp
6448           // C(E) :: C(Y)0,7
6449           // C(AQ)0,27 :: C(Y)8,35
6450 
6451           fcmp (cpup);
6452           break;
6453 
6454         /// Floating-Point Miscellaneous
6455 
6456         case x0 (0415):  // ade
6457           // C(E) + C(Y)0,7 -> C(E)
6458           {
6459             CPTUR (cptUseE);
6460             int y = SIGNEXT8_int ((cpu.CY >> 28) & 0377);
6461             int e = SIGNEXT8_int (cpu.rE);
6462             e = e + y;
6463 
6464             cpu.rE = e & 0377;
6465             CLR_I_ZERO;
6466             CLR_I_NEG;
6467 
6468             if (e > 127)
6469               {
6470                 SET_I_EOFL;
6471                 if (tstOVFfault (cpup))
6472                   doFault (FAULT_OFL, fst_zero, "ade exp overflow fault");
6473               }
6474 
6475             if (e < -128)
6476               {
6477                 SET_I_EUFL;
6478                 if (tstOVFfault (cpup))
6479                   doFault (FAULT_OFL, fst_zero, "ade exp underflow fault");
6480               }
6481           }
6482           break;
6483 
6484         case x0 (0430):  // fszn
6485 
6486           // Zero: If C(Y)8,35 = 0, then ON; otherwise OFF
6487           // Negative: If C(Y)8 = 1, then ON; otherwise OFF
6488 
6489           SC_I_ZERO ((cpu.CY & 001777777777LL) == 0);
6490           SC_I_NEG (cpu.CY & 001000000000LL);
6491 
6492           break;
6493 
6494         case x0 (0411):  // lde
6495           // C(Y)0,7 -> C(E)
6496 
6497           CPTUR (cptUseE);
6498           cpu.rE = (cpu.CY >> 28) & 0377;
6499           CLR_I_ZERO;
6500           CLR_I_NEG;
6501 
6502           break;
6503 
6504         case x0 (0456):  // ste
6505           // C(E) -> C(Y)0,7
6506           // 00...0 -> C(Y)8,17
6507 
6508           CPTUR (cptUseE);
6509           //putbits36_18 (& cpu.CY, 0, ((word18) (cpu.rE & 0377) << 10));
6510           cpu.CY = ((word36) (cpu.rE & 0377)) << 28;
6511           cpu.zone = 0777777000000;
6512           cpu.useZone = true;
6513           break;
6514 
6515         /// TRANSFER INSTRUCTIONS
6516 
6517         case x0 (0713):  // call6
6518 
6519           CPTUR (cptUsePRn + 7);
6520 
6521           do_caf (cpup);
6522           read_tra_op (cpup);
6523           sim_debug (DBG_TRACEEXT, & cpu_dev,
6524                      "call6 PRR %o PSR %o\n", cpu.PPR.PRR, cpu.PPR.PSR);
6525 
6526           return CONT_TRA;
6527 
6528         case x0 (0630):  // ret
6529           {
6530             // Parity mask: If C(Y)27 = 1, and the processor is in absolute or
6531             // mask privileged mode, then ON; otherwise OFF. This indicator is
6532             // not affected in the normal or BAR modes.
6533             // Not BAR mode: Can be set OFF but not ON by the ret instruction
6534             // Absolute mode: Can be set OFF but not ON by the ret instruction
6535             // All other indicators: If corresponding bit in C(Y) is 1, then ON;
6536             // otherwise, OFF
6537 
6538             // C(Y)0,17 -> C(PPR.IC)
6539             // C(Y)18,31 -> C(IR)
6540             do_caf (cpup);
6541             ReadOperandRead (cpup, cpu.TPR.CA, & cpu.CY);
6542 
6543             cpu.PPR.IC = GETHI (cpu.CY);
6544             word18 tempIR = GETLO (cpu.CY) & 0777770;
6545             // Assuming 'mask privileged mode' is 'temporary absolute mode'
6546             if (is_priv_mode (cpup)) // abs. or temp. abs. or priv.
6547               {
6548                 // if abs, copy existing parity mask to tempIR
6549                 // According to ISOLTS pm785, not the case.
6550                 //SCF (TST_I_PMASK, tempIR, I_PMASK);
6551                 // if abs, copy existing I_MIF to tempIR
6552                 SCF (TST_I_MIF, tempIR, I_MIF);
6553               }
6554             else
6555               {
6556                 CLRF (tempIR, I_MIF);
6557               }
6558             // can be set OFF but not on
6559             //  IR   ret   result
6560             //  off  off   off
6561             //  off  on    off
6562             //  on   on    on
6563             //  on   off   off
6564             // "If it was on, set it to on"
6565             //SCF (TST_I_NBAR, tempIR, I_NBAR);
6566             if (! (TST_I_NBAR && TSTF (tempIR, I_NBAR)))
6567               {
6568                 CLRF (tempIR, I_NBAR);
6569               }
6570             if (! (TST_I_ABS && TSTF (tempIR, I_ABS)))
6571               {
6572                 CLRF (tempIR, I_ABS);
6573               }
6574 
6575             //sim_debug (DBG_TRACEEXT, & cpu_dev,
6576             //           "RET NBAR was %d now %d\n",
6577             //           TST_NBAR ? 1 : 0,
6578             //           TSTF (tempIR, I_NBAR) ? 1 : 0);
6579             //sim_debug (DBG_TRACEEXT, & cpu_dev,
6580             //           "RET ABS  was %d now %d\n",
6581             //           TST_I_ABS ? 1 : 0,
6582             //           TSTF (tempIR, I_ABS) ? 1 : 0);
6583             CPTUR (cptUseIR);
6584             cpu.cu.IR = tempIR;
6585             return CONT_RET;
6586           }
6587 
6588 // Optimized to the top of the loop
6589 //        case x0 (0610):  // rtcd
6590 
6591         case x0 (0614):  // teo
6592           // If exponent overflow indicator ON then
6593           //  C(TPR.CA) -> C(PPR.IC)
6594           //  C(TPR.TSR) -> C(PPR.PSR)
6595           // otherwise, no change to C(PPR)
6596           if (TST_I_EOFL)
6597             {
6598               CLR_I_EOFL;
6599               do_caf (cpup);
6600               read_tra_op (cpup);
6601               return CONT_TRA;
6602             }
6603           break;
6604 
6605         case x0 (0615):  // teu
6606           // If exponent underflow indicator ON then
6607           //  C(TPR.CA) -> C(PPR.IC)
6608           //  C(TPR.TSR) -> C(PPR.PSR)
6609           if (TST_I_EUFL)
6610             {
6611               CLR_I_EUFL;
6612               do_caf (cpup);
6613               read_tra_op (cpup);
6614               return CONT_TRA;
6615             }
6616           break;
6617 
6618 // Optimized to the top of the loop
6619 //        case x0 (0604):  // tmi
6620 
6621 // Optimized to the top of the loop
6622 //        case x1 (0604):  // tmoz
6623 
6624         case x0 (0602):  // tnc
6625           // If carry indicator OFF then
6626           //   C(TPR.CA) -> C(PPR.IC)
6627           //   C(TPR.TSR) -> C(PPR.PSR)
6628           if (!TST_I_CARRY)
6629             {
6630               do_caf (cpup);
6631               read_tra_op (cpup);
6632               return CONT_TRA;
6633             }
6634           break;
6635 
6636 // Optimized to the top of the loop
6637 //         case x0 (0601):  // tnz
6638 
6639         case x0 (0617):  // tov
6640           // If overflow indicator ON then
6641           //   C(TPR.CA) -> C(PPR.IC)
6642           //   C(TPR.TSR) -> C(PPR.PSR)
6643           if (TST_I_OFLOW)
6644             {
6645               CLR_I_OFLOW;
6646               do_caf (cpup);
6647               read_tra_op (cpup);
6648               return CONT_TRA;
6649             }
6650           break;
6651 
6652         case x0 (0605):  // tpl
6653           // If negative indicator OFF, then
6654           //   C(TPR.CA) -> C(PPR.IC)
6655           //   C(TPR.TSR) -> C(PPR.PSR)
6656           if (! (TST_I_NEG))
6657             {
6658               do_caf (cpup);
6659               read_tra_op (cpup);
6660               return CONT_TRA;
6661             }
6662           break;
6663 
6664 // Optimized to the top of the loop
6665 //        case x1 (0605):  // tpnz
6666 
6667 // Optimized to the top of the loop
6668 //        case x0 (0710):  // tra
6669 
6670         case x0 (0603):  // trc
6671           //  If carry indicator ON then
6672           //    C(TPR.CA) -> C(PPR.IC)
6673           //    C(TPR.TSR) -> C(PPR.PSR)
6674           if (TST_I_CARRY)
6675             {
6676               do_caf (cpup);
6677               read_tra_op (cpup);
6678               return CONT_TRA;
6679             }
6680           break;
6681 
6682         case x1 (0601):  // trtf
6683             // If truncation indicator OFF then
6684             //  C(TPR.CA) -> C(PPR.IC)
6685             //  C(TPR.TSR) -> C(PPR.PSR)
6686             if (!TST_I_TRUNC)
6687             {
6688                 do_caf (cpup);
6689                 read_tra_op (cpup);
6690                 return CONT_TRA;
6691             }
6692             break;
6693 
6694         case x1 (0600):  // trtn
6695             // If truncation indicator ON then
6696             //  C(TPR.CA) -> C(PPR.IC)
6697             //  C(TPR.TSR) -> C(PPR.PSR)
6698             if (TST_I_TRUNC)
6699             {
6700                 CLR_I_TRUNC;
6701                 do_caf (cpup);
6702                 read_tra_op (cpup);
6703                 return CONT_TRA;
6704             }
6705             break;
6706 
6707 // Optimized to the top of the loop
6708 //                         // tspn
6709 //        case x0 (0270):  // tsp0
6710 //        case x0 (0271):  // tsp1
6711 //        case x0 (0272):  // tsp2
6712 //        case x0 (0273):  // tsp3
6713 //        case x0 (0670):  // tsp4
6714 //        case x0 (0671):  // tsp5
6715 //        case x0 (0672):  // tsp6
6716 //        case x0 (0673):  // tsp7
6717 
6718         case x0 (0715):  // tss
6719           CPTUR (cptUseBAR);
6720           do_caf (cpup);
6721           if (get_bar_mode (cpup))
6722             read_tra_op (cpup);
6723           else
6724             {
6725               cpu.TPR.CA = get_BAR_address (cpup, cpu.TPR.CA);
6726               read_tra_op (cpup);
6727               CLR_I_NBAR;
6728             }
6729           return CONT_TRA;
6730 
6731 // Optimized to the top of the loop
6732 //                         // tsxn
6733 //        case x0 (0700):  // tsx0
6734 //        case x0 (0701):  // tsx1
6735 //        case x0 (0702):  // tsx2
6736 //        case x0 (0703):  // tsx3
6737 //        case x0 (0704):  // tsx4
6738 //        case x0 (0705):  // tsx5
6739 //        case x0 (0706):  // tsx6
6740 //        case x0 (0707):  // tsx7
6741 
6742         case x0 (0607):  // ttf
6743           // If tally runout indicator OFF then
6744           //   C(TPR.CA) -> C(PPR.IC)
6745           //  C(TPR.TSR) -> C(PPR.PSR)
6746           // otherwise, no change to C(PPR)
6747           if (TST_I_TALLY == 0)
6748             {
6749               do_caf (cpup);
6750               read_tra_op (cpup);
6751               return CONT_TRA;
6752             }
6753           break;
6754 
6755         case x1 (0606):  // ttn
6756             // If tally runout indicator ON then
6757             //  C(TPR.CA) -> C(PPR.IC)
6758             //  C(TPR.TSR) -> C(PPR.PSR)
6759             // otherwise, no change to C(PPR)
6760             if (TST_I_TALLY)
6761             {
6762                 do_caf (cpup);
6763                 read_tra_op (cpup);
6764                 return CONT_TRA;
6765             }
6766             break;
6767 
6768 // Optimized to the top of the loop
6769 //        case x0 (0600):  // tze
6770 
6771         /// POINTER REGISTER INSTRUCTIONS
6772 
6773         /// Pointer Register Data Movement Load
6774 
6775                          // easpn
6776 
6777         case x0 (0311):  // easp0
6778           // C(TPR.CA) -> C(PRn.SNR)
6779           CPTUR (cptUsePRn + 0);
6780           cpu.PR[0].SNR = cpu.TPR.CA & MASK15;
6781 #if defined(TESTING)
6782           HDBGRegPRW (0, "easp0");
6783 #endif
6784           break;
6785 
6786         case x1 (0310):  // easp1
6787           // C(TPR.CA) -> C(PRn.SNR)
6788           CPTUR (cptUsePRn + 1);
6789           cpu.PR[1].SNR = cpu.TPR.CA & MASK15;
6790 #if defined(TESTING)
6791           HDBGRegPRW (1, "easp1");
6792 #endif
6793           break;
6794 
6795         case x0 (0313):  // easp2
6796           // C(TPR.CA) -> C(PRn.SNR)
6797           CPTUR (cptUsePRn + 2);
6798           cpu.PR[2].SNR = cpu.TPR.CA & MASK15;
6799 #if defined(TESTING)
6800           HDBGRegPRW (2, "easp2");
6801 #endif
6802           break;
6803 
6804         case x1 (0312):  // easp3
6805           // C(TPR.CA) -> C(PRn.SNR)
6806           CPTUR (cptUsePRn + 3);
6807           cpu.PR[3].SNR = cpu.TPR.CA & MASK15;
6808 #if defined(TESTING)
6809           HDBGRegPRW (3, "easp3");
6810 #endif
6811           break;
6812 
6813         case x0 (0331):  // easp4
6814           // C(TPR.CA) -> C(PRn.SNR)
6815           CPTUR (cptUsePRn + 4);
6816           cpu.PR[4].SNR = cpu.TPR.CA & MASK15;
6817 #if defined(TESTING)
6818           HDBGRegPRW (4, "easp4");
6819 #endif
6820           break;
6821 
6822         case x1 (0330):  // easp5
6823           // C(TPR.CA) -> C(PRn.SNR)
6824           CPTUR (cptUsePRn + 5);
6825           cpu.PR[5].SNR = cpu.TPR.CA & MASK15;
6826 #if defined(TESTING)
6827           HDBGRegPRW (5, "easp5");
6828 #endif
6829           break;
6830 
6831         case x0 (0333):  // easp6
6832           // C(TPR.CA) -> C(PRn.SNR)
6833           CPTUR (cptUsePRn + 6);
6834           cpu.PR[6].SNR = cpu.TPR.CA & MASK15;
6835 #if defined(TESTING)
6836           HDBGRegPRW (6, "easp6");
6837 #endif
6838           break;
6839 
6840         case x1 (0332):  // easp7
6841           // C(TPR.CA) -> C(PRn.SNR)
6842           CPTUR (cptUsePRn + 7);
6843           cpu.PR[7].SNR = cpu.TPR.CA & MASK15;
6844 #if defined(TESTING)
6845           HDBGRegPRW (7, "easp7");
6846 #endif
6847           break;
6848 
6849                          // eawpn
6850 
6851         case x0 (0310):  // eawp0
6852           // For n = 0, 1, ..., or 7 as determined by operation code
6853           //  C(TPR.CA) -> C(PRn.WORDNO)
6854           //  C(TPR.TBR) -> C(PRn.BITNO)
6855           CPTUR (cptUsePRn + 0);
6856           cpu.PR[0].WORDNO = cpu.TPR.CA;
6857           SET_PR_BITNO (0, cpu.TPR.TBR);
6858 #if defined(TESTING)
6859           HDBGRegPRW (0, "eawp0");
6860 #endif
6861           break;
6862 
6863         case x1 (0311):  // eawp1
6864           // For n = 0, 1, ..., or 7 as determined by operation code
6865           //  C(TPR.CA) -> C(PRn.WORDNO)
6866           //  C(TPR.TBR) -> C(PRn.BITNO)
6867           CPTUR (cptUsePRn + 1);
6868           cpu.PR[1].WORDNO = cpu.TPR.CA;
6869           SET_PR_BITNO (1, cpu.TPR.TBR);
6870 #if defined(TESTING)
6871           HDBGRegPRW (1, "eawp1");
6872 #endif
6873           break;
6874 
6875         case x0 (0312):  // eawp2
6876           // For n = 0, 1, ..., or 7 as determined by operation code
6877           //  C(TPR.CA) -> C(PRn.WORDNO)
6878           //  C(TPR.TBR) -> C(PRn.BITNO)
6879           CPTUR (cptUsePRn + 2);
6880           cpu.PR[2].WORDNO = cpu.TPR.CA;
6881           SET_PR_BITNO (2, cpu.TPR.TBR);
6882 #if defined(TESTING)
6883           HDBGRegPRW (2, "eawp2");
6884 #endif
6885           break;
6886 
6887         case x1 (0313):  // eawp3
6888           // For n = 0, 1, ..., or 7 as determined by operation code
6889           //  C(TPR.CA) -> C(PRn.WORDNO)
6890           //  C(TPR.TBR) -> C(PRn.BITNO)
6891           CPTUR (cptUsePRn + 3);
6892           cpu.PR[3].WORDNO = cpu.TPR.CA;
6893           SET_PR_BITNO (3, cpu.TPR.TBR);
6894 #if defined(TESTING)
6895           HDBGRegPRW (3, "eawp3");
6896 #endif
6897           break;
6898 
6899         case x0 (0330):  // eawp4
6900           // For n = 0, 1, ..., or 7 as determined by operation code
6901           //  C(TPR.CA) -> C(PRn.WORDNO)
6902           //  C(TPR.TBR) -> C(PRn.BITNO)
6903           CPTUR (cptUsePRn + 4);
6904           cpu.PR[4].WORDNO = cpu.TPR.CA;
6905           SET_PR_BITNO (4, cpu.TPR.TBR);
6906 #if defined(TESTING)
6907           HDBGRegPRW (4, "eawp4");
6908 #endif
6909           break;
6910 
6911         case x1 (0331):  // eawp5
6912           // For n = 0, 1, ..., or 7 as determined by operation code
6913           //  C(TPR.CA) -> C(PRn.WORDNO)
6914           //  C(TPR.TBR) -> C(PRn.BITNO)
6915           CPTUR (cptUsePRn + 5);
6916           cpu.PR[5].WORDNO = cpu.TPR.CA;
6917           SET_PR_BITNO (5, cpu.TPR.TBR);
6918 #if defined(TESTING)
6919           HDBGRegPRW (5, "eawp5");
6920 #endif
6921           break;
6922 
6923         case x0 (0332):  // eawp6
6924           // For n = 0, 1, ..., or 7 as determined by operation code
6925           //  C(TPR.CA) -> C(PRn.WORDNO)
6926           //  C(TPR.TBR) -> C(PRn.BITNO)
6927           CPTUR (cptUsePRn + 6);
6928           cpu.PR[6].WORDNO = cpu.TPR.CA;
6929           SET_PR_BITNO (6, cpu.TPR.TBR);
6930 #if defined(TESTING)
6931           HDBGRegPRW (6, "eawp6");
6932 #endif
6933           break;
6934 
6935         case x1 (0333):  // eawp7
6936           // For n = 0, 1, ..., or 7 as determined by operation code
6937           //  C(TPR.CA) -> C(PRn.WORDNO)
6938           //  C(TPR.TBR) -> C(PRn.BITNO)
6939           CPTUR (cptUsePRn + 7);
6940           cpu.PR[7].WORDNO = cpu.TPR.CA;
6941           SET_PR_BITNO (7, cpu.TPR.TBR);
6942 #if defined(TESTING)
6943           HDBGRegPRW (7, "eawp7");
6944 #endif
6945           break;
6946 
6947 // Optimized to the top of the loop
6948 //        case x1 (0350):  // epbp0
6949 //        case x0 (0351):  // epbp1
6950 //        case x1 (0352):  // epbp2
6951 //        case x0 (0353):  // epbp3
6952 //        case x1 (0370):  // epbp4
6953 //        case x0 (0371):  // epbp5
6954 //        case x1 (0372):  // epbp6
6955 //        case x0 (0373):  // epbp7
6956 
6957 // Optimized to the top of the switch
6958 //        case x0 (0350):  // epp0
6959 //        case x1 (0351):  // epp1
6960 //        case x0 (0352):  // epp2
6961 //        case x1 (0353):  // epp3
6962 //        case x0 (0374):  // epp4
6963 //        case x1 (0371):  // epp5
6964 //        case x0 (0376):  // epp6
6965 //        case x1 (0373):  // epp7
6966 
6967         case x0 (0173):  // lpri
6968           // For n = 0, 1, ..., 7
6969           //  Y-pair = Y-block16 + 2n
6970           //  Maximum of C(Y-pair)18,20; C(SDW.R1); C(TPR.TRR) -> C(PRn.RNR)
6971           //  C(Y-pair) 3,17 -> C(PRn.SNR)
6972           //  C(Y-pair)36,53 -> C(PRn.WORDNO)
6973           //  C(Y-pair)57,62 -> C(PRn.BITNO)
6974 
6975           for (uint32 n = 0 ; n < 8 ; n ++)
6976             {
6977               CPTUR (cptUsePRn + n);
6978               // Even word of ITS pointer pair
6979               cpu.Ypair[0] = cpu.Yblock16[n * 2 + 0];
6980               // Odd word of ITS pointer pair
6981               cpu.Ypair[1] = cpu.Yblock16[n * 2 + 1];
6982 
6983               // RNR from ITS pair
6984               word3 Crr = (GETLO (cpu.Ypair[0]) >> 15) & 07;
6985               if (get_addr_mode (cpup) == APPEND_mode)
6986                 cpu.PR[n].RNR = max3 (Crr, cpu.SDW->R1, cpu.TPR.TRR);
6987               else
6988                 cpu.PR[n].RNR = Crr;
6989               cpu.PR[n].SNR    = (cpu.Ypair[0] >> 18) & MASK15;
6990               cpu.PR[n].WORDNO = GETHI (cpu.Ypair[1]);
6991               word6 bitno      = (GETLO (cpu.Ypair[1]) >> 9) & 077;
6992 // According to ISOLTS, loading a 077 into bitno results in 037
6993 // pa851    test-04b    lpri test       bar-100176
6994 // test start 105321   patch 105461   subtest loop point 105442
6995 // s/b 77777737
6996 // was 77777733
6997               if (bitno == 077)
6998                 bitno = 037;
6999               SET_PR_BITNO (n, bitno);
7000 #if defined(TESTING)
7001               HDBGRegPRW (n, "lpri");
7002 #endif
7003             }
7004 
7005           break;
7006 
7007 // Optimized to the top of the loop
7008 //                         // lprpn
7009 //        case x0 (0760):  // lprp0
7010 //        case x0 (0761):  // lprp1
7011 //        case x0 (0762):  // lprp2
7012 //        case x0 (0763):  // lprp3
7013 //        case x0 (0764):  // lprp4
7014 //        case x0 (0765):  // lprp5
7015 //        case x0 (0766):  // lprp6
7016 //        case x0 (0767):  // lprp7
7017 
7018         /// Pointer Register Data Movement Store
7019 
7020 // Optimized to the top of the loop
7021 //        case x1 (0250):  // spbp0
7022 //        case x0 (0251):  // spbp1
7023 //        case x1 (0252):  // spbp2
7024 //        case x0 (0253):  // spbp3
7025 //        case x1 (0650):  // spbp4
7026 //        case x0 (0651):  // spbp5
7027 //        case x1 (0652):  // spbp6
7028 //        case x0 (0653):  // spbp7
7029 
7030         case x0 (0254):  // spri
7031           // For n = 0, 1, ..., 7
7032           //  Y-pair = Y-block16 + 2n
7033 
7034           //  000 -> C(Y-pair)0,2
7035           //  C(PRn.SNR) -> C(Y-pair)3,17
7036           //  C(PRn.RNR) -> C(Y-pair)18,20
7037           //  00...0 -> C(Y-pair)21,29
7038           //  (43)8 -> C(Y-pair)30,35
7039 
7040           //  C(PRn.WORDNO) -> C(Y-pair)36,53
7041           //  000 -> C(Y-pair)54,56
7042           //  C(PRn.BITNO) -> C(Y-pair)57,62
7043           //  00...0 -> C(Y-pair)63,71
7044 
7045           for (uint32 n = 0 ; n < 8 ; n++)
7046             {
7047               CPTUR (cptUsePRn + n);
7048               cpu.Yblock16[2 * n]      = 043;
7049               cpu.Yblock16[2 * n]     |= ((word36) cpu.PR[n].SNR) << 18;
7050               cpu.Yblock16[2 * n]     |= ((word36) cpu.PR[n].RNR) << 15;
7051 
7052               cpu.Yblock16[2 * n + 1]  = (word36) cpu.PR[n].WORDNO << 18;
7053               cpu.Yblock16[2 * n + 1] |= (word36) GET_PR_BITNO(n) << 9;
7054             }
7055 
7056           break;
7057 
7058 // Optimized to the top of the loop
7059 //        case x0 (0250):  // spri0
7060 //        case x1 (0251):  // spri1
7061 //        case x0 (0252):  // spri2
7062 //        case x1 (0253):  // spri3
7063 //        case x0 (0650):  // spri4
7064 //        case x1 (0255):  // spri5
7065 //        case x0 (0652):  // spri6
7066 //        case x1 (0257):  // spri7
7067 
7068                          // sprpn
7069         case x0 (0540):  // sprp0
7070         case x0 (0541):  // sprp1
7071         case x0 (0542):  // sprp2
7072         case x0 (0543):  // sprp3
7073         case x0 (0544):  // sprp4
7074         case x0 (0545):  // sprp5
7075         case x0 (0546):  // sprp6
7076         case x0 (0547):  // sprp7
7077           // For n = 0, 1, ..., or 7 as determined by operation code
7078           //  C(PRn.BITNO) -> C(Y)0,5
7079           //  C(PRn.SNR)3,14 -> C(Y)6,17
7080           //  C(PRn.WORDNO) -> C(Y)18,35
7081           {
7082             uint32 n = opcode10 & 07;  // get n
7083             CPTUR (cptUsePRn + n);
7084 
7085             // If C(PRn.SNR)0,2 are nonzero, and C(PRn.SNR) != 11...1, then
7086             // a store fault (illegal pointer) will occur and C(Y) will not
7087             // be changed.
7088 
7089             if ((cpu.PR[n].SNR & 070000) != 0 && cpu.PR[n].SNR != MASK15)
7090               doFault (FAULT_STR, fst_str_ptr, "sprpn");
7091 
7092             cpu.CY  =  ((word36) (GET_PR_BITNO(n) & 077)) << 30;
7093             // lower 12- of 15-bits
7094             cpu.CY |=  ((word36) (cpu.PR[n].SNR & 07777)) << 18;
7095             cpu.CY |=  cpu.PR[n].WORDNO & PAMASK;
7096             cpu.CY &= DMASK;    // keep to 36-bits
7097           }
7098           break;
7099 
7100         /// Pointer Register Address Arithmetic
7101 
7102                           // adwpn
7103         case x0 (0050):   // adwp0
7104         case x0 (0051):   // adwp1
7105         case x0 (0052):   // adwp2
7106         case x0 (0053):   // adwp3
7107           // For n = 0, 1, ..., or 7 as determined by operation code
7108           //   C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7109           //   00...0 -> C(PRn.BITNO)
7110           {
7111               uint32 n = opcode10 & 03;  // get n
7112               CPTUR (cptUsePRn + n);
7113               cpu.PR[n].WORDNO += GETHI (cpu.CY);
7114               cpu.PR[n].WORDNO &= MASK18;
7115               SET_PR_BITNO (n, 0);
7116 #if defined(TESTING)
7117               HDBGRegPRW (n, "adwpn");
7118 #endif
7119           }
7120           break;
7121 
7122         case x0 (0150):   // adwp4
7123         case x0 (0151):   // adwp5
7124         case x0 (0152):   // adwp6
7125         case x0 (0153):   // adwp7
7126           // For n = 0, 1, ..., or 7 as determined by operation code
7127           //   C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7128           //   00...0 -> C(PRn.BITNO)
7129           {
7130               uint32 n = (opcode10 & MASK3) + 4U;  // get n
7131               CPTUR (cptUsePRn + n);
7132               cpu.PR[n].WORDNO += GETHI (cpu.CY);
7133               cpu.PR[n].WORDNO &= MASK18;
7134               SET_PR_BITNO (n, 0);
7135 #if defined(TESTING)
7136               HDBGRegPRW (n, "adwpn");
7137 #endif
7138           }
7139           break;
7140 
7141         /// Pointer Register Miscellaneous
7142 
7143 // Optimized to the top of the loop
7144 //        case x0 (0213):  // epaq
7145 
7146         /// MISCELLANEOUS INSTRUCTIONS
7147 
7148         case x0 (0633):  // rccl
7149           // 00...0 -> C(AQ)0,19
7150           // C(calendar clock) -> C(AQ)20,71
7151           {
7152             // For the rccl instruction, the first 2 or 3 bits of the addr
7153             // field of the instruction are used to specify which SCU.
7154             // init_processor.alm systematically steps through the SCUs,
7155             // using addresses 000000 100000 200000 300000.
7156             uint cpu_port_num;
7157             if (cpu.tweaks.l68_mode)
7158               cpu_port_num = (cpu.TPR.CA >> 15) & 07;
7159             else
7160               cpu_port_num = (cpu.TPR.CA >> 15) & 03;
7161             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
7162               {
7163                 sim_warn ("rccl on CPU %u port %d has no SCU; faulting\n",
7164                           current_running_cpu_idx, cpu_port_num);
7165                 doFault (FAULT_ONC, fst_onc_nem, "(rccl)");
7166               }
7167             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
7168 
7169             t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
7170                                   040, & cpu.rA, & cpu.rQ);
7171 #if defined(TESTING)
7172             HDBGRegAW ("rccl");
7173             HDBGRegQW ("rccl");
7174 #endif
7175             if (rc > 0)
7176               return rc;
7177 #if !defined(SPEED)
7178             if_sim_debug (DBG_TRACEEXT, & cpu_dev)
7179               {
7180                 // Clock at initialization
7181                 // date -d "Tue Jul 22 16:39:38 PDT 1999" +%s
7182                 // 932686778
7183                 uint64 UnixSecs     = 932686778;
7184                 uint64 UnixuSecs    = UnixSecs * 1000000LL;
7185                 // now determine uSecs since Jan 1, 1901 ...
7186                 uint64 MulticsuSecs = 2177452800000000LL + UnixuSecs;
7187 
7188                 // Back into 72 bits
7189                word72 big           = convert_to_word72 (cpu.rA, cpu.rQ);
7190 # if defined(NEED_128)
7191                 // Convert to time since boot
7192                 big             = subtract_128 (big, construct_128 (0, MulticsuSecs));
7193                 uint32_t remainder;
7194                 uint128 bigsecs = divide_128_32 (big, 1000000u, & remainder);
7195                 uint64_t uSecs  = remainder;
7196                 uint64_t secs   = bigsecs.l;
7197                 sim_debug (DBG_TRACEEXT, & cpu_dev,
7198                            "Clock time since boot %4llu.%06llu seconds\n",
7199                            secs, uSecs);
7200 # else
7201                 // Convert to time since boot
7202                 big                 -= MulticsuSecs;
7203                 unsigned long uSecs  = big % 1000000u;
7204                 unsigned long secs   = (unsigned long) (big / 1000000u);
7205                 sim_debug (DBG_TRACEEXT, & cpu_dev,
7206                            "Clock time since boot %4lu.%06lu seconds\n",
7207                            secs, uSecs);
7208 # endif
7209               }
7210 #endif
7211           }
7212           break;
7213 
7214         case x0 (0002):   // drl
7215           // Causes a fault which fetches and executes, in absolute mode, the
7216           // instruction pair at main memory location C+(14)8. The value of C
7217           // is obtained from the FAULT VECTOR switches on the processor
7218           // configuration panel.
7219 
7220           if (cpu.tweaks.drl_fatal)
7221             {
7222               return STOP_STOP;
7223             }
7224           doFault (FAULT_DRL, fst_zero, "drl");
7225 
7226         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7227         case x0 (0716):  // xec
7228           cpu.cu.xde = 1;
7229           cpu.cu.xdo = 0;
7230 // XXX NB. This used to be done in executeInstruction post-execution
7231 // processing; moving it here means that post-execution code cannot inspect IWB
7232 // to determine what the instruction or it flags were.
7233           cpu.cu.IWB = cpu.CY;
7234           return CONT_XEC;
7235 
7236         case x0 (0717):  // xed
7237           // The xed instruction itself does not affect any indicator.
7238           // However, the execution of the instruction pair from C(Y-pair)
7239           // may affect indicators.
7240           //
7241           // The even instruction from C(Y-pair) must not alter
7242           // C(Y-pair)36,71, and must not be another xed instruction.
7243           //
7244           // If the execution of the instruction pair from C(Y-pair) alters
7245           // C(PPR.IC), then a transfer of control occurs; otherwise, the
7246           // next instruction to be executed is fetched from C(PPR.IC)+1. If
7247           // the even instruction from C(Y-pair) alters C(PPR.IC), then the
7248           // transfer of control is effective immediately and the odd
7249           // instruction is not executed.
7250           //
7251           // To execute an instruction pair having an rpd instruction as the
7252           // odd instruction, the xed instruction must be located at an odd
7253           // address. The instruction pair repeated is that instruction pair
7254           // at C PPR.IC)+1, that is, the instruction pair immediately
7255           // following the xed instruction. C(PPR.IC) is adjusted during the
7256           // execution of the repeated instruction pair so the next
7257           // instruction fetched for execution is from the first word
7258           // following the repeated instruction pair.
7259           //
7260           // The instruction pair at C(Y-pair) may cause any of the processor
7261           // defined fault conditions, but only the directed faults (0,1,2,3)
7262           // and the access violation fault may be restarted successfully by
7263           // the hardware. Note that the software induced fault tag (1,2,3)
7264           // faults cannot be properly restarted.
7265           //
7266           //  An attempt to execute an EIS multiword instruction causes an
7267           //  illegal procedure fault.
7268           //
7269           //  Attempted repetition with the rpt, rpd, or rpl instructions
7270           //  causes an illegal procedure fault.
7271 
7272           cpu.cu.xde = 1;
7273           cpu.cu.xdo = 1;
7274 // XXX NB. This used to be done in executeInstruction post-execution
7275 // processing; moving it here means that post-execution code cannot inspect IWB
7276 // to determine what the instruction or it flags were.
7277           cpu.cu.IWB   = cpu.Ypair[0];
7278           cpu.cu.IRODD = cpu.Ypair[1];
7279           return CONT_XEC;
7280 
7281         case x0 (0001):   // mme
7282 #if defined(TESTING)
7283           if (sim_deb_mme_cntdwn > 0)
7284             sim_deb_mme_cntdwn --;
7285 #endif
7286           // Causes a fault that fetches and executes, in absolute mode, the
7287           // instruction pair at main memory location C+4. The value of C is
7288           // obtained from the FAULT VECTOR switches on the processor
7289           // configuration panel.
7290           doFault (FAULT_MME, fst_zero, "Master Mode Entry (mme)");
7291 
7292         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7293         case x0 (0004):   // mme2
7294           // Causes a fault that fetches and executes, in absolute mode, the
7295           // instruction pair at main memory location C+(52)8. The value of C
7296           // is obtained from the FAULT VECTOR switches on the processor
7297           // configuration panel.
7298           doFault (FAULT_MME2, fst_zero, "Master Mode Entry 2 (mme2)");
7299 
7300         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7301         case x0 (0005):   // mme3
7302           // Causes a fault that fetches and executes, in absolute mode, the
7303           // instruction pair at main memory location C+(54)8. The value of C
7304           // is obtained from the FAULT VECTOR switches on the processor
7305           // configuration panel.
7306           doFault (FAULT_MME3, fst_zero, "Master Mode Entry 3 (mme3)");
7307 
7308         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7309         case x0 (0007):   // mme4
7310           // Causes a fault that fetches and executes, in absolute mode, the
7311           // instruction pair at main memory location C+(56)8. The value of C
7312           // is obtained from the FAULT VECTOR switches on the processor
7313           // configuration panel.
7314           doFault (FAULT_MME4, fst_zero, "Master Mode Entry 4 (mme4)");
7315 
7316         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7317         case x0 (0011):   // nop
7318           break;
7319 
7320         case x0 (0012):   // puls1
7321           break;
7322 
7323         case x0 (0013):   // puls2
7324           break;
7325 
7326         /// Repeat
7327 
7328         case x0 (0560):  // rpd
7329           {
7330             if ((cpu.PPR.IC & 1) == 0)
7331               doFault (FAULT_IPR, fst_ill_proc, "rpd odd");
7332             cpu.cu.delta = i->tag;
7333             // a:AL39/rpd1
7334             word1 c = (i->address >> 7) & 1;
7335             if (c)
7336               {
7337                 cpu.rX[0] = i->address;    // Entire 18 bits
7338 #if defined(TESTING)
7339                 HDBGRegXW (0, "rpd");
7340 #endif
7341               }
7342             cpu.cu.rd = 1;
7343             cpu.cu.repeat_first = 1;
7344           }
7345           break;
7346 
7347         case x0 (0500):  // rpl
7348           {
7349             uint c       = (i->address >> 7) & 1;
7350             cpu.cu.delta = i->tag;
7351             if (c)
7352               {
7353                 cpu.rX[0] = i->address;    // Entire 18 bits
7354 #if defined(TESTING)
7355                 HDBGRegXW (0, "rpl");
7356 #endif
7357               }
7358             cpu.cu.rl           = 1;
7359             cpu.cu.repeat_first = 1;
7360           }
7361           break;
7362 
7363         case x0 (0520):  // rpt
7364           {
7365             uint c       = (i->address >> 7) & 1;
7366             cpu.cu.delta = i->tag;
7367             if (c)
7368               {
7369                 cpu.rX[0] = i->address;    // Entire 18 bits
7370 #if defined(TESTING)
7371                 HDBGRegXW (0, "rpt");
7372 #endif
7373               }
7374             cpu.cu.rpt          = 1;
7375             cpu.cu.repeat_first = 1;
7376           }
7377           break;
7378 
7379         /// Ring Alarm Register
7380 
7381         case x1 (0754):  // sra
7382             // 00...0 -> C(Y)0,32
7383             // C(RALR) -> C(Y)33,35
7384 
7385             CPTUR (cptUseRALR);
7386             cpu.CY = (word36)cpu.rRALR;
7387 
7388             break;
7389 
7390         /// Store Base Address Register
7391 
7392         case x0 (0550):  // sbar
7393           // C(BAR) -> C(Y) 0,17
7394           CPTUR (cptUseBAR);
7395           //SETHI (cpu.CY, (cpu.BAR.BASE << 9) | cpu.BAR.BOUND);
7396           cpu.CY      = ((((word36) cpu.BAR.BASE) << 9) | cpu.BAR.BOUND) << 18;
7397           cpu.zone    = 0777777000000;
7398           cpu.useZone = true;
7399           break;
7400 
7401         /// Translation
7402 
7403         case x0 (0505):  // bcd
7404           // Shift C(A) left three positions
7405           // | C(A) | / C(Y) -> 4-bit quotient
7406           // C(A) - C(Y) * quotient -> remainder
7407           // Shift C(Q) left six positions
7408           // 4-bit quotient -> C(Q)32,35
7409           // remainder -> C(A)
7410 
7411           {
7412             word36 tmp1   = cpu.rA & SIGN36; // A0
7413             word36 tmp36  = (cpu.rA << 3) & DMASK;
7414             word36 tmp36q = tmp36 / cpu.CY;  // this may be more than 4 bits, keep it for remainder calculation
7415             word36 tmp36r = 0;
7416             if (!tmp1) {
7417                 tmp36r = tmp36 - tmp36q * cpu.CY;
7418             } else {
7419                 // ISOLTS-745 05i: bcd when rA is negative.
7420                 // Note that this only gets called in the first round of the bcd
7421                 // conversion; the rA sign bit will get shifted out.
7422                 // Looking at the expected results, it appears that a 'borrow'
7423                 // is represented in a residue style notation -- an unborrow
7424                 // result is 0-9 (000 - 011), a borrowed digit as 6-15 (006-017)
7425                 tmp36q += 6;
7426                 tmp36r  = tmp36 + tmp36q * cpu.CY;
7427             }
7428 
7429             cpu.rQ <<= 6;       // Shift C(Q) left six positions
7430             cpu.rQ &= DMASK;
7431 
7432             //cpu.rQ &= (word36) ~017;     // 4-bit quotient -> C(Q)32,35  lo6 bits already zeroed out
7433             cpu.rQ |= (tmp36q & 017);
7434 #if defined(TESTING)
7435             HDBGRegQW ("bcd");
7436 #endif
7437 
7438             cpu.rA = tmp36r & DMASK;    // remainder -> C(A)
7439 #if defined(TESTING)
7440             HDBGRegAW ("bcd");
7441 #endif
7442 
7443             SC_I_ZERO (cpu.rA == 0);  // If C(A) = 0, then ON;
7444                                             // otherwise OFF
7445             SC_I_NEG (tmp1);   // If C(A)0 = 1 before execution,
7446                                             // then ON; otherwise OFF
7447           }
7448           break;
7449 
7450         case x0 (0774):  // gtb
7451           // C(A)0 -> C(A)0
7452           // C(A)i XOR C(A)i-1 -> C(A)i for i = 1, 2, ..., 35
7453           {
7454             word36 tmp = cpu.rA & MASK36;
7455             word36 mask = SIGN36;
7456 
7457             for (int n=1;n<=35;n++) {
7458                 tmp ^= (tmp & mask) >> 1;
7459                 mask >>= 1;
7460             }
7461 
7462             cpu.rA = tmp;
7463 #if defined(TESTING)
7464             HDBGRegAW ("gtb");
7465 #endif
7466 
7467             SC_I_ZERO (cpu.rA == 0);  // If C(A) = 0, then ON;
7468                                       // otherwise OFF
7469             SC_I_NEG (cpu.rA & SIGN36);   // If C(A)0 = 1, then ON;
7470                                           // otherwise OFF
7471           }
7472           break;
7473 
7474         /// REGISTER LOAD
7475 
7476         case x0 (0230):  // lbar
7477           // C(Y)0,17 -> C(BAR)
7478           CPTUR (cptUseBAR);
7479           // BAR.BASE is upper 9-bits (0-8)
7480           cpu.BAR.BASE  = (GETHI (cpu.CY) >> 9) & 0777;
7481           // BAR.BOUND is next lower 9-bits (9-17)
7482           cpu.BAR.BOUND = GETHI (cpu.CY) & 0777;
7483           break;
7484 
7485         /// PRIVILEGED INSTRUCTIONS
7486 
7487         /// Privileged - Register Load
7488 
7489         case x0 (0674):  // lcpr
7490           // DPS8M interpretation
7491           switch (i->tag)
7492             {
7493               // Extract bits from 'from' under 'mask' shifted to where (where
7494               // is dps8 '0 is the msbit.
7495 
7496               case 02: // cache mode register
7497                 {
7498                   //cpu.CMR = cpu.CY;
7499                   // cpu.CMR.cache_dir_address = <ignored for lcpr>
7500                   // cpu.CMR.par_bit = <ignored for lcpr>
7501                   // cpu.CMR.lev_ful = <ignored for lcpr>
7502 
7503                   CPTUR (cptUseCMR);
7504                   // a:AL39/cmr2  If either cache enable bit c or d changes
7505                   // from disable state to enable state, the entire cache is
7506                   // cleared.
7507                   uint csh1_on    = getbits36_1 (cpu.CY, 54 - 36);
7508                   uint csh2_on    = getbits36_1 (cpu.CY, 55 - 36);
7509                   //bool clear = (cpu.CMR.csh1_on == 0 && csh1_on != 0) ||
7510                                //(cpu.CMR.csh1_on == 0 && csh1_on != 0);
7511                   cpu.CMR.csh1_on = (word1) csh1_on;
7512                   cpu.CMR.csh2_on = (word1) csh2_on;
7513                   //if (clear) // a:AL39/cmr2
7514                     //{
7515                     //}
7516                   L68_ (cpu.CMR.opnd_on = getbits36_1 (cpu.CY, 56 - 36);)
7517                   cpu.CMR.inst_on = getbits36_1 (cpu.CY, 57 - 36);
7518                   cpu.CMR.csh_reg = getbits36_1 (cpu.CY, 59 - 36);
7519                   if (cpu.CMR.csh_reg)
7520                     sim_warn ("LCPR set csh_reg\n");
7521                   // cpu.CMR.str_asd = <ignored for lcpr>
7522                   // cpu.CMR.col_ful = <ignored for lcpr>
7523                   // cpu.CMR.rro_AB = getbits36_1 (cpu.CY, 18);
7524                   DPS8M_ (cpu.CMR.bypass_cache = getbits36_1 (cpu.CY, 68 - 36);)
7525                   cpu.CMR.luf = getbits36_2 (cpu.CY, 70 - 36);
7526                 }
7527                 break;
7528 
7529               case 04: // mode register
7530                 {
7531                   CPTUR (cptUseMR);
7532                   cpu.MR.r = cpu.CY;
7533 // XXX TEST/NORMAL switch is set to NORMAL
7534                   putbits36_1 (& cpu.MR.r, 32, 0);
7535 // SBZ
7536                   putbits36_2 (& cpu.MR.r, 33, 0);
7537                   L68_ (
7538                     cpu.MR.FFV = getbits36_15 (cpu.CY, 0);
7539                     cpu.MR.OC_TRAP = getbits36_1 (cpu.CY, 16);
7540                     cpu.MR.ADR_TRAP = getbits36_1 (cpu.CY, 17);
7541                     cpu.MR.OPCODE = getbits36_9 (cpu.CY, 18);
7542                     cpu.MR.OPCODEX = getbits36_1 (cpu.CY, 27);
7543                   )
7544                   cpu.MR.sdpap = getbits36_1 (cpu.CY, 20);
7545                   cpu.MR.separ = getbits36_1 (cpu.CY, 21);
7546                   cpu.MR.hrhlt = getbits36_1 (cpu.CY, 28);
7547                   DPS8M_ (cpu.MR.hrxfr = getbits36_1 (cpu.CY, 29);)
7548                   cpu.MR.ihr = getbits36_1 (cpu.CY, 30);
7549                   cpu.MR.ihrrs = getbits36_1 (cpu.CY, 31);
7550                   cpu.MR.emr = getbits36_1 (cpu.CY, 35);
7551                   if (! cpu.tweaks.l68_mode) // DPS8M
7552                     cpu.MR.hexfp = getbits36_1 (cpu.CY, 33);
7553                   else // L68
7554                     cpu.MR.hexfp = 0;
7555 
7556                   // Stop HR Strobe on HR Counter Overflow. (Setting bit 28
7557                   // shall cause the HR counter to be reset to zero.)
7558                   // CAC: It is unclear if bit 28 is edge or level
7559                   // triggered; assuming level for simplicity.
7560                   if (cpu.MR.hrhlt)
7561                     {
7562                       for (uint hset = 0; hset < N_HIST_SETS; hset ++)
7563                          cpu.history_cyclic[hset] = 0;
7564                     }
7565 
7566 
7567 
7568 
7569 
7570 
7571 
7572 
7573 
7574 
7575 
7576 
7577                 }
7578                 break;
7579 
7580               case 03: // 0's -> history
7581                 {
7582                   for (uint i = 0; i < N_HIST_SETS; i ++)
7583                     add_history_force (cpup, i, 0, 0);
7584 // XXX ISOLTS pm700 test-01n
7585 // The test clears the history registers but with ihr & emr set, causing
7586 // the registers to fill with alternating 0's and lcpr instructions.
7587 // Set flag to prevent the LCPR from being recorded.
7588                     //cpu.MR.ihr = 0;
7589                     cpu.skip_cu_hist = true;
7590 
7591                 }
7592                 break;
7593 
7594               case 07: // 1's -> history
7595                 {
7596                   for (uint i = 0; i < N_HIST_SETS; i ++)
7597                     add_history_force (cpup, i, MASK36, MASK36);
7598 // XXX ISOLTS pm700 test-01n
7599 // The test clears the history registers but with ihr & emr set, causing
7600 // the registers to fill with alternating 0's and lcpr instructions.
7601 // Set flag to prevent the LCPR from being recorded.
7602                     //cpu.MR.ihr = 0;
7603                     cpu.skip_cu_hist = true;
7604                 }
7605                 break;
7606 
7607               default:
7608                 doFault (FAULT_IPR,
7609                          fst_ill_mod,
7610                          "lcpr tag invalid");
7611 
7612             }
7613             break;
7614 
7615         case x0 (0232):  // ldbr
7616           do_ldbr (cpup, cpu.Ypair);
7617           ucInvalidate (cpup);
7618           break;
7619 
7620         case x0 (0637):  // ldt
7621           CPTUR (cptUseTR);
7622           cpu.rTR = (cpu.CY >> 9) & MASK27;
7623           cpu.rTRticks = 0;
7624           if (cpu.tweaks.isolts_mode)
7625             {
7626               cpu.shadowTR = cpu.TR0 = cpu.rTR;
7627               cpu.rTRlsb = 0;
7628             }
7629           sim_debug (DBG_TRACEEXT, & cpu_dev, "ldt TR %d (%o)\n",
7630                      cpu.rTR, cpu.rTR);
7631 #if defined(LOOPTRC)
7632 elapsedtime ();
7633  sim_printf (" ldt %d  PSR:IC %05o:%06o\r\n", cpu.rTR, cpu.PPR.PSR, cpu.PPR.IC);
7634 #endif
7635           // Undocumented feature. return to bce has been observed to
7636           // experience TRO while masked, setting the TR to -1, and
7637           // experiencing an unexpected TRo interrupt when unmasking.
7638           // Reset any pending TRO fault when the TR is loaded.
7639           clearTROFault (cpup);
7640           break;
7641 
7642         case x1 (0257):  // lptp
7643 
7644           if (cpu.tweaks.l68_mode) {
7645             // For i = 0, 1, ..., 15
7646             //   m = C(PTWAM(i).USE)
7647             //   C(Y-block16+m)0,14 -> C(PTWAM(m).POINTER)
7648             //   C(Y-block16+m)15,26 -> C(PTWAM(m).PAGE)
7649             //   C(Y-block16+m)27 -> C(PTWAM(m).F)
7650 
7651             for (uint i = 0; i < 16; i ++)
7652               {
7653                 word4 m              = cpu.PTWAM[i].USE;
7654                 cpu.PTWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i],  0);
7655                 cpu.PTWAM[m].PAGENO  = getbits36_12 (cpu.Yblock16[i], 15);
7656                 cpu.PTWAM[m].FE      = getbits36_1  (cpu.Yblock16[i], 27);
7657               }
7658           }
7659           break;
7660 
7661         case x1 (0173):  // lptr
7662           if (cpu.tweaks.l68_mode) {
7663             // For i = 0, 1, ..., 15
7664             //   m = C(PTWAM(i).USE)
7665             //   C(Y-block16+m)0,17 -> C(PTWAM(m).ADDR)
7666             //   C(Y-block16+m)29 -> C(PTWAM(m).M)
7667             for (uint i = 0; i < 16; i ++)
7668               {
7669                 word4 m           = cpu.PTWAM[i].USE;
7670                 cpu.PTWAM[m].ADDR = getbits36_18 (cpu.Yblock16[i],  0);
7671                 cpu.PTWAM[m].M    = getbits36_1  (cpu.Yblock16[i], 29);
7672               }
7673           }
7674           break;
7675 
7676         case x1 (0774):  // lra
7677             CPTUR (cptUseRALR);
7678             cpu.rRALR = cpu.CY & MASK3;
7679             sim_debug (DBG_TRACEEXT, & cpu_dev, "RALR set to %o\n", cpu.rRALR);
7680 #if defined(LOOPTRC)
7681 {
7682 void elapsedtime (void);
7683 elapsedtime ();
7684  sim_printf (" RALR set to %o  PSR:IC %05o:%06o\r\n", cpu.rRALR, cpu.PPR.PSR, cpu.PPR.IC);
7685 }
7686 #endif
7687             break;
7688 
7689         case x0 (0257):  // lsdp
7690           if (cpu.tweaks.l68_mode) {
7691             // For i = 0, 1, ..., 15
7692             //   m = C(SDWAM(i).USE)
7693             //   C(Y-block16+m)0,14 -> C(SDWAM(m).POINTER)
7694             //   C(Y-block16+m)27 -> C(SDWAM(m).F) Note: typo in AL39, P(17) should be F(27)
7695             for (uint i = 0; i < 16; i ++)
7696               {
7697                 word4 m              = cpu.SDWAM[i].USE;
7698                 cpu.SDWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i],  0);
7699                 cpu.SDWAM[m].FE      = getbits36_1  (cpu.Yblock16[i], 27);
7700               }
7701           }
7702           break;
7703 
7704         case x1 (0232):  // lsdr
7705           if (cpu.tweaks.l68_mode) {
7706             // For i = 0, 1, ..., 15
7707             //   m = C(SDWAM(i).USE)
7708             //   C(Y-block32+2m)0,23  -> C(SDWAM(m).ADDR)
7709             //   C(Y-block32+2m)24,32 -> C(SDWAM(m).R1, R2, R3)
7710             //   C(Y-block32+2m)37,50 -> C(SDWAM(m).BOUND)
7711             //   C(Y-block32+2m)51,57 -> C(SDWAM(m).R, E, W, P, U, G, C) Note: typo in AL39, 52 should be 51
7712             //   C(Y-block32+2m)58,71 -> C(SDWAM(m).CL)
7713             for (uint i = 0; i < 16; i ++)
7714               {
7715                 word4 m            = cpu.SDWAM[i].USE;
7716                 uint j             = (uint)m * 2;
7717                 cpu.SDWAM[m].ADDR  = getbits36_24 (cpu.Yblock32[j],  0);
7718                 cpu.SDWAM[m].R1    = getbits36_3  (cpu.Yblock32[j], 24);
7719                 cpu.SDWAM[m].R2    = getbits36_3  (cpu.Yblock32[j], 27);
7720                 cpu.SDWAM[m].R3    = getbits36_3  (cpu.Yblock32[j], 30);
7721 
7722                 cpu.SDWAM[m].BOUND = getbits36_14 (cpu.Yblock32[j + 1], 37 - 36);
7723                 cpu.SDWAM[m].R     = getbits36_1  (cpu.Yblock32[j + 1], 51 - 36);
7724                 cpu.SDWAM[m].E     = getbits36_1  (cpu.Yblock32[j + 1], 52 - 36);
7725                 cpu.SDWAM[m].W     = getbits36_1  (cpu.Yblock32[j + 1], 53 - 36);
7726                 cpu.SDWAM[m].P     = getbits36_1  (cpu.Yblock32[j + 1], 54 - 36);
7727                 cpu.SDWAM[m].U     = getbits36_1  (cpu.Yblock32[j + 1], 55 - 36);
7728                 cpu.SDWAM[m].G     = getbits36_1  (cpu.Yblock32[j + 1], 56 - 36);
7729                 cpu.SDWAM[m].C     = getbits36_1  (cpu.Yblock32[j + 1], 57 - 36);
7730                 cpu.SDWAM[m].EB    = getbits36_14 (cpu.Yblock32[j + 1], 58 - 36);
7731               }
7732           }
7733           break;
7734 
7735         case x0 (0613):  // rcu
7736           doRCU (cpup); // never returns!
7737 
7738         /// Privileged - Register Store
7739 
7740         /*FALLTHRU*/ /* fall through */ /* fallthrough */
7741         case x0 (0452):  // scpr
7742           {
7743             uint tag = (i->tag) & MASK6;
7744             switch (tag)
7745               {
7746                 case 000: // C(APU history register#1) -> C(Y-pair)
7747                   {
7748                     uint reg = cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG;
7749                     cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7750                     cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7751                     cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7752                   }
7753                   break;
7754 
7755                 case 001: // C(fault register) -> C(Y-pair)0,35
7756                           // 00...0 -> C(Y-pair)36,71
7757                   {
7758                     CPTUR (cptUseFR);
7759                     cpu.Ypair[0]         = cpu.faultRegister[0];
7760                     cpu.Ypair[1]         = cpu.faultRegister[1];
7761                     cpu.faultRegister[0] = 0;
7762                     cpu.faultRegister[1] = 0;
7763                   }
7764                   break;
7765 
7766                 case 006: // C(mode register) -> C(Y-pair)0,35
7767                           // C(cache mode register) -> C(Y-pair)36,72
7768                   {
7769                     CPTUR (cptUseMR);
7770                     cpu.Ypair[0] = cpu.MR.r;
7771                     putbits36_1 (& cpu.Ypair[0], 20, cpu.MR.sdpap);
7772                     putbits36_1 (& cpu.Ypair[0], 21, cpu.MR.separ);
7773                     putbits36_1 (& cpu.Ypair[0], 30, cpu.MR.ihr);
7774                     DPS8M_ (putbits36_1 (& cpu.Ypair[0], 33, cpu.MR.hexfp);)
7775                     CPTUR (cptUseCMR);
7776                     cpu.Ypair[1] = 0;
7777                     putbits36_15 (& cpu.Ypair[1], 36 - 36,
7778                                   cpu.CMR.cache_dir_address);
7779                     putbits36_1 (& cpu.Ypair[1], 51 - 36, cpu.CMR.par_bit);
7780                     putbits36_1 (& cpu.Ypair[1], 52 - 36, cpu.CMR.lev_ful);
7781                     putbits36_1 (& cpu.Ypair[1], 54 - 36, cpu.CMR.csh1_on);
7782                     putbits36_1 (& cpu.Ypair[1], 55 - 36, cpu.CMR.csh2_on);
7783                     L68_ (putbits36_1 (& cpu.Ypair[1], 56 - 36, cpu.CMR.opnd_on);)
7784                     putbits36_1 (& cpu.Ypair[1], 57 - 36, cpu.CMR.inst_on);
7785                     putbits36_1 (& cpu.Ypair[1], 59 - 36, cpu.CMR.csh_reg);
7786                     putbits36_1 (& cpu.Ypair[1], 60 - 36, cpu.CMR.str_asd);
7787                     putbits36_1 (& cpu.Ypair[1], 61 - 36, cpu.CMR.col_ful);
7788                     putbits36_2 (& cpu.Ypair[1], 62 - 36, cpu.CMR.rro_AB);
7789                     DPS8M_ (putbits36_1 (& cpu.Ypair[1], 68 - 36, cpu.CMR.bypass_cache);)
7790                     putbits36_2 (& cpu.Ypair[1], 70 - 36, cpu.CMR.luf);
7791                   }
7792                   break;
7793 
7794                 case 010: // C(APU history register#2) -> C(Y-pair)
7795                   {
7796                     uint reg = cpu.tweaks.l68_mode ? L68_DU_HIST_REG : DPS8M_EAPU_HIST_REG;
7797                     cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7798                     cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7799                     cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7800                   }
7801                   break;
7802 
7803                 case 020: // C(CU history register) -> C(Y-pair)
7804                   {
7805                     cpu.Ypair[0] =
7806                       cpu.history[CU_HIST_REG]
7807                                  [cpu.history_cyclic[CU_HIST_REG]][0];
7808                     cpu.Ypair[1] =
7809                       cpu.history[CU_HIST_REG]
7810                                  [cpu.history_cyclic[CU_HIST_REG]][1];
7811                     cpu.history_cyclic[CU_HIST_REG] =
7812                       (cpu.history_cyclic[CU_HIST_REG] + 1) % N_MODEL_HIST_SIZE;
7813                   }
7814                   break;
7815 
7816                 case 040: // C(OU/DU history register) -> C(Y-pair)
7817                   {
7818                     uint reg = cpu.tweaks.l68_mode ? L68_OU_HIST_REG : DPS8M_DU_OU_HIST_REG;
7819                     cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7820                     cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7821                     cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7822                   }
7823                   break;
7824 
7825                 default:
7826                   {
7827                     doFault (FAULT_IPR,
7828                              fst_ill_mod,
7829                              "SCPR Illegal register select value");
7830                   }
7831               }
7832           }
7833           break;
7834 
7835         case x0 (0657):  // scu
7836           // AL-39 defines the behavior of SCU during fault/interrupt
7837           // processing, but not otherwise.
7838           // The T&D tape uses SCU during normal processing, and apparently
7839           // expects the current CU state to be saved.
7840 
7841           if (cpu.cycle == EXEC_cycle)
7842             {
7843               // T&D behavior
7844 
7845               // An 'Add Delta' addressing mode will alter the TALLY bit;
7846               // restore it.
7847               //SC_I_TALLY (cpu.currentInstruction.stiTally == 0);
7848 
7849               scu2words (cpup, cpu.Yblock8);
7850             }
7851           else
7852             {
7853               // AL-39 behavior
7854               for (int j = 0; j < 8; j ++)
7855                 cpu.Yblock8[j] = cpu.scu_data[j];
7856             }
7857           break;
7858 
7859         case x0 (0154):  // sdbr
7860           {
7861             CPTUR (cptUseDSBR);
7862             // C(DSBR.ADDR) -> C(Y-pair) 0,23
7863             // 00...0 -> C(Y-pair) 24,36
7864             cpu.Ypair[0] = ((word36) (cpu.DSBR.ADDR & PAMASK)) << (35 - 23);
7865 
7866             // C(DSBR.BOUND) -> C(Y-pair) 37,50
7867             // 0000 -> C(Y-pair) 51,54
7868             // C(DSBR.U) -> C(Y-pair) 55
7869             // 000 -> C(Y-pair) 56,59
7870             // C(DSBR.STACK) -> C(Y-pair) 60,71
7871             cpu.Ypair[1] = ((word36) (cpu.DSBR.BND & 037777)) << (71 - 50) |
7872                            ((word36) (cpu.DSBR.U & 1)) << (71 - 55) |
7873                            ((word36) (cpu.DSBR.STACK & 07777)) << (71 - 71);
7874           }
7875           break;
7876 
7877         case x1 (0557):  // sptp
7878           {
7879 // XXX AL39 The associative memory is ignored (forced to "no match") during address
7880 // preparation.
7881             // Level j is selected by C(TPR.CA)12,13
7882             uint level;
7883             L68_ (level = 0;)
7884             DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7885             uint toffset = level * 16;
7886             for (uint j = 0; j < 16; j ++)
7887               {
7888                 cpu.Yblock16[j] = 0;
7889                 putbits36_15 (& cpu.Yblock16[j],  0,
7890                            cpu.PTWAM[toffset + j].POINTER);
7891                 DPS8M_ (
7892                   putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO & 07760);
7893 
7894                   uint parity = 0;
7895                   if (cpu.PTWAM[toffset + j].FE) {
7896                     // calculate parity
7897                     // 58009997-040 p.101,111
7898                     parity = ((uint) cpu.PTWAM[toffset + j].POINTER << 4) | (cpu.PTWAM[toffset + j].PAGENO >> 8);
7899                     parity = parity ^ (parity >>16);
7900                     parity = parity ^ (parity >> 8);
7901                     parity = parity ^ (parity >> 4);
7902                     parity = ~ (0x6996u >> (parity & 0xf));
7903                   }
7904                   putbits36_1 (& cpu.Yblock16[j], 23, (word1) (parity & 1));
7905                 )
7906                 L68_ (putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO); )
7907                 putbits36_1 (& cpu.Yblock16[j], 27,
7908                            cpu.PTWAM[toffset + j].FE);
7909                 DPS8M_ (putbits36_6 (& cpu.Yblock16[j], 30, cpu.PTWAM[toffset + j].USE);)
7910                 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.PTWAM[toffset + j].USE);)
7911               }
7912           }
7913           break;
7914 
7915         case x1 (0154):  // sptr
7916           {
7917 // XXX The associative memory is ignored (forced to "no match") during address
7918 // preparation.
7919 
7920             // Level j is selected by C(TPR.CA)12,13
7921             uint level;
7922             DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7923             L68_ (level = 0;)
7924             uint toffset = level * 16;
7925             for (uint j = 0; j < 16; j ++)
7926               {
7927                 cpu.Yblock16[j] = 0;
7928                 DPS8M_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR & 0777760);)
7929                 L68_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR);)
7930                 putbits36_1 (& cpu.Yblock16[j], 29,
7931                              cpu.PTWAM[toffset + j].M);
7932               }
7933           }
7934           break;
7935 
7936         case x0 (0557):  // ssdp
7937           {
7938             // XXX AL39: The associative memory is ignored (forced to "no match")
7939             // during address preparation.
7940             // Level j is selected by C(TPR.CA)12,13
7941             uint level;
7942             DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
7943             L68_ (level = 0;)
7944             uint toffset = level * 16;
7945             for (uint j = 0; j < 16; j ++)
7946               {
7947                 cpu.Yblock16[j] = 0;
7948                 putbits36_15 (& cpu.Yblock16[j], 0,
7949                            cpu.SDWAM[toffset + j].POINTER);
7950                 putbits36_1 (& cpu.Yblock16[j], 27,
7951                            cpu.SDWAM[toffset + j].FE);
7952                 DPS8M_ (
7953                   uint parity = 0;
7954                   if (cpu.SDWAM[toffset + j].FE) {
7955                     // calculate parity
7956                     // 58009997-040 p.112
7957                     parity = cpu.SDWAM[toffset + j].POINTER >> 4;
7958                     //parity = parity ^ (parity >>16);
7959                     parity = parity ^ (parity >> 8);
7960                     parity = parity ^ (parity >> 4);
7961                     parity = ~ (0x6996u >> (parity & 0xf));
7962                   }
7963                   putbits36_1 (& cpu.Yblock16[j], 15, (word1) (parity & 1));
7964 
7965                   putbits36_6 (& cpu.Yblock16[j], 30, cpu.SDWAM[toffset + j].USE);
7966                 )
7967                 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.SDWAM[toffset + j].USE);)
7968               }
7969           }
7970           break;
7971 
7972         case x1 (0254):  // ssdr
7973           {
7974 // XXX AL39: The associative memory is ignored (forced to "no match") during
7975 // address preparation.
7976 
7977             // Level j is selected by C(TPR.CA)11,12
7978             // Note: not bits 12,13. This is due to operand being Yblock32
7979             uint level = 0;
7980             DPS8M_ (level = (cpu.TPR.CA >> 5) & 03;)
7981             L68_ (level = 0;)
7982             uint toffset = level * 16;
7983             for (uint j = 0; j < 16; j ++)
7984               {
7985                 cpu.Yblock32[j * 2] = 0;
7986                 putbits36_24 (& cpu.Yblock32[j * 2],  0,
7987                            cpu.SDWAM[toffset + j].ADDR);
7988                 putbits36_3  (& cpu.Yblock32[j * 2], 24,
7989                            cpu.SDWAM[toffset + j].R1);
7990                 putbits36_3  (& cpu.Yblock32[j * 2], 27,
7991                            cpu.SDWAM[toffset + j].R2);
7992                 putbits36_3  (& cpu.Yblock32[j * 2], 30,
7993                            cpu.SDWAM[toffset + j].R3);
7994                 cpu.Yblock32[j * 2 + 1] = 0;
7995 
7996                 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 37 - 36,
7997                            cpu.SDWAM[toffset + j].BOUND);
7998                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 51 - 36,
7999                            cpu.SDWAM[toffset + j].R);
8000                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 52 - 36,
8001                            cpu.SDWAM[toffset + j].E);
8002                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 53 - 36,
8003                            cpu.SDWAM[toffset + j].W);
8004                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 54 - 36,
8005                            cpu.SDWAM[toffset + j].P);
8006                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 55 - 36,
8007                            cpu.SDWAM[toffset + j].U);
8008                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 56 - 36,
8009                            cpu.SDWAM[toffset + j].G);
8010                 putbits36_1  (& cpu.Yblock32[j * 2 + 1], 57 - 36,
8011                            cpu.SDWAM[toffset + j].C);
8012                 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 58 - 36,
8013                            cpu.SDWAM[toffset + j].EB);
8014               }
8015           }
8016           break;
8017 
8018         /// Privileged - Clear Associative Memory
8019 
8020         case x1 (0532):  // camp
8021           {
8022             // C(TPR.CA) 16,17 control disabling or enabling the associative
8023             // memory.
8024             // This may be done to either or both halves.
8025             // The full/empty bit of cache PTWAM register is set to zero and
8026             // the LRU counters are initialized.
8027             if (cpu.tweaks.enable_wam)
8028               { // disabled, do nothing
8029                 if (cpu.tweaks.l68_mode || cpu.cu.PT_ON) // only clear when enabled
8030                     for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8031                       {
8032                         cpu.PTWAM[i].FE = 0;
8033                         L68_ (cpu.PTWAM[i].USE = (word4) i;)
8034                         DPS8M_ (cpu.PTWAM[i].USE = 0;)
8035                       }
8036 
8037 // 58009997-040 A level of the associative memory is disabled if
8038 // C(TPR.CA) 16,17 = 01
8039 // 58009997-040 A level of the associative memory is enabled if
8040 // C(TPR.CA) 16,17 = 10
8041 // Level j is selected to be enabled/disable if
8042 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8043 // All levels are selected to be enabled/disabled if
8044 // C(TPR.CA) 11,14 = 0
8045 // This is contrary to what AL39 says, so I'm not going to implement it.
8046 // In fact, I'm not even going to implement the halves.
8047 
8048                 DPS8M_ (if (cpu.TPR.CA != 0000002 && (cpu.TPR.CA & 3) != 0)
8049                   sim_warn ("CAMP ignores enable/disable %06o\n", cpu.TPR.CA);)
8050                 if ((cpu.TPR.CA & 3) == 02)
8051                   cpu.cu.PT_ON = 1;
8052                 else if ((cpu.TPR.CA & 3) == 01)
8053                   cpu.cu.PT_ON = 0;
8054               }
8055             else
8056               {
8057                 cpu.PTW0.FE  = 0;
8058                 cpu.PTW0.USE = 0;
8059               }
8060           }
8061           ucInvalidate (cpup);
8062           break;
8063 
8064         case x0 (0532):  // cams
8065           {
8066             // The full/empty bit of each SDWAM register is set to zero and the
8067             // LRU counters are initialized. The remainder of the contents of
8068             // the registers are unchanged. If the associative memory is
8069             // disabled, F and LRU are unchanged.
8070             // C(TPR.CA) 16,17 control disabling or enabling the associative
8071             // memory.
8072             // This may be done to either or both halves.
8073             if (cpu.tweaks.enable_wam)
8074               {
8075                 if (cpu.tweaks.l68_mode || cpu.cu.SD_ON) // only clear when enabled
8076                     for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8077                       {
8078                         cpu.SDWAM[i].FE = 0;
8079                         L68_ (cpu.SDWAM[i].USE = (word4) i;)
8080                         DPS8M_ (cpu.SDWAM[i].USE = 0;)
8081                       }
8082 // 58009997-040 A level of the associative memory is disabled if
8083 // C(TPR.CA) 16,17 = 01
8084 // 58009997-040 A level of the associative memory is enabled if
8085 // C(TPR.CA) 16,17 = 10
8086 // Level j is selected to be enabled/disable if
8087 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8088 // All levels are selected to be enabled/disabled if
8089 // C(TPR.CA) 11,14 = 0
8090 // This is contrary to what AL39 says, so I'm not going to implement it. In
8091 // fact, I'm not even going to implement the halves.
8092 
8093                 DPS8M_ (if (cpu.TPR.CA != 0000006 && (cpu.TPR.CA & 3) != 0)
8094                   sim_warn ("CAMS ignores enable/disable %06o\n", cpu.TPR.CA);)
8095                 if ((cpu.TPR.CA & 3) == 02)
8096                   cpu.cu.SD_ON = 1;
8097                 else if ((cpu.TPR.CA & 3) == 01)
8098                   cpu.cu.SD_ON = 0;
8099               }
8100             else
8101               {
8102                 cpu.SDW0.FE  = 0;
8103                 cpu.SDW0.USE = 0;
8104               }
8105           }
8106           ucInvalidate (cpup);
8107           break;
8108 
8109         /// Privileged - Configuration and Status
8110 
8111         case x0 (0233):  // rmcm
8112           {
8113             // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8114             // specify which processor port (i.e., which system
8115             // controller) is used.
8116             uint cpu_port_num;
8117             DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8118             L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8119             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8120               {
8121                 sim_warn ("rmcm to non-existent controller on "
8122                           "cpu %d port %d\n",
8123                           current_running_cpu_idx, cpu_port_num);
8124                 break;
8125               }
8126             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8127             t_stat rc = scu_rmcm ((uint) scuUnitIdx,
8128                                   current_running_cpu_idx,
8129                                   & cpu.rA, & cpu.rQ);
8130 #if defined(TESTING)
8131             HDBGRegAW ("rmcm");
8132             HDBGRegQW ("rmcm");
8133 #endif
8134             if (rc)
8135               return rc;
8136             SC_I_ZERO (cpu.rA == 0);
8137             SC_I_NEG (cpu.rA & SIGN36);
8138           }
8139           break;
8140 
8141         case x0 (0413):  // rscr
8142           {
8143             // For the rscr instruction, the first 2 (DPS8M) or 3 (L68) bits of
8144             // the addr field of the instruction are used to specify which SCU.
8145             // (2 bits for the DPS8M. (Expect for x6x and x7x below, where
8146             // the selected SCU is the one holding the addressed memory).
8147 
8148             // According to DH02:
8149             //   XXXXXX0X  SCU Mode Register (Level 66 only)
8150             //   XXXXXX1X  Configuration switches
8151             //   XXXXXn2X  Interrupt mask port n
8152             //   XXXXXX3X  Interrupt cells
8153             //   XXXXXX4X  Elapsed time clock
8154             //   XXXXXX5X  Elapsed time clock
8155             //   XXXXXX6X  Mode register
8156             //   XXXXXX7X  Mode register
8157 
8158             // According to privileged_mode_ut,
8159             //   port*1024 + scr_input*8
8160 
8161             // privileged_mode_ut makes no reference to the special case
8162             // of x6x and x7x.
8163 
8164             // According to DH02, RSCR in Slave Mode does the CAF
8165             // without BAR correction, and then forces the CA to 040,
8166             // resulting in a Clock Read from the SCU on port 0.
8167 
8168             // According to AL93, RSCR in BAR mode is IPR.
8169 
8170 //
8171 // Implementing privileged_mode_ut.alm algorithm
8172 //
8173 
8174             // Extract port number
8175             uint cpu_port_num;
8176             DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 10) & 03;)
8177             L68_ (cpu_port_num = (cpu.TPR.CA >> 10) & 07;)
8178 
8179             // Trace the cable from the port to find the SCU number
8180             // connected to that port
8181             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8182               {
8183                 // CPTUR (cptUseFR) -- will be set by doFault
8184 
8185                 // Set IAn in Fault register
8186                 if (cpu_port_num == 0)
8187                   putbits36 (& cpu.faultRegister[0], 16, 4, 010);
8188                 else if (cpu_port_num == 1)
8189                   putbits36 (& cpu.faultRegister[0], 20, 4, 010);
8190                 else if (cpu_port_num == 2)
8191                   putbits36 (& cpu.faultRegister[0], 24, 4, 010);
8192                 else
8193                   putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8194 
8195                 doFault (FAULT_CMD, fst_cmd_ctl, "(rscr)");
8196               }
8197             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8198 #if defined(PANEL68)
8199             {
8200                uint function = (cpu.iefpFinalAddress >> 3) & 07;
8201                CPT (cpt13L, function);
8202             }
8203 #endif
8204             t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8205                                   cpu.iefpFinalAddress & MASK15,
8206                                   & cpu.rA, & cpu.rQ);
8207 #if defined(TESTING)
8208             HDBGRegAW ("rscr");
8209             HDBGRegQW ("rscr");
8210 #endif
8211             if (rc)
8212               return rc;
8213           }
8214           break;
8215 
8216         case x0 (0231):  // rsw
8217           {
8218             if (! cpu.tweaks.l68_mode) {
8219               word6 rTAG = GET_TAG (IWB_IRODD);
8220               word6 Td = GET_TD (rTAG);
8221               word6 Tm = GET_TM (rTAG);
8222               if (Tm == TM_R && Td == TD_DL)
8223                 {
8224                   unsigned char PROM[1024];
8225                   setupPROM (current_running_cpu_idx, PROM);
8226                   cpu.rA = PROM[cpu.TPR.CA & 1023];
8227                   break;
8228                 }
8229             }  // DPS8M
8230             uint select = cpu.TPR.CA & 0x7;
8231             switch (select)
8232               {
8233                 case 0: // data switches
8234                   cpu.rA = cpu.switches.data_switches;
8235                   break;
8236 
8237                 case 1: // configuration switches for ports A, B, C, D
8238 // y = 1:
8239 //
8240 //   0               0 0               1 1               2 2               3
8241 //   0               8 9               7 8               6 7               5
8242 //  -------------------------------------------------------------------------
8243 //  |      PORT A     |     PORT B      |     PORT C      |     PORT D      |
8244 //  -------------------------------------------------------------------------
8245 //  | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8246 //  -------------------------------------------------------------------------
8247 //
8248 //
8249 //   ADR: Address assignment switch setting for port
8250 //         This defines the base address for the SCU
8251 //   j: port enabled flag
8252 //   k: system initialize enabled flag
8253 //   l: interface enabled flag
8254 //   MEM coded memory size
8255 //     000 32K     2^15
8256 //     001 64K     2^16
8257 //     010 128K    2^17
8258 //     011 256K    2^18
8259 //     100 512K    2^19
8260 //     101 1024K   2^20
8261 //     110 2048K   2^21
8262 //     111 4096K   2^22
8263 
8264                   cpu.rA  = 0;
8265                   cpu.rA |= (word36) (cpu.switches.assignment  [0] & 07LL)
8266                             << (35 -  (2 +  0));
8267                   cpu.rA |= (word36) (cpu.switches.enable      [0] & 01LL)
8268                             << (35 -  (3 +  0));
8269                   cpu.rA |= (word36) (cpu.switches.init_enable [0] & 01LL)
8270                             << (35 -  (4 +  0));
8271                   cpu.rA |= (word36) (cpu.switches.interlace   [0] ? 1LL:0LL)
8272                             << (35 -  (5 +  0));
8273                   cpu.rA |= (word36) (cpu.switches.store_size  [0] & 07LL)
8274                             << (35 -  (8 +  0));
8275 
8276                   cpu.rA |= (word36) (cpu.switches.assignment  [1] & 07LL)
8277                             << (35 -  (2 +  9));
8278                   cpu.rA |= (word36) (cpu.switches.enable      [1] & 01LL)
8279                             << (35 -  (3 +  9));
8280                   cpu.rA |= (word36) (cpu.switches.init_enable [1] & 01LL)
8281                             << (35 -  (4 +  9));
8282                   cpu.rA |= (word36) (cpu.switches.interlace   [1] ? 1LL:0LL)
8283                             << (35 -  (5 +  9));
8284                   cpu.rA |= (word36) (cpu.switches.store_size  [1] & 07LL)
8285                             << (35 -  (8 +  9));
8286 
8287                   cpu.rA |= (word36) (cpu.switches.assignment  [2] & 07LL)
8288                             << (35 -  (2 + 18));
8289                   cpu.rA |= (word36) (cpu.switches.enable      [2] & 01LL)
8290                             << (35 -  (3 + 18));
8291                   cpu.rA |= (word36) (cpu.switches.init_enable [2] & 01LL)
8292                             << (35 -  (4 + 18));
8293                   cpu.rA |= (word36) (cpu.switches.interlace   [2] ? 1LL:0LL)
8294                             << (35 -  (5 + 18));
8295                   cpu.rA |= (word36) (cpu.switches.store_size  [2] & 07LL)
8296                             << (35 -  (8 + 18));
8297 
8298                   cpu.rA |= (word36) (cpu.switches.assignment  [3] & 07LL)
8299                             << (35 -  (2 + 27));
8300                   cpu.rA |= (word36) (cpu.switches.enable      [3] & 01LL)
8301                             << (35 -  (3 + 27));
8302                   cpu.rA |= (word36) (cpu.switches.init_enable [3] & 01LL)
8303                             << (35 -  (4 + 27));
8304                   cpu.rA |= (word36) (cpu.switches.interlace   [3] ? 1LL:0LL)
8305                             << (35 -  (5 + 27));
8306                   cpu.rA |= (word36) (cpu.switches.store_size  [3] & 07LL)
8307                             << (35 -  (8 + 27));
8308                   break;
8309 
8310                 case 2: // fault base and processor number  switches
8311 // y = 2:
8312 //
8313 //   0     0 0 0 0            1 1 1     1 1 1 2 2 2 2 2 2 2   2 2     3 3   3
8314 //   0     3 4 5 6            2 3 4     7 8 9 0 1 2 3 4 5 6   8 9     2 3   5
8315 //  --------------------------------------------------------------------------
8316 //  |A|B|C|D|   |              | |       | | | |   | | | |     |       |     |
8317 //  --------- b |   FLT BASE   |c|0 0 0 0|d|e|f|0 0|g|h|i|0 0 0| SPEED | CPU |
8318 //  |a|a|a|a|   |              | |       | | | |   | | | |     |       |     |
8319 //  --------------------------------------------------------------------------
8320 //
8321 
8322 //   a: port A-D is 0: 4 word or 1: 2 word
8323 //   b: processor type 0:L68 or DPS, 1: DPS8M, 2,3: reserved for future use
8324 //   c: id prom 0: not installed, 1: installed
8325 //   d: 1: bcd option installed (marketing designation)
8326 //   e: 1: dps option installed (marketing designation)
8327 //   f: 1: 8k cache installed
8328 //   g: processor type designation: 0: dps8/xx, 1: dps8m/xx
8329 //   h: gcos/vms switch position: 0:GCOS mode 1: virtual mode
8330 //   i: current or new product line peripheral type: 0:CPL, 1:NPL
8331 //   SPEED: 0000 = 8/70, 0100 = 8/52
8332 //   CPU: Processor number
8333 // DPS 8M processors:
8334 // C(Port interlace, Ports A-D) -> C(A) 0,3
8335 // 01 -> C(A) 4,5
8336 // C(Fault base switches) -> C(A) 6,12
8337 // 1 -> C(A) 13
8338 // 0000 -> C(A) 14,17
8339 // 111 -> C(A) 18,20
8340 // 00 -> C(A) 21,22
8341 // 1 -> C(A) 23
8342 // C(Processor mode sw) -> C(A) 24
8343 // 1 -> C(A) 25
8344 // 000 -> C(A) 26,28
8345 // C(Processor speed) -> C (A) 29,32
8346 
8347 // C(Processor number switches) -> C(A) 33,35
8348 
8349 // According to bound_gcos_.1.s.archive/gcos_fault_processor_.pl1 (L68/DPS):
8350 //
8351 // /* Set the A register to reflect switch info. */
8352 //                          mc.regs.a =
8353 //
8354 // /* (A-reg bits) */
8355 // /* (0-3) Port address expansion option:           */ (4)"0"b
8356 // /* (4-5) Reserved for future use:                 */ || (2)"0"b
8357 // /* (6-12) Processor fault base address switches:  */ || (7)"0"b
8358 // /* (13-16) L66 peripheral connectability:         */ || (4)"0"b
8359 // /* (17) Future use (must be zero):                */ || (1)"1"b
8360 // /* (18) BCD option installed:                     */ || (1)"1"b
8361 // /* (19) DPS type processor:                       */ || (1)"0"b
8362 // /* (20) 8K cache option installed:                */ || (1)"0"b
8363 // /* (21) Gear shift model processor:               */ || (1)"0"b
8364 // /* (22) Power patch option installed:             */ || (1)"0"b
8365 // /* (23) VMS-CU option installed - 66B' proc:      */ || (1)"0"b
8366 // /* (24) VMS-VU option installed - 66B proc:       */ || (1)"0"b
8367 // /* (25) Type processor (0) CPL, (1) DPSE-NPL:     */ || (1)"0"b
8368 // /* (26) 6025, 6605 or 6610 type processor:        */ || (1)"0"b
8369 // /* (27) 2K cache option installed:                */ || (1)"0"b
8370 // /* (28) Extended memory option installed:         */ || (1)"0"b
8371 // /* (29-30) cabinet (00) 8/70, (01) 8/52, (10) 862, (11) 846:          */ || (2)"0"b
8372 // /* (31) EIS option installed:                     */ || (1)"1"b
8373 // /* (32) (1) slow memory access, (0) fast memory:  */ || (1)"0"b
8374 // /* (33) (1) no instruction overlap, (0) overlap:  */ || (1)"0"b
8375 // /* (34-35) Processor number:                      */ ||unspec (mc.cpu_type);
8376 
8377                   cpu.rA = 0;
8378                   DPS8M_ (
8379                     cpu.rA |= (word36) ((cpu.switches.interlace[0] == 2 ?
8380                             1LL : 0LL) << (35- 0));
8381                     cpu.rA |= (word36) ((cpu.switches.interlace[1] == 2 ?
8382                             1LL : 0LL) << (35- 1));
8383                     cpu.rA |= (word36) ((cpu.switches.interlace[2] == 2 ?
8384                             1LL : 0LL) << (35- 2));
8385                     cpu.rA |= (word36) ((cpu.switches.interlace[3] == 2 ?
8386                             1LL : 0LL) << (35- 3));
8387                   )
8388 
8389                   if (cpu.tweaks.l68_mode)
8390                     // NO-OP
8391                     // cpu.rA |= (word36) ((00L)  /* 0b00 L68/DPS */
8392                     //          << (35- 5));
8393                     ;
8394                   else
8395                     cpu.rA |= (word36) ((01L)  /* 0b01 DPS8M */
8396                              << (35- 5));
8397                   cpu.rA |= (word36) ((cpu.switches.FLT_BASE & 0177LL)
8398                              << (35-12));
8399                   DPS8M_ (cpu.rA |= (word36) ((01L) /* 0b1 ID_PROM installed */
8400                              << (35-13));)
8401                   // NO-OP
8402                   // cpu.rA |= (word36) ((00L) // 0b0000
8403                   //           << (35-17));
8404                   //cpu.rA |= (word36) ((0b111L)
8405                               //<< (35-20));
8406                   // According to rsw.incl.pl1, Multics ignores this bit.
8407                   // NO-OP
8408                   // cpu.rA |= (word36) ((00L)  // 0b0 BCD option off
8409                   //           << (35-18));
8410                   if (cpu.tweaks.l68_mode)
8411                     // NO-OP
8412                     // cpu.rA |= (word36) ((00L)  // 0b0 L68/DPS option: L68
8413                     //        << (35-19));
8414                     ;
8415                   else
8416                     cpu.rA |= (word36) ((01L)  // 0b1 L68/DPS option: DPS
8417                             << (35-19));
8418                   DPS8M_ (
8419                                              // 8K cache
8420                                              // 0b0: not installed
8421                                              // 0b1: installed
8422                     cpu.rA |= (word36) ((cpu.switches.enable_cache ? 1 : 0)
8423                             << (35-20));
8424                     // NO-OP
8425                     // cpu.rA |= (word36) ((00L) // 0b00
8426                     //         << (35-22));
8427                     cpu.rA |= (word36) ((cpu.switches.procMode)  /* 0b1 DPS8M */
8428                             << (35-23));
8429                     cpu.rA |= (word36) ((cpu.switches.procMode & 1U)
8430                             << (35-24));
8431                     // NO-OP
8432                     // cpu.rA |= (word36) ((00L) // 0b0 new product line (CPL/NPL)
8433                     //         << (35-25));
8434                     // NO-OP
8435                     // cpu.rA |= (word36) ((00L) // 0b000
8436                     //         << (35-28));
8437                     cpu.rA |= (word36) ((cpu.options.proc_speed & 017LL)
8438                             << (35-32));
8439                   )
8440 
8441                   L68_ (
8442                     // NO-OP
8443                     // cpu.rA |= (word36) ((00L) // 0b0 2K cache disabled
8444                     //         << (35-27));
8445                     // NO-OP
8446                     // cpu.rA |= (word36) ((00L) // 0b0 GCOS mode extended memory disabled
8447                     //         << (35-28));
8448                     cpu.rA |= (word36) ((016L) // 0b1110 CPU ID
8449                             << (35-32));
8450                   )
8451                   cpu.rA |= (word36) ((cpu.switches.cpu_num & 07LL)
8452                             << (35-35));
8453                   break;
8454 
8455                 case 3: // configuration switches for ports E, F, G, H
8456                   if (!cpu.tweaks.l68_mode) { // DPS8M
8457                     cpu.rA = 0;
8458                     break;
8459                   }
8460                   // L68
8461 // y = 3:
8462 //
8463 //   0               0 0               1 1               2 2               3
8464 //   0               8 9               7 8               6 7               5
8465 //  -------------------------------------------------------------------------
8466 //  |      PORT E     |     PORT F      |     PORT G      |     PORT H      |
8467 //  -------------------------------------------------------------------------
8468 //  | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8469 //  -------------------------------------------------------------------------
8470 //
8471 //
8472 //   ADR: Address assignment switch setting for port
8473 //         This defines the base address for the SCU
8474 //   j: port enabled flag
8475 //   k: system initialize enabled flag
8476 //   l: interface enabled flag
8477 //   MEM coded memory size
8478 //     000 32K     2^15
8479 //     001 64K     2^16
8480 //     010 128K    2^17
8481 //     011 256K    2^18
8482 //     100 512K    2^19
8483 //     101 1024K   2^20
8484 //     110 2048K   2^21
8485 //     111 4096K   2^22
8486 
8487                   cpu.rA  = 0;
8488                   cpu.rA |= (word36) (cpu.switches.assignment  [4] & 07LL)
8489                             << (35 -  (2 +  0));
8490                   cpu.rA |= (word36) (cpu.switches.enable      [4] & 01LL)
8491                             << (35 -  (3 +  0));
8492                   cpu.rA |= (word36) (cpu.switches.init_enable [4] & 01LL)
8493                             << (35 -  (4 +  0));
8494                   cpu.rA |= (word36) (cpu.switches.interlace   [4] ? 1LL:0LL)
8495                             << (35 -  (5 +  0));
8496                   cpu.rA |= (word36) (cpu.switches.store_size  [4] & 07LL)
8497                             << (35 -  (8 +  0));
8498 
8499                   cpu.rA |= (word36) (cpu.switches.assignment  [5] & 07LL)
8500                             << (35 -  (2 +  9));
8501                   cpu.rA |= (word36) (cpu.switches.enable      [5] & 01LL)
8502                             << (35 -  (3 +  9));
8503                   cpu.rA |= (word36) (cpu.switches.init_enable [5] & 01LL)
8504                             << (35 -  (4 +  9));
8505                   cpu.rA |= (word36) (cpu.switches.interlace   [5] ? 1LL:0LL)
8506                             << (35 -  (5 +  9));
8507                   cpu.rA |= (word36) (cpu.switches.store_size  [5] & 07LL)
8508                             << (35 -  (8 +  9));
8509 
8510                   cpu.rA |= (word36) (cpu.switches.assignment  [6] & 07LL)
8511                             << (35 -  (2 + 18));
8512                   cpu.rA |= (word36) (cpu.switches.enable      [6] & 01LL)
8513                             << (35 -  (3 + 18));
8514                   cpu.rA |= (word36) (cpu.switches.init_enable [6] & 01LL)
8515                             << (35 -  (4 + 18));
8516                   cpu.rA |= (word36) (cpu.switches.interlace   [6] ? 1LL:0LL)
8517                             << (35 -  (5 + 18));
8518                   cpu.rA |= (word36) (cpu.switches.store_size  [6] & 07LL)
8519                             << (35 -  (8 + 18));
8520 
8521                   cpu.rA |= (word36) (cpu.switches.assignment  [7] & 07LL)
8522                             << (35 -  (2 + 27));
8523                   cpu.rA |= (word36) (cpu.switches.enable      [7] & 01LL)
8524                             << (35 -  (3 + 27));
8525                   cpu.rA |= (word36) (cpu.switches.init_enable [7] & 01LL)
8526                             << (35 -  (4 + 27));
8527                   cpu.rA |= (word36) (cpu.switches.interlace   [7] ? 1LL:0LL)
8528                             << (35 -  (5 + 27));
8529                   cpu.rA |= (word36) (cpu.switches.store_size  [7] & 07LL)
8530                             << (35 -  (8 + 27));
8531                   break;
8532 
8533                 case 4:
8534                   // I suspect the this is a L68 only, but AL39 says both
8535                   // port interlace and half/full size
8536                   // The DPS doesn't seem to have the half/full size switches
8537                   // so we'll always report full, and the interlace bits were
8538                   // squeezed into RSW 2
8539 
8540 //  0                       1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2           3
8541 //  0                       2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9           5
8542 // -------------------------------------------------------------------------
8543 // |                         | A | B | C | D | E | F | G | H |             |
8544 // |0 0 0 0 0 0 0 0 0 0 0 0 0---------------------------------0 0 0 0 0 0 0|
8545 // |                         |f|g|f|g|f|g|f|g|f|g|f|g|f|g|f|g|             |
8546 // -------------------------------------------------------------------------
8547 //                         13 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1             7
8548 
8549                   cpu.rA  = 0;
8550                   cpu.rA |= (word36) (cpu.switches.interlace [0] == 2 ?
8551                             1LL : 0LL) << (35-13);
8552                   cpu.rA |= (word36) (cpu.switches.interlace [1] == 2 ?
8553                             1LL : 0LL) << (35-15);
8554                   cpu.rA |= (word36) (cpu.switches.interlace [2] == 2 ?
8555                             1LL : 0LL) << (35-17);
8556                   cpu.rA |= (word36) (cpu.switches.interlace [3] == 2 ?
8557                             1LL : 0LL) << (35-19);
8558                   L68_ (
8559                     cpu.rA |= (word36) (cpu.switches.interlace [4] == 2 ?
8560                             1LL : 0LL) << (35-21);
8561                     cpu.rA |= (word36) (cpu.switches.interlace [5] == 2 ?
8562                             1LL : 0LL) << (35-23);
8563                     cpu.rA |= (word36) (cpu.switches.interlace [6] == 2 ?
8564                             1LL : 0LL) << (35-25);
8565                     cpu.rA |= (word36) (cpu.switches.interlace [7] == 2 ?
8566                             1LL : 0LL) << (35-27);
8567                   )
8568                   break;
8569 
8570                 default:
8571                   // XXX Guessing values; also we don't know if this is actually a fault
8572                   doFault (FAULT_IPR,
8573                            fst_ill_mod,
8574                            "Illegal register select value");
8575               }
8576 #if defined(TESTING)
8577             HDBGRegAW ("rsw");
8578 #endif
8579             SC_I_ZERO (cpu.rA == 0);
8580             SC_I_NEG (cpu.rA & SIGN36);
8581           }
8582           break;
8583 
8584         /// Privileged - System Control
8585 
8586         case x0 (0015):  // cioc
8587           {
8588 
8589 #if defined(THREADZ) || defined(LOCKLESS)
8590 
8591 
8592 
8593 
8594 
8595 
8596 
8597 
8598 
8599 
8600 
8601 #endif
8602 
8603             // cioc The system controller addressed by Y (i.e., contains
8604             // the word at Y) sends a connect signal to the port specified
8605             // by C(Y) 33,35.
8606             int cpu_port_num = lookup_cpu_mem_map (cpup, cpu.iefpFinalAddress);
8607             // If there is no port to that memory location, fault
8608             if (cpu_port_num < 0)
8609               {
8610                 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8611               }
8612             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8613               {
8614                 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8615               }
8616             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8617 
8618 // expander word
8619 // dcl  1 scs$reconfig_general_cow aligned external, /* Used during reconfig
8620 //                                                      ops. */
8621 //   2 pad bit (36) aligned,
8622 //   2 cow,                        /* Connect operand word, in odd location. */
8623 //   3 sub_mask bit (8) unaligned, /* Expander sub-port mask */
8624 //   3 mbz1 bit (13) unaligned,
8625 //   3 expander_command bit (3) unaligned,   /* Expander command. */
8626 //   3 mbz2 bit (9) unaligned,
8627 //   3 controller_port fixed bin (3) unaligned unsigned;/* controller port for
8628 //                                                          this CPU */
8629 
8630             word8 sub_mask = getbits36_8 (cpu.CY, 0);
8631             word3 expander_command = getbits36_3 (cpu.CY, 21);
8632             uint scu_port_num = (uint) getbits36_3 (cpu.CY, 33);
8633             scu_cioc (current_running_cpu_idx, (uint) scuUnitIdx, scu_port_num,
8634                       expander_command, sub_mask);
8635           }
8636           break;
8637 
8638         case x0 (0553):  // smcm
8639           {
8640             // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8641             // specify which processor port (i.e., which system
8642             // controller) is used.
8643             uint cpu_port_num;
8644             DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8645             L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8646             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8647               {
8648                 sim_warn ("smcm to non-existent controller on "
8649                           "cpu %d port %d\n",
8650                           current_running_cpu_idx, cpu_port_num);
8651                 break;
8652               }
8653             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8654             t_stat rc = scu_smcm ((uint) scuUnitIdx,
8655                                   current_running_cpu_idx, cpu.rA, cpu.rQ);
8656             if (rc)
8657               return rc;
8658           }
8659           break;
8660 
8661         case x0 (0451):  // smic
8662           {
8663             // For the smic instruction, the first 2 or 3 bits of the addr
8664             // field of the instruction are used to specify which SCU.
8665             // 2 bits for the DPS8M.
8666             //int scuUnitIdx = getbits36_2 (TPR.CA, 0);
8667 
8668             // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8669             // specify which processor port (i.e., which system
8670             // controller) is used.
8671             uint cpu_port_num;
8672             DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8673             L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8674             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8675               {
8676                 DPS8M_ (return SCPE_OK;)
8677                 // L68
8678                 // CPTUR (cptUseFR) -- will be set by doFault
8679                 if (cpu_port_num == 0)
8680                   putbits36_4 (& cpu.faultRegister[0], 16, 010);
8681                 else if (cpu_port_num == 1)
8682                   putbits36_4 (& cpu.faultRegister[0], 20, 010);
8683                 else if (cpu_port_num == 2)
8684                   putbits36_4 (& cpu.faultRegister[0], 24, 010);
8685                 else if (cpu_port_num == 3)
8686                   putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8687 // XXX What if the port is > 3?
8688                 doFault (FAULT_CMD, fst_cmd_ctl, "(smic)");
8689               }
8690             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8691             t_stat rc = scu_smic (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8692                                   cpu_port_num, cpu.rA);
8693             if (rc)
8694               return rc;
8695           }
8696           break;
8697 
8698         case x0 (0057):  // sscr
8699           {
8700             //uint cpu_port_num = (cpu.TPR.CA >> 15) & 03;
8701             // Looking at privileged_mode_ut.alm, shift 10 bits...
8702             uint cpu_port_num;
8703             DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 10) & 03;)
8704             L68_ (cpu_port_num = (cpu.TPR.CA >> 10) & 07;)
8705             if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8706               {
8707                 // CPTUR (cptUseFR) -- will be set by doFault
8708                 if (cpu_port_num == 0)
8709                   putbits36_4 (& cpu.faultRegister[0], 16, 010);
8710                 else if (cpu_port_num == 1)
8711                   putbits36_4 (& cpu.faultRegister[0], 20, 010);
8712                 else if (cpu_port_num == 2)
8713                   putbits36_4 (& cpu.faultRegister[0], 24, 010);
8714                 else
8715                   putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8716                 doFault (FAULT_CMD, fst_cmd_ctl, "(sscr)");
8717               }
8718             uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8719             t_stat rc = scu_sscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8720                                   cpu_port_num, cpu.iefpFinalAddress & MASK15,
8721                                   cpu.rA, cpu.rQ);
8722 
8723             if (rc)
8724               return rc;
8725           }
8726           break;
8727 
8728         // Privileged - Miscellaneous
8729 
8730         case x0 (0212):  // absa
8731           {
8732             word36 result;
8733             int rc = doABSA (cpup, & result);
8734             if (rc)
8735               return rc;
8736             cpu.rA = result;
8737 #if defined(TESTING)
8738             HDBGRegAW ("absa");
8739 #endif
8740             SC_I_ZERO (cpu.rA == 0);
8741             SC_I_NEG (cpu.rA & SIGN36);
8742           }
8743           break;
8744 
8745         case x0 (0616):  // dis
8746 
8747 #ifdef SYNCTEST
8748           // Trap the call to sys$trouble
8749           if (cpu.PPR.PSR == 034 && cpu.PPR.IC == 03535) {
8750 # ifdef HDBG
8751             hdbgPrint ();
8752 # endif
8753             sim_printf ("sys$trouble\r\n");
8754             exit (1);
8755           }
8756 #endif
8757 
8758 #if defined(THREADZ) || defined(LOCKLESS)
8759           if (cpu.forceRestart) {
8760             cpu.forceRestart = 0;
8761             longjmp (cpu.jmpMain, JMP_FORCE_RESTART);
8762           }
8763 #endif
8764 
8765           if (! cpu.tweaks.dis_enable)
8766             {
8767               return STOP_STOP;
8768             }
8769 
8770           // XXX This is subtle; g7Pending below won't see the queued
8771           // g7Fault. I don't understand how the real hardware dealt
8772           // with this, but this seems to work. (I would hazard a guess
8773           // that DIS was doing a continuous FETCH/EXECUTE cycle
8774           // ('if !interrupt goto .'))
8775           advanceG7Faults (cpup);
8776 
8777           if ((! cpu.tweaks.tro_enable) &&
8778               (! sample_interrupts (cpup)) &&
8779               (sim_qcount () == 0))  // XXX If clk_svc is implemented it will
8780                                      // break this logic
8781             {
8782               sim_printf ("DIS@0%06o with no interrupts pending and"
8783                           " no events in queue\n", cpu.PPR.IC);
8784 #if defined(WIN_STDIO)
8785               sim_printf ("\nCycles = %llu\n",
8786 #else
8787               sim_printf ("\nCycles = %'llu\n",
8788 #endif /* if defined(WIN_STDIO) */
8789                           (unsigned long long)cpu.cycleCnt);
8790 #if defined(WIN_STDIO)
8791               sim_printf ("\nInstructions = %llu\n",
8792 #else
8793               sim_printf ("\nInstructions = %'llu\n",
8794 #endif /* if defined(WIN_STDIO) */
8795                           (unsigned long long)cpu.cycleCnt);
8796               longjmp (cpu.jmpMain, JMP_STOP);
8797             }
8798 
8799 // Multics/BCE halt
8800           if (cpu.PPR.PSR == 0430 && cpu.PPR.IC == 012)
8801               {
8802                 sim_printf ("BCE DIS causes CPU halt\n");
8803                 sim_debug (DBG_MSG, & cpu_dev, "BCE DIS causes CPU halt\n");
8804 #if defined(LOCKLESS)
8805                 bce_dis_called = true;
8806 #endif // LOCKLESS
8807                 longjmp (cpu.jmpMain, JMP_STOP);
8808               }
8809 
8810 #if defined(THREADZ) || defined(LOCKLESS)
8811 // RCF halt
8812           // XXX pxss uses a distinctive DIS operation
8813           // for RCF DELETE. If we see it, remember that
8814           // we did.
8815           if (IWB_IRODD == 0000777616207) {
8816             //HDBGNote (cpup, "DIS", "DIS clears inMultics%s", "");
8817             cpu.inMultics = false;
8818           }
8819 
8820 // ISOLTS start:
8821 //     CPU B thread created.
8822 //     DBG(1)> CPU 1 TRACE:  000000 0 000000616000 (DIS 000000)
8823 //     DBG(3)> CPU 1 INTR:  Interrupt pair address 0
8824 //     DBG(3)> CPU 1 FINAL: intr even read  00000000 000000755200
8825 //     DBG(3)> CPU 1 FINAL: intr odd read  00000001 000000616200
8826 //     DBG(4)> CPU 1 TRACE:  000001 0 000000755200 (STA 000000)
8827 //     DBG(4)> CPU 1 REG: sta read   A   000000000000
8828 //     DBG(4)> CPU 1 IEFP ABS     WRITE: :000000
8829 //     DBG(4)> CPU 1 FINAL: WriteOperandStore AB write 00000000 000000000000
8830 //     DBG(5)> CPU 1 TRACE:  000001 0 000000616200 (DIS 000000)
8831 // There are different behaviors for various configuration errors.
8832 //   If ISOLTS mode is not set, we see an IWB_IRODD of 0000000616200
8833 //   If set, 0000001616200
8834 
8835           // If we do a DIS while sync clock master, and are inMultics,
8836           // cancel sync clock... But not the processor startup DIS
8837 
8838           if (UNLIKELY (cpu.syncClockModeMaster) &&
8839               cpu.inMultics &&
8840               (cpu.PPR.PSR !=0 || cpu.PPR.IC != 0)) {
8841 # ifdef SYNCTEST
8842             sim_printf ("CPU%c DIS %o:%o gives up master\n", cpu.cpuIdx + 'A', cpu.PPR.PSR, cpu.PPR.IC);
8843 # endif
8844             //HDBGNote (cpup, "DIS", "DIS give up clock master%s", "");
8845             giveupClockMaster (cpup);
8846           }
8847 #endif
8848 
8849 
8850 
8851 
8852 
8853 
8854 
8855 
8856 
8857 
8858 
8859 
8860 
8861 
8862 
8863 
8864 
8865 
8866 
8867 
8868 #if defined(ROUND_ROBIN)
8869           if (cpu.PPR.PSR == 034 && cpu.PPR.IC == 03535)
8870               {
8871                 sim_printf ("[%lld] sys_trouble$die DIS causes CPU halt\n", cpu.cycleCnt);
8872                 sim_debug (DBG_MSG, & cpu_dev, "sys_trouble$die DIS causes CPU halt\n");
8873                 //longjmp (cpu.jmpMain, JMP_STOP);
8874                 cpu.isRunning = false;
8875               }
8876 #endif
8877           sim_debug (DBG_TRACEEXT, & cpu_dev, "entered DIS_cycle\n");
8878 
8879           // No operation takes place, and the processor does not
8880           // continue with the next instruction; it waits for a
8881           // external interrupt signal.
8882           // AND, according to pxss.alm, TRO
8883 
8884 // Bless NovaScale...
8885 //  DIS
8886 //
8887 //    NOTES:
8888 //
8889 //      1. The inhibit bit in this instruction only affects the recognition
8890 //         of a Timer Runout (TROF) fault.
8891 //
8892 //         Inhibit ON delays the recognition of a TROF until the processor
8893 //         enters Slave mode.
8894 //
8895 //         Inhibit OFF allows the TROF to interrupt the DIS state.
8896 //
8897 //      2. For all other faults and interrupts, the inhibit bit is ignored.
8898 //
8899 //      3. The use of this instruction in the Slave or Master mode causes a
8900 //         Command fault.
8901 
8902           if (sample_interrupts (cpup))
8903             {
8904               sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees an interrupt\n");
8905               cpu.interrupt_flag = true;
8906               break;
8907             }
8908 // Implementing TRO according to AL39 for the DIS cause the idle systems to
8909 // hang in the DIS instruction. Revert back to the old behavior.
8910 
8911           if (GET_I (cpu.cu.IWB) ? bG7PendingNoTRO (cpup) : bG7Pending (cpup))
8912 
8913 
8914 
8915 
8916 
8917 
8918 
8919 
8920             {
8921               sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees a TRO\n");
8922               cpu.g7_flag = true;
8923               break;
8924             }
8925           else
8926             {
8927               sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS refetches\n");
8928 #if defined(ROUND_ROBIN)
8929               if (cpu.tweaks.isolts_mode)
8930                 {
8931                   //sim_printf ("stopping CPU %c\n", current_running_cpu_idx + 'A');
8932                   cpu.isRunning = false;
8933                 }
8934 #endif
8935               return CONT_DIS;
8936             }
8937 
8938         /// POINTER REGISTER INSTRUCTIONS
8939 
8940         /// PRIVILEGED INSTRUCTIONS
8941 
8942         /// Privileged - Register Load
8943 
8944         /// Privileged - Clear Associative Memory
8945 
8946         /// EIS - Address Register Load
8947 
8948                          // aarn
8949         case x1 (0560):  // aar0
8950         case x1 (0561):  // aar1
8951         case x1 (0562):  // aar2
8952         case x1 (0563):  // aar3
8953         case x1 (0564):  // aar4
8954         case x1 (0565):  // aar5
8955         case x1 (0566):  // aar6
8956         case x1 (0567):  // aar7
8957           {
8958             // For n = 0, 1, ..., or 7 as determined by operation code
8959             PNL (L68_ (DU_CYCLE_DDU_LDEA;))
8960 
8961             if (getbits36_1 (cpu.CY, 23) != 0)
8962               doFault (FAULT_IPR,
8963                        fst_ill_proc,
8964                        "aarn C(Y)23 != 0");
8965 
8966             uint32 n = opcode10 & 07;  // get
8967             CPTUR (cptUsePRn + n);
8968 
8969             // C(Y)0,17 -> C(ARn.WORDNO)
8970             cpu.AR[n].WORDNO = GETHI (cpu.CY);
8971 
8972             uint TA = getbits36_2 (cpu.CY, 21);
8973             uint CN = getbits36_3 (cpu.CY, 18);
8974 
8975             switch (TA)
8976               {
8977                 case CTA4:  // 2
8978                   // If C(Y)21,22 = 10 (TA code = 2), then
8979                   //   C(Y)18,20 / 2 -> C(ARn.CHAR)
8980                   //   4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
8981 
8982                   // According to AL39, CN is translated:
8983                   //  CN   CHAR  BIT
8984                   //   0      0    1
8985                   //   1      0    5
8986                   //   2      1    1
8987                   //   3      1    5
8988                   //   4      2    1
8989                   //   5      2    5
8990                   //   6      3    1
8991                   //   7      3    5
8992                   //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
8993 
8994                   // According to ISOLTS ps805
8995                   //  CN   CHAR  BIT
8996                   //   0      0    0
8997                   //   1      0    5
8998                   //   2      1    0
8999                   //   3      1    5
9000                   //   4      2    0
9001                   //   5      2    5
9002                   //   6      3    0
9003                   //   7      3    5
9004                   SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
9005 
9006                   break;
9007 
9008                 case CTA6:  // 1
9009                   // If C(Y)21,22 = 01 (TA code = 1) and C(Y)18,20 = 110
9010                   // or 111 an illegal procedure fault occurs.
9011                   if (CN > 5)
9012                     {
9013                       cpu.AR[n].WORDNO = 0;
9014                       SET_AR_CHAR_BITNO (n, 0, 0);
9015                       doFault (FAULT_IPR, fst_ill_proc, "aarn TN > 5");
9016                     }
9017 
9018                   // If C(Y)21,22 = 01 (TA code = 1), then
9019                   //   (6 * C(Y)18,20) / 9 -> C(ARn.CHAR)
9020                   //   (6 * C(Y)18,20)mod9 -> C(ARn.BITNO)
9021                   SET_AR_CHAR_BITNO (n, (word2) ((6 * CN) / 9),
9022                                      (6 * CN) % 9);
9023                   break;
9024 
9025                 case CTA9:  // 0
9026                   // If C(Y)21,22 = 00 (TA code = 0), then
9027                   //   C(Y)18,19 -> C(ARn.CHAR)
9028                   //   0000 -> C(ARn.BITNO)
9029                   // remember, 9-bit CN's are funky
9030                   SET_AR_CHAR_BITNO (n, (word2) (CN >> 1), 0);
9031                   break;
9032 
9033                 case CTAILL: // 3
9034                   // If C(Y)21,22 = 11 (TA code = 3) an illegal procedure
9035                   // fault occurs.
9036                   cpu.AR[n].WORDNO = 0;
9037                   SET_AR_CHAR_BITNO (n, 0, 0);
9038 #if defined(TESTING)
9039                   HDBGRegARW (n, "aarn");
9040 #endif
9041                   doFault (FAULT_IPR, fst_ill_proc, "aarn TA = 3");
9042               }
9043 #if defined(TESTING)
9044             HDBGRegARW (n, "aarn");
9045 #endif
9046           }
9047           break;
9048 
9049         // Load Address Register n
9050                         // larn
9051         case x1 (0760): // lar0
9052         case x1 (0761): // lar1
9053         case x1 (0762): // lar2
9054         case x1 (0763): // lar3
9055         case x1 (0764): // lar4
9056         case x1 (0765): // lar5
9057         case x1 (0766): // lar6
9058         case x1 (0767): // lar7
9059           {
9060             // For n = 0, 1, ..., or 7 as determined by operation code
9061             //    C(Y)0,23 -> C(ARn)
9062             PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9063 
9064             uint32 n = opcode10 & 07;  // get n
9065             CPTUR (cptUsePRn + n);
9066             cpu.AR[n].WORDNO = GETHI (cpu.CY);
9067 // AL-38 implies CHAR/BITNO, but ISOLTS requires PR.BITNO.
9068             SET_AR_CHAR_BITNO (n,  getbits36_2 (cpu.CY, 18),
9069                                getbits36_4 (cpu.CY, 20));
9070 #if defined(TESTING)
9071             HDBGRegARW (n, "larn");
9072 #endif
9073           }
9074           break;
9075 
9076         // lareg - Load Address Registers
9077 
9078         case x1 (0463):  // lareg
9079           PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9080 
9081           for (uint32 n = 0 ; n < 8 ; n += 1)
9082             {
9083               CPTUR (cptUsePRn + n);
9084               word36 tmp36 = cpu.Yblock8[n];
9085               cpu.AR[n].WORDNO = getbits36_18 (tmp36, 0);
9086               SET_AR_CHAR_BITNO (n,  getbits36_2 (tmp36, 18),
9087                                  getbits36_4 (tmp36, 20));
9088 #if defined(TESTING)
9089               HDBGRegARW (n, "lareg");
9090 #endif
9091             }
9092           break;
9093 
9094         // lpl - Load Pointers and Lengths
9095 
9096         case x1 (0467):  // lpl
9097           PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9098           words2du (cpup, cpu.Yblock8);
9099           break;
9100 
9101         // narn -  (G'Kar?) Numeric Descriptor to Address Register n
9102                         // narn
9103         case x1 (0660): // nar0
9104         case x1 (0661): // nar1
9105         case x1 (0662): // nar2
9106         case x1 (0663): // nar3
9107         case x1 (0664): // nar4
9108         case x1 (0665): // nar5
9109         case x1 (0666): // nar6 beware!!!! :-)
9110         case x1 (0667): // nar7
9111           {
9112             // For n = 0, 1, ..., or 7 as determined by operation code
9113             PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9114 
9115             uint32 n = opcode10 & 07;  // get
9116             CPTUR (cptUsePRn + n);
9117 
9118             // C(Y)0,17 -> C(ARn.WORDNO)
9119             cpu.AR[n].WORDNO = GETHI (cpu.CY);
9120 
9121             uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9122             uint CN = getbits36_3 (cpu.CY, 18); // C(Y) 18-20
9123 
9124             switch(TN)
9125               {
9126                 case CTN4:   // 1
9127                     // If C(Y)21 = 1 (TN code = 1), then
9128                     //   (C(Y)18,20) / 2 -> C(ARn.CHAR)
9129                     //   4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
9130 
9131                     // According to AL39, CN is translated:
9132                     //  CN   CHAR  BIT
9133                     //   0      0    1
9134                     //   1      0    5
9135                     //   2      1    1
9136                     //   3      1    5
9137                     //   4      2    1
9138                     //   5      2    5
9139                     //   6      3    1
9140                     //   7      3    5
9141                     //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
9142 
9143                     // According to ISOLTS ps805
9144                     //  CN   CHAR  BIT
9145                     //   0      0    0
9146                     //   1      0    5
9147                     //   2      1    0
9148                     //   3      1    5
9149                     //   4      2    0
9150                     //   5      2    5
9151                     //   6      3    0
9152                     //   7      3    5
9153                     SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
9154 
9155                     break;
9156 
9157                 case CTN9:  // 0
9158                   // If C(Y)21 = 0 (TN code = 0) and C(Y)20 = 1 an
9159                   // illegal procedure fault occurs.
9160                   if ((CN & 1) != 0)
9161                     doFault (FAULT_IPR, fst_ill_proc, "narn N9 and CN odd");
9162                   // The character number is in bits 18-19; recover it
9163                   CN >>= 1;
9164                   // If C(Y)21 = 0 (TN code = 0), then
9165                   //   C(Y)18,20 -> C(ARn.CHAR)
9166                   //   0000 -> C(ARn.BITNO)
9167                   SET_AR_CHAR_BITNO (n, (word2) CN, 0);
9168                   break;
9169               }
9170 #if defined(TESTING)
9171             HDBGRegARW (n, "narn");
9172 #endif
9173           }
9174           break;
9175 
9176         /// EIS - Address Register Store
9177 
9178         // aran Address Register n to Alphanumeric Descriptor
9179 
9180                         // aran
9181         case x1 (0540): // ara0
9182         case x1 (0541): // ara1
9183         case x1 (0542): // ara2
9184         case x1 (0543): // ara3
9185         case x1 (0544): // ara4
9186         case x1 (0545): // ara5
9187         case x1 (0546): // ara6
9188         case x1 (0547): // ara7
9189             {
9190                 // The alphanumeric descriptor is fetched from Y and C(Y)21,22
9191                 // (TA field) is examined to determine the data type described.
9192                 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9193 
9194                 uint TA = getbits36_2 (cpu.CY, 21);
9195 
9196                 // If C(Y)21,22 = 11 (TA code = 3) or C(Y)23 = 1 (unused bit),
9197                 // an illegal procedure fault occurs.
9198                 if (TA == 03) {
9199                   dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn tag == 3");
9200                   break;
9201                 }
9202                 if (getbits36_1 (cpu.CY, 23) != 0) {
9203                   dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn b23 == 1");
9204                   break;
9205                 }
9206 
9207                 uint32 n = opcode10 & 07;  // get
9208                 CPTUR (cptUsePRn + n);
9209                 // For n = 0, 1, ..., or 7 as determined by operation code
9210 
9211                 // C(ARn.WORDNO) -> C(Y)0,17
9212                 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9213 
9214                 // If TA = 1 (6-bit data) or TA = 2 (4-bit data), C(ARn.CHAR)
9215                 // and C(ARn.BITNO) are translated to an equivalent character
9216                 // position that goes to C(Y)18,20.
9217 
9218                 int CN = 0;
9219 
9220                 switch (TA)
9221                 {
9222                     case CTA4:  // 2
9223                         // If C(Y)21,22 = 10 (TA code = 2), then
9224                         // (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 -> C(Y)18,20
9225                         CN = (9 * GET_AR_CHAR (n) + GET_AR_BITNO (n) - 1) / 4;
9226                         putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9227                         break;
9228 
9229                     case CTA6:  // 1
9230                         // If C(Y)21,22 = 01 (TA code = 1), then
9231                         // (9 * C(ARn.CHAR) + C(ARn.BITNO)) / 6 -> C(Y)18,20
9232                         CN = (9 * GET_AR_CHAR (n) + GET_AR_BITNO (n)) / 6;
9233                         putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9234                         break;
9235 
9236                     case CTA9:  // 0
9237                         // If C(Y)21,22 = 00 (TA code = 0), then
9238                         //   C(ARn.CHAR) -> C(Y)18,19
9239                         //   0 -> C(Y)20
9240                         putbits36_3 (& cpu.CY, 18,
9241                                      (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9242                         break;
9243                 }
9244               cpu.zone = 0777777700000;
9245               cpu.useZone = true;
9246             }
9247             break;
9248 
9249         // arnn Address Register n to Numeric Descriptor
9250 
9251                         // aarn
9252         case x1 (0640): // aar0
9253         case x1 (0641): // aar1
9254         case x1 (0642): // aar2
9255         case x1 (0643): // aar3
9256         case x1 (0644): // aar4
9257         case x1 (0645): // aar5
9258         case x1 (0646): // aar6
9259         case x1 (0647): // aar7
9260             {
9261                 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9262                 uint32 n = opcode10 & 07;  // get register #
9263                 CPTUR (cptUsePRn + n);
9264 
9265                 // The Numeric descriptor is fetched from Y and C(Y)21,22 (TA
9266                 // field) is examined to determine the data type described.
9267 
9268                 uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9269 
9270                 // For n = 0, 1, ..., or 7 as determined by operation code
9271                 // C(ARn.WORDNO) -> C(Y)0,17
9272                 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9273 
9274                 switch (TN)
9275                 {
9276                     case CTN4:  // 1
9277                       {
9278                         // If C(Y)21 = 1 (TN code = 1) then
9279                         //   (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 ->
9280                         //     C(Y)18,20
9281                         word3 CN = (9 * GET_AR_CHAR (n) +
9282                                     GET_AR_BITNO (n) - 1) / 4;
9283                         putbits36_3 (& cpu.CY, 18, CN & MASK3);
9284                         break;
9285                       }
9286                     case CTN9:  // 0
9287                         // If C(Y)21 = 0 (TN code = 0), then
9288                         //   C(ARn.CHAR) -> C(Y)18,19
9289                         //   0 -> C(Y)20
9290                         putbits36_3 (& cpu.CY, 18,
9291                                      (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9292                         break;
9293                 }
9294               cpu.zone = 0777777700000;
9295               cpu.useZone = true;
9296             }
9297             break;
9298 
9299         // sarn Store Address Register n
9300 
9301                         // sarn
9302         case x1 (0740): // sar0
9303         case x1 (0741): // sar1
9304         case x1 (0742): // sar2
9305         case x1 (0743): // sar3
9306         case x1 (0744): // sar4
9307         case x1 (0745): // sar5
9308         case x1 (0746): // sar6
9309         case x1 (0747): // sar7
9310             //For n = 0, 1, ..., or 7 as determined by operation code
9311             //  C(ARn) -> C(Y)0,23
9312             //  C(Y)24,35 -> unchanged
9313             {
9314                 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9315                 uint32 n = opcode10 & 07;  // get n
9316                 CPTUR (cptUsePRn + n);
9317                 putbits36 (& cpu.CY,  0, 18, cpu.PR[n].WORDNO);
9318 // AL-39 implies CHAR/BITNO, but ISOLTS test 805 requires BITNO
9319                 putbits36 (& cpu.CY, 18, 2, GET_AR_CHAR (n));
9320                 putbits36 (& cpu.CY, 20, 4, GET_AR_BITNO (n));
9321                 //putbits36 (& cpu.CY, 18, 6, GET_PR_BITNO (n));
9322                 cpu.zone = 0777777770000;
9323                 cpu.useZone = true;
9324             }
9325           break;
9326 
9327         // sareg Store Address Registers
9328 
9329         case x1 (0443):  // sareg
9330             // a:AL39/ar1 According to ISOLTS ps805, the BITNO data is stored
9331             // in BITNO format, not CHAR/BITNO.
9332             PNL (L68_ (DU_CYCLE_DDU_STEA;))
9333             (void)memset (cpu.Yblock8, 0, sizeof (cpu.Yblock8));
9334             for (uint32 n = 0 ; n < 8 ; n += 1)
9335             {
9336                 CPTUR (cptUsePRn + n);
9337                 word36 arx = 0;
9338                 putbits36 (& arx,  0, 18, cpu.PR[n].WORDNO);
9339                 putbits36 (& arx, 18,  2, GET_AR_CHAR (n));
9340                 putbits36 (& arx, 20,  4, GET_AR_BITNO (n));
9341                 cpu.Yblock8[n] = arx;
9342             }
9343             break;
9344 
9345         // spl Store Pointers and Lengths
9346 
9347         case x1 (0447):  // spl
9348             PNL (L68_ (DU_CYCLE_DDU_STEA;))
9349             du2words (cpup, cpu.Yblock8);
9350           break;
9351 
9352         /// EIS - Address Register Special Arithmetic
9353 
9354         // a4bd Add 4-bit Displacement to Address Register 5
9355 
9356         case x1 (0502):  // a4bd
9357           asxbd (cpup, 4, false);
9358           break;
9359 
9360         // a6bd Add 6-bit Displacement to Address Register
9361 
9362         case x1 (0501):  // a6bd
9363           asxbd (cpup, 6, false);
9364           break;
9365 
9366         // a9bd Add 9-bit Displacement to Address Register
9367 
9368         case x1 (0500):  // a9bd
9369           asxbd (cpup, 9, false);
9370           break;
9371 
9372         // abd Add Bit Displacement to Address Register
9373 
9374         case x1 (0503):  // abd
9375           asxbd (cpup, 1, false);
9376           break;
9377 
9378         // awd Add Word Displacement to Address Register
9379 
9380         case x1 (0507):  // awd
9381           asxbd (cpup, 36, false);
9382           break;
9383 
9384         // s4bd Subtract 4-bit Displacement from Address Register
9385 
9386         case x1 (0522):  // s4bd
9387           asxbd (cpup, 4, true);
9388           break;
9389 
9390         // s6bd Subtract 6-bit Displacement from Address Register
9391 
9392         case x1 (0521):  // s6bd
9393           asxbd (cpup, 6, true);
9394           break;
9395 
9396         // s9bd Subtract 9-bit Displacement from Address Register
9397 
9398         case x1 (0520):  // s9bd
9399           asxbd (cpup, 9, true);
9400           break;
9401 
9402         // sbd Subtract Bit Displacement from Address Register
9403 
9404         case x1 (0523):  // sbd
9405           asxbd (cpup, 1, true);
9406           break;
9407 
9408         // swd Subtract Word Displacement from Address Register
9409 
9410         case x1 (0527):  // swd
9411           asxbd (cpup, 36, true);
9412           break;
9413 
9414         /// EIS = Alphanumeric Compare
9415 
9416         case x1 (0106):  // cmpc
9417           cmpc (cpup);
9418           break;
9419 
9420         case x1 (0120):  // scd
9421           scd (cpup);
9422           break;
9423 
9424         case x1 (0121):  // scdr
9425           scdr (cpup);
9426           break;
9427 
9428         case x1 (0124):  // scm
9429           scm (cpup);
9430           break;
9431 
9432         case x1 (0125):  // scmr
9433           scmr (cpup);
9434           break;
9435 
9436         case x1 (0164):  // tct
9437           tct (cpup);
9438           break;
9439 
9440         case x1 (0165):  // tctr
9441           tctr (cpup);
9442           break;
9443 
9444         /// EIS - Alphanumeric Move
9445 
9446         case x1 (0100):  // mlr
9447           mlr (cpup);
9448           break;
9449 
9450         case x1 (0101):  // mrl
9451           mrl (cpup);
9452           break;
9453 
9454         case x1 (0020):  // mve
9455           mve (cpup);
9456           break;
9457 
9458         case x1 (0160):  // mvt
9459           mvt (cpup);
9460           break;
9461 
9462         /// EIS - Numeric Compare
9463 
9464         case x1 (0303):  // cmpn
9465           cmpn (cpup);
9466           break;
9467 
9468         /// EIS - Numeric Move
9469 
9470         case x1 (0300):  // mvn
9471           mvn (cpup);
9472           break;
9473 
9474         case x1 (0024):   // mvne
9475           mvne (cpup);
9476           break;
9477 
9478         /// EIS - Bit String Combine
9479 
9480         case x1 (0060):   // csl
9481           csl (cpup);
9482           break;
9483 
9484         case x1 (0061):   // csr
9485           csr (cpup);
9486           break;
9487 
9488         /// EIS - Bit String Compare
9489 
9490         case x1 (0066):   // cmpb
9491           cmpb (cpup);
9492           break;
9493 
9494         /// EIS - Bit String Set Indicators
9495 
9496         case x1 (0064):   // sztl
9497           // The execution of this instruction is identical to the Combine
9498           // Bit Strings Left (csl) instruction except that C(BOLR)m is
9499           // not placed into C(Y-bit2)i-1.
9500           sztl (cpup);
9501           break;
9502 
9503         case x1 (0065):   // sztr
9504           // The execution of this instruction is identical to the Combine
9505           // Bit Strings Left (csr) instruction except that C(BOLR)m is
9506           // not placed into C(Y-bit2)i-1.
9507           sztr (cpup);
9508           break;
9509 
9510         /// EIS -- Data Conversion
9511 
9512         case x1 (0301):  // btd
9513           btd (cpup);
9514           break;
9515 
9516         case x1 (0305):  // dtb
9517           dtb (cpup);
9518           break;
9519 
9520         /// EIS - Decimal Addition
9521 
9522         case x1 (0202):  // ad2d
9523             ad2d (cpup);
9524             break;
9525 
9526         case x1 (0222):  // ad3d
9527             ad3d (cpup);
9528             break;
9529 
9530         /// EIS - Decimal Subtraction
9531 
9532         case x1 (0203):  // sb2d
9533             sb2d (cpup);
9534             break;
9535 
9536         case x1 (0223):  // sb3d
9537             sb3d (cpup);
9538             break;
9539 
9540         /// EIS - Decimal Multiplication
9541 
9542         case x1 (0206):  // mp2d
9543             mp2d (cpup);
9544             break;
9545 
9546         case x1 (0226):  // mp3d
9547             mp3d (cpup);
9548             break;
9549 
9550         /// EIS - Decimal Division
9551 
9552         case x1 (0207):  // dv2d
9553             dv2d (cpup);
9554             break;
9555 
9556         case x1 (0227):  // dv3d
9557             dv3d (cpup);
9558             break;
9559 
9560         case x1 (0420):  // emcall instruction Custom, for an emulator call for scp
9561         {
9562             if (cpu.tweaks.enable_emcall) {
9563               int ret = emCall (cpup);
9564               if (ret)
9565                 return ret;
9566               break;
9567             }
9568             goto unimp;
9569         }
9570 
9571         default:
9572         unimp:
9573           if (cpu.tweaks.halt_on_unimp)
9574             return STOP_STOP;
9575           doFault (FAULT_IPR,
9576                    fst_ill_op,
9577                    "Illegal instruction");
9578       }
9579     L68_ (
9580       cpu.ou.STR_OP = (is_ou && (i->info->flags & (STORE_OPERAND | STORE_YPAIR))) ? 1 : 0;
9581       cpu.ou.cycle |= ou_GOF;
9582       if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_ou)
9583         add_l68_OU_history (cpup);
9584       if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_du)
9585         add_l68_DU_history (cpup);
9586     )
9587     return SCPE_OK;
9588 }
9589 
9590 #include <ctype.h>
9591 #include <time.h>
9592 
9593 /*
9594  * emulator call instruction. Do whatever address field sez' ....
9595  */
9596 
9597 //static clockid_t clockID;
9598 //static struct timespec startTime;
9599 static uv_rusage_t startTime;
9600 static unsigned long long startInstrCnt;
9601 
9602 static int emCall (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
9603 {
9604 #if defined(THREADZ) || defined(LOCKLESS)
9605     atomic_thread_fence (memory_order_seq_cst);
9606 #endif /* defined(THREADZ) || defined(LOCKLESS) */
9607 
9608     DCDstruct * i = & cpu.currentInstruction;
9609 
9610 // The address is absolute address of a structure consisting of a
9611 // operation code word and optional following words containing
9612 // data for the operation.
9613 
9614    word36 op = M[i->address];
9615    switch (op)
9616      {
9617        // OP 1: Print the unsigned decimal representation of the first data
9618        //       word.
9619        case 1:
9620          sim_printf ("%lld\n", (long long int) M[i->address+1]);
9621          break;
9622 
9623        // OP 2: Halt the simulation
9624        case 2:
9625 #if defined(LOCKLESS)
9626          bce_dis_called = true;
9627 #endif
9628          return STOP_STOP;
9629 
9630        // OP 3: Start CPU clock
9631        case 3:
9632          startInstrCnt = cpu.instrCnt;
9633          uv_getrusage (& startTime);
9634          break;
9635 
9636        // OP 4: Report CPU clock
9637        case 4:
9638          {
9639 #define ns_sec  (1000000000L)
9640 #define ns_msec (1000000000L / 1000L)
9641 #define ns_usec (1000000000L / 1000L / 1000L)
9642            uv_rusage_t now;
9643            uv_getrusage (& now);
9644            uint64_t start            = (uint64_t)((uint64_t)startTime.ru_utime.tv_usec * 1000ULL +
9645                                                   (uint64_t)startTime.ru_utime.tv_sec * (uint64_t)ns_sec);
9646            uint64_t stop             = (uint64_t)((uint64_t)now.ru_utime.tv_usec * 1000ULL +
9647                                                   (uint64_t)now.ru_utime.tv_sec * (uint64_t)ns_sec);
9648            uint64_t delta            = stop - start;
9649            uint64_t seconds          = delta / ns_sec;
9650            uint64_t milliseconds     = (delta / ns_msec) % 1000ULL;
9651            uint64_t microseconds     = (delta / ns_usec) % 1000ULL;
9652            uint64_t nanoseconds      = delta % 1000ULL;
9653            unsigned long long nInsts = (unsigned long long)((unsigned long long)cpu.instrCnt -
9654                                                             (unsigned long long)startInstrCnt);
9655            double secs               = (double)(((long double) delta) / ((long double) ns_sec));
9656            long double ips           = (long double)(((long double) nInsts) / ((long double) secs));
9657            long double mips          = (long double)(ips / 1000000.0L);
9658 
9659 #if defined(WIN_STDIO)
9660            sim_printf ("CPU time %llu.%03llu,%03llu,%03llu\n",
9661 #else
9662            sim_printf ("CPU time %'llu.%03llu,%03llu,%03llu\n",
9663 #endif /* if defined(WIN_STDIO) */
9664                        (unsigned long long) seconds,
9665                        (unsigned long long) milliseconds,
9666                        (unsigned long long) microseconds,
9667                        (unsigned long long) nanoseconds);
9668 #if defined(WIN_STDIO)
9669            sim_printf ("%llu instructions\n", (unsigned long long) nInsts);
9670            sim_printf ("%f MIPS\n", (double) mips);
9671 #else
9672            sim_printf ("%'llu instructions\n", (unsigned long long) nInsts);
9673            sim_printf ("%'f MIPS\n", (double) mips);
9674 #endif /* if defined(WIN_STDIO) */
9675            break;
9676          }
9677        default:
9678          sim_printf ("emcall unknown op %llo\n", (unsigned long long)op);
9679       }
9680     return 0;
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 
9816 
9817 
9818 
9819 
9820 
9821 
9822 
9823 
9824 
9825 
9826 
9827 
9828 
9829 
9830 
9831 
9832 
9833 
9834 
9835 
9836 
9837 
9838 
9839 
9840 
9841 
9842 
9843 
9844 
9845 
9846 
9847 
9848 
9849 
9850 
9851 
9852 
9853 
9854 
9855 
9856 
9857 
9858 
9859 
9860 
9861 
9862 
9863 
9864 
9865 
9866 
9867 
9868 
9869 
9870 
9871 
9872   }
9873 
9874 // CANFAULT
9875 static int doABSA (cpu_state_t * cpup, word36 * result)
     /* [previous][next][first][last][top][bottom][index][help] */
9876   {
9877     word36 res;
9878     sim_debug (DBG_APPENDING, & cpu_dev, "absa CA:%08o\n", cpu.TPR.CA);
9879 
9880     //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.isb29)
9881     //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.went_appending) // ISOLTS-860
9882     if (get_addr_mode (cpup) == ABSOLUTE_mode && ! (cpu.cu.XSF || cpu.currentInstruction.b29)) // ISOLTS-860
9883       {
9884         * result = ((word36) (cpu.TPR.CA & MASK18)) << 12; // 24:12 format
9885         return SCPE_OK;
9886       }
9887 
9888     // ABSA handles directed faults differently, so a special append cycle is
9889     // needed.
9890     // do_append_cycle also provides WAM support, which is required by
9891     // ISOLTS-860 02
9892     //   res = (word36) do_append_cycle (cpu.TPR.CA & MASK18, ABSA_CYCLE, NULL,
9893     //                                   0) << 12;
9894     //res = (word36) do_append_cycle (ABSA_CYCLE, NULL, 0) << 12;
9895     res = (word36) doAppendCycleABSA (cpup, NULL, 0) << 12;
9896 
9897     * result = res;
9898 
9899     return SCPE_OK;
9900   }
9901 
9902 void doRCU (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
9903   {
9904 #if defined(LOOPTRC)
9905 elapsedtime ();
9906  sim_printf (" rcu to %05o:%06o  PSR:IC %05o:%06o\r\n",
9907              (cpu.Yblock8[0]>>18)&MASK15, (cpu.Yblock8[4]>>18)&MASK18, cpu.PPR.PSR, cpu.PPR.IC);
9908 #endif
9909 
9910     if_sim_debug (DBG_FAULT, & cpu_dev)
9911       {
9912         dump_words(cpup, cpu.Yblock8);
9913         //for (int i = 0; i < 8; i ++)
9914         //  {
9915         //    sim_debug (DBG_FAULT, & cpu_dev, "RCU %d %012"PRIo64"\n", i,
9916         //               cpu.Yblock8[i]);
9917         //  }
9918       }
9919 
9920     words2scu (cpup, cpu.Yblock8);
9921     decode_instruction (cpup, IWB_IRODD, & cpu.currentInstruction);
9922 
9923 // Restore addressing mode
9924 
9925     word1 saveP = cpu.PPR.P; // ISOLTS-870 02m
9926     if (TST_I_ABS == 0)
9927       set_addr_mode (cpup, APPEND_mode);
9928     else
9929       set_addr_mode (cpup, ABSOLUTE_mode);
9930     cpu.PPR.P = saveP;
9931 
9932     if (getbits36_1  (cpu.Yblock8[1], 35) == 0) // cpu.cu.FLT_INT is interrupt, not fault
9933       {
9934         sim_debug (DBG_FAULT, & cpu_dev, "RCU interrupt return\n");
9935         longjmp (cpu.jmpMain, JMP_REFETCH);
9936       }
9937 
9938     // Resync the append unit
9939     fauxDoAppendCycle (cpup, INSTRUCTION_FETCH);
9940 
9941 // All of the faults list as having handlers have actually
9942 // been encountered in Multics operation and are believed
9943 // to be being handled correctly. The handlers in
9944 // parenthesis are speculative and untested.
9945 //
9946 // Unhandled:
9947 //
9948 //    SDF Shutdown: Why would you RCU from a shutdown fault?
9949 //    STR Store:
9950 //      AL39 is contradictory or vague about store fault subfaults and store
9951 //      faults in general. They are mentioned:
9952 //        SPRPn: store fault (illegal pointer) (assuming STR:ISN)
9953 //        SMCM: store fault (not control)  -
9954 //        SMIC: store fault (not control)   > I believe that these should be
9955 //        SSCR: store fault (not control)  -  command fault
9956 //        TSS:  STR:OOB
9957 //        Bar mode out-of-bounds: STR:OOB
9958 //     The SCU register doesn't define which bit is "store fault (not control)"
9959 // STR:ISN - illegal segment number
9960 // STR:NEA - nonexistent address
9961 // STR:OOB - bar mode out-of-bounds
9962 //
9963 // decimal   octal
9964 // fault     fault  mnemonic   name             priority group  handler
9965 // number   address
9966 //   0         0      sdf      Shutdown               27 7
9967 //   1         2      str      Store                  10 4                                 get_BAR_address, instruction execution
9968 //   2         4      mme      Master mode entry 1    11 5      JMP_SYNC_FAULT_RETURN      instruction execution
9969 //   3         6      f1       Fault tag 1            17 5      (JMP_REFETCH/JMP_RESTART)  do_caf
9970 //   4        10      tro      Timer runout           26 7      JMP_REFETCH                FETCH_cycle
9971 //   5        12      cmd      Command                 9 4      JMP_REFETCH/JMP_RESTART    instruction execution
9972 //   6        14      drl      Derail                 15 5      JMP_REFETCH/JMP_RESTART    instruction execution
9973 //   7        16      luf      Lockup                  5 4      JMP_REFETCH                do_caf, FETCH_cycle
9974 //   8        20      con      Connect                25 7      JMP_REFETCH                FETCH_cycle
9975 //   9        22      par      Parity                  8 4
9976 //  10        24      ipr      Illegal procedure      16 5                                 doITSITP, do_caf, instruction execution
9977 //  11        26      onc      Operation not complete  4 2                                 nem_check, instruction execution
9978 //  12        30      suf      Startup                 1 1
9979 //  13        32      ofl      Overflow                7 3      JMP_REFETCH/JMP_RESTART    instruction execution
9980 //  14        34      div      Divide check            6 3                                 instruction execution
9981 //  15        36      exf      Execute                 2 1      JMP_REFETCH/JMP_RESTART    FETCH_cycle
9982 //  16        40      df0      Directed fault 0       20 6      JMP_REFETCH/JMP_RESTART    getSDW, do_append_cycle
9983 //  17        42      df1      Directed fault 1       21 6      JMP_REFETCH/JMP_RESTART    getSDW, do_append_cycle
9984 //  18        44      df2      Directed fault 2       22 6      (JMP_REFETCH/JMP_RESTART)  getSDW, do_append_cycle
9985 //  19        46      df3      Directed fault 3       23 6      JMP_REFETCH/JMP_RESTART    getSDW, do_append_cycle
9986 //  20        50      acv      Access violation       24 6      JMP_REFETCH/JMP_RESTART    fetchDSPTW, modifyDSPTW, fetchNSDW,
9987 //                                                                                          do_append_cycle, EXEC_cycle (ring alarm)
9988 //  21        52      mme2     Master mode entry 2    12 5      JMP_SYNC_FAULT_RETURN      instruction execution
9989 //  22        54      mme3     Master mode entry 3    13 5      (JMP_SYNC_FAULT_RETURN)    instruction execution
9990 //  23        56      mme4     Master mode entry 4    14 5      (JMP_SYNC_FAULT_RETURN)    instruction execution
9991 //  24        60      f2       Fault tag 2            18 5      JMP_REFETCH/JMP_RESTART    do_caf
9992 //  25        62      f3       Fault tag 3            19 5      JMP_REFETCH/JMP_RESTART    do_caf
9993 //  26        64               Unassigned
9994 //  27        66               Unassigned
9995 //  28        70               Unassigned
9996 //  29        72               Unassigned
9997 //  30        74               Unassigned
9998 //  31        76      trb      Trouble                 3 2                                  FETCH_cycle, doRCU
9999 
10000 // Reworking logic
10001 
10002 #define rework
10003 #if defined(rework)
10004     if (cpu.cu.FIF) // fault occurred during instruction fetch
10005       {
10006 //if (cpu.cu.rfi) sim_printf ( "RCU FIF refetch return caught rfi\n");
10007         // I am misusing this bit; on restart I want a way to tell the
10008         // CPU state machine to restart the instruction, which is not
10009         // how Multics uses it. I need to pick a different way to
10010         // communicate; for now, turn it off on refetch so the state
10011         // machine doesn't become confused.
10012         cpu.cu.rfi = 0;
10013         sim_debug (DBG_FAULT, & cpu_dev, "RCU FIF REFETCH return\n");
10014         longjmp (cpu.jmpMain, JMP_REFETCH);
10015       }
10016 
10017 // RFI means 'refetch this instruction'
10018     if (cpu.cu.rfi)
10019       {
10020 //sim_printf ( "RCU rfi refetch return\n");
10021         sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi refetch return\n");
10022 // Setting the to RESTART causes ISOLTS 776 to report unexpected
10023 // trouble faults.
10024 // Without clearing rfi, ISOLTS pm776-08i LUFs.
10025         cpu.cu.rfi = 0;
10026         longjmp (cpu.jmpMain, JMP_REFETCH);
10027       }
10028 
10029 // The debug command uses MME2 to implement breakpoints, but it is not
10030 // clear what it does to the MC data to signal RFI behavior.
10031 
10032     word5 fi_addr = getbits36_5  (cpu.Yblock8[1], 30);
10033     if (fi_addr == FAULT_MME  ||
10034         fi_addr == FAULT_MME2 ||
10035         fi_addr == FAULT_MME3 ||
10036         fi_addr == FAULT_MME4 ||
10037         fi_addr == FAULT_DRL)
10038     //if (fi_addr == FAULT_MME2)
10039       {
10040 //sim_printf ("MME2 restart\n");
10041         sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\n");
10042         cpu.cu.rfi = 0;
10043         longjmp (cpu.jmpMain, JMP_RESTART);
10044       }
10045 #else
10046     if (cpu.cu.rfi || // S/W asked for the instruction to be started
10047         cpu.cu.FIF)   // fault occurred during instruction fetch
10048       {
10049         // I am misusing this bit; on restart I want a way to tell the
10050         // CPU state machine to restart the instruction, which is not
10051         // how Multics uses it. I need to pick a different way to
10052         // communicate; for now, turn it off on refetch so the state
10053         // machine doesn't become confused.
10054 
10055         cpu.cu.rfi = 0;
10056         sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi/FIF REFETCH return\n");
10057         longjmp (cpu.jmpMain, JMP_REFETCH);
10058       }
10059 
10060 // It seems obvious that MMEx should do a JMP_SYNC_FAULT_RETURN, but doing
10061 // a JMP_RESTART makes 'debug' work. (The same change to DRL does not make
10062 // 'gtss' work, tho.
10063 
10064     if (fi_addr == FAULT_MME2)
10065       {
10066 //sim_printf ("MME2 restart\n");
10067         sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\n");
10068         cpu.cu.rfi = 1;
10069         longjmp (cpu.jmpMain, JMP_RESTART);
10070       }
10071 #endif
10072 
10073 
10074 
10075 
10076 
10077 
10078 
10079 
10080 
10081 
10082 
10083 
10084 
10085 
10086 
10087 
10088 
10089 
10090 
10091     // MME faults resume with the next instruction
10092 
10093 #if defined(rework)
10094     if (fi_addr == FAULT_DIV ||
10095         fi_addr == FAULT_OFL ||
10096         fi_addr == FAULT_IPR)
10097       {
10098         sim_debug (DBG_FAULT, & cpu_dev, "RCU sync fault return\n");
10099         cpu.cu.rfi = 0;
10100         longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10101       }
10102 #else
10103     if (fi_addr == FAULT_MME  ||
10104      /* fi_addr == FAULT_MME2 || */
10105         fi_addr == FAULT_MME3 ||
10106         fi_addr == FAULT_MME4 ||
10107         fi_addr == FAULT_DRL  ||
10108         fi_addr == FAULT_DIV  ||
10109         fi_addr == FAULT_OFL  ||
10110         fi_addr == FAULT_IPR)
10111       {
10112         sim_debug (DBG_FAULT, & cpu_dev, "RCU MMEx sync fault return\n");
10113         cpu.cu.rfi = 0;
10114         longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10115       }
10116 #endif
10117 
10118     // LUF can happen during fetch or CAF. If fetch, handled above
10119     if (fi_addr == FAULT_LUF)
10120       {
10121         cpu.cu.rfi = 1;
10122         sim_debug (DBG_FAULT, & cpu_dev, "RCU LUF RESTART return\n");
10123         longjmp (cpu.jmpMain, JMP_RESTART);
10124       }
10125 
10126     if (fi_addr == FAULT_DF0 ||
10127         fi_addr == FAULT_DF1 ||
10128         fi_addr == FAULT_DF2 ||
10129         fi_addr == FAULT_DF3 ||
10130         fi_addr == FAULT_ACV ||
10131         fi_addr == FAULT_F1  ||
10132         fi_addr == FAULT_F2  ||
10133         fi_addr == FAULT_F3  ||
10134         fi_addr == FAULT_CMD ||
10135         fi_addr == FAULT_EXF)
10136       {
10137         // If the fault occurred during fetch, handled above.
10138         cpu.cu.rfi = 1;
10139         sim_debug (DBG_FAULT, & cpu_dev, "RCU ACV RESTART return\n");
10140         longjmp (cpu.jmpMain, JMP_RESTART);
10141       }
10142     sim_printf ("doRCU dies with unhandled fault number %d\n", fi_addr);
10143     doFault (FAULT_TRB,
10144              (_fault_subtype) {.bits=fi_addr},
10145              "doRCU dies with unhandled fault number");
10146   }

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