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-2025 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     (void)atomic_fetch_add_explicit(&cpu.faults[faultNumber], 1u, memory_order_acquire);
 404 #endif /* if defined(PROFILER) */
 405 #if defined(TESTING)
 406     HDBGFault (faultNumber, subFault, faultMsg, "");
 407 #endif /* if defined(TESTING) */
 408 #if !defined(SPEED)
 409     if_sim_debug (DBG_FAULT, & cpu_dev)
 410       traceInstruction (DBG_FAULT);
 411 #endif /* if !defined(SPEED) */
 412 
 413     PNL (cpu.DACVpDF = faultNumber >=  FAULT_DF0 && faultNumber <= FAULT_ACV;)
 414 
 415 #if defined(TESTING)
 416     // some debugging support stuff
 417     fault_psr = cpu . PPR.PSR;
 418     fault_ic  = cpu . PPR.IC;
 419     strcpy (fault_msg, faultMsg);
 420 #endif /* if defined(TESTING) */
 421 
 422     //if (faultNumber < 0 || faultNumber > 31)
 423     if (faultNumber & ~037U)  // quicker?
 424     {
 425         sim_printf ("fault(out-of-range): %d %llo '%s'\n",
 426                     faultNumber, (unsigned long long)subFault.bits,
 427                     faultMsg ? faultMsg : "?");
 428         sim_warn ("fault out-of-range\n");
 429         faultNumber = FAULT_TRB; // XXX Really? this is a simulator bug, not a trouble fault
 430     }
 431 
 432     cpu.faultNumber = faultNumber;
 433     cpu.subFault    = subFault;
 434     cpu.faultCnt [faultNumber] ++;
 435 
 436     // "The occurrence of a fault or interrupt sets the cache-to-register mode bit to OFF." a:AL39/cmr1
 437     CPTUR (cptUseCMR);
 438     cpu.CMR.csh_reg = 0;
 439 
 440     // Increment FCT
 441 
 442     word3 FCT = cpu.cu.APUCycleBits & MASK3;
 443     FCT = (FCT + 1u) & MASK3;
 444     cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | FCT);
 445 
 446     // Set fault register bits
 447 
 448     CPTUR (cptUseFR);
 449     if (faultNumber == FAULT_IPR)
 450       {
 451 
 452 
 453 
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461         cpu . faultRegister [0] |= subFault.bits;
 462 
 463       }
 464     else if (faultNumber == FAULT_ONC && subFault.fault_onc_subtype == flt_onc_nem)
 465       {
 466         cpu . faultRegister [0] |= FR_NEM;
 467       }
 468     else if (faultNumber == FAULT_STR)
 469       {
 470         if (subFault.fault_str_subtype == flt_str_oob)
 471           cpu . faultRegister [0] |= FR_OOB;
 472         //else if (subFault.fault_str_subtype == flt_str_ill_ptr)
 473           //cpu . faultRegister [0] |= ?;    // XXX
 474         //else if (subFault.fault_str_subtype == flt_str_nea)
 475           //cpu . faultRegister [0] |= ?;    // XXX
 476       }
 477     else if (faultNumber == FAULT_CON)
 478       {
 479         switch (subFault.fault_con_subtype)
 480           {
 481             case con_a:
 482               cpu . faultRegister [0] |= FR_CON_A;
 483               break;
 484             case con_b:
 485               cpu . faultRegister [0] |= FR_CON_B;
 486               break;
 487             case con_c:
 488               cpu . faultRegister [0] |= FR_CON_C;
 489               break;
 490             case con_d:
 491               cpu . faultRegister [0] |= FR_CON_D;
 492               break;
 493             default:
 494               sim_warn ("FAULT_CON can't map port %lo\n", (long unsigned) subFault.fault_con_subtype);
 495               break;
 496           }
 497       }
 498 
 499     // Set cu word1 fault bits
 500 
 501     cpu . cu . IRO_ISN          = 0;
 502     cpu . cu . OEB_IOC          = 0;
 503     cpu . cu . EOFF_IAIM        = 0;
 504     cpu . cu . ORB_ISP          = 0;
 505     cpu . cu . ROFF_IPR         = 0;
 506     cpu . cu . OWB_NEA          = 0;
 507     cpu . cu . WOFF_OOB         = 0;
 508     cpu . cu . NO_GA            = 0;
 509     cpu . cu . OCB              = 0;
 510     cpu . cu . OCALL            = 0;
 511     cpu . cu . BOC              = 0;
 512     DPS8M_ (cpu . cu . PTWAM_ER = 0;)
 513     cpu . cu . CRT              = 0;
 514     cpu . cu . RALR             = 0;
 515     cpu . cu . SDWAM_ER         = 0;
 516     cpu . cu . OOSB             = 0;
 517     cpu . cu . PARU             = 0;
 518     cpu . cu . PARL             = 0;
 519     cpu . cu . ONC1             = 0;
 520     cpu . cu . ONC2             = 0;
 521     cpu . cu . IA               = 0;
 522     cpu . cu . IACHN            = 0;
 523     cpu . cu . CNCHN            = (faultNumber == FAULT_CON) ? subFault.fault_con_subtype & MASK3 : 0;
 524 
 525     // Set control unit 'fault occurred during instruction fetch' flag
 526     cpu . cu . FIF       = cpu . cycle == FETCH_cycle ? 1 : 0;
 527     cpu . cu . FI_ADDR   = (word5) faultNumber;
 528 
 529     // XXX Under what conditions should this be set?
 530     // Assume no
 531     // Reading Multics source, it seems like Multics is setting this bit; I'm going
 532     // to assume that the h/w also sets it to 0, and the s/w has to explicitly set it on.
 533     cpu . cu . rfi = 0;
 534 
 535 // Try to decide if this a MIF fault (fault during EIS instruction)
 536 // EIS instructions are not used in fault/interrupt pairs, so the
 537 // only time an EIS instruction could be executing is during EXEC_cycle.
 538 // I am also assuming that only multi-word EIS instructions are of interest.
 539 // Testing faultNumber fixes ISOLTS 890-04a
 540     // fixes 890-04a and 791 / 792
 541     SC_I_MIF (cpu.cycle == EXEC_cycle &&
 542               (cpu.currentInstruction.info->ndes > 0 ||
 543                (faultNumber == FAULT_IPR && (subFault.fault_ipr_subtype & FR_ILL_OP_CONST) &&
 544                 cpu.currentInstruction.opcodeX &&
 545                 (cpu.currentInstruction.opcode & 0410) == 0)));
 546     sim_debug (DBG_TRACEEXT, & cpu_dev, "MIF %o\n", TST_I_MIF);
 547 
 548 
 549 
 550 
 551 
 552 
 553 
 554 
 555 
 556 
 557 
 558 
 559     if (faultNumber == FAULT_ACV)
 560       {
 561         // This is annoyingly inefficient since the subFault value
 562         // is bitwise the same as the upper half of CU word1;
 563         // if the upper half were not broken out, then this would be
 564         // cpu . cu . word1_upper_half = subFault.
 565 
 566         if (subFault.fault_acv_subtype & ACV0)
 567           cpu . cu . IRO_ISN   = 1;
 568         if (subFault.fault_acv_subtype & ACV1)
 569           cpu . cu . OEB_IOC   = 1;
 570         if (subFault.fault_acv_subtype & ACV2)
 571           cpu . cu . EOFF_IAIM = 1;
 572         if (subFault.fault_acv_subtype & ACV3)
 573           cpu . cu . ORB_ISP   = 1;
 574         if (subFault.fault_acv_subtype & ACV4)
 575           cpu . cu . ROFF_IPR  = 1;
 576         if (subFault.fault_acv_subtype & ACV5)
 577           cpu . cu . OWB_NEA   = 1;
 578         if (subFault.fault_acv_subtype & ACV6)
 579           cpu . cu . WOFF_OOB  = 1;
 580         if (subFault.fault_acv_subtype & ACV7)
 581           cpu . cu . NO_GA     = 1;
 582         if (subFault.fault_acv_subtype & ACV8)
 583           cpu . cu . OCB       = 1;
 584         if (subFault.fault_acv_subtype & ACV9)
 585           cpu . cu . OCALL     = 1;
 586         if (subFault.fault_acv_subtype & ACV10)
 587           cpu . cu . BOC       = 1;
 588         if (subFault.fault_acv_subtype & ACV11)
 589           cpu . cu . PTWAM_ER  = 1;
 590         if (subFault.fault_acv_subtype & ACV12)
 591           cpu . cu . CRT       = 1;
 592         if (subFault.fault_acv_subtype & ACV13)
 593           cpu . cu . RALR      = 1;
 594         if (subFault.fault_acv_subtype & ACV14)
 595           cpu . cu . SDWAM_ER  = 1;
 596         if (subFault.fault_acv_subtype & ACV15)
 597           cpu . cu . OOSB      = 1;
 598       }
 599     else if (faultNumber == FAULT_STR)
 600       {
 601         if (subFault.fault_str_subtype == flt_str_oob)
 602           cpu . cu . WOFF_OOB  = 1;
 603         //else if (subFault.fault_str_subtype == flt_str_ill_ptr)
 604           //cpu . cu . ??? = 1; // XXX
 605         else if (subFault.fault_str_subtype == flt_str_nea)
 606           cpu . cu . OWB_NEA   = 1;
 607       }
 608     else if (faultNumber == FAULT_IPR)
 609       {
 610         if (subFault.fault_ipr_subtype & FR_ILL_OP_CONST)
 611           cpu . cu . OEB_IOC   = 1;
 612         if (subFault.fault_ipr_subtype & FR_ILL_MOD_CONST)
 613           cpu . cu . EOFF_IAIM = 1;
 614         if (subFault.fault_ipr_subtype & FR_ILL_SLV_CONST)
 615           cpu . cu . ORB_ISP   = 1;
 616         if (subFault.fault_ipr_subtype & FR_ILL_DIG)
 617           cpu . cu . ROFF_IPR  = 1;
 618       }
 619     else if (faultNumber == FAULT_CMD)
 620       {
 621         if (subFault.fault_cmd_subtype == flt_cmd_lprpn_bits)
 622           cpu . cu . IA        = 0;
 623         else if (subFault.fault_cmd_subtype == flt_cmd_not_control)
 624           cpu . cu . IA        = 010;
 625       }
 626 
 627     L68_ (
 628       // History registers
 629       // IHRRS; AL39 pg 47
 630       // History register lock control. If this bit is set ON, set STROBE ยข
 631       // (bit 30, key k) OFF, locking the history registers for all faults
 632       // including the floating faults.
 633       CPTUR (cptUseMR);
 634       if (cpu.MR.emr && cpu.MR.ihrrs)
 635         {
 636           cpu.MR.ihr = 0;
 637         }
 638     )
 639     DPS8M_ (
 640       // History registers
 641       // IHRRS; AL39 pg 49
 642       // Additional resetting of bit 30. If bit 31 = 1, the following faults also
 643       // reset bit 30:
 644       //   Lock Up
 645       //   Parity
 646       //   Command
 647       //   Store
 648       //   Illegal Procedure
 649       //   Shutdown
 650       if (cpu.MR.emr && cpu.MR.ihrrs)
 651         {
 652           if (faultNumber == FAULT_LUF ||
 653               faultNumber == FAULT_PAR ||
 654               faultNumber == FAULT_CMD ||
 655               faultNumber == FAULT_STR ||
 656               faultNumber == FAULT_IPR ||
 657               faultNumber == FAULT_SDF)
 658             {
 659               cpu.MR.ihr = 0;
 660             }
 661         }
 662       // Enable History Registers.  This bit will be reset by ... an Op Not
 663       // Complete fault. It may be reset by other faults (see bit 31).
 664       if (faultNumber == FAULT_ONC)
 665         {
 666           cpu.MR.ihr = 0;
 667         }
 668     )
 669 
 670     // If already in a FAULT CYCLE then signal trouble fault
 671 
 672     if (cpu.cycle == FAULT_EXEC_cycle)
 673       {
 674         sim_debug (DBG_CYCLE, & cpu_dev, "Changing fault number to Trouble fault\n");
 675 
 676         cpu.faultNumber   = FAULT_TRB;
 677         cpu.cu.FI_ADDR    = FAULT_TRB;
 678         cpu.subFault.bits = 0; // XXX ???
 679         if (cpu.bTroubleFaultCycle)
 680           {
 681 #if !defined(THREADZ) && !defined(LOCKLESS)
 682 # if !defined(PANEL68)
 683 #  if !defined(ROUND_ROBIN)
 684             if ((! sample_interrupts (cpup)) &&
 685                 (sim_qcount () == 0))  // XXX If clk_svc is implemented it will
 686                                        // break this logic
 687               {
 688                 sim_printf \
 689                     ("Fault cascade @0%06o with no interrupts pending and no events in queue\n",
 690                      cpu.PPR.IC);
 691                 sim_printf("\nCycles = %"PRId64"\n", cpu.cycleCnt);
 692                 sim_printf("\nInstructions = %"PRId64"\n", cpu.instrCnt);
 693                 //stop_reason = STOP_FLT_CASCADE;
 694                 longjmp (cpu.jmpMain, JMP_STOP);
 695               }
 696 #  endif /* if !defined(ROUND_ROBIN) */
 697 # endif /* if !defined(PANEL68) */
 698 #endif
 699           }
 700         else
 701           {
 702 //--            f = &_faults[FAULT_TRB];
 703             cpu . bTroubleFaultCycle = true;
 704           }
 705       }
 706     else
 707       {
 708         cpu . bTroubleFaultCycle = false;
 709       }
 710 
 711     // If doInstruction faults, the instruction cycle counter doesn't get
 712     // bumped.
 713     if (cpu . cycle == EXEC_cycle)
 714       cpu.instrCnt ++;
 715 
 716     cpu . cycle = FAULT_cycle;
 717     sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to FAULT_cycle\n");
 718     longjmp (cpu.jmpMain, JMP_REENTRY);
 719 #if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
 720     /*NOTREACHED*/ /* unreachable */
 721     abort(); /* not reached */
 722 #endif
 723 }
 724 
 725 void do_FFV_fault (cpu_state_t * cpup, uint fault_number, const char * fault_msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 726   {
 727     sim_debug (DBG_FAULT, & cpu_dev,
 728                "Floating fault %d '%s'\n",
 729                fault_number, fault_msg);
 730 #if !defined(SPEED)
 731     if_sim_debug (DBG_FAULT, & cpu_dev)
 732       traceInstruction (DBG_FAULT);
 733 #endif /* if !defined(SPEED) */
 734 
 735     if (fault_number < 1 || fault_number > 3)
 736       {
 737         sim_printf ("floating fault(out-of-range): %d '%s'\n",
 738                     fault_number, fault_msg ? fault_msg : "?");
 739         sim_warn ("fault out-of-range\n");
 740       }
 741 
 742     cpu.FFV_fault_number = fault_number;
 743     cpu.faultNumber      = fault_number;
 744 
 745     // "The occurrence of a fault or interrupt sets the
 746     // cache-to-register mode bit to OFF." a:AL39/cmr1
 747     CPTUR (cptUseCMR);
 748     cpu.CMR.csh_reg = 0;
 749 
 750     // Increment FCT
 751 
 752     word3 FCT = cpu.cu.APUCycleBits & MASK3;
 753     FCT = (FCT + 1) & MASK3;
 754     cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | FCT);
 755 
 756     // Set fault register bits
 757     CPTUR (cptUseFR);
 758     cpu.faultRegister [0] = 0;
 759 
 760     // Set cu word1 fault bits
 761 
 762     cpu.cu.IRO_ISN   = 0;
 763     cpu.cu.OEB_IOC   = 0;
 764     cpu.cu.EOFF_IAIM = 0;
 765     cpu.cu.ORB_ISP   = 0;
 766     cpu.cu.ROFF_IPR  = 0;
 767     cpu.cu.OWB_NEA   = 0;
 768     cpu.cu.WOFF_OOB  = 0;
 769     cpu.cu.NO_GA     = 0;
 770     cpu.cu.OCB       = 0;
 771     cpu.cu.OCALL     = 0;
 772     cpu.cu.BOC       = 0;
 773 // FFVs are L68 only, so we don't need this:
 774 //# if defined(DPS8M)
 775   //cpu.cu.PTWAM_ER  = 0;
 776 //# endif /* if defined(DPS8M) */
 777     cpu.cu.CRT       = 0;
 778     cpu.cu.RALR      = 0;
 779     cpu.cu.SDWAM_ER  = 0;
 780     cpu.cu.OOSB      = 0;
 781     cpu.cu.PARU      = 0;
 782     cpu.cu.PARL      = 0;
 783     cpu.cu.ONC1      = 0;
 784     cpu.cu.ONC2      = 0;
 785     cpu.cu.IA        = 0;
 786     cpu.cu.IACHN     = 0;
 787     cpu.cu.CNCHN     = 0;
 788 
 789     // Set control unit 'fault occurred during instruction fetch' flag
 790     cpu.cu.FIF       = 0;
 791     cpu.cu.FI_ADDR   = (word5) fault_number & MASK5;
 792 
 793     // XXX Under what conditions should this be set?
 794     // Assume no
 795     // Reading Multics source, it seems like Multics is setting this bit; I'm going
 796     // to assume that the h/w also sets it to 0, and the s/w has to explicitly set it on.
 797     cpu.cu.rfi = 0;
 798 
 799 // Try to decide if this a MIF fault (fault during EIS instruction)
 800 // EIS instructions are not used in fault/interrupt pairs, so the
 801 // only time an EIS instruction could be executing is during EXEC_cycle.
 802 // I am also assuming that only multi-word EIS instructions are of interest.
 803 
 804     SC_I_MIF (cpu.cycle == EXEC_cycle &&
 805         cpu.currentInstruction.info->ndes > 0);
 806     sim_debug (DBG_TRACEEXT, & cpu_dev, "MIF %o\n", TST_I_MIF);
 807 
 808 
 809     // History registers
 810     // IHRRS; AL39 pg 47
 811     // History register lock control. If this bit is set ON, set STROBE ยข
 812     // (bit 30, key k) OFF, locking the history registers for all faults
 813     // including the floating faults.
 814     CPTUR (cptUseMR);
 815     if (cpu.MR.emr && cpu.MR.ihrrs)
 816       {
 817         cpu.MR.ihr = 0;
 818       }
 819 
 820     if (cpu.cycle == FAULT_EXEC_cycle)
 821       {
 822         cpu.faultNumber   = FAULT_TRB;
 823         cpu.cu.FI_ADDR    = FAULT_TRB;
 824         cpu.subFault.bits = 0; // XXX ???
 825         if (cpu.bTroubleFaultCycle)
 826           {
 827 #if !defined(THREADZ) && !defined(LOCKLESS)
 828 # if !defined(PANEL68)
 829 #  if !defined(ROUND_ROBIN)
 830             if ((! sample_interrupts (cpup)) &&
 831                 (sim_qcount () == 0))  // XXX If clk_svc is implemented it will
 832                                        // break this logic
 833               {
 834                 sim_printf \
 835                     ("Fault cascade @0%06o with no interrupts pending and no events in queue\n",
 836                      cpu.PPR.IC);
 837                 sim_printf("\nCycles = %"PRId64"\n", cpu.cycleCnt);
 838                 sim_printf("\nInstructions = %"PRId64"\n", cpu.instrCnt);
 839                 longjmp (cpu.jmpMain, JMP_STOP);
 840               }
 841 #  endif /* if !defined(ROUND_ROBIN) */
 842 # endif /* if !defined(PANEL68) */
 843 #endif /* if !defined(THREADZ) && !defined(LOCKLESS) */
 844           }
 845         else
 846           {
 847             cpu.bTroubleFaultCycle = true;
 848           }
 849         cpu.cycle = FAULT_cycle;
 850         sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to FAULT_cycle\n");
 851         longjmp (cpu.jmpMain, JMP_REENTRY);
 852       }
 853     cpu.bTroubleFaultCycle = false;
 854 
 855     // If doInstruction faults, the instruction cycle counter doesn't get
 856     // bumped.
 857     if (cpu . cycle == EXEC_cycle)
 858       cpu.instrCnt ++;
 859 
 860     cpu.is_FFV = true;
 861     cpu.cycle  = FAULT_cycle;
 862     longjmp (cpu.jmpMain, JMP_REENTRY);
 863 }
 864 
 865 void dlyDoFault (_fault faultNumber, _fault_subtype subFault,
     /* [previous][next][first][last][top][bottom][index][help] */
 866                 const char * faultMsg)
 867   {
 868     cpu_state_t * cpup = _cpup;
 869     cpu.dlyFlt       = true;
 870     cpu.dlyFltNum    = faultNumber;
 871     cpu.dlySubFltNum = subFault;
 872     cpu.dlyCtx       = faultMsg;
 873   }
 874 
 875 //
 876 // return true if group 7 faults are pending ...
 877 //
 878 
 879 // Note: The DIS code assumes that the only G7 fault is TRO. Adding any
 880 // other G7 faults will potentially require changing the DIS code.
 881 
 882 bool bG7Pending (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 883   {
 884     if (cpu.tweaks.l68_mode)
 885       return cpu.g7Faults != 0 || cpu.FFV_faults != 0; // L68
 886 
 887     return cpu.g7Faults != 0; // DPS8M
 888   }
 889 
 890 bool bG7PendingNoTRO (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 891   {
 892     if (cpu.tweaks.l68_mode)
 893       return (cpu.g7Faults & (~ (1u << FAULT_TRO))) != 0 || cpu.FFV_faults != 0; // L68
 894 
 895     return (cpu.g7Faults & (~ (1u << FAULT_TRO))) != 0; // DPS8M
 896   }
 897 
 898 void setG7fault (uint cpuNo, _fault faultNo)
     /* [previous][next][first][last][top][bottom][index][help] */
 899   {
 900     cpu_state_t * cpup = &cpus[cpuNo];
 901     sim_debug (DBG_FAULT, & cpu_dev, "setG7fault CPU %d fault %d (%o)\n",
 902                cpuNo, faultNo, faultNo);
 903 #if defined(THREADZ) || defined(LOCKLESS)
 904     //__atomic_or_fetch (& cpup->g7FaultsPreset, (1u << faultNo), __ATOMIC_ACQUIRE);
 905     (void)atomic_fetch_or_explicit(&cpup->g7FaultsPreset, (1u << faultNo), memory_order_acquire);
 906 #else
 907     cpup->g7FaultsPreset |= (1u << faultNo);
 908 #endif
 909 #if defined(THREADZ) || defined(LOCKLESS)
 910     if (cpuNo != current_running_cpu_idx)
 911       wakeCPU(cpuNo);
 912 #endif
 913   }
 914 
 915 void set_FFV_fault (cpu_state_t * cpup, uint f_fault_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 916   {
 917     sim_debug (DBG_FAULT, & cpu_dev, "set_FFV_fault CPU f_fault_no %u\n",
 918                f_fault_no);
 919     // Map fault number (2/4/6) to bit mask  01/02/04
 920     cpu.FFV_faults_preset |= 1u << ((f_fault_no / 2) - 1);
 921   }
 922 
 923 void clearTROFault (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 924   {
 925     cpu . g7Faults &= ~(1u << FAULT_TRO);
 926   }
 927 
 928 void doG7Fault (cpu_state_t * cpup, bool allowTR)
     /* [previous][next][first][last][top][bottom][index][help] */
 929   {
 930     // sim_printf ("doG7fault %08o [%"PRId64"]\n", cpu . g7Faults, cpu.cycleCnt);
 931     // if (cpu . g7Faults)
 932       // {
 933         // sim_debug (DBG_FAULT, & cpu_dev, "doG7Fault %08o\n", cpu . g7Faults);
 934       // }
 935     // According AL39,  Table 7-1. List of Faults, priority of connect is 25
 936     // and priority of Timer runout is 26, lower number means higher priority
 937 #if defined(THREADZ) || defined(LOCKLESS)
 938     lock_scu ();
 939 #endif
 940      if (cpu.g7Faults & (1u << FAULT_CON))
 941        {
 942          cpu.g7Faults &= ~(1u << FAULT_CON);
 943 
 944 #if defined(THREADZ) || defined(LOCKLESS)
 945          unlock_scu ();
 946 #endif
 947          doFault (FAULT_CON, fst_zero, "Connect");
 948        }
 949 
 950      if (allowTR && (cpu.g7Faults & (1u << FAULT_TRO)))
 951        {
 952          cpu . g7Faults &= ~(1u << FAULT_TRO);
 953 
 954          //sim_printf("timer runout %12o\n",cpu.PPR.IC);
 955 #if defined(THREADZ) || defined(LOCKLESS)
 956          unlock_scu ();
 957 #endif
 958          doFault (FAULT_TRO, fst_zero, "Timer runout");
 959        }
 960 
 961      // Strictly speaking EXF isn't a G7 fault, but if we treat is as one,
 962      // we are allowing the current instruction to complete, simplifying
 963      // implementation
 964      if (cpu . g7Faults & (1u << FAULT_EXF))
 965        {
 966          cpu . g7Faults &= ~(1u << FAULT_EXF);
 967 
 968 #if defined(THREADZ) || defined(LOCKLESS)
 969          unlock_scu ();
 970 #endif
 971          doFault (FAULT_EXF, fst_zero, "Execute fault");
 972        }
 973 
 974      if (cpu.tweaks.l68_mode) {  // L68
 975        if (cpu.FFV_faults & 1u)  // FFV + 2 OC TRAP
 976          {
 977            cpu.FFV_faults &= ~1u;
 978 #if defined(THREADZ) || defined(LOCKLESS)
 979            unlock_scu ();
 980 #endif
 981            do_FFV_fault (cpup, 1, "OC TRAP");
 982          }
 983        if (cpu.FFV_faults & 2u)  // FFV + 4 CU HISTORY OVERFLOW TRAP
 984          {
 985            cpu.FFV_faults &= ~2u;
 986 #if defined(THREADZ) || defined(LOCKLESS)
 987            unlock_scu ();
 988 #endif
 989            do_FFV_fault (cpup, 2, "CU HIST OVF TRAP");
 990          }
 991        if (cpu.FFV_faults & 4u)  // FFV + 6 ADR TRAP
 992          {
 993            cpu.FFV_faults &= ~4u;
 994 #if defined(THREADZ) || defined(LOCKLESS)
 995            unlock_scu ();
 996 #endif
 997            do_FFV_fault (cpup, 3, "ADR TRAP");
 998          }
 999      }
1000 #if defined(THREADZ) || defined(LOCKLESS)
1001      unlock_scu ();
1002 #endif
1003      doFault (FAULT_TRB, (_fault_subtype) {.bits=cpu.g7Faults}, "Dazed and confused in doG7Fault");
1004   }
1005 
1006 void advanceG7Faults (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
1007   {
1008 // This is potentially stale cached, but we don't care, we will see eventually ZZZ
1009     if (!cpu.g7FaultsPreset && !cpu.FFV_faults_preset)
1010       return;
1011 
1012 #if defined(THREADZ) || defined(LOCKLESS)
1013     lock_scu ();
1014     uint zero = 0;
1015     //__atomic_exchange (& cpu.g7FaultsPreset, & zero, & cpu.g7Faults, __ATOMIC_ACQUIRE);
1016     cpu.g7Faults = atomic_exchange_explicit(&cpu.g7FaultsPreset, zero, memory_order_acquire);
1017 #else
1018     cpu.g7Faults       |= cpu.g7FaultsPreset;
1019     cpu.g7FaultsPreset  = 0;
1020 #endif
1021     L68_ (
1022       cpu.FFV_faults |= cpu.FFV_faults_preset;
1023       cpu.FFV_faults_preset = 0;
1024     )
1025 #if defined(THREADZ) || defined(LOCKLESS)
1026     unlock_scu ();
1027 #endif
1028   }

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