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