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

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