root/src/dps8/doAppendCycleIndirectWordFetch.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. doAppendCycleIndirectWordFetch

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 501f8fe6-171d-11ee-ab15-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2022-2023 Charles Anthony
   9  * Copyright (c) 2022-2023 Jeffrey H. Johnson <trnsz@pobox.com>
  10  * Copyright (c) 2023-2023 The DPS8M Development Team
  11  *
  12  * All rights reserved.
  13  *
  14  * This software is made available under the terms of the ICU
  15  * License, version 1.8.1 or later.  For more details, see the
  16  * LICENSE.md file at the top-level directory of this distribution.
  17  *
  18  * ---------------------------------------------------------------------------
  19  */
  20 
  21 //  Indirect word fetch
  22 //
  23 //     A: Get SDW
  24 //         |
  25 //         V
  26 //     B: Check the ring
  27 //         |
  28 //         V
  29 //     G: Check BOUND
  30 //        Paged? No-------------------+
  31 //          Yes                       |
  32 //           |                        |
  33 //           V                        |
  34 //        Get PTW                     |
  35 //           |                        |
  36 //           V                        V
  37 //     I: Compute final address   H: Compute final address
  38 //           |                        |
  39 //           <------------------------+
  40 //           |
  41 //           V
  42 //     HI: Read data
  43 //           |
  44 //           V
  45 //     J: ITS? Yes------------------+
  46 //        ITP? Yes----+             |
  47 //          |         |             |
  48 //          |         V             V
  49 //          |       P: ITP        O: ITS
  50 //          |       Update TRR     Update TRR
  51 //          |         |             |
  52 //          +<--------+-------------+
  53 //          |
  54 //          V
  55 //        Exit: return final address
  56 
  57 word24 doAppendCycleIndirectWordFetch (word36 * data, uint nWords) {
     /* [previous][next][first][last][top][bottom][index][help] */
  58   DCDstruct * i = & cpu.currentInstruction;
  59   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) thisCycle=INDIRECT_WORD_FETCH\n");
  60   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) lastCycle=%s\n", str_pct (cpu.apu.lastCycle));
  61   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) CA %06o\n", cpu.TPR.CA);
  62   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) n=%2u\n", nWords);
  63   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) PPR.PRR=%o PPR.PSR=%05o\n", cpu.PPR.PRR, cpu.PPR.PSR);
  64   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) TPR.TRR=%o TPR.TSR=%05o\n", cpu.TPR.TRR, cpu.TPR.TSR);
  65 
  66   if (i->b29) {
  67     DBGAPP ("doAppendCycleIndirectWordFetch(Entry) isb29 PRNO %o\n", GET_PRN (IWB_IRODD));
  68   }
  69 
  70   uint this = UC_INDIRECT_WORD_FETCH;
  71 
  72   word24 finalAddress = 0;
  73   word24 pageAddress = 0;
  74   word3 RSDWH_R1 = 0;
  75   word14 bound = 0;
  76   word1 p = 0;
  77   bool paged = false;
  78 
  79 /* Indirect Word Fetch Cache disabled (due to it not working!) */
  80 #undef IDWF_CACHE
  81 //# define IDWF_CACHE 1
  82 #ifdef IDWF_CACHE
  83 // Is this cycle a candidate for ucache?
  84 
  85   // Prepage mode?
  86   // check for "uninterruptible" EIS instruction
  87   // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
  88   // ad2/3d,sb2/3d,mp2/3d,dv2/3d
  89   // DH03 p.8-13: probably also mve,btd,dtb
  90   if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
  91       || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300)) {
  92     //sim_printf ("skip uninterruptible\r\n");
  93     goto skip_ucache;
  94   }
  95 
  96 // Yes; check the ucache
  97   if (! ucCacheCheck (this, cpu.TPR.TSR, cpu.TPR.CA, & bound, & p, & pageAddress, & RSDWH_R1, & paged))
  98     goto miss_ucache;
  99 
 100   if (paged) {
 101     finalAddress = pageAddress + (cpu.TPR.CA & OS18MASK);
 102   } else {
 103     finalAddress = pageAddress + cpu.TPR.CA;
 104   }
 105   cpu.RSDWH_R1 = RSDWH_R1;
 106 
 107   cpu.apu.lastCycle = INDIRECT_WORD_FETCH;
 108   goto HI;
 109 
 110 skip_ucache:;
 111 # ifdef UCACHE_STATS
 112   cpu.uCache.skips[this] ++;
 113 # endif
 114 
 115 miss_ucache:;
 116 
 117 #endif /* ifdef IDWF_CACHE */
 118 
 119   bool nomatch = true;
 120   if (cpu.tweaks.enable_wam) {
 121     // AL39: The associative memory is ignored (forced to "no match") during
 122     // address preparation.
 123     // lptp,lptr,lsdp,lsdr,sptp,sptr,ssdp,ssdr
 124     // Unfortunately, ISOLTS doesn't try to execute any of these in append mode.
 125     // XXX should this be only for OPERAND_READ and OPERAND_STORE?
 126     nomatch = ((i->opcode == 0232 || i->opcode == 0254 ||
 127                 i->opcode == 0154 || i->opcode == 0173) &&
 128                 i->opcodeX ) ||
 129                ((i->opcode == 0557 || i->opcode == 0257) &&
 130                 ! i->opcodeX);
 131   }
 132 
 133   processor_cycle_type lastCycle = cpu.apu.lastCycle;
 134   cpu.apu.lastCycle = INDIRECT_WORD_FETCH;
 135 
 136   DBGAPP ("doAppendCycleIndirectWordFetch(Entry) XSF %o\n", cpu.cu.XSF);
 137 
 138   PNL (L68_ (cpu.apu.state = 0;))
 139 
 140   cpu.RSDWH_R1 = 0;
 141 
 142   cpu.acvFaults = 0;
 143 
 144 //#define FMSG(x) x
 145 #define FMSG(x)
 146   FMSG (char * acvFaultsMsg = "<unknown>";)
 147 
 148 ////////////////////////////////////////
 149 //
 150 // Sheet 1: "START APPEND"
 151 //
 152 ////////////////////////////////////////
 153 
 154 // START APPEND
 155   word3 n = 0; // PRn to be saved to TSN_PRNO
 156 
 157 ////////////////////////////////////////
 158 //
 159 // Sheet 2: "A"
 160 //
 161 ////////////////////////////////////////
 162 
 163 //
 164 //  A:
 165 //    Get SDW
 166 
 167   //PNL (cpu.APUMemAddr = address;)
 168   PNL (cpu.APUMemAddr = cpu.TPR.CA;)
 169 
 170   DBGAPP ("doAppendCycleIndirectWordFetch(A)\n");
 171 
 172   // is SDW for C(TPR.TSR) in SDWAM?
 173   if (nomatch || ! fetch_sdw_from_sdwam (cpu.TPR.TSR)) {
 174     // No
 175     DBGAPP ("doAppendCycleIndirectWordFetch(A):SDW for segment %05o not in SDWAM\n", cpu.TPR.TSR);
 176     DBGAPP ("doAppendCycleIndirectWordFetch(A):DSBR.U=%o\n", cpu.DSBR.U);
 177 
 178     if (cpu.DSBR.U == 0) {
 179       fetch_dsptw (cpu.TPR.TSR);
 180 
 181       if (! cpu.PTW0.DF)
 182         doFault (FAULT_DF0 + cpu.PTW0.FC, fst_zero, "doAppendCycleIndirectWordFetch(A): PTW0.F == 0");
 183 
 184       if (! cpu.PTW0.U)
 185           modify_dsptw (cpu.TPR.TSR);
 186 
 187       fetch_psdw (cpu.TPR.TSR);
 188     } else
 189       fetch_nsdw (cpu.TPR.TSR); // load SDW0 from descriptor segment table.
 190 
 191     if (cpu.SDW0.DF == 0) {
 192       DBGAPP ("doAppendCycleIndirectWordFetch(A): SDW0.F == 0! " "Initiating directed fault\n");
 193       // initiate a directed fault ...
 194       doFault (FAULT_DF0 + cpu.SDW0.FC, fst_zero, "SDW0.F == 0");
 195     }
 196     // load SDWAM .....
 197     load_sdwam (cpu.TPR.TSR, nomatch);
 198   }
 199   DBGAPP ("doAppendCycleIndirectWordFetch(A) R1 %o R2 %o R3 %o E %o\n", cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3, cpu.SDW->E);
 200 
 201   // Yes...
 202   RSDWH_R1 = cpu.RSDWH_R1 = cpu.SDW->R1;
 203 
 204 ////////////////////////////////////////
 205 //
 206 // Sheet 3: "B"
 207 //
 208 ////////////////////////////////////////
 209 
 210 //
 211 // B: Check the ring
 212 //
 213 
 214   DBGAPP ("doAppendCycleIndirectWordFetch(B)\n");
 215 
 216   // check ring bracket consistency
 217 
 218   //C(SDW.R1) <= C(SDW.R2) <= C(SDW .R3)?
 219   if (! (cpu.SDW->R1 <= cpu.SDW->R2 && cpu.SDW->R2 <= cpu.SDW->R3)) {
 220     // Set fault ACV0 = IRO
 221     cpu.acvFaults |= ACV0;
 222     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 223     FMSG (acvFaultsMsg = "acvFaults(B) C(SDW.R1) <= C(SDW.R2) <= " "C(SDW .R3)";)
 224   }
 225 
 226   // lastCycle == RTCD_OPERAND_FETCH
 227   // if a fault happens between the RTCD_OPERAND_FETCH and the INSTRUCTION_FETCH
 228   // of the next instruction - this happens about 35 time for just booting  and
 229   // shutting down multics -- a stored lastCycle is useless.
 230   // the opcode is preserved across faults and only replaced as the
 231   // INSTRUCTION_FETCH succeeds.
 232   if (lastCycle == RTCD_OPERAND_FETCH)
 233     sim_warn ("%s: lastCycle == RTCD_OPERAND_FETCH opcode %0#o\n", __func__, i->opcode);
 234 
 235   //
 236   // B1: The operand is one of: an instruction, data to be read or data to be
 237   //     written
 238   //
 239 
 240   //
 241   // check read bracket for read access
 242   //
 243 
 244   DBGAPP ("doAppendCycleIndirectWordFetch(B):!STR-OP\n");
 245 
 246   // No
 247   // C(TPR.TRR) > C(SDW .R2)?
 248   if (cpu.TPR.TRR > cpu.SDW->R2) {
 249     DBGAPP ("ACV3\n");
 250     DBGAPP ("doAppendCycleIndirectWordFetch(B) ACV3\n");
 251     //Set fault ACV3 = ORB
 252     cpu.acvFaults |= ACV3;
 253     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 254     FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R2)";)
 255   }
 256 
 257   if (cpu.SDW->R == 0) {
 258     // isolts 870
 259     cpu.TPR.TRR = cpu.PPR.PRR;
 260 
 261     //C(PPR.PSR) = C(TPR.TSR)?
 262     if (cpu.PPR.PSR != cpu.TPR.TSR) {
 263       DBGAPP ("ACV4\n");
 264       DBGAPP ("doAppendCycleIndirectWordFetch(B) ACV4\n");
 265       //Set fault ACV4 = R-OFF
 266       cpu.acvFaults |= ACV4;
 267       PNL (L68_ (cpu.apu.state |= apu_FLT;))
 268       FMSG (acvFaultsMsg = "acvFaults(B) C(PPR.PSR) = C(TPR.TSR)";)
 269     //} else {
 270       // sim_warn ("doAppendCycleIndirectWordFetch(B) SDW->R == 0 && cpu.PPR.PSR == cpu.TPR.TSR: %0#o\n", cpu.PPR.PSR);
 271     }
 272   }
 273 
 274 //  goto G;
 275 
 276 ////////////////////////////////////////
 277 //
 278 // Sheet 7: "G"
 279 //
 280 ////////////////////////////////////////
 281 
 282 //G:;
 283 
 284   DBGAPP ("doAppendCycleIndirectWordFetch(G)\n");
 285 
 286   //C(TPR.CA)0,13 > SDW.BOUND?
 287   if (((cpu.TPR.CA >> 4) & 037777) > cpu.SDW->BOUND) {
 288     DBGAPP ("ACV15\n");
 289     DBGAPP ("doAppendCycleIndirectWordFetch(G) ACV15\n");
 290     cpu.acvFaults |= ACV15;
 291     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 292     FMSG (acvFaultsMsg = "acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND";)
 293     DBGAPP ("acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND\n" "   CA %06o CA>>4 & 037777 %06o SDW->BOUND %06o", cpu.TPR.CA, ((cpu.TPR.CA >> 4) & 037777), cpu.SDW->BOUND);
 294   }
 295   bound = cpu.SDW->BOUND;
 296   p = cpu.SDW->P;
 297 
 298   if (cpu.acvFaults) {
 299     DBGAPP ("doAppendCycleIndirectWordFetch(G) acvFaults\n");
 300     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 301     // Initiate an access violation fault
 302     doFault (FAULT_ACV, (_fault_subtype) {.fault_acv_subtype=cpu.acvFaults}, "ACV fault");
 303   }
 304 
 305   // is segment C(TPR.TSR) paged?
 306   if (cpu.SDW->U)
 307     goto H; // Not paged
 308 
 309   // Yes. segment is paged ...
 310   // is PTW for C(TPR.CA) in PTWAM?
 311 
 312   DBGAPP ("doAppendCycleIndirectWordFetch(G) CA %06o\n", cpu.TPR.CA);
 313   if (nomatch ||
 314       ! fetch_ptw_from_ptwam (cpu.SDW->POINTER, cpu.TPR.CA)) {
 315     fetch_ptw (cpu.SDW, cpu.TPR.CA);
 316     if (! cpu.PTW0.DF) {
 317       // initiate a directed fault
 318       doFault (FAULT_DF0 + cpu.PTW0.FC, (_fault_subtype) {.bits=0}, "PTW0.F == 0");
 319     }
 320     loadPTWAM (cpu.SDW->POINTER, cpu.TPR.CA, nomatch); // load PTW0 to PTWAM
 321   }
 322 
 323   // Prepage mode?
 324   // check for "uninterruptible" EIS instruction
 325   // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
 326   // ad2/3d,sb2/3d,mp2/3d,dv2/3d
 327   // DH03 p.8-13: probably also mve,btd,dtb
 328   if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
 329       || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300)) {
 330     do_ptw2 (cpu.SDW, cpu.TPR.CA);
 331   }
 332   goto I;
 333 
 334 ////////////////////////////////////////
 335 //
 336 // Sheet 8: "H", "I"
 337 //
 338 ////////////////////////////////////////
 339 
 340 H:;
 341   DBGAPP ("doAppendCycleIndirectWordFetch(H): FANP\n");
 342 
 343   paged = false;
 344 
 345   PNL (L68_ (cpu.apu.state |= apu_FANP;))
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 
 354   set_apu_status (apuStatus_FANP);
 355 
 356   DBGAPP ("doAppendCycleIndirectWordFetch(H): SDW->ADDR=%08o CA=%06o \n", cpu.SDW->ADDR, cpu.TPR.CA);
 357 
 358   pageAddress = (cpu.SDW->ADDR & 077777760);
 359   finalAddress = (cpu.SDW->ADDR & 077777760) + cpu.TPR.CA;
 360   finalAddress &= 0xffffff;
 361   PNL (cpu.APUMemAddr = finalAddress;)
 362 
 363   DBGAPP ("doAppendCycleIndirectWordFetch(H:FANP): (%05o:%06o) finalAddress=%08o\n", cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
 364 
 365   goto HI;
 366 
 367 I:;
 368 
 369 // Set PTW.M
 370 
 371   DBGAPP ("doAppendCycleIndirectWordFetch(I): FAP\n");
 372 
 373   paged = true;
 374 
 375   // final address paged
 376   set_apu_status (apuStatus_FAP);
 377   PNL (L68_ (cpu.apu.state |= apu_FAP;))
 378 
 379   word24 y2 = cpu.TPR.CA % 1024;
 380 
 381   pageAddress = (((word24)cpu.PTW->ADDR & 0777760) << 6);
 382   // AL39: The hardware ignores low order bits of the main memory page
 383   // address according to page size
 384   finalAddress = (((word24)cpu.PTW->ADDR & 0777760) << 6) + y2;
 385   finalAddress &= 0xffffff;
 386   PNL (cpu.APUMemAddr = finalAddress;)
 387 
 388 #ifdef L68
 389   if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 390     add_APU_history (APUH_FAP);
 391 #endif
 392   DBGAPP ("doAppendCycleIndirectWordFetch(H:FAP): (%05o:%06o) finalAddress=%08o\n", cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
 393 
 394   // goto HI;
 395 
 396 HI:
 397   DBGAPP ("doAppendCycleIndirectWordFetch(HI)\n");
 398 
 399   ucCacheSave (this, cpu.TPR.TSR, cpu.TPR.CA, bound, p, pageAddress, RSDWH_R1, paged);
 400 
 401   // isolts 870
 402   cpu.cu.XSF = 1;
 403   sim_debug (DBG_TRACEEXT, & cpu_dev, "loading of cpu.TPR.TSR sets XSF to 1\n");
 404 
 405   core_readN (finalAddress, data, nWords, "INDIRECT_WORD_FETCH");
 406 
 407 ////////////////////////////////////////
 408 //
 409 // Sheet 9: "J"
 410 //
 411 ////////////////////////////////////////
 412 
 413 // Indirect operand fetch
 414 
 415   DBGAPP ("doAppendCycleIndirectWordFetch(J)\n");
 416 
 417   // ri or ir & TPC.CA even?
 418   word6 tag = GET_TAG (IWB_IRODD);
 419   if ((GET_TM (tag) == TM_IR || GET_TM (tag) == TM_RI) && (cpu.TPR.CA & 1) == 0) {
 420     if (ISITS (* data))
 421       goto O;
 422     if (ISITP (* data))
 423       goto P;
 424   }
 425 
 426   goto Exit;
 427 
 428 ////////////////////////////////////////
 429 //
 430 // Sheet 11: "O", "P"
 431 //
 432 ////////////////////////////////////////
 433 
 434 O:; // ITS, RTCD
 435   DBGAPP ("doAppendCycleIndirectWordFetch(O)\n");
 436   word3 its_RNR = GET_ITS_RN (data);
 437   DBGAPP ("doAppendCycleIndirectWordFetch(O) TRR %o RSDWH.R1 %o ITS.RNR %o\n", cpu.TPR.TRR, cpu.RSDWH_R1, its_RNR);
 438 
 439   // Maximum of
 440   //  C(Y)18,20;  C(TPR.TRR); C(SDW.R1) -> C(TPR.TRR)
 441   cpu.TPR.TRR = max3 (its_RNR, cpu.TPR.TRR, cpu.RSDWH_R1);
 442   DBGAPP ("doAppendCycleIndirectWordFetch(O) Set TRR to %o\n", cpu.TPR.TRR);
 443 
 444   goto Exit;
 445 
 446 P:; // ITP
 447 
 448   DBGAPP ("doAppendCycleIndirectWordFetch(P)\n");
 449 
 450   n = GET_ITP_PRNUM (data);
 451   DBGAPP ("doAppendCycleIndirectWordFetch(P) TRR %o RSDWH.R1 %o PR[n].RNR %o\n", cpu.TPR.TRR, cpu.RSDWH_R1, cpu.PR[n].RNR);
 452 
 453   // Maximum of
 454   // cpu.PR[n].RNR;  C(TPR.TRR); C(SDW.R1) -> C(TPR.TRR)
 455   cpu.TPR.TRR = max3 (cpu.PR[n].RNR, cpu.TPR.TRR, cpu.RSDWH_R1);
 456   DBGAPP ("doAppendCycleIndirectWordFetch(P) Set TRR to %o\n", cpu.TPR.TRR);
 457 
 458   goto Exit;
 459 
 460 Exit:;
 461 
 462   PNL (cpu.APUDataBusOffset = cpu.TPR.CA;)
 463   PNL (cpu.APUDataBusAddr = finalAddress;)
 464 
 465   PNL (L68_ (cpu.apu.state |= apu_FA;))
 466 
 467   DBGAPP ("doAppendCycleIndirectWordFetch (Exit) PRR %o PSR %05o P %o IC %06o\n", cpu.PPR.PRR, cpu.PPR.PSR, cpu.PPR.P, cpu.PPR.IC);
 468   DBGAPP ("doAppendCycleIndirectWordFetch (Exit) TRR %o TSR %05o TBR %02o CA %06o\n", cpu.TPR.TRR, cpu.TPR.TSR, cpu.TPR.TBR, cpu.TPR.CA);
 469 
 470   return finalAddress;
 471 }

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