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)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
167 {
168 cpu.apu.lastCycle = thisCycle;
169 }