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

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