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

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