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

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