First Commit of my working state
[simh.git] / I7094 / i7094_cpu.c
1 /* i7094_cpu.c: IBM 7094 CPU simulator
2
3 Copyright (c) 2003-2007, Robert M. Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 cpu 7094 central processor
27
28 28-Apr-07 RMS Removed clock initialization
29 29-Oct-06 RMS Added additional expanded core instructions
30 17-Oct-06 RMS Fixed the fix in halt IO wait loop
31 16-Jun-06 RMS Fixed bug in halt IO wait loop
32
33 The register state for the 7094 is:
34
35 AC<S,Q,P,1:35> accumulator
36 MQ<S,1:35> multiplier-quotient register
37 SI<S,1:35> storage indicators
38 KEYS<0:35> front panel keys (switches)
39 IC<0:14> instruction counter (called PC here)
40 XR<0:14>[8] index registers (XR[0] is always 0)
41 SSW<0:5> sense switches
42 SLT<0:3> sense lights
43 OVF AC overflow
44 MQO MQ overflow
45 DVC divide check
46 IOC I/O check
47 TTRAP transfer trap mode
48 CTRAP copy trap mode (for 709 compatibility)
49 FTRAP floating trap mode (off is 704 compatibility)
50 STRAP select trap mode
51 STORN storage nullifcation mode
52 MULTI multi-tag mode (7090 compatibility)
53
54 CTSS required a set of special features: memory extension (to 65K),
55 protection, and relocation. Additional state:
56
57 USER user mode
58 INST_BASE instruction memory select (A vs B core)
59 DATA_BASE data memory select (A vs B core)
60 IND_RELOC<0:6> relocation value (block number)
61 IND_START<0:6> start address block
62 IND_LIMIT<0:6> limit address block
63
64 The 7094 had five instruction formats: memory reference,
65 memory reference with count, convert, decrement, and immediate.
66
67 00000000011 11 1111 112 222222222333333
68 S12345678901 23 4567 890 123456789012345
69 +------------+--+----+---+---------------+
70 | opcode |ND|0000|tag| address | memory reference
71 +------------+--+----+---+---------------+
72
73 00000000011 111111 112 222222222333333
74 S12345678901 234567 890 123456789012345
75 +------------+------+---+---------------+
76 | opcode | count|tag| address | memory reference
77 +------------+------+---+---------------+ with count
78
79 000000000 11111111 11 2 222222222333333
80 S123456789 01234567 89 0 123456789012345
81 +----------+--------+--+-+---------------+
82 | opcode | count |00|X| address | convert
83 +----------+--------+--+-+---------------+
84
85 00 000000011111111 112 222222222333333
86 S12 345678901234567 890 123456789012345
87 +---+---------------+---+---------------+
88 |opc| decrement |tag| address | decrement
89 +---+---------------+---+---------------+
90
91 00000000011 111111 112222222222333333
92 S12345678901 234567 890123456789012345
93 +------------+------+------------------+
94 | opcode |000000| immediate | immediate
95 +------------+------+------------------+
96
97 This routine is the instruction decode routine for the 7094.
98 It is called from the simulator control program to execute
99 instructions in simulated memory, starting at the simulated PC.
100 It runs until a stop condition occurs.
101
102 General notes:
103
104 1. Reasons to stop. The simulator can be stopped by:
105
106 HALT instruction
107 illegal instruction
108 illegal I/O operation for device
109 illegal I/O operation for channel
110 breakpoint encountered
111 nested XEC's exceeding limit
112 divide check
113 I/O error in I/O simulator
114
115 2. Data channel traps. The 7094 is a channel-based system.
116 Channels can generate traps for errors and status conditions.
117 Channel trap state:
118
119 ch_flags[0..7] flags for channels A..H
120 chtr_enab channel trap enables
121 chtr_inht channel trap inhibit due to trap (cleared by RCT)
122 chtr_inhi channel trap inhibit due to XEC, ENAB, RCT, RDS,
123 or WDS (cleared after one instruction)
124
125 Channel traps are summarized in variable chtr_pend.
126
127 3. Arithmetic. The 7094 uses signed magnitude arithmetic for
128 integer and floating point calculations, and 2's complement
129 arithmetic for indexing calculations.
130
131 4. Adding I/O devices. These modules must be modified:
132
133 i7094_defs.h add device definitions
134 i7094_io.c add device address mapping
135 i7094_sys.c add sim_devices table entry
136 */
137
138 #include "i7094_defs.h"
139
140 #define PCQ_SIZE 64 /* must be 2**n */
141 #define PCQ_MASK (PCQ_SIZE - 1)
142 #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (PC | inst_base)
143
144 #define HIST_MIN 64
145 #define HIST_MAX (2 << 18)
146 #define HIST_CH_C 1 /* include channel */
147 #define HIST_CH_I 2 /* include IO */
148
149 #define HALT_IO_LIMIT ((2 << 18) + 1) /* max wait to stop */
150
151 t_uint64 *M = NULL; /* memory */
152 t_uint64 AC = 0; /* AC */
153 t_uint64 MQ = 0; /* MQ */
154 t_uint64 SI = 0; /* indicators */
155 t_uint64 KEYS = 0; /* storage keys */
156 uint32 PC = 0; /* PC (IC) */
157 uint32 oldPC = 0; /* prior PC */
158 uint32 XR[8] = { 0 }; /* index registers */
159 uint32 SSW = 0; /* sense switches */
160 uint32 SLT = 0; /* sense lights */
161 uint32 ch_req = 0; /* channel requests */
162 uint32 chtr_pend = 0; /* chan trap pending */
163 uint32 chtr_inht = 0; /* chan trap inhibit trap */
164 uint32 chtr_inhi = 0; /* chan trap inhibit inst */
165 uint32 chtr_enab = 0; /* chan trap enables */
166 uint32 mode_ttrap = 0; /* transfer trap mode */
167 uint32 mode_ctrap = 0; /* copy trap mode */
168 uint32 mode_strap = 0; /* select trap mode */
169 uint32 mode_ftrap = 0; /* floating trap mode */
170 uint32 mode_storn = 0; /* storage nullification */
171 uint32 mode_multi = 0; /* multi-index mode */
172 uint32 ind_ovf = 0; /* overflow */
173 uint32 ind_mqo = 0; /* MQ overflow */
174 uint32 ind_dvc = 0; /* divide check */
175 uint32 ind_ioc = 0; /* IO check */
176 uint32 cpu_model = I_9X|I_94; /* CPU type */
177 uint32 mode_user = 0; /* (CTSS) user mode */
178 uint32 ind_reloc = 0; /* (CTSS) relocation */
179 uint32 ind_start = 0; /* (CTSS) prot start */
180 uint32 ind_limit = 0; /* (CTSS) prot limit */
181 uint32 inst_base = 0; /* (CTSS) inst A/B sel */
182 uint32 data_base = 0; /* (CTSS) data A/B sel */
183 uint32 xec_max = 16; /* XEC chain limit */
184 uint32 ht_pend = 0; /* HTR pending */
185 uint32 ht_addr = 0; /* HTR address */
186 uint32 stop_illop = 1; /* stop on ill op */
187 uint32 cpu_astop = 0; /* address stop */
188 static uint32 eamask = AMASK; /* (dynamic) addr mask */
189
190 uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
191 int32 pcq_p = 0; /* PC queue ptr */
192 REG *pcq_r = NULL; /* PC queue reg ptr */
193 int32 hst_p = 0; /* history pointer */
194 int32 hst_lnt = 0; /* history length */
195 uint32 hst_ch = 0; /* channel history */
196 InstHistory *hst = NULL; /* instruction history */
197
198 extern uint32 ch_sta[NUM_CHAN];
199 extern uint32 ch_flags[NUM_CHAN];
200 extern DEVICE mt_dev[NUM_CHAN];
201 extern DEVICE ch_dev[NUM_CHAN];
202 extern FILE *sim_deb;
203 extern int32 sim_int_char;
204 extern int32 sim_interval;
205 extern int32 sim_switches;
206 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
207
208 /* Forward and external declarations */
209
210 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
211 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
212 t_stat cpu_reset (DEVICE *dptr);
213 t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
214 t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc);
215 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
216 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
217 t_bool ReadI (uint32 va, t_uint64 *dat);
218 t_bool Read (uint32 va, t_uint64 *dat);
219 t_bool Write (uint32 va, t_uint64 dat);
220 void WriteTA (uint32 pa, uint32 addr);
221 void WriteTAD (uint32 pa, uint32 addr, uint32 decr);
222 void TrapXfr (uint32 newpc);
223 t_bool fp_trap (uint32 spill);
224 t_bool prot_trap (uint32 decr);
225 t_bool sel_trap (uint32 va);
226 t_bool cpy_trap (uint32 va);
227 uint32 get_xri (uint32 tag);
228 uint32 get_xrx (uint32 tag);
229 void put_xr (uint32 tag, uint32 dat);
230 t_stat cpu_fprint_one_inst (FILE *st, uint32 pc, uint32 rpt, uint32 ea,
231 t_uint64 ir, t_uint64 ac, t_uint64 mq, t_uint64 si, t_uint64 opnd);
232
233 extern uint32 chtr_eval (uint32 *decr);
234 extern void op_add (t_uint64 sr);
235 extern void op_mpy (t_uint64 ac, t_uint64 sr, uint32 sc);
236 extern t_bool op_div (t_uint64 sr, uint32 sc);
237 extern uint32 op_fad (t_uint64 sr, t_bool norm);
238 extern uint32 op_fmp (t_uint64 sr, t_bool norm);
239 extern uint32 op_fdv (t_uint64);
240 extern uint32 op_dfad (t_uint64 shi, t_uint64 slo, t_bool norm);
241 extern uint32 op_dfmp (t_uint64 shi, t_uint64 slo, t_bool norm);
242 extern uint32 op_dfdv (t_uint64 shi, t_uint64 slo);
243 extern void op_als (uint32 ea);
244 extern void op_ars (uint32 ea);
245 extern void op_lls (uint32 ea);
246 extern void op_lrs (uint32 ea);
247 extern void op_lgl (uint32 ea);
248 extern void op_lgr (uint32 ea);
249 extern t_stat op_pse (uint32 ea);
250 extern t_stat op_mse (uint32 ea);
251 extern t_stat ch_op_ds (uint32 ch, uint32 ds, uint32 unit);
252 extern t_stat ch_op_nds (uint32 ch, uint32 ds, uint32 unit);
253 extern t_stat ch_op_start (uint32 ch, uint32 clc, t_bool reset);
254 extern t_stat ch_op_store (uint32 ch, t_uint64 *dat);
255 extern t_stat ch_op_store_diag (uint32 ch, t_uint64 *dat);
256 extern t_stat ch_proc (uint32 ch);
257
258 /* CPU data structures
259
260 cpu_dev CPU device descriptor
261 cpu_unit CPU unit
262 cpu_reg CPU register list
263 cpu_mod CPU modifier list
264 */
265
266 UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, STDMEMSIZE) };
267
268 REG cpu_reg[] = {
269 { ORDATA (PC, PC, ASIZE) },
270 { ORDATA (AC, AC, 38) },
271 { ORDATA (MQ, MQ, 36) },
272 { ORDATA (SI, SI, 36) },
273 { ORDATA (KEYS, KEYS, 36) },
274 { ORDATA (XR1, XR[1], 15) },
275 { ORDATA (XR2, XR[2], 15) },
276 { ORDATA (XR3, XR[3], 15) },
277 { ORDATA (XR4, XR[4], 15) },
278 { ORDATA (XR5, XR[5], 15) },
279 { ORDATA (XR6, XR[6], 15) },
280 { ORDATA (XR7, XR[7], 15) },
281 { FLDATA (SS1, SSW, 5) },
282 { FLDATA (SS2, SSW, 4) },
283 { FLDATA (SS3, SSW, 3) },
284 { FLDATA (SS4, SSW, 2) },
285 { FLDATA (SS5, SSW, 1) },
286 { FLDATA (SS6, SSW, 0) },
287 { FLDATA (SL1, SLT, 3) },
288 { FLDATA (SL2, SLT, 2) },
289 { FLDATA (SL3, SLT, 1) },
290 { FLDATA (SL4, SLT, 0) },
291 { FLDATA (OVF, ind_ovf, 0) },
292 { FLDATA (MQO, ind_mqo, 0) },
293 { FLDATA (DVC, ind_dvc, 0) },
294 { FLDATA (IOC, ind_ioc, 0) },
295 { FLDATA (TTRAP, mode_ttrap, 0) },
296 { FLDATA (CTRAP, mode_ctrap, 0) },
297 { FLDATA (STRAP, mode_strap, 0) },
298 { FLDATA (FTRAP, mode_ftrap, 0) },
299 { FLDATA (STORN, mode_storn, 0) },
300 { FLDATA (MULTI, mode_multi, 0) },
301 { ORDATA (CHREQ, ch_req, NUM_CHAN) },
302 { FLDATA (CHTR_PEND, chtr_pend, 0) },
303 { FLDATA (CHTR_INHT, chtr_inht, 0) },
304 { FLDATA (CHTR_INHI, chtr_inhi, 0) },
305 { ORDATA (CHTR_ENAB, chtr_enab, 30) },
306 { FLDATA (USERM, mode_user, 0) },
307 { FLDATA (IMEM, inst_base, BCORE_V) },
308 { FLDATA (DMEM, data_base, BCORE_V) },
309 { GRDATA (RELOC, ind_reloc, 8, VA_N_BLK, VA_V_BLK) },
310 { GRDATA (START, ind_start, 8, VA_N_BLK, VA_V_BLK) },
311 { GRDATA (LIMIT, ind_limit, 8, VA_N_BLK, VA_V_BLK) },
312 { ORDATA (OLDPC, oldPC, ASIZE), REG_RO },
313 { BRDATA (PCQ, pcq, 8, ASIZE, PCQ_SIZE), REG_RO+REG_CIRC },
314 { ORDATA (PCQP, pcq_p, 6), REG_HRO },
315 { FLDATA (HTPEND, ht_pend, 0) },
316 { ORDATA (HTADDR, ht_addr, ASIZE) },
317 { DRDATA (XECMAX, xec_max, 8), PV_LEFT + REG_NZ },
318 { ORDATA (WRU, sim_int_char, 8) },
319 { FLDATA (STOP_ILL, stop_illop, 0) },
320 { ORDATA (MODEL, cpu_model, 4), REG_HRO },
321 { NULL }
322 };
323
324 MTAB cpu_mod[] = {
325 { MTAB_XTD | MTAB_VDV, I_9X|I_94|I_CT, "MODEL", "CTSS",
326 &cpu_set_model, &cpu_show_model, NULL },
327 { MTAB_XTD | MTAB_VDV, I_9X|I_94, NULL, "7094",
328 &cpu_set_model, NULL, NULL },
329 { MTAB_XTD | MTAB_VDV, I_9X, NULL, "7090",
330 &cpu_set_model, NULL, NULL },
331 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
332 &cpu_set_hist, &cpu_show_hist },
333 { 0 }
334 };
335
336 DEVICE cpu_dev = {
337 "CPU", &cpu_unit, cpu_reg, cpu_mod,
338 1, 8, PASIZE, 1, 8, 36,
339 &cpu_ex, &cpu_dep, &cpu_reset,
340 NULL, NULL, NULL,
341 NULL, DEV_DEBUG
342 };
343
344 /* Instruction decode table */
345
346 const uint8 op_flags[1024] = {
347 I_XN , 0 , 0 , 0 , /* +000 */
348 0 , 0 , 0 , 0 ,
349 0 , 0 , 0 , 0 ,
350 0 , 0 , 0 , 0 ,
351 I_XN , I_XN|I_9X , I_XN , 0 , /* +020 */
352 I_XN , 0 , I_XN , I_XN ,
353 I_XN , I_XN , I_XN , I_XN ,
354 0 , 0 , 0 , 0 ,
355 I_XN|I_9X , I_9X , I_XN|I_9X , I_9X , /* +040 */
356 I_9X , 0 , I_XN|I_9X , 0 ,
357 0 , I_9X , 0 , 0 ,
358 I_9X , I_9X , I_9X , I_9X ,
359 I_XN , I_XN , I_XN , I_XN , /* +060 */
360 I_XN , I_XN , I_XN , I_XN ,
361 0 , 0 , 0 , 0 ,
362 0 , 0 , 0 , 0 ,
363 I_XN , I_XN|I_CT , 0 , 0 , /* +100 */
364 0 , 0 , 0 , 0 ,
365 0 , 0 , 0 , 0 ,
366 I_9X , I_9X , I_9X , I_9X ,
367 I_XN , 0 , 0 , 0 , /* +120 */
368 0 , 0 , 0 , 0 ,
369 0 , I_9X , 0 , 0 ,
370 0 , 0 , 0 , 0 ,
371 I_XN , 0 , 0 , 0 , /* +140 */
372 0 , 0 , 0 , 0 ,
373 0 , 0 , 0 , 0 ,
374 0 , 0 , 0 , 0 ,
375 0 , I_XN|I_9X , I_XN|I_9X , 0 , /* +160 */
376 0 , 0 , 0 , 0 ,
377 0 , 0 , 0 , 0 ,
378 0 , 0 , 0 , 0 ,
379 I_XNR , 0 , 0 , 0 , /* +200 */
380 I_XNR , I_XNR , 0 , 0 ,
381 0 , 0 , 0 , 0 ,
382 0 , 0 , 0 , 0 ,
383 I_XNR|I_9X, I_XNR , 0 , 0 , /* +220 */
384 I_XNR|I_9X, I_XNR , I_XNR|I_9X, I_XNR ,
385 0 , 0 , 0 , 0 ,
386 0 , 0 , 0 , 0 ,
387 I_XNR|I_9X, I_XNR , 0 , 0 , /* +240 */
388 0 , 0 , 0 , 0 ,
389 0 , 0 , 0 , 0 ,
390 0 , 0 , 0 , 0 ,
391 I_XNR , I_XND|I_94, 0 , 0 , /* +260 */
392 0 , 0 , 0 , 0 ,
393 0 , 0 , 0 , 0 ,
394 0 , 0 , 0 , 0 ,
395 I_XNR , I_XND|I_94, I_XNR , I_XND|I_94, /* +300 */
396 I_XNR|I_9X, I_XND|I_94, I_XNR|I_9X, I_XND|I_94,
397 0 , 0 , 0 , 0 ,
398 0 , 0 , 0 , 0 ,
399 I_XNR|I_9X, 0 , I_XNR|I_9X, 0 , /* +320 */
400 0 , 0 , 0 , 0 ,
401 0 , 0 , 0 , 0 ,
402 0 , 0 , 0 , 0 ,
403 I_XNR , 0 , 0 , 0 , /* +340 */
404 0 , 0 , 0 , 0 ,
405 0 , 0 , 0 , 0 ,
406 0 , 0 , 0 , 0 ,
407 0 , I_XNR , 0 , 0 , /* +360 */
408 0 , 0 , 0 , 0 ,
409 0 , 0 , 0 , 0 ,
410 0 , 0 , 0 , 0 ,
411 I_XNR , I_XNR|I_9X, I_XNR , 0 , /* +400 */
412 0 , 0 , 0 , 0 ,
413 0 , 0 , 0 , 0 ,
414 0 , 0 , 0 , 0 ,
415 0 , 0 , 0 , 0 , /* +420 */
416 0 , 0 , 0 , 0 ,
417 0 , 0 , 0 , 0 ,
418 0 , 0 , 0 , 0 ,
419 I_XNR|I_9X, I_XNR|I_9X, I_XNR|I_9X, I_XNR|I_94, /* +440 */
420 I_XNR|I_9X, I_XNR|I_9X, I_XNR|I_9X, 0 ,
421 0 , 0 , 0 , 0 ,
422 0 , 0 , 0 , 0 ,
423 I_9X , 0 , 0 , 0 , /* +460 */
424 0 , 0 , 0 , 0 ,
425 0 , 0 , 0 , 0 ,
426 0 , 0 , 0 , 0 ,
427 I_XNR|I_9X, 0 , I_XNR , 0 , /* +500 */
428 0 , 0 , 0 , 0 ,
429 0 , 0 , 0 , 0 ,
430 0 , 0 , 0 , 0 ,
431 I_XNR , 0 , I_XNR , 0 , /* +520 */
432 0 , 0 , 0 , 0 ,
433 0 , 0 , 0 , 0 ,
434 I_R , I_R , 0 , 0 ,
435 I_XN , I_XN , I_XN , I_XN , /* +540 */
436 I_XN , I_XN , I_XN , I_XN ,
437 0 , 0 , 0 , 0 ,
438 0 , 0 , 0 , 0 ,
439 I_XNR , 0 , I_XNR|I_CT, 0 , /* +560 */
440 I_XNR , 0 , 0 , 0 ,
441 0 , 0 , 0 , 0 ,
442 0 , 0 , 0 , 0 ,
443 I_XN , I_XN , I_XN , 0 , /* +600 */
444 I_XN|I_9X , 0 , 0 , 0 ,
445 0 , 0 , 0 , 0 ,
446 0 , 0 , 0 , 0 ,
447 0 , I_XNR , I_XNR , 0 , /* +620 */
448 0 , I_XNR|I_9X, 0 , 0 ,
449 I_XNR|I_9X, 0 , 0 , 0 ,
450 I_R , 0 , I_R|I_94 , 0 ,
451 I_XN , I_XN , I_XN , I_XN , /* +640 */
452 I_XN|I_9X , I_XN|I_9X , I_XN|I_9X , I_XN|I_9X ,
453 0 , 0 , 0 , 0 ,
454 0 , 0 , 0 , 0 ,
455 0 , 0 , 0 , 0 , /* +660 */
456 0 , 0 , 0 , 0 ,
457 0 , 0 , 0 , 0 ,
458 0 , 0 , 0 , 0 ,
459 I_9X , 0 , 0 , 0 , /* +700 */
460 0 , 0 , 0 , 0 ,
461 0 , 0 , 0 , 0 ,
462 0 , 0 , 0 , 0 ,
463 0 , 0 , 0 , 0 , /* +720 */
464 0 , 0 , 0 , 0 ,
465 0 , 0 , 0 , 0 ,
466 0 , 0 , 0 , 0 ,
467 0 , 0 , 0 , 0 , /* +740 */
468 0 , 0 , 0 , 0 ,
469 0 , 0 , 0 , 0 ,
470 0 , 0 , I_94 , 0 ,
471 I_X , 0 , I_X , I_X , /* +760 */
472 I_X , I_X , I_X , I_X ,
473 I_X , I_X , I_X , 0 ,
474 0 , 0 , 0 , 0 ,
475
476 I_XN , 0 , 0 , 0 , /* -000 */
477 0 , 0 , 0 , 0 ,
478 0 , 0 , 0 , 0 ,
479 0 , 0 , 0 , 0 ,
480 I_XN , I_XN|I_9X , I_XN , 0 , /* -020 */
481 I_XN , 0 , I_XN , I_XN ,
482 I_XN , I_XN , I_XN , I_XN ,
483 0 , 0 , 0 , 0 ,
484 0 , 0 , 0 , 0 , /* -040 */
485 0 , 0 , I_9X , 0 ,
486 0 , I_9X , 0 , 0 ,
487 I_9X , I_9X , I_9X , I_9X ,
488 I_XN|I_9X , I_XN|I_9X , I_XN|I_9X , I_XN|I_9X , /* -060 */
489 I_XN|I_9X , I_XN|I_9X , I_XN|I_9X , I_XN|I_9X ,
490 0 , 0 , 0 , 0 ,
491 0 , 0 , 0 , 0 ,
492 I_XN , I_XN|I_CT , 0 , 0 , /* -100 */
493 0 , 0 , 0 , 0 ,
494 0 , 0 , 0 , 0 ,
495 I_9X , I_9X , I_9X , I_9X ,
496 I_XN , 0 , 0 , 0 , /* -120 */
497 0 , 0 , 0 , 0 ,
498 I_9X , 0 , 0 , 0 ,
499 0 , 0 , 0 , 0 ,
500 I_XN|I_9X , 0 , 0 , 0 , /* -140 */
501 0 , 0 , 0 , 0 ,
502 0 , 0 , 0 , 0 ,
503 I_9X , I_9X , I_9X , I_9X ,
504 0 , 0 , 0 , 0 , /* -160 */
505 0 , 0 , 0 , 0 ,
506 0 , 0 , 0 , 0 ,
507 0 , 0 , 0 , 0 ,
508 I_XNR|I_9X, 0 , 0 , 0 , /* -200 */
509 0 , 0 , 0 , 0 ,
510 0 , 0 , 0 , 0 ,
511 0 , 0 , 0 , 0 ,
512 0 , 0 , 0 , 0 , /* -220 */
513 0 , 0 , 0 , 0 ,
514 0 , 0 , 0 , 0 ,
515 0 , 0 , 0 , 0 ,
516 I_XND|I_94, I_XND|I_94, 0 , 0 , /* -240 */
517 0 , 0 , 0 , 0 ,
518 0 , 0 , 0 , 0 ,
519 0 , 0 , 0 , 0 ,
520 I_XNR , I_XND|I_94, 0 , 0 , /* -260 */
521 0 , 0 , 0 , 0 ,
522 0 , 0 , 0 , 0 ,
523 0 , 0 , 0 , 0 ,
524 I_XNR , I_XND|I_94, I_XNR , I_XND|I_94, /* -300 */
525 I_XNR|I_9X, I_XND|I_94, I_XNR|I_9X, I_XND|I_94,
526 0 , 0 , 0 , 0 ,
527 0 , 0 , 0 , 0 ,
528 I_XNR , 0 , 0 , 0 , /* -320 */
529 0 , 0 , 0 , 0 ,
530 0 , 0 , 0 , 0 ,
531 0 , 0 , 0 , 0 ,
532 I_XNR , 0 , 0 , 0 , /* -340 */
533 0 , 0 , 0 , 0 ,
534 0 , 0 , 0 , 0 ,
535 0 , 0 , 0 , 0 ,
536 0 , 0 , 0 , 0 , /* -360 */
537 0 , 0 , 0 , 0 ,
538 0 , 0 , 0 , 0 ,
539 0 , 0 , 0 , 0 ,
540 I_XNR|I_9X, 0 , 0 , 0 , /* -400 */
541 0 , 0 , 0 , 0 ,
542 0 , 0 , 0 , 0 ,
543 0 , 0 , 0 , 0 ,
544 0 , 0 , 0 , 0 , /* -420 */
545 0 , 0 , 0 , 0 ,
546 0 , 0 , 0 , 0 ,
547 0 , 0 , 0 , 0 ,
548 0 , 0 , 0 , 0 , /* -440 */
549 0 , 0 , 0 , 0 ,
550 0 , 0 , 0 , 0 ,
551 0 , 0 , 0 , 0 ,
552 0 , 0 , 0 , 0 , /* -460 */
553 0 , 0 , 0 , 0 ,
554 0 , 0 , 0 , 0 ,
555 0 , 0 , 0 , 0 ,
556 I_XNR , I_XNR , 0 , 0 , /* -500 */
557 0 , 0 , 0 , 0 ,
558 0 , 0 , 0 , 0 ,
559 0 , 0 , 0 , 0 ,
560 I_XNR|I_9X, 0 , 0 , 0 , /* -520 */
561 0 , 0 , 0 , 0 ,
562 0 , 0 , 0 , 0 ,
563 I_R , I_R , 0 , 0 ,
564 I_XN , I_XN , I_XN , I_XN , /* -540 */
565 I_XN , I_XN , I_XNR , I_XN ,
566 0 , 0 , 0 , 0 ,
567 0 , 0 , 0 , 0 ,
568 0 , 0 , 0 , 0 , /* -560 */
569 I_XNR|I_CT, 0 , 0 , 0 ,
570 0 , 0 , 0 , 0 ,
571 0 , 0 , 0 , 0 ,
572 I_XN , 0 , I_XNR|I_9X, I_XN|I_94 , /* -600 */
573 0 , 0 , 0 , 0 ,
574 0 , 0 , 0 , 0 ,
575 0 , 0 , 0 , 0 ,
576 I_XNR|I_9X, 0 , 0 , 0 , /* -620 */
577 0 , I_XNR , 0 , 0 ,
578 0 , 0 , 0 , 0 ,
579 I_R , 0 , I_R|I_94 , 0 ,
580 I_XN , I_XN , I_XN , I_XN , /* -640 */
581 I_XN|I_9X , I_XN|I_9X , I_XN|I_9X , I_XN|I_9X ,
582 0 , 0 , 0 , 0 ,
583 0 , 0 , 0 , 0 ,
584 0 , 0 , 0 , 0 , /* -660 */
585 0 , 0 , 0 , 0 ,
586 0 , 0 , 0 , 0 ,
587 0 , 0 , 0 , 0 ,
588 I_9X , 0 , 0 , 0 , /* -700 */
589 0 , 0 , 0 , 0 ,
590 0 , 0 , 0 , 0 ,
591 0 , 0 , 0 , 0 ,
592 0 , 0 , 0 , 0 , /* -720 */
593 0 , 0 , 0 , 0 ,
594 0 , 0 , 0 , 0 ,
595 0 , 0 , 0 , 0 ,
596 0 , 0 , 0 , 0 , /* -740 */
597 0 , 0 , 0 , 0 ,
598 0 , 0 , 0 , 0 ,
599 0 , 0 , I_94 , 0 ,
600 I_X , I_X|I_CT , 0 , I_X , /* -760 */
601 0 , I_X , 0 , 0 ,
602 0 , 0 , I_X , I_X ,
603 I_9X , 0 , 0 , 0
604 };
605
606 /* Instruction execution routine */
607
608 t_stat sim_instr (void)
609 {
610 t_stat reason = SCPE_OK;
611 t_uint64 IR, SR, t, t1, t2, sr1;
612 uint32 op, fl, tag, tagi, addr, ea;
613 uint32 ch, dec, xr, xec_cnt, trp;
614 uint32 i, j, sc, s1, s2, spill;
615 t_bool tracing;
616
617 /* Restore register state */
618
619 ch_set_map (); /* set dispatch map */
620 if (!(cpu_model & (I_94|I_CT))) mode_multi = 1; /* ~7094? MTM always on */
621 eamask = mode_storn? A704_MASK: AMASK; /* set eff addr mask */
622 inst_base = inst_base & ~AMASK; /* A/B sel is 1b */
623 data_base = data_base & ~AMASK;
624 ind_reloc = ind_reloc & VA_BLK; /* canonical form */
625 ind_start = ind_start & VA_BLK;
626 ind_limit = (ind_limit & VA_BLK) | VA_OFF;
627 chtr_pend = chtr_eval (NULL); /* eval chan traps */
628 tracing = ((hst_lnt != 0) || DEBUG_PRS (cpu_dev));
629
630 if (ht_pend) { /* HTR pending? */
631 oldPC = (PC - 1) & AMASK;
632 ht_pend = 0; /* clear flag */
633 PCQ_ENTRY;
634 if (mode_ttrap) { /* trap? */
635 WriteTA (TRAP_STD_SAV, oldPC); /* save PC */
636 TrapXfr (TRAP_TRA_PC); /* trap */
637 }
638 else PC = ht_addr; /* branch */
639 }
640
641 /* Main instruction fetch/decode loop */
642
643 while (reason == SCPE_OK) { /* loop until error */
644
645 if (cpu_astop) { /* debug stop? */
646 cpu_astop = 0;
647 reason = SCPE_STOP;
648 break;
649 }
650
651 if (sim_interval <= 0) { /* intv cnt expired? */
652 if (reason = sim_process_event ()) break; /* process events */
653 chtr_pend = chtr_eval (NULL); /* eval chan traps */
654 }
655
656 for (i = 0; ch_req && (i < NUM_CHAN); i++) { /* loop thru channels */
657 if (ch_req & REQ_CH (i)) { /* channel request? */
658 if (reason = ch_proc (i)) break;
659 }
660 chtr_pend = chtr_eval (NULL);
661 if (reason) break; /* error? */
662 }
663
664 if (chtr_pend) { /* channel trap? */
665 addr = chtr_eval (&trp); /* get trap info, clr */
666 chtr_inht = 1; /* inhibit traps */
667 chtr_pend = 0; /* no trap pending */
668 WriteTAD (addr, PC, trp); /* wr trap addr,flag */
669 IR = ReadP (addr + 1); /* get trap instr */
670 oldPC = PC; /* save current PC */
671 }
672
673 else {
674 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
675 reason = STOP_IBKPT; /* stop simulation */
676 break;
677 }
678 if (chtr_inhi) { /* 1 cycle inhibit? */
679 chtr_inhi = 0; /* clear */
680 chtr_pend = chtr_eval (NULL); /* re-evaluate */
681 }
682 oldPC = PC; /* save current PC */
683 PC = (PC + 1) & eamask; /* increment PC */
684 if (!ReadI (oldPC, &IR)) continue; /* get inst; trap? */
685 }
686
687 sim_interval = sim_interval - 1;
688 xec_cnt = 0; /* clear XEC cntr */
689
690 XEC:
691
692 tag = GET_TAG (IR); /* get tag */
693 addr = (uint32) IR & eamask; /* get base addr */
694
695 /* Decrement format instructions */
696
697 if (IR & INST_T_DEC) { /* decrement type? */
698 op = GET_OPD (IR); /* get opcode */
699 dec = GET_DEC (IR); /* get decrement */
700 xr = get_xrx (tag); /* get xr, upd MTM */
701 if (tracing) { /* trace or history? */
702 if (hst_lnt) /* history enabled? */
703 cpu_ent_hist (oldPC|HIST_PC, xr, IR, 0);
704 if (DEBUG_PRS (cpu_dev))
705 cpu_fprint_one_inst (sim_deb, oldPC|HIST_PC, 0, xr,
706 IR, AC, MQ, SI, 0);
707 }
708 switch (op) {
709
710 case 01: /* TXI */
711 put_xr (tag, xr + dec); /* xr += decr */
712 PCQ_ENTRY;
713 if (mode_ttrap) { /* trap? */
714 WriteTA (TRAP_STD_SAV, oldPC); /* save PC */
715 TrapXfr (TRAP_TRA_PC); /* trap */
716 }
717 else PC = addr; /* branch */
718 break;
719
720 case 02: /* TIX */
721 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
722 if (xr > dec) { /* if xr > decr */
723 put_xr (tag, xr - dec); /* xr -= decr */
724 PCQ_ENTRY;
725 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
726 else PC = addr; /* branch */
727 }
728 break;
729
730 case 03: /* TXH */
731 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
732 if (xr > dec) { /* if xr > decr */
733 PCQ_ENTRY;
734 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
735 else PC = addr; /* branch */
736 }
737 break;
738
739 case 05: /* STR */
740 WriteTA (TRAP_STD_SAV, PC); /* save inst+1 */
741 PCQ_ENTRY;
742 PC = TRAP_STR_PC; /* branch to 2 */
743 break;
744
745 case 06: /* TNX */
746 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
747 if (xr > dec) put_xr (tag, xr - dec); /* if xr > decr */
748 else { /* xr -= decr */
749 PCQ_ENTRY;
750 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
751 else PC = addr; /* branch */
752 }
753 break;
754
755 case 07: /* TXL */
756 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
757 if (xr <= dec) { /* if xr <= decr */
758 PCQ_ENTRY;
759 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
760 else PC = addr; /* branch */
761 }
762 break;
763 }
764 } /* end if */
765
766 /* Normal format instructions */
767
768 else {
769 op = GET_OPC (IR); /* get opcode */
770 fl = op_flags[op]; /* get flags */
771 if (fl & I_MODEL & ~cpu_model) { /* invalid for model? */
772 if (stop_illop) reason = STOP_ILLEG; /* possible stop */
773 continue;
774 }
775 if (tag && (fl & I_X)) /* tag and indexable? */
776 ea = (addr - get_xri (tag)) & eamask; /* do indexing */
777 else ea = addr;
778 if (TST_IND (IR) && (fl & I_N)) { /* indirect? */
779 if (!ReadI (ea, &SR)) continue; /* get ind; trap? */
780 addr = (uint32) SR & eamask; /* get address */
781 tagi = GET_TAG (SR); /* get tag */
782 if (tagi) /* tag? */
783 ea = (addr - get_xri (tagi)) & eamask; /* do indexing */
784 else ea = addr;
785 }
786 if ((fl & I_R) && !Read (ea, &SR)) continue; /* read opnd; trap? */
787 else if (fl & I_D) { /* double prec? */
788 if ((ea & 1) && fp_trap (TRAP_F_ODD)) continue;
789 if (!Read (ea, &SR)) continue; /* SR gets high */
790 if (!Read (ea | 1, &sr1)) continue; /* "sr1" gets low */
791 }
792 if (tracing) { /* tracing or history? */
793 if (hst_lnt) /* history enabled? */
794 cpu_ent_hist (oldPC|HIST_PC, ea, IR, SR);
795 if (DEBUG_PRS (cpu_dev))
796 cpu_fprint_one_inst (sim_deb, oldPC|HIST_PC, 0, ea,
797 IR, AC, MQ, SI, SR);
798 }
799 switch (op) { /* case on opcode */
800
801 /* Positive instructions */
802
803 case 00000: /* HTR */
804 case 01000: /* also -HTR */
805 if (prot_trap (0)) break; /* user mode? */
806 ht_pend = 1; /* transfer pending */
807 ht_addr = ea; /* save address */
808 reason = STOP_HALT; /* halt if I/O done */
809 break;
810
811 case 00020: /* TRA */
812 case 01020: /* also -TRA */
813 PCQ_ENTRY;
814 if (mode_ttrap) { /* trap? */
815 WriteTA (TRAP_STD_SAV, oldPC); /* save PC */
816 TrapXfr (TRAP_TRA_PC); /* trap */
817 }
818 else PC = ea; /* branch */
819 break;
820
821 case 00021: /* TTR */
822 PCQ_ENTRY;
823 PC = ea; /* branch, no trap */
824 break;
825
826 case 00040: /* TLQ */
827 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
828 s1 = (AC & AC_S)? 1: 0; /* get AC, MQ sign, */
829 s2 = (MQ & SIGN)? 1: 0; /* magnitude */
830 t1 = AC & AC_MMASK;
831 t2 = MQ & MMASK; /* signs differ? */
832 if ((s1 != s2)? s2: /* y, br if MQ- */
833 ((t1 != t2) && (s2 ^ (t1 > t2)))) { /* n, br if sgn-^AC>MQ */
834 PCQ_ENTRY;
835 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
836 else PC = ea; /* branch */
837 }
838 break;
839
840 case 00041: /* IIA */
841 SI = SI ^ (AC & DMASK);
842 break;
843
844 case 00042: /* TIO */
845 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
846 if ((SI & AC) == (AC & DMASK)) { /* if ind on */
847 PCQ_ENTRY;
848 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
849 else PC = ea; /* branch */
850 }
851 break;
852
853 case 00043: /* OAI */
854 SI = SI | (AC & DMASK);
855 break;
856
857 case 00044: /* PAI */
858 SI = AC & DMASK;
859 break;
860
861 case 00046: /* TIF */
862 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
863 if ((SI & AC) == 0) { /* if ind off */
864 PCQ_ENTRY;
865 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
866 else PC = ea; /* branch */
867 }
868 break;
869
870 case 00051: /* IIR */
871 SI = SI ^ (IR & RMASK);
872 break;
873
874 case 00054: /* RFT */
875 t = IR & RMASK;
876 if ((SI & t) == 0) PC = (PC + 1) & eamask; /* if ind off, skip */
877 break;
878
879 case 00055: /* SIR */
880 SI = SI | (IR & RMASK);
881 break;
882
883 case 00056: /* RNT */
884 t = IR & RMASK;
885 if ((SI & t) == t) PC = (PC + 1) & eamask; /* if ind on, skip */
886 break;
887
888 case 00057: /* RIR */
889 SI = SI & ~(IR & RMASK);
890 break;
891
892 case 00074: /* TSX */
893 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
894 if (tag) put_xr (tag, ~oldPC + 1); /* save -inst loc */
895 PCQ_ENTRY;
896 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
897 else PC = ea; /* branch */
898 break;
899
900 case 00100: /* TZE */
901 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
902 if ((AC & AC_MMASK) == 0) { /* if AC Q,P,1-35 = 0 */
903 PCQ_ENTRY;
904 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
905 else PC = ea; /* branch */
906 }
907 break;
908
909 case 00101: /* (CTSS) TIA */
910 if (prot_trap (0)) break; /* not user mode? */
911 PCQ_ENTRY;
912 PC = ea;
913 inst_base = 0;
914 break;
915
916 case 00114: case 00115: case 00116: case 00117: /* CVR */
917 sc = GET_CCNT (IR);
918 SR = ea;
919 while (sc) {
920 ea = (uint32) ((AC & 077) + SR) & eamask;
921 if (!Read (ea, &SR)) break;
922 AC = (AC & AC_S) | ((AC >> 6) & 0017777777777) |
923 (SR & 0770000000000);
924 sc--;
925 }
926 if ((sc == 0) && (IR & INST_T_CXR1))
927 put_xr (1, (uint32) SR);
928 break;
929
930 case 00120: /* TPL */
931 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
932 if ((AC & AC_S) == 0) { /* if AC + */
933 PCQ_ENTRY;
934 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
935 else PC = ea; /* branch */
936 }
937 break;
938
939 case 00131: /* XCA */
940 t = MQ;
941 MQ = (AC & MMASK) | ((AC & AC_S)? SIGN: 0);
942 AC = (t & MMASK) | ((t & SIGN)? AC_S: 0);
943 break;
944
945 case 00140: /* TOV */
946 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
947 if (ind_ovf) { /* if overflow */
948 PCQ_ENTRY;
949 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
950 else PC = ea; /* branch */
951 ind_ovf = 0; /* clear overflow */
952 }
953 break;
954
955 case 00161: /* TQO */
956 if (!mode_ftrap) { /* only in 704 mode */
957 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
958 if (ind_mqo) { /* if MQ overflow */
959 PCQ_ENTRY;
960 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
961 else PC = ea; /* branch */
962 ind_mqo = 0; /* clear overflow */
963 }
964 }
965 break;
966
967 case 00162: /* TQP */
968 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
969 if ((MQ & SIGN) == 0) { /* if MQ + */
970 PCQ_ENTRY;
971 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
972 else PC = ea; /* branch */
973 }
974 break;
975
976 case 00200: /* MPY */
977 op_mpy (0, SR, 043);
978 break;
979
980 case 00204: /* VLM */
981 case 00205: /* for diagnostic */
982 sc = GET_VCNT (IR);
983 op_mpy (0, SR, sc);
984 break;
985
986 case 00220: /* DVH */
987 if (op_div (SR, 043)) {
988 ind_dvc = 1;
989 if (!prot_trap (0)) reason = STOP_DIVCHK;
990 }
991 break;
992
993 case 00221: /* DVP */
994 if (op_div (SR, 043)) ind_dvc = 1;
995 break;
996
997 case 00224: /* VDH */
998 case 00226: /* for diagnostic */
999 sc = GET_VCNT (IR);
1000 if (op_div (SR, sc)) {
1001 ind_dvc = 1;
1002 if (!prot_trap (0)) reason = STOP_DIVCHK;
1003 }
1004 break;
1005
1006 case 00225: /* VDP */
1007 case 00227: /* for diagnostic */
1008 sc = GET_VCNT (IR);
1009 if (op_div (SR, sc)) ind_dvc = 1;
1010 break;
1011
1012 case 00240: /* FDH */
1013 spill = op_fdv (SR);
1014 if (spill == TRAP_F_DVC) {
1015 ind_dvc = 1;
1016 if (!prot_trap (0)) reason = STOP_DIVCHK;
1017 }
1018 else if (spill) fp_trap (spill);
1019 break;
1020
1021 case 00241: /* FDP */
1022 spill = op_fdv (SR);
1023 if (spill == TRAP_F_DVC) ind_dvc = 1;
1024 else if (spill) fp_trap (spill);
1025 break;
1026
1027 case 00260: /* FMP */
1028 spill = op_fmp (SR, 1); /* MQ * SR */
1029 if (spill) fp_trap (spill);
1030 break;
1031
1032 case 00261: /* DFMP */
1033 spill = op_dfmp (SR, sr1, 1);
1034 if (spill) fp_trap (spill);
1035 break;
1036
1037 case 00300: /* FAD */
1038 spill = op_fad (SR, 1);
1039 if (spill) fp_trap (spill);
1040 break;
1041
1042 case 00301: /* DFAD */
1043 spill = op_dfad (SR, sr1, 1);
1044 if (spill) fp_trap (spill);
1045 break;
1046
1047 case 00302: /* FSB */
1048 spill = op_fad (SR ^ SIGN, 1);
1049 if (spill) fp_trap (spill);
1050 break;
1051
1052 case 00303: /* DFSB */
1053 spill = op_dfad (SR ^ SIGN, sr1, 1);
1054 if (spill) fp_trap (spill);
1055 break;
1056
1057 case 00304: /* FAM */
1058 spill = op_fad (SR & ~SIGN, 1);
1059 if (spill) fp_trap (spill);
1060 break;
1061
1062 case 00305: /* DFAM */
1063 spill = op_dfad (SR & ~SIGN, sr1, 1);
1064 if (spill) fp_trap (spill);
1065 break;
1066
1067 case 00306: /* FSM */
1068 spill = op_fad (SR | SIGN, 1);
1069 if (spill) fp_trap (spill);
1070 break;
1071
1072 case 00307: /* DFSM */
1073 spill = op_dfad (SR | SIGN, sr1, 1);
1074 if (spill) fp_trap (spill);
1075 break;
1076
1077 case 00320: /* ANS */
1078 SR = AC & SR;
1079 Write (ea, SR);
1080 break;
1081
1082 case 00322: /* ERA */
1083 AC = (AC ^ SR) & DMASK; /* AC S,Q cleared */
1084 break;
1085
1086 case 00340: /* CAS */
1087 s1 = (AC & AC_S)? 1: 0; /* get AC, MQ signs, */
1088 s2 = (SR & SIGN)? 1: 0;
1089 t1 = AC & AC_MMASK; /* magnitudes */
1090 t2 = SR & MMASK;
1091 if (s1 ^ s2) { /* diff signs? */
1092 if (s1) PC = (PC + 2) & eamask; /* AC < mem? skip 2 */
1093 }
1094 else if (t1 == t2) PC = (PC + 1) & eamask; /* equal? skip 1 */
1095 else if ((t1 < t2) ^ s1) /* AC < mem, AC +, or */
1096 PC = (PC + 2) & eamask; /* AC > mem, AC -? */
1097 break;
1098
1099 case 00361: /* ACL */
1100 t = (AC + SR) & DMASK; /* AC P,1-35 + SR */
1101 if (t < SR) t = (t + 1) & DMASK; /* end around carry */
1102 AC = (AC & (AC_S | AC_Q)) | t; /* preserve AC S,Q */
1103 break;
1104
1105 case 00400: /* ADD */
1106 op_add (SR);
1107 break;
1108
1109 case 00401: /* ADM */
1110 op_add (SR & MMASK);
1111 break;
1112
1113 case 00402: /* SUB */
1114 op_add (SR ^ SIGN);
1115 break;
1116
1117 case 00420: /* HPR */
1118 if (prot_trap (0)) break; /* user mode? */
1119 reason = STOP_HALT; /* halt if I/O done */
1120 break;
1121
1122 case 00440: /* IIS */
1123 SI = SI ^ SR;
1124 break;
1125
1126 case 00441: /* LDI */
1127 SI = SR;
1128 break;
1129
1130 case 00442: /* OSI */
1131 SI = SI | SR;
1132 break;
1133
1134 case 00443: /* DLD */
1135 AC = (SR & MMASK) | ((SR & SIGN)? AC_S: 0); /* normal load */
1136 if (!Read (ea | 1, &SR)) break; /* second load */
1137 MQ = SR;
1138 if (ea & 1) fp_trap (TRAP_F_ODD); /* trap after exec */
1139 break;
1140
1141 case 00444: /* OFT */
1142 if ((SI & SR) == 0) PC = (PC + 1) & eamask; /* skip if ind off */
1143 break;
1144
1145 case 00445: /* RIS */
1146 SI = SI & ~SR;
1147 break;
1148
1149 case 00446: /* ONT */
1150 if ((SI & SR) == SR) PC = (PC + 1) & eamask;/* skip if ind on */
1151 break;
1152
1153 case 00460: /* LDA (704) */
1154 cpy_trap (PC);
1155 break;
1156
1157 case 00500: /* CLA */
1158 AC = (SR & MMASK) | ((SR & SIGN)? AC_S: 0);
1159 break;
1160
1161 case 00502: /* CLS */
1162 AC = (SR & MMASK) | ((SR & SIGN)? 0: AC_S);
1163 break;
1164
1165 case 00520: /* ZET */
1166 if ((SR & MMASK) == 0) PC = (PC + 1) & eamask; /* skip if M 1-35 = 0 */
1167 break;
1168
1169 case 00522: /* XEC */
1170 if (xec_cnt++ >= xec_max) { /* xec chain limit? */
1171 reason = STOP_XEC; /* stop */
1172 break;
1173 }
1174 IR = SR; /* operand is new inst */
1175 chtr_inhi = 1; /* delay traps */
1176 chtr_pend = 0; /* no trap now */
1177 goto XEC; /* start over */
1178
1179 case 00534: /* LXA */
1180 if (tag) put_xr (tag, (uint32) SR); /* M addr -> xr */
1181 break;
1182
1183 case 00535: /* LAC */
1184 if (tag) put_xr (tag, NEG ((uint32) SR)); /* -M addr -> xr */
1185 break;
1186
1187 case 00560: /* LDQ */
1188 MQ = SR;
1189 break;
1190
1191 case 00562: /* (CTSS) LRI */
1192 if (prot_trap (0)) break; /* user mode? */
1193 ind_reloc = ((uint32) SR) & VA_BLK;
1194 break;
1195
1196 case 00564: /* ENB */
1197 if (prot_trap (0)) break; /* user mode? */
1198 chtr_enab = (uint32) SR; /* set enables */
1199 chtr_inht = 0; /* clear inhibit */
1200 chtr_inhi = 1; /* 1 cycle delay */
1201 chtr_pend = 0; /* no traps now */
1202 break;
1203
1204 case 00600: /* STZ */
1205 Write (ea, 0);
1206 break;
1207
1208 case 00601: /* STO */
1209 SR = (AC & MMASK) | ((AC & AC_S)? SIGN: 0);
1210 Write (ea, SR);
1211 break;
1212
1213 case 00602: /* SLW */
1214 Write (ea, AC & DMASK);
1215 break;
1216
1217 case 00604: /* STI */
1218 Write (ea, SI);
1219 break;
1220
1221 case 00621: /* STA */
1222 SR = (SR & ~AMASK) | (AC & AMASK);
1223 Write (ea, SR);
1224 break;
1225
1226 case 00622: /* STD */
1227 SR = (SR & ~XMASK) | (AC & XMASK);
1228 Write (ea, SR);
1229 break;
1230
1231 case 00625: /* STT */
1232 SR = (SR & ~TMASK) | (AC & TMASK);
1233 Write (ea, SR);
1234 break;
1235
1236 case 00630: /* STP */
1237 SR = (SR & ~PMASK) | (AC & PMASK);
1238 Write (ea, SR);
1239 break;
1240
1241 case 00634: /* SXA */
1242 SR = (SR & ~AMASK) | /* xr -> M addr */
1243 ((t_uint64) get_xrx (tag));
1244 Write (ea, SR);
1245 break;
1246
1247 case 00636: /* SCA */
1248 SR = (SR & ~AMASK) | /* -xr -> M addr */
1249 ((t_uint64) (NEG (get_xrx (tag)) & AMASK));
1250 Write (ea, SR);
1251 break;
1252
1253 case 00700: /* CPY (704) */
1254 cpy_trap (PC);
1255 break;
1256
1257 case 00734: /* PAX */
1258 if (tag) put_xr (tag, (uint32) AC); /* AC addr -> xr */
1259 break;
1260
1261 case 00737: /* PAC */
1262 if (tag) put_xr (tag, NEG ((uint32) AC)); /* -AC addr -> xr */
1263 break;
1264
1265 case 00754: /* PXA */
1266 AC = get_xrx (tag); /* xr -> AC */
1267 break;
1268
1269 case 00756: /* PCA */
1270 AC = NEG (get_xrx (tag)) & AMASK; /* -xr -> AC */
1271 break;
1272
1273 case 00760: /* PSE */
1274 if (prot_trap (0)) break; /* user mode? */
1275 reason = op_pse (ea);
1276 break;
1277
1278 case 00761: /* NOP */
1279 break;
1280
1281 case 00763: /* LLS */
1282 op_lls (ea);
1283 break;
1284
1285 case 00765: /* LRS */
1286 op_lrs (ea);
1287 break;
1288
1289 case 00767: /* ALS */
1290 op_als (ea);
1291 break;
1292
1293 case 00771: /* ARS */
1294 op_ars (ea);
1295 break;
1296
1297 case 00774: /* AXT */
1298 if (tag) put_xr (tag, addr); /* IR addr -> xr */
1299 break;
1300
1301 /* Negative instructions */
1302
1303 case 01021: /* ESNT */
1304 mode_storn = 1; /* enter nullification */
1305 PCQ_ENTRY;
1306 PC = ea; /* branch, no trap */
1307 break;
1308
1309 case 01042: /* RIA */
1310 SI = SI & ~AC;
1311 break;
1312
1313 case 01046: /* PIA */
1314 AC = SI;
1315 break;
1316
1317 case 01051: /* IIL */
1318 SI = SI ^ ((IR & RMASK) << 18);
1319 break;
1320
1321 case 01054: /* LFT */
1322 t = (IR & RMASK) << 18;
1323 if ((SI & t) == 0) PC = (PC + 1) & eamask; /* if ind off, skip */
1324 break;
1325
1326 case 01055: /* SIL */
1327 SI = SI | ((IR & RMASK) << 18);
1328 break;
1329
1330 case 01056: /* LNT */
1331 t = (IR & RMASK) << 18;
1332 if ((SI & t) == t) PC = (PC + 1) & eamask; /* if ind on, skip */
1333 break;
1334
1335 case 01057: /* RIL */
1336 SI = SI & ~((IR & RMASK) << 18);
1337 break;
1338
1339 case 01100: /* TNZ */
1340 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1341 if ((AC & AC_MMASK) != 0) { /* if AC != 0 */
1342 PCQ_ENTRY;
1343 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1344 else PC = ea; /* branch */
1345 }
1346 break;
1347
1348 case 01101: /* (CTSS) TIB */
1349 if (prot_trap (0)) break; /* not user mode? */
1350 PCQ_ENTRY;
1351 PC = ea;
1352 mode_user = 1;
1353 inst_base = BCORE_BASE;
1354 break;
1355
1356 case 01114: case 01115: case 01116: case 01117: /* CAQ */
1357 sc = GET_CCNT (IR);
1358 SR = ea;
1359 while (sc) {
1360 ea = (uint32) ((MQ >> 30) + SR) & eamask;
1361 if (!Read (ea, &SR)) break;
1362 MQ = ((MQ << 6) & DMASK) | (MQ >> 30);
1363 AC = (AC & AC_S) | ((AC + SR) & AC_MMASK);
1364 sc--;
1365 }
1366 if ((sc == 0) && (IR & INST_T_CXR1))
1367 put_xr (1, (uint32) SR);
1368 break;
1369
1370 case 01120: /* TMI */
1371 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1372 if ((AC & AC_S) != 0) { /* if AC - */
1373 PCQ_ENTRY;
1374 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1375 else PC = ea; /* branch */
1376 }
1377 break;
1378
1379 case 01130: /* XCL */
1380 t = MQ;
1381 MQ = AC & DMASK;
1382 AC = t;
1383 break;
1384
1385 case 01140: /* TNO */
1386 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1387 if (!ind_ovf) { /* if no overflow */
1388 PCQ_ENTRY;
1389 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1390 else PC = ea; /* branch */
1391 }
1392 ind_ovf = 0; /* clear overflow */
1393 break;
1394
1395 case 01154: case 01155: case 01156: case 01157: /* CRQ */
1396 sc = GET_CCNT (IR);
1397 SR = ea;
1398 while (sc) {
1399 ea = (uint32) ((MQ >> 30) + SR) & eamask;
1400 if (!Read (ea, &SR)) break;
1401 MQ = ((MQ << 6) & DMASK) | (SR >> 30);
1402 sc--;
1403 }
1404 if ((sc == 0) && (IR & INST_T_CXR1))
1405 put_xr (1, (uint32) SR);
1406 break;
1407
1408 case 01200: /* MPR */
1409 op_mpy (0, SR, 043);
1410 if (MQ & B1) AC = (AC & AC_S) | ((AC + 1) & AC_MMASK);
1411 break;
1412
1413 case 01240: /* DFDH */
1414 spill = op_dfdv (SR, sr1);
1415 if (spill == TRAP_F_DVC) {
1416 ind_dvc = 1;
1417 if (!prot_trap (0)) reason = STOP_DIVCHK;
1418 }
1419 else if (spill) fp_trap (spill);
1420 break;
1421
1422 case 01241: /* DFDP */
1423 spill = op_dfdv (SR, sr1);
1424 if (spill == TRAP_F_DVC) ind_dvc = 1;
1425 else if (spill) fp_trap (spill);
1426 break;
1427
1428 case 01260: /* UFM */
1429 spill = op_fmp (SR, 0);
1430 if (spill) fp_trap (spill);
1431 break;
1432
1433 case 01261: /* DUFM */
1434 spill = op_dfmp (SR, sr1, 0);
1435 if (spill) fp_trap (spill);
1436 break;
1437
1438 case 01300: /* UFA */
1439 spill = op_fad (SR, 0);
1440 if (spill) fp_trap (spill);
1441 break;
1442
1443 case 01301: /* DUFA */
1444 spill = op_dfad (SR, sr1, 0);
1445 if (spill) fp_trap (spill);
1446 break;
1447
1448 case 01302: /* UFS */
1449 spill = op_fad (SR ^ SIGN, 0);
1450 if (spill) fp_trap (spill);
1451 break;
1452
1453 case 01303: /* DUFS */
1454 spill = op_dfad (SR ^ SIGN, sr1, 0);
1455 if (spill) fp_trap (spill);
1456 break;
1457
1458 case 01304: /* UAM */
1459 spill = op_fad (SR & ~SIGN, 0);
1460 if (spill) fp_trap (spill);
1461 break;
1462
1463 case 01305: /* DUAM */
1464 spill = op_dfad (SR & ~SIGN, sr1, 0);
1465 if (spill) fp_trap (spill);
1466 break;
1467
1468 case 01306: /* USM */
1469 spill = op_fad (SR | SIGN, 0);
1470 if (spill) fp_trap (spill);
1471 break;
1472
1473 case 01307: /* DUSM */
1474 spill = op_dfad (SR | SIGN, sr1, 0);
1475 if (spill) fp_trap (spill);
1476 break;
1477
1478 case 01320: /* ANA */
1479 AC = AC & SR;
1480 break;
1481
1482 case 01340: /* LAS */
1483 t = AC & AC_MMASK; /* AC Q,P,1-35 */
1484 if (t < SR) PC = (PC + 2) & eamask;
1485 else if (t == SR) PC = (PC + 1) & eamask;
1486 break;
1487
1488 case 01400: /* SBM */
1489 op_add (SR | SIGN);
1490 break;
1491
1492 case 01500: /* CAL */
1493 AC = SR;
1494 break;
1495
1496 case 01501: /* ORA */
1497 AC = AC | SR;
1498 break;
1499
1500 case 01520: /* NZT */
1501 if ((SR & MMASK) != 0) PC = (PC + 1) & eamask; ;
1502 break;
1503
1504 case 01534: /* LXD */
1505 if (tag) put_xr (tag, GET_DEC (SR)); /* M decr -> xr */
1506 break;
1507
1508 case 01535: /* LDC */
1509 if (tag) put_xr (tag, NEG (GET_DEC (SR))); /* -M decr -> xr */
1510 break;
1511
1512 case 01564: /* (CTSS) LPI */
1513 if (prot_trap (0)) break; /* user mode? */
1514 ind_start = ((uint32) SR) & VA_BLK;
1515 ind_limit = (GET_DEC (SR) & VA_BLK) | VA_OFF;
1516 break;
1517
1518 case 01600: /* STQ */
1519 Write (ea, MQ);
1520 break;
1521
1522 case 01602: /* ORS */
1523 SR = SR | (AC & DMASK);
1524 Write (ea, SR);
1525 break;
1526
1527 case 01603: /* DST */
1528 SR = (AC & MMASK) | ((AC & AC_S)? SIGN: 0);
1529 if (!Write (ea, SR)) break;
1530 Write ((ea + 1) & eamask, MQ);
1531 break;
1532
1533 case 01620: /* SLQ */
1534 SR = (SR & RMASK) | (MQ & LMASK);
1535 Write (ea, SR);
1536 break;
1537
1538 case 01625: /* STL */
1539 SR = (SR & ~AMASK) | PC;
1540 Write (ea, SR);
1541 break;
1542
1543 case 01634: /* SXD */
1544 SR = (SR & ~XMASK) | /* xr -> M decr */
1545 (((t_uint64) get_xrx (tag)) << INST_V_DEC);
1546 Write (ea, SR);
1547 break;
1548
1549 case 01636: /* SCD */
1550 SR = (SR & ~XMASK) | /* -xr -> M decr */
1551 (((t_uint64) (NEG (get_xrx (tag)) & AMASK)) << INST_V_DEC);
1552 Write (ea, SR);
1553 break;
1554
1555 case 01700: /* CAD (704) */
1556 cpy_trap (PC);
1557 break;
1558
1559 case 01734: /* PDX */
1560 if (tag) put_xr (tag, GET_DEC (AC)); /* AC decr -> xr */
1561 break;
1562
1563 case 01737: /* PDC */
1564 if (tag) put_xr (tag, NEG (GET_DEC (AC))); /* -AC decr -> xr */
1565 break;
1566
1567 case 01754: /* PXD */
1568 AC = ((t_uint64) get_xrx (tag)) << INST_V_DEC;
1569 break; /* xr -> AC decr */
1570
1571 case 01756: /* PCD */
1572 AC = ((t_uint64) (NEG (get_xrx (tag)) & AMASK)) << INST_V_DEC;
1573 break; /* -xr -> AC decr */
1574
1575 case 01760: /* MSE */
1576 if (prot_trap (0)) break; /* user mode? */
1577 reason = op_mse (ea);
1578 break;
1579
1580 case 01761: /* (CTSS) ext core */
1581 if (prot_trap (0)) break; /* user mode? */
1582 if (ea == 041) /* SEA? */
1583 data_base = 0;
1584 else if (ea == 042) /* SEB? */
1585 data_base = BCORE_BASE;
1586 else if (ea == 043) { /* IFT? */
1587 if (inst_base == 0)
1588 PC = (PC + 1) & eamask;
1589 }
1590 else if (ea == 044) { /* EFT? */
1591 if (data_base == 0)
1592 PC = (PC + 1) & eamask;
1593 }
1594 else if (stop_illop)
1595 reason = STOP_ILLEG;
1596 break;
1597
1598 case 01763: /* LGL */
1599 op_lgl (ea);
1600 break;
1601
1602 case 01765: /* LGR */
1603 op_lgr (ea);
1604 break;
1605
1606 case 01773: /* RQL */
1607 sc = (ea & SCMASK) % 36;
1608 if (sc) MQ = ((MQ << sc) | (MQ >> (36 - sc))) & DMASK;
1609 break;
1610
1611 case 01774: /* AXC */
1612 if (tag) put_xr (tag, NEG (addr)); /* -IR addr -> xr */
1613 break;
1614
1615 /* IO instructions */
1616
1617 case 00022: case 00024: case 00026: /* TRCx */
1618 case 01022: case 01024: case 01026:
1619 if (prot_trap (0)) break; /* user mode? */
1620 ch = ((op & 077) - 00022) | ((op >> 9) & 01);
1621 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1622 if (!BIT_TST (chtr_enab, CHTR_V_TRC + ch) &&
1623 (ch_flags[ch] & CHF_TRC)) {
1624 PCQ_ENTRY;
1625 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1626 else PC = ea; /* branch */
1627 ch_flags[ch] = ch_flags[ch] & ~CHF_TRC;
1628 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1629 }
1630 break;
1631
1632 case 00027: case 01027:
1633 if (prot_trap (0)) break; /* user mode? */
1634 ch = 6 + ((op >> 9) & 01);
1635 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1636 if (!BIT_TST (chtr_enab, CHTR_V_TRC + ch) &&
1637 (ch_flags[ch] & CHF_TRC)) {
1638 PCQ_ENTRY;
1639 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1640 else PC = ea; /* branch */
1641 ch_flags[ch] = ch_flags[ch] & ~CHF_TRC;
1642 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1643 }
1644 break;
1645
1646 case 00030: case 00031: case 00032: case 00033: /* TEFx */
1647 case 01030: case 01031: case 01032: case 01033:
1648 if (prot_trap (0)) break; /* user mode? */
1649 ch = ((op & 03) << 1) | ((op >> 9) & 01);
1650 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1651 if (!BIT_TST (chtr_enab, CHTR_V_CME + ch) &&
1652 (ch_flags[ch] & CHF_EOF)) {
1653 PCQ_ENTRY;
1654 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1655 else PC = ea; /* branch */
1656 ch_flags[ch] = ch_flags[ch] & ~CHF_EOF;
1657 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1658 }
1659 break;
1660
1661 case 00060: case 00061: case 00062: case 00063: /* TCOx */
1662 case 00064: case 00065: case 00066: case 00067:
1663 if (prot_trap (0)) break; /* user mode? */
1664 ch = op & 07;
1665 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1666 if (ch_sta[ch] != CHXS_IDLE) {
1667 PCQ_ENTRY;
1668 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1669 else PC = ea; /* branch */
1670 }
1671 break;
1672
1673 case 01060: case 01061: case 01062: case 01063: /* TCNx */
1674 case 01064: case 01065: case 01066: case 01067:
1675 if (prot_trap (0)) break; /* user mode? */
1676 ch = op & 07;
1677 if (mode_ttrap) WriteTA (TRAP_STD_SAV, oldPC);
1678 if (ch_sta[ch] == CHXS_IDLE) {
1679 PCQ_ENTRY;
1680 if (mode_ttrap) TrapXfr (TRAP_TRA_PC); /* trap? */
1681 else PC = ea; /* branch */
1682 }
1683 break;
1684
1685 case 00540: case 00541: case 00542: case 00543: /* RCHx */
1686 case 01540: case 01541: case 01542: case 01543:
1687 if (prot_trap (0)) break; /* user mode? */
1688 ch = ((op & 03) << 1) | ((op >> 9) & 01);
1689 reason = ch_op_start (ch, ea, TRUE);
1690 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1691 break;
1692
1693 case 00544: case 00545: case 00546: case 00547: /* LCHx */
1694 case 01544: case 01545: case 01546: case 01547:
1695 if (prot_trap (0)) break; /* user mode? */
1696 ch = ((op & 03) << 1) | ((op >> 9) & 01);
1697 reason = ch_op_start (ch, ea, FALSE);
1698 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1699 break;
1700
1701 case 00640: case 00641: case 00642: case 00643: /* SCHx */
1702 case 01640: case 01641: case 01642: case 01643:
1703 if (prot_trap (0)) break; /* user mode? */
1704 ch = ((op & 03) << 1) | ((op >> 9) & 01);
1705 if ((reason = ch_op_store (ch, &SR)) == SCPE_OK)
1706 Write (ea, SR);
1707 break;
1708
1709 case 00644: case 00645: case 00646: case 00647: /* SCDx */
1710 case 01644: case 01645: case 01646: case 01647:
1711 ch = ((op & 03) << 1) | ((op >> 9) & 01);
1712 if ((reason = ch_op_store_diag (ch, &SR)) == SCPE_OK)
1713 Write (ea, SR);
1714 break;
1715
1716 case 00762: /* RDS */
1717 if (prot_trap (0) || sel_trap (PC)) break;
1718 ch = GET_U_CH (IR);
1719 reason = ch_op_ds (ch, CHSL_RDS, GET_U_UNIT (ea));
1720 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1721 break;
1722
1723 case 00764: /* BSR */
1724 if (prot_trap (0) || sel_trap (PC)) break;
1725 ch = GET_U_CH (IR);
1726 reason = ch_op_nds (ch, CHSL_BSR, GET_U_UNIT (ea));
1727 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1728 break;
1729
1730 case 00766: /* WRS */
1731 if (prot_trap (0) || sel_trap (PC)) break;
1732 ch = GET_U_CH (IR);
1733 reason = ch_op_ds (ch, CHSL_WRS, GET_U_UNIT (ea));
1734 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1735 break;
1736
1737 case 00770: /* WEF */
1738 if (prot_trap (0) || sel_trap (PC)) break;
1739 ch = GET_U_CH (IR);
1740 reason = ch_op_nds (ch, CHSL_WEF, GET_U_UNIT (ea));
1741 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1742 break;
1743
1744 case 00772: /* REW */
1745 if (prot_trap (0) || sel_trap (PC)) break;
1746 ch = GET_U_CH (IR);
1747 reason = ch_op_nds (ch, CHSL_REW, GET_U_UNIT (ea));
1748 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1749 break;
1750
1751 case 01764: /* BSF */
1752 if (prot_trap (0) || sel_trap (PC)) break;
1753 ch = GET_U_CH (IR);
1754 reason = ch_op_nds (ch, CHSL_BSF, GET_U_UNIT (ea));
1755 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1756 break;
1757
1758 case 01772: /* RUN */
1759 if (prot_trap (0) || sel_trap (PC)) break;
1760 ch = GET_U_CH (IR);
1761 reason = ch_op_nds (ch, CHSL_RUN, GET_U_UNIT (ea));
1762 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1763 break;
1764
1765 case 00776: /* SDN */
1766 if (prot_trap (0) || sel_trap (PC)) break;
1767 ch = GET_U_CH (IR);
1768 reason = ch_op_nds (ch, CHSL_SDN, GET_U_UNIT (ea));
1769 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1770 break;
1771
1772 default:
1773 if (stop_illop) reason = STOP_ILLEG;
1774 break;
1775 }
1776 } /* end else */
1777
1778 if (reason) { /* reason code? */
1779 if (reason == ERR_STALL) { /* stall? */
1780 PC = oldPC; /* back up PC */
1781 reason = 0;
1782 }
1783 else if (reason == STOP_HALT) { /* halt? wait for IO */
1784 t_stat r;
1785 for (i = 0; (i < HALT_IO_LIMIT) && !ch_qidle (); i++) {
1786 sim_interval = 0;
1787 if (r = sim_process_event ()) return r; /* process events */
1788 chtr_pend = chtr_eval (NULL); /* eval chan traps */
1789 while (ch_req) { /* until no ch req */
1790 for (j = 0; j < NUM_CHAN; j++) { /* loop thru channels */
1791 if (ch_req & REQ_CH (j)) { /* channel request? */
1792 if (r = ch_proc (j)) return r;
1793 }
1794 chtr_pend = chtr_eval (NULL);
1795 }
1796 } /* end while ch_req */
1797 } /* end for wait */
1798 if (chtr_pend) reason = 0; /* trap? cancel HALT */
1799 } /* end if HALT */
1800 } /* end if reason */
1801 } /* end while */
1802
1803 pcq_r->qptr = pcq_p; /* update pc q ptr */
1804 return reason;
1805 }
1806
1807 /* Get index register for indexing */
1808
1809 uint32 get_xri (uint32 tag)
1810 {
1811 tag = tag & INST_M_TAG;
1812
1813 if (tag) {
1814 if (mode_multi) {
1815 uint32 r = 0;
1816 if (tag & 1) r = r | XR[1];
1817 if (tag & 2) r = r | XR[2];
1818 if (tag & 4) r = r | XR[4];
1819 return r & eamask;
1820 }
1821 return XR[tag] & eamask;
1822 }
1823 return 0;
1824 }
1825
1826 /* Get index register for instruction execution
1827
1828 Instructions which are 'executing directly' on index registers rewrite
1829 the index register value. In multi-tag mode, this causes all registers
1830 involved in the OR function to receive the OR'd value. */
1831
1832 uint32 get_xrx (uint32 tag)
1833 {
1834 tag = tag & INST_M_TAG;
1835
1836 if (tag) {
1837 if (mode_multi) {
1838 uint32 r = 0;
1839 if (tag & 1) r = r | XR[1];
1840 if (tag & 2) r = r | XR[2];
1841 if (tag & 4) r = r | XR[4];
1842 put_xr (tag, r);
1843 return r & eamask;
1844 }
1845 return XR[tag] & eamask;
1846 }
1847 return 0;
1848 }
1849
1850 /* Store index register */
1851
1852 void put_xr (uint32 tag, uint32 dat)
1853 {
1854 tag = tag & INST_M_TAG;
1855 dat = dat & eamask;
1856
1857 if (tag) {
1858 if (mode_multi) {
1859 if (tag & 1) XR[1] = dat;
1860 if (tag & 2) XR[2] = dat;
1861 if (tag & 4) XR[4] = dat;
1862 }
1863 else XR[tag] = dat;
1864 }
1865 return;
1866 }
1867
1868 /* Floating point trap */
1869
1870 t_bool fp_trap (uint32 spill)
1871 {
1872 if (mode_ftrap) {
1873 WriteTAD (TRAP_STD_SAV, PC, spill);
1874 PCQ_ENTRY;
1875 PC = TRAP_FP_PC;
1876 return TRUE;
1877 }
1878 else {
1879 if (spill & TRAP_F_AC) ind_ovf = 1;
1880 if (spill & TRAP_F_MQ) ind_mqo = 1;
1881 }
1882 return FALSE;
1883 }
1884
1885 /* (CTSS) Protection trap */
1886
1887 t_bool prot_trap (uint32 decr)
1888 {
1889 if (mode_user) {
1890 WriteTAD (TRAP_PROT_SAV, PC, decr);
1891 PCQ_ENTRY;
1892 PC = TRAP_PROT_PC;
1893 return TRUE;
1894 }
1895 return FALSE;
1896 }
1897
1898 /* Store trap address and decrement, with A/B select flags; clear A/B, user mode */
1899
1900 void WriteTAD (uint32 pa, uint32 addr, uint32 decr)
1901 {
1902 t_uint64 mem;
1903
1904 if (inst_base) decr |= TRAP_F_BINST;
1905 if (data_base) decr |= TRAP_F_BDATA;
1906 mem = ReadP (pa) & ~(XMASK | AMASK);
1907 mem |= (((t_uint64) (decr & AMASK)) << INST_V_DEC) |
1908 ((t_uint64) (addr & AMASK));
1909 WriteP (pa, mem);
1910 mode_ctrap = 0;
1911 mode_strap = 0;
1912 mode_storn = 0;
1913 mode_user = 0;
1914 inst_base = 0;
1915 data_base = 0;
1916 return;
1917 }
1918
1919 /* Copy trap */
1920
1921 t_bool cpy_trap (uint32 va)
1922 {
1923 if (mode_ctrap) {
1924 WriteTA (TRAP_704_SAV, va);
1925 PCQ_ENTRY;
1926 TrapXfr (TRAP_CPY_PC);
1927 return TRUE;
1928 }
1929 return FALSE;
1930 }
1931
1932 /* Select trap */
1933
1934 t_bool sel_trap (uint32 va)
1935 {
1936 if (mode_strap) {
1937 WriteTA (TRAP_704_SAV, va);
1938 PCQ_ENTRY;
1939 TrapXfr (TRAP_SEL_PC);
1940 return TRUE;
1941 }
1942 return FALSE;
1943 }
1944
1945 /* Store trap address - do not alter state yet (might be TRA) */
1946
1947 void WriteTA (uint32 pa, uint32 dat)
1948 {
1949 t_uint64 mem;
1950
1951 mem = ReadP (pa) & ~AMASK;
1952 mem |= (dat & AMASK);
1953 WriteP (pa, mem);
1954 return;
1955 }
1956
1957 /* Set trap PC - second half of address-only trap */
1958
1959 void TrapXfr (uint32 newpc)
1960 {
1961 PC = newpc;
1962 mode_ctrap = 0;
1963 mode_strap = 0;
1964 mode_storn = 0;
1965 mode_user = 0;
1966 inst_base = 0;
1967 data_base = 0;
1968 return;
1969 }
1970
1971 /* Read instruction and indirect */
1972
1973 t_bool ReadI (uint32 va, t_uint64 *val)
1974 {
1975 if (mode_user) {
1976 va = (va + ind_reloc) & AMASK;
1977 if ((va < ind_start) || (va > ind_limit)) {
1978 prot_trap (0);
1979 return FALSE;
1980 }
1981 }
1982 *val = M[va | inst_base];
1983 return TRUE;
1984 }
1985
1986 /* Read */
1987
1988 t_bool Read (uint32 va, t_uint64 *val)
1989 {
1990 if (mode_user) {
1991 va = (va + ind_reloc) & AMASK;
1992 if ((va < ind_start) || (va > ind_limit)) {
1993 prot_trap (0);
1994 return FALSE;
1995 }
1996 }
1997 *val = M[va | data_base];
1998 return TRUE;
1999 }
2000
2001 /* Write */
2002
2003 t_bool Write (uint32 va, t_uint64 dat)
2004 {
2005 if (mode_user) {
2006 va = (va + ind_reloc) & AMASK;
2007 if ((va < ind_start) || (va > ind_limit)) {
2008 prot_trap (0);
2009 return FALSE;
2010 }
2011 }
2012 M[va | data_base] = dat;
2013 return TRUE;
2014 }
2015
2016 /* Reset routine */
2017
2018 t_stat cpu_reset (DEVICE *dptr)
2019 {
2020 ind_ovf = 0;
2021 ind_mqo = 0;
2022 ind_dvc = 0;
2023 ind_ioc = 0;
2024 ind_reloc = 0;
2025 ind_start = 0;
2026 ind_limit = 0;
2027 mode_ttrap = 0;
2028 mode_ctrap = 0;
2029 mode_strap = 0;
2030 mode_ftrap = 1;
2031 mode_storn = 0;
2032 if (cpu_model & (I_94|I_CT)) mode_multi = 0;
2033 else mode_multi = 1;
2034 mode_user = 0;
2035 inst_base = 0;
2036 data_base = 0;
2037 ch_req = 0;
2038 chtr_pend = chtr_enab = 0;
2039 chtr_inht = chtr_inhi = 0;
2040 ht_pend = 0;
2041 SLT = 0;
2042 XR[0] = 0;
2043 if (M == NULL) M = (t_uint64 *) calloc (MAXMEMSIZE, sizeof (t_uint64));
2044 if (M == NULL) return SCPE_MEM;
2045 pcq_r = find_reg ("PCQ", NULL, dptr);
2046 if (pcq_r) pcq_r->qptr = 0;
2047 else return SCPE_IERR;
2048 sim_brk_types = sim_brk_dflt = SWMASK ('E');
2049 return SCPE_OK;
2050 }
2051
2052 /* Memory examine */
2053
2054 t_stat cpu_ex (t_value *vptr, t_addr ea, UNIT *uptr, int32 sw)
2055 {
2056 if (vptr == NULL) return SCPE_ARG;
2057 if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) return SCPE_NXM;
2058 if ((sw & SWMASK ('B')) ||
2059 ((sw & SWMASK ('V')) && mode_user && inst_base)) ea = ea | BCORE_BASE;
2060 *vptr = M[ea] & DMASK;
2061 return SCPE_OK;
2062 }
2063
2064 /* Memory deposit */
2065
2066 t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw)
2067 {
2068 if ((sw & (SWMASK ('A') | SWMASK ('B')))? (ea > AMASK): (ea >= MEMSIZE)) return SCPE_NXM;
2069 if (sw & SWMASK ('B')) ea = ea | BCORE_BASE;
2070 M[ea] = val & DMASK;
2071 return SCPE_OK;
2072 }
2073
2074 /* Set model */
2075
2076 t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc)
2077 {
2078 UNIT *chuptr = mt_dev[CHRONO_CH].units + CHRONO_UNIT;
2079 extern DEVICE clk_dev;
2080
2081 cpu_model = val;
2082 if (val & I_CT) {
2083 uptr->capac = MAXMEMSIZE;
2084 detach_unit (uptr);
2085 chuptr->flags &= ~UNIT_ATTABLE;
2086 clk_dev.flags &= ~DEV_DIS;
2087 }
2088 else {
2089 uptr->capac = STDMEMSIZE;
2090 chuptr->flags |= UNIT_ATTABLE;
2091 }
2092 if (!(cpu_model & I_94)) mode_multi = 1;
2093 return SCPE_OK;
2094 }
2095
2096 /* Show CTSS */
2097
2098 t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc)
2099 {
2100 if (cpu_model & I_CT) fputs ("CTSS", st);
2101 else if (cpu_model & I_94) fputs ("7094", st);
2102 else fputs ("7090", st);
2103 return SCPE_OK;
2104 }
2105
2106 /* Insert history entry */
2107
2108 static uint32 inst_io_tab[32] = {
2109 0, 0, 0, 0, 0, 0, 0, 0, /* 0000 - 0377 */
2110 0, 0, 0, 0x000000FF, 0, 0, 0, 0x45540000, /* 0400 - 0777 */
2111 0, 0, 0, 0, 0, 0, 0, 0, /* 1000 - 1400 */
2112 0, 0, 0, 0x000000FF, 0, 0, 0, 0 /* 1400 - 1777 */
2113 };
2114
2115 void cpu_ent_hist (uint32 pc, uint32 ea, t_uint64 ir, t_uint64 opnd)
2116 {
2117 int32 prv_p;
2118
2119 if (pc & HIST_PC) {
2120 if ((pc == hst[hst_p].pc) && (ir == hst[hst_p].ir)) { /* repeat last? */
2121 hst[hst_p].rpt++;
2122 return;
2123 }
2124 prv_p = hst_p? hst_p - 1: hst_lnt - 1;
2125 if ((pc == hst[prv_p].pc) && (ir == hst[prv_p].ir)) { /* 2 line loop? */
2126 hst[prv_p].rpt++;
2127 return;
2128 }
2129 if (hst_ch & HIST_CH_I) { /* IO only? */
2130 uint32 op = GET_OPC (ir); /* get opcode */
2131 if ((ir & INST_T_DEC) ||
2132 !(inst_io_tab[op / 32] & (1u << (op & 037)))) return;
2133 }
2134 }
2135 hst_p = (hst_p + 1); /* next entry */
2136 if (hst_p >= hst_lnt) hst_p = 0;
2137 hst[hst_p].pc = pc;
2138 hst[hst_p].ir = ir;
2139 hst[hst_p].ac = AC;
2140 hst[hst_p].mq = MQ;
2141 hst[hst_p].si = SI;
2142 hst[hst_p].ea = ea;
2143 hst[hst_p].opnd = opnd;
2144 hst[hst_p].rpt = 0;
2145 return;
2146 }
2147
2148 /* Set history */
2149
2150 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
2151 {
2152 int32 i, lnt;
2153 t_stat r;
2154
2155 if (cptr == NULL) {
2156 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
2157 hst_p = 0;
2158 return SCPE_OK;
2159 }
2160 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
2161 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
2162 hst_p = 0;
2163 if (hst_lnt) {
2164 free (hst);
2165 hst_lnt = hst_ch = 0;
2166 hst = NULL;
2167 }
2168 if (lnt) {
2169 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
2170 if (hst == NULL) return SCPE_MEM;
2171 hst_lnt = lnt;
2172 if (sim_switches & SWMASK ('I')) hst_ch = HIST_CH_I|HIST_CH_C;
2173 else if (sim_switches & SWMASK ('C')) hst_ch = HIST_CH_C;
2174 else hst_ch = 0;
2175 }
2176 return SCPE_OK;
2177 }
2178
2179 /* Print one instruction */
2180
2181 t_stat cpu_fprint_one_inst (FILE *st, uint32 pc, uint32 rpt, uint32 ea,
2182 t_uint64 ir, t_uint64 ac, t_uint64 mq, t_uint64 si, t_uint64 opnd)
2183 {
2184 int32 ch;
2185 t_value sim_eval;
2186 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
2187 UNIT *uptr, int32 sw);
2188
2189 sim_eval = ir;
2190 if (pc & HIST_PC) { /* instruction? */
2191 fputs ("CPU ", st);
2192 fprintf (st, "%05o ", pc & AMASK);
2193 if (rpt == 0) fprintf (st, " ");
2194 else if (rpt < 1000000) fprintf (st, "%6d ", rpt);
2195 else fprintf (st, "%5dM ", rpt / 1000000);
2196 fprint_val (st, ac, 8, 38, PV_RZRO);
2197 fputc (' ', st);
2198 fprint_val (st, mq, 8, 36, PV_RZRO);
2199 fputc (' ', st);
2200 fprint_val (st, si, 8, 36, PV_RZRO);
2201 fputc (' ', st);
2202 if (ir & INST_T_DEC) fprintf (st, " ");
2203 else fprintf (st, "%05o ", ea);
2204 if (fprint_sym (st, pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M')) > 0) {
2205 fputs ("(undefined) ", st);
2206 fprint_val (st, ir, 8, 36, PV_RZRO);
2207 }
2208 else if (!(ir & INST_T_DEC) && (op_flags[GET_OPC (ir)] & I_R)) {
2209 fputs (" [", st);
2210 fprint_val (st, opnd, 8, 36, PV_RZRO);
2211 fputc (']', st);
2212 }
2213 fputc ('\n', st); /* end line */
2214 } /* end if instruction */
2215 else if (ch = HIST_CH (pc)) { /* channel? */
2216 fprintf (st, "CH%c ", 'A' + ch - 1);
2217 fprintf (st, "%05o ", pc & AMASK);
2218 fputs (" ", st);
2219 fprintf (st, "%05o ", ea & AMASK);
2220 if (fprint_sym (st, pc & AMASK, &sim_eval, &cpu_unit,
2221 (ch_dev[ch - 1].flags & DEV_7909)? SWMASK ('N'): SWMASK ('I')) > 0) {
2222 fputs ("(undefined) ", st);
2223 fprint_val (st, ir, 8, 36, PV_RZRO);
2224 }
2225 fputc ('\n', st); /* end line */
2226 } /* end else channel */
2227 return SCPE_OK;
2228 }
2229
2230 /* Show history */
2231
2232 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
2233 {
2234 int32 k, di, lnt;
2235 char *cptr = (char *) desc;
2236 t_stat r;
2237 InstHistory *h;
2238
2239 if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
2240 if (cptr) {
2241 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
2242 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;
2243 }
2244 else lnt = hst_lnt;
2245 di = hst_p - lnt; /* work forward */
2246 if (di < 0) di = di + hst_lnt;
2247 fprintf (st, " PC repeat AC MQ SI EA IR\n\n");
2248 for (k = 0; k < lnt; k++) { /* print specified */
2249 h = &hst[(++di) % hst_lnt]; /* entry pointer */
2250 cpu_fprint_one_inst (st, h->pc, h->rpt, h->ea, h->ir, h->ac, h->mq, h->si, h->opnd);
2251 } /* end for */
2252 return SCPE_OK;
2253 }