root/src/dps8/dps8_ins.c

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

DEFINITIONS

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

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

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