1 /* i7094_cpu.c: IBM 7094 CPU simulator
3 Copyright (c) 2003-2007, Robert M. Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 cpu 7094 central processor
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
33 The register state for the 7094 is:
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
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)
54 CTSS required a set of special features: memory extension (to 65K),
55 protection, and relocation. Additional state:
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
64 The 7094 had five instruction formats: memory reference,
65 memory reference with count, convert, decrement, and immediate.
67 00000000011 11 1111 112 222222222333333
68 S12345678901 23 4567 890 123456789012345
69 +------------+--+----+---+---------------+
70 | opcode |ND|0000|tag| address | memory reference
71 +------------+--+----+---+---------------+
73 00000000011 111111 112 222222222333333
74 S12345678901 234567 890 123456789012345
75 +------------+------+---+---------------+
76 | opcode | count|tag| address | memory reference
77 +------------+------+---+---------------+ with count
79 000000000 11111111 11 2 222222222333333
80 S123456789 01234567 89 0 123456789012345
81 +----------+--------+--+-+---------------+
82 | opcode | count |00|X| address | convert
83 +----------+--------+--+-+---------------+
85 00 000000011111111 112 222222222333333
86 S12 345678901234567 890 123456789012345
87 +---+---------------+---+---------------+
88 |opc| decrement |tag| address | decrement
89 +---+---------------+---+---------------+
91 00000000011 111111 112222222222333333
92 S12345678901 234567 890123456789012345
93 +------------+------+------------------+
94 | opcode |000000| immediate | immediate
95 +------------+------+------------------+
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.
104 1. Reasons to stop. The simulator can be stopped by:
108 illegal I/O operation for device
109 illegal I/O operation for channel
110 breakpoint encountered
111 nested XEC's exceeding limit
113 I/O error in I/O simulator
115 2. Data channel traps. The 7094 is a channel-based system.
116 Channels can generate traps for errors and status conditions.
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)
125 Channel traps are summarized in variable chtr_pend.
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.
131 4. Adding I/O devices. These modules must be modified:
133 i7094_defs.h add device definitions
134 i7094_io.c add device address mapping
135 i7094_sys.c add sim_devices table entry
138 #include "i7094_defs.h"
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)
145 #define HIST_MAX (2 << 18)
146 #define HIST_CH_C 1 /* include channel */
147 #define HIST_CH_I 2 /* include IO */
149 #define HALT_IO_LIMIT ((2 << 18) + 1) /* max wait to stop */
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 */
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 */
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 */
208 /* Forward and external declarations */
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
);
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
);
258 /* CPU data structures
260 cpu_dev CPU device descriptor
262 cpu_reg CPU register list
263 cpu_mod CPU modifier list
266 UNIT cpu_unit
= { UDATA (NULL
, UNIT_FIX
+UNIT_BINK
, STDMEMSIZE
) };
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
},
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
},
337 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
338 1, 8, PASIZE
, 1, 8, 36,
339 &cpu_ex
, &cpu_dep
, &cpu_reset
,
344 /* Instruction decode table */
346 const uint8 op_flags
[1024] = {
347 I_XN
, 0 , 0 , 0 , /* +000 */
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
,
355 I_XN
|I_9X
, I_9X
, I_XN
|I_9X
, I_9X
, /* +040 */
356 I_9X
, 0 , I_XN
|I_9X
, 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
,
363 I_XN
, I_XN
|I_CT
, 0 , 0 , /* +100 */
366 I_9X
, I_9X
, I_9X
, I_9X
,
367 I_XN
, 0 , 0 , 0 , /* +120 */
371 I_XN
, 0 , 0 , 0 , /* +140 */
375 0 , I_XN
|I_9X
, I_XN
|I_9X
, 0 , /* +160 */
379 I_XNR
, 0 , 0 , 0 , /* +200 */
380 I_XNR
, I_XNR
, 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
,
387 I_XNR
|I_9X
, I_XNR
, 0 , 0 , /* +240 */
391 I_XNR
, I_XND
|I_94
, 0 , 0 , /* +260 */
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
,
399 I_XNR
|I_9X
, 0 , I_XNR
|I_9X
, 0 , /* +320 */
403 I_XNR
, 0 , 0 , 0 , /* +340 */
407 0 , I_XNR
, 0 , 0 , /* +360 */
411 I_XNR
, I_XNR
|I_9X
, I_XNR
, 0 , /* +400 */
415 0 , 0 , 0 , 0 , /* +420 */
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 ,
423 I_9X
, 0 , 0 , 0 , /* +460 */
427 I_XNR
|I_9X
, 0 , I_XNR
, 0 , /* +500 */
431 I_XNR
, 0 , I_XNR
, 0 , /* +520 */
435 I_XN
, I_XN
, I_XN
, I_XN
, /* +540 */
436 I_XN
, I_XN
, I_XN
, I_XN
,
439 I_XNR
, 0 , I_XNR
|I_CT
, 0 , /* +560 */
443 I_XN
, I_XN
, I_XN
, 0 , /* +600 */
444 I_XN
|I_9X
, 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
,
455 0 , 0 , 0 , 0 , /* +660 */
459 I_9X
, 0 , 0 , 0 , /* +700 */
463 0 , 0 , 0 , 0 , /* +720 */
467 0 , 0 , 0 , 0 , /* +740 */
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 ,
476 I_XN
, 0 , 0 , 0 , /* -000 */
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
,
484 0 , 0 , 0 , 0 , /* -040 */
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
,
492 I_XN
, I_XN
|I_CT
, 0 , 0 , /* -100 */
495 I_9X
, I_9X
, I_9X
, I_9X
,
496 I_XN
, 0 , 0 , 0 , /* -120 */
500 I_XN
|I_9X
, 0 , 0 , 0 , /* -140 */
503 I_9X
, I_9X
, I_9X
, I_9X
,
504 0 , 0 , 0 , 0 , /* -160 */
508 I_XNR
|I_9X
, 0 , 0 , 0 , /* -200 */
512 0 , 0 , 0 , 0 , /* -220 */
516 I_XND
|I_94
, I_XND
|I_94
, 0 , 0 , /* -240 */
520 I_XNR
, I_XND
|I_94
, 0 , 0 , /* -260 */
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
,
528 I_XNR
, 0 , 0 , 0 , /* -320 */
532 I_XNR
, 0 , 0 , 0 , /* -340 */
536 0 , 0 , 0 , 0 , /* -360 */
540 I_XNR
|I_9X
, 0 , 0 , 0 , /* -400 */
544 0 , 0 , 0 , 0 , /* -420 */
548 0 , 0 , 0 , 0 , /* -440 */
552 0 , 0 , 0 , 0 , /* -460 */
556 I_XNR
, I_XNR
, 0 , 0 , /* -500 */
560 I_XNR
|I_9X
, 0 , 0 , 0 , /* -520 */
564 I_XN
, I_XN
, I_XN
, I_XN
, /* -540 */
565 I_XN
, I_XN
, I_XNR
, I_XN
,
568 0 , 0 , 0 , 0 , /* -560 */
569 I_XNR
|I_CT
, 0 , 0 , 0 ,
572 I_XN
, 0 , I_XNR
|I_9X
, I_XN
|I_94
, /* -600 */
576 I_XNR
|I_9X
, 0 , 0 , 0 , /* -620 */
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
,
584 0 , 0 , 0 , 0 , /* -660 */
588 I_9X
, 0 , 0 , 0 , /* -700 */
592 0 , 0 , 0 , 0 , /* -720 */
596 0 , 0 , 0 , 0 , /* -740 */
600 I_X
, I_X
|I_CT
, 0 , I_X
, /* -760 */
606 /* Instruction execution routine */
608 t_stat
sim_instr (void)
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
;
617 /* Restore register state */
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
));
630 if (ht_pend
) { /* HTR pending? */
631 oldPC
= (PC
- 1) & AMASK
;
632 ht_pend
= 0; /* clear flag */
634 if (mode_ttrap
) { /* trap? */
635 WriteTA (TRAP_STD_SAV
, oldPC
); /* save PC */
636 TrapXfr (TRAP_TRA_PC
); /* trap */
638 else PC
= ht_addr
; /* branch */
641 /* Main instruction fetch/decode loop */
643 while (reason
== SCPE_OK
) { /* loop until error */
645 if (cpu_astop
) { /* debug stop? */
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 */
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;
660 chtr_pend
= chtr_eval (NULL
);
661 if (reason
) break; /* error? */
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 */
674 if (sim_brk_summ
&& sim_brk_test (PC
, SWMASK ('E'))) { /* breakpoint? */
675 reason
= STOP_IBKPT
; /* stop simulation */
678 if (chtr_inhi
) { /* 1 cycle inhibit? */
679 chtr_inhi
= 0; /* clear */
680 chtr_pend
= chtr_eval (NULL
); /* re-evaluate */
682 oldPC
= PC
; /* save current PC */
683 PC
= (PC
+ 1) & eamask
; /* increment PC */
684 if (!ReadI (oldPC
, &IR
)) continue; /* get inst; trap? */
687 sim_interval
= sim_interval
- 1;
688 xec_cnt
= 0; /* clear XEC cntr */
692 tag
= GET_TAG (IR
); /* get tag */
693 addr
= (uint32
) IR
& eamask
; /* get base addr */
695 /* Decrement format instructions */
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
,
711 put_xr (tag
, xr
+ dec
); /* xr += decr */
713 if (mode_ttrap
) { /* trap? */
714 WriteTA (TRAP_STD_SAV
, oldPC
); /* save PC */
715 TrapXfr (TRAP_TRA_PC
); /* trap */
717 else PC
= addr
; /* branch */
721 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
722 if (xr
> dec
) { /* if xr > decr */
723 put_xr (tag
, xr
- dec
); /* xr -= decr */
725 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
726 else PC
= addr
; /* branch */
731 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
732 if (xr
> dec
) { /* if xr > decr */
734 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
735 else PC
= addr
; /* branch */
740 WriteTA (TRAP_STD_SAV
, PC
); /* save inst+1 */
742 PC
= TRAP_STR_PC
; /* branch to 2 */
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 */
750 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
751 else PC
= addr
; /* branch */
756 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
757 if (xr
<= dec
) { /* if xr <= decr */
759 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
760 else PC
= addr
; /* branch */
766 /* Normal format instructions */
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 */
775 if (tag
&& (fl
& I_X
)) /* tag and indexable? */
776 ea
= (addr
- get_xri (tag
)) & eamask
; /* do indexing */
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 */
783 ea
= (addr
- get_xri (tagi
)) & eamask
; /* do indexing */
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 */
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
,
799 switch (op
) { /* case on opcode */
801 /* Positive instructions */
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 */
811 case 00020: /* TRA */
812 case 01020: /* also -TRA */
814 if (mode_ttrap
) { /* trap? */
815 WriteTA (TRAP_STD_SAV
, oldPC
); /* save PC */
816 TrapXfr (TRAP_TRA_PC
); /* trap */
818 else PC
= ea
; /* branch */
821 case 00021: /* TTR */
823 PC
= ea
; /* branch, no trap */
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 */
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 */
835 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
836 else PC
= ea
; /* branch */
840 case 00041: /* IIA */
841 SI
= SI
^ (AC
& DMASK
);
844 case 00042: /* TIO */
845 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
846 if ((SI
& AC
) == (AC
& DMASK
)) { /* if ind on */
848 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
849 else PC
= ea
; /* branch */
853 case 00043: /* OAI */
854 SI
= SI
| (AC
& DMASK
);
857 case 00044: /* PAI */
861 case 00046: /* TIF */
862 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
863 if ((SI
& AC
) == 0) { /* if ind off */
865 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
866 else PC
= ea
; /* branch */
870 case 00051: /* IIR */
871 SI
= SI
^ (IR
& RMASK
);
874 case 00054: /* RFT */
876 if ((SI
& t
) == 0) PC
= (PC
+ 1) & eamask
; /* if ind off, skip */
879 case 00055: /* SIR */
880 SI
= SI
| (IR
& RMASK
);
883 case 00056: /* RNT */
885 if ((SI
& t
) == t
) PC
= (PC
+ 1) & eamask
; /* if ind on, skip */
888 case 00057: /* RIR */
889 SI
= SI
& ~(IR
& RMASK
);
892 case 00074: /* TSX */
893 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
894 if (tag
) put_xr (tag
, ~oldPC
+ 1); /* save -inst loc */
896 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
897 else PC
= ea
; /* branch */
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 */
904 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
905 else PC
= ea
; /* branch */
909 case 00101: /* (CTSS) TIA */
910 if (prot_trap (0)) break; /* not user mode? */
916 case 00114: case 00115: case 00116: case 00117: /* CVR */
920 ea
= (uint32
) ((AC
& 077) + SR
) & eamask
;
921 if (!Read (ea
, &SR
)) break;
922 AC
= (AC
& AC_S
) | ((AC
>> 6) & 0017777777777) |
923 (SR
& 0770000000000);
926 if ((sc
== 0) && (IR
& INST_T_CXR1
))
927 put_xr (1, (uint32
) SR
);
930 case 00120: /* TPL */
931 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
932 if ((AC
& AC_S
) == 0) { /* if AC + */
934 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
935 else PC
= ea
; /* branch */
939 case 00131: /* XCA */
941 MQ
= (AC
& MMASK
) | ((AC
& AC_S
)? SIGN
: 0);
942 AC
= (t
& MMASK
) | ((t
& SIGN
)? AC_S
: 0);
945 case 00140: /* TOV */
946 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
947 if (ind_ovf
) { /* if overflow */
949 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
950 else PC
= ea
; /* branch */
951 ind_ovf
= 0; /* clear overflow */
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 */
960 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
961 else PC
= ea
; /* branch */
962 ind_mqo
= 0; /* clear overflow */
967 case 00162: /* TQP */
968 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
969 if ((MQ
& SIGN
) == 0) { /* if MQ + */
971 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
972 else PC
= ea
; /* branch */
976 case 00200: /* MPY */
980 case 00204: /* VLM */
981 case 00205: /* for diagnostic */
986 case 00220: /* DVH */
987 if (op_div (SR
, 043)) {
989 if (!prot_trap (0)) reason
= STOP_DIVCHK
;
993 case 00221: /* DVP */
994 if (op_div (SR
, 043)) ind_dvc
= 1;
997 case 00224: /* VDH */
998 case 00226: /* for diagnostic */
1000 if (op_div (SR
, sc
)) {
1002 if (!prot_trap (0)) reason
= STOP_DIVCHK
;
1006 case 00225: /* VDP */
1007 case 00227: /* for diagnostic */
1009 if (op_div (SR
, sc
)) ind_dvc
= 1;
1012 case 00240: /* FDH */
1013 spill
= op_fdv (SR
);
1014 if (spill
== TRAP_F_DVC
) {
1016 if (!prot_trap (0)) reason
= STOP_DIVCHK
;
1018 else if (spill
) fp_trap (spill
);
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
);
1027 case 00260: /* FMP */
1028 spill
= op_fmp (SR
, 1); /* MQ * SR */
1029 if (spill
) fp_trap (spill
);
1032 case 00261: /* DFMP */
1033 spill
= op_dfmp (SR
, sr1
, 1);
1034 if (spill
) fp_trap (spill
);
1037 case 00300: /* FAD */
1038 spill
= op_fad (SR
, 1);
1039 if (spill
) fp_trap (spill
);
1042 case 00301: /* DFAD */
1043 spill
= op_dfad (SR
, sr1
, 1);
1044 if (spill
) fp_trap (spill
);
1047 case 00302: /* FSB */
1048 spill
= op_fad (SR
^ SIGN
, 1);
1049 if (spill
) fp_trap (spill
);
1052 case 00303: /* DFSB */
1053 spill
= op_dfad (SR
^ SIGN
, sr1
, 1);
1054 if (spill
) fp_trap (spill
);
1057 case 00304: /* FAM */
1058 spill
= op_fad (SR
& ~SIGN
, 1);
1059 if (spill
) fp_trap (spill
);
1062 case 00305: /* DFAM */
1063 spill
= op_dfad (SR
& ~SIGN
, sr1
, 1);
1064 if (spill
) fp_trap (spill
);
1067 case 00306: /* FSM */
1068 spill
= op_fad (SR
| SIGN
, 1);
1069 if (spill
) fp_trap (spill
);
1072 case 00307: /* DFSM */
1073 spill
= op_dfad (SR
| SIGN
, sr1
, 1);
1074 if (spill
) fp_trap (spill
);
1077 case 00320: /* ANS */
1082 case 00322: /* ERA */
1083 AC
= (AC
^ SR
) & DMASK
; /* AC S,Q cleared */
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 */
1091 if (s1
^ s2
) { /* diff signs? */
1092 if (s1
) PC
= (PC
+ 2) & eamask
; /* AC < mem? skip 2 */
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 -? */
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 */
1105 case 00400: /* ADD */
1109 case 00401: /* ADM */
1110 op_add (SR
& MMASK
);
1113 case 00402: /* SUB */
1117 case 00420: /* HPR */
1118 if (prot_trap (0)) break; /* user mode? */
1119 reason
= STOP_HALT
; /* halt if I/O done */
1122 case 00440: /* IIS */
1126 case 00441: /* LDI */
1130 case 00442: /* OSI */
1134 case 00443: /* DLD */
1135 AC
= (SR
& MMASK
) | ((SR
& SIGN
)? AC_S
: 0); /* normal load */
1136 if (!Read (ea
| 1, &SR
)) break; /* second load */
1138 if (ea
& 1) fp_trap (TRAP_F_ODD
); /* trap after exec */
1141 case 00444: /* OFT */
1142 if ((SI
& SR
) == 0) PC
= (PC
+ 1) & eamask
; /* skip if ind off */
1145 case 00445: /* RIS */
1149 case 00446: /* ONT */
1150 if ((SI
& SR
) == SR
) PC
= (PC
+ 1) & eamask
;/* skip if ind on */
1153 case 00460: /* LDA (704) */
1157 case 00500: /* CLA */
1158 AC
= (SR
& MMASK
) | ((SR
& SIGN
)? AC_S
: 0);
1161 case 00502: /* CLS */
1162 AC
= (SR
& MMASK
) | ((SR
& SIGN
)? 0: AC_S
);
1165 case 00520: /* ZET */
1166 if ((SR
& MMASK
) == 0) PC
= (PC
+ 1) & eamask
; /* skip if M 1-35 = 0 */
1169 case 00522: /* XEC */
1170 if (xec_cnt
++ >= xec_max
) { /* xec chain limit? */
1171 reason
= STOP_XEC
; /* stop */
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 */
1179 case 00534: /* LXA */
1180 if (tag
) put_xr (tag
, (uint32
) SR
); /* M addr -> xr */
1183 case 00535: /* LAC */
1184 if (tag
) put_xr (tag
, NEG ((uint32
) SR
)); /* -M addr -> xr */
1187 case 00560: /* LDQ */
1191 case 00562: /* (CTSS) LRI */
1192 if (prot_trap (0)) break; /* user mode? */
1193 ind_reloc
= ((uint32
) SR
) & VA_BLK
;
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 */
1204 case 00600: /* STZ */
1208 case 00601: /* STO */
1209 SR
= (AC
& MMASK
) | ((AC
& AC_S
)? SIGN
: 0);
1213 case 00602: /* SLW */
1214 Write (ea
, AC
& DMASK
);
1217 case 00604: /* STI */
1221 case 00621: /* STA */
1222 SR
= (SR
& ~AMASK
) | (AC
& AMASK
);
1226 case 00622: /* STD */
1227 SR
= (SR
& ~XMASK
) | (AC
& XMASK
);
1231 case 00625: /* STT */
1232 SR
= (SR
& ~TMASK
) | (AC
& TMASK
);
1236 case 00630: /* STP */
1237 SR
= (SR
& ~PMASK
) | (AC
& PMASK
);
1241 case 00634: /* SXA */
1242 SR
= (SR
& ~AMASK
) | /* xr -> M addr */
1243 ((t_uint64
) get_xrx (tag
));
1247 case 00636: /* SCA */
1248 SR
= (SR
& ~AMASK
) | /* -xr -> M addr */
1249 ((t_uint64
) (NEG (get_xrx (tag
)) & AMASK
));
1253 case 00700: /* CPY (704) */
1257 case 00734: /* PAX */
1258 if (tag
) put_xr (tag
, (uint32
) AC
); /* AC addr -> xr */
1261 case 00737: /* PAC */
1262 if (tag
) put_xr (tag
, NEG ((uint32
) AC
)); /* -AC addr -> xr */
1265 case 00754: /* PXA */
1266 AC
= get_xrx (tag
); /* xr -> AC */
1269 case 00756: /* PCA */
1270 AC
= NEG (get_xrx (tag
)) & AMASK
; /* -xr -> AC */
1273 case 00760: /* PSE */
1274 if (prot_trap (0)) break; /* user mode? */
1275 reason
= op_pse (ea
);
1278 case 00761: /* NOP */
1281 case 00763: /* LLS */
1285 case 00765: /* LRS */
1289 case 00767: /* ALS */
1293 case 00771: /* ARS */
1297 case 00774: /* AXT */
1298 if (tag
) put_xr (tag
, addr
); /* IR addr -> xr */
1301 /* Negative instructions */
1303 case 01021: /* ESNT */
1304 mode_storn
= 1; /* enter nullification */
1306 PC
= ea
; /* branch, no trap */
1309 case 01042: /* RIA */
1313 case 01046: /* PIA */
1317 case 01051: /* IIL */
1318 SI
= SI
^ ((IR
& RMASK
) << 18);
1321 case 01054: /* LFT */
1322 t
= (IR
& RMASK
) << 18;
1323 if ((SI
& t
) == 0) PC
= (PC
+ 1) & eamask
; /* if ind off, skip */
1326 case 01055: /* SIL */
1327 SI
= SI
| ((IR
& RMASK
) << 18);
1330 case 01056: /* LNT */
1331 t
= (IR
& RMASK
) << 18;
1332 if ((SI
& t
) == t
) PC
= (PC
+ 1) & eamask
; /* if ind on, skip */
1335 case 01057: /* RIL */
1336 SI
= SI
& ~((IR
& RMASK
) << 18);
1339 case 01100: /* TNZ */
1340 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
1341 if ((AC
& AC_MMASK
) != 0) { /* if AC != 0 */
1343 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
1344 else PC
= ea
; /* branch */
1348 case 01101: /* (CTSS) TIB */
1349 if (prot_trap (0)) break; /* not user mode? */
1353 inst_base
= BCORE_BASE
;
1356 case 01114: case 01115: case 01116: case 01117: /* CAQ */
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
);
1366 if ((sc
== 0) && (IR
& INST_T_CXR1
))
1367 put_xr (1, (uint32
) SR
);
1370 case 01120: /* TMI */
1371 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
1372 if ((AC
& AC_S
) != 0) { /* if AC - */
1374 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
1375 else PC
= ea
; /* branch */
1379 case 01130: /* XCL */
1385 case 01140: /* TNO */
1386 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
1387 if (!ind_ovf
) { /* if no overflow */
1389 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
1390 else PC
= ea
; /* branch */
1392 ind_ovf
= 0; /* clear overflow */
1395 case 01154: case 01155: case 01156: case 01157: /* CRQ */
1399 ea
= (uint32
) ((MQ
>> 30) + SR
) & eamask
;
1400 if (!Read (ea
, &SR
)) break;
1401 MQ
= ((MQ
<< 6) & DMASK
) | (SR
>> 30);
1404 if ((sc
== 0) && (IR
& INST_T_CXR1
))
1405 put_xr (1, (uint32
) SR
);
1408 case 01200: /* MPR */
1409 op_mpy (0, SR
, 043);
1410 if (MQ
& B1
) AC
= (AC
& AC_S
) | ((AC
+ 1) & AC_MMASK
);
1413 case 01240: /* DFDH */
1414 spill
= op_dfdv (SR
, sr1
);
1415 if (spill
== TRAP_F_DVC
) {
1417 if (!prot_trap (0)) reason
= STOP_DIVCHK
;
1419 else if (spill
) fp_trap (spill
);
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
);
1428 case 01260: /* UFM */
1429 spill
= op_fmp (SR
, 0);
1430 if (spill
) fp_trap (spill
);
1433 case 01261: /* DUFM */
1434 spill
= op_dfmp (SR
, sr1
, 0);
1435 if (spill
) fp_trap (spill
);
1438 case 01300: /* UFA */
1439 spill
= op_fad (SR
, 0);
1440 if (spill
) fp_trap (spill
);
1443 case 01301: /* DUFA */
1444 spill
= op_dfad (SR
, sr1
, 0);
1445 if (spill
) fp_trap (spill
);
1448 case 01302: /* UFS */
1449 spill
= op_fad (SR
^ SIGN
, 0);
1450 if (spill
) fp_trap (spill
);
1453 case 01303: /* DUFS */
1454 spill
= op_dfad (SR
^ SIGN
, sr1
, 0);
1455 if (spill
) fp_trap (spill
);
1458 case 01304: /* UAM */
1459 spill
= op_fad (SR
& ~SIGN
, 0);
1460 if (spill
) fp_trap (spill
);
1463 case 01305: /* DUAM */
1464 spill
= op_dfad (SR
& ~SIGN
, sr1
, 0);
1465 if (spill
) fp_trap (spill
);
1468 case 01306: /* USM */
1469 spill
= op_fad (SR
| SIGN
, 0);
1470 if (spill
) fp_trap (spill
);
1473 case 01307: /* DUSM */
1474 spill
= op_dfad (SR
| SIGN
, sr1
, 0);
1475 if (spill
) fp_trap (spill
);
1478 case 01320: /* ANA */
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
;
1488 case 01400: /* SBM */
1492 case 01500: /* CAL */
1496 case 01501: /* ORA */
1500 case 01520: /* NZT */
1501 if ((SR
& MMASK
) != 0) PC
= (PC
+ 1) & eamask
; ;
1504 case 01534: /* LXD */
1505 if (tag
) put_xr (tag
, GET_DEC (SR
)); /* M decr -> xr */
1508 case 01535: /* LDC */
1509 if (tag
) put_xr (tag
, NEG (GET_DEC (SR
))); /* -M decr -> xr */
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
;
1518 case 01600: /* STQ */
1522 case 01602: /* ORS */
1523 SR
= SR
| (AC
& DMASK
);
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
);
1533 case 01620: /* SLQ */
1534 SR
= (SR
& RMASK
) | (MQ
& LMASK
);
1538 case 01625: /* STL */
1539 SR
= (SR
& ~AMASK
) | PC
;
1543 case 01634: /* SXD */
1544 SR
= (SR
& ~XMASK
) | /* xr -> M decr */
1545 (((t_uint64
) get_xrx (tag
)) << INST_V_DEC
);
1549 case 01636: /* SCD */
1550 SR
= (SR
& ~XMASK
) | /* -xr -> M decr */
1551 (((t_uint64
) (NEG (get_xrx (tag
)) & AMASK
)) << INST_V_DEC
);
1555 case 01700: /* CAD (704) */
1559 case 01734: /* PDX */
1560 if (tag
) put_xr (tag
, GET_DEC (AC
)); /* AC decr -> xr */
1563 case 01737: /* PDC */
1564 if (tag
) put_xr (tag
, NEG (GET_DEC (AC
))); /* -AC decr -> xr */
1567 case 01754: /* PXD */
1568 AC
= ((t_uint64
) get_xrx (tag
)) << INST_V_DEC
;
1569 break; /* xr -> AC decr */
1571 case 01756: /* PCD */
1572 AC
= ((t_uint64
) (NEG (get_xrx (tag
)) & AMASK
)) << INST_V_DEC
;
1573 break; /* -xr -> AC decr */
1575 case 01760: /* MSE */
1576 if (prot_trap (0)) break; /* user mode? */
1577 reason
= op_mse (ea
);
1580 case 01761: /* (CTSS) ext core */
1581 if (prot_trap (0)) break; /* user mode? */
1582 if (ea
== 041) /* SEA? */
1584 else if (ea
== 042) /* SEB? */
1585 data_base
= BCORE_BASE
;
1586 else if (ea
== 043) { /* IFT? */
1588 PC
= (PC
+ 1) & eamask
;
1590 else if (ea
== 044) { /* EFT? */
1592 PC
= (PC
+ 1) & eamask
;
1594 else if (stop_illop
)
1595 reason
= STOP_ILLEG
;
1598 case 01763: /* LGL */
1602 case 01765: /* LGR */
1606 case 01773: /* RQL */
1607 sc
= (ea
& SCMASK
) % 36;
1608 if (sc
) MQ
= ((MQ
<< sc
) | (MQ
>> (36 - sc
))) & DMASK
;
1611 case 01774: /* AXC */
1612 if (tag
) put_xr (tag
, NEG (addr
)); /* -IR addr -> xr */
1615 /* IO instructions */
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
)) {
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 */
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
)) {
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 */
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
)) {
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 */
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? */
1665 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
1666 if (ch_sta
[ch
] != CHXS_IDLE
) {
1668 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
1669 else PC
= ea
; /* branch */
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? */
1677 if (mode_ttrap
) WriteTA (TRAP_STD_SAV
, oldPC
);
1678 if (ch_sta
[ch
] == CHXS_IDLE
) {
1680 if (mode_ttrap
) TrapXfr (TRAP_TRA_PC
); /* trap? */
1681 else PC
= ea
; /* branch */
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 */
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 */
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
)
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
)
1716 case 00762: /* RDS */
1717 if (prot_trap (0) || sel_trap (PC
)) break;
1719 reason
= ch_op_ds (ch
, CHSL_RDS
, GET_U_UNIT (ea
));
1720 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1723 case 00764: /* BSR */
1724 if (prot_trap (0) || sel_trap (PC
)) break;
1726 reason
= ch_op_nds (ch
, CHSL_BSR
, GET_U_UNIT (ea
));
1727 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1730 case 00766: /* WRS */
1731 if (prot_trap (0) || sel_trap (PC
)) break;
1733 reason
= ch_op_ds (ch
, CHSL_WRS
, GET_U_UNIT (ea
));
1734 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1737 case 00770: /* WEF */
1738 if (prot_trap (0) || sel_trap (PC
)) break;
1740 reason
= ch_op_nds (ch
, CHSL_WEF
, GET_U_UNIT (ea
));
1741 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1744 case 00772: /* REW */
1745 if (prot_trap (0) || sel_trap (PC
)) break;
1747 reason
= ch_op_nds (ch
, CHSL_REW
, GET_U_UNIT (ea
));
1748 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1751 case 01764: /* BSF */
1752 if (prot_trap (0) || sel_trap (PC
)) break;
1754 reason
= ch_op_nds (ch
, CHSL_BSF
, GET_U_UNIT (ea
));
1755 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1758 case 01772: /* RUN */
1759 if (prot_trap (0) || sel_trap (PC
)) break;
1761 reason
= ch_op_nds (ch
, CHSL_RUN
, GET_U_UNIT (ea
));
1762 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1765 case 00776: /* SDN */
1766 if (prot_trap (0) || sel_trap (PC
)) break;
1768 reason
= ch_op_nds (ch
, CHSL_SDN
, GET_U_UNIT (ea
));
1769 chtr_pend
= chtr_eval (NULL
); /* eval chan traps */
1773 if (stop_illop
) reason
= STOP_ILLEG
;
1778 if (reason
) { /* reason code? */
1779 if (reason
== ERR_STALL
) { /* stall? */
1780 PC
= oldPC
; /* back up PC */
1783 else if (reason
== STOP_HALT
) { /* halt? wait for IO */
1785 for (i
= 0; (i
< HALT_IO_LIMIT
) && !ch_qidle (); i
++) {
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
;
1794 chtr_pend
= chtr_eval (NULL
);
1796 } /* end while ch_req */
1797 } /* end for wait */
1798 if (chtr_pend
) reason
= 0; /* trap? cancel HALT */
1800 } /* end if reason */
1803 pcq_r
->qptr
= pcq_p
; /* update pc q ptr */
1807 /* Get index register for indexing */
1809 uint32
get_xri (uint32 tag
)
1811 tag
= tag
& INST_M_TAG
;
1816 if (tag
& 1) r
= r
| XR
[1];
1817 if (tag
& 2) r
= r
| XR
[2];
1818 if (tag
& 4) r
= r
| XR
[4];
1821 return XR
[tag
] & eamask
;
1826 /* Get index register for instruction execution
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. */
1832 uint32
get_xrx (uint32 tag
)
1834 tag
= tag
& INST_M_TAG
;
1839 if (tag
& 1) r
= r
| XR
[1];
1840 if (tag
& 2) r
= r
| XR
[2];
1841 if (tag
& 4) r
= r
| XR
[4];
1845 return XR
[tag
] & eamask
;
1850 /* Store index register */
1852 void put_xr (uint32 tag
, uint32 dat
)
1854 tag
= tag
& INST_M_TAG
;
1859 if (tag
& 1) XR
[1] = dat
;
1860 if (tag
& 2) XR
[2] = dat
;
1861 if (tag
& 4) XR
[4] = dat
;
1868 /* Floating point trap */
1870 t_bool
fp_trap (uint32 spill
)
1873 WriteTAD (TRAP_STD_SAV
, PC
, spill
);
1879 if (spill
& TRAP_F_AC
) ind_ovf
= 1;
1880 if (spill
& TRAP_F_MQ
) ind_mqo
= 1;
1885 /* (CTSS) Protection trap */
1887 t_bool
prot_trap (uint32 decr
)
1890 WriteTAD (TRAP_PROT_SAV
, PC
, decr
);
1898 /* Store trap address and decrement, with A/B select flags; clear A/B, user mode */
1900 void WriteTAD (uint32 pa
, uint32 addr
, uint32 decr
)
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
));
1921 t_bool
cpy_trap (uint32 va
)
1924 WriteTA (TRAP_704_SAV
, va
);
1926 TrapXfr (TRAP_CPY_PC
);
1934 t_bool
sel_trap (uint32 va
)
1937 WriteTA (TRAP_704_SAV
, va
);
1939 TrapXfr (TRAP_SEL_PC
);
1945 /* Store trap address - do not alter state yet (might be TRA) */
1947 void WriteTA (uint32 pa
, uint32 dat
)
1951 mem
= ReadP (pa
) & ~AMASK
;
1952 mem
|= (dat
& AMASK
);
1957 /* Set trap PC - second half of address-only trap */
1959 void TrapXfr (uint32 newpc
)
1971 /* Read instruction and indirect */
1973 t_bool
ReadI (uint32 va
, t_uint64
*val
)
1976 va
= (va
+ ind_reloc
) & AMASK
;
1977 if ((va
< ind_start
) || (va
> ind_limit
)) {
1982 *val
= M
[va
| inst_base
];
1988 t_bool
Read (uint32 va
, t_uint64
*val
)
1991 va
= (va
+ ind_reloc
) & AMASK
;
1992 if ((va
< ind_start
) || (va
> ind_limit
)) {
1997 *val
= M
[va
| data_base
];
2003 t_bool
Write (uint32 va
, t_uint64 dat
)
2006 va
= (va
+ ind_reloc
) & AMASK
;
2007 if ((va
< ind_start
) || (va
> ind_limit
)) {
2012 M
[va
| data_base
] = dat
;
2018 t_stat
cpu_reset (DEVICE
*dptr
)
2032 if (cpu_model
& (I_94
|I_CT
)) mode_multi
= 0;
2033 else mode_multi
= 1;
2038 chtr_pend
= chtr_enab
= 0;
2039 chtr_inht
= chtr_inhi
= 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');
2052 /* Memory examine */
2054 t_stat
cpu_ex (t_value
*vptr
, t_addr ea
, UNIT
*uptr
, int32 sw
)
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
;
2064 /* Memory deposit */
2066 t_stat
cpu_dep (t_value val
, t_addr ea
, UNIT
*uptr
, int32 sw
)
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
;
2076 t_stat
cpu_set_model (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
2078 UNIT
*chuptr
= mt_dev
[CHRONO_CH
].units
+ CHRONO_UNIT
;
2079 extern DEVICE clk_dev
;
2083 uptr
->capac
= MAXMEMSIZE
;
2085 chuptr
->flags
&= ~UNIT_ATTABLE
;
2086 clk_dev
.flags
&= ~DEV_DIS
;
2089 uptr
->capac
= STDMEMSIZE
;
2090 chuptr
->flags
|= UNIT_ATTABLE
;
2092 if (!(cpu_model
& I_94
)) mode_multi
= 1;
2098 t_stat
cpu_show_model (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
2100 if (cpu_model
& I_CT
) fputs ("CTSS", st
);
2101 else if (cpu_model
& I_94
) fputs ("7094", st
);
2102 else fputs ("7090", st
);
2106 /* Insert history entry */
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 */
2115 void cpu_ent_hist (uint32 pc
, uint32 ea
, t_uint64 ir
, t_uint64 opnd
)
2120 if ((pc
== hst
[hst_p
].pc
) && (ir
== hst
[hst_p
].ir
)) { /* repeat last? */
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? */
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;
2135 hst_p
= (hst_p
+ 1); /* next entry */
2136 if (hst_p
>= hst_lnt
) hst_p
= 0;
2143 hst
[hst_p
].opnd
= opnd
;
2150 t_stat
cpu_set_hist (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
2156 for (i
= 0; i
< hst_lnt
; i
++) hst
[i
].pc
= 0;
2160 lnt
= (int32
) get_uint (cptr
, 10, HIST_MAX
, &r
);
2161 if ((r
!= SCPE_OK
) || (lnt
&& (lnt
< HIST_MIN
))) return SCPE_ARG
;
2165 hst_lnt
= hst_ch
= 0;
2169 hst
= (InstHistory
*) calloc (lnt
, sizeof (InstHistory
));
2170 if (hst
== NULL
) return SCPE_MEM
;
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
;
2179 /* Print one instruction */
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
)
2186 extern t_stat
fprint_sym (FILE *ofile
, t_addr addr
, t_value
*val
,
2187 UNIT
*uptr
, int32 sw
);
2190 if (pc
& HIST_PC
) { /* instruction? */
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
);
2198 fprint_val (st
, mq
, 8, 36, PV_RZRO
);
2200 fprint_val (st
, si
, 8, 36, PV_RZRO
);
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
);
2208 else if (!(ir
& INST_T_DEC
) && (op_flags
[GET_OPC (ir
)] & I_R
)) {
2210 fprint_val (st
, opnd
, 8, 36, PV_RZRO
);
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
);
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
);
2225 fputc ('\n', st
); /* end line */
2226 } /* end else channel */
2232 t_stat
cpu_show_hist (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
2235 char *cptr
= (char *) desc
;
2239 if (hst_lnt
== 0) return SCPE_NOFNC
; /* enabled? */
2241 lnt
= (int32
) get_uint (cptr
, 10, hst_lnt
, &r
);
2242 if ((r
!= SCPE_OK
) || (lnt
== 0)) return SCPE_ARG
;
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
);