DBGAPP ("RTCD_OPERAND_FETCH ABSOLUTE mode set TSR %05o TRR %o\n", cpu.TPR.TSR, cpu.TPR.TRR);
}
- goto A;
-
-////////////////////////////////////////
+// goto A;
//
-// Sheet 2: "A"
+//////////////////////////////////////////
+////
+//// Sheet 2: "A"
+////
+//////////////////////////////////////////
//
-////////////////////////////////////////
-
+////
+//// A:
+//// Get SDW
//
-// A:
-// Get SDW
-
-A:;
-
- //PNL (cpu.APUMemAddr = address;)
- PNL (cpu.APUMemAddr = cpu.TPR.CA;)
-
- DBGAPP ("do_append_cycle(A)\n");
-
-#ifdef WAM
- // is SDW for C(TPR.TSR) in SDWAM?
- if (nomatch || ! fetch_sdw_from_sdwam (cpu.TPR.TSR))
-#endif
- {
- // No
- DBGAPP ("do_append_cycle(A):SDW for segment %05o not in SDWAM\n",
- cpu.TPR.TSR);
-
- DBGAPP ("do_append_cycle(A):DSBR.U=%o\n",
- cpu.DSBR.U);
-
- if (cpu.DSBR.U == 0)
- {
- fetch_dsptw (cpu.TPR.TSR);
-
- if (! cpu.PTW0.DF)
- doFault (FAULT_DF0 + cpu.PTW0.FC, fst_zero,
- "do_append_cycle(A): PTW0.F == 0");
-
- if (! cpu.PTW0.U)
- modify_dsptw (cpu.TPR.TSR);
-
- fetch_psdw (cpu.TPR.TSR);
- }
- else
- fetch_nsdw (cpu.TPR.TSR); // load SDW0 from descriptor segment table.
-
- if (cpu.SDW0.DF == 0)
- {
- if (thisCycle != ABSA_CYCLE)
- {
- DBGAPP ("do_append_cycle(A): SDW0.F == 0! "
- "Initiating directed fault\n");
- // initiate a directed fault ...
- doFault (FAULT_DF0 + cpu.SDW0.FC, fst_zero, "SDW0.F == 0");
- }
- }
- // load SDWAM .....
- load_sdwam (cpu.TPR.TSR, nomatch);
- }
- DBGAPP ("do_append_cycle(A) R1 %o R2 %o R3 %o E %o\n",
- cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3, cpu.SDW->E);
-
- // Yes...
- cpu.RSDWH_R1 = cpu.SDW->R1;
-
-////////////////////////////////////////
+//A:;
//
-// Sheet 3: "B"
+// //PNL (cpu.APUMemAddr = address;)
+// PNL (cpu.APUMemAddr = cpu.TPR.CA;)
//
-////////////////////////////////////////
-
+// DBGAPP ("do_append_cycle(A)\n");
+//
+//#ifdef WAM
+// // is SDW for C(TPR.TSR) in SDWAM?
+// if (nomatch || ! fetch_sdw_from_sdwam (cpu.TPR.TSR))
+//#endif
+// {
+// // No
+// DBGAPP ("do_append_cycle(A):SDW for segment %05o not in SDWAM\n",
+// cpu.TPR.TSR);
+//
+// DBGAPP ("do_append_cycle(A):DSBR.U=%o\n",
+// cpu.DSBR.U);
+//
+// if (cpu.DSBR.U == 0)
+// {
+// fetch_dsptw (cpu.TPR.TSR);
+//
+// if (! cpu.PTW0.DF)
+// doFault (FAULT_DF0 + cpu.PTW0.FC, fst_zero,
+// "do_append_cycle(A): PTW0.F == 0");
+//
+// if (! cpu.PTW0.U)
+// modify_dsptw (cpu.TPR.TSR);
+//
+// fetch_psdw (cpu.TPR.TSR);
+// }
+// else
+// fetch_nsdw (cpu.TPR.TSR); // load SDW0 from descriptor segment table.
+//
+// if (cpu.SDW0.DF == 0)
+// {
+// if (thisCycle != ABSA_CYCLE)
+// {
+// DBGAPP ("do_append_cycle(A): SDW0.F == 0! "
+// "Initiating directed fault\n");
+// // initiate a directed fault ...
+// doFault (FAULT_DF0 + cpu.SDW0.FC, fst_zero, "SDW0.F == 0");
+// }
+// }
+// // load SDWAM .....
+// load_sdwam (cpu.TPR.TSR, nomatch);
+// }
+// DBGAPP ("do_append_cycle(A) R1 %o R2 %o R3 %o E %o\n",
+// cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3, cpu.SDW->E);
//
-// B: Check the ring
+// // Yes...
+// cpu.RSDWH_R1 = cpu.SDW->R1;
//
-
- DBGAPP ("do_append_cycle(B)\n");
-
- // check ring bracket consistency
-
- //C(SDW.R1) <= C(SDW.R2) <= C(SDW .R3)?
- if (! (cpu.SDW->R1 <= cpu.SDW->R2 && cpu.SDW->R2 <= cpu.SDW->R3))
- {
- // Set fault ACV0 = IRO
- cpu.acvFaults |= ACV0;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) C(SDW.R1) <= C(SDW.R2) <= "
- "C(SDW .R3)";)
- }
-
- // lastCycle == RTCD_OPERAND_FETCH
- // if a fault happens between the RTCD_OPERAND_FETCH and the INSTRUCTION_FETCH
- // of the next instruction - this happens about 35 time for just booting and
- // shutting down multics -- a stored lastCycle is useless.
- // the opcode is preserved accross faults and only replaced as the
- // INSTRUCTION_FETCH succeeds.
- if (thisCycle == INSTRUCTION_FETCH &&
- i->opcode == 0610 && ! i->opcodeX)
- goto C;
- else if (lastCycle == RTCD_OPERAND_FETCH)
- sim_warn ("%s: lastCycle == RTCD_OPERAND_FETCH opcode %0#o\n", __func__, i->opcode);
-
- //
- // B1: The operand is one of: an instruction, data to be read or data to be
- // written
- //
-
- // Is OPCODE call6?
- if (thisCycle == OPERAND_READ && (i->info->flags & CALL6_INS))
- goto E;
-
-#if 0
- // If the instruction is a transfer operand or we are doing an instruction
- // fetch, the operand is destined to be executed. Verify that the operand
- // is executable
-
- // The flowchart trips up on the TSP PRn|foo,* for the INDIRECT_WORD_FETCH.
- // Also, it transfers to F on RTCD PRn,n and E-OFFs; the operand is not in
- // an executable segment, and should be treated as READ_OPERAND here.
-
- bool boolA = (thisCycle == INSTRUCTION_FETCH ||
- ((i->info->flags & TRANSFER_INS) &&
- thisCycle != INDIRECT_WORD_FETCH &&
- thisCycle != RTCD_OPERAND_FETCH));
- bool boolB = (thisCycle == INSTRUCTION_FETCH ||
- ((i->info->flags & TRANSFER_INS) &&
- thisCycle == OPERAND_READ));
- if (boolA != boolB)
- sim_warn ("do_append_cycle(B) boolA %d != boolB %d cycle %s insflag %d\n",
- boolA, boolB, str_pct (thisCycle), i->info->flags & TRANSFER_INS);
-#endif
-
- // Transfer or instruction fetch?
- if (thisCycle == INSTRUCTION_FETCH ||
- (thisCycle == OPERAND_READ && (i->info->flags & TRANSFER_INS)))
- goto F;
-
- //
- // check read bracket for read access
- //
-
-#ifdef LOCKLESS
- if (!StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
-#else
- if (!StrOp)
-#endif
- {
- DBGAPP ("do_append_cycle(B):!STR-OP\n");
-
- // No
- // C(TPR.TRR) > C(SDW .R2)?
- if (cpu.TPR.TRR > cpu.SDW->R2)
- {
- DBGAPP ("ACV3\n");
- DBGAPP ("do_append_cycle(B) ACV3\n");
- //Set fault ACV3 = ORB
- cpu.acvFaults |= ACV3;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R2)";)
- }
-
- if (cpu.SDW->R == 0)
- {
- // isolts 870
- cpu.TPR.TRR = cpu.PPR.PRR;
-
- //C(PPR.PSR) = C(TPR.TSR)?
- if (cpu.PPR.PSR != cpu.TPR.TSR)
- {
- DBGAPP ("ACV4\n");
- DBGAPP ("do_append_cycle(B) ACV4\n");
- //Set fault ACV4 = R-OFF
- cpu.acvFaults |= ACV4;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) C(PPR.PSR) = C(TPR.TSR)";)
- }
- else
- {
- // sim_warn ("do_append_cycle(B) SDW->R == 0 && cpu.PPR.PSR == cpu.TPR.TSR: %0#o\n", cpu.PPR.PSR);
- }
- }
- }
-
- //
- // check write bracket for write access
- //
-#ifdef LOCKLESS
- if (StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
-#else
- if (StrOp)
-#endif
- {
- DBGAPP ("do_append_cycle(B):STR-OP\n");
-
- // isolts 870
- if (cpu.TPR.TSR == cpu.PPR.PSR)
- cpu.TPR.TRR = cpu.PPR.PRR;
-
- // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
- if (cpu.TPR.TRR > cpu.SDW->R1)
- {
- DBGAPP ("ACV5 TRR %o R1 %o\n",
- cpu.TPR.TRR, cpu.SDW->R1);
- //Set fault ACV5 = OWB
- cpu.acvFaults |= ACV5;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
- }
-
- if (! cpu.SDW->W)
- {
- // isolts 870
- cpu.TPR.TRR = cpu.PPR.PRR;
-
- DBGAPP ("ACV6\n");
- // Set fault ACV6 = W-OFF
- cpu.acvFaults |= ACV6;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
- }
-
- }
-#ifdef LOCKLESS
- if (StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
-#else
- if (StrOp)
-#endif
- {
- DBGAPP ("do_append_cycle(B):STR-OP\n");
-
- // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
- if (cpu.TPR.TRR > cpu.SDW->R1)
- {
- DBGAPP ("ACV5 TRR %o R1 %o\n",
- cpu.TPR.TRR, cpu.SDW->R1);
- //Set fault ACV5 = OWB
- cpu.acvFaults |= ACV5;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
- }
-
- if (! cpu.SDW->W)
- {
- DBGAPP ("ACV6\n");
- // Set fault ACV6 = W-OFF
- cpu.acvFaults |= ACV6;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
- }
-
- }
- goto G;
-
-////////////////////////////////////////
+//////////////////////////////////////////
+////
+//// Sheet 3: "B"
+////
+//////////////////////////////////////////
//
-// Sheet 4: "C" "D"
+////
+//// B: Check the ring
+////
//
-////////////////////////////////////////
-
-C:;
- DBGAPP ("do_append_cycle(C)\n");
-
- //
- // check ring bracket for instruction fetch after rtcd instruction
- //
- // allow outbound transfers (cpu.TPR.TRR >= cpu.PPR.PRR)
- //
-
- // C(TPR.TRR) < C(SDW.R1)?
- // C(TPR.TRR) > C(SDW.R2)?
- if (cpu.TPR.TRR < cpu.SDW->R1 ||
- cpu.TPR.TRR > cpu.SDW->R2)
- {
- DBGAPP ("ACV1 c\n");
- DBGAPP ("acvFaults(C) ACV1 ! ( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
- cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
- //Set fault ACV1 = OEB
- cpu.acvFaults |= ACV1;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(C) C(SDW.R1 > C(TPR.TRR) > C(SDW.R2)";)
- }
- // SDW.E set ON?
- if (! cpu.SDW->E)
- {
- DBGAPP ("ACV2 a\n");
- DBGAPP ("do_append_cycle(C) ACV2\n");
- //Set fault ACV2 = E-OFF
- cpu.acvFaults |= ACV2;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(C) SDW.E";)
- }
- if (cpu.TPR.TRR > cpu.PPR.PRR)
- sim_warn ("rtcd: outbound call cpu.TPR.TRR %d cpu.PPR.PRR %d\n",
- cpu.TPR.TRR, cpu.PPR.PRR);
- // C(TPR.TRR) >= C(PPR.PRR)
- if (cpu.TPR.TRR < cpu.PPR.PRR)
- {
- DBGAPP ("ACV11\n");
- DBGAPP ("do_append_cycle(C) ACV11\n");
- //Set fault ACV11 = INRET
- cpu.acvFaults |= ACV11;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(C) TRR>=PRR";)
- }
-
-D:;
- DBGAPP ("do_append_cycle(D)\n");
-
- // transfer or instruction fetch
-
- // check ring alarm to catch outbound transfers
-
- if (cpu.rRALR == 0)
- goto G;
-
- // C(PPR.PRR) < RALR?
- if (! (cpu.PPR.PRR < cpu.rRALR))
- {
- DBGAPP ("ACV13\n");
- DBGAPP ("acvFaults(D) C(PPR.PRR) %o < RALR %o\n",
- cpu.PPR.PRR, cpu.rRALR);
- cpu.acvFaults |= ACV13;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(D) C(PPR.PRR) < RALR";)
- }
-
- goto G;
-
-////////////////////////////////////////
+// DBGAPP ("do_append_cycle(B)\n");
//
-// Sheet 5: "E"
+// // check ring bracket consistency
+//
+// //C(SDW.R1) <= C(SDW.R2) <= C(SDW .R3)?
+// if (! (cpu.SDW->R1 <= cpu.SDW->R2 && cpu.SDW->R2 <= cpu.SDW->R3))
+// {
+// // Set fault ACV0 = IRO
+// cpu.acvFaults |= ACV0;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) C(SDW.R1) <= C(SDW.R2) <= "
+// "C(SDW .R3)";)
+// }
//
-////////////////////////////////////////
-
-E:;
-
- //
- // check ring bracket for instruction fetch after call6 instruction
- // (this is the call6 read operand)
- //
-
- DBGAPP ("do_append_cycle(E): CALL6\n");
- DBGAPP ("do_append_cycle(E): E %o G %o PSR %05o TSR %05o CA %06o "
- "EB %06o R %o%o%o TRR %o PRR %o\n",
- cpu.SDW->E, cpu.SDW->G, cpu.PPR.PSR, cpu.TPR.TSR, cpu.TPR.CA,
- cpu.SDW->EB, cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3,
- cpu.TPR.TRR, cpu.PPR.PRR);
-
- //SDW.E set ON?
- if (! cpu.SDW->E)
- {
- DBGAPP ("ACV2 b\n");
- DBGAPP ("do_append_cycle(E) ACV2\n");
- // Set fault ACV2 = E-OFF
- cpu.acvFaults |= ACV2;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(E) SDW .E set OFF";)
- }
-
- //SDW .G set ON?
- if (cpu.SDW->G)
- goto E1;
-
- // C(PPR.PSR) = C(TPR.TSR)?
- if (cpu.PPR.PSR == cpu.TPR.TSR && ! TST_I_ABS)
- goto E1;
-
- // XXX This doesn't seem right
- // EB is word 15; masking address makes no sense; rather 0-extend EB
- // Fixes ISOLTS 880-01
- if (cpu.TPR.CA >= (word18) cpu.SDW->EB)
- {
- DBGAPP ("ACV7\n");
- DBGAPP ("do_append_cycle(E) ACV7\n");
- // Set fault ACV7 = NO GA
- cpu.acvFaults |= ACV7;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(E) TPR.CA4-17 >= SDW.CL";)
- }
-
-E1:
- DBGAPP ("do_append_cycle(E1): CALL6 (cont'd)\n");
-
- // C(TPR.TRR) > SDW.R3?
- if (cpu.TPR.TRR > cpu.SDW->R3)
- {
- DBGAPP ("ACV8\n");
- DBGAPP ("do_append_cycle(E) ACV8\n");
- //Set fault ACV8 = OCB
- cpu.acvFaults |= ACV8;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > SDW.R3";)
- }
-
- // C(TPR.TRR) < SDW.R1?
- if (cpu.TPR.TRR < cpu.SDW->R1)
- {
- DBGAPP ("ACV9\n");
- DBGAPP ("do_append_cycle(E) ACV9\n");
- // Set fault ACV9 = OCALL
- cpu.acvFaults |= ACV9;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) < SDW.R1";)
- }
-
-
- // C(TPR.TRR) > C(PPR.PRR)?
- if (cpu.TPR.TRR > cpu.PPR.PRR)
- {
- // C(PPR.PRR) < SDW.R2?
- if (cpu.PPR.PRR < cpu.SDW->R2)
- {
- DBGAPP ("ACV10\n");
- DBGAPP ("do_append_cycle(E) ACV10\n");
- // Set fault ACV10 = BOC
- cpu.acvFaults |= ACV10;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > C(PPR.PRR) && "
- "C(PPR.PRR) < SDW.R2";)
- }
- }
-
-
- DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o SDW->R2 %o\n",
- cpu.TPR.TRR, cpu.SDW->R2);
-
- // C(TPR.TRR) > SDW.R2?
- if (cpu.TPR.TRR > cpu.SDW->R2)
- {
- // SDW.R2 -> C(TPR.TRR)
- cpu.TPR.TRR = cpu.SDW->R2;
- }
-
- DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o\n", cpu.TPR.TRR);
-
- goto G;
-
-////////////////////////////////////////
+// // lastCycle == RTCD_OPERAND_FETCH
+// // if a fault happens between the RTCD_OPERAND_FETCH and the INSTRUCTION_FETCH
+// // of the next instruction - this happens about 35 time for just booting and
+// // shutting down multics -- a stored lastCycle is useless.
+// // the opcode is preserved accross faults and only replaced as the
+// // INSTRUCTION_FETCH succeeds.
+// if (thisCycle == INSTRUCTION_FETCH &&
+// i->opcode == 0610 && ! i->opcodeX)
+// goto C;
+// else if (lastCycle == RTCD_OPERAND_FETCH)
+// sim_warn ("%s: lastCycle == RTCD_OPERAND_FETCH opcode %0#o\n", __func__, i->opcode);
//
-// Sheet 6: "F"
+// //
+// // B1: The operand is one of: an instruction, data to be read or data to be
+// // written
+// //
//
-////////////////////////////////////////
-
-F:;
- PNL (L68_ (cpu.apu.state |= apu_PIAU;))
- DBGAPP ("do_append_cycle(F): transfer or instruction fetch\n");
-
- //
- // check ring bracket for instruction fetch
- //
-
- // C(TPR.TRR) < C(SDW .R1)?
- // C(TPR.TRR) > C(SDW .R2)?
- if (cpu.TPR.TRR < cpu.SDW->R1 ||
- cpu.TPR.TRR > cpu.SDW->R2)
- {
- DBGAPP ("ACV1 a/b\n");
- DBGAPP ("acvFaults(F) ACV1 !( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
- cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
- cpu.acvFaults |= ACV1;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(F) C(TPR.TRR) < C(SDW .R1)";)
- }
- // SDW .E set ON?
- if (! cpu.SDW->E)
- {
- DBGAPP ("ACV2 c \n");
- DBGAPP ("do_append_cycle(F) ACV2\n");
- cpu.acvFaults |= ACV2;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(F) SDW .E set OFF";)
- }
-
- // C(PPR.PRR) = C(TPR.TRR)?
- if (cpu.PPR.PRR != cpu.TPR.TRR)
- {
- DBGAPP ("ACV12\n");
- DBGAPP ("do_append_cycle(F) ACV12\n");
- //Set fault ACV12 = CRT
- cpu.acvFaults |= ACV12;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(F) C(PPR.PRR) != C(TPR.TRR)";)
- }
-
- goto D;
-
-////////////////////////////////////////
+// // Is OPCODE call6?
+// if (thisCycle == OPERAND_READ && (i->info->flags & CALL6_INS))
+// goto E;
//
-// Sheet 7: "G"
+//#if 0
+// // If the instruction is a transfer operand or we are doing an instruction
+// // fetch, the operand is destined to be executed. Verify that the operand
+// // is executable
//
-////////////////////////////////////////
-
-G:;
-
- DBGAPP ("do_append_cycle(G)\n");
-
- //C(TPR.CA)0,13 > SDW.BOUND?
- if (((cpu.TPR.CA >> 4) & 037777) > cpu.SDW->BOUND)
- {
- DBGAPP ("ACV15\n");
- DBGAPP ("do_append_cycle(G) ACV15\n");
- cpu.acvFaults |= ACV15;
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- FMSG (acvFaultsMsg = "acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND";)
- 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);
- }
-
- if (cpu.acvFaults)
- {
- DBGAPP ("do_append_cycle(G) acvFaults\n");
- PNL (L68_ (cpu.apu.state |= apu_FLT;))
- // Initiate an access violation fault
- doFault (FAULT_ACV, (_fault_subtype) {.fault_acv_subtype=cpu.acvFaults},
- "ACV fault");
- }
-
- // is segment C(TPR.TSR) paged?
- if (cpu.SDW->U)
- goto H; // Not paged
-
- // Yes. segment is paged ...
- // is PTW for C(TPR.CA) in PTWAM?
-
- DBGAPP ("do_append_cycle(G) CA %06o\n", cpu.TPR.CA);
-#ifdef WAM
- if (nomatch ||
- ! fetch_ptw_from_ptwam (cpu.SDW->POINTER, cpu.TPR.CA)) //TPR.CA))
-#endif
- {
- fetch_ptw (cpu.SDW, cpu.TPR.CA);
- if (! cpu.PTW0.DF)
- {
- if (thisCycle != ABSA_CYCLE)
- {
- // initiate a directed fault
- doFault (FAULT_DF0 + cpu.PTW0.FC, (_fault_subtype) {.bits=0},
- "PTW0.F == 0");
- }
- }
- loadPTWAM (cpu.SDW->POINTER, cpu.TPR.CA, nomatch); // load PTW0 to PTWAM
- }
-
- // Prepage mode?
- // check for "uninterruptible" EIS instruction
- // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
- // ad2/3d,sb2/3d,mp2/3d,dv2/3d
- // DH03 p.8-13: probably also mve,btd,dtb
- if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
- || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300))
- {
- do_ptw2 (cpu.SDW, cpu.TPR.CA);
- }
- goto I;
-
-////////////////////////////////////////
+// // The flowchart trips up on the TSP PRn|foo,* for the INDIRECT_WORD_FETCH.
+// // Also, it transfers to F on RTCD PRn,n and E-OFFs; the operand is not in
+// // an executable segment, and should be treated as READ_OPERAND here.
//
-// Sheet 8: "H", "I"
+// bool boolA = (thisCycle == INSTRUCTION_FETCH ||
+// ((i->info->flags & TRANSFER_INS) &&
+// thisCycle != INDIRECT_WORD_FETCH &&
+// thisCycle != RTCD_OPERAND_FETCH));
+// bool boolB = (thisCycle == INSTRUCTION_FETCH ||
+// ((i->info->flags & TRANSFER_INS) &&
+// thisCycle == OPERAND_READ));
+// if (boolA != boolB)
+// sim_warn ("do_append_cycle(B) boolA %d != boolB %d cycle %s insflag %d\n",
+// boolA, boolB, str_pct (thisCycle), i->info->flags & TRANSFER_INS);
+//#endif
//
-////////////////////////////////////////
-
-H:;
- DBGAPP ("do_append_cycle(H): FANP\n");
-
- PNL (L68_ (cpu.apu.state |= apu_FANP;))
-#if 0
- // ISOLTS pa865 test-01a 101232
- if (get_bar_mode ())
- {
- set_apu_status (apuStatus_FABS);
- }
- else
- ....
-#endif
- set_apu_status (apuStatus_FANP);
-
- DBGAPP ("do_append_cycle(H): SDW->ADDR=%08o CA=%06o \n",
- cpu.SDW->ADDR, cpu.TPR.CA);
+// // Transfer or instruction fetch?
+// if (thisCycle == INSTRUCTION_FETCH ||
+// (thisCycle == OPERAND_READ && (i->info->flags & TRANSFER_INS)))
+// goto F;
+//
+// //
+// // check read bracket for read access
+// //
+//
+//#ifdef LOCKLESS
+// if (!StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
+//#else
+// if (!StrOp)
+//#endif
+// {
+// DBGAPP ("do_append_cycle(B):!STR-OP\n");
+//
+// // No
+// // C(TPR.TRR) > C(SDW .R2)?
+// if (cpu.TPR.TRR > cpu.SDW->R2)
+// {
+// DBGAPP ("ACV3\n");
+// DBGAPP ("do_append_cycle(B) ACV3\n");
+// //Set fault ACV3 = ORB
+// cpu.acvFaults |= ACV3;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R2)";)
+// }
+//
+// if (cpu.SDW->R == 0)
+// {
+// // isolts 870
+// cpu.TPR.TRR = cpu.PPR.PRR;
+//
+// //C(PPR.PSR) = C(TPR.TSR)?
+// if (cpu.PPR.PSR != cpu.TPR.TSR)
+// {
+// DBGAPP ("ACV4\n");
+// DBGAPP ("do_append_cycle(B) ACV4\n");
+// //Set fault ACV4 = R-OFF
+// cpu.acvFaults |= ACV4;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) C(PPR.PSR) = C(TPR.TSR)";)
+// }
+// else
+// {
+// // sim_warn ("do_append_cycle(B) SDW->R == 0 && cpu.PPR.PSR == cpu.TPR.TSR: %0#o\n", cpu.PPR.PSR);
+// }
+// }
+// }
+//
+// //
+// // check write bracket for write access
+// //
+//#ifdef LOCKLESS
+// if (StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
+//#else
+// if (StrOp)
+//#endif
+// {
+// DBGAPP ("do_append_cycle(B):STR-OP\n");
+//
+// // isolts 870
+// if (cpu.TPR.TSR == cpu.PPR.PSR)
+// cpu.TPR.TRR = cpu.PPR.PRR;
+//
+// // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
+// if (cpu.TPR.TRR > cpu.SDW->R1)
+// {
+// DBGAPP ("ACV5 TRR %o R1 %o\n",
+// cpu.TPR.TRR, cpu.SDW->R1);
+// //Set fault ACV5 = OWB
+// cpu.acvFaults |= ACV5;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
+// }
+//
+// if (! cpu.SDW->W)
+// {
+// // isolts 870
+// cpu.TPR.TRR = cpu.PPR.PRR;
+//
+// DBGAPP ("ACV6\n");
+// // Set fault ACV6 = W-OFF
+// cpu.acvFaults |= ACV6;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
+// }
+//
+// }
+//#ifdef LOCKLESS
+// if (StrOp || thisCycle == OPERAND_RMW || thisCycle == APU_DATA_RMW)
+//#else
+// if (StrOp)
+//#endif
+// {
+// DBGAPP ("do_append_cycle(B):STR-OP\n");
+//
+// // C(TPR.TRR) > C(SDW .R1)? Note typo in AL39, R2 should be R1
+// if (cpu.TPR.TRR > cpu.SDW->R1)
+// {
+// DBGAPP ("ACV5 TRR %o R1 %o\n",
+// cpu.TPR.TRR, cpu.SDW->R1);
+// //Set fault ACV5 = OWB
+// cpu.acvFaults |= ACV5;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) C(TPR.TRR) > C(SDW .R1)";)
+// }
+//
+// if (! cpu.SDW->W)
+// {
+// DBGAPP ("ACV6\n");
+// // Set fault ACV6 = W-OFF
+// cpu.acvFaults |= ACV6;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(B) ACV6 = W-OFF";)
+// }
+//
+// }
+// goto G;
+//
+//////////////////////////////////////////
+////
+//// Sheet 4: "C" "D"
+////
+//////////////////////////////////////////
+//
+//C:;
+// DBGAPP ("do_append_cycle(C)\n");
+//
+// //
+// // check ring bracket for instruction fetch after rtcd instruction
+// //
+// // allow outbound transfers (cpu.TPR.TRR >= cpu.PPR.PRR)
+// //
+//
+// // C(TPR.TRR) < C(SDW.R1)?
+// // C(TPR.TRR) > C(SDW.R2)?
+// if (cpu.TPR.TRR < cpu.SDW->R1 ||
+// cpu.TPR.TRR > cpu.SDW->R2)
+// {
+// DBGAPP ("ACV1 c\n");
+// DBGAPP ("acvFaults(C) ACV1 ! ( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
+// cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
+// //Set fault ACV1 = OEB
+// cpu.acvFaults |= ACV1;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(C) C(SDW.R1 > C(TPR.TRR) > C(SDW.R2)";)
+// }
+// // SDW.E set ON?
+// if (! cpu.SDW->E)
+// {
+// DBGAPP ("ACV2 a\n");
+// DBGAPP ("do_append_cycle(C) ACV2\n");
+// //Set fault ACV2 = E-OFF
+// cpu.acvFaults |= ACV2;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(C) SDW.E";)
+// }
+// if (cpu.TPR.TRR > cpu.PPR.PRR)
+// sim_warn ("rtcd: outbound call cpu.TPR.TRR %d cpu.PPR.PRR %d\n",
+// cpu.TPR.TRR, cpu.PPR.PRR);
+// // C(TPR.TRR) >= C(PPR.PRR)
+// if (cpu.TPR.TRR < cpu.PPR.PRR)
+// {
+// DBGAPP ("ACV11\n");
+// DBGAPP ("do_append_cycle(C) ACV11\n");
+// //Set fault ACV11 = INRET
+// cpu.acvFaults |= ACV11;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(C) TRR>=PRR";)
+// }
+//
+//D:;
+// DBGAPP ("do_append_cycle(D)\n");
+//
+// // transfer or instruction fetch
+//
+// // check ring alarm to catch outbound transfers
+//
+// if (cpu.rRALR == 0)
+// goto G;
+//
+// // C(PPR.PRR) < RALR?
+// if (! (cpu.PPR.PRR < cpu.rRALR))
+// {
+// DBGAPP ("ACV13\n");
+// DBGAPP ("acvFaults(D) C(PPR.PRR) %o < RALR %o\n",
+// cpu.PPR.PRR, cpu.rRALR);
+// cpu.acvFaults |= ACV13;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(D) C(PPR.PRR) < RALR";)
+// }
+//
+// goto G;
+//
+//////////////////////////////////////////
+////
+//// Sheet 5: "E"
+////
+//////////////////////////////////////////
+//
+//E:;
+//
+// //
+// // check ring bracket for instruction fetch after call6 instruction
+// // (this is the call6 read operand)
+// //
+//
+// DBGAPP ("do_append_cycle(E): CALL6\n");
+// DBGAPP ("do_append_cycle(E): E %o G %o PSR %05o TSR %05o CA %06o "
+// "EB %06o R %o%o%o TRR %o PRR %o\n",
+// cpu.SDW->E, cpu.SDW->G, cpu.PPR.PSR, cpu.TPR.TSR, cpu.TPR.CA,
+// cpu.SDW->EB, cpu.SDW->R1, cpu.SDW->R2, cpu.SDW->R3,
+// cpu.TPR.TRR, cpu.PPR.PRR);
+//
+// //SDW.E set ON?
+// if (! cpu.SDW->E)
+// {
+// DBGAPP ("ACV2 b\n");
+// DBGAPP ("do_append_cycle(E) ACV2\n");
+// // Set fault ACV2 = E-OFF
+// cpu.acvFaults |= ACV2;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(E) SDW .E set OFF";)
+// }
+//
+// //SDW .G set ON?
+// if (cpu.SDW->G)
+// goto E1;
+//
+// // C(PPR.PSR) = C(TPR.TSR)?
+// if (cpu.PPR.PSR == cpu.TPR.TSR && ! TST_I_ABS)
+// goto E1;
+//
+// // XXX This doesn't seem right
+// // EB is word 15; masking address makes no sense; rather 0-extend EB
+// // Fixes ISOLTS 880-01
+// if (cpu.TPR.CA >= (word18) cpu.SDW->EB)
+// {
+// DBGAPP ("ACV7\n");
+// DBGAPP ("do_append_cycle(E) ACV7\n");
+// // Set fault ACV7 = NO GA
+// cpu.acvFaults |= ACV7;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(E) TPR.CA4-17 >= SDW.CL";)
+// }
+//
+//E1:
+// DBGAPP ("do_append_cycle(E1): CALL6 (cont'd)\n");
+//
+// // C(TPR.TRR) > SDW.R3?
+// if (cpu.TPR.TRR > cpu.SDW->R3)
+// {
+// DBGAPP ("ACV8\n");
+// DBGAPP ("do_append_cycle(E) ACV8\n");
+// //Set fault ACV8 = OCB
+// cpu.acvFaults |= ACV8;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > SDW.R3";)
+// }
+//
+// // C(TPR.TRR) < SDW.R1?
+// if (cpu.TPR.TRR < cpu.SDW->R1)
+// {
+// DBGAPP ("ACV9\n");
+// DBGAPP ("do_append_cycle(E) ACV9\n");
+// // Set fault ACV9 = OCALL
+// cpu.acvFaults |= ACV9;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) < SDW.R1";)
+// }
+//
+//
+// // C(TPR.TRR) > C(PPR.PRR)?
+// if (cpu.TPR.TRR > cpu.PPR.PRR)
+// {
+// // C(PPR.PRR) < SDW.R2?
+// if (cpu.PPR.PRR < cpu.SDW->R2)
+// {
+// DBGAPP ("ACV10\n");
+// DBGAPP ("do_append_cycle(E) ACV10\n");
+// // Set fault ACV10 = BOC
+// cpu.acvFaults |= ACV10;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(E1) C(TPR.TRR) > C(PPR.PRR) && "
+// "C(PPR.PRR) < SDW.R2";)
+// }
+// }
+//
+//
+// DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o SDW->R2 %o\n",
+// cpu.TPR.TRR, cpu.SDW->R2);
+//
+// // C(TPR.TRR) > SDW.R2?
+// if (cpu.TPR.TRR > cpu.SDW->R2)
+// {
+// // SDW.R2 -> C(TPR.TRR)
+// cpu.TPR.TRR = cpu.SDW->R2;
+// }
+//
+// DBGAPP ("do_append_cycle(E1): CALL6 TPR.TRR %o\n", cpu.TPR.TRR);
+//
+// goto G;
+//
+//////////////////////////////////////////
+////
+//// Sheet 6: "F"
+////
+//////////////////////////////////////////
+//
+//F:;
+// PNL (L68_ (cpu.apu.state |= apu_PIAU;))
+// DBGAPP ("do_append_cycle(F): transfer or instruction fetch\n");
+//
+// //
+// // check ring bracket for instruction fetch
+// //
+//
+// // C(TPR.TRR) < C(SDW .R1)?
+// // C(TPR.TRR) > C(SDW .R2)?
+// if (cpu.TPR.TRR < cpu.SDW->R1 ||
+// cpu.TPR.TRR > cpu.SDW->R2)
+// {
+// DBGAPP ("ACV1 a/b\n");
+// DBGAPP ("acvFaults(F) ACV1 !( C(SDW .R1) %o <= C(TPR.TRR) %o <= C(SDW .R2) %o )\n",
+// cpu.SDW->R1, cpu.TPR.TRR, cpu.SDW->R2);
+// cpu.acvFaults |= ACV1;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(F) C(TPR.TRR) < C(SDW .R1)";)
+// }
+// // SDW .E set ON?
+// if (! cpu.SDW->E)
+// {
+// DBGAPP ("ACV2 c \n");
+// DBGAPP ("do_append_cycle(F) ACV2\n");
+// cpu.acvFaults |= ACV2;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(F) SDW .E set OFF";)
+// }
+//
+// // C(PPR.PRR) = C(TPR.TRR)?
+// if (cpu.PPR.PRR != cpu.TPR.TRR)
+// {
+// DBGAPP ("ACV12\n");
+// DBGAPP ("do_append_cycle(F) ACV12\n");
+// //Set fault ACV12 = CRT
+// cpu.acvFaults |= ACV12;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(F) C(PPR.PRR) != C(TPR.TRR)";)
+// }
+//
+// goto D;
+//
+//////////////////////////////////////////
+////
+//// Sheet 7: "G"
+////
+//////////////////////////////////////////
+//
+//G:;
+//
+// DBGAPP ("do_append_cycle(G)\n");
+//
+// //C(TPR.CA)0,13 > SDW.BOUND?
+// if (((cpu.TPR.CA >> 4) & 037777) > cpu.SDW->BOUND)
+// {
+// DBGAPP ("ACV15\n");
+// DBGAPP ("do_append_cycle(G) ACV15\n");
+// cpu.acvFaults |= ACV15;
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// FMSG (acvFaultsMsg = "acvFaults(G) C(TPR.CA)0,13 > SDW.BOUND";)
+// 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);
+// }
+//
+// if (cpu.acvFaults)
+// {
+// DBGAPP ("do_append_cycle(G) acvFaults\n");
+// PNL (L68_ (cpu.apu.state |= apu_FLT;))
+// // Initiate an access violation fault
+// doFault (FAULT_ACV, (_fault_subtype) {.fault_acv_subtype=cpu.acvFaults},
+// "ACV fault");
+// }
+//
+// // is segment C(TPR.TSR) paged?
+// if (cpu.SDW->U)
+// goto H; // Not paged
+//
+// // Yes. segment is paged ...
+// // is PTW for C(TPR.CA) in PTWAM?
+//
+// DBGAPP ("do_append_cycle(G) CA %06o\n", cpu.TPR.CA);
+//#ifdef WAM
+// if (nomatch ||
+// ! fetch_ptw_from_ptwam (cpu.SDW->POINTER, cpu.TPR.CA)) //TPR.CA))
+//#endif
+// {
+// fetch_ptw (cpu.SDW, cpu.TPR.CA);
+// if (! cpu.PTW0.DF)
+// {
+// if (thisCycle != ABSA_CYCLE)
+// {
+// // initiate a directed fault
+// doFault (FAULT_DF0 + cpu.PTW0.FC, (_fault_subtype) {.bits=0},
+// "PTW0.F == 0");
+// }
+// }
+// loadPTWAM (cpu.SDW->POINTER, cpu.TPR.CA, nomatch); // load PTW0 to PTWAM
+// }
+//
+// // Prepage mode?
+// // check for "uninterruptible" EIS instruction
+// // ISOLTS-878 02: mvn,cmpn,mvne,ad3d; obviously also
+// // ad2/3d,sb2/3d,mp2/3d,dv2/3d
+// // DH03 p.8-13: probably also mve,btd,dtb
+// if (i->opcodeX && ((i->opcode & 0770)== 0200|| (i->opcode & 0770) == 0220
+// || (i->opcode & 0770)== 020|| (i->opcode & 0770) == 0300))
+// {
+// do_ptw2 (cpu.SDW, cpu.TPR.CA);
+// }
+// goto I;
+//
+//////////////////////////////////////////
+////
+//// Sheet 8: "H", "I"
+////
+//////////////////////////////////////////
+//
+//H:;
+// DBGAPP ("do_append_cycle(H): FANP\n");
+//
+// PNL (L68_ (cpu.apu.state |= apu_FANP;))
+//#if 0
+// // ISOLTS pa865 test-01a 101232
+// if (get_bar_mode ())
+// {
+// set_apu_status (apuStatus_FABS);
+// }
+// else
+// ....
+//#endif
+// set_apu_status (apuStatus_FANP);
+//
+// DBGAPP ("do_append_cycle(H): SDW->ADDR=%08o CA=%06o \n",
+// cpu.SDW->ADDR, cpu.TPR.CA);
if (thisCycle == RTCD_OPERAND_FETCH &&
get_addr_mode () == ABSOLUTE_mode &&
}
else
{
- finalAddress = (cpu.SDW->ADDR & 077777760) + cpu.TPR.CA;
- finalAddress &= 0xffffff;
+// finalAddress = (cpu.SDW->ADDR & 077777760) + cpu.TPR.CA;
+// finalAddress &= 0xffffff;
+ finalAddress = (cpu.TPR.TSR << 18) | cpu.TPR.CA;
}
PNL (cpu.APUMemAddr = finalAddress;)
#include "dps8/dps8_sys.h"
#include "object_map.h"
#include "rassert.h"
+#include "stack_header.h"
-#define N_PATHS 1
-char *paths[] = {
+#define N_PATHS 2
+char *paths[N_PATHS] = {
+ "tape/word/system_library_1/",
"tape/word/system_library_standard/"
};
-void get_acc_string(uint64_t *acc_string, char *buf, int buf_len) {
- int len = (acc_string[0] >> 27) & 0777;
- rassert(len < buf_len);
+#define N_LOADED_SEGMENT 0x100
+int n_loaded_segment;
+struct loaded_segment {
+ const char *name;
+ int segment;
+ int bitcount;
+} loaded_segment[N_LOADED_SEGMENT];
- static int shifts[4] = {27, 18, 9, 0};
- for (int i = 0, j = 1; i < len; ++i, ++j)
- buf[i] = (acc_string[j >> 2] >> shifts[j & 3]) & 0xff;
- buf[len] = 0;
-}
+#define N_SEGMENT 0x200
+struct loaded_segment *loaded_segment_xref[N_SEGMENT];
+int next_segment;
-int main(int argc, char **argv) {
- if (argc < 3) {
- printf(
- "usage: %s object_segment_name entry_segment$entry_name [arguments]\n",
- argv[0]
- );
- exit(EXIT_FAILURE);
- }
- char *object_segment_name = argv[1];
- char *entry_segment, *entry_name;
- {
- char *p = strchr(argv[2], '$');
- if (p) {
- *p++ = 0;
- entry_segment = argv[2];
- entry_name = p;
- }
- else {
- entry_segment = object_segment_name;
- entry_name = argv[2];
- }
- }
+int linkage_segment;
+struct packed_pointer *lot;
+struct packed_pointer *isot;
- // initialize CPU
- cpu_reset_unit_idx(0, false);
+int stack_segment;
+struct stack_header *stack_header;
- // initialize memory
- uint64_t *null_segment = mmap(
+#define STACK_OFFSET (sizeof(stack_header) / sizeof(uint64_t))
+
+#define LOT_OFFSET 0
+#define ISOT_OFFSET (LOT_OFFSET + N_SEGMENT)
+#define LINKAGE_OFFSET (ISOT_OFFSET + N_SEGMENT)
+int next_linkage_offset;
+
+int scratch_segment(void) {
+ rassert(next_segment < N_SEGMENT);
+ int index = next_segment++;
+
+ M[index] = (word36 *)mmap(
NULL,
01000000 * sizeof(uint64_t),
- PROT_NONE,
+ PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
(off_t)0
);
- rassert(null_segment != (uint64_t *)-1);
- for (int i = 0; i < 0100000; ++i)
- M[i] = (word36 *)null_segment;
+ rassert(M[index] != (word36 *)-1);
+
+ return index;
+}
+
+struct object_map *get_object_map(struct loaded_segment *p) {
+ rassert(p->bitcount % 36 == 0);
+ int wordcount = (p->bitcount / 36) & 0777777;
+ rassert(wordcount >= 1);
+ struct object_map *object_map = (struct object_map *)(
+ M[p->segment] + (
+ (M[p->segment][(wordcount - 1) & 0777777] >> 18) & 0777777
+ )
+ );
+ rassert(object_map->decl_vers == 2);
+ rassert(object_map->identifier[0] == 0157142152137); // 'obj_'
+ rassert(object_map->identifier[1] == 0155141160040); // 'map '
+
+ return object_map;
+}
+
+struct loaded_segment *load_segment(const char *name) {
+ // see if already loaded
+ for (int i = 0; i < n_loaded_segment; ++i)
+ if (strcmp(loaded_segment[i].name, name) == 0)
+ return loaded_segment + i;
+
+ // allocate table entries
+ rassert(n_loaded_segment < N_LOADED_SEGMENT);
+ struct loaded_segment *p =
+ loaded_segment + n_loaded_segment++;
+ p->name = strdup(name);
+ rassert(p->name);
- // search for object segment
- int fd;
+ rassert(next_segment < N_SEGMENT);
+ p->segment = next_segment++;
+ loaded_segment_xref[p->segment] = p;
+
+ // search for segment in path
int path_index;
for (path_index = 0; path_index < N_PATHS; ++path_index) {
- char name[0x1000];
- rassert(strlen(paths[path_index]) + strlen(object_segment_name) < sizeof(name));
- strcpy(name, paths[path_index]);
- strcat(name, object_segment_name);
-
- fd = open(name, O_RDONLY);
- if (fd != -1)
- goto found_object_segment;
+ char path[0x1000];
+ rassert(strlen(paths[path_index]) + strlen(name) < sizeof(path));
+ strcpy(path, paths[path_index]);
+ strcat(path, name);
+
+ int fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ M[p->segment] = (word36 *)mmap(
+ NULL,
+ 01000000 * sizeof(uint64_t),
+ PROT_READ,
+ MAP_SHARED,
+ fd,
+ (off_t)0
+ );
+ rassert(M[p->segment] != (word36 *)-1);
+
+ close(fd);
+ goto found_segment;
+ }
}
- fprintf(
- stderr,
- "can't find object segment %s in paths list\n",
- object_segment_name
- );
+ fprintf(stderr, "can't find segment name %s in paths list\n", name);
exit(EXIT_FAILURE);
-found_object_segment:
+found_segment:
;
- uint64_t *object_segment = mmap(
- NULL,
- 01000000 * sizeof(uint64_t),
- PROT_READ,
- MAP_SHARED,
- fd,
- (off_t)0
- );
- rassert(object_segment != (uint64_t *)-1);
+ char path[0x1000];
+ rassert(strlen(paths[path_index]) + 4 < sizeof(path));
+ strcpy(path, paths[path_index]);
+ strcat(path, ".dir");
- // search for entry point in object segment
- uint64_t bitcount;
- {
- char index_name[0x1000];
- rassert(strlen(paths[path_index]) + 4 < sizeof(index_name));
- strcpy(index_name, paths[path_index]);
- strcat(index_name, ".dir");
-
- FILE *fp = fopen(index_name, "r");
- char line[0x100];
- while (fgets(line, 0x100, fp)) {
- char *p = strchr(line, ' ');
- if (p) {
- *p++ = 0;
- if (strcmp(line, object_segment_name) == 0) {
- bitcount = strtol(p, NULL, 0);
- goto found_bitcount;
- }
+ FILE *fp = fopen(path, "r");
+ char line[0x100];
+ while (fgets(line, 0x100, fp)) {
+ char *q = strchr(line, ' ');
+ if (q) {
+ *q++ = 0;
+ if (strcmp(line, name) == 0) {
+ p->bitcount = (int)strtol(q, NULL, 0);
+ goto found_bitcount;
}
}
-
- fprintf(
- stderr,
- "can't find object %s in index %s\n",
- object_segment_name,
- index_name
- );
- exit(EXIT_FAILURE);
}
+ fprintf(stderr, "can't find segment name %s in index %s\n", name, path);
+ exit(EXIT_FAILURE);
+
found_bitcount:
- rassert(bitcount % 36 == 0);
- uint32_t wordcount = (bitcount / 36) & 0777777;
+ ;
+ struct object_map *object_map = get_object_map(p);
- struct object_map *object_map = (struct object_map *)(
- object_segment +
- ((object_segment[(wordcount - 1) & 0777777] >> 18) & 0777777)
+ // copy linkage section
+ lot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
+ rassert(next_linkage_offset + object_map->linkage_length <= 01000000);
+ memcpy(
+ M[linkage_segment] + next_linkage_offset,
+ M[p->segment] + object_map->linkage_offset,
+ object_map->linkage_length * sizeof(uint64_t)
);
- rassert(object_map->decl_vers == 2);
- rassert(object_map->identifier[0] == 0157142152137); // 'obj_'
- rassert(object_map->identifier[1] == 0155141160040); // 'map '
+ next_linkage_offset += object_map->linkage_length;
+
+ // copy static section
+ isot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
+ rassert(next_linkage_offset + object_map->static_length <= 01000000);
+ memcpy(
+ M[linkage_segment] + next_linkage_offset,
+ M[p->segment] + object_map->static_offset,
+ object_map->static_length * sizeof(uint64_t)
+ );
+ next_linkage_offset += object_map->static_length;
+
+ stack_header->cur_lot_size = next_segment;
+
+ return p;
+}
+
+void get_acc_string(uint64_t *acc_string, char *buf, int buf_len) {
+ int len = (acc_string[0] >> 27) & 0777;
+ rassert(len < buf_len);
+
+ static int shifts[4] = {27, 18, 9, 0};
+ for (int i = 0, j = 1; i < len; ++i, ++j)
+ buf[i] = (acc_string[j >> 2] >> shifts[j & 3]) & 0xff;
+ buf[len] = 0;
+}
+
+void dump_entries(struct loaded_segment *p) {
+ struct object_map *object_map = get_object_map(p);
+ struct definition_header *definition_header = (struct definition_header *)(
+ M[p->segment] + object_map->definition_offset
+ );
+
+ struct definition *definition;
+ for (
+ int definition_relp = (int)definition_header->def_list_relp;
+ definition_relp;
+ definition_relp = (int)definition->forward_relp
+ ) {
+ definition = (struct definition *)(
+ (uint64_t *)definition_header + definition_relp
+ );
+ if (definition->class >= 7)
+ break; // can be dummy entry at end with all zeros and illegal class
+
+ char name[0x20];
+ get_acc_string(
+ (uint64_t *)definition_header + definition->name_relp,
+ name,
+ sizeof(name)
+ );
+ printf(
+ "%06o %s \"%s\" ignore %d entry %d indirect %d thing_relp %06o %s_relp %06o\n",
+ definition_relp,
+ class_names[definition->class],
+ name,
+ definition->flags_ignore,
+ definition->flags_entry,
+ definition->flags_indirect,
+ definition->thing_relp,
+ definition->class == CLASS_SEGNAME ? "first" : "segname",
+ definition->segname_relp
+ );
+ }
+}
+int find_entry(
+ struct loaded_segment *p,
+ const char *entry_segment,
+ const char *entry_name,
+ bool entry
+) {
+ struct object_map *object_map = get_object_map(p);
struct definition_header *definition_header = (struct definition_header *)(
- object_segment + object_map->definition_offset
+ M[p->segment] + object_map->definition_offset
);
struct definition *definition;
for (
- uint32_t definition_relp = definition_header->def_list_relp;
+ int definition_relp = (int)definition_header->def_list_relp;
definition_relp;
- definition_relp = definition->forward_relp
+ definition_relp = (int)definition->forward_relp
) {
definition = (struct definition *)(
(uint64_t *)definition_header + definition_relp
);
+ if (definition->class >= 7)
+ break; // can be dummy entry at end with all zeros and illegal class
-#if 1
if (
definition->class == CLASS_TEXT &&
!definition->flags_ignore &&
- definition->flags_entry
+ (!entry || definition->flags_entry)
) {
struct segname_definition *segname_definition =
(struct segname_definition *)(
);
if (strcmp(definition_name, entry_name) == 0)
- goto found_entry;
+ return (int)(object_map->text_offset + definition->thing_relp);
}
}
-#else
- char name[0x20];
- get_acc_string(
- (uint64_t *)definition_header + definition->name_relp,
- name,
- sizeof(name)
- );
- printf(
- "%06o %s \"%s\" ignore %d entry %d indirect %d thing_relp %06o %s_relp %06o\n",
- definition_relp,
- class_names[definition->class],
- name,
- definition->flags_ignore,
- definition->flags_entry,
- definition->flags_indirect,
- definition->thing_relp,
- definition->class == CLASS_SEGNAME ? "first" : "segname",
- definition->segname_relp
- );
-#endif
}
- printf(
- "can't find entry %s$%s in object %s\n",
+
+ fprintf(
+ stderr,
+ "can't find entry %s$%s in segment %s\n",
entry_segment,
entry_name,
- object_segment_name
+ p->name
);
exit(EXIT_FAILURE);
+}
-found_entry:
- ;
-
- // map in segment and start executing
- M[0] = (word36 *)object_segment;
- cpu.PPR.PRR = 3; // ring
- cpu.PPR.PSR = 0; // segment
- cpu.PPR.P = 0; // privilege
- cpu.PPR.IC = (object_map->text_offset + definition->thing_relp) & 0777777;
+// callback from simulator when fault type 2 occurs
+bool snap_link(void) {
printf(
- "entry %s$%s at %06o -> %012llo\n",
- entry_segment,
- entry_name,
+ "fault type 2 at %06o:%06o accessing %06o:%06o\n",
+ cpu.PPR.PSR,
cpu.PPR.IC,
- M[cpu.PPR.PSR][cpu.PPR.IC]
+ cpu.TPR.TSR,
+ cpu.TPR.CA
);
+
+ struct loaded_segment *p;
+ struct object_map *object_map;
+ if (
+ cpu.PPR.PSR >= N_SEGMENT ||
+ (p = loaded_segment_xref[cpu.PPR.PSR]) == NULL ||
+ cpu.TPR.TSR != lot[cpu.PPR.PSR].segment ||
+ cpu.TPR.CA < lot[cpu.PPR.PSR].address ||
+ cpu.TPR.CA >= lot[cpu.PPR.PSR].address + (
+ object_map = get_object_map(p)
+ )->linkage_length
+ )
+ return false;
+
+ abort();
+}
+
+int main(int argc, char **argv) {
+ if (argc < 3) {
+ printf(
+ "usage: %s object_segment_name entry_segment$entry_name [arguments]\n",
+ argv[0]
+ );
+ exit(EXIT_FAILURE);
+ }
+ char *object_segment_name = argv[1];
+ char *entry_segment, *entry_name;
+ {
+ char *p = strchr(argv[2], '$');
+ if (p) {
+ *p++ = 0;
+ entry_segment = argv[2];
+ entry_name = p;
+ }
+ else {
+ entry_segment = object_segment_name;
+ entry_name = argv[2];
+ }
+ }
+
+ // initialize CPU
+ cpu_reset_unit_idx(0, false);
+
+ // initialize memory
+ uint64_t *null_segment = mmap(
+ NULL,
+ 01000000 * sizeof(uint64_t),
+ PROT_NONE,
+ MAP_ANONYMOUS | MAP_PRIVATE,
+ -1,
+ (off_t)0
+ );
+ rassert(null_segment != (uint64_t *)-1);
+ for (int i = 0; i < 0100000; ++i)
+ M[i] = (word36 *)null_segment;
+ next_segment = 1;
+
+ // create linkage segment
+ linkage_segment = scratch_segment();
+ lot = (struct packed_pointer *)(M[linkage_segment] + LOT_OFFSET);
+ isot = (struct packed_pointer *)(M[linkage_segment] + ISOT_OFFSET);
+ next_linkage_offset = LINKAGE_OFFSET;
+
+ // create stack segment
+ stack_segment = scratch_segment();
+ stack_header = (struct stack_header *)M[stack_segment];
+ stack_header->max_lot_size = N_SEGMENT;
+ stack_header->stack_begin_ptr = its_pointer(stack_segment, STACK_OFFSET);
+ stack_header->stack_end_ptr = its_pointer(stack_segment, STACK_OFFSET);
+ stack_header->lot_ptr = its_pointer(linkage_segment, LOT_OFFSET);
+ stack_header->isot_ptr = its_pointer(linkage_segment, ISOT_OFFSET);
+
+ // load pl1 operators
+ struct loaded_segment *p = load_segment("bound_library_wired_");
+ //dump_entries(p);
+ //exit(EXIT_FAILURE);
+ stack_header->pl1_operators_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "operator_table", false)
+ );
+ stack_header->call_op_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "alm_call", false)
+ );
+ stack_header->push_op_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "alm_push", false)
+ );
+ stack_header->return_op_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "alm_return", false)
+ );
+ stack_header->no_pop_op_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "alm_return_no_pop", false)
+ );
+ stack_header->entry_op_ptr = its_pointer(
+ p->segment,
+ find_entry(p, "pl1_operators_", "alm_entry", false)
+ );
+
+ // set up registers
+ struct loaded_segment *q = load_segment(object_segment_name);
+ set_addr_mode(APPEND_mode);
+
+ // ic (instruction counter)
+ cpu.PPR.PRR = 3; // ring
+ cpu.PPR.PSR = q->segment; // segment
+ cpu.PPR.P = 0; // privilege
+ cpu.PPR.IC = find_entry(q, entry_segment, entry_name, true); // address
+
+ // sp (stack frame pointer)
+ cpu.PR[6].RNR = 3; // ring
+ cpu.PR[6].SNR = p->segment; // segment
+ cpu.PR[6].WORDNO = STACK_OFFSET; // address
+
+ // sb (stack base pointer)
+ cpu.PR[7].RNR = 3; // ring
+ cpu.PR[7].SNR = stack_segment; // segment
+ cpu.PR[7].WORDNO = 0; // address
+
+ // enter simulator
sim_instr();
return 0;