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