root/src/dps8/doAppendCycleOperandRMW.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. doAppendCycleOperandRMW

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 339b75b0-171d-11ee-bb9f-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2022-2023 Charles Anthony
   9  * Copyright (c) 2022-2023 Jeffrey H. Johnson
  10  * Copyright (c) 2022-2024 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 word24 doAppendCycleOperandRMW (cpu_state_t * cpup, word36 * data, uint nWords) {
     /* [previous][next][first][last][top][bottom][index][help] */
  19   DCDstruct * i = & cpu.currentInstruction;
  20   DBGAPP ("doAppendCycleOperandRMW(Entry) thisCycle=OPERAND_RMW\n");
  21   DBGAPP ("doAppendCycleOperandRMW(Entry) lastCycle=%s\n", str_pct (cpu.apu.lastCycle));
  22   DBGAPP ("doAppendCycleOperandRMW(Entry) CA %06o\n", cpu.TPR.CA);
  23   DBGAPP ("doAppendCycleOperandRMW(Entry) n=%2u\n", nWords);
  24   DBGAPP ("doAppendCycleOperandRMW(Entry) PPR.PRR=%o PPR.PSR=%05o\n", cpu.PPR.PRR, cpu.PPR.PSR);
  25   DBGAPP ("doAppendCycleOperandRMW(Entry) TPR.TRR=%o TPR.TSR=%05o\n", cpu.TPR.TRR, cpu.TPR.TSR);
  26 
  27   if (i->b29) {
  28     DBGAPP ("doAppendCycleOperandRMW(Entry) isb29 PRNO %o\n", GET_PRN (IWB_IRODD));
  29   }
  30 
  31   bool nomatch = true;
  32   if (cpu.tweaks.enable_wam) {
  33     // AL39: The associative memory is ignored (forced to "no match") during
  34     // address preparation.
  35     // lptp,lptr,lsdp,lsdr,sptp,sptr,ssdp,ssdr
  36     // Unfortunately, ISOLTS doesn't try to execute any of these in append mode.
  37     // XXX should this be only for OPERAND_READ and OPERAND_STORE?
  38     nomatch = ((i->opcode == 0232 || i->opcode == 0254 ||
  39                 i->opcode == 0154 || i->opcode == 0173) &&
  40                 i->opcodeX ) ||
  41                ((i->opcode == 0557 || i->opcode == 0257) &&
  42                 ! i->opcodeX);
  43   }
  44 
  45   processor_cycle_type lastCycle = cpu.apu.lastCycle;
  46   cpu.apu.lastCycle = OPERAND_RMW;
  47 
  48   DBGAPP ("doAppendCycleOperandRMW(Entry) XSF %o\n", cpu.cu.XSF);
  49 
  50   PNL (L68_ (cpu.apu.state = 0;))
  51 
  52   cpu.RSDWH_R1 = 0;
  53 
  54   cpu.acvFaults = 0;
  55 
  56 //#define FMSG(x) x
  57 #define FMSG(x)
  58   FMSG (char * acvFaultsMsg = "<unknown>";)
  59 
  60   word24 finalAddress = (word24) -1;  // not everything requires a final
  61                                       // address
  62 
  63 ////////////////////////////////////////
  64 //
  65 // Sheet 2: "A"
  66 //
  67 ////////////////////////////////////////
  68 
  69 //
  70 //  A:
  71 //    Get SDW
  72 
  73   //PNL (cpu.APUMemAddr = address;)
  74   PNL (cpu.APUMemAddr = cpu.TPR.CA;)
  75 
  76   DBGAPP ("doAppendCycleOperandRMW(A)\n");
  77 
  78   // is SDW for C(TPR.TSR) in SDWAM?
  79   if (nomatch || ! fetch_sdw_from_sdwam (cpup, cpu.TPR.TSR)) {
  80     // No
  81     DBGAPP ("doAppendCycleOperandRMW(A):SDW for segment %05o not in SDWAM\n", cpu.TPR.TSR);
  82     DBGAPP ("doAppendCycleOperandRMW(A):DSBR.U=%o\n", cpu.DSBR.U);
  83 
  84     if (cpu.DSBR.U == 0) {
  85       fetch_dsptw (cpup, cpu.TPR.TSR);
  86 
  87       if (! cpu.PTW0.DF)
  88         doFault (FAULT_DF0 + cpu.PTW0.FC, fst_zero, "doAppendCycleOperandRMW(A): PTW0.F == 0");
  89 
  90       if (! cpu.PTW0.U)
  91         modify_dsptw (cpup, cpu.TPR.TSR);
  92 
  93       fetch_psdw (cpup, cpu.TPR.TSR);
  94     } else
  95       fetch_nsdw (cpup, cpu.TPR.TSR); // load SDW0 from descriptor segment table.
  96 
  97     if (cpu.SDW0.DF == 0) {
  98       DBGAPP ("doAppendCycleOperandRMW(A): SDW0.F == 0! Initiating directed fault\n");
  99       // initiate a directed fault ...
 100       doFault (FAULT_DF0 + cpu.SDW0.FC, fst_zero, "SDW0.F == 0");
 101     }
 102     // load SDWAM .....
 103     load_sdwam (cpup, cpu.TPR.TSR, nomatch);
 104   }
 105   DBGAPP ("doAppendCycleOperandRMW(A) R1 %o R2 %o R3 %o E %o\n", cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3, cpu.SDW->E);
 106 
 107   // Yes...
 108   cpu.RSDWH_R1 = cpu.SDW->R1;
 109 
 110 ////////////////////////////////////////
 111 //
 112 // Sheet 3: "B"
 113 //
 114 ////////////////////////////////////////
 115 
 116 //
 117 // B: Check the ring
 118 //
 119 
 120   DBGAPP ("doAppendCycleOperandRMW(B)\n");
 121 
 122   // check ring bracket consistency
 123 
 124   //C(SDW.R1) <= C(SDW.R2) <= C(SDW .R3)?
 125   if (! (cpu.SDW->R1 <= cpu.SDW->R2 && cpu.SDW->R2 <= cpu.SDW->R3)) {
 126     // Set fault ACV0 = IRO
 127     cpu.acvFaults |= ACV0;
 128     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 129     FMSG (acvFaultsMsg = "acvFaults(B) C(SDW.R1) <= C(SDW.R2) <= " "C(SDW .R3)";)
 130   }
 131 
 132   // lastCycle == RTCD_OPERAND_FETCH
 133   // if a fault happens between the RTCD_OPERAND_FETCH and the INSTRUCTION_FETCH
 134   // of the next instruction - this happens about 35 time for just booting  and
 135   // shutting down multics -- a stored lastCycle is useless.
 136   // the opcode is preserved across faults and only replaced as the
 137   // INSTRUCTION_FETCH succeeds.
 138   if (lastCycle == RTCD_OPERAND_FETCH)
 139     sim_warn ("%s: lastCycle == RTCD_OPERAND_FETCH opcode %0#o\n", __func__, i->opcode);
 140 
 141   //
 142   // B1: The operand is one of: an instruction, data to be read or data to be
 143   //     written
 144   //
 145 
 146   //
 147   // check read bracket for read access
 148   //
 149 
 150   DBGAPP ("doAppendCycleOperandRMW(B):!STR-OP\n");
 151 
 152   // No
 153   // C(TPR.TRR) > C(SDW .R2)?
 154   if (cpu.TPR.TRR > cpu.SDW->R2) {
 155     DBGAPP ("ACV3\n");
 156     DBGAPP ("doAppendCycleOperandRMW(B) ACV3\n");
 157     //Set fault ACV3 = ORB
 158     cpu.acvFaults |= ACV3;
 159     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 160     FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R2)";)
 161   }
 162 
 163   if (cpu.SDW->R == 0) {
 164     // isolts 870
 165     cpu.TPR.TRR = cpu.PPR.PRR;
 166 
 167     //C(PPR.PSR) = C(TPR.TSR)?
 168     if (cpu.PPR.PSR != cpu.TPR.TSR) {
 169       DBGAPP ("ACV4\n");
 170       DBGAPP ("doAppendCycleOperandRMW(B) ACV4\n");
 171       //Set fault ACV4 = R-OFF
 172       cpu.acvFaults |= ACV4;
 173       PNL (L68_ (cpu.apu.state |= apu_FLT;))
 174       FMSG (acvFaultsMsg = "acvFaults(B) C(PPR.PSR) = C(TPR.TSR)";)
 175     //} else {
 176       // sim_warn ("doAppendCycleOperandRMW(B) SDW->R == 0 && cpu.PPR.PSR == cpu.TPR.TSR: %0#o\n", cpu.PPR.PSR);
 177     }
 178   }
 179 
 180   //
 181   // check write bracket for write access
 182   //
 183   DBGAPP ("doAppendCycleOperandRMW(B):STR-OP\n");
 184 
 185   // isolts 870
 186   if (cpu.TPR.TSR == cpu.PPR.PSR)
 187     cpu.TPR.TRR = cpu.PPR.PRR;
 188 
 189   // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
 190   if (cpu.TPR.TRR > cpu.SDW->R1) {
 191     DBGAPP ("ACV5 TRR %o R1 %o\n", cpu.TPR.TRR, cpu.SDW->R1);
 192     //Set fault ACV5 = OWB
 193     cpu.acvFaults |= ACV5;
 194     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 195     FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
 196   }
 197 
 198   if (! cpu.SDW->W) {
 199     // isolts 870
 200     cpu.TPR.TRR = cpu.PPR.PRR;
 201 
 202     DBGAPP ("ACV6\n");
 203     // Set fault ACV6 = W-OFF
 204     cpu.acvFaults |= ACV6;
 205     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 206     FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
 207   }
 208 
 209   goto G;
 210 
 211 ////////////////////////////////////////
 212 //
 213 // Sheet 7: "G"
 214 //
 215 ////////////////////////////////////////
 216 
 217 G:;
 218 
 219   DBGAPP ("doAppendCycleOperandRMW(G)\n");
 220 
 221   //C(TPR.CA)0,13 > SDW.BOUND?
 222   if (((cpu.TPR.CA >> 4) & 037777) > cpu.SDW->BOUND) {
 223     DBGAPP ("ACV15\n");
 224     DBGAPP ("doAppendCycleOperandRMW(G) ACV15\n");
 225     cpu.acvFaults |= ACV15;
 226     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 227     FMSG (acvFaultsMsg = "acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND";)
 228     DBGAPP ("acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND\n" "   CA %06o CA>>4 & 037777 %06o SDW->BOUND %06o",
 229             cpu.TPR.CA, ((cpu.TPR.CA >> 4) & 037777), cpu.SDW->BOUND);
 230   }
 231 
 232   if (cpu.acvFaults) {
 233     DBGAPP ("doAppendCycleOperandRMW(G) acvFaults\n");
 234     PNL (L68_ (cpu.apu.state |= apu_FLT;))
 235     // Initiate an access violation fault
 236     doFault (FAULT_ACV, (_fault_subtype) {.fault_acv_subtype=cpu.acvFaults}, "ACV fault");
 237   }
 238 
 239   // is segment C(TPR.TSR) paged?
 240   if (cpu.SDW->U)
 241     goto H; // Not paged
 242 
 243   // Yes. segment is paged ...
 244   // is PTW for C(TPR.CA) in PTWAM?
 245 
 246   DBGAPP ("doAppendCycleOperandRMW(G) CA %06o\n", cpu.TPR.CA);
 247   if (nomatch || ! fetch_ptw_from_ptwam (cpup, cpu.SDW->POINTER, cpu.TPR.CA))  {
 248     fetch_ptw (cpup, cpu.SDW, cpu.TPR.CA);
 249     if (! cpu.PTW0.DF) {
 250       // initiate a directed fault
 251       doFault (FAULT_DF0 + cpu.PTW0.FC, (_fault_subtype) {.bits=0}, "PTW0.F == 0");
 252     }
 253     loadPTWAM (cpup, cpu.SDW->POINTER, cpu.TPR.CA, nomatch); // load PTW0 to PTWAM
 254   }
 255 
 256   // Prepage mode?
 257   // check for "uninterruptible" EIS instruction
 258   // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
 259   // ad2/3d,sb2/3d,mp2/3d,dv2/3d
 260   // DH03 p.8-13: probably also mve,btd,dtb
 261   if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
 262       || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300)) {
 263     do_ptw2 (cpup, cpu.SDW, cpu.TPR.CA);
 264   }
 265   goto I;
 266 
 267 ////////////////////////////////////////
 268 //
 269 // Sheet 8: "H", "I"
 270 //
 271 ////////////////////////////////////////
 272 
 273 H:;
 274   DBGAPP ("doAppendCycleOperandRMW(H): FANP\n");
 275 
 276   PNL (L68_ (cpu.apu.state |= apu_FANP;))
 277 
 278 
 279 
 280 
 281 
 282 
 283 
 284   set_apu_status (cpup, apuStatus_FANP);
 285 
 286   DBGAPP ("doAppendCycleOperandRMW(H): SDW->ADDR=%08o CA=%06o \n", cpu.SDW->ADDR, cpu.TPR.CA);
 287 
 288   finalAddress = (cpu.SDW->ADDR & 077777760) + cpu.TPR.CA;
 289   finalAddress &= 0xffffff;
 290   PNL (cpu.APUMemAddr = finalAddress;)
 291 
 292   DBGAPP ("doAppendCycleOperandRMW(H:FANP): (%05o:%06o) finalAddress=%08o\n", cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
 293 
 294   goto HI;
 295 
 296 I:;
 297 
 298 // Set PTW.M
 299 
 300   DBGAPP ("doAppendCycleOperandRMW(I): FAP\n");
 301   if (cpu.PTW->M == 0)  // is this the right way to do this?
 302     modify_ptw (cpup, cpu.SDW, cpu.TPR.CA);
 303 
 304   // final address paged
 305   set_apu_status (cpup, apuStatus_FAP);
 306   PNL (L68_ (cpu.apu.state |= apu_FAP;))
 307 
 308   word24 y2 = cpu.TPR.CA % 1024;
 309 
 310   // AL39: The hardware ignores low order bits of the main memory page
 311   // address according to page size
 312   finalAddress = (((word24)cpu.PTW->ADDR & 0777760) << 6) + y2;
 313   finalAddress &= 0xffffff;
 314   PNL (cpu.APUMemAddr = finalAddress;)
 315 
 316 #if defined(L68)
 317   if (cpu.MR_cache.emr && cpu.MR_cache.ihr)
 318     add_APU_history (APUH_FAP);
 319 #endif /* if defined(L68) */
 320   DBGAPP ("doAppendCycleOperandRMW(H:FAP): (%05o:%06o) finalAddress=%08o\n", cpu.TPR.TSR, cpu.TPR.CA, finalAddress);
 321 
 322   goto HI;
 323 
 324 HI:
 325   DBGAPP ("doAppendCycleOperandRMW(HI)\n");
 326 
 327   // isolts 870
 328   cpu.cu.XSF = 1;
 329   sim_debug (DBG_TRACEEXT, & cpu_dev, "loading of cpu.TPR.TSR sets XSF to 1\n");
 330 
 331   if (nWords == 1) {
 332     core_read_lock (cpup, finalAddress, data, "OPERAND_RMW");
 333   } else {
 334     sim_warn("doAppendCycleOperandRMW: RMW nWords %d !=1\n", nWords);
 335     core_readN (cpup, finalAddress, data, nWords, "OPERAND_RMW");
 336   }
 337 
 338 ////////////////////////////////////////
 339 //
 340 // Sheet 11: "O", "P"
 341 //
 342 ////////////////////////////////////////
 343 
 344 //Exit:;
 345 
 346   PNL (cpu.APUDataBusOffset = cpu.TPR.CA;)
 347   PNL (cpu.APUDataBusAddr = finalAddress;)
 348 
 349   PNL (L68_ (cpu.apu.state |= apu_FA;))
 350 
 351   DBGAPP ("doAppendCycleOperandRMW (Exit) PRR %o PSR %05o P %o IC %06o\n", cpu.PPR.PRR, cpu.PPR.PSR, cpu.PPR.P, cpu.PPR.IC);
 352   DBGAPP ("doAppendCycleOperandRMW (Exit) TRR %o TSR %05o TBR %02o CA %06o\n", cpu.TPR.TRR, cpu.TPR.TSR, cpu.TPR.TBR, cpu.TPR.CA);
 353 
 354   return finalAddress;
 355 }

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