root/src/dps8/dps8_append.c

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

DEFINITIONS

This source file includes following definitions.
  1. selftest_ptwaw
  2. do_ldbr
  3. fetch_dsptw
  4. modify_dsptw
  5. calc_hit_am
  6. fetch_sdw_from_sdwam
  7. fetch_psdw
  8. fetch_nsdw
  9. str_sdw
  10. dump_sdwam
  11. to_be_discarded_am
  12. load_sdwam
  13. fetch_ptw_from_ptwam
  14. fetch_ptw
  15. loadPTWAM
  16. modify_ptw
  17. do_ptw2
  18. str_access_type
  19. str_acv
  20. str_pct
  21. do_append_cycle
  22. do_append_cycle
  23. dbgLookupAddress

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * SPDX-License-Identifier: Multics
   5  * scspell-id: 4bc3e31c-f62d-11ec-bf00-80ee73e9b8e7
   6  *
   7  * ---------------------------------------------------------------------------
   8  *
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2022 Charles Anthony
  11  * Copyright (c) 2017 Michal Tomek
  12  * Copyright (c) 2021-2024 The DPS8M Development Team
  13  *
  14  * This software is made available under the terms of the ICU License.
  15  * See the LICENSE.md file at the top-level directory of this distribution.
  16  *
  17  * ---------------------------------------------------------------------------
  18  *
  19  * This source file may contain code comments that adapt, include, and/or
  20  * incorporate Multics program code and/or documentation distributed under
  21  * the Multics License.  In the event of any discrepancy between code
  22  * comments herein and the original Multics materials, the original Multics
  23  * materials should be considered authoritative unless otherwise noted.
  24  * For more details and historical background, see the LICENSE.md file at
  25  * the top-level directory of this distribution.
  26  *
  27  * ---------------------------------------------------------------------------
  28  */
  29 
  30 #include <stdio.h>
  31 #include "dps8.h"
  32 #include "dps8_sys.h"
  33 #include "dps8_iom.h"
  34 #include "dps8_cable.h"
  35 #include "dps8_cpu.h"
  36 #include "dps8_addrmods.h"
  37 #include "dps8_faults.h"
  38 #include "dps8_scu.h"
  39 #include "dps8_append.h"
  40 #include "dps8_utils.h"
  41 #if defined(THREADZ) || defined(LOCKLESS)
  42 # include "threadz.h"
  43 #endif
  44 
  45 #define DBG_CTR cpu.cycleCnt
  46 
  47 /*
  48  * The appending unit ...
  49  */
  50 
  51 #if defined(TESTING)
  52 # define DBG_CTR cpu.cycleCnt
  53 # define DBGAPP(...) sim_debug (DBG_APPENDING, & cpu_dev, __VA_ARGS__)
  54 #else
  55 # define DBGAPP(...)
  56 #endif /* if defined(TESTING) */
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 #if defined(TESTING)
 115 static char *str_sdw (char * buf, sdw_s *SDW);
 116 #endif /* if defined(TESTING) */
 117 
 118 //
 119 //
 120 //  The Use of Bit 29 in the Instruction Word
 121 //  The reader is reminded that there is a preliminary step of loading TPR.CA
 122 //  with the ADDRESS field of the instruction word during instruction decode.
 123 //  If bit 29 of the instruction word is set to 1, modification by pointer
 124 //  register is invoked and the preliminary step is executed as follows:
 125 //  1. The ADDRESS field of the instruction word is interpreted as shown in
 126 //  Figure 6-7 below.
 127 //  2. C(PRn.SNR) -> C(TPR.TSR)
 128 //  3. maximum of ( C(PRn.RNR), C(TPR.TRR), C(PPR.PRR) ) -> C(TPR.TRR)
 129 //  4. C(PRn.WORDNO) + OFFSET -> C(TPR.CA) (NOTE: OFFSET is a signed binary
 130 //  number.)
 131 //  5. C(PRn.BITNO) -> TPR.BITNO
 132 //
 133 
 134 // Define this to do error detection on the PTWAM table.
 135 // Useful if PTWAM reports an error message, but it slows the emulator
 136 // down 50%
 137 
 138 #if defined(do_selftestPTWAM)
 139 static void selftest_ptwaw (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 140   {
 141     int usages[N_NAX_WAM_ENTRIES];
 142     for (int i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
 143       usages[i] = -1;
 144 
 145     for (int i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
 146       {
 147         ptw_s * p = cpu.PTWAM + i;
 148         if (p->USE > N_MODEL_WAM_ENTRIES - 1)
 149           sim_printf ("PTWAM[%d].USE is %d; > %d!\n",
 150                       i, p->USE, N_MODEL_WAM_ENTRIES - 1);
 151         if (usages[p->USE] != -1)
 152           sim_printf ("PTWAM[%d].USE is equal to PTWAM[%d].USE; %d\n",
 153                       i, usages[p->USE], p->USE);
 154         usages[p->USE] = i;
 155       }
 156     for (int i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
 157       {
 158         if (usages[i] == -1)
 159           sim_printf ("No PTWAM had a USE of %d\n", i);
 160       }
 161   }
 162 #endif /* if defined(do_selftestPTWAM) */
 163 
 164 /*
 165  * implement ldbr instruction
 166  */
 167 
 168 void do_ldbr (cpu_state_t * cpup, word36 * Ypair)
     /* [previous][next][first][last][top][bottom][index][help] */
 169   {
 170     CPTUR (cptUseDSBR);
 171     if (cpu.tweaks.enable_wam)
 172       {
 173         if (cpu.cu.SD_ON)
 174           {
 175             // If SDWAM is enabled, then
 176             //   0 -> C(SDWAM(i).FULL) for i = 0, 1, ..., 15
 177             //   i -> C(SDWAM(i).USE) for i = 0, 1, ..., 15
 178             for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
 179               {
 180                 cpu.SDWAM[i].FE = 0;
 181                 L68_ (cpu.SDWAM[i].USE = (word4) i;)
 182                 DPS8M_ (cpu.SDWAM[i].USE = 0;)
 183               }
 184           }
 185 
 186         if (cpu.cu.PT_ON)
 187           {
 188             // If PTWAM is enabled, then
 189             //   0 -> C(PTWAM(i).FULL) for i = 0, 1, ..., 15
 190             //   i -> C(PTWAM(i).USE) for i = 0, 1, ..., 15
 191             for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
 192               {
 193                 cpu.PTWAM[i].FE = 0;
 194                 L68_ (cpu.PTWAM[i].USE = (word4) i;)
 195                 DPS8M_ (cpu.PTWAM[i].USE = 0;)
 196               }
 197 #if defined(do_selftestPTWAM)
 198             selftest_ptwaw ();
 199 #endif /* if defined(do_selftestPTWAM) */
 200           }
 201       }
 202     else
 203       {
 204         cpu.SDW0.FE  = 0;
 205         cpu.SDW0.USE = 0;
 206         cpu.PTW0.FE  = 0;
 207         cpu.PTW0.USE = 0;
 208       }
 209 
 210     // If cache is enabled, reset all cache column and level full flags
 211     // XXX no cache
 212 
 213     // C(Y-pair) 0,23 -> C(DSBR.ADDR)
 214     cpu.DSBR.ADDR  = (Ypair[0] >> (35 - 23)) & PAMASK;
 215 
 216     // C(Y-pair) 37,50 -> C(DSBR.BOUND)
 217     cpu.DSBR.BND   = (Ypair[1] >> (71 - 50)) & 037777;
 218 
 219     // C(Y-pair) 55 -> C(DSBR.U)
 220     cpu.DSBR.U     = (Ypair[1] >> (71 - 55)) & 01;
 221 
 222     // C(Y-pair) 60,71 -> C(DSBR.STACK)
 223     cpu.DSBR.STACK = (Ypair[1] >> (71 - 71)) & 07777;
 224     DBGAPP ("ldbr 0 -> SDWAM/PTWAM[*].F, i -> SDWAM/PTWAM[i].USE, "
 225             "DSBR.ADDR 0%o, DSBR.BND 0%o, DSBR.U 0%o, DSBR.STACK 0%o\n",
 226             cpu.DSBR.ADDR, cpu.DSBR.BND, cpu.DSBR.U, cpu.DSBR.STACK);
 227   }
 228 
 229 /*
 230  * fetch descriptor segment PTW ...
 231  */
 232 
 233 // CANFAULT
 234 
 235 static void fetch_dsptw (cpu_state_t * cpup, word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
 236   {
 237     DBGAPP ("%s segno 0%o\n", __func__, segno);
 238     PNL (L68_ (cpu.apu.state |= apu_FDPT;))
 239 
 240     if (2 * segno >= 16 * (cpu.DSBR.BND + 1))
 241       {
 242         DBGAPP ("%s ACV15\n", __func__);
 243         // generate access violation, out of segment bounds fault
 244         PNL (cpu.acvFaults |= ACV15;)
 245         PNL (L68_ (cpu.apu.state |= apu_FLT;))
 246         doFault (FAULT_ACV, fst_acv15,
 247                  "acvFault: fetch_dsptw out of segment bounds fault");
 248       }
 249     set_apu_status (cpup, apuStatus_DSPTW);
 250 
 251     //word24 y1 = (2u * segno) % 1024u;
 252     word24 x1 = (2u * segno) / 1024u; // floor
 253 
 254     PNL (cpu.lastPTWOffset = segno;)
 255     PNL (cpu.lastPTWIsDS = true;)
 256 
 257     word36 PTWx1;
 258     core_read (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
 259 
 260     cpu.PTW0.ADDR = GETHI (PTWx1);
 261     cpu.PTW0.U    = TSTBIT (PTWx1, 9);
 262     cpu.PTW0.M    = TSTBIT (PTWx1, 6);
 263     cpu.PTW0.DF   = TSTBIT (PTWx1, 2);
 264     cpu.PTW0.FC   = PTWx1 & 3;
 265 
 266     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 267       add_l68_APU_history (cpup, APUH_FDSPTW);)
 268 
 269     DBGAPP ("%s x1 0%o DSBR.ADDR 0%o PTWx1 0%012"PRIo64" "
 270             "PTW0: ADDR 0%o U %o M %o F %o FC %o\n",
 271             __func__, x1, cpu.DSBR.ADDR, PTWx1, cpu.PTW0.ADDR, cpu.PTW0.U,
 272             cpu.PTW0.M, cpu.PTW0.DF, cpu.PTW0.FC);
 273   }
 274 
 275 /*
 276  * modify descriptor segment PTW (Set U=1) ...
 277  */
 278 
 279 // CANFAULT
 280 
 281 static void modify_dsptw (cpu_state_t * cpup, word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
 282   {
 283     PNL (L68_ (cpu.apu.state |= apu_MDPT;))
 284 
 285     set_apu_status (cpup, apuStatus_MDSPTW);
 286 
 287     word24 x1 = (2u * segno) / 1024u; // floor
 288 
 289 #if defined(THREADZ)
 290     bool lck = get_rmw_lock ();
 291     if (! lck)
 292       lock_rmw ();
 293 #endif /* if defined(THREADZ) */
 294 
 295     word36 PTWx1;
 296 #if defined(LOCKLESS)
 297     core_read_lock (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
 298     PTWx1 = SETBIT (PTWx1, 9);
 299     core_write_unlock (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, PTWx1, __func__);
 300 #else
 301     core_read (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
 302     PTWx1 = SETBIT (PTWx1, 9);
 303     core_write (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, PTWx1, __func__);
 304 #endif /* if defined(LOCKLESS) */
 305 
 306 #if defined(THREADZ)
 307     if (! lck)
 308       unlock_rmw ();
 309 #endif /* if defined(THREADZ) */
 310 
 311     cpu.PTW0.U = 1;
 312     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 313       add_l68_APU_history (cpup, APUH_MDSPTW);)
 314   }
 315 
 316 static word6 calc_hit_am (word6 LRU, uint hit_level)
     /* [previous][next][first][last][top][bottom][index][help] */
 317   {
 318 #if defined(TESTING)
 319     cpu_state_t * cpup = _cpup;
 320 #endif
 321     switch (hit_level)
 322       {
 323         case 0:  // hit level A
 324           return (LRU | 070);
 325         case 1:  // hit level B
 326           return ((LRU & 037) | 06);
 327         case 2:  // hit level C
 328           return ((LRU & 053) | 01);
 329         case 3:  // hit level D
 330           return (LRU & 064);
 331         default:
 332           DBGAPP ("%s: Invalid AM level\n", __func__);
 333           return 0;
 334      }
 335   }
 336 
 337 static sdw_s * fetch_sdw_from_sdwam (cpu_state_t * cpup, word15 segno) {
     /* [previous][next][first][last][top][bottom][index][help] */
 338   DBGAPP ("%s(0):segno=%05o\n", __func__, segno);
 339 
 340   if ((! cpu.tweaks.enable_wam || ! cpu.cu.SD_ON)) {
 341     DBGAPP ("%s(0): SDWAM disabled\n", __func__);
 342     return NULL;
 343   }
 344 
 345   if (cpu.tweaks.l68_mode) { // L68
 346     int nwam = N_L68_WAM_ENTRIES;
 347     for (int _n = 0; _n < nwam; _n++) {
 348       // make certain we initialize SDWAM prior to use!!!
 349       if (cpu.SDWAM[_n].FE && segno == cpu.SDWAM[_n].POINTER) {
 350         DBGAPP ("%s(1):found match for segno %05o " "at _n=%d\n", __func__, segno, _n);
 351 
 352         cpu.cu.SDWAMM = 1;
 353         cpu.SDWAMR = (word4) _n;
 354         cpu.SDW = & cpu.SDWAM[_n];
 355 
 356         // If the SDWAM match logic circuitry indicates a hit, all usage
 357         // counts (SDWAM.USE) greater than the usage count of the register
 358         // hit are decremented by one, the usage count of the register hit
 359         // is set to 15, and the contents of the register hit are read out
 360         // into the address preparation circuitry.
 361 
 362         for (int _h = 0; _h < nwam; _h++) {
 363           if (cpu.SDWAM[_h].USE > cpu.SDW->USE)
 364             cpu.SDWAM[_h].USE -= 1;
 365         }
 366         cpu.SDW->USE = N_L68_WAM_ENTRIES - 1;
 367 
 368         char buf[256];
 369         (void)buf;
 370 #if defined(TESTING)
 371         DBGAPP ("%s(2):SDWAM[%d]=%s\n", __func__, _n, str_sdw (buf, cpu.SDW));
 372 #endif /* if defined(TESTING) */
 373         return cpu.SDW;
 374       }
 375     }
 376   }
 377 
 378   if (! cpu.tweaks.l68_mode) { // DPS8M
 379     uint setno = segno & 017;
 380     uint toffset;
 381     sdw_s *p;
 382     for (toffset = 0; toffset < 64; toffset += 16) {
 383       p = & cpu.SDWAM[toffset + setno];
 384       if (p->FE && segno == p->POINTER) {
 385         DBGAPP ("%s(1):found match for segno %05o " "at _n=%d\n", __func__, segno, toffset + setno);
 386 
 387         cpu.cu.SDWAMM = 1;
 388         cpu.SDWAMR = (word6) (toffset + setno);
 389         cpu.SDW = p; // export pointer for appending
 390 
 391         word6 u = calc_hit_am (p->USE, toffset >> 4);
 392         for (toffset = 0; toffset < 64; toffset += 16) { // update LRU
 393           p = & cpu.SDWAM[toffset + setno];
 394           if (p->FE)
 395             p->USE = u;
 396         }
 397 
 398         char buf[256];
 399         (void)buf;
 400 #if defined(TESTING)
 401         DBGAPP ("%s(2):SDWAM[%d]=%s\n", __func__, toffset + setno, str_sdw (buf, cpu.SDW));
 402 #endif /* if defined(TESTING) */
 403         return cpu.SDW;
 404       }
 405     }
 406   }
 407 #if defined(TESTING)
 408   DBGAPP ("%s(3):SDW for segment %05o not found in SDWAM\n", __func__, segno);
 409 #endif /* if defined(TESTING) */
 410   cpu.cu.SDWAMM = 0;
 411   return NULL;    // segment not referenced in SDWAM
 412 }
 413 
 414 /*
 415  * Fetches an SDW from a paged descriptor segment.
 416  */
 417 // CANFAULT
 418 
 419 static void fetch_psdw (cpu_state_t * cpup, word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
 420   {
 421     DBGAPP ("%s(0):segno=%05o\n",
 422             __func__, segno);
 423 
 424     PNL (L68_ (cpu.apu.state |= apu_FSDP;))
 425 
 426     set_apu_status (cpup, apuStatus_SDWP);
 427     word24 y1 = (2 * segno) % 1024;
 428 
 429     word36 SDWeven, SDWodd;
 430 
 431     core_read2 (cpup, ((((word24) cpu.PTW0.ADDR & 0777760) << 6) + y1) & PAMASK,
 432                 & SDWeven, & SDWodd, __func__);
 433 
 434     // even word
 435     cpu.SDW0.ADDR  = (SDWeven >> 12) & 077777777;
 436     cpu.SDW0.R1    = (SDWeven >> 9)  & 7;
 437     cpu.SDW0.R2    = (SDWeven >> 6)  & 7;
 438     cpu.SDW0.R3    = (SDWeven >> 3)  & 7;
 439     cpu.SDW0.DF    = TSTBIT (SDWeven, 2);
 440     cpu.SDW0.FC    = SDWeven & 3;
 441 
 442     // odd word
 443     cpu.SDW0.BOUND = (SDWodd >> 21) & 037777;
 444     cpu.SDW0.R     = TSTBIT (SDWodd, 20);
 445     cpu.SDW0.E     = TSTBIT (SDWodd, 19);
 446     cpu.SDW0.W     = TSTBIT (SDWodd, 18);
 447     cpu.SDW0.P     = TSTBIT (SDWodd, 17);
 448     cpu.SDW0.U     = TSTBIT (SDWodd, 16);
 449     cpu.SDW0.G     = TSTBIT (SDWodd, 15);
 450     cpu.SDW0.C     = TSTBIT (SDWodd, 14);
 451     cpu.SDW0.EB    = SDWodd & 037777;
 452 
 453     L68_ (
 454       if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 455         add_l68_APU_history (cpup, APUH_FSDWP);
 456      )
 457     DBGAPP ("%s y1 0%o p->ADDR 0%o SDW 0%012"PRIo64" 0%012"PRIo64" "
 458             "ADDR %o R %o%o%o BOUND 0%o REWPUGC %o%o%o%o%o%o%o "
 459             "F %o FC %o FE %o USE %o\n",
 460             __func__, y1, cpu.PTW0.ADDR, SDWeven, SDWodd, cpu.SDW0.ADDR,
 461             cpu.SDW0.R1, cpu.SDW0.R2, cpu.SDW0.R3, cpu.SDW0.BOUND,
 462             cpu.SDW0.R, cpu.SDW0.E, cpu.SDW0.W, cpu.SDW0.P, cpu.SDW0.U,
 463             cpu.SDW0.G, cpu.SDW0.C, cpu.SDW0.DF, cpu.SDW0.FC, cpu.SDW0.FE,
 464             cpu.SDW0.USE);
 465   }
 466 
 467 // Nonpaged SDW Fetch
 468 // Fetches an SDW from an unpaged descriptor segment.
 469 // CANFAULT
 470 
 471 static void fetch_nsdw (cpu_state_t * cpup, word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
 472   {
 473     DBGAPP ("%s (0):segno=%05o\n", __func__, segno);
 474 
 475     PNL (L68_ (cpu.apu.state |= apu_FSDN;))
 476 
 477     set_apu_status (cpup, apuStatus_SDWNP);
 478 
 479     if (2 * segno >= 16 * (cpu.DSBR.BND + 1))
 480       {
 481         DBGAPP ("%s (1):Access Violation, out of segment bounds for "
 482                 "segno=%05o DSBR.BND=%d\n",
 483                 __func__, segno, cpu.DSBR.BND);
 484         // generate access violation, out of segment bounds fault
 485         PNL (cpu.acvFaults |= ACV15;)
 486         PNL (L68_ (cpu.apu.state |= apu_FLT;))
 487         doFault (FAULT_ACV, fst_acv15,
 488                  "acvFault fetch_dsptw: out of segment bounds fault");
 489       }
 490     DBGAPP ("%s (2):fetching SDW from %05o\n",
 491             __func__, cpu.DSBR.ADDR + 2u * segno);
 492 
 493     word36 SDWeven, SDWodd;
 494     core_read2 (cpup, (cpu.DSBR.ADDR + 2u * segno) & PAMASK,
 495                 & SDWeven, & SDWodd, __func__);
 496 
 497     // even word
 498     cpu.SDW0.ADDR = (SDWeven >> 12) & 077777777;
 499     cpu.SDW0.R1   = (SDWeven >> 9)  & 7;
 500     cpu.SDW0.R2   = (SDWeven >> 6)  & 7;
 501     cpu.SDW0.R3   = (SDWeven >> 3)  & 7;
 502     cpu.SDW0.DF   = TSTBIT (SDWeven, 2);
 503     cpu.SDW0.FC   = SDWeven & 3;
 504 
 505     // odd word
 506     cpu.SDW0.BOUND = (SDWodd >> 21) & 037777;
 507     cpu.SDW0.R     = TSTBIT (SDWodd, 20);
 508     cpu.SDW0.E     = TSTBIT (SDWodd, 19);
 509     cpu.SDW0.W     = TSTBIT (SDWodd, 18);
 510     cpu.SDW0.P     = TSTBIT (SDWodd, 17);
 511     cpu.SDW0.U     = TSTBIT (SDWodd, 16);
 512     cpu.SDW0.G     = TSTBIT (SDWodd, 15);
 513     cpu.SDW0.C     = TSTBIT (SDWodd, 14);
 514     cpu.SDW0.EB    = SDWodd & 037777;
 515 
 516     L68_ (
 517       if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 518         add_l68_APU_history (cpup, 0 /* No fetch no paged bit */);
 519     )
 520 #if !defined(SPEED)
 521     char buf[256];
 522     (void)buf;
 523     DBGAPP ("%s (2):SDW0=%s\n", __func__, str_SDW0 (buf, & cpu.SDW0));
 524 #endif /* if !defined(SPEED) */
 525   }
 526 
 527 #if defined(TESTING)
 528 static char *str_sdw (char * buf, sdw_s *SDW)
     /* [previous][next][first][last][top][bottom][index][help] */
 529   {
 530     if (! SDW->FE)
 531       (void)sprintf (buf, "*** SDW Uninitialized ***");
 532     else
 533       (void)sprintf (buf,
 534                      "ADDR:%06o R1:%o R2:%o R3:%o BOUND:%o R:%o E:%o W:%o P:%o "
 535                      "U:%o G:%o C:%o CL:%o DF:%o FC:%o POINTER=%o USE=%d",
 536                      SDW->ADDR,    SDW->R1, SDW->R2, SDW->R3, SDW->BOUND,
 537                      SDW->R,       SDW->E,  SDW->W,  SDW->P,  SDW->U,
 538                      SDW->G,       SDW->C,  SDW->EB, SDW->DF, SDW->FC,
 539                      SDW->POINTER, SDW->USE);
 540     return buf;
 541   }
 542 
 543 /*
 544  * dump SDWAM...
 545  */
 546 
 547 t_stat dump_sdwam (cpu_state_t * cpup)
     /* [previous][next][first][last][top][bottom][index][help] */
 548   {
 549     char buf[256];
 550     (void)buf;
 551     for (int _n = 0; _n < N_MODEL_WAM_ENTRIES; _n++)
 552       {
 553         sdw_s *p = & cpu.SDWAM[_n];
 554 
 555         if (p->FE)
 556           sim_printf ("SDWAM n:%d %s\n", _n, str_sdw (buf, p));
 557       }
 558     return SCPE_OK;
 559   }
 560 #endif /* if defined(TESTING) */
 561 
 562 static uint to_be_discarded_am (word6 LRU)
     /* [previous][next][first][last][top][bottom][index][help] */
 563   {
 564 
 565 
 566 
 567 
 568 
 569 
 570 
 571 
 572 
 573 
 574 
 575 
 576     if ((LRU & 070) == 070) return 0;
 577     if ((LRU & 046) == 006) return 1;
 578     if ((LRU & 025) == 001) return 2;
 579     return 3;
 580   }
 581 
 582 /*
 583  * load the current in-core SDW0 into the SDWAM ...
 584  */
 585 
 586 static void load_sdwam (cpu_state_t * cpup, word15 segno, bool nomatch)
     /* [previous][next][first][last][top][bottom][index][help] */
 587   {
 588     cpu.SDW0.POINTER = segno;
 589     cpu.SDW0.USE = 0;
 590 
 591     cpu.SDW0.FE = true;     // in use by SDWAM
 592 
 593     cpu.SDW = & cpu.SDW0;
 594 
 595     if (nomatch || (! cpu.tweaks.enable_wam) || (! cpu.cu.SD_ON))
 596       {
 597         DBGAPP ("%s: SDWAM disabled\n", __func__);
 598         return;
 599       }
 600 
 601     if (cpu.tweaks.l68_mode) { // L68
 602       // If the SDWAM match logic does not indicate a hit, the SDW is fetched
 603       // from the descriptor segment in main memory and loaded into the SDWAM
 604       // register with usage count 0 (the oldest), all usage counts are
 605       // decremented by one with the newly loaded register rolling over from 0 to
 606       // 15, and the newly loaded register is read out into the address
 607       // preparation circuitry.
 608 
 609       for (int _n = 0; _n < N_L68_WAM_ENTRIES; _n++) {
 610         sdw_s * p = & cpu.SDWAM[_n];
 611         if (! p->FE || p->USE == 0) {
 612           DBGAPP ("%s(1):SDWAM[%d] FE=0 || USE=0\n", __func__, _n);
 613 
 614           * p = cpu.SDW0;
 615           p->POINTER = segno;
 616           p->USE = 0;
 617           p->FE = true;     // in use by SDWAM
 618 
 619           for (int _h = 0; _h < N_L68_WAM_ENTRIES; _h++) {
 620             sdw_s * q = & cpu.SDWAM[_h];
 621             q->USE -= 1;
 622             q->USE &= N_L68_WAM_MASK;
 623           }
 624 
 625           cpu.SDW = p;
 626 
 627           char buf[256];
 628           (void) buf;
 629 #if defined(TESTING)
 630           DBGAPP ("%s(2):SDWAM[%d]=%s\n", __func__, _n, str_sdw (buf, p));
 631 #endif /* if defined(TESTING) */
 632           return;
 633         }
 634       }
 635       // if we reach this, USE is scrambled
 636 #if defined(TESTING)
 637       DBGAPP ("%s(3) no USE=0 found for segment=%d\n", __func__, segno);
 638       sim_printf ("%s(%05o): no USE=0 found!\n", __func__, segno);
 639       dump_sdwam (cpup);
 640 #endif /* if defined(TESTING) */
 641     }
 642 
 643     if (! cpu.tweaks.l68_mode) { // DPS8M
 644       uint setno = segno & 017;
 645       uint toffset;
 646       sdw_s *p;
 647       for (toffset = 0; toffset < 64; toffset += 16) {
 648         p = & cpu.SDWAM[toffset + setno];
 649         if (!p->FE)
 650           break;
 651       }
 652       if (toffset == 64) { // all FE==1
 653         toffset = to_be_discarded_am (p->USE) << 4;
 654         p = & cpu.SDWAM[toffset + setno];
 655       }
 656       DBGAPP ("%s(1):SDWAM[%d] FE=0 || LRU\n", __func__, toffset + setno);
 657 
 658       word6 u = calc_hit_am (p->USE, toffset >> 4); // before loading the SDWAM!
 659       * p = cpu.SDW0; // load the SDW
 660       p->POINTER = segno;
 661       p->FE = true;  // in use
 662       cpu.SDW = p; // export pointer for appending
 663 
 664       for (uint toffset1 = 0; toffset1 < 64; toffset1 += 16) { // update LRU
 665         p = & cpu.SDWAM[toffset1 + setno];
 666         if (p->FE)
 667           p->USE = u;
 668       }
 669 
 670       char buf[256];
 671       (void) buf;
 672 #if defined(TESTING)
 673       DBGAPP ("%s(2):SDWAM[%d]=%s\n", __func__, toffset + setno, str_sdw (buf, cpu.SDW));
 674 #endif /* if defined(TESTING) */
 675     } // DPS8M
 676   }
 677 
 678 static ptw_s * fetch_ptw_from_ptwam (cpu_state_t * cpup, word15 segno, word18 CA)
     /* [previous][next][first][last][top][bottom][index][help] */
 679   {
 680     if ((! cpu.tweaks.enable_wam) || (! cpu.cu.PT_ON))
 681       {
 682         DBGAPP ("%s: PTWAM disabled\n", __func__);
 683         return NULL;
 684       }
 685 
 686     if (cpu.tweaks.l68_mode) { // L68
 687       int nwam = N_L68_WAM_ENTRIES;
 688       for (int _n = 0; _n < nwam; _n++)
 689         {
 690           if (cpu.PTWAM[_n].FE && ((CA >> 6) & 07760) == cpu.PTWAM[_n].PAGENO &&
 691               cpu.PTWAM[_n].POINTER == segno)   //_initialized
 692             {
 693               DBGAPP ("%s: found match for segno=%o pageno=%o "
 694                       "at _n=%d\n",
 695                       __func__, segno, cpu.PTWAM[_n].PAGENO, _n);
 696               cpu.cu.PTWAMM = 1;
 697               cpu.PTWAMR = (word4) _n;
 698               cpu.PTW = & cpu.PTWAM[_n];
 699 
 700               // If the PTWAM match logic circuitry indicates a hit, all usage
 701               // counts (PTWAM.USE) greater than the usage count of the register
 702               // hit are decremented by one, the usage count of the register hit
 703               // is set to 15, and the contents of the register hit are read out
 704               // into the address preparation circuitry.
 705 
 706               for (int _h = 0; _h < nwam; _h++)
 707                 {
 708                   if (cpu.PTWAM[_h].USE > cpu.PTW->USE)
 709                     cpu.PTWAM[_h].USE -= 1; //PTW->USE -= 1;
 710                 }
 711               cpu.PTW->USE = N_L68_WAM_ENTRIES - 1;
 712 #if defined(do_selftestPTWAM)
 713               selftest_ptwaw ();
 714 #endif /* if defined(do_selftestPTWAM) */
 715               DBGAPP ("%s: ADDR 0%o U %o M %o F %o FC %o\n",
 716                       __func__, cpu.PTW->ADDR, cpu.PTW->U, cpu.PTW->M,
 717                       cpu.PTW->DF, cpu.PTW->FC);
 718               return cpu.PTW;
 719             }
 720         }
 721     }
 722 
 723     DPS8M_ (
 724       uint setno = (CA >> 10) & 017;
 725       uint toffset;
 726       ptw_s *p;
 727       for (toffset = 0; toffset < 64; toffset += 16)
 728         {
 729           p = & cpu.PTWAM[toffset + setno];
 730 
 731           if (p->FE && ((CA >> 6) & 07760) == p->PAGENO && p->POINTER == segno)
 732             {
 733               DBGAPP ("%s: found match for segno=%o pageno=%o "
 734                       "at _n=%d\n",
 735                       __func__, segno, p->PAGENO, toffset + setno);
 736               cpu.cu.PTWAMM = 1;
 737               cpu.PTWAMR = (word6) (toffset + setno);
 738               cpu.PTW = p; // export pointer for appending
 739 
 740               word6 u = calc_hit_am (p->USE, toffset >> 4);
 741               for (toffset = 0; toffset < 64; toffset += 16) // update LRU
 742                 {
 743                   p = & cpu.PTWAM[toffset + setno];
 744                   if (p->FE)
 745                     p->USE = u;
 746                 }
 747 
 748               DBGAPP ("%s: ADDR 0%o U %o M %o F %o FC %o\n",
 749                       __func__, cpu.PTW->ADDR, cpu.PTW->U, cpu.PTW->M,
 750                       cpu.PTW->DF, cpu.PTW->FC);
 751               return cpu.PTW;
 752             }
 753         }
 754      )
 755     cpu.cu.PTWAMM = 0;
 756     return NULL;    // page not referenced in PTWAM
 757   }
 758 
 759 static void fetch_ptw (cpu_state_t * cpup, sdw_s *sdw, word18 offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 760   {
 761     // AL39 p.5-7
 762     // Fetches a PTW from a page table other than a descriptor segment page
 763     // table and sets the page accessed bit (PTW.U)
 764     PNL (L68_ (cpu.apu.state |= apu_FPTW;))
 765     set_apu_status (cpup, apuStatus_PTW);
 766 
 767     //word24 y2 = offset % 1024;
 768     word24 x2 = (offset) / 1024; // floor
 769 
 770     word36 PTWx2;
 771 
 772     DBGAPP ("%s address %08o\n", __func__, sdw->ADDR + x2);
 773 
 774     PNL (cpu.lastPTWOffset = offset;)
 775     PNL (cpu.lastPTWIsDS = false;)
 776 
 777 #if defined(THREADZ)
 778     bool lck = get_rmw_lock ();
 779     if (! lck)
 780       lock_rmw ();
 781 #endif /* if defined(THREADZ) */
 782 #if defined(LOCKLESS)
 783     core_read_lock (cpup, (sdw->ADDR + x2) & PAMASK, & PTWx2, __func__);
 784 #else
 785     core_read (cpup, (sdw->ADDR + x2) & PAMASK, & PTWx2, __func__);
 786 #endif /* if defined(LOCKLESS) */
 787 
 788     cpu.PTW0.ADDR = GETHI  (PTWx2);
 789     cpu.PTW0.U    = TSTBIT (PTWx2, 9);
 790     cpu.PTW0.M    = TSTBIT (PTWx2, 6);
 791     cpu.PTW0.DF   = TSTBIT (PTWx2, 2);
 792     cpu.PTW0.FC   = PTWx2 & 3;
 793 
 794     // ISOLTS-861 02
 795 #if !defined(LOCKLESS)
 796     if (! cpu.PTW0.U)
 797 #endif /* if !defined(LOCKLESS) */
 798       {
 799         PTWx2 = SETBIT (PTWx2, 9);
 800 #if defined(LOCKLESS)
 801         core_write_unlock (cpup, (sdw->ADDR + x2) & PAMASK, PTWx2, __func__);
 802 #else
 803         core_write (cpup, (sdw->ADDR + x2) & PAMASK, PTWx2, __func__);
 804 #endif /* if defined(LOCKLESS) */
 805         cpu.PTW0.U = 1;
 806       }
 807 
 808 #if defined(THREADZ)
 809     if (! lck)
 810       unlock_rmw ();
 811 #endif /* if defined(THREADZ) */
 812 
 813     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 814       add_l68_APU_history (cpup, APUH_FPTW);)
 815 
 816     DBGAPP ("%s x2 0%o sdw->ADDR 0%o PTWx2 0%012"PRIo64" "
 817             "PTW0: ADDR 0%o U %o M %o F %o FC %o\n",
 818             __func__, x2, sdw->ADDR, PTWx2, cpu.PTW0.ADDR, cpu.PTW0.U,
 819             cpu.PTW0.M, cpu.PTW0.DF, cpu.PTW0.FC);
 820   }
 821 
 822 static void loadPTWAM (cpu_state_t * cpup, word15 segno, word18 offset, UNUSED bool nomatch)
     /* [previous][next][first][last][top][bottom][index][help] */
 823   {
 824     cpu.PTW0.PAGENO  = (offset >> 6) & 07760;
 825     cpu.PTW0.POINTER = segno;
 826     cpu.PTW0.USE     = 0;
 827     cpu.PTW0.FE      = true;
 828 
 829     cpu.PTW = & cpu.PTW0;
 830     if (nomatch || (! cpu.tweaks.enable_wam) || (! cpu.cu.PT_ON))
 831       {
 832         DBGAPP ("loadPTWAM: PTWAM disabled\n");
 833         return;
 834       }
 835 
 836     if (cpu.tweaks.l68_mode) { // L68
 837       // If the PTWAM match logic does not indicate a hit, the PTW is fetched
 838       // from main memory and loaded into the PTWAM register with usage count 0
 839       // (the oldest), all usage counts are decremented by one with the newly
 840       // loaded register rolling over from 0 to 15, and the newly loaded register
 841       // is read out into the address preparation circuitry.
 842 
 843       for (int _n = 0; _n < N_L68_WAM_ENTRIES; _n++)
 844         {
 845           ptw_s * p = & cpu.PTWAM[_n];
 846           if (! p->FE || p->USE == 0)
 847             {
 848               DBGAPP ("loadPTWAM(1):PTWAM[%d] FE=0 || USE=0\n", _n);
 849               *p = cpu.PTW0;
 850               p->PAGENO = (offset >> 6) & 07760;
 851               p->POINTER = segno;
 852               p->USE = 0;
 853               p->FE = true;
 854 
 855               for (int _h = 0; _h < N_L68_WAM_ENTRIES; _h++)
 856                 {
 857                   ptw_s * q = & cpu.PTWAM[_h];
 858                   q->USE -= 1;
 859                   q->USE &= N_L68_WAM_MASK;
 860                 }
 861 
 862               cpu.PTW = p;
 863               DBGAPP ("loadPTWAM(2): ADDR 0%o U %o M %o F %o FC %o "
 864                       "POINTER=%o PAGENO=%o USE=%d\n",
 865                       cpu.PTW->ADDR, cpu.PTW->U, cpu.PTW->M, cpu.PTW->DF,
 866                       cpu.PTW->FC, cpu.PTW->POINTER, cpu.PTW->PAGENO,
 867                       cpu.PTW->USE);
 868 #if defined(do_selftestPTWAM)
 869               selftest_ptwaw ();
 870 #endif /* if defined(do_selftestPTWAM) */
 871               return;
 872             }
 873         }
 874       // if we reach this, USE is scrambled
 875       sim_printf ("loadPTWAM(segno=%05o, offset=%012o): no USE=0 found!\n",
 876                   segno, offset);
 877     }
 878 
 879     DPS8M_ (
 880       uint setno = (offset >> 10) & 017;
 881       uint toffset;
 882       ptw_s *p;
 883       for (toffset = 0; toffset < 64; toffset += 16)
 884         {
 885           p = & cpu.PTWAM[toffset + setno];
 886           if (! p->FE)
 887             break;
 888         }
 889       if (toffset == 64) // all FE==1
 890         {
 891           toffset = to_be_discarded_am (p->USE) << 4;
 892           p = & cpu.PTWAM[toffset + setno];
 893         }
 894 
 895       DBGAPP ("loadPTWAM(1):PTWAM[%d] FE=0 || LRU\n",
 896               toffset + setno);
 897 
 898       word6 u = calc_hit_am (p->USE, toffset >> 4); // before loading the PTWAM
 899       * p = cpu.PTW0; // load the PTW
 900       p->PAGENO = (offset >> 6) & 07760;
 901       p->POINTER = segno;
 902       p->FE = true;  // in use
 903       cpu.PTW = p; // export pointer for appending
 904 
 905       for (uint toffset1 = 0; toffset1 < 64; toffset1 += 16) // update LRU
 906         {
 907           p = & cpu.PTWAM[toffset1 + setno];
 908           if (p->FE)
 909             p->USE = u;
 910         }
 911 
 912       DBGAPP ("loadPTWAM(2): ADDR 0%o U %o M %o F %o FC %o POINTER=%o "
 913               "PAGENO=%o USE=%d\n",
 914               cpu.PTW->ADDR, cpu.PTW->U, cpu.PTW->M, cpu.PTW->DF,
 915               cpu.PTW->FC, cpu.PTW->POINTER, cpu.PTW->PAGENO, cpu.PTW->USE);
 916     )
 917   }
 918 
 919 /*
 920  * modify target segment PTW (Set M=1) ...
 921  */
 922 
 923 static void modify_ptw (cpu_state_t * cpup, sdw_s *sdw, word18 offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 924   {
 925     PNL (L68_ (cpu.apu.state |= apu_MPTW;))
 926     //word24 y2 = offset % 1024;
 927     word24 x2 = offset / 1024; // floor
 928 
 929     word36 PTWx2;
 930 
 931     set_apu_status (cpup, apuStatus_MPTW);
 932 
 933 #if defined(THREADZ)
 934     bool lck = get_rmw_lock ();
 935     if (! lck)
 936       lock_rmw ();
 937 #endif /* if defined(THREADZ) */
 938 #if defined(LOCKLESS)
 939     core_read_lock (cpup, (sdw->ADDR + x2) & PAMASK, & PTWx2, __func__);
 940     PTWx2 = SETBIT (PTWx2, 6);
 941     core_write_unlock (cpup, (sdw->ADDR + x2) & PAMASK, PTWx2, __func__);
 942 #else
 943     core_read (cpup, (sdw->ADDR + x2) & PAMASK, & PTWx2, __func__);
 944     PTWx2 = SETBIT (PTWx2, 6);
 945     core_write (cpup, (sdw->ADDR + x2) & PAMASK, PTWx2, __func__);
 946 #endif /* if defined(LOCKLESS) */
 947 #if defined(THREADZ)
 948     if (! lck)
 949       unlock_rmw ();
 950 #endif /* if defined(THREADZ) */
 951     cpu.PTW->M = 1;
 952     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 953       add_l68_APU_history (cpup, APUH_MPTW);)
 954   }
 955 
 956 static void do_ptw2 (cpu_state_t * cpup, sdw_s *sdw, word18 offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 957   {
 958     PNL (L68_ (cpu.apu.state |= apu_FPTW2;))
 959     set_apu_status (cpup, apuStatus_PTW2);
 960 
 961     //word24 y2 = offset % 1024;
 962     word24 x2 = (offset) / 1024; // floor
 963 
 964     word36 PTWx2n;
 965 
 966     DBGAPP ("%s address %08o\n", __func__, sdw->ADDR + x2 + 1);
 967 
 968     core_read (cpup, (sdw->ADDR + x2 + 1) & PAMASK, & PTWx2n, __func__);
 969 
 970     ptw_s PTW2;
 971     PTW2.ADDR = GETHI (PTWx2n);
 972     PTW2.U    = TSTBIT (PTWx2n, 9);
 973     PTW2.M    = TSTBIT (PTWx2n, 6);
 974     PTW2.DF   = TSTBIT (PTWx2n, 2);
 975     PTW2.FC   = PTWx2n & 3;
 976 
 977     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 978       add_l68_APU_history (cpup, APUH_FPTW2);)
 979 
 980     DBGAPP ("%s x2 0%o sdw->ADDR 0%o PTW2 0%012"PRIo64" "
 981             "PTW2: ADDR 0%o U %o M %o F %o FC %o\n",
 982             __func__, x2, sdw->ADDR, PTWx2n, PTW2.ADDR, PTW2.U, PTW2.M,
 983             PTW2.DF, PTW2.FC);
 984 
 985     // check that PTW2 is the next page of the same segment
 986     // ISOLTS 875 02a
 987     if ((PTW2.ADDR & 0777760) == (cpu.PTW->ADDR & 0777760) + 16)
 988        //Is PTW2.F set ON?
 989        if (! PTW2.DF)
 990            // initiate a directed fault
 991            doFault (FAULT_DF0 + PTW2.FC, fst_zero, "PTW2.F == 0");
 992   }
 993 
 994 /*
 995  * Is the instruction a SToRage OPeration ?
 996  */
 997 
 998 #if !defined(QUIET_UNUSED)
 999 static char *str_access_type (MemoryAccessType accessType)
     /* [previous][next][first][last][top][bottom][index][help] */
1000   {
1001     switch (accessType)
1002       {
1003         case UnknownMAT:        return "Unknown";
1004         case OperandRead:       return "OperandRead";
1005         case OperandWrite:      return "OperandWrite";
1006         default:                return "???";
1007       }
1008   }
1009 
1010 static char *str_acv (_fault_subtype acv)
     /* [previous][next][first][last][top][bottom][index][help] */
1011   {
1012     switch (acv)
1013       {
1014         case ACV0:  return "Illegal ring order (ACV0=IRO)";
1015         case ACV1:  return "Not in execute bracket (ACV1=OEB)";
1016         case ACV2:  return "No execute permission (ACV2=E-OFF)";
1017         case ACV3:  return "Not in read bracket (ACV3=ORB)";
1018         case ACV4:  return "No read permission (ACV4=R-OFF)";
1019         case ACV5:  return "Not in write bracket (ACV5=OWB)";
1020         case ACV6:  return "No write permission (ACV6=W-OFF)";
1021         case ACV7:  return "Call limiter fault (ACV7=NO GA)";
1022         case ACV8:  return "Out of call brackets (ACV8=OCB)";
1023         case ACV9:  return "Outward call (ACV9=OCALL)";
1024         case ACV10: return "Bad outward call (ACV10=BOC)";
1025         case ACV11: return "Inward return (ACV11=INRET) XXX ??";
1026         case ACV12: return "Invalid ring crossing (ACV12=CRT)";
1027         case ACV13: return "Ring alarm (ACV13=RALR)";
1028         case ACV14: return "Associative memory error XXX ??";
1029         case ACV15: return "Out of segment bounds (ACV15=OOSB)";
1030         //case ACDF0: return "Directed fault 0";
1031         //case ACDF1: return "Directed fault 1";
1032         //case ACDF2: return "Directed fault 2";
1033         //case ACDF3: return "Directed fault 3";
1034         default:
1035             break;
1036       }
1037   return "unhandled acv in str_acv";
1038   }
1039 #endif /* if !defined(QUIET_UNUSED) */
1040 
1041 #if defined (TESTING) || defined (OLDAPP)
1042 static char *str_pct (processor_cycle_type t)
     /* [previous][next][first][last][top][bottom][index][help] */
1043   {
1044     switch (t)
1045       {
1046         case UNKNOWN_CYCLE:       return "UNKNOWN_CYCLE";
1047         case OPERAND_STORE:       return "OPERAND_STORE";
1048         case OPERAND_READ:        return "OPERAND_READ";
1049         case INDIRECT_WORD_FETCH: return "INDIRECT_WORD_FETCH";
1050 # if defined(LOCKLESS)
1051         case OPERAND_RMW:         return "OPERAND_RMW";
1052         case APU_DATA_RMW:        return "APU_DATA_RMW";
1053 # endif /* if defined(LOCKLESS) */
1054         default:
1055             return "Unhandled processor_cycle_type";
1056       }
1057   }
1058 #endif
1059 
1060 #if !defined(OLDAPP)
1061 word24 do_append_cycle (cpu_state_t * cpup, processor_cycle_type thisCycle, word36 * data, uint nWords) {
     /* [previous][next][first][last][top][bottom][index][help] */
1062   switch (thisCycle) {
1063     case OPERAND_STORE:
1064       return doAppendCycleOperandStore (cpup, data, nWords);
1065     case OPERAND_READ:
1066       return doAppendCycleOperandRead (cpup, data, nWords);
1067     case INDIRECT_WORD_FETCH:
1068       return doAppendCycleIndirectWordFetch (cpup, data, nWords);
1069     case RTCD_OPERAND_FETCH:
1070       return doAppendCycleRTCDOperandFetch (cpup, data, nWords);
1071     case INSTRUCTION_FETCH:
1072       return doAppendCycleInstructionFetch (cpup, data, nWords);
1073     case APU_DATA_READ:
1074       return doAppendCycleAPUDataRead (cpup, data, nWords);
1075     case APU_DATA_STORE:
1076       return doAppendCycleAPUDataStore (cpup, data, nWords);
1077     case ABSA_CYCLE:
1078       return doAppendCycleABSA (cpup, data, nWords);
1079 # if defined(LOCKLESS)
1080     case OPERAND_RMW:
1081       return doAppendCycleOperandRMW (cpup, data, nWords);
1082     case APU_DATA_RMW:
1083       return doAppendCycleAPUDataRMW (cpup, data, nWords);
1084 # endif /* if defined(LOCKLESS) */
1085     case UNKNOWN_CYCLE:
1086     default:
1087       (void)fprintf (stderr, "\rFATAL: APU unknown cycle %llu! Aborting at %s[%s:%d]\r\n",
1088                      (long long unsigned)thisCycle, __func__, __FILE__, __LINE__);
1089 # if defined(USE_BACKTRACE)
1090 #  if defined(SIGUSR2)
1091       (void)raise(SIGUSR2);
1092       /*NOTREACHED*/ /* unreachable */
1093 #  endif /* if defined(SIGUSR2) */
1094 # endif /* if defined(USE_BACKTRACE) */
1095       abort();
1096   }
1097 }
1098 #endif /* if !defined(OLDAPP) */
1099 
1100 #if !defined(OLDAPP)
1101 # include "doAppendCycleOperandStore.h"
1102 # include "doAppendCycleOperandRead.h"
1103 # include "doAppendCycleIndirectWordFetch.h"
1104 # include "doAppendCycleRTCDOperandFetch.h"
1105 # include "doAppendCycleInstructionFetch.h"
1106 # include "doAppendCycleAPUDataRead.h"
1107 # include "doAppendCycleAPUDataStore.h"
1108 # include "doAppendCycleABSA.h"
1109 # if defined(LOCKLESS)
1110 #  include "doAppendCycleOperandRMW.h"
1111 #  include "doAppendCycleAPUDataRMW.h"
1112 # endif /* if defined(LOCKLESS) */
1113 #endif /* if !defined(OLDAPP) */
1114 
1115 #if defined(OLDAPP)
1116 /*
1117  * recoding APU functions to more closely match Fig 5,6 & 8 ...
1118  * Returns final address suitable for core_read/write
1119  */
1120 
1121 //
1122 // Phase 1:
1123 //
1124 //     A: Get the SDW
1125 //
1126 //     B: Check the ring
1127 //
1128 // Phase 2:
1129 //
1130 //     B1: If CALL6 operand
1131 //           goto E
1132 //         If instruction fetch or transfer instruction operand
1133 //           goto F
1134 //         If write
1135 //           check write permission
1136 //         else
1137 //           check read permission
1138 //         goto G
1139 //
1140 //     E: -- CALL6 operand handling
1141 //        Check execute and gate bits
1142 //        Get the ring
1143 //        goto G
1144 //
1145 //     F: -- instruction fetch or transfer instruction operand
1146 //        Check execute bit and ring
1147 //        goto D
1148 //
1149 //     D: Check RALR
1150 //        goto G
1151 //
1152 // Phase 3
1153 //
1154 //     G: Check BOUND
1155 //        If not paged
1156 //          goto H
1157 //        Fetch PTW
1158 //        Fetch prepage PTW
1159 //        Goto I
1160 //
1161 //     H: Compute final address
1162 //        Goto HI
1163 //
1164 //     I: If write
1165 //          set PTW.M
1166 //        Compute final address
1167 //        Goto HI
1168 //
1169 // Phase 4
1170 //
1171 //     HI: --
1172 //         If indirect word fetch
1173 //           goto J
1174 //         if rtcd operand fetch
1175 //           goto K
1176 //         if CALL6
1177 //           goto N
1178 //         If instruction fetch or transfer instruction operand
1179 //           goto L
1180 //         APU data movement?
1181 //           load/store APU data
1182 //
1183 //    K: Set PPR.P
1184 //         Goto J
1185 //
1186 //    J: return
1187 //
1188 
1189 // CANFAULT
1190 
1191 word24 do_append_cycle (processor_cycle_type thisCycle, word36 * data,
     /* [previous][next][first][last][top][bottom][index][help] */
1192                       uint nWords)
1193   {
1194     DCDstruct * i = & cpu.currentInstruction;
1195     DBGAPP ("do_append_cycle(Entry) thisCycle=%s\n",
1196             str_pct (thisCycle));
1197     DBGAPP ("do_append_cycle(Entry) lastCycle=%s\n",
1198             str_pct (cpu.apu.lastCycle));
1199     DBGAPP ("do_append_cycle(Entry) CA %06o\n",
1200             cpu.TPR.CA);
1201     DBGAPP ("do_append_cycle(Entry) n=%2u\n",
1202             nWords);
1203     DBGAPP ("do_append_cycle(Entry) PPR.PRR=%o PPR.PSR=%05o\n",
1204             cpu.PPR.PRR, cpu.PPR.PSR);
1205     DBGAPP ("do_append_cycle(Entry) TPR.TRR=%o TPR.TSR=%05o\n",
1206             cpu.TPR.TRR, cpu.TPR.TSR);
1207 
1208     if (i->b29)
1209       {
1210         DBGAPP ("do_append_cycle(Entry) isb29 PRNO %o\n",
1211                 GET_PRN (IWB_IRODD));
1212       }
1213 
1214     bool StrOp = (thisCycle == OPERAND_STORE ||
1215                   thisCycle == APU_DATA_STORE);
1216 
1217     bool nomatch = true;
1218     if (cpu.tweaks.enable_wam)
1219       {
1220         // AL39: The associative memory is ignored (forced to "no match") during
1221         // address preparation.
1222         // lptp,lptr,lsdp,lsdr,sptp,sptr,ssdp,ssdr
1223         // Unfortunately, ISOLTS doesn't try to execute any of these in append mode.
1224         // XXX should this be only for OPERAND_READ and OPERAND_STORE?
1225         nomatch = ((i->opcode == 0232 || i->opcode == 0254  ||
1226                     i->opcode == 0154 || i->opcode == 0173) &&   i->opcodeX) ||
1227                   ((i->opcode == 0557 || i->opcode == 0257) && ! i->opcodeX);
1228       }
1229 
1230     processor_cycle_type lastCycle = cpu.apu.lastCycle;
1231     cpu.apu.lastCycle = thisCycle;
1232 
1233     DBGAPP ("do_append_cycle(Entry) XSF %o\n", cpu.cu.XSF);
1234 
1235     PNL (L68_ (cpu.apu.state = 0;))
1236 
1237     cpu.RSDWH_R1 = 0;
1238 
1239     cpu.acvFaults = 0;
1240 
1241 //#define FMSG(x) x
1242 # define FMSG(x)
1243     FMSG (char * acvFaultsMsg = "<unknown>";)
1244 
1245     word24 finalAddress = (word24) -1;  // not everything requires a final
1246                                         // address
1247 
1248 ////////////////////////////////////////
1249 //
1250 // Sheet 1: "START APPEND"
1251 //
1252 ////////////////////////////////////////
1253 
1254 // START APPEND
1255     word3 n = 0; // PRn to be saved to TSN_PRNO
1256 
1257     // If the rtcd instruction is executed with the processor in absolute
1258     // mode with bit 29 of the instruction word set OFF and without
1259     // indirection through an ITP or ITS pair, then:
1260     //
1261     //   appending mode is entered for address preparation for the
1262     //   rtcd operand and is retained if the instruction executes
1263     //   successfully, and the effective segment number generated for
1264     //   the SDW fetch and subsequent loading into C(TPR.TSR) is equal
1265     //   to C(PPR.PSR) and may be undefined in absolute mode, and the
1266     //   effective ring number loaded into C(TPR.TRR) prior to the SDW
1267     //   fetch is equal to C(PPR.PRR) (which is 0 in absolute mode)
1268     //   implying that control is always transferred into ring 0.
1269     //
1270     if (thisCycle == RTCD_OPERAND_FETCH &&
1271         get_addr_mode() == ABSOLUTE_mode &&
1272         ! (cpu.cu.XSF || cpu.currentInstruction.b29) /*get_went_appending()*/)
1273       {
1274         cpu.TPR.TSR = 0;
1275         DBGAPP ("RTCD_OPERAND_FETCH ABSOLUTE mode set TSR %05o TRR %o\n",
1276                 cpu.TPR.TSR, cpu.TPR.TRR);
1277       }
1278 
1279     goto A;
1280 
1281 ////////////////////////////////////////
1282 //
1283 // Sheet 2: "A"
1284 //
1285 ////////////////////////////////////////
1286 
1287 //
1288 //  A:
1289 //    Get SDW
1290 
1291 A:;
1292 
1293     //PNL (cpu.APUMemAddr = address;)
1294     PNL (cpu.APUMemAddr = cpu.TPR.CA;)
1295 
1296     DBGAPP ("do_append_cycle(A)\n");
1297 
1298     // is SDW for C(TPR.TSR) in SDWAM?
1299     if (nomatch || ! fetch_sdw_from_sdwam (cpu.TPR.TSR))
1300       {
1301         // No
1302         DBGAPP ("do_append_cycle(A):SDW for segment %05o not in SDWAM\n",
1303                  cpu.TPR.TSR);
1304 
1305         DBGAPP ("do_append_cycle(A):DSBR.U=%o\n",
1306                 cpu.DSBR.U);
1307 
1308         if (cpu.DSBR.U == 0)
1309           {
1310             fetch_dsptw (cpu.TPR.TSR);
1311 
1312             if (! cpu.PTW0.DF)
1313               doFault (FAULT_DF0 + cpu.PTW0.FC, fst_zero,
1314                        "do_append_cycle(A): PTW0.F == 0");
1315 
1316             if (! cpu.PTW0.U)
1317               modify_dsptw (cpu.TPR.TSR);
1318 
1319             fetch_psdw (cpu.TPR.TSR);
1320           }
1321         else
1322           fetch_nsdw (cpu.TPR.TSR); // load SDW0 from descriptor segment table.
1323 
1324         if (cpu.SDW0.DF == 0)
1325           {
1326             if (thisCycle != ABSA_CYCLE)
1327               {
1328                 DBGAPP ("do_append_cycle(A): SDW0.F == 0! "
1329                         "Initiating directed fault\n");
1330                 // initiate a directed fault ...
1331                 doFault (FAULT_DF0 + cpu.SDW0.FC, fst_zero, "SDW0.F == 0");
1332               }
1333           }
1334         // load SDWAM .....
1335         load_sdwam (cpu.TPR.TSR, nomatch);
1336       }
1337     DBGAPP ("do_append_cycle(A) R1 %o R2 %o R3 %o E %o\n",
1338             cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3, cpu.SDW->E);
1339 
1340     // Yes...
1341     cpu.RSDWH_R1 = cpu.SDW->R1;
1342 
1343 ////////////////////////////////////////
1344 //
1345 // Sheet 3: "B"
1346 //
1347 ////////////////////////////////////////
1348 
1349 //
1350 // B: Check the ring
1351 //
1352 
1353     DBGAPP ("do_append_cycle(B)\n");
1354 
1355     // check ring bracket consistency
1356 
1357     //C(SDW.R1) <= C(SDW.R2) <= C(SDW .R3)?
1358     if (! (cpu.SDW->R1 <= cpu.SDW->R2 && cpu.SDW->R2 <= cpu.SDW->R3))
1359       {
1360         // Set fault ACV0 = IRO
1361         cpu.acvFaults |= ACV0;
1362         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1363         FMSG (acvFaultsMsg = "acvFaults(B) C(SDW.R1) <= C(SDW.R2) <= "
1364                               "C(SDW .R3)";)
1365       }
1366 
1367     // lastCycle == RTCD_OPERAND_FETCH
1368     // if a fault happens between the RTCD_OPERAND_FETCH and the INSTRUCTION_FETCH
1369     // of the next instruction - this happens about 35 time for just booting  and
1370     // shutting down Multics -- a stored lastCycle is useless.
1371     // the opcode is preserved across faults and only replaced as the
1372     // INSTRUCTION_FETCH succeeds.
1373     if (thisCycle == INSTRUCTION_FETCH &&
1374         i->opcode == 0610  && ! i->opcodeX)
1375       goto C;
1376     else if (lastCycle == RTCD_OPERAND_FETCH)
1377       sim_warn ("%s: lastCycle == RTCD_OPERAND_FETCH opcode %0#o\n", __func__, i->opcode);
1378 
1379     //
1380     // B1: The operand is one of: an instruction, data to be read or data to be
1381     //     written
1382     //
1383 
1384     // Is OPCODE call6?
1385     if (thisCycle == OPERAND_READ && (i->info->flags & CALL6_INS))
1386       goto E;
1387 
1388 
1389 
1390 
1391 
1392 
1393 
1394 
1395 
1396 
1397 
1398 
1399 
1400 
1401 
1402 
1403 
1404 
1405 
1406 
1407 
1408 
1409     // Transfer or instruction fetch?
1410     if (thisCycle == INSTRUCTION_FETCH ||
1411         (thisCycle == OPERAND_READ && (i->info->flags & TRANSFER_INS)))
1412       goto F;
1413 
1414     //
1415     // check read bracket for read access
1416     //
1417 
1418 # if defined(LOCKLESS)
1419     if (!StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW) // -V560
1420 # else
1421     if (!StrOp)
1422 # endif /* if defined(LOCKLESS) */
1423       {
1424         DBGAPP ("do_append_cycle(B):!STR-OP\n");
1425 
1426         // No
1427         // C(TPR.TRR) > C(SDW .R2)?
1428         if (cpu.TPR.TRR > cpu.SDW->R2)
1429           {
1430             DBGAPP ("ACV3\n");
1431             DBGAPP ("do_append_cycle(B) ACV3\n");
1432             //Set fault ACV3 = ORB
1433             cpu.acvFaults |= ACV3;
1434             PNL (L68_ (cpu.apu.state |= apu_FLT;))
1435             FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R2)";)
1436           }
1437 
1438         if (cpu.SDW->R == 0)
1439           {
1440             // isolts 870
1441             cpu.TPR.TRR = cpu.PPR.PRR;
1442 
1443             //C(PPR.PSR) = C(TPR.TSR)?
1444             if (cpu.PPR.PSR != cpu.TPR.TSR)
1445               {
1446                 DBGAPP ("ACV4\n");
1447                 DBGAPP ("do_append_cycle(B) ACV4\n");
1448                 //Set fault ACV4 = R-OFF
1449                 cpu.acvFaults |= ACV4;
1450                 PNL (L68_ (cpu.apu.state |= apu_FLT;))
1451                 FMSG (acvFaultsMsg = "acvFaults(B) C(PPR.PSR) = C(TPR.TSR)";)
1452               }
1453 
1454 
1455 
1456 
1457 
1458 
1459           }
1460       }
1461 
1462     //
1463     // check write bracket for write access
1464     //
1465 # if defined(LOCKLESS)
1466     if (StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
1467 # else
1468     if (StrOp)
1469 # endif /* if defined(LOCKLESS) */
1470       {
1471         DBGAPP ("do_append_cycle(B):STR-OP\n");
1472 
1473         // isolts 870
1474         if (cpu.TPR.TSR == cpu.PPR.PSR)
1475             cpu.TPR.TRR = cpu.PPR.PRR;
1476 
1477         // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
1478         if (cpu.TPR.TRR > cpu.SDW->R1)
1479           {
1480             DBGAPP ("ACV5 TRR %o R1 %o\n",
1481                     cpu.TPR.TRR, cpu.SDW->R1);
1482             //Set fault ACV5 = OWB
1483             cpu.acvFaults |= ACV5;
1484             PNL (L68_ (cpu.apu.state |= apu_FLT;))
1485             FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
1486           }
1487 
1488         if (! cpu.SDW->W)
1489           {
1490             // isolts 870
1491             cpu.TPR.TRR = cpu.PPR.PRR;
1492 
1493             DBGAPP ("ACV6\n");
1494             // Set fault ACV6 = W-OFF
1495             cpu.acvFaults |= ACV6;
1496             PNL (L68_ (cpu.apu.state |= apu_FLT;))
1497             FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
1498           }
1499 
1500       }
1501     goto G;
1502 
1503 ////////////////////////////////////////
1504 //
1505 // Sheet 4: "C" "D"
1506 //
1507 ////////////////////////////////////////
1508 
1509 C:;
1510     DBGAPP ("do_append_cycle(C)\n");
1511 
1512     //
1513     // check ring bracket for instruction fetch after rtcd instruction
1514     //
1515     //   allow outbound transfers (cpu.TPR.TRR >= cpu.PPR.PRR)
1516     //
1517 
1518     // C(TPR.TRR) < C(SDW.R1)?
1519     // C(TPR.TRR) > C(SDW.R2)?
1520     if (cpu.TPR.TRR < cpu.SDW->R1 ||
1521         cpu.TPR.TRR > cpu.SDW->R2)
1522       {
1523         DBGAPP ("ACV1 c\n");
1524         DBGAPP ("acvFaults(C) ACV1 ! ( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
1525                 cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
1526         //Set fault ACV1 = OEB
1527         cpu.acvFaults |= ACV1;
1528         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1529         FMSG (acvFaultsMsg = "acvFaults(C) C(SDW.R1 > C(TPR.TRR) > C(SDW.R2)";)
1530       }
1531     // SDW.E set ON?
1532     if (! cpu.SDW->E)
1533       {
1534         DBGAPP ("ACV2 a\n");
1535         DBGAPP ("do_append_cycle(C) ACV2\n");
1536         //Set fault ACV2 = E-OFF
1537         cpu.acvFaults |= ACV2;
1538         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1539         FMSG (acvFaultsMsg = "acvFaults(C) SDW.E";)
1540       }
1541     if (cpu.TPR.TRR > cpu.PPR.PRR)
1542       sim_warn ("rtcd: outbound call cpu.TPR.TRR %d cpu.PPR.PRR %d\n",
1543                 cpu.TPR.TRR, cpu.PPR.PRR);
1544     // C(TPR.TRR) >= C(PPR.PRR)
1545     if (cpu.TPR.TRR < cpu.PPR.PRR)
1546       {
1547         DBGAPP ("ACV11\n");
1548         DBGAPP ("do_append_cycle(C) ACV11\n");
1549         //Set fault ACV11 = INRET
1550         cpu.acvFaults |= ACV11;
1551         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1552         FMSG (acvFaultsMsg = "acvFaults(C) TRR>=PRR";)
1553       }
1554 
1555 D:;
1556     DBGAPP ("do_append_cycle(D)\n");
1557 
1558     // transfer or instruction fetch
1559 
1560     // check ring alarm to catch outbound transfers
1561 
1562     if (cpu.rRALR == 0)
1563         goto G;
1564 
1565     // C(PPR.PRR) < RALR?
1566     if (! (cpu.PPR.PRR < cpu.rRALR))
1567       {
1568         DBGAPP ("ACV13\n");
1569         DBGAPP ("acvFaults(D) C(PPR.PRR) %o < RALR %o\n",
1570                 cpu.PPR.PRR, cpu.rRALR);
1571         cpu.acvFaults |= ACV13;
1572         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1573         FMSG (acvFaultsMsg = "acvFaults(D) C(PPR.PRR) < RALR";)
1574       }
1575 
1576     goto G;
1577 
1578 ////////////////////////////////////////
1579 //
1580 // Sheet 5: "E"
1581 //
1582 ////////////////////////////////////////
1583 
1584 E:;
1585 
1586     //
1587     // check ring bracket for instruction fetch after call6 instruction
1588     //   (this is the call6 read operand)
1589     //
1590 
1591     DBGAPP ("do_append_cycle(E): CALL6\n");
1592     DBGAPP ("do_append_cycle(E): E %o G %o PSR %05o TSR %05o CA %06o "
1593             "EB %06o R %o%o%o TRR %o PRR %o\n",
1594             cpu.SDW->E, cpu.SDW->G, cpu.PPR.PSR, cpu.TPR.TSR, cpu.TPR.CA,
1595             cpu.SDW->EB, cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3,
1596             cpu.TPR.TRR, cpu.PPR.PRR);
1597 
1598     //SDW.E set ON?
1599     if (! cpu.SDW->E)
1600       {
1601         DBGAPP ("ACV2 b\n");
1602         DBGAPP ("do_append_cycle(E) ACV2\n");
1603         // Set fault ACV2 = E-OFF
1604         cpu.acvFaults |= ACV2;
1605         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1606         FMSG (acvFaultsMsg = "acvFaults(E) SDW .E set OFF";)
1607       }
1608 
1609     //SDW .G set ON?
1610     if (cpu.SDW->G)
1611       goto E1;
1612 
1613     // C(PPR.PSR) = C(TPR.TSR)?
1614     if (cpu.PPR.PSR == cpu.TPR.TSR && ! TST_I_ABS)
1615       goto E1;
1616 
1617     // XXX This doesn't seem right
1618     // EB is word 15; masking address makes no sense; rather 0-extend EB
1619     // Fixes ISOLTS 880-01
1620     if (cpu.TPR.CA >= (word18) cpu.SDW->EB)
1621       {
1622         DBGAPP ("ACV7\n");
1623         DBGAPP ("do_append_cycle(E) ACV7\n");
1624         // Set fault ACV7 = NO GA
1625         cpu.acvFaults |= ACV7;
1626         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1627         FMSG (acvFaultsMsg = "acvFaults(E) TPR.CA4-17 >= SDW.CL";)
1628       }
1629 
1630 E1:
1631     DBGAPP ("do_append_cycle(E1): CALL6 (cont'd)\n");
1632 
1633     // C(TPR.TRR) > SDW.R3?
1634     if (cpu.TPR.TRR > cpu.SDW->R3)
1635       {
1636         DBGAPP ("ACV8\n");
1637         DBGAPP ("do_append_cycle(E) ACV8\n");
1638         //Set fault ACV8 = OCB
1639         cpu.acvFaults |= ACV8;
1640         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1641         FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > SDW.R3";)
1642       }
1643 
1644     // C(TPR.TRR) < SDW.R1?
1645     if (cpu.TPR.TRR < cpu.SDW->R1)
1646       {
1647         DBGAPP ("ACV9\n");
1648         DBGAPP ("do_append_cycle(E) ACV9\n");
1649         // Set fault ACV9 = OCALL
1650         cpu.acvFaults |= ACV9;
1651         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1652         FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) < SDW.R1";)
1653       }
1654 
1655     // C(TPR.TRR) > C(PPR.PRR)?
1656     if (cpu.TPR.TRR > cpu.PPR.PRR)
1657       {
1658         // C(PPR.PRR) < SDW.R2?
1659         if (cpu.PPR.PRR < cpu.SDW->R2)
1660           {
1661             DBGAPP ("ACV10\n");
1662             DBGAPP ("do_append_cycle(E) ACV10\n");
1663             // Set fault ACV10 = BOC
1664             cpu.acvFaults |= ACV10;
1665             PNL (L68_ (cpu.apu.state |= apu_FLT;))
1666             FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > C(PPR.PRR) && "
1667                   "C(PPR.PRR) < SDW.R2";)
1668           }
1669       }
1670 
1671     DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o SDW->R2 %o\n",
1672             cpu.TPR.TRR, cpu.SDW->R2);
1673 
1674     // C(TPR.TRR) > SDW.R2?
1675     if (cpu.TPR.TRR > cpu.SDW->R2)
1676       {
1677         // SDW.R2 -> C(TPR.TRR)
1678         cpu.TPR.TRR = cpu.SDW->R2;
1679       }
1680 
1681     DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o\n", cpu.TPR.TRR);
1682 
1683     goto G;
1684 
1685 ////////////////////////////////////////
1686 //
1687 // Sheet 6: "F"
1688 //
1689 ////////////////////////////////////////
1690 
1691 F:;
1692     PNL (L68_ (cpu.apu.state |= apu_PIAU;))
1693     DBGAPP ("do_append_cycle(F): transfer or instruction fetch\n");
1694 
1695     //
1696     // check ring bracket for instruction fetch
1697     //
1698 
1699     // C(TPR.TRR) < C(SDW .R1)?
1700     // C(TPR.TRR) > C(SDW .R2)?
1701     if (cpu.TPR.TRR < cpu.SDW->R1 ||
1702         cpu.TPR.TRR > cpu.SDW->R2)
1703       {
1704         DBGAPP ("ACV1 a/b\n");
1705         DBGAPP ("acvFaults(F) ACV1 !( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
1706                 cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
1707         cpu.acvFaults |= ACV1;
1708         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1709         FMSG (acvFaultsMsg = "acvFaults(F) C(TPR.TRR) < C(SDW .R1)";)
1710       }
1711     // SDW .E set ON?
1712     if (! cpu.SDW->E)
1713       {
1714         DBGAPP ("ACV2 c \n");
1715         DBGAPP ("do_append_cycle(F) ACV2\n");
1716         cpu.acvFaults |= ACV2;
1717         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1718         FMSG (acvFaultsMsg = "acvFaults(F) SDW .E set OFF";)
1719       }
1720 
1721     // C(PPR.PRR) = C(TPR.TRR)?
1722     if (cpu.PPR.PRR != cpu.TPR.TRR)
1723       {
1724         DBGAPP ("ACV12\n");
1725         DBGAPP ("do_append_cycle(F) ACV12\n");
1726         //Set fault ACV12 = CRT
1727         cpu.acvFaults |= ACV12;
1728         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1729         FMSG (acvFaultsMsg = "acvFaults(F) C(PPR.PRR) != C(TPR.TRR)";)
1730       }
1731 
1732     goto D;
1733 
1734 ////////////////////////////////////////
1735 //
1736 // Sheet 7: "G"
1737 //
1738 ////////////////////////////////////////
1739 
1740 G:;
1741 
1742     DBGAPP ("do_append_cycle(G)\n");
1743 
1744     //C(TPR.CA)0,13 > SDW.BOUND?
1745     if (((cpu.TPR.CA >> 4) & 037777) > cpu.SDW->BOUND)
1746       {
1747         DBGAPP ("ACV15\n");
1748         DBGAPP ("do_append_cycle(G) ACV15\n");
1749         cpu.acvFaults |= ACV15;
1750         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1751         FMSG (acvFaultsMsg = "acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND";)
1752         DBGAPP ("acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND\n"
1753                 "   CA %06o CA>>4 & 037777 %06o SDW->BOUND %06o",
1754                 cpu.TPR.CA, ((cpu.TPR.CA >> 4) & 037777), cpu.SDW->BOUND);
1755       }
1756 
1757     if (cpu.acvFaults)
1758       {
1759         DBGAPP ("do_append_cycle(G) acvFaults\n");
1760         PNL (L68_ (cpu.apu.state |= apu_FLT;))
1761         // Initiate an access violation fault
1762         doFault (FAULT_ACV, (_fault_subtype) {.fault_acv_subtype=cpu.acvFaults},
1763                  "ACV fault");
1764       }
1765 
1766     // is segment C(TPR.TSR) paged?
1767     if (cpu.SDW->U)
1768       goto H; // Not paged
1769 
1770     // Yes. segment is paged ...
1771     // is PTW for C(TPR.CA) in PTWAM?
1772 
1773     DBGAPP ("do_append_cycle(G) CA %06o\n", cpu.TPR.CA);
1774     if (nomatch ||
1775         ! fetch_ptw_from_ptwam (cpu.SDW->POINTER, cpu.TPR.CA))  //TPR.CA))
1776       {
1777         fetch_ptw (cpu.SDW, cpu.TPR.CA);
1778         if (! cpu.PTW0.DF)
1779           {
1780             if (thisCycle != ABSA_CYCLE)
1781               {
1782                 // initiate a directed fault
1783                 doFault (FAULT_DF0 + cpu.PTW0.FC, (_fault_subtype) {.bits=0},
1784                          "PTW0.F == 0");
1785               }
1786           }
1787         loadPTWAM (cpu.SDW->POINTER, cpu.TPR.CA, nomatch); // load PTW0 to PTWAM
1788       }
1789 
1790     // Prepage mode?
1791     // check for "uninterruptible" EIS instruction
1792     // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
1793     // ad2/3d,sb2/3d,mp2/3d,dv2/3d
1794     // DH03 p.8-13: probably also mve,btd,dtb
1795     if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
1796         || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300))
1797       {
1798         do_ptw2 (cpu.SDW, cpu.TPR.CA);
1799       }
1800     goto I;
1801 
1802 ////////////////////////////////////////
1803 //
1804 // Sheet 8: "H", "I"
1805 //
1806 ////////////////////////////////////////
1807 
1808 H:;
1809     DBGAPP ("do_append_cycle(H): FANP\n");
1810 
1811     PNL (L68_ (cpu.apu.state |= apu_FANP;))
1812 
1813 
1814 
1815 
1816 
1817 
1818 
1819 
1820 
1821     set_apu_status (apuStatus_FANP);
1822 
1823     DBGAPP ("do_append_cycle(H): SDW->ADDR=%08o CA=%06o \n",
1824             cpu.SDW->ADDR, cpu.TPR.CA);
1825 
1826     if (thisCycle == RTCD_OPERAND_FETCH &&
1827         get_addr_mode () == ABSOLUTE_mode &&
1828         ! (cpu.cu.XSF || cpu.currentInstruction.b29) /*get_went_appending ()*/)
1829       {
1830         finalAddress = cpu.TPR.CA;
1831       }
1832     else
1833       {
1834         finalAddress = (cpu.SDW->ADDR & 077777760) + cpu.TPR.CA;
1835         finalAddress &= 0xffffff;
1836       }
1837     PNL (cpu.APUMemAddr = finalAddress;)
1838 
1839     DBGAPP ("do_append_cycle(H:FANP): (%05o:%06o) finalAddress=%08o\n",
1840             cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
1841 
1842     //if (thisCycle == ABSA_CYCLE)
1843     //    goto J;
1844     goto HI;
1845 
1846 I:;
1847 
1848 // Set PTW.M
1849 
1850     DBGAPP ("do_append_cycle(I): FAP\n");
1851 # if defined(LOCKLESS)
1852     if ((StrOp ||
1853         thisCycle == OPERAND_RMW ||
1854         thisCycle == APU_DATA_RMW) && cpu.PTW->M == 0)  // is this the right way to do this?
1855 # else
1856     if (StrOp && cpu.PTW->M == 0)  // is this the right way to do this?
1857 # endif /* if defined(LOCKLESS) */
1858       {
1859        modify_ptw (cpu.SDW, cpu.TPR.CA);
1860       }
1861 
1862     // final address paged
1863     set_apu_status (apuStatus_FAP);
1864     PNL (L68_ (cpu.apu.state |= apu_FAP;))
1865 
1866     word24 y2 = cpu.TPR.CA % 1024;
1867 
1868     // AL39: The hardware ignores low order bits of the main memory page
1869     // address according to page size
1870     finalAddress = (((word24)cpu.PTW->ADDR & 0777760) << 6) + y2;
1871     finalAddress &= 0xffffff;
1872     PNL (cpu.APUMemAddr = finalAddress;)
1873 
1874     L68_ (if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
1875       add_l68_APU_history (APUH_FAP);)
1876 
1877     DBGAPP ("do_append_cycle(H:FAP): (%05o:%06o) finalAddress=%08o\n",
1878             cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
1879 
1880     //if (thisCycle == ABSA_CYCLE)
1881     //    goto J;
1882     goto HI;
1883 
1884 HI:
1885     DBGAPP ("do_append_cycle(HI)\n");
1886 
1887     // isolts 870
1888     if (thisCycle != ABSA_CYCLE)
1889       {
1890         cpu.cu.XSF = 1;
1891         sim_debug (DBG_TRACEEXT, & cpu_dev, "loading of cpu.TPR.TSR sets XSF to 1\n");
1892       }
1893 
1894     if (thisCycle == OPERAND_STORE && cpu.useZone)
1895       {
1896         core_write_zone (finalAddress, * data, str_pct (thisCycle));
1897       }
1898     else if (StrOp)
1899       {
1900         core_writeN (finalAddress, data, nWords, str_pct (thisCycle));
1901       }
1902     else
1903       {
1904 # if defined(LOCKLESS)
1905         if ((thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW) && nWords == 1)
1906           {
1907             core_read_lock (finalAddress, data, str_pct (thisCycle));
1908           }
1909         else
1910           {
1911             if (thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
1912               sim_warn("do_append_cycle: RMW nWords %d !=1\n", nWords);
1913             core_readN (finalAddress, data, nWords, str_pct (thisCycle));
1914           }
1915 # else
1916         if (thisCycle != ABSA_CYCLE)
1917           core_readN (finalAddress, data, nWords, str_pct (thisCycle));
1918 # endif /* if defined(LOCKLESS) */
1919       }
1920 
1921     // Was this an indirect word fetch?
1922     if (thisCycle == INDIRECT_WORD_FETCH)
1923       goto J;
1924 
1925     // Was this an rtcd operand fetch?
1926     if (thisCycle == RTCD_OPERAND_FETCH)
1927       goto K;
1928 
1929     // is OPCODE call6?
1930     if (thisCycle == OPERAND_READ && (i->info->flags & CALL6_INS))
1931       goto N;
1932 
1933     // Transfer or instruction fetch?
1934     if (thisCycle == INSTRUCTION_FETCH ||
1935         (thisCycle == OPERAND_READ && (i->info->flags & TRANSFER_INS)))
1936       goto L;
1937 
1938     // APU data movement?
1939     //  handled above
1940    goto Exit;
1941 
1942 ////////////////////////////////////////
1943 //
1944 // Sheet 9: "J"
1945 //
1946 ////////////////////////////////////////
1947 
1948 // Indirect operand fetch
1949 
1950 J:;
1951     DBGAPP ("do_append_cycle(J)\n");
1952 
1953     // ri or ir & TPC.CA even?
1954     word6 tag = GET_TAG (IWB_IRODD);
1955     if ((GET_TM (tag) == TM_IR || GET_TM (tag) == TM_RI) &&
1956         (cpu.TPR.CA & 1) == 0)
1957       {
1958         if (ISITS (* data))
1959           goto O;
1960         if (ISITP (* data))
1961           goto P;
1962       }
1963 
1964     // C(Y) tag == other indirect?
1965     //   TM_R never indirects
1966     //   TM_RI always indirects
1967     //   TM_IR always indirects
1968     //   TM_IT always indirects
1969 
1970 
1971 
1972 
1973 
1974 
1975 
1976 
1977 
1978 
1979 
1980 
1981 
1982 
1983 
1984 
1985 
1986 
1987 
1988 
1989 
1990 
1991 
1992 
1993 
1994 
1995 
1996 
1997     if ((* data) & 060)
1998 
1999       {
2000         // C(Y)0,17 -> C(IWB)0,17
2001         // C(Y)30,35 -> C(IWB)30,35
2002         // 0 -> C(IWB)29
2003         //updateIWB (GET_ADDR (* data), (* data) & MASK6);
2004         //cpu.cu.TSN_PRNO[0] = n;
2005         //cpu.cu.TSN_VALID[0] = 1;
2006 
2007       }
2008 
2009      goto Exit;
2010 
2011 ////////////////////////////////////////
2012 //
2013 // Sheet 10: "K", "L", "M", "N"
2014 //
2015 ////////////////////////////////////////
2016 
2017 K:; // RTCD operand fetch
2018     DBGAPP ("do_append_cycle(K)\n");
2019 
2020     word3 y = GET_ITS_RN (data);
2021 
2022     // C(Y-pair)3,17 -> C(PPR.PSR)
2023     // We set TSR here; TSR will be copied to PSR at KL
2024     cpu.TPR.TSR = GET_ITS_SEGNO (data);
2025 
2026     // Maximum of
2027     // C(Y-pair)18,20; C(TPR.TRR); C(SDW.R1) -> C(PPR.PRR)
2028     // We set TRR here as well
2029     cpu.PPR.PRR = cpu.TPR.TRR = max3 (y, cpu.TPR.TRR, cpu.RSDWH_R1);
2030 
2031     // C(Y-pair)36,53 -> C(PPR.IC)
2032     // We set CA here; copied to IC  at KL
2033     cpu.TPR.CA = GET_ITS_WORDNO (data);
2034 
2035     // If C(PPR.PRR) = 0 then C(SDW.P) -> C(PPR.P);
2036     //     otherwise 0 -> C(PPR.P)
2037     // Done at M
2038 
2039     goto KL;
2040 
2041 L:; // Transfer or instruction fetch
2042 
2043     DBGAPP ("do_append_cycle(L)\n");
2044 
2045     // Is OPCODE tspn?
2046     if (thisCycle == OPERAND_READ && (i->info->flags & TSPN_INS))
2047       {
2048         //word3 n;
2049         if (i->opcode <= 0273)
2050           n = (i->opcode & 3);
2051         else
2052           n = (i->opcode & 3) + 4;
2053 
2054         // C(PPR.PRR) -> C(PRn .RNR)
2055         // C(PPR.PSR) -> C(PRn .SNR)
2056         // C(PPR.IC)  -> C(PRn .WORDNO)
2057         // 000000     -> C(PRn .BITNO)
2058         cpu.PR[n].RNR = cpu.PPR.PRR;
2059 // According the AL39, the PSR is 'undefined' in absolute mode.
2060 // ISOLTS thinks means don't change the operand
2061         if (get_addr_mode () == APPEND_mode)
2062           cpu.PR[n].SNR = cpu.PPR.PSR;
2063         cpu.PR[n].WORDNO = (cpu.PPR.IC + 1) & MASK18;
2064         SET_PR_BITNO (n, 0);
2065 # if defined(TESTING)
2066         HDBGRegPRW (n, "app tspn");
2067 # endif /* if defined(TESTING) */
2068       }
2069 
2070     // lastCycle == RTCD_OPERAND_FETCH
2071 
2072     if (thisCycle == INSTRUCTION_FETCH &&
2073         i->opcode == 0610  && ! i->opcodeX)
2074       {
2075         // C(PPR.PRR) -> C(PRn.RNR) for n = (0, 1, ..., 7)
2076         // Use TRR here; PRR not set until KL
2077         CPTUR (cptUsePRn + 0);
2078         CPTUR (cptUsePRn + 1);
2079         CPTUR (cptUsePRn + 2);
2080         CPTUR (cptUsePRn + 3);
2081         CPTUR (cptUsePRn + 4);
2082         CPTUR (cptUsePRn + 5);
2083         CPTUR (cptUsePRn + 6);
2084         CPTUR (cptUsePRn + 7);
2085         cpu.PR[0].RNR =
2086         cpu.PR[1].RNR =
2087         cpu.PR[2].RNR =
2088         cpu.PR[3].RNR =
2089         cpu.PR[4].RNR =
2090         cpu.PR[5].RNR =
2091         cpu.PR[6].RNR =
2092         cpu.PR[7].RNR = cpu.TPR.TRR;
2093 # if defined(TESTING)
2094         HDBGRegPRW (0, "app rtcd");
2095         HDBGRegPRW (1, "app rtcd");
2096         HDBGRegPRW (2, "app rtcd");
2097         HDBGRegPRW (3, "app rtcd");
2098         HDBGRegPRW (4, "app rtcd");
2099         HDBGRegPRW (5, "app rtcd");
2100         HDBGRegPRW (6, "app rtcd");
2101         HDBGRegPRW (7, "app rtcd");
2102 # endif /* if defined(TESTING) */
2103       }
2104     goto KL;
2105 
2106 KL:
2107     DBGAPP ("do_append_cycle(KL)\n");
2108 
2109     // C(TPR.TSR) -> C(PPR.PSR)
2110     cpu.PPR.PSR   = cpu.TPR.TSR;
2111     // C(TPR.CA)  -> C(PPR.IC)
2112     cpu.PPR.IC    = cpu.TPR.CA;
2113 
2114     goto M;
2115 
2116 M: // Set P
2117     DBGAPP ("do_append_cycle(M)\n");
2118 
2119     // C(TPR.TRR) = 0?
2120     if (cpu.TPR.TRR == 0)
2121       {
2122         // C(SDW.P) -> C(PPR.P)
2123         cpu.PPR.P = cpu.SDW->P;
2124       }
2125     else
2126       {
2127         // 0 C(PPR.P)
2128         cpu.PPR.P = 0;
2129       }
2130 
2131     goto Exit;
2132 
2133 N: // CALL6
2134     DBGAPP ("do_append_cycle(N)\n");
2135 
2136     // C(TPR.TRR) = C(PPR.PRR)?
2137     if (cpu.TPR.TRR == cpu.PPR.PRR)
2138       {
2139         // C(PR6.SNR) -> C(PR7.SNR)
2140         cpu.PR[7].SNR = cpu.PR[6].SNR;
2141         DBGAPP ("do_append_cycle(N) PR7.SNR = PR6.SNR %05o\n", cpu.PR[7].SNR);
2142       }
2143     else
2144       {
2145         // C(DSBR.STACK) || C(TPR.TRR) -> C(PR7.SNR)
2146         cpu.PR[7].SNR = ((word15) (cpu.DSBR.STACK << 3)) | cpu.TPR.TRR;
2147         DBGAPP ("do_append_cycle(N) STACK %05o TRR %o\n",
2148                 cpu.DSBR.STACK, cpu.TPR.TRR);
2149         DBGAPP ("do_append_cycle(N) PR7.SNR = STACK||TRR  %05o\n", cpu.PR[7].SNR);
2150       }
2151 
2152     // C(TPR.TRR) -> C(PR7.RNR)
2153     cpu.PR[7].RNR = cpu.TPR.TRR;
2154     // 00...0 -> C(PR7.WORDNO)
2155     cpu.PR[7].WORDNO = 0;
2156     // 000000 -> C(PR7.BITNO)
2157     SET_PR_BITNO (7, 0);
2158 # if defined(TESTING)
2159     HDBGRegPRW (7, "app call6");
2160 # endif /* if defined(TESTING) */
2161     // C(TPR.TRR) -> C(PPR.PRR)
2162     cpu.PPR.PRR   = cpu.TPR.TRR;
2163     // C(TPR.TSR) -> C(PPR.PSR)
2164     cpu.PPR.PSR   = cpu.TPR.TSR;
2165     // C(TPR.CA)  -> C(PPR.IC)
2166     cpu.PPR.IC    = cpu.TPR.CA;
2167 
2168     goto M;
2169 
2170 ////////////////////////////////////////
2171 //
2172 // Sheet 11: "O", "P"
2173 //
2174 ////////////////////////////////////////
2175 
2176 O:; // ITS, RTCD
2177     DBGAPP ("do_append_cycle(O)\n");
2178     word3 its_RNR = GET_ITS_RN (data);
2179     DBGAPP ("do_append_cycle(O) TRR %o RSDWH.R1 %o ITS.RNR %o\n",
2180             cpu.TPR.TRR, cpu.RSDWH_R1, its_RNR);
2181 
2182     // Maximum of
2183     //  C(Y)18,20;  C(TPR.TRR); C(SDW.R1) -> C(TPR.TRR)
2184     cpu.TPR.TRR = max3 (its_RNR, cpu.TPR.TRR, cpu.RSDWH_R1);
2185     DBGAPP ("do_append_cycle(O) Set TRR to %o\n", cpu.TPR.TRR);
2186 
2187     goto Exit;
2188 
2189 P:; // ITP
2190 
2191     DBGAPP ("do_append_cycle(P)\n");
2192 
2193     n = GET_ITP_PRNUM (data);
2194     DBGAPP ("do_append_cycle(P) TRR %o RSDWH.R1 %o PR[n].RNR %o\n",
2195             cpu.TPR.TRR, cpu.RSDWH_R1, cpu.PR[n].RNR);
2196 
2197     // Maximum of
2198     // cpu.PR[n].RNR;  C(TPR.TRR); C(SDW.R1) -> C(TPR.TRR)
2199     cpu.TPR.TRR = max3 (cpu.PR[n].RNR, cpu.TPR.TRR, cpu.RSDWH_R1);
2200     DBGAPP ("do_append_cycle(P) Set TRR to %o\n", cpu.TPR.TRR);
2201 
2202     goto Exit;
2203 
2204 Exit:;
2205 
2206     PNL (cpu.APUDataBusOffset = cpu.TPR.CA;)
2207     PNL (cpu.APUDataBusAddr = finalAddress;)
2208 
2209     PNL (L68_ (cpu.apu.state |= apu_FA;))
2210 
2211     DBGAPP ("do_append_cycle (Exit) PRR %o PSR %05o P %o IC %06o\n",
2212             cpu.PPR.PRR, cpu.PPR.PSR, cpu.PPR.P, cpu.PPR.IC);
2213     DBGAPP ("do_append_cycle (Exit) TRR %o TSR %05o TBR %02o CA %06o\n",
2214             cpu.TPR.TRR, cpu.TPR.TSR, cpu.TPR.TBR, cpu.TPR.CA);
2215 
2216     return finalAddress;    // or 0 or -1???
2217   }
2218 #endif /* if defined(OLDAPP) */
2219 
2220 // Translate a segno:offset to a absolute address.
2221 // Return 0 if successful.
2222 
2223 #if defined(TESTING)
2224 int dbgLookupAddress (word18 segno, word18 offset, word24 * finalAddress,
     /* [previous][next][first][last][top][bottom][index][help] */
2225                       char * * msg)
2226   {
2227     cpu_state_t * cpup = _cpup;
2228     // Local copies so we don't disturb machine state
2229 
2230     ptw_s PTW1;
2231     sdw_s SDW1;
2232 
2233    if (2u * segno >= 16u * (cpu.DSBR.BND + 1u))
2234      {
2235        if (msg)
2236          * msg = "DSBR boundary violation.";
2237        return 1;
2238      }
2239 
2240     if (cpu.DSBR.U == 0)
2241       {
2242         // fetch_dsptw
2243 
2244         word24 y1 = (2 * segno) % 1024;
2245         word24 x1 = (2 * segno) / 1024; // floor
2246 
2247         word36 PTWx1;
2248         core_read (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
2249 
2250         PTW1.ADDR = GETHI (PTWx1);
2251         PTW1.U = TSTBIT (PTWx1, 9);
2252         PTW1.M = TSTBIT (PTWx1, 6);
2253         PTW1.DF = TSTBIT (PTWx1, 2);
2254         PTW1.FC = PTWx1 & 3;
2255 
2256         if (! PTW1.DF)
2257           {
2258             if (msg)
2259               * msg = "!PTW0.F";
2260             return 2;
2261           }
2262 
2263         // fetch_psdw
2264 
2265         y1 = (2 * segno) % 1024;
2266 
2267         word36 SDWeven, SDWodd;
2268 
2269         core_read2 (cpup, ((((word24)PTW1. ADDR & 0777760) << 6) + y1) & PAMASK,
2270                     & SDWeven, & SDWodd, __func__);
2271 
2272         // even word
2273         SDW1.ADDR = (SDWeven >> 12) & 077777777;
2274         SDW1.R1   = (SDWeven >> 9)  & 7;
2275         SDW1.R2   = (SDWeven >> 6)  & 7;
2276         SDW1.R3   = (SDWeven >> 3)  & 7;
2277         SDW1.DF   = TSTBIT (SDWeven, 2);
2278         SDW1.FC   = SDWeven & 3;
2279 
2280         // odd word
2281         SDW1.BOUND = (SDWodd >> 21) & 037777;
2282         SDW1.R     = TSTBIT (SDWodd, 20);
2283         SDW1.E     = TSTBIT (SDWodd, 19);
2284         SDW1.W     = TSTBIT (SDWodd, 18);
2285         SDW1.P     = TSTBIT (SDWodd, 17);
2286         SDW1.U     = TSTBIT (SDWodd, 16);
2287         SDW1.G     = TSTBIT (SDWodd, 15);
2288         SDW1.C     = TSTBIT (SDWodd, 14);
2289         SDW1.EB    = SDWodd & 037777;
2290       }
2291     else // ! DSBR.U
2292       {
2293         // fetch_nsdw
2294 
2295         word36 SDWeven, SDWodd;
2296 
2297         core_read2 (cpup, (cpu.DSBR.ADDR + 2 * segno) & PAMASK,
2298                     & SDWeven, & SDWodd, __func__);
2299 
2300         // even word
2301         SDW1.ADDR = (SDWeven >> 12) & 077777777;
2302         SDW1.R1   = (SDWeven >> 9)  & 7;
2303         SDW1.R2   = (SDWeven >> 6)  & 7;
2304         SDW1.R3   = (SDWeven >> 3)  & 7;
2305         SDW1.DF   = TSTBIT (SDWeven, 2);
2306         SDW1.FC   = SDWeven & 3;
2307 
2308         // odd word
2309         SDW1.BOUND = (SDWodd >> 21) & 037777;
2310         SDW1.R     = TSTBIT (SDWodd, 20);
2311         SDW1.E     = TSTBIT (SDWodd, 19);
2312         SDW1.W     = TSTBIT (SDWodd, 18);
2313         SDW1.P     = TSTBIT (SDWodd, 17);
2314         SDW1.U     = TSTBIT (SDWodd, 16);
2315         SDW1.G     = TSTBIT (SDWodd, 15);
2316         SDW1.C     = TSTBIT (SDWodd, 14);
2317         SDW1.EB    = SDWodd & 037777;
2318 
2319       }
2320 
2321     if (SDW1.DF == 0)
2322       {
2323         if (msg)
2324           * msg = "!SDW0.F != 0";
2325         return 3;
2326       }
2327 
2328     if (((offset >> 4) & 037777) > SDW1.BOUND)
2329       {
2330         if (msg)
2331           * msg = "C(TPR.CA)0,13 > SDW.BOUND";
2332         return 4;
2333       }
2334 
2335     // is segment C(TPR.TSR) paged?
2336     if (SDW1.U)
2337       {
2338         * finalAddress = (SDW1.ADDR + offset) & PAMASK;
2339       }
2340     else
2341       {
2342         // fetch_ptw
2343         word24 y2 = offset % 1024;
2344         word24 x2 = (offset) / 1024; // floor
2345 
2346         word36 PTWx2;
2347 
2348         core_read (cpup, (SDW1.ADDR + x2) & PAMASK, & PTWx2, __func__);
2349 
2350         PTW1.ADDR = GETHI (PTWx2);
2351         PTW1.U    = TSTBIT (PTWx2, 9);
2352         PTW1.M    = TSTBIT (PTWx2, 6);
2353         PTW1.DF   = TSTBIT (PTWx2, 2);
2354         PTW1.FC   = PTWx2 & 3;
2355 
2356         if (! PTW1.DF)
2357           {
2358             if (msg)
2359               * msg = "!PTW0.F";
2360             return 5;
2361           }
2362 
2363         y2 = offset % 1024;
2364 
2365         * finalAddress = ((((word24)PTW1.ADDR & 0777760) << 6) + y2) & PAMASK;
2366       }
2367     if (msg)
2368       * msg = "";
2369     return 0;
2370   }
2371 #endif /* if defined(TESTING) */

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