1 /* 2 * vim: filetype=c:tabstop=4:ai:expandtab 3 * SPDX-License-Identifier: ICU 4 * scspell-id: 506d89bb-f62d-11ec-b87a-80ee73e9b8e7 5 * 6 * --------------------------------------------------------------------------- 7 * 8 * Copyright (c) 2013-2017 Charles Anthony 9 * Copyright (c) 2021-2023 The DPS8M Development Team 10 * 11 * All rights reserved. 12 * 13 * This software is made available under the terms of the ICU 14 * License, version 1.8.1 or later. For more details, see the 15 * LICENSE.md file at the top-level directory of this distribution. 16 * 17 * --------------------------------------------------------------------------- 18 */ 19 20 // Appending unit stuff ....... 21 22 // Once segno and offset are formed in TPR.SNR and TPR.CA, respectively, the 23 // process of generating the 24-bit absolute main memory address can involve a 24 // number of different and distinct appending unit cycles. 25 // 26 // The operation of the appending unit is shown in the flowchart in Figure 5-4. 27 // This flowchart assumes that directed faults, store faults, and parity faults 28 // do not occur. 29 // 30 // A segment boundary check is made in every cycle except PSDW. If a boundary 31 // violation is detected, an access violation, out of segment bounds, fault is 32 // generated and the execution of the instruction interrupted. The occurrence 33 // of any fault interrupts the sequence at the point of occurrence. The 34 // operating system software should store the control unit data for possible 35 // later continuation and attempt to resolve the fault condition. 36 // 37 // The value of the associative memories may be seen in the flowchart by 38 // observing the number of appending unit cycles bypassed if an SDW or PTW is 39 // found in the associative memories. 40 // 41 // There are nine different appending unit cycles that involve accesses to main 42 // memory. Two of these (FANP, FAP) generate the 24-bit absolute main memory 43 // address and initiate a main memory access for the operand, indirect word, or 44 // instruction pair; five (NSDW, PSDW, PTW, PTW2, and DSPTW) generate a main 45 // memory access to fetch an SDW or PTW; and two (MDSPTW and MPTW) generate a 46 // main memory access to update page status bits (PTW.U and PTW.M) in a PTW. 47 // The cycles are defined in Table 5-1. 48 49 // enum _appendingUnit_cycle_type { 50 // apuCycle_APPUNKNOWN = 0, // unknown 51 // 52 // apuCycle_FIAP, // Fetch instruction 53 // 54 // apuCycle_FANP, // Final address nonpaged. 55 // // Generates the 24-bit absolute main memory address and 56 // // initiates a main memory access to an unpaged segment for 57 // // operands, indirect words, or instructions. 58 // 59 // apuCycle_FAP, // Final address paged 60 // // Generates the 24-bit absolute main memory address and 61 // // initiates a main memory access to a paged segment for 62 // // operands, indirect words, or instructions. 63 // 64 // apuCycle_NSDW, // Nonpaged SDW Fetch 65 // // Fetches an SDW from an unpaged descriptor segment. 66 // 67 // apuCycle_PSDW, // Paged SDW Fetch 68 // // Fetches an SDW from a paged descriptor segment. 69 // 70 // apuCycle_PTWfetch, // PTW fetch 71 // // Fetches a PTW from a page table other than a descriptor 72 // // segment page table and sets the page accessed bit (PTW.U). 73 // 74 // apuCycle_PTW2, // Prepage PTW fetch 75 // // Fetches the next PTW from a page table other than a 76 // // descriptor segment page table during hardware prepaging for 77 // // certain uninterruptible EIS instructions. This cycle does 78 // // not load the next PTW into the appending unit. It merely 79 // // assures that the PTW is not faulted (PTW.F = 1) and that 80 // // the target page will be in main memory when and if needed 81 // // by the instruction. 82 // 83 // apuCycle_DSPTW, // Descriptor segment PTW fetch 84 // // Fetches a PTW from a descriptor segment page table. 85 // 86 // apuCycle_MDSPTW, // Modify DSPTW 87 // // Sets the page accessed bit (PTW.U) in the PTW for a page 88 // // in a descriptor segment page table. This cycle always 89 // // immediately follows a DSPTW cycle. 90 // 91 // apuCycle_MPTW // Modify PTW 92 // // Sets the page modified bit (PTW.M) in the PTW for a page 93 // // in other than a descriptor segment page table. 94 // }; 95 96 // These bits are aligned to match the CU word 0 APU status bit positions. 97 // This produces some oddness in the scu save/restore code. 98 99 typedef enum apuStatusBits 100 { 101 apuStatus_PI_AP = 1u << (35 - 24), // -AP Instruction fetch append cycle 102 apuStatus_DSPTW = 1u << (35 - 25), // Fetch descriptor segment PTW 103 apuStatus_SDWNP = 1u << (35 - 26), // Fetch SDW non paged 104 apuStatus_SDWP = 1u << (35 - 27), // Fetch SDW paged 105 apuStatus_PTW = 1u << (35 - 28), // Fetch PTW 106 apuStatus_PTW2 = 1u << (35 - 29), // Fetch prepage PTW 107 apuStatus_FAP = 1u << (35 - 30), // Fetch final address - paged 108 apuStatus_FANP = 1u << (35 - 31), // Fetch final address - nonpaged 109 apuStatus_FABS = 1u << (35 - 32), // Fetch final address - absolute 110 111 // XXX these don't seem like the right solution. 112 // XXX there are MDSPTW and MPTW bits in the APU history 113 // register, but not in the CU. 114 115 apuStatus_MDSPTW = 1u << (35 - 25), // Fetch descriptor segment PTW 116 apuStatus_MPTW = 1u << (35 - 28) // Fetch PTW 117 } apuStatusBits; 118 119 static inline void set_apu_status (apuStatusBits status) /* */ 120 { 121 word12 FCT = cpu.cu.APUCycleBits & MASK3; 122 cpu.cu.APUCycleBits = (status & 07770) | FCT; 123 } 124 125 #ifdef TESTING 126 t_stat dump_sdwam (void); 127 #endif 128 word24 do_append_cycle (processor_cycle_type thisCycle, word36 * data, uint nWords); 129 #ifndef OLDAPP 130 word24 doAppendCycleUnknown (word36 * data, uint nWords); 131 word24 doAppendCycleOperandStore (word36 * data, uint nWords); 132 word24 doAppendCycleOperandRead (word36 * data, uint nWords); 133 word24 doAppendCycleIndirectWordFetch (word36 * data, uint nWords); 134 word24 doAppendCycleRTCDOperandFetch (word36 * data, uint nWords); 135 word24 doAppendCycleInstructionFetch (word36 * data, uint nWords); 136 word24 doAppendCycleAPUDataRead (word36 * data, uint nWords); 137 word24 doAppendCycleAPUDataStore (word36 * data, uint nWords); 138 word24 doAppendCycleABSA (word36 * data, uint nWords); 139 # ifdef LOCKLESS 140 word24 doAppendCycleOperandRMW (word36 * data, uint nWords); 141 word24 doAppendCycleAPUDataRMW (word36 * data, uint nWords); 142 # endif // LOCKLESS 143 #else // OLDAPP 144 # define doAppendCycleUnknown(data, nWords) do_append_cycle (UNKNOWN_CYCLE, data, nWords) 145 # define doAppendCycleOperandStore(data, nWords) do_append_cycle (OPERAND_STORE, data, nWords) 146 # define doAppendCycleOperandRead(data, nWords) do_append_cycle (OPERAND_READ, data, nWords) 147 # define doAppendCycleIndirectWordFetch(data, nWords) do_append_cycle (INDIRECT_WORD_FETCH, data, nWords) 148 # define doAppendCycleRTCDOperandFetch(data, nWords) do_append_cycle (RTCD_OPERAND_FETCH, data, nWords) 149 # define doAppendCycleInstructionFetch(data, nWords) do_append_cycle (INSTRUCTION_FETCH, data, nWords) 150 # define doAppendCycleAPUDataRead(data, nWords) do_append_cycle (APU_DATA_READ, data, nWords) 151 # define doAppendCycleAPUDataStore(data, nWords) do_append_cycle (APU_DATA_STORE, data, nWords) 152 # define doAppendCycleABSA(data, nWords) do_append_cycle (ABSA_CYCLE, data, nWords) 153 # ifdef LOCKLESS 154 # define doAppendCycleOperandRMW(data, nWords) do_append_cycle (OPERAND_RMW, data, nWords) 155 # define doAppendCycleAPUDataRMW(data, nWords) do_append_cycle (APU_DATA_RMW, data, nWords) 156 # endif // LOCKLESS 157 #endif // OLDAPP 158 159 void do_ldbr (word36 * Ypair); 160 void do_sdbr (word36 * Ypair); 161 void do_camp (word36 Y); 162 void do_cams (word36 Y); 163 #ifdef TESTING 164 int dbgLookupAddress (word18 segno, word18 offset, word24 * finalAddress, 165 char * * msg); 166 #endif 167 sdw0_s * getSDW (word15 segno); 168 169 static inline void fauxDoAppendCycle (processor_cycle_type thisCycle) /* */ 170 { 171 cpu.apu.lastCycle = thisCycle; 172 }