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