root/src/dps8/dps8_faults.c

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

DEFINITIONS

This source file includes following definitions.
  1. emCallReportFault
  2. clearFaultCycle
  3. doFault
  4. do_FFV_fault
  5. dlyDoFault
  6. bG7Pending
  7. bG7PendingNoTRO
  8. setG7fault
  9. set_FFV_fault
  10. clearTROFault
  11. doG7Fault
  12. advanceG7Faults

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * SPDX-License-Identifier: Multics
   5  * scspell-id: 4182f303-f62e-11ec-9475-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) 2017 Michal Tomek
  13  * Copyright (c) 2021-2024 The DPS8M Development Team
  14  *
  15  * This software is made available under the terms of the ICU License.
  16  * See the LICENSE.md file at the top-level directory of this distribution.
  17  *
  18  * ---------------------------------------------------------------------------
  19  *
  20  * This source file may contain code comments that adapt, include, and/or
  21  * incorporate Multics program code and/or documentation distributed under
  22  * the Multics License.  In the event of any discrepancy between code
  23  * comments herein and the original Multics materials, the original Multics
  24  * materials should be considered authoritative unless otherwise noted.
  25  * For more details and historical background, see the LICENSE.md file at
  26  * the top-level directory of this distribution.
  27  *
  28  * ---------------------------------------------------------------------------
  29  */
  30 
  31 #include <stdio.h>
  32 
  33 #include "dps8.h"
  34 #include "dps8_sys.h"
  35 #include "dps8_iom.h"
  36 #include "dps8_cable.h"
  37 #include "dps8_cpu.h"
  38 #include "dps8_faults.h"
  39 #include "dps8_scu.h"
  40 #include "dps8_append.h"
  41 #include "dps8_ins.h"
  42 #include "dps8_utils.h"
  43 #if defined(THREADZ) || defined(LOCKLESS)
  44 # include "threadz.h"
  45 #endif
  46 
  47 #define DBG_CTR cpu.cycleCnt
  48 
  49 /*
  50  * FAULT RECOGNITION
  51  * For the discussion following, the term "function" is defined as a major processor functional
  52  * cycle. Examples are: APPEND CYCLE, CA CYCLE, INSTRUCTION FETCH CYCLE, OPERAND STORE CYCLE,
  53  * DIVIDE EXECUTION CYCLE. Some of these cycles are discussed in various sections of this manual.
  54  * Faults in groups 1 and 2 cause the processor to abort all functions immediately by entering a
  55  * FAULT CYCLE. Faults in group 3 cause the processor to "close out" current functions without
  56  * taking any irrevocable action (such as setting PTW.U in an APPEND CYCLE or modifying an
  57  * indirect word in a CA CYCLE), then to discard any pending functions (such as an APPEND CYCLE
  58  * needed during a CA CYCLE), and to enter a FAULT CYCLE. Faults in group 4 cause the processor
  59  * to suspend overlapped operation, to complete current and pending functions for the current
  60  * instruction, and then to enter a FAULT CYCLE. Faults in groups 5 or 6 are normally detected
  61  * during virtual address formation and instruction decode. These faults cause the processor to
  62  * suspend overlapped operation, to complete the current and pending instructions, and to enter
  63  * a FAULT CYCLE. If a fault in a higher priority group is generated by the execution of the
  64  * current or pending instructions, that higher priority fault will take precedence and the
  65  * group 5 or 6 fault will be lost. If a group 5 or 6 fault is detected during execution of the
  66  * current instruction (e.g., an access violation, out of segment bounds, fault during certain
  67  * interruptible EIS instructions), the instruction is considered "complete" upon detection of
  68  * the fault. Faults in group 7 are held and processed (with interrupts) at the completion of
  69  * the current instruction pair. Group 7 faults are inhibitable by setting bit 28 of the
  70  * instruction word. Faults in groups 3 through 6 must wait for the system controller to
  71  * acknowledge the last access request before entering the FAULT CYCLE.
  72  */
  73 
  74 /*
  75  *                                Table 7-1. List of Faults
  76  *
  77  * Decimal fault     Octal (1)      Fault   Fault name            Priority    Group
  78  *    number      fault address   mnemonic
  79  *       0      ;         0     ;      sdf  ;   Shutdown             ;   27     ;     7
  80  *       1      ;         2     ;      str  ;   Store                ;   10     ;     4
  81  *       2      ;         4     ;      mme  ;   Master mode entry 1  ;   11     ;     5
  82  *       3      ;         6     ;      f1   ;   Fault tag 1          ;   17     ;     5
  83  *       4      ;        10     ;      tro  ;   Timer runout         ;   26     ;     7
  84  *       5      ;        12     ;      cmd  ;   Command              ;   9      ;     4
  85  *       6      ;        14     ;      drl  ;   Derail               ;   15     ;     5
  86  *       7      ;        16     ;      luf  ;   Lockup               ;   5      ;     4
  87  *       8      ;        20     ;      con  ;   Connect              ;   25     ;     7
  88  *       9      ;        22     ;      par  ;   Parity               ;   8      ;     4
  89  *       10     ;        24     ;      ipr  ;   Illegal procedure    ;   16     ;     5
  90  *       11     ;        26     ;      onc  ;   Operation not complete ; 4      ;     2
  91  *       12     ;        30     ;      suf  ;   Startup              ;   1      ;     1
  92  *       13     ;        32     ;      ofl  ;   Overflow             ;   7      ;     3
  93  *       14     ;        34     ;      div  ;   Divide check         ;   6      ;     3
  94  *       15     ;        36     ;      exf  ;   Execute              ;   2      ;     1
  95  *       16     ;        40     ;      df0  ;   Directed fault 0     ;   20     ;     6
  96  *       17     ;        42     ;      df1  ;   Directed fault 1     ;   21     ;     6
  97  *       18     ;        44     ;      df2  ;   Directed fault 2     ;   22     ;     6
  98  *       19     ;        46     ;      df3  ;   Directed fault 3     ;   23     ;     6
  99  *       20     ;        50     ;      acv  ;   Access violation     ;   24     ;     6
 100  *       21     ;        52     ;      mme2 ;   Master mode entry 2  ;   12     ;     5
 101  *       22     ;        54     ;      mme3 ;   Master mode entry 3  ;   13     ;     5
 102  *       23     ;        56     ;      mme4 ;   Master mode entry 4  ;   14     ;     5
 103  *       24     ;        60     ;      f2   ;   Fault tag 2          ;   18     ;     5
 104  *       25     ;        62     ;      f3   ;   Fault tag 3          ;   19     ;     5
 105  *       26     ;        64     ;           ;   Unassigned           ;          ;
 106  *       27     ;        66     ;           ;   Unassigned           ;          ;
 107  */
 108 
 109 #if !defined(QUIET_UNUSED)
 110 static dps8faults _faultsP[] = { // sorted by priority
 111 //      number  address  mnemonic  name                   Priority   Group
 112     {   12,     030,     "suf",    "Startup",                   1,      1,     false },
 113     {   15,     036,     "exf",    "Execute",                   2,      1,     false },
 114     {   31,     076,     "trb",    "Trouble",                   3,      2,     false },
 115     {   11,     026,     "onc",    "Operation not complete",    4,      2,     false },
 116     {    7,     016,     "luf",    "Lockup",                    5,      4,     false },
 117     {   14,     034,     "div",    "Divide check",              6,      3,     false },
 118     {   13,     032,     "ofl",    "Overflow",                  7,      3,     false },
 119     {    9,     022,     "par",    "Parity",                    8,      4,     false },
 120     {    5,     012,     "cmd",    "Command",                   9,      4,     false },
 121     {    1,       2,     "str",    "Store",                    10,      4,     false },
 122     {    2,       4,     "mme",    "Master mode entry 1",      11,      5,     false },
 123     {   21,     052,    "mme2",    "Master mode entry 2",      12,      5,     false },
 124     {   22,     054,    "mme3",    "Master mode entry 3",      13,      5,     false },
 125     {   23,     056,    "mme4",    "Master mode entry 4",      14,      5,     false },
 126     {    6,     014,     "drl",    "Derail",                   15,      5,     false },
 127     {   10,     024,     "ipr",    "Illegal procedure",        16,      5,     false },
 128     {    3,      06,      "f1",    "Fault tag 1",              17,      5,     false },
 129     {   24,     060,      "f2",    "Fault tag 2",              18,      5,     false },
 130     {   25,     062,      "f3",    "Fault tag 3",              19,      5,     false },
 131     {   16,     040,     "df0",    "Directed fault 0",         20,      6,     false },
 132     {   17,     042,     "df1",    "Directed fault 1",         21,      6,     false },
 133     {   18,     044,     "df2",    "Directed fault 2",         22,      6,     false },
 134     {   19,     046,     "df3",    "Directed fault 3",         23,      6,     false },
 135     {   20,     050,     "acv",    "Access violation",         24,      6,     false },
 136     {    8,     020,     "con",    "Connect",                  25,      7,     false },
 137     {    4,     010,     "tro",    "Timer runout",             26,      7,     false },
 138     {    0,       0,     "sdf",    "Shutdown",                 27,      7,     false },
 139     {   26,     064,     "???",    "Unassigned",               -1,     -1,     false },
 140     {   27,     066,     "???",    "Unassigned",               -1,     -1,     false },
 141     {   -1,      -1,      NULL,     NULL,                      -1,     -1,     false }
 142 };
 143 
 144 static dps8faults _faults[] = {    // sorted by number
 145 //      number  address  mnemonic  name                   Priority   Group
 146     {   0,        0,     "sdf",    "Shutdown",                 27,      7,     false },
 147     {   1,        2,     "str",    "Store",                    10,      4,     false },
 148     {   2,        4,     "mme",    "Master mode entry 1",      11,      5,     false },
 149     {   3,       06,      "f1",    "Fault tag 1",              17,      5,     false },
 150     {   4,      010,     "tro",    "Timer runout",             26,      7,     false },
 151     {   5,      012,     "cmd",    "Command",                  9,       4,     false },
 152     {   6,      014,     "drl",    "Derail",                   15,      5,     false },
 153     {   7,      016,     "luf",    "Lockup",                   5,       4,     false },
 154     {   8,      020,     "con",    "Connect",                  25,      7,     false },
 155     {   9,      022,     "par",    "Parity",                   8,       4,     false },
 156     {   10,     024,     "ipr",    "Illegal procedure",        16,      5,     false },
 157     {   11,     026,     "onc",    "Operation not complete",   4,       2,     false },
 158     {   12,     030,     "suf",    "Startup",                  1,       1,     false },
 159     {   13,     032,     "ofl",    "Overflow",                 7,       3,     false },
 160     {   14,     034,     "div",    "Divide check",             6,       3,     false },
 161     {   15,     036,     "exf",    "Execute",                  2,       1,     false },
 162     {   16,     040,     "df0",    "Directed fault 0",         20,      6,     false },
 163     {   17,     042,     "df1",    "Directed fault 1",         21,      6,     false },
 164     {   18,     044,     "df2",    "Directed fault 2",         22,      6,     false },
 165     {   19,     046,     "df3",    "Directed fault 3",         23,      6,     false },
 166     {   20,     050,     "acv",    "Access violation",         24,      6,     false },
 167     {   21,     052,    "mme2",    "Master mode entry 2",      12,      5,     false },
 168     {   22,     054,    "mme3",    "Master mode entry 3",      13,      5,     false },
 169     {   23,     056,    "mme4",    "Master mode entry 4",      14,      5,     false },
 170     {   24,     060,      "f2",    "Fault tag 2",              18,      5,     false },
 171     {   25,     062,      "f3",    "Fault tag 3",              19,      5,     false },
 172     {   26,     064,     "???",    "Unassigned",               -1,     -1,     false },
 173     {   27,     066,     "???",    "Unassigned",               -1,     -1,     false },
 174     {   28,     070,     "???",    "Unassigned",               -1,     -1,     false },
 175     {   29,     072,     "???",    "Unassigned",               -1,     -1,     false },
 176     {   30,     074,     "???",    "Unassigned",               -1,     -1,     false },
 177     {   31,     076,     "trb",    "Trouble",                   3,      2,     false },
 178     {   -1,     -1,       NULL,     NULL,                      -1,     -1,     false }
 179 };
 180 #endif /* if !defined(QUIET_UNUSED) */
 181 
 182 char * faultNames [N_FAULTS] =
 183   {
 184     "Shutdown",
 185     "Store",
 186     "Master mode entry 1",
 187     "Fault tag 1",
 188     "Timer runout",
 189     "Command",
 190     "Derail",
 191     "Lockup",
 192     "Connect",
 193     "Parity",
 194     "Illegal procedure",
 195     "Operation not complete",
 196     "Startup",
 197     "Overflow",
 198     "Divide check",
 199     "Execute",
 200     "Directed fault 0",
 201     "Directed fault 1",
 202     "Directed fault 2",
 203     "Directed fault 3",
 204     "Access violation",
 205     "Master mode entry 2",
 206     "Master mode entry 3",
 207     "Master mode entry 4",
 208     "Fault tag 2",
 209     "Fault tag 3",
 210     "Unassigned 26",
 211     "Unassigned 27",
 212     "Unassigned 28",
 213     "Unassigned 29",
 214     "Unassigned 30",
 215     "Trouble"
 216   };
 217 //bool pending_fault = false;     // true when a fault has been signalled, but not processed
 218 
 219 #if !defined(QUIET_UNUSED)
 220 static bool port_interrupts[8] = { false, false, false, false, false, false, false, false };
 221 #endif /* if !defined(QUIET_UNUSED) */
 222 
 223 //-----------------------------------------------------------------------------
 224 // ***  Constants, unchanging lookup tables, etc
 225 
 226 #if !defined (QUIET_UNUSED)
 227 static int fault2group[32] = {
 228     // from AL39, page 7-3
 229     7, 4, 5, 5, 7, 4, 5, 4,
 230     7, 4, 5, 2, 1, 3, 3, 1,
 231     6, 6, 6, 6, 6, 5, 5, 5,
 232     5, 5, 0, 0, 0, 0, 0, 2
 233 };
 234 
 235 static int fault2prio[32] = {
 236     // from AL39, page 7-3
 237     27, 10, 11, 17, 26,  9, 15,  5,
 238     25,  8, 16,  4,  1,  7,  6,  2,
 239     20, 21, 22, 23, 24, 12, 13, 14,
 240     18, 19,  0,  0,  0,  0,  0,  3
 241 };
 242 #endif /* if !defined(QUIET_UNUSED) */
 243 
 244 /*
 245  * fault handler(s).
 246  */
 247 
 248 #if defined(TESTING)
 249 // We stash a few things for debugging; they are accessed by emCall.
 250 static word18 fault_ic;
 251 static word15 fault_psr;
 252 static char fault_msg [1024];
 253 
 254 void emCallReportFault (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 255   {
 256            cpu_state_t * cpup = _cpup;
 257            sim_printf ("fault report:\n");
 258            sim_printf ("  fault number %d (%o)\n", cpu . faultNumber, cpu . faultNumber);
 259            sim_printf ("  subfault number %llu (%llo)\n", (unsigned long long) cpu.subFault.bits,
 260                    (unsigned long long)cpu.subFault.bits);
 261            sim_printf ("  faulting address %05o:%06o\n", fault_psr, fault_ic);
 262            sim_printf ("  msg %s\n", fault_msg);
 263   }
 264 #endif /* if defined(TESTING) */
 265 
 266 void clearFaultCycle (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 267   {
 268     cpu . bTroubleFaultCycle = false;
 269   }
 270 
 271 /*
 272 
 273 Faults in groups 1 and 2 cause the processor to abort all functions immediately
 274 by entering a FAULT CYCLE.
 275 
 276 Faults in group 3 cause the processor to "close out" current functions without
 277 taking any irrevocable action (such as setting PTW.U in an APPEND CYCLE or
 278 modifying an indirect word in a CA CYCLE), then to discard any pending
 279 functions (such as an APPEND CYCLE needed during a CA CYCLE), and to enter a
 280 FAULT CYCLE.
 281 
 282 Faults in group 4 cause the processor to suspend overlapped operation, to
 283 complete current and pending functions for the current instruction, and then to
 284 enter a FAULT CYCLE.
 285 
 286 Faults in groups 5 or 6 are normally detected during virtual address formation
 287 and instruction decode. These faults cause the processor to suspend overlapped
 288 operation, to complete the current and pending instructions, and to enter a
 289 FAULT CYCLE. If a fault in a higher priority group is generated by the
 290 execution of the current or pending instructions, that higher priority fault
 291 will take precedence and the group 5 or 6 fault will be lost. If a group 5 or 6
 292 fault is detected during execution of the current instruction (e.g., an access
 293 violation, out of segment bounds, fault during certain interruptible EIS
 294 instructions), the instruction is considered "complete" upon detection of the
 295 fault.
 296 
 297 Faults in group 7 are held and processed (with interrupts) at the completion
 298 of the current instruction pair.
 299 
 300 Group 7 faults are inhibitable by setting bit 28 of the instruction word.
 301 
 302 Faults in groups 3 through 6 must wait for the system controller to acknowledge
 303 the last access request before entering the FAULT CYCLE.
 304 
 305 After much rumination here are my thoughts for fault processing .....
 306 
 307 For now, at least, we must remember a few things:
 308 
 309 1) We only have 1 cpu so we have few & limited async faults - shutdown, TRO,
 310 etc.
 311 2) We have no overlapping instruction execution
 312 3) Because of 2) we have no pending instructions
 313 4) We have no system controller to wait for
 314 
 315 Group 1 & 2 faults can be processed immediately and then proceed to next
 316 instruction as long as no transfer prevents us from returning from the XED pair.
 317 
 318 Group 3 faults will probably also execute immediately since a G3 fault causes
 319 "the processor to "close out" current functions without taking any irrevocable
 320 action (such as setting PTW.U in an APPEND CYCLE or modifying an indirect word
 321 in a CA CYCLE), then to discard any pending functions (such as an APPEND CYCLE
 322 needed during a CA CYCLE), and to enter a FAULT CYCLE."
 323 
 324 Group 4 faults will probably also execute immediately since a G4 fault causes
 325 "the processor to suspend overlapped operation, to complete current and pending
 326 functions for the current instruction, and then to enter a FAULT CYCLE."
 327 
 328 Group 5 & 6 faults will probably also execute immediately because "if a group 5
 329 or 6 fault is detected during execution of the current instruction (e.g., an
 330 access violation, out of segment bounds, fault during certain interruptible EIS
 331 instructions), the instruction is considered "complete" upon detection of the
 332 fault." However, remember "If a fault in a higher priority group is generated
 333 by the execution of the current or pending instructions, that higher priority
 334 fault will take precedence and the group 5 or 6 fault will be lost. If a group
 335 5 or 6 fault is detected during execution of the current instruction (e.g., an
 336 access violation, out of segment bounds, fault during certain interruptible EIS
 337 instructions), the instruction is considered "complete" upon detection of the
 338 fault."
 339 
 340 For further justification of immediate execution since "Faults in groups 3
 341 through 6 must wait for the system controller to acknowledge the last access
 342 request before entering the FAULT CYCLE."
 343 
 344 Group 7 faults will be processed after next even instruction decode instruction
 345 decode, but before instruction execution. In this way we can actually use
 346 bit-28 tp inhibit interrupts
 347 
 348 */
 349 
 350 #if defined(LOOPTRC)
 351 # include <time.h>
 352 void elapsedtime (void);
 353 #endif /* if defined(LOOPRTC) */
 354 
 355 #if !defined(NEED_128)
 356 const _fault_subtype fst_zero      = (_fault_subtype) {.bits=0};
 357 const _fault_subtype fst_acv9      = (_fault_subtype) {.fault_acv_subtype=ACV9};
 358 const _fault_subtype fst_acv15     = (_fault_subtype) {.fault_acv_subtype=ACV15};
 359 const _fault_subtype fst_ill_mod   = (_fault_subtype) {.fault_ipr_subtype=FR_ILL_MOD};
 360 const _fault_subtype fst_ill_proc  = (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC};
 361 const _fault_subtype fst_ill_dig   = (_fault_subtype) {.fault_ipr_subtype=FR_ILL_DIG};
 362 const _fault_subtype fst_ill_op    = (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP};
 363 const _fault_subtype fst_str_oob   = (_fault_subtype) {.fault_str_subtype=flt_str_oob};
 364 const _fault_subtype fst_str_nea   = (_fault_subtype) {.fault_str_subtype=flt_str_nea};
 365 const _fault_subtype fst_str_ptr   = (_fault_subtype) {.fault_str_subtype=flt_str_ill_ptr};
 366 const _fault_subtype fst_cmd_lprpn = (_fault_subtype) {.fault_cmd_subtype=flt_cmd_lprpn_bits};
 367 const _fault_subtype fst_cmd_ctl   = (_fault_subtype) {.fault_cmd_subtype=flt_cmd_not_control};
 368 const _fault_subtype fst_onc_nem   = (_fault_subtype) {.fault_onc_subtype=flt_onc_nem};
 369 #endif /* if !defined(NEED_128) */
 370 // CANFAULT
 371 void doFault (_fault faultNumber, _fault_subtype subFault,
     /* [previous][next][first][last][top][bottom][index][help] */
 372               const char * faultMsg)
 373   {
 374   cpu_state_t * cpup = _cpup;
 375 
 376 #if defined(LOOPTRC)
 377 if (faultNumber == FAULT_TRO)
 378 {
 379  elapsedtime ();
 380  sim_printf (" TRO PSR:IC %05o:%06o\r\n", cpu.PPR.PSR, cpu.PPR.IC);
 381 }
 382 else if (faultNumber == FAULT_ACV)
 383 {
 384  elapsedtime ();
 385  sim_printf (" ACV %012llo PSR:IC %05o:%06o\r\n", subFault.bits, cpu.PPR.PSR, cpu.PPR.IC);
 386 }
 387 #endif /* if defined(LOOPRTC) */
 388 //if (current_running_cpu_idx)
 389     //sim_printf ("Fault %d(0%0o), sub %ld(0%lo), dfc %c, '%s'\n",
 390                //faultNumber, faultNumber, subFault, subFault,
 391                //cpu . bTroubleFaultCycle ? 'Y' : 'N', faultMsg);
 392 //if (current_running_cpu_idx)
 393     //sim_printf ("xde %d xdo %d\n", cpu.cu.xde, cpu.cu.xdo);
 394     sim_debug (DBG_FAULT, & cpu_dev,
 395                "Fault %d(0%0o), sub %"PRIu64"(0%"PRIo64"), dfc %c, '%s'\n",
 396                faultNumber, faultNumber, subFault.bits, subFault.bits,
 397                cpu . bTroubleFaultCycle ? 'Y' : 'N', faultMsg);
 398 #if defined(PROFILER)
 399 # if !defined(GNU_ATOMICS)
 400 #  error PROFILER requires GNU_ATOMICS
 401 # endif /* if !defined(GNU_ATOMICS) */
 402     __atomic_add_fetch (& cpu.faults[faultNumber], 1u, __ATOMIC_ACQUIRE);
 403 #endif /* if defined(PROFILER) */
 404 #if defined(TESTING)
 405     HDBGFault (faultNumber, subFault, faultMsg, "");
 406 #endif /* if defined(TESTING) */
 407 #if !defined(SPEED)
 408     if_sim_debug (DBG_FAULT, & cpu_dev)
 409       traceInstruction (DBG_FAULT);
 410 #endif /* if !defined(SPEED) */
 411 
 412     PNL (cpu.DACVpDF = faultNumber >=  FAULT_DF0 && faultNumber <= FAULT_ACV;)
 413 
 414 #if defined(TESTING)
 415     // some debugging support stuff
 416     fault_psr = cpu . PPR.PSR;
 417     fault_ic  = cpu . PPR.IC;
 418     strcpy (fault_msg, faultMsg);
 419 #endif /* if defined(TESTING) */
 420 
 421     //if (faultNumber < 0 || faultNumber > 31)
 422     if (faultNumber & ~037U)  // quicker?
 423     {
 424         sim_printf ("fault(out-of-range): %d %llo '%s'\n",
 425                     faultNumber, (unsigned long long)subFault.bits,
 426                     faultMsg ? faultMsg : "?");
 427         sim_warn ("fault out-of-range\n");
 428         faultNumber = FAULT_TRB;
 429     }
 430 
 431     cpu.faultNumber = faultNumber;
 432     cpu.subFault    = subFault;
 433     cpu.faultCnt [faultNumber] ++;
 434 
 435     // "The occurrence of a fault or interrupt sets the cache-to-register mode bit to OFF." a:AL39/cmr1
 436     CPTUR (cptUseCMR);
 437     cpu.CMR.csh_reg = 0;
 438 
 439     // Increment FCT
 440 
 441     word3 FCT = cpu.cu.APUCycleBits & MASK3;
 442     FCT = (FCT + 1u) & MASK3;
 443     cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | FCT);
 444 
 445     // Set fault register bits
 446 
 447     CPTUR (cptUseFR);
 448     if (faultNumber == FAULT_IPR)
 449       {
 450 
 451 
 452 
 453 
 454 
 455 
 456 
 457 
 458 
 459 
 460         cpu . faultRegister [0] |= subFault.bits;
 461 
 462       }
 463     else if (faultNumber == FAULT_ONC && subFault.fault_onc_subtype == flt_onc_nem)
 464       {
 465         cpu . faultRegister [0] |= FR_NEM;
 466       }
 467     else if (faultNumber == FAULT_STR)
 468       {
 469         if (subFault.fault_str_subtype == flt_str_oob)
 470           cpu . faultRegister [0] |= FR_OOB;
 471         //else if (subFault.fault_str_subtype == flt_str_ill_ptr)
 472           //cpu . faultRegister [0] |= ?;    // XXX
 473         //else if (subFault.fault_str_subtype == flt_str_nea)
 474           //cpu . faultRegister [0] |= ?;    // XXX
 475       }
 476     else if (faultNumber == FAULT_CON)
 477       {
 478         switch (subFault.fault_con_subtype)
 479           {
 480             case con_a:
 481               cpu . faultRegister [0] |= FR_CON_A;
 482               break;
 483             case con_b:
 484               cpu . faultRegister [0] |= FR_CON_B;
 485               break;
 486             case con_c:
 487               cpu . faultRegister [0] |= FR_CON_C;
 488               break;
 489             case con_d:
 490               cpu . faultRegister [0] |= FR_CON_D;
 491               break;
 492             default:
 493               sim_warn ("FAULT_CON can't map port %lo\n", (long unsigned) subFault.fault_con_subtype);
 494               break;
 495           }
 496       }
 497 
 498     // Set cu word1 fault bits
 499 
 500     cpu . cu . IRO_ISN          = 0;
 501     cpu . cu . OEB_IOC          = 0;
 502     cpu . cu . EOFF_IAIM        = 0;
 503     cpu . cu . ORB_ISP          = 0;
 504     cpu . cu . ROFF_IPR         = 0;
 505     cpu . cu . OWB_NEA          = 0;
 506     cpu . cu . WOFF_OOB         = 0;
 507     cpu . cu . NO_GA            = 0;
 508     cpu . cu . OCB              = 0;
 509     cpu . cu . OCALL            = 0;
 510     cpu . cu . BOC              = 0;
 511     DPS8M_ (cpu . cu . PTWAM_ER = 0;)
 512     cpu . cu . CRT              = 0;
 513     cpu . cu . RALR             = 0;
 514     cpu . cu . SDWAM_ER         = 0;
 515     cpu . cu . OOSB             = 0;
 516     cpu . cu . PARU             = 0;
 517     cpu . cu . PARL             = 0;
 518     cpu . cu . ONC1             = 0;
 519     cpu . cu . ONC2             = 0;
 520     cpu . cu . IA               = 0;
 521     cpu . cu . IACHN            = 0;
 522     cpu . cu . CNCHN            = (faultNumber == FAULT_CON) ? subFault.fault_con_subtype & MASK3 : 0;
 523 
 524     // Set control unit 'fault occurred during instruction fetch' flag
 525     cpu . cu . FIF       = cpu . cycle == FETCH_cycle ? 1 : 0;
 526     cpu . cu . FI_ADDR   = (word5) faultNumber;
 527 
 528     // XXX Under what conditions should this be set?
 529     // Assume no
 530     // Reading Multics source, it seems like Multics is setting this bit; I'm going
 531     // to assume that the h/w also sets it to 0, and the s/w has to explicitly set it on.
 532     cpu . cu . rfi = 0;
 533 
 534 // Try to decide if this a MIF fault (fault during EIS instruction)
 535 // EIS instructions are not used in fault/interrupt pairs, so the
 536 // only time an EIS instruction could be executing is during EXEC_cycle.
 537 // I am also assuming that only multi-word EIS instructions are of interest.
 538 // Testing faultNumber fixes ISOLTS 890-04a
 539     // fixes 890-04a and 791 / 792
 540     SC_I_MIF (cpu.cycle == EXEC_cycle &&
 541               (cpu.currentInstruction.info->ndes > 0 ||
 542                (faultNumber == FAULT_IPR && (subFault.fault_ipr_subtype & FR_ILL_OP_CONST) &&
 543                 cpu.currentInstruction.opcodeX &&
 544                 (cpu.currentInstruction.opcode & 0410) == 0)));
 545     sim_debug (DBG_TRACEEXT, & cpu_dev, "MIF %o\n", TST_I_MIF);
 546 
 547 
 548 
 549 
 550 
 551 
 552 
 553 
 554 
 555 
 556 
 557 
 558     if (faultNumber == FAULT_ACV)
 559       {
 560         // This is annoyingly inefficient since the subFault value
 561         // is bitwise the same as the upper half of CU word1;
 562         // if the upper half were not broken out, then this would be
 563         // cpu . cu . word1_upper_half = subFault.
 564 
 565         if (subFault.fault_acv_subtype & ACV0)
 566           cpu . cu . IRO_ISN   = 1;
 567         if (subFault.fault_acv_subtype & ACV1)
 568           cpu . cu . OEB_IOC   = 1;
 569         if (subFault.fault_acv_subtype & ACV2)
 570           cpu . cu . EOFF_IAIM = 1;
 571         if (subFault.fault_acv_subtype & ACV3)
 572           cpu . cu . ORB_ISP   = 1;
 573         if (subFault.fault_acv_subtype & ACV4)
 574           cpu . cu . ROFF_IPR  = 1;
 575         if (subFault.fault_acv_subtype & ACV5)
 576           cpu . cu . OWB_NEA   = 1;
 577         if (subFault.fault_acv_subtype & ACV6)
 578           cpu . cu . WOFF_OOB  = 1;
 579         if (subFault.fault_acv_subtype & ACV7)
 580           cpu . cu . NO_GA     = 1;
 581         if (subFault.fault_acv_subtype & ACV8)
 582           cpu . cu . OCB       = 1;
 583         if (subFault.fault_acv_subtype & ACV9)
 584           cpu . cu . OCALL     = 1;
 585         if (subFault.fault_acv_subtype & ACV10)
 586           cpu . cu . BOC       = 1;
 587         if (subFault.fault_acv_subtype & ACV11)
 588           cpu . cu . PTWAM_ER  = 1;
 589         if (subFault.fault_acv_subtype & ACV12)
 590           cpu . cu . CRT       = 1;
 591         if (subFault.fault_acv_subtype & ACV13)
 592           cpu . cu . RALR      = 1;
 593         if (subFault.fault_acv_subtype & ACV14)
 594           cpu . cu . SDWAM_ER  = 1;
 595         if (subFault.fault_acv_subtype & ACV15)
 596           cpu . cu . OOSB      = 1;
 597       }
 598     else if (faultNumber == FAULT_STR)
 599       {
 600         if (subFault.fault_str_subtype == flt_str_oob)
 601           cpu . cu . WOFF_OOB  = 1;
 602         //else if (subFault.fault_str_subtype == flt_str_ill_ptr)
 603           //cpu . cu . ??? = 1; // XXX
 604         else if (subFault.fault_str_subtype == flt_str_nea)
 605           cpu . cu . OWB_NEA   = 1;
 606       }
 607     else if (faultNumber == FAULT_IPR)
 608       {
 609         if (subFault.fault_ipr_subtype & FR_ILL_OP_CONST)
 610           cpu . cu . OEB_IOC   = 1;
 611         if (subFault.fault_ipr_subtype & FR_ILL_MOD_CONST)
 612           cpu . cu . EOFF_IAIM = 1;
 613         if (subFault.fault_ipr_subtype & FR_ILL_SLV_CONST)
 614           cpu . cu . ORB_ISP   = 1;
 615         if (subFault.fault_ipr_subtype & FR_ILL_DIG)
 616           cpu . cu . ROFF_IPR  = 1;
 617       }
 618     else if (faultNumber == FAULT_CMD)
 619       {
 620         if (subFault.fault_cmd_subtype == flt_cmd_lprpn_bits)
 621           cpu . cu . IA        = 0;
 622         else if (subFault.fault_cmd_subtype == flt_cmd_not_control)
 623           cpu . cu . IA        = 010;
 624       }
 625 
 626     L68_ (
 627       // History registers
 628       // IHRRS; AL39 pg 47
 629       // History register lock control. If this bit is set ON, set STROBE ยข
 630       // (bit 30, key k) OFF, locking the history registers for all faults
 631       // including the floating faults.
 632       CPTUR (cptUseMR);
 633       if (cpu.MR.emr && cpu.MR.ihrrs)
 634         {
 635           cpu.MR.ihr = 0;
 636         }
 637     )
 638     DPS8M_ (
 639       // History registers
 640       // IHRRS; AL39 pg 49
 641       // Additional resetting of bit 30. If bit 31 = 1, the following faults also
 642       // reset bit 30:
 643       //   Lock Up
 644       //   Parity
 645       //   Command
 646       //   Store
 647       //   Illegal Procedure
 648       //   Shutdown
 649       if (cpu.MR.emr && cpu.MR.ihrrs)
 650         {
 651           if (faultNumber == FAULT_LUF ||
 652               faultNumber == FAULT_PAR ||
 653               faultNumber == FAULT_CMD ||
 654               faultNumber == FAULT_STR ||
 655               faultNumber == FAULT_IPR ||
 656               faultNumber == FAULT_SDF)
 657             {
 658               cpu.MR.ihr = 0;
 659             }
 660         }
 661       // Enable History Registers.  This bit will be reset by ... an Op Not
 662       // Complete fault. It may be reset by other faults (see bit 31).
 663       if (faultNumber == FAULT_ONC)
 664         {
 665           cpu.MR.ihr = 0;
 666         }
 667     )
 668 
 669     // If already in a FAULT CYCLE then signal trouble fault
 670 
 671     if (cpu.cycle == FAULT_EXEC_cycle)
 672       {
 673         sim_debug (DBG_CYCLE, & cpu_dev, "Changing fault number to Trouble fault\n");
 674 
 675         cpu.faultNumber   = FAULT_TRB;
 676         cpu.cu.FI_ADDR    = FAULT_TRB;
 677         cpu.subFault.bits = 0; // XXX ???
 678         if (cpu.bTroubleFaultCycle)
 679           {
 680 #if !defined(THREADZ) && !defined(LOCKLESS)
 681 # if !defined(PANEL68)
 682 #  if !defined(ROUND_ROBIN)
 683             if ((! sample_interrupts (cpup)) &&
 684                 (sim_qcount () == 0))  // XXX If clk_svc is implemented it will
 685                                        // break this logic
 686               {
 687                 sim_printf \
 688                     ("Fault cascade @0%06o with no interrupts pending and no events in queue\n",
 689                      cpu.PPR.IC);
 690                 sim_printf("\nCycles = %"PRId64"\n", cpu.cycleCnt);
 691                 sim_printf("\nInstructions = %"PRId64"\n", cpu.instrCnt);
 692                 //stop_reason = STOP_FLT_CASCADE;
 693                 longjmp (cpu.jmpMain, JMP_STOP);
 694               }
 695 #  endif /* if !defined(ROUND_ROBIN) */
 696 # endif /* if !defined(PANEL68) */
 697 #endif
 698           }
 699         else
 700           {
 701 //--            f = &_faults[FAULT_TRB];
 702             cpu . bTroubleFaultCycle = true;
 703           }
 704       }
 705     else
 706       {
 707         cpu . bTroubleFaultCycle = false;
 708       }
 709 
 710     // If doInstruction faults, the instruction cycle counter doesn't get
 711     // bumped.
 712     if (cpu . cycle == EXEC_cycle)
 713       cpu.instrCnt ++;
 714 
 715     cpu . cycle = FAULT_cycle;
 716     sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to FAULT_cycle\n");
 717     longjmp (cpu.jmpMain, JMP_REENTRY);
 718 #if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
 719     /*NOTREACHED*/ /* unreachable */
 720     abort(); /* not reached */
 721 #endif
 722 }
 723 
 724 void do_FFV_fault (cpu_state_t * cpup, uint fault_number, const char * fault_msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 725   {
 726     sim_debug (DBG_FAULT, & cpu_dev,
 727                "Floating fault %d '%s'\n",
 728                fault_number, fault_msg);
 729 #if !defined(SPEED)
 730     if_sim_debug (DBG_FAULT, & cpu_dev)
 731       traceInstruction (DBG_FAULT);
 732 #endif /* if !defined(SPEED) */
 733 
 734     if (fault_number < 1 || fault_number > 3)
 735       {
 736         sim_printf ("floating fault(out-of-range): %d '%s'\n",
 737                     fault_number, fault_msg ? fault_msg : "?");
 738         sim_warn ("fault out-of-range\n");
 739       }
 740 
 741     cpu.FFV_fault_number = fault_number;
 742     cpu.faultNumber      = fault_number;
 743 
 744     // "The occurrence of a fault or interrupt sets the
 745     // cache-to-register mode bit to OFF." a:AL39/cmr1
 746     CPTUR (cptUseCMR);
 747     cpu.CMR.csh_reg = 0;
 748 
 749     // Increment FCT
 750 
 751     word3 FCT = cpu.cu.APUCycleBits & MASK3;
 752     FCT = (FCT + 1) & MASK3;
 753     cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | FCT);
 754 
 755     // Set fault register bits
 756     CPTUR (cptUseFR);
 757     cpu.faultRegister [0] = 0;
 758 
 759     // Set cu word1 fault bits
 760 
 761     cpu.cu.IRO_ISN   = 0;
 762     cpu.cu.OEB_IOC   = 0;
 763     cpu.cu.EOFF_IAIM = 0;
 764     cpu.cu.ORB_ISP   = 0;
 765     cpu.cu.ROFF_IPR  = 0;
 766     cpu.cu.OWB_NEA   = 0;
 767     cpu.cu.WOFF_OOB  = 0;
 768     cpu.cu.NO_GA     = 0;
 769     cpu.cu.OCB       = 0;
 770     cpu.cu.OCALL     = 0;
 771     cpu.cu.BOC       = 0;
 772 // FFVs are L68 only, so we don't need this:
 773 //# if defined(DPS8M)
 774   //cpu.cu.PTWAM_ER  = 0;
 775 //# endif /* if defined(DPS8M) */
 776     cpu.cu.CRT       = 0;
 777     cpu.cu.RALR      = 0;
 778     cpu.cu.SDWAM_ER  = 0;
 779     cpu.cu.OOSB      = 0;
 780     cpu.cu.PARU      = 0;
 781     cpu.cu.PARL      = 0;
 782     cpu.cu.ONC1      = 0;
 783     cpu.cu.ONC2      = 0;
 784     cpu.cu.IA        = 0;
 785     cpu.cu.IACHN     = 0;
 786     cpu.cu.CNCHN     = 0;
 787 
 788     // Set control unit 'fault occurred during instruction fetch' flag
 789     cpu.cu.FIF       = 0;
 790     cpu.cu.FI_ADDR   = (word5) fault_number & MASK5;
 791 
 792     // XXX Under what conditions should this be set?
 793     // Assume no
 794     // Reading Multics source, it seems like Multics is setting this bit; I'm going
 795     // to assume that the h/w also sets it to 0, and the s/w has to explicitly set it on.
 796     cpu.cu.rfi = 0;
 797 
 798 // Try to decide if this a MIF fault (fault during EIS instruction)
 799 // EIS instructions are not used in fault/interrupt pairs, so the
 800 // only time an EIS instruction could be executing is during EXEC_cycle.
 801 // I am also assuming that only multi-word EIS instructions are of interest.
 802 
 803     SC_I_MIF (cpu.cycle == EXEC_cycle &&
 804         cpu.currentInstruction.info->ndes > 0);
 805     sim_debug (DBG_TRACEEXT, & cpu_dev, "MIF %o\n", TST_I_MIF);
 806 
 807 
 808     // History registers
 809     // IHRRS; AL39 pg 47
 810     // History register lock control. If this bit is set ON, set STROBE ยข
 811     // (bit 30, key k) OFF, locking the history registers for all faults
 812     // including the floating faults.
 813     CPTUR (cptUseMR);
 814     if (cpu.MR.emr && cpu.MR.ihrrs)
 815       {
 816         cpu.MR.ihr = 0;
 817       }
 818 
 819     if (cpu.cycle == FAULT_EXEC_cycle)
 820       {
 821         cpu.faultNumber   = FAULT_TRB;
 822         cpu.cu.FI_ADDR    = FAULT_TRB;
 823         cpu.subFault.bits = 0; // XXX ???
 824         if (cpu.bTroubleFaultCycle)
 825           {
 826 #if !defined(THREADZ) && !defined(LOCKLESS)
 827 # if !defined(PANEL68)
 828 #  if !defined(ROUND_ROBIN)
 829             if ((! sample_interrupts (cpup)) &&
 830                 (sim_qcount () == 0))  // XXX If clk_svc is implemented it will
 831                                        // break this logic
 832               {
 833                 sim_printf \
 834                     ("Fault cascade @0%06o with no interrupts pending and no events in queue\n",
 835                      cpu.PPR.IC);
 836                 sim_printf("\nCycles = %"PRId64"\n", cpu.cycleCnt);
 837                 sim_printf("\nInstructions = %"PRId64"\n", cpu.instrCnt);
 838                 longjmp (cpu.jmpMain, JMP_STOP);
 839               }
 840 #  endif /* if !defined(ROUND_ROBIN) */
 841 # endif /* if !defined(PANEL68) */
 842 #endif /* if !defined(THREADZ) && !defined(LOCKLESS) */
 843           }
 844         else
 845           {
 846             cpu.bTroubleFaultCycle = true;
 847           }
 848         cpu.cycle = FAULT_cycle;
 849         sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to FAULT_cycle\n");
 850         longjmp (cpu.jmpMain, JMP_REENTRY);
 851       }
 852     cpu.bTroubleFaultCycle = false;
 853 
 854     // If doInstruction faults, the instruction cycle counter doesn't get
 855     // bumped.
 856     if (cpu . cycle == EXEC_cycle)
 857       cpu.instrCnt ++;
 858 
 859     cpu.is_FFV = true;
 860     cpu.cycle  = FAULT_cycle;
 861     longjmp (cpu.jmpMain, JMP_REENTRY);
 862 }
 863 
 864 void dlyDoFault (_fault faultNumber, _fault_subtype subFault,
     /* [previous][next][first][last][top][bottom][index][help] */
 865                 const char * faultMsg)
 866   {
 867     cpu_state_t * cpup = _cpup;
 868     cpu.dlyFlt       = true;
 869     cpu.dlyFltNum    = faultNumber;
 870     cpu.dlySubFltNum = subFault;
 871     cpu.dlyCtx       = faultMsg;
 872   }
 873 
 874 //
 875 // return true if group 7 faults are pending ...
 876 //
 877 
 878 // Note: The DIS code assumes that the only G7 fault is TRO. Adding any
 879 // other G7 faults will potentially require changing the DIS code.
 880 
 881 bool bG7Pending (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 882   {
 883     if (cpu.tweaks.l68_mode)
 884       return cpu.g7Faults != 0 || cpu.FFV_faults != 0; // L68
 885 
 886     return cpu.g7Faults != 0; // DPS8M
 887   }
 888 
 889 bool bG7PendingNoTRO (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 890   {
 891     if (cpu.tweaks.l68_mode)
 892       return (cpu.g7Faults & (~ (1u << FAULT_TRO))) != 0 || cpu.FFV_faults != 0; // L68
 893 
 894     return (cpu.g7Faults & (~ (1u << FAULT_TRO))) != 0; // DPS8M
 895   }
 896 
 897 void setG7fault (uint cpuNo, _fault faultNo, _fault_subtype subFault)
     /* [previous][next][first][last][top][bottom][index][help] */
 898   {
 899     cpu_state_t * cpup = &cpus[cpuNo];
 900     sim_debug (DBG_FAULT, & cpu_dev, "setG7fault CPU %d fault %d (%o) sub %"PRId64" %"PRIo64"\n",
 901                cpuNo, faultNo, faultNo, subFault.bits, subFault.bits);
 902     cpup->g7FaultsPreset |= (1u << faultNo);
 903     //cpu.g7SubFaultsPreset [faultNo] = subFault;
 904     cpup->g7SubFaults [faultNo] = subFault;
 905 #if defined(THREADZ) || defined(LOCKLESS)
 906     wakeCPU(cpuNo);
 907 #endif
 908   }
 909 
 910 void set_FFV_fault (cpu_state_t * cpup, uint f_fault_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 911   {
 912     sim_debug (DBG_FAULT, & cpu_dev, "set_FFV_fault CPU f_fault_no %u\n",
 913                f_fault_no);
 914     // Map fault number (2/4/6) to bit mask  01/02/04
 915     cpu.FFV_faults_preset |= 1u << ((f_fault_no / 2) - 1);
 916   }
 917 
 918 void clearTROFault (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 919   {
 920     cpu . g7Faults &= ~(1u << FAULT_TRO);
 921   }
 922 
 923 void doG7Fault (cpu_state_t * cpup, bool allowTR)
     /* [previous][next][first][last][top][bottom][index][help] */
 924   {
 925     // sim_printf ("doG7fault %08o [%"PRId64"]\n", cpu . g7Faults, cpu.cycleCnt);
 926     // if (cpu . g7Faults)
 927       // {
 928         // sim_debug (DBG_FAULT, & cpu_dev, "doG7Fault %08o\n", cpu . g7Faults);
 929       // }
 930     // According AL39,  Table 7-1. List of Faults, priority of connect is 25
 931     // and priority of Timer runout is 26, lower number means higher priority
 932 #if defined(THREADZ) || defined(LOCKLESS)
 933     lock_scu ();
 934 #endif
 935      if (cpu.g7Faults & (1u << FAULT_CON))
 936        {
 937          cpu.g7Faults &= ~(1u << FAULT_CON);
 938 
 939 #if defined(THREADZ) || defined(LOCKLESS)
 940          unlock_scu ();
 941 #endif
 942          doFault (FAULT_CON, cpu.g7SubFaults [FAULT_CON], "Connect");
 943        }
 944 
 945      if (allowTR && (cpu.g7Faults & (1u << FAULT_TRO)))
 946        {
 947          cpu . g7Faults &= ~(1u << FAULT_TRO);
 948 
 949          //sim_printf("timer runout %12o\n",cpu.PPR.IC);
 950 #if defined(THREADZ) || defined(LOCKLESS)
 951          unlock_scu ();
 952 #endif
 953          doFault (FAULT_TRO, fst_zero, "Timer runout");
 954        }
 955 
 956      // Strictly speaking EXF isn't a G7 fault, but if we treat is as one,
 957      // we are allowing the current instruction to complete, simplifying
 958      // implementation
 959      if (cpu . g7Faults & (1u << FAULT_EXF))
 960        {
 961          cpu . g7Faults &= ~(1u << FAULT_EXF);
 962 
 963 #if defined(THREADZ) || defined(LOCKLESS)
 964          unlock_scu ();
 965 #endif
 966          doFault (FAULT_EXF, fst_zero, "Execute fault");
 967        }
 968 
 969      if (cpu.tweaks.l68_mode) {  // L68
 970        if (cpu.FFV_faults & 1u)  // FFV + 2 OC TRAP
 971          {
 972            cpu.FFV_faults &= ~1u;
 973 #if defined(THREADZ) || defined(LOCKLESS)
 974            unlock_scu ();
 975 #endif
 976            do_FFV_fault (cpup, 1, "OC TRAP");
 977          }
 978        if (cpu.FFV_faults & 2u)  // FFV + 4 CU HISTORY OVERFLOW TRAP
 979          {
 980            cpu.FFV_faults &= ~2u;
 981 #if defined(THREADZ) || defined(LOCKLESS)
 982            unlock_scu ();
 983 #endif
 984            do_FFV_fault (cpup, 2, "CU HIST OVF TRAP");
 985          }
 986        if (cpu.FFV_faults & 4u)  // FFV + 6 ADR TRAP
 987          {
 988            cpu.FFV_faults &= ~4u;
 989 #if defined(THREADZ) || defined(LOCKLESS)
 990            unlock_scu ();
 991 #endif
 992            do_FFV_fault (cpup, 3, "ADR TRAP");
 993          }
 994      }
 995 #if defined(THREADZ) || defined(LOCKLESS)
 996      unlock_scu ();
 997 #endif
 998      doFault (FAULT_TRB, (_fault_subtype) {.bits=cpu.g7Faults}, "Dazed and confused in doG7Fault");
 999   }
1000 
1001 void advanceG7Faults (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
1002   {
1003     if (!cpu.g7FaultsPreset && !cpu.FFV_faults_preset)
1004       return;
1005 
1006 #if defined(THREADZ) || defined(LOCKLESS)
1007     lock_scu ();
1008 #endif
1009     cpu.g7Faults       |= cpu.g7FaultsPreset;
1010     cpu.g7FaultsPreset  = 0;
1011     //memcpy (cpu.g7SubFaults, cpu.g7SubFaultsPreset, sizeof (cpu.g7SubFaults));
1012     L68_ (
1013       cpu.FFV_faults |= cpu.FFV_faults_preset;
1014       cpu.FFV_faults_preset = 0;
1015     )
1016 #if defined(THREADZ) || defined(LOCKLESS)
1017     unlock_scu ();
1018 #endif
1019   }

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