First Commit of my working state
[simh.git] / PDP10 / pdp10_cpu.c
CommitLineData
196ba1fc
PH
1/* pdp10_cpu.c: PDP-10 CPU simulator\r
2\r
3 Copyright (c) 1993-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 KS10 central processor\r
27\r
28 17-Jul-07 RMS Fixed non-portable usage in SHOW HISTORY\r
29 28-Apr-07 RMS Removed clock initialization\r
30 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)\r
31 Fixed warning in MOVNI\r
32 16-Aug-05 RMS Fixed C++ declaration and cast problems\r
33 10-Nov-04 RMS Added instruction history\r
34 08-Oct-02 RMS Revised to build dib_tab dynamically\r
35 Added SHOW IOSPACE\r
36 30-Dec-01 RMS Added old PC queue\r
37 25-Dec-01 RMS Cleaned up sim_inst declarations\r
38 07-Dec-01 RMS Revised to use new breakpoint package\r
39 21-Nov-01 RMS Implemented ITS 1-proceed hack\r
40 31-Aug-01 RMS Changed int64 to t_int64 for Windoze\r
41 10-Aug-01 RMS Removed register in declarations\r
42 17-Jul-01 RMS Moved function prototype\r
43 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug\r
44 29-Apr-01 RMS Fixed modifier naming conflict\r
45 Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS\r
46 Added CLRCSH for ITS\r
47\r
48 The 36b system family had six different implementions: PDP-6, KA10, KI10,\r
49 L10, KL10 extended, and KS10. This simulator implements the KS10.\r
50\r
51 The register state for the KS10 is:\r
52\r
53 AC[8][16] accumulators\r
54 PC program counter\r
55 flags<0:11> state flags\r
56 pi_enb<1:7> enabled PI levels\r
57 pi_act<1:7> active PI levels\r
58 pi_prq<1:7> program PI requests\r
59 apr_enb<0:7> enabled system flags\r
60 apr_flg<0:7> system flags\r
61 ebr executive base register\r
62 ubr user base register\r
63 hsb halt status block address\r
64 spt SPT base\r
65 cst CST base\r
66 pur process use register\r
67 cstm CST mask\r
68\r
69 The PDP-10 had just two instruction formats: memory reference\r
70 and I/O.\r
71\r
72 000000000 0111 1 1111 112222222222333333\r
73 012345678 9012 3 4567 890123456789012345\r
74 +---------+----+-+----+------------------+\r
75 | opcode | ac |i| idx| address | memory reference\r
76 +---------+----+-+----+------------------+\r
77\r
78 000 0000000 111 1 1111 112222222222333333\r
79 012 3456789 012 3 4567 890123456789012345\r
80 +---+-------+---+-+----+------------------+\r
81 |111|device |iop|i| idx| address | I/O\r
82 +---+-------+---+-+----+------------------+\r
83\r
84 This routine is the instruction decode routine for the PDP-10.\r
85 It is called from the simulator control program to execute\r
86 instructions in simulated memory, starting at the simulated PC.\r
87 It runs until an abort occurs.\r
88\r
89 General notes:\r
90\r
91 1. Reasons to stop. The simulator can be stopped by:\r
92\r
93 HALT instruction\r
94 MUUO instruction in executive mode\r
95 pager error in interrupt sequence\r
96 invalid vector table in interrupt sequence\r
97 illegal instruction in interrupt sequence\r
98 breakpoint encountered\r
99 nested indirects exceeding limit\r
100 nested XCT's exceeding limit\r
101 I/O error in I/O simulator\r
102\r
103 2. Interrupts. PDP-10's have a seven level priority interrupt\r
104 system. Interrupt requests can come from internal sources,\r
105 such as APR program requests, or external sources, such as\r
106 I/O devices. The requests are stored in pi_prq for program\r
107 requests, pi_apr for other internal flags, and pi_ioq for\r
108 I/O device flags. Internal and device (but not program)\r
109 interrupts must be enabled on a level by level basis. When\r
110 an interrupt is granted on a level, interrupts at that level\r
111 and below are masked until the interrupt is dismissed.\r
112\r
113 The I/O device interrupt system is taken from the PDP-11.\r
114 int_req stores the interrupt requests for Unibus I/O devices.\r
115 Routines in the Unibus adapter map requests in int_req to\r
116 PDP-10 levels. The Unibus adapter also calculates which\r
117 device to get a vector from when a PDP-10 interrupt is granted.\r
118\r
119 3. Arithmetic. The PDP-10 is a 2's complement system.\r
120\r
121 4. Adding I/O devices. These modules must be modified:\r
122\r
123 pdp10_defs.h add device address and interrupt definitions\r
124 pdp10_sys.c add sim_devices table entry\r
125\r
126 A note on ITS 1-proceed. The simulator follows the implementation\r
127 on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than\r
128 as flags<8>. This simplifies the flag saving instructions, which\r
129 don't have to clear flags<8> before saving it. Instead, the page\r
130 fail and interrupt code must restore flags<8> from its_1pr. Unlike\r
131 the KS10, the simulator will not lose the 1-proceed trap if the\r
132 1-proceeded instructions clears 1-proceed.\r
133*/\r
134\r
135#include "pdp10_defs.h"\r
136#include <setjmp.h>\r
137\r
138#define PCQ_SIZE 64 /* must be 2**n */\r
139#define PCQ_MASK (PCQ_SIZE - 1)\r
140#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC\r
141\r
142#define HIST_PC 0x40000000\r
143#define HIST_MIN 64\r
144#define HIST_MAX 65536\r
145\r
146typedef struct {\r
147 a10 pc;\r
148 a10 ea;\r
149 d10 ir;\r
150 d10 ac;\r
151 } InstHistory;\r
152\r
153d10 *M = NULL; /* memory */\r
154d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */\r
155d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */\r
156a10 epta, upta; /* proc tbl addr (dyn) */\r
157a10 saved_PC = 0; /* scp: saved PC */\r
158d10 pager_word = 0; /* pager: error word */\r
159a10 pager_PC = 0; /* pager: saved PC */\r
160int32 pager_flags = 0; /* pager: trap flags */\r
161t_bool pager_pi = FALSE; /* pager: in pi seq */\r
162t_bool pager_tc = FALSE; /* pager: trap cycle */\r
163d10 ebr = 0; /* exec base reg */\r
164d10 ubr = 0; /* user base reg */\r
165d10 hsb = 0; /* halt status block */\r
166d10 spt = 0; /* TOPS20 paging regs */\r
167d10 cst = 0;\r
168d10 pur = 0;\r
169d10 cstm = 0;\r
170a10 dbr1 = 0; /* ITS paging regs */\r
171a10 dbr2 = 0;\r
172a10 dbr3 = 0;\r
173a10 dbr4 = 0;\r
174d10 pcst = 0; /* ITS PC sampling */\r
175int32 pi_on = 0; /* pi system enable */\r
176int32 pi_enb = 0; /* pi enabled levels */\r
177int32 pi_act = 0; /* pi active levels */\r
178int32 pi_ioq = 0; /* pi io requests */\r
179int32 pi_apr = 0; /* pi apr requests */\r
180int32 pi_prq = 0; /* pi prog requests */\r
181int32 apr_enb = 0; /* apr enables */\r
182int32 apr_flg = 0; /* apr flags */\r
183int32 apr_lvl = 0; /* apr level */\r
184int32 qintr = 0; /* interrupt pending */\r
185int32 flags = 0; /* flags */\r
186int32 its_1pr = 0; /* ITS 1-proceed */\r
187int32 stop_op0 = 0; /* stop on 0 */\r
188int32 rlog = 0; /* extend fixup log */\r
189int32 ind_max = 32; /* nested ind limit */\r
190int32 xct_max = 32; /* nested XCT limit */\r
191int32 t20_idlelock = 0; /* TOPS-20 idle lock */\r
192a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */\r
193int32 pcq_p = 0; /* PC queue ptr */\r
194REG *pcq_r = NULL; /* PC queue reg ptr */\r
195jmp_buf save_env;\r
196int32 hst_p = 0; /* history pointer */\r
197int32 hst_lnt = 0; /* history length */\r
198InstHistory *hst = NULL; /* instruction history */\r
199\r
200extern int32 sim_int_char;\r
201extern int32 sim_interval;\r
202extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */\r
203\r
204/* Forward and external declarations */\r
205\r
206t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);\r
207t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);\r
208t_stat cpu_reset (DEVICE *dptr);\r
209t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);\r
210t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);\r
211d10 adjsp (d10 val, a10 ea);\r
212void ibp (a10 ea, int32 pflgs);\r
213d10 ldb (a10 ea, int32 pflgs);\r
214void dpb (d10 val, a10 ea, int32 pflgs);\r
215void adjbp (int32 ac, a10 ea, int32 pflgs);\r
216d10 add (d10 val, d10 mb);\r
217d10 sub (d10 val, d10 mb);\r
218void dadd (int32 ac, d10 *rs);\r
219void dsub (int32 ac, d10 *rs);\r
220int32 jffo (d10 val);\r
221d10 lsh (d10 val, a10 ea);\r
222d10 rot (d10 val, a10 ea);\r
223d10 ash (d10 val, a10 ea);\r
224void lshc (int32 ac, a10 ea);\r
225void rotc (int32 ac, a10 ea);\r
226void ashc (int32 ac, a10 ea);\r
227void circ (int32 ac, a10 ea);\r
228void blt (int32 ac, a10 ea, int32 pflgs);\r
229void bltu (int32 ac, a10 ea, int32 pflgs, int dir);\r
230a10 calc_ea (d10 inst, int32 prv);\r
231a10 calc_ioea (d10 inst, int32 prv);\r
232d10 calc_jrstfea (d10 inst, int32 pflgs);\r
233void pi_dismiss (void);\r
234void set_newflags (d10 fl, t_bool jrst);\r
235extern t_bool aprid (a10 ea, int32 prv);\r
236t_bool wrpi (a10 ea, int32 prv);\r
237t_bool rdpi (a10 ea, int32 prv);\r
238t_bool czpi (a10 ea, int32 prv);\r
239t_bool copi (a10 ea, int32 prv);\r
240t_bool wrapr (a10 ea, int32 prv);\r
241t_bool rdapr (a10 ea, int32 prv);\r
242t_bool czapr (a10 ea, int32 prv);\r
243t_bool coapr (a10 ea, int32 prv);\r
244int32 pi_eval (void);\r
245int32 test_int (void);\r
246void set_ac_display (d10 *acbase);\r
247\r
248extern t_stat build_dib_tab (void);\r
249extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);\r
250extern d10 Read (a10 ea, int32 prv); /* read, read check */\r
251extern d10 ReadM (a10 ea, int32 prv); /* read, write check */\r
252extern d10 ReadE (a10 ea); /* read, exec */\r
253extern d10 ReadP (a10 ea); /* read, physical */\r
254extern void Write (a10 ea, d10 val, int32 prv); /* write */\r
255extern void WriteE (a10 ea, d10 val); /* write, exec */\r
256extern void WriteP (a10 ea, d10 val); /* write, physical */\r
257extern t_bool AccViol (a10 ea, int32 prv, int32 mode); /* access check */\r
258extern void set_dyn_ptrs (void);\r
259extern a10 conmap (a10 ea, int32 mode, int32 sw);\r
260extern void fe_intr ();\r
261extern void dfad (int32 ac, d10 *rs, int32 inv);\r
262extern void dfmp (int32 ac, d10 *rs);\r
263extern void dfdv (int32 ac, d10 *rs);\r
264extern void dmul (int32 ac, d10 *rs);\r
265extern void ddiv (int32 ac, d10 *rs);\r
266extern void fix (int32 ac, d10 mb, t_bool rnd);\r
267extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv);\r
268extern d10 fmp (d10 val, d10 mb, t_bool rnd);\r
269extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd);\r
270extern d10 fsc (d10 val, a10 ea);\r
271extern d10 fltr (d10 mb);\r
272extern int xtend (int32 ac, a10 ea, int32 pflgs);\r
273extern void xtcln (int32 rlog);\r
274extern d10 map (a10 ea, int32 prv);\r
275extern d10 imul (d10 val, d10 mb);\r
276extern t_bool idiv (d10 val, d10 mb, d10 *rs);\r
277extern void mul (d10 val, d10 mb, d10 *rs);\r
278extern t_bool divi (int32 ac, d10 mb, d10 *rs);\r
279extern t_bool io710 (int32 ac, a10 ea);\r
280extern t_bool io711 (int32 ac, a10 ea);\r
281extern d10 io712 (a10 ea);\r
282extern void io713 (d10 val, a10 ea);\r
283extern void io714 (d10 val, a10 ea);\r
284extern void io715 (d10 val, a10 ea);\r
285extern t_bool io720 (int32 ac, a10 ea);\r
286extern t_bool io721 (int32 ac, a10 ea);\r
287extern d10 io722 (a10 ea);\r
288extern void io723 (d10 val, a10 ea);\r
289extern void io724 (d10 val, a10 ea);\r
290extern void io725 (d10 val, a10 ea);\r
291extern t_bool clrcsh (a10 ea, int32 prv);\r
292extern t_bool clrpt (a10 ea, int32 prv);\r
293extern t_bool wrubr (a10 ea, int32 prv);\r
294extern t_bool wrebr (a10 ea, int32 prv);\r
295extern t_bool wrhsb (a10 ea, int32 prv);\r
296extern t_bool wrspb (a10 ea, int32 prv);\r
297extern t_bool wrcsb (a10 ea, int32 prv);\r
298extern t_bool wrpur (a10 ea, int32 prv);\r
299extern t_bool wrcstm (a10 ea, int32 prv);\r
300extern t_bool ldbr1 (a10 ea, int32 prv);\r
301extern t_bool ldbr2 (a10 ea, int32 prv);\r
302extern t_bool ldbr3 (a10 ea, int32 prv);\r
303extern t_bool ldbr4 (a10 ea, int32 prv);\r
304extern t_bool rdubr (a10 ea, int32 prv);\r
305extern t_bool rdebr (a10 ea, int32 prv);\r
306extern t_bool rdhsb (a10 ea, int32 prv);\r
307extern t_bool rdspb (a10 ea, int32 prv);\r
308extern t_bool rdcsb (a10 ea, int32 prv);\r
309extern t_bool rdpur (a10 ea, int32 prv);\r
310extern t_bool rdcstm (a10 ea, int32 prv);\r
311extern t_bool sdbr1 (a10 ea, int32 prv);\r
312extern t_bool sdbr2 (a10 ea, int32 prv);\r
313extern t_bool sdbr3 (a10 ea, int32 prv);\r
314extern t_bool sdbr4 (a10 ea, int32 prv);\r
315extern t_bool rdtim (a10 ea, int32 prv);\r
316extern t_bool rdint (a10 ea, int32 prv);\r
317extern t_bool wrtim (a10 ea, int32 prv);\r
318extern t_bool wrint (a10 ea, int32 prv);\r
319extern t_bool rdpcst (a10 ea, int32 prv);\r
320extern t_bool wrpcst (a10 ea, int32 prv);\r
321extern t_bool spm (a10 ea, int32 prv);\r
322extern t_bool lpmr (a10 ea, int32 prv);\r
323extern int32 pi_ub_vec (int32 lvl, int32 *uba);\r
324extern t_stat tim_set_mod (UNIT *uptr, int32 val, char *cptr, void *desc);\r
325\r
326/* CPU data structures\r
327\r
328 cpu_dev CPU device descriptor\r
329 cpu_unit CPU unit\r
330 cpu_reg CPU register list\r
331 cpu_mod CPU modifier list\r
332*/\r
333\r
334UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MAXMEMSIZE) };\r
335\r
336REG cpu_reg[] = {\r
337 { ORDATA (PC, saved_PC, VASIZE) },\r
338 { ORDATA (FLAGS, flags, 18) },\r
339 { ORDATA (AC0, acs[0], 36) }, /* addr in memory */\r
340 { ORDATA (AC1, acs[1], 36) }, /* modified at exit */\r
341 { ORDATA (AC2, acs[2], 36) }, /* to SCP */\r
342 { ORDATA (AC3, acs[3], 36) },\r
343 { ORDATA (AC4, acs[4], 36) },\r
344 { ORDATA (AC5, acs[5], 36) },\r
345 { ORDATA (AC6, acs[6], 36) },\r
346 { ORDATA (AC7, acs[7], 36) },\r
347 { ORDATA (AC10, acs[10], 36) },\r
348 { ORDATA (AC11, acs[11], 36) },\r
349 { ORDATA (AC12, acs[12], 36) },\r
350 { ORDATA (AC13, acs[13], 36) },\r
351 { ORDATA (AC14, acs[14], 36) },\r
352 { ORDATA (AC15, acs[15], 36) },\r
353 { ORDATA (AC16, acs[16], 36) },\r
354 { ORDATA (AC17, acs[17], 36) },\r
355 { ORDATA (PFW, pager_word, 36) },\r
356 { ORDATA (EBR, ebr, EBR_N_EBR) },\r
357 { FLDATA (PGON, ebr, EBR_V_PGON) },\r
358 { FLDATA (T20P, ebr, EBR_V_T20P) },\r
359 { ORDATA (UBR, ubr, 36) },\r
360 { GRDATA (CURAC, ubr, 8, 3, UBR_V_CURAC), REG_RO },\r
361 { GRDATA (PRVAC, ubr, 8, 3, UBR_V_PRVAC) },\r
362 { ORDATA (SPT, spt, 36) },\r
363 { ORDATA (CST, cst, 36) },\r
364 { ORDATA (PUR, pur, 36) },\r
365 { ORDATA (CSTM, cstm, 36) },\r
366 { ORDATA (HSB, hsb, 36) },\r
367 { ORDATA (DBR1, dbr1, PASIZE) },\r
368 { ORDATA (DBR2, dbr2, PASIZE) },\r
369 { ORDATA (DBR3, dbr3, PASIZE) },\r
370 { ORDATA (DBR4, dbr4, PASIZE) },\r
371 { ORDATA (PCST, pcst, 36) }, \r
372 { ORDATA (PIENB, pi_enb, 7) },\r
373 { FLDATA (PION, pi_on, 0) },\r
374 { ORDATA (PIACT, pi_act, 7) },\r
375 { ORDATA (PIPRQ, pi_prq, 7) },\r
376 { ORDATA (PIIOQ, pi_ioq, 7), REG_RO },\r
377 { ORDATA (PIAPR, pi_apr, 7), REG_RO },\r
378 { ORDATA (APRENB, apr_enb, 8) },\r
379 { ORDATA (APRFLG, apr_flg, 8) },\r
380 { ORDATA (APRLVL, apr_lvl, 3) },\r
381 { ORDATA (RLOG, rlog, 10) },\r
382 { FLDATA (F1PR, its_1pr, 0) },\r
383 { BRDATA (PCQ, pcq, 8, VASIZE, PCQ_SIZE), REG_RO+REG_CIRC },\r
384 { ORDATA (PCQP, pcq_p, 6), REG_HRO },\r
385 { DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ },\r
386 { DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ },\r
387 { ORDATA (WRU, sim_int_char, 8) },\r
388 { FLDATA (STOP_ILL, stop_op0, 0) },\r
389 { BRDATA (REG, acs, 8, 36, AC_NUM * AC_NBLK) },\r
390 { NULL }\r
391 };\r
392\r
393MTAB cpu_mod[] = {\r
394 { UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, "TOPS-10", "TOPS-10", &tim_set_mod },\r
395 { UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, NULL , "TOPS10", &tim_set_mod },\r
396 { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, "TOPS-20", "TOPS-20", &tim_set_mod },\r
397 { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, NULL, "TOPS20", &tim_set_mod },\r
398 { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_ITS, "ITS", "ITS", &tim_set_mod },\r
399 { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_KLAD, "diagnostic mode", "KLAD", &tim_set_mod },\r
400 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },\r
401 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },\r
402 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,\r
403 NULL, &show_iospace },\r
404 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",\r
405 &cpu_set_hist, &cpu_show_hist },\r
406 { 0 }\r
407 };\r
408\r
409DEVICE cpu_dev = {\r
410 "CPU", &cpu_unit, cpu_reg, cpu_mod,\r
411 1, 8, PASIZE, 1, 8, 36,\r
412 &cpu_ex, &cpu_dep, &cpu_reset,\r
413 NULL, NULL, NULL\r
414 };\r
415\r
416/* Data arrays */\r
417 \r
418const int32 pi_l2bit[8] = {\r
419 0, 0100, 0040, 0020, 0010, 0004, 0002, 0001\r
420 };\r
421\r
422const int32 pi_m2lvl[128] = {\r
423 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,\r
424 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\r
425 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
426 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
427 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
428 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
429 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r
431 };\r
432\r
433const d10 bytemask[64] = { 0,\r
434 01, 03, 07, 017, 037, 077,\r
435 0177, 0377, 0777, 01777, 03777, 07777,\r
436 017777, 037777, 077777,\r
437 0177777, 0377777, 0777777,\r
438 01777777, 03777777, 07777777,\r
439 017777777, 037777777, 077777777,\r
440 0177777777, 0377777777, 0777777777,\r
441 01777777777, 03777777777, 07777777777,\r
442 017777777777, 037777777777, 077777777777,\r
443 0177777777777, 0377777777777, 0777777777777,\r
444 ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,\r
445 ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,\r
446 ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES\r
447 };\r
448\r
449static t_bool (*io700d[16])() = {\r
450 &aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr,\r
451 NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi\r
452 };\r
453static t_bool (*io701d[16])() = {\r
454 NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,\r
455 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\r
456 };\r
457static t_bool (*io702d[16])() = {\r
458 &rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL,\r
459 &wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL\r
460 };\r
461#define io700i io700d\r
462static t_bool (*io701i[16])() = {\r
463 &clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,\r
464 NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL\r
465 };\r
466static t_bool (*io702i[16])() = {\r
467 &sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm,\r
468 &ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr\r
469 };\r
470\r
471/* JRST classes and validation table */\r
472\r
473#define JRST_U 1 /* ok anywhere */\r
474#define JRST_E 2 /* ok exec mode */\r
475#define JRST_UIO 3 /* ok user I/O mode */\r
476 \r
477static t_stat jrst_tab[16] = {\r
478 JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E,\r
479 JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0\r
480 };\r
481\r
482/* Address operations */\r
483\r
484#define IM ((d10) ea)\r
485#define IMS (((d10) ea) << 18)\r
486#define JUMP(x) PCQ_ENTRY, PC = ((a10) (x)) & AMASK\r
487#define SUBJ(x) CLRF (F_AFI | F_FPD | F_TR); JUMP (x)\r
488#define INCPC PC = INCA (PC)\r
489\r
490/* AC operations */\r
491\r
492#define AOBAC AC(ac) = AOB (AC(ac))\r
493#define SOBAC AC(ac) = SOB (AC(ac))\r
494#define G2AC rs[0] = AC(ac), rs[1] = AC(P1)\r
495#define S1AC AC(ac) = rs[0]\r
496#define S2AC S1AC, AC(P1) = rs[1]\r
497#define LAC if (ac) AC(ac) = mb\r
498\r
499/* Memory operations */\r
500\r
501#define RD mb = Read (ea, MM_OPND)\r
502#define RDAC AC(ac) = Read (ea, MM_OPND)\r
503#define RM mb = ReadM (ea, MM_OPND)\r
504#define RMAC AC(ac) = ReadM (ea, MM_OPND)\r
505#define RDP mb = Read (((a10) AC(ac)) & AMASK, MM_BSTK)\r
506#define RD2 rs[0] = Read (ea, MM_OPND); \\r
507 rs[1] = Read (INCA (ea), MM_OPND)\r
508#define WR Write (ea, mb, MM_OPND)\r
509#define WRAC Write (ea, AC(ac), MM_OPND)\r
510#define WRP(x) Write (((a10) INCA (AC(ac))), (x), MM_BSTK)\r
511#define WR1 Write (ea, rs[0], MM_OPND)\r
512#define WR2 ReadM (INCA (ea), MM_OPND); \\r
513 Write (ea, rs[0], MM_OPND); \\r
514 Write (INCA (ea), rs[1], MM_OPND)\r
515\r
516/* Tests and compares */\r
517\r
518#define TL(a) (TSTS (a) != 0)\r
519#define TE(a) ((a) == 0)\r
520#define TLE(a) (TL (a) || TE (a))\r
521#define TGE(a) (TSTS (a) == 0)\r
522#define TN(a) ((a) != 0)\r
523#define TG(a) (TGE (a) && TN (a))\r
524#define CL(a) ((TSTS (AC(ac) ^ a))? (a < AC(ac)): (AC(ac) < a))\r
525#define CE(a) (AC(ac) == a)\r
526#define CLE(a) (CL (a) || CE (a))\r
527#define CGE(a) (!CL (a))\r
528#define CN(a) (AC(ac) != a)\r
529#define CG(a) (CGE (a) && CN (a))\r
530\r
531/* Word assemblies */\r
532\r
533#define FLPC XWD (flags, PC)\r
534#define UUOWORD (((d10) op) << INST_V_OP) | (((d10) ac) << INST_V_AC) | ea\r
535#define APRHWORD ((apr_flg << APR_V_FLG) | (apr_lvl & APR_M_LVL) | \\r
536 ((apr_flg & apr_enb)? APR_IRQ: 0))\r
537#define APRWORD ((apr_enb << (APR_V_FLG + 18)) | APRHWORD)\r
538#define PIHWORD ((pi_act << PI_V_ACT) | (pi_on << PI_V_ON) | \\r
539 (pi_enb << PI_V_ENB))\r
540#define PIWORD ((pi_prq << PI_V_PRQ) | PIHWORD)\r
541\r
542/* Instruction operations */\r
543\r
544#define CIBP if (!TSTF (F_FPD)) { ibp (ea, pflgs); SETF (F_FPD); }\r
545#define LDB AC(ac) = ldb (ea, pflgs)\r
546#define DPB dpb (AC(ac), ea, pflgs)\r
547#define FAD(s) fad (AC(ac), s, FALSE, 0)\r
548#define FADR(s) fad (AC(ac), s, TRUE, 0)\r
549#define FSB(s) fad (AC(ac), s, FALSE, 1)\r
550#define FSBR(s) fad (AC(ac), s, TRUE, 1)\r
551#define FMP(s) fmp (AC(ac), s, FALSE)\r
552#define FMPR(s) fmp (AC(ac), s, TRUE)\r
553#define FDV(s) fdv (AC(ac), s, rs, FALSE)\r
554#define FDVR(s) fdv (AC(ac), s, rs, TRUE)\r
555#define MOVN(s) NEG (s); MOVNF(s)\r
556#define MOVM(s) ABS (s); MOVMF(s)\r
557#define ADD(s) add (AC(ac), s)\r
558#define SUB(s) sub (AC(ac), s)\r
559#define IMUL(s) imul (AC(ac), s)\r
560#define IDIV(s) idiv (AC(ac), s, rs)\r
561#define MUL(s) mul (AC(ac), s, rs)\r
562#define DIV(s) divi (ac, s, rs)\r
563#define AOJ AC(ac) = INC (AC(ac)); INCF (AC(ac))\r
564#define AOS RM; mb = INC (mb); WR; INCF (mb); LAC\r
565#define SOJ AC(ac) = DEC (AC(ac)); DECF (AC(ac))\r
566#define SOS RM; mb = DEC (mb); WR; DECF (mb); LAC\r
567#define SETCA(s) ~AC(ac) & DMASK\r
568#define SETCM(s) ~(s) & DMASK;\r
569#define AND(s) AC(ac) & (s)\r
570#define ANDCA(s) ~AC(ac) & (s)\r
571#define ANDCM(s) AC(ac) & ~(s)\r
572#define ANDCB(s) (~AC(ac) & ~(s)) & DMASK\r
573#define IOR(s) AC(ac) | (s)\r
574#define ORCA(s) (~AC(ac) | (s)) & DMASK\r
575#define ORCM(s) (AC(ac) | ~(s)) & DMASK\r
576#define ORCB(s) (~AC(ac) | ~(s)) & DMASK\r
577#define XOR(s) AC(ac) ^ (s)\r
578#define EQV(s) (~(AC(ac) ^ (s))) & DMASK\r
579#define LL(s,d) ((s) & LMASK) | ((d) & RMASK)\r
580#define RL(s,d) (((s) << 18) & LMASK) | ((d) & RMASK)\r
581#define RR(s,d) ((s) & RMASK) | ((d) & LMASK)\r
582#define LR(s,d) (((s) >> 18) & RMASK) | ((d) & LMASK)\r
583#define LLO(s) ((s) & LMASK) | RMASK\r
584#define RLO(s) (((s) << 18) & LMASK) | RMASK\r
585#define RRO(s) ((s) & RMASK) | LMASK\r
586#define LRO(s) (((s) >> 18) & RMASK) | LMASK\r
587#define LLE(s) ((s) & LMASK) | (((s) & LSIGN)? RMASK: 0)\r
588#define RLE(s) (((s) << 18) & LMASK) | (((s) & RSIGN)? RMASK: 0)\r
589#define RRE(s) ((s) & RMASK) | (((s) & RSIGN)? LMASK: 0)\r
590#define LRE(s) (((s) >> 18) & RMASK) | (((s) & LSIGN)? LMASK: 0)\r
591#define TD_ RD\r
592#define TS_ RD; mb = SWP (mb)\r
593#define TL_ mb = IMS\r
594#define TR_ mb = IM\r
595#define T_Z AC(ac) = AC(ac) & ~mb\r
596#define T_O AC(ac) = AC(ac) | mb\r
597#define T_C AC(ac) = AC(ac) ^ mb\r
598#define T__E if ((AC(ac) & mb) == 0) INCPC\r
599#define T__N if ((AC(ac) & mb) != 0) INCPC\r
600#define T__A INCPC\r
601#define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO;\r
602#define IO7(x,y) IOC; fptr = ((Q_ITS)? x[ac]: y[ac]); \\r
603 if (fptr == NULL) goto MUUO; \\r
604 if (fptr (ea, MM_OPND)) INCPC; break;\r
605#define IOA IOC; if (!Q_ITS) ea = calc_ioea (inst, pflgs)\r
606#define IOAM IOC; ea = ((Q_ITS)? ((a10) Read (ea, MM_OPND)): \\r
607 calc_ioea (inst, pflgs))\r
608\r
609/* Flag tests */\r
610\r
611#define MOVNF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1); \\r
612 else if ((x) == 0) SETF (F_C0 | F_C1)\r
613#define MOVMF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)\r
614#define INCF(x) if ((x) == 0) SETF (F_C0 | F_C1); \\r
615 else if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)\r
616#define DECF(x) if ((x) == MAXPOS) SETF (F_C0 | F_AOV | F_T1); \\r
617 else if ((x) != ONES) SETF (F_C0 | F_C1)\r
618#define PUSHF if (LRZ (AC(ac)) == 0) SETF (F_T2)\r
619#define POPF if (LRZ (AC(ac)) == RMASK) SETF (F_T2)\r
620#define DMOVNF if (rs[1] == 0) { MOVNF (rs[0]); }\r
621\r
622t_stat sim_instr (void)\r
623{\r
624a10 PC; /* set by setjmp */\r
625int abortval = 0; /* abort value */\r
626t_stat r;\r
627\r
628/* Restore register state */\r
629\r
630if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */\r
631pager_PC = PC = saved_PC & AMASK; /* load local PC */\r
632set_dyn_ptrs (); /* set up local ptrs */\r
633pager_tc = FALSE; /* not in trap cycle */\r
634pager_pi = FALSE; /* not in pi sequence */\r
635rlog = 0; /* not in extend */\r
636pi_eval (); /* eval pi system */\r
637if (!Q_ITS) its_1pr = 0; /* ~ITS, clr 1-proc */\r
638t20_idlelock = 0; /* clr T20 idle lock */\r
639\r
640/* Abort handling\r
641\r
642 Aborts may come from within the simulator to stop simulation (values > 0),\r
643 for page fails (values < 0), or for an interrupt check (value = 0).\r
644*/\r
645\r
646abortval = setjmp (save_env); /* set abort hdlr */\r
647if ((abortval > 0) || pager_pi) { /* stop or pi err? */\r
648 if (pager_pi && (abortval == PAGE_FAIL))\r
649 abortval = STOP_PAGINT; /* stop for pi err */\r
650 saved_PC = pager_PC & AMASK; /* failing instr PC */\r
651 set_ac_display (ac_cur); /* set up AC display */\r
652 pcq_r->qptr = pcq_p; /* update pc q ptr */\r
653 return abortval; /* return to SCP */\r
654 }\r
655\r
656/* Page fail - checked against KS10 ucode\r
657 All state variables MUST be declared global for GCC optimization to work\r
658*/\r
659\r
660else if (abortval == PAGE_FAIL) { /* page fail */\r
661 d10 mb;\r
662 if (rlog) xtcln (rlog); /* clean up extend */\r
663 rlog = 0; /* clear log */\r
664 if (pager_tc) flags = pager_flags; /* trap? get flags */\r
665 if (T20PAG) { /* TOPS-20 paging? */\r
666 WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */\r
667 WriteP (upta + UPT_T20_OFL, XWD (flags, 0));\r
668 WriteP (upta + UPT_T20_OPC, pager_PC);\r
669 mb = ReadP (upta + UPT_T20_NPC);\r
670 }\r
671 else {\r
672 a10 ea; /* TOPS-10 or ITS */\r
673 if (Q_ITS) { /* ITS? */\r
674 ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);\r
675 if (its_1pr) flags = flags | F_1PR; /* store 1-proc */\r
676 its_1pr = 0; /* clear 1-proc */\r
677 }\r
678 else ea = upta + UPT_T10_PAG;\r
679 WriteP (ea, pager_word); /* write page fail wd */\r
680 WriteP (ADDA (ea, 1), XWD (flags, pager_PC));\r
681 mb = ReadP (ADDA (ea, 2));\r
682 }\r
683 JUMP (mb); /* set new PC */\r
684 set_newflags (mb, FALSE); /* set new flags */\r
685 pi_eval (); /* eval pi system */\r
686 }\r
687else PC = pager_PC; /* intr, restore PC */\r
688\r
689/* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */\r
690\r
691for ( ;; ) { /* loop until ABORT */\r
692int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs;\r
693a10 ea;\r
694d10 inst, mb, indrct, rs[2];\r
695t_bool (*fptr)();\r
696\r
697pager_PC = PC; /* update pager PC */\r
698pager_tc = FALSE; /* not in trap cycle */\r
699pflgs = 0; /* not in PXCT */\r
700xct_cnt = 0; /* count XCT's */\r
701if (sim_interval <= 0) { /* check clock queue */\r
702 if (i = sim_process_event ()) ABORT (i); /* error? stop sim */\r
703 pi_eval (); /* eval pi system */\r
704 }\r
705\r
706/* PI interrupt (Unibus or system flags).\r
707 On the KS10, only JSR and XPCW are allowed as interrupt instructions.\r
708 Because of exec mode addressing, and unconditional processing of flags,\r
709 they are explicitly emulated here.\r
710*/\r
711\r
712if (qintr) {\r
713 int32 vec, uba;\r
714 pager_pi = TRUE; /* flag in pi seq */\r
715 if (vec = pi_ub_vec (qintr, &uba)) { /* Unibus interrupt? */\r
716 mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */\r
717 if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */\r
718 inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK);\r
719 if (inst == 0) ABORT (STOP_ZERINT);\r
720 }\r
721 else inst = ReadP (epta + EPT_PIIT + (2 * qintr));\r
722 op = GET_OP (inst); /* get opcode */\r
723 ac = GET_AC (inst); /* get ac */\r
724 if (its_1pr && Q_ITS) { /* 1-proc set? */\r
725 flags = flags | F_1PR; /* store 1-proc */\r
726 its_1pr = 0; /* clear 1-proc */\r
727 }\r
728 if (op == OP_JSR) { /* JSR? */\r
729 ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */\r
730 WriteE (ea, FLPC); /* save flags+PC, exec */\r
731 JUMP (INCA (ea)); /* PC = ea + 1 */\r
732 set_newflags (0, FALSE); /* set new flags */\r
733 }\r
734 else if ((op == OP_JRST) && (ac == AC_XPCW)) { /* XPCW? */\r
735 ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */\r
736 WriteE (ea, XWD (flags, 0)); /* write flags, exec */\r
737 WriteE (ADDA (ea, 1), PC); /* write PC, exec */\r
738 rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */\r
739 rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */\r
740 JUMP (rs[1]); /* set new PC */\r
741 set_newflags (rs[0], FALSE); /* set new flags */\r
742 }\r
743 else ABORT (STOP_ILLINT); /* invalid instr */\r
744 pi_act = pi_act | pi_l2bit[qintr]; /* set level active */\r
745 pi_eval (); /* eval pi system */\r
746 pager_pi = FALSE; /* end of sequence */\r
747 if (sim_interval) sim_interval--; /* charge for instr */\r
748 continue;\r
749 } /* end if interrupt */\r
750 \r
751/* Traps fetch and execute an instruction from the current mode process table.\r
752 On the KS10, the fetch of the next instruction has started, and a page fail\r
753 trap on the instruction fetch takes precedence over the trap. During a trap,\r
754 flags are cleared before the execute, but if the execute aborts, they must\r
755 be restored. Also, the MUUO processor needs to know whether we are in a\r
756 trap sequence. Hence, trap in progress is recorded in pflgs, and the\r
757 traps for pager restoration are recorded in pager_flags.\r
758*/\r
759\r
760if (TSTF (F_T1 | F_T2) && PAGING) {\r
761 Read (pager_PC = PC, MM_CUR); /* test fetch */\r
762 pager_tc = TRUE; /* in a trap sequence */\r
763 pager_flags = flags; /* save flags */\r
764 ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE)\r
765 + GET_TRAPS (flags);\r
766 inst = ReadP (ea); /* get trap instr */\r
767 CLRF (F_T1 | F_T2); /* clear flags */\r
768 }\r
769\r
770/* Test for instruction breakpoint */\r
771\r
772else {\r
773 if (sim_brk_summ &&\r
774 sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */\r
775 ABORT (STOP_IBKPT); /* stop simulation */\r
776 }\r
777\r
778/* Ready (at last) to get an instruction */\r
779\r
780 inst = Read (pager_PC = PC, MM_CUR); /* get instruction */\r
781 INCPC; \r
782 sim_interval = sim_interval - 1;\r
783 }\r
784\r
785its_2pr = its_1pr; /* save 1-proc flag */\r
786\r
787/* Execute instruction. XCT and PXCT also return here. */\r
788\r
789XCT:\r
790op = GET_OP (inst); /* get opcode */\r
791ac = GET_AC (inst); /* get AC */\r
792for (indrct = inst, i = 0; i < ind_max; i++) { /* calc eff addr */\r
793 ea = GET_ADDR (indrct);\r
794 xr = GET_XR (indrct);\r
795 if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK;\r
796 if (TST_IND (indrct)) indrct = Read (ea, MM_EA);\r
797 else break;\r
798 }\r
799if (i >= ind_max)\r
800 ABORT (STOP_IND); /* too many ind? stop */\r
801if (hst_lnt) { /* history enabled? */\r
802 hst_p = (hst_p + 1); /* next entry */\r
803 if (hst_p >= hst_lnt) hst_p = 0;\r
804 hst[hst_p].pc = pager_PC | HIST_PC;\r
805 hst[hst_p].ea = ea;\r
806 hst[hst_p].ir = inst;\r
807 hst[hst_p].ac = AC(ac);\r
808 }\r
809switch (op) { /* case on opcode */\r
810\r
811/* UUO's (0000 - 0077) - checked against KS10 ucode */\r
812\r
813case 0000: if (stop_op0) { ABORT (STOP_ILLEG); }\r
814 goto MUUO;\r
815case 0001: /* local UUO's */\r
816case 0002:\r
817case 0003:\r
818case 0004:\r
819case 0005:\r
820case 0006:\r
821case 0007:\r
822case 0010:\r
823case 0011:\r
824case 0012:\r
825case 0013:\r
826case 0014:\r
827case 0015:\r
828case 0016:\r
829case 0017:\r
830case 0020:\r
831case 0021:\r
832case 0022:\r
833case 0023:\r
834case 0024:\r
835case 0025:\r
836case 0026:\r
837case 0027:\r
838case 0030:\r
839case 0031:\r
840case 0032:\r
841case 0033:\r
842case 0034:\r
843case 0035:\r
844case 0036:\r
845case 0037: Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */\r
846 inst = Read (041, MM_CUR); /* get new instr */\r
847 goto XCT;\r
848\r
849/* case 0040 - 0077: MUUO's, handled by default at end of case */\r
850\r
851/* Floating point, bytes, multiple precision (0100 - 0177) */\r
852\r
853/* case 0100: MUUO /* UJEN */\r
854/* case 0101: MUUO /* unassigned */\r
855case 0102: if (Q_ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */\r
856 inst = Read (ea, MM_OPND);\r
857 pflgs = pflgs | ac; goto XCT;\r
858 }\r
859 goto MUUO;\r
860case 0103: if (Q_ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */\r
861 inst = Read (ea, MM_OPND);\r
862 pflgs = pflgs | ac; goto XCT;\r
863 }\r
864 goto MUUO;\r
865/* case 0104: MUUO /* JSYS (T20) */\r
866case 0105: AC(ac) = adjsp (AC(ac), ea); break; /* ADJSP */\r
867/* case 0106: MUUO /* GFMP (KL)*/\r
868/* case 0107: MUUO /* GFDV (KL) */\r
869case 0110: RD2; dfad (ac, rs, 0); break; /* DFAD */\r
870case 0111: RD2; dfad (ac, rs, 1); break; /* DFSB */\r
871case 0112: RD2; dfmp (ac, rs); break; /* DFMP */\r
872case 0113: RD2; dfdv (ac, rs); break; /* DFDV */\r
873case 0114: RD2; dadd (ac, rs); break; /* DADD */\r
874case 0115: RD2; dsub (ac, rs); break; /* DSUB */\r
875case 0116: RD2; dmul (ac, rs); break; /* DMUL */\r
876case 0117: RD2; ddiv (ac, rs); break; /* DDIV */\r
877case 0120: RD2; S2AC; break; /* DMOVE */\r
878case 0121: RD2; DMOVN (rs); S2AC; DMOVNF; break; /* DMOVN */\r
879case 0122: RD; fix(ac, mb, 0); break; /* FIX */\r
880case 0123: st = xtend (ac, ea, pflgs); /* EXTEND */\r
881 rlog = 0; /* clear log */\r
882 switch (st) {\r
883 case XT_SKIP:\r
884 INCPC;\r
885 case XT_NOSK:\r
886 break;\r
887 default:\r
888 goto MUUO;\r
889 }\r
890 break;\r
891case 0124: G2AC; WR2; break; /* DMOVEM */\r
892case 0125: G2AC; DMOVN (rs); WR2; DMOVNF; break; /* DMOVNM */\r
893case 0126: RD; fix (ac, mb, 1); break; /* FIXR */\r
894case 0127: RD; AC(ac) = fltr (mb); break; /* FLTR */\r
895/* case 0130: MUUO /* UFA */\r
896/* case 0131: MUUO /* DFN */\r
897case 0132: AC(ac) = fsc (AC(ac), ea); break; /* FSC */\r
898case 0133: if (!ac) ibp (ea, pflgs); /* IBP */\r
899 else adjbp (ac, ea, pflgs); break;\r
900case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */\r
901case 0135: LDB; break; /* LDB */\r
902case 0136: CIBP; DPB; CLRF (F_FPD); break; /* IDBP */\r
903case 0137: DPB; break; /* DPB */\r
904case 0140: RD; AC(ac) = FAD (mb); break; /* FAD */\r
905/* case 0141: MUUO /* FADL */\r
906case 0142: RM; mb = FAD (mb); WR; break; /* FADM */\r
907case 0143: RM; AC(ac) = FAD (mb); WRAC; break; /* FADB */\r
908case 0144: RD; AC(ac) = FADR (mb); break; /* FADR */\r
909case 0145: AC(ac) = FADR (IMS); break; /* FADRI */\r
910case 0146: RM; mb = FADR (mb); WR; break; /* FADRM */\r
911case 0147: RM; AC(ac) = FADR (mb); WRAC; break; /* FADRB */\r
912case 0150: RD; AC(ac) = FSB (mb); break; /* FSB */\r
913/* case 0151: MUUO /* FSBL */\r
914case 0152: RM; mb = FSB (mb); WR; break; /* FSBM */\r
915case 0153: RM; AC(ac) = FSB (mb); WRAC; break; /* FSBB */\r
916case 0154: RD; AC(ac) = FSBR (mb); break; /* FSBR */\r
917case 0155: AC(ac) = FSBR (IMS); break; /* FSBRI */\r
918case 0156: RM; mb = FSBR (mb); WR; break; /* FSBRM */\r
919case 0157: RM; AC(ac) = FSBR (mb); WRAC; break; /* FSBRB */\r
920case 0160: RD; AC(ac) = FMP (mb); break; /* FMP */\r
921/* case 0161: MUUO /* FMPL */\r
922case 0162: RM; mb = FMP (mb); WR; break; /* FMPM */\r
923case 0163: RM; AC(ac) = FMP (mb); WRAC; break; /* FMPB */\r
924case 0164: RD; AC(ac) = FMPR (mb); break; /* FMPR */\r
925case 0165: AC(ac) = FMPR (IMS); break; /* FMPRI */\r
926case 0166: RM; mb = FMPR (mb); WR; break; /* FMPRM */\r
927case 0167: RM; AC(ac) = FMPR (mb); WRAC; break; /* FMPRB */\r
928case 0170: RD; if (FDV (mb)) S1AC; break; /* FDV */\r
929/* case 0171: MUUO /* FDVL */\r
930case 0172: RM; if (FDV (mb)) WR1; break; /* FDVM */\r
931case 0173: RM; if (FDV (mb)) { S1AC; WRAC; } break; /* FDVB */\r
932case 0174: RD; if (FDVR (mb)) S1AC; break; /* FDVR */\r
933case 0175: if (FDVR (IMS)) S1AC; break; /* FDVRI */\r
934case 0176: RM; if (FDVR (mb)) WR1; break; /* FDVRM */\r
935case 0177: RM; if (FDVR (mb)) { S1AC; WRAC; } break; /* FDVRB */\r
936\r
937/* Move, arithmetic, shift, and jump (0200 - 0277)\r
938\r
939 Note that instructions which modify the flags and store a\r
940 result in memory must prove the writeability of the result\r
941 location before modifying the flags. Also, 0247 and 0257,\r
942 if not implemented, are nops, not MUUO's.\r
943*/\r
944\r
945case 0200: RDAC; break; /* MOVE */\r
946case 0201: AC(ac) = ea; break; /* MOVEI */\r
947case 0202: WRAC; break; /* MOVEM */\r
948case 0203: RM; LAC; break; /* MOVES */\r
949case 0204: RD; AC(ac) = SWP (mb); break; /* MOVS */\r
950case 0205: AC(ac) = IMS; break; /* MOVSI */\r
951case 0206: mb = SWP (AC(ac)); WR; break; /* MOVSM */\r
952case 0207: RM; mb = SWP (mb); WR; LAC; break; /* MOVSS */\r
953case 0210: RD; AC(ac) = MOVN (mb); break; /* MOVN */\r
954case 0211: AC(ac) = NEG (IM); /* MOVNI */\r
955 if (AC(ac) == 0) SETF (F_C0 | F_C1); break;\r
956case 0212: RM; mb = MOVN (AC(ac)); WR; break; /* MOVNM */\r
957case 0213: RM; mb = MOVN (mb); WR; LAC; break; /* MOVNS */\r
958case 0214: RD; AC(ac) = MOVM (mb); break; /* MOVM */\r
959case 0215: AC(ac) = ea; break; /* MOVMI */\r
960case 0216: RM; mb = MOVM (AC(ac)); WR; break; /* MOVMM */\r
961case 0217: RM; mb = MOVM (mb); WR; LAC; break; /* MOVMS */\r
962case 0220: RD; AC(ac) = IMUL (mb); break; /* IMUL */\r
963case 0221: AC(ac) = IMUL (IM); break; /* IMULI */\r
964case 0222: RM; mb = IMUL (mb); WR; break; /* IMULM */\r
965case 0223: RM; AC(ac) = IMUL (mb); WRAC; break; /* IMULB */\r
966case 0224: RD; MUL (mb); S2AC; break; /* MUL */\r
967case 0225: MUL (IM); S2AC; break; /* MULI */\r
968case 0226: RM; MUL (mb); WR1; break; /* MULM */\r
969case 0227: RM; MUL (mb); WR1; S2AC; break; /* MULB */\r
970case 0230: RD; if (IDIV (mb)) S2AC; break; /* IDIV */\r
971case 0231: if (IDIV (IM)) S2AC; break; /* IDIVI */\r
972case 0232: RM; if (IDIV (mb)) WR1; break; /* IDIVM */\r
973case 0233: RM; if (IDIV (mb)) { WR1; S2AC; } break; /* IDIVB */\r
974case 0234: RD; if (DIV (mb)) S2AC; break; /* DIV */\r
975case 0235: if (DIV (IM)) S2AC; break; /* DIVI */\r
976case 0236: RM; if (DIV (mb)) WR1; break; /* DIVM */\r
977case 0237: RM; if (DIV (mb)) { WR1; S2AC; } break; /* DIVB */\r
978case 0240: AC(ac) = ash (AC(ac), ea); break; /* ASH */\r
979case 0241: AC(ac) = rot (AC(ac), ea); break; /* ROT */\r
980case 0242: AC(ac) = lsh (AC(ac), ea); break; /* LSH */\r
981case 0243: AC(P1) = jffo (AC(ac)); /* JFFO */\r
982 if (AC(ac)) JUMP (ea); break;\r
983case 0244: ashc (ac, ea); break; /* ASHC */\r
984case 0245: rotc (ac, ea); break; /* ROTC */\r
985case 0246: lshc (ac, ea); break; /* LSHC */\r
986case 0247: if (Q_ITS) circ (ac, ea); break; /* (ITS) CIRC */\r
987case 0250: RM; WRAC; AC(ac) = mb; break; /* EXCH */\r
988case 0251: blt (ac, ea, pflgs); break; /* BLT */\r
989case 0252: AOBAC; if (TGE (AC(ac))) JUMP (ea); break; /* AOBJP */\r
990case 0253: AOBAC; if (TL (AC(ac))) JUMP (ea); break; /* AOBJN */\r
991/* case 0254: /* shown later /* JRST */\r
992case 0255: if (flags & (ac << 14)) { /* JFCL */\r
993 JUMP (ea);\r
994 CLRF (ac << 14);\r
995 }\r
996 break;\r
997case 0256: if (xct_cnt++ >= xct_max) /* XCT */\r
998 ABORT (STOP_XCT);\r
999 inst = Read (ea, MM_OPND);\r
1000 if (ac && !TSTF (F_USR) && !Q_ITS)\r
1001 pflgs = pflgs | ac;\r
1002 goto XCT;\r
1003case 0257: if (Q_ITS) goto MUUO; /* MAP */\r
1004 AC(ac) = map (ea, MM_OPND); break;\r
1005case 0260: WRP (FLPC); AOBAC; /* PUSHJ */\r
1006 SUBJ (ea); PUSHF; break;\r
1007case 0261: RD; WRP (mb); AOBAC; PUSHF; break; /* PUSH */\r
1008case 0262: RDP; WR; SOBAC; POPF; break; /* POP */\r
1009case 0263: RDP; JUMP (mb); SOBAC; POPF; break; /* POPJ */\r
1010case 0264: Write (ea, FLPC, MM_OPND); /* JSR */\r
1011 SUBJ (INCR (ea)); break;\r
1012case 0265: AC(ac) = FLPC; SUBJ (ea); break; /* JSP */\r
1013case 0266: WRAC; AC(ac) = XWD (ea, PC); /* JSA */\r
1014 JUMP (INCR (ea)); break;\r
1015case 0267: AC(ac) = Read ((a10) LRZ (AC(ac)), MM_OPND);/* JRA */\r
1016 JUMP (ea); break;\r
1017case 0270: RD; AC(ac) = ADD (mb); break; /* ADD */\r
1018case 0271: AC(ac) = ADD (IM); break; /* ADDI */\r
1019case 0272: RM; mb = ADD (mb); WR; break; /* ADDM */\r
1020case 0273: RM; AC(ac) = ADD (mb); WRAC; break; /* ADDB */\r
1021case 0274: RD; AC(ac) = SUB (mb); break; /* SUB */\r
1022case 0275: AC(ac) = SUB (IM); break; /* SUBI */\r
1023case 0276: RM; mb = SUB (mb); WR; break; /* SUBM */\r
1024case 0277: RM; AC(ac) = SUB (mb); WRAC; break; /* SUBB */\r
1025\r
1026/* Compare, jump, skip instructions (0300 - 0377) - checked against KS10 ucode */\r
1027\r
1028case 0300: break; /* CAI */\r
1029case 0301: if (CL (IM)) INCPC; break; /* CAIL */\r
1030case 0302: if (CE (IM)) INCPC; break; /* CAIE */\r
1031case 0303: if (CLE (IM)) INCPC; break; /* CAILE */\r
1032case 0304: INCPC; break; /* CAIA */\r
1033case 0305: if (CGE (IM)) INCPC; break; /* CAIGE */\r
1034case 0306: if (CN (IM)) INCPC; break; /* CAIN */\r
1035case 0307: if (CG (IM)) INCPC; break; /* CAIG */\r
1036case 0310: RD; break; /* CAM */\r
1037case 0311: RD; if (CL (mb)) INCPC; break; /* CAML */\r
1038case 0312: RD; if (CE (mb)) INCPC; break; /* CAME */\r
1039case 0313: RD; if (CLE (mb)) INCPC; break; /* CAMLE */\r
1040case 0314: RD; INCPC; break; /* CAMA */\r
1041case 0315: RD; if (CGE (mb)) INCPC; break; /* CAMGE */\r
1042case 0316: RD; if (CN (mb)) INCPC; break; /* CAMN */\r
1043case 0317: RD; if (CG (mb)) INCPC; break; /* CAMG */\r
1044case 0320: break; /* JUMP */\r
1045case 0321: if (TL (AC(ac))) JUMP (ea); break; /* JUMPL */\r
1046case 0322: if (TE (AC(ac))) JUMP (ea); break; /* JUMPE */\r
1047case 0323: if (TLE( AC(ac))) JUMP (ea); break; /* JUMPLE */\r
1048case 0324: JUMP (ea); break; /* JUMPA */\r
1049case 0325: if (TGE (AC(ac))) JUMP (ea); break; /* JUMPGE */\r
1050case 0326: if (TN (AC(ac))) JUMP (ea); break; /* JUMPN */\r
1051case 0327: if (TG (AC(ac))) JUMP (ea); break; /* JUMPG */\r
1052case 0330: RD; LAC; break; /* SKIP */\r
1053case 0331: RD; LAC; if (TL (mb)) INCPC; break; /* SKIPL */\r
1054case 0332: RD; LAC; if (TE (mb)) INCPC; break; /* SKIPE */\r
1055case 0333: RD; LAC; if (TLE (mb)) INCPC; break; /* SKIPLE */\r
1056case 0334: RD; LAC; INCPC; break; /* SKIPA */\r
1057case 0335: RD; LAC; if (TGE (mb)) INCPC; break; /* SKIPGE */\r
1058case 0336: RD; LAC; if (TN (mb)) INCPC; break; /* SKIPN */\r
1059case 0337: RD; LAC; if (TG (mb)) INCPC; break; /* SKIPG */\r
1060case 0340: AOJ; break; /* AOJ */\r
1061case 0341: AOJ; if (TL (AC(ac))) JUMP (ea); break; /* AOJL */\r
1062case 0342: AOJ; if (TE (AC(ac))) JUMP (ea); break; /* AOJE */\r
1063case 0343: AOJ; if (TLE (AC(ac))) JUMP (ea); break; /* AOJLE */\r
1064case 0344: AOJ; JUMP(ea); /* AOJA */\r
1065 if (Q_ITS && Q_IDLE && /* ITS idle? */\r
1066 TSTF (F_USR) && (pager_PC == 017) && /* user mode, loc 17? */\r
1067 (ac == 0) && (ea == 017)) /* AOJA 0,17? */\r
1068 sim_idle (0, FALSE);\r
1069 break;\r
1070case 0345: AOJ; if (TGE (AC(ac))) JUMP (ea); break; /* AOJGE */\r
1071case 0346: AOJ; if (TN (AC(ac))) JUMP (ea); break; /* AOJN */\r
1072case 0347: AOJ; if (TG (AC(ac))) JUMP (ea); break; /* AOJG */\r
1073case 0350: AOS; break; /* AOS */\r
1074case 0351: AOS; if (TL (mb)) INCPC; break; /* AOSL */\r
1075case 0352: AOS; if (TE (mb)) INCPC; break; /* AOSE */\r
1076case 0353: AOS; if (TLE (mb)) INCPC; break; /* AOSLE */\r
1077case 0354: AOS; INCPC; break; /* AOSA */\r
1078case 0355: AOS; if (TGE (mb)) INCPC; break; /* AOSGE */\r
1079case 0356: AOS; if (TN (mb)) INCPC; break; /* AOSN */\r
1080case 0357: AOS; if (TG (mb)) INCPC; break; /* AOSG */\r
1081case 0360: SOJ; break; /* SOJ */\r
1082case 0361: SOJ; if (TL (AC(ac))) JUMP (ea); break; /* SOJL */\r
1083case 0362: SOJ; if (TE (AC(ac))) JUMP (ea); break; /* SOJE */\r
1084case 0363: SOJ; if (TLE (AC(ac))) JUMP (ea); break; /* SOJLE */\r
1085case 0364: SOJ; JUMP(ea); break; /* SOJA */\r
1086case 0365: SOJ; if (TGE (AC(ac))) JUMP (ea); break; /* SOJGE */\r
1087case 0366: SOJ; if (TN (AC(ac))) JUMP (ea); break; /* SOJN */\r
1088case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); /* SOJG */\r
1089 if ((ea == pager_PC) && Q_IDLE) { /* to self, idle enab? */\r
1090 extern int32 tmr_poll;\r
1091 if ((ac == 6) && (ea == 1) && /* SOJG 6,1? */\r
1092 TSTF (F_USR) && Q_T10) /* T10, user mode? */\r
1093 sim_idle (0, FALSE);\r
1094 else if (!t20_idlelock && /* interlock off? */\r
1095 (ac == 2) && (ea == 3) && /* SOJG 2,3? */\r
1096 !TSTF (F_USR) && Q_T20 && /* T20, mon mode? */\r
1097 (sim_interval > (tmr_poll >> 1))) { /* >= half clock? */\r
1098 t20_idlelock = 1; /* set interlock */\r
1099 if (sim_os_ms_sleep (1)) /* sleep 1ms */\r
1100 sim_interval = 0; /* if ok, sched event */\r
1101 }\r
1102 } \r
1103 break;\r
1104case 0370: SOS; break; /* SOS */\r
1105case 0371: SOS; if (TL (mb)) INCPC; break; /* SOSL */\r
1106case 0372: SOS; if (TE (mb)) INCPC; break; /* SOSE */\r
1107case 0373: SOS; if (TLE (mb)) INCPC; break; /* SOSLE */\r
1108case 0374: SOS; INCPC; break; /* SOSA */\r
1109case 0375: SOS; if (TGE (mb)) INCPC; break; /* SOSGE */\r
1110case 0376: SOS; if (TN (mb)) INCPC; break; /* SOSN */\r
1111case 0377: SOS; if (TG (mb)) INCPC; break; /* SOSG */\r
1112\r
1113/* Boolean instructions (0400 - 0477) - checked against KS10 ucode\r
1114\r
1115 Note that for boolean B, the initial read checks writeability of\r
1116 the memory operand; hence, it is safe to modify the AC.\r
1117*/\r
1118\r
1119case 0400: AC(ac) = 0; break; /* SETZ */\r
1120case 0401: AC(ac) = 0; break; /* SETZI */\r
1121case 0402: mb = 0; WR; break; /* SETZM */\r
1122case 0403: mb = 0; WR; AC(ac) = 0; break; /* SETZB */\r
1123case 0404: RD; AC(ac) = AND (mb); break; /* AND */\r
1124case 0405: AC(ac) = AND (IM); break; /* ANDI */\r
1125case 0406: RM; mb = AND (mb); WR; break; /* ANDM */\r
1126case 0407: RM; AC(ac) = AND (mb); WRAC; break; /* ANDB */\r
1127case 0410: RD; AC(ac) = ANDCA (mb); break; /* ANDCA */\r
1128case 0411: AC(ac) = ANDCA (IM); break; /* ANDCAI */\r
1129case 0412: RM; mb = ANDCA (mb); WR; break; /* ANDCAM */\r
1130case 0413: RM; AC(ac) = ANDCA (mb); WRAC; break; /* ANDCAB */\r
1131case 0414: RDAC; break; /* SETM */\r
1132case 0415: AC(ac) = ea; break; /* SETMI */\r
1133case 0416: RM; WR; break; /* SETMM */\r
1134case 0417: RMAC; WRAC; break; /* SETMB */\r
1135case 0420: RD; AC(ac) = ANDCM (mb); break; /* ANDCM */\r
1136case 0421: AC(ac) = ANDCM (IM); break; /* ANDCMI */\r
1137case 0422: RM; mb = ANDCM (mb); WR; break; /* ANDCMM */\r
1138case 0423: RM; AC(ac) = ANDCM (mb); WRAC; break; /* ANDCMB */\r
1139case 0424: break; /* SETA */\r
1140case 0425: break; /* SETAI */\r
1141case 0426: WRAC; break; /* SETAM */\r
1142case 0427: WRAC; break; /* SETAB */\r
1143case 0430: RD; AC(ac) = XOR (mb); break; /* XOR */\r
1144case 0431: AC(ac) = XOR (IM); break; /* XORI */\r
1145case 0432: RM; mb = XOR (mb); WR; break; /* XORM */\r
1146case 0433: RM; AC(ac) = XOR (mb); WRAC; break; /* XORB */\r
1147case 0434: RD; AC(ac) = IOR (mb); break; /* IOR */\r
1148case 0435: AC(ac) = IOR (IM); break; /* IORI */\r
1149case 0436: RM; mb = IOR (mb); WR; break; /* IORM */\r
1150case 0437: RM; AC(ac) = IOR (mb); WRAC; break; /* IORB */\r
1151case 0440: RD; AC(ac) = ANDCB (mb); break; /* ANDCB */\r
1152case 0441: AC(ac) = ANDCB (IM); break; /* ANDCBI */\r
1153case 0442: RM; mb = ANDCB (mb); WR; break; /* ANDCBM */\r
1154case 0443: RM; AC(ac) = ANDCB (mb); WRAC; break; /* ANDCBB */\r
1155case 0444: RD; AC(ac) = EQV (mb); break; /* EQV */\r
1156case 0445: AC(ac) = EQV (IM); break; /* EQVI */\r
1157case 0446: RM; mb = EQV (mb); WR; break; /* EQVM */\r
1158case 0447: RM; AC(ac) = EQV (mb); WRAC; break; /* EQVB */\r
1159case 0450: RD; AC(ac) = SETCA (mb); break; /* SETCA */\r
1160case 0451: AC(ac) = SETCA (IM); break; /* SETCAI */\r
1161case 0452: RM; mb = SETCA (mb); WR; break; /* SETCAM */\r
1162case 0453: RM; AC(ac) = SETCA (mb); WRAC; break; /* SETCAB */\r
1163case 0454: RD; AC(ac) = ORCA (mb); break; /* ORCA */\r
1164case 0455: AC(ac) = ORCA (IM); break; /* ORCAI */\r
1165case 0456: RM; mb = ORCA (mb); WR; break; /* ORCAM */\r
1166case 0457: RM; AC(ac) = ORCA (mb); WRAC; break; /* ORCAB */\r
1167case 0460: RD; AC(ac) = SETCM (mb); break; /* SETCM */\r
1168case 0461: AC(ac) = SETCM (IM); break; /* SETCMI */\r
1169case 0462: RM; mb = SETCM (mb); WR; break; /* SETCMM */\r
1170case 0463: RM; AC(ac) = SETCM (mb); WRAC; break; /* SETCMB */\r
1171case 0464: RD; AC(ac) = ORCM (mb); break; /* ORCM */\r
1172case 0465: AC(ac) = ORCM (IM); break; /* ORCMI */\r
1173case 0466: RM; mb = ORCM (mb); WR; break; /* ORCMM */\r
1174case 0467: RM; AC(ac) = ORCM (mb); WRAC; break; /* ORCMB */\r
1175case 0470: RD; AC(ac) = ORCB (mb); break; /* ORCB */\r
1176case 0471: AC(ac) = ORCB (IM); break; /* ORCBI */\r
1177case 0472: RM; mb = ORCB (mb); WR; break; /* ORCBM */\r
1178case 0473: RM; AC(ac) = ORCB (mb); WRAC; break; /* ORCBB */\r
1179case 0474: AC(ac) = ONES; break; /* SETO */\r
1180case 0475: AC(ac) = ONES; break; /* SETOI */\r
1181case 0476: mb = ONES; WR; break; /* SETOM */\r
1182case 0477: mb = ONES; WR; AC(ac) = ONES; break; /* SETOB */\r
1183\r
1184/* Halfword instructions (0500 - 0577) - checked against KS10 ucode */\r
1185\r
1186case 0500: RD; AC(ac) = LL (mb, AC(ac)); break; /* HLL */\r
1187case 0501: AC(ac) = LL (IM, AC(ac)); break; /* HLLI */\r
1188case 0502: RM; mb = LL (AC(ac), mb); WR; break; /* HLLM */\r
1189case 0503: RM; mb = LL (mb, mb); WR; LAC; break; /* HLLS */\r
1190case 0504: RD; AC(ac) = RL (mb, AC(ac)); break; /* HRL */\r
1191case 0505: AC(ac) = RL (IM, AC(ac)); break; /* HRLI */\r
1192case 0506: RM; mb = RL (AC(ac), mb); WR; break; /* HRLM */\r
1193case 0507: RM; mb = RL (mb, mb); WR; LAC; break; /* HRLS */\r
1194case 0510: RD; AC(ac) = LLZ (mb); break; /* HLLZ */\r
1195case 0511: AC(ac) = LLZ (IM); break; /* HLLZI */\r
1196case 0512: mb = LLZ (AC(ac)); WR; break; /* HLLZM */\r
1197case 0513: RM; mb = LLZ (mb); WR; LAC; break; /* HLLZS */\r
1198case 0514: RD; AC(ac) = RLZ (mb); break; /* HRLZ */\r
1199case 0515: AC(ac) = RLZ (IM); break; /* HRLZI */\r
1200case 0516: mb = RLZ (AC(ac)); WR; break; /* HRLZM */\r
1201case 0517: RM; mb = RLZ (mb); WR; LAC; break; /* HRLZS */\r
1202case 0520: RD; AC(ac) = LLO (mb); break; /* HLLO */\r
1203case 0521: AC(ac) = LLO (IM); break; /* HLLOI */\r
1204case 0522: mb = LLO (AC(ac)); WR; break; /* HLLOM */\r
1205case 0523: RM; mb = LLO (mb); WR; LAC; break; /* HLLOS */\r
1206case 0524: RD; AC(ac) = RLO (mb); break; /* HRLO */\r
1207case 0525: AC(ac) = RLO (IM); break; /* HRLOI */\r
1208case 0526: mb = RLO (AC(ac)); WR; break; /* HRLOM */\r
1209case 0527: RM; mb = RLO (mb); WR; LAC; break; /* HRLOS */\r
1210case 0530: RD; AC(ac) = LLE (mb); break; /* HLLE */\r
1211case 0531: AC(ac) = LLE (IM); break; /* HLLEI */\r
1212case 0532: mb = LLE (AC(ac)); WR; break; /* HLLEM */\r
1213case 0533: RM; mb = LLE (mb); WR; LAC; break; /* HLLES */\r
1214case 0534: RD; AC(ac) = RLE (mb); break; /* HRLE */\r
1215case 0535: AC(ac) = RLE (IM); break; /* HRLEI */\r
1216case 0536: mb = RLE (AC(ac)); WR; break; /* HRLEM */\r
1217case 0537: RM; mb = RLE (mb); WR; LAC; break; /* HRLES */\r
1218case 0540: RD; AC(ac) = RR (mb, AC(ac)); break; /* HRR */\r
1219case 0541: AC(ac) = RR (IM, AC(ac)); break; /* HRRI */\r
1220case 0542: RM; mb = RR (AC(ac), mb); WR; break; /* HRRM */\r
1221case 0543: RM; mb = RR (mb, mb); WR; LAC; break; /* HRRS */\r
1222case 0544: RD; AC(ac) = LR (mb, AC(ac)); break; /* HLR */\r
1223case 0545: AC(ac) = LR (IM, AC(ac)); break; /* HLRI */\r
1224case 0546: RM; mb = LR (AC(ac), mb); WR; break; /* HLRM */\r
1225case 0547: RM; mb = LR (mb, mb); WR; LAC; break; /* HLRS */\r
1226case 0550: RD; AC(ac) = RRZ (mb); break; /* HRRZ */\r
1227case 0551: AC(ac) = RRZ (IM); break; /* HRRZI */\r
1228case 0552: mb = RRZ (AC(ac)); WR; break; /* HRRZM */\r
1229case 0553: RM; mb = RRZ(mb); WR; LAC; break; /* HRRZS */\r
1230case 0554: RD; AC(ac) = LRZ (mb); break; /* HLRZ */\r
1231case 0555: AC(ac) = LRZ (IM); break; /* HLRZI */\r
1232case 0556: mb = LRZ (AC(ac)); WR; break; /* HLRZM */\r
1233case 0557: RM; mb = LRZ (mb); WR; LAC; break; /* HLRZS */\r
1234case 0560: RD; AC(ac) = RRO (mb); break; /* HRRO */\r
1235case 0561: AC(ac) = RRO (IM); break; /* HRROI */\r
1236case 0562: mb = RRO (AC(ac)); WR; break; /* HRROM */\r
1237case 0563: RM; mb = RRO (mb); WR; LAC; break; /* HRROS */\r
1238case 0564: RD; AC(ac) = LRO (mb); break; /* HLRO */\r
1239case 0565: AC(ac) = LRO (IM); break; /* HLROI */\r
1240case 0566: mb = LRO (AC(ac)); WR; break; /* HLROM */\r
1241case 0567: RM; mb = LRO (mb); WR; LAC; break; /* HLROS */\r
1242case 0570: RD; AC(ac) = RRE (mb); break; /* HRRE */\r
1243case 0571: AC(ac) = RRE (IM); break; /* HRREI */\r
1244case 0572: mb = RRE (AC(ac)); WR; break; /* HRREM */\r
1245case 0573: RM; mb = RRE (mb); WR; LAC; break; /* HRRES */\r
1246case 0574: RD; AC(ac) = LRE (mb); break; /* HLRE */\r
1247case 0575: AC(ac) = LRE (IM); break; /* HLREI */\r
1248case 0576: mb = LRE (AC(ac)); WR; break; /* HLREM */\r
1249case 0577: RM; mb = LRE (mb); WR; LAC; break; /* HLRES */\r
1250\r
1251/* Test instructions (0600 - 0677) - checked against KS10 ucode\r
1252 In the KS10 ucode, TDN and TSN do not fetch an operand; the Processor\r
1253 Reference Manual describes them as NOPs that reference memory.\r
1254*/\r
1255\r
1256case 0600: break; /* TRN */\r
1257case 0601: break; /* TLN */\r
1258case 0602: TR_; T__E; break; /* TRNE */\r
1259case 0603: TL_; T__E; break; /* TLNE */\r
1260case 0604: T__A; break; /* TRNA */\r
1261case 0605: T__A; break; /* TLNA */\r
1262case 0606: TR_; T__N; break; /* TRNN */\r
1263case 0607: TL_; T__N; break; /* TLNN */\r
1264case 0610: TD_; break; /* TDN */\r
1265case 0611: TS_; break; /* TSN */\r
1266case 0612: TD_; T__E; break; /* TDNE */\r
1267case 0613: TS_; T__E; break; /* TSNE */\r
1268case 0614: TD_; T__A; break; /* TDNA */\r
1269case 0615: TS_; T__A; break; /* TSNA */\r
1270case 0616: TD_; T__N; break; /* TDNN */\r
1271case 0617: TS_; T__N; break; /* TSNN */\r
1272case 0620: TR_; T_Z; break; /* TRZ */\r
1273case 0621: TL_; T_Z; break; /* TLZ */\r
1274case 0622: TR_; T__E; T_Z; break; /* TRZE */\r
1275case 0623: TL_; T__E; T_Z; break; /* TLZE */\r
1276case 0624: TR_; T__A; T_Z; break; /* TRZA */\r
1277case 0625: TL_; T__A; T_Z; break; /* TLZA */\r
1278case 0626: TR_; T__N; T_Z; break; /* TRZN */\r
1279case 0627: TL_; T__N; T_Z; break; /* TLZN */\r
1280case 0630: TD_; T_Z; break; /* TDZ */\r
1281case 0631: TS_; T_Z; break; /* TSZ */\r
1282case 0632: TD_; T__E; T_Z; break; /* TDZE */\r
1283case 0633: TS_; T__E; T_Z; break; /* TSZE */\r
1284case 0634: TD_; T__A; T_Z; break; /* TDZA */\r
1285case 0635: TS_; T__A; T_Z; break; /* TSZA */\r
1286case 0636: TD_; T__N; T_Z; break; /* TDZN */\r
1287case 0637: TS_; T__N; T_Z; break; /* TSZN */\r
1288case 0640: TR_; T_C; break; /* TRC */\r
1289case 0641: TL_; T_C; break; /* TLC */\r
1290case 0642: TR_; T__E; T_C; break; /* TRCE */\r
1291case 0643: TL_; T__E; T_C; break; /* TLCE */\r
1292case 0644: TR_; T__A; T_C; break; /* TRCA */\r
1293case 0645: TL_; T__A; T_C; break; /* TLCA */\r
1294case 0646: TR_; T__N; T_C; break; /* TRCN */\r
1295case 0647: TL_; T__N; T_C; break; /* TLCN */\r
1296case 0650: TD_; T_C; break; /* TDC */\r
1297case 0651: TS_; T_C; break; /* TSC */\r
1298case 0652: TD_; T__E; T_C; break; /* TDCE */\r
1299case 0653: TS_; T__E; T_C; break; /* TSCE */\r
1300case 0654: TD_; T__A; T_C; break; /* TDCA */\r
1301case 0655: TS_; T__A; T_C; break; /* TSCA */\r
1302case 0656: TD_; T__N; T_C; break; /* TDCN */\r
1303case 0657: TS_; T__N; T_C; break; /* TSCN */\r
1304case 0660: TR_; T_O; break; /* TRO */\r
1305case 0661: TL_; T_O; break; /* TLO */\r
1306case 0662: TR_; T__E; T_O; break; /* TROE */\r
1307case 0663: TL_; T__E; T_O; break; /* TLOE */\r
1308case 0664: TR_; T__A; T_O; break; /* TROA */\r
1309case 0665: TL_; T__A; T_O; break; /* TLOA */\r
1310case 0666: TR_; T__N; T_O; break; /* TRON */\r
1311case 0667: TL_; T__N; T_O; break; /* TLON */\r
1312case 0670: TD_; T_O; break; /* TDO */\r
1313case 0671: TS_; T_O; break; /* TSO */\r
1314case 0672: TD_; T__E; T_O; break; /* TDOE */\r
1315case 0673: TS_; T__E; T_O; break; /* TSOE */\r
1316case 0674: TD_; T__A; T_O; break; /* TDOA */\r
1317case 0675: TS_; T__A; T_O; break; /* TSOA */\r
1318case 0676: TD_; T__N; T_O; break; /* TDON */\r
1319case 0677: TS_; T__N; T_O; break; /* TSON */\r
1320\r
1321/* I/O instructions (0700 - 0777)\r
1322\r
1323 Only the defined I/O instructions have explicit case labels;\r
1324 the rest default to unimplemented (monitor UUO). Note that \r
1325 710-715 and 720-725 have different definitions under ITS and\r
1326 use normal effective addresses instead of the special address\r
1327 calculation required by TOPS-10 and TOPS-20.\r
1328*/\r
1329\r
1330case 0700: IO7 (io700i, io700d); break; /* I/O 0 */\r
1331case 0701: IO7 (io701i, io701d); break; /* I/O 1 */\r
1332case 0702: IO7 (io702i, io702d); break; /* I/O 2 */\r
1333case 0704: IOC; AC(ac) = Read (ea, OPND_PXCT); break; /* UMOVE */\r
1334case 0705: IOC; Write (ea, AC(ac), OPND_PXCT); break; /* UMOVEM */\r
1335case 0710: IOA; if (io710 (ac, ea)) INCPC; break; /* TIOE, IORDI */\r
1336case 0711: IOA; if (io711 (ac, ea)) INCPC; break; /* TION, IORDQ */\r
1337case 0712: IOAM; AC(ac) = io712 (ea); break; /* RDIO, IORD */\r
1338case 0713: IOAM; io713 (AC(ac), ea); break; /* WRIO, IOWR */\r
1339case 0714: IOA; io714 (AC(ac), ea); break; /* BSIO, IOWRI */\r
1340case 0715: IOA; io715 (AC(ac), ea); break; /* BCIO, IOWRQ */\r
1341case 0716: IOC; bltu (ac, ea, pflgs, 0); break; /* BLTBU */\r
1342case 0717: IOC; bltu (ac, ea, pflgs, 1); break; /* BLTUB */\r
1343case 0720: IOA; if (io720 (ac, ea)) INCPC; break; /* TIOEB, IORDBI */\r
1344case 0721: IOA; if (io721 (ac, ea)) INCPC; break; /* TIONB, IORDBQ */\r
1345case 0722: IOAM; AC(ac) = io722 (ea); break; /* RDIOB, IORDB */\r
1346case 0723: IOAM; io723 (AC(ac), ea); break; /* WRIOB, IOWRB */\r
1347case 0724: IOA; io724 (AC(ac), ea); break; /* BSIOB, IOWRBI */\r
1348case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */\r
1349\r
1350/* If undefined, monitor UUO - checked against KS10 ucode\r
1351 The KS10 implements a much more limited version of MUUO flag handling.\r
1352 In the KS10, the trap ucode checks for opcodes 000-077. If the opcode\r
1353 is in that range, the trap flags are not cleared. Instead, the MUUO\r
1354 microcode stores the flags with traps cleared, and uses the trap flags\r
1355 to determine how to vector. Thus, MUUO's >= 100 will vector incorrectly.\r
1356*/\r
1357\r
1358default:\r
1359MUUO:\r
1360 its_2pr = 0; /* clear trap */\r
1361 if (T20PAG) { /* TOPS20 paging? */\r
1362 int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18));\r
1363 WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */\r
1364 flags & ~(F_T2 | F_T1), tf)); /* traps clear */\r
1365 WriteP (upta + UPT_MUPC, PC); /* store PC */\r
1366 WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */\r
1367 WriteP (upta + UPT_T20_CTX, UBRWORD); /* store context */\r
1368 }\r
1369 else { /* TOPS10/ITS */\r
1370 WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */\r
1371 WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */\r
1372 flags & ~(F_T2 | F_T1), PC)); /* traps clear */\r
1373 WriteP (upta + UPT_T10_CTX, UBRWORD); /* store context */\r
1374 }\r
1375 ea = upta + (TSTF (F_USR)? UPT_UNPC: UPT_ENPC) +\r
1376 (pager_tc? UPT_NPCT: 0); /* calculate vector */\r
1377 mb = ReadP (ea); /* new flags, PC */\r
1378 JUMP (mb); /* set new PC */\r
1379 if (TSTF (F_USR)) mb = mb | XWD (F_UIO, 0); /* set PCU */\r
1380 set_newflags (mb, FALSE); /* set new flags */\r
1381 break;\r
1382\r
1383/* JRST - checked against KS10 ucode\r
1384 Differences from the KS10: the KS10\r
1385 - (JRSTF, JEN) refetches the base instruction from PC - 1\r
1386 - (XJEN) dismisses interrupt before reading the new flags and PC\r
1387 - (XPCW) writes the old flags and PC before reading the new\r
1388 ITS microcode includes extended JRST's, although they are not used\r
1389*/\r
1390\r
1391case 0254: /* JRST */\r
1392 i = jrst_tab[ac]; /* get subop flags */\r
1393 if ((i == 0) || ((i == JRST_E) && TSTF (F_USR)) ||\r
1394 ((i == JRST_UIO) && TSTF (F_USR) && !TSTF (F_UIO)))\r
1395 goto MUUO; /* not legal */\r
1396 switch (ac) { /* case on subopcode */\r
1397\r
1398 case 000: /* JRST 0 = jump */\r
1399 case 001: /* JRST 1 = portal */\r
1400 JUMP (ea);\r
1401 break;\r
1402\r
1403 case 002: /* JRST 2 = JRSTF */\r
1404 mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */\r
1405 JUMP (ea); /* set new PC */\r
1406 set_newflags (mb, TRUE); /* set new flags */\r
1407 break;\r
1408\r
1409 case 004: /* JRST 4 = halt */\r
1410 JUMP (ea); /* old_PC = halt + 1 */\r
1411 pager_PC = PC; /* force right PC */\r
1412 ABORT (STOP_HALT); /* known to be exec */\r
1413 break;\r
1414\r
1415 case 005: /* JRST 5 = XJRSTF */\r
1416 RD2; /* read doubleword */\r
1417 JUMP (rs[1]); /* set new PC */\r
1418 set_newflags (rs[0], TRUE); /* set new flags */\r
1419 break;\r
1420\r
1421 case 006: /* JRST 6 = XJEN */\r
1422 RD2; /* read doubleword */\r
1423 pi_dismiss (); /* page ok, dismiss */\r
1424 JUMP (rs[1]); /* set new PC */\r
1425 set_newflags (rs[0], FALSE); /* known to be exec */\r
1426 break;\r
1427\r
1428 case 007: /* JRST 7 = XPCW */\r
1429 ea = ADDA (i = ea, 2); /* new flags, PC */\r
1430 RD2; /* read, test page fail */\r
1431 ReadM (INCA (i), MM_OPND); /* test PC write */\r
1432 Write (i, XWD (flags, 0), MM_OPND); /* write flags */\r
1433 Write (INCA (i), PC, MM_OPND); /* write PC */\r
1434 JUMP (rs[1]); /* set new PC */\r
1435 set_newflags (rs[0], FALSE); /* known to be exec */\r
1436 break;\r
1437\r
1438 case 010: /* JRST 10 = dismiss */\r
1439 pi_dismiss (); /* dismiss int */\r
1440 JUMP (ea); /* set new PC */\r
1441 break;\r
1442\r
1443 case 012: /* JRST 12 = JEN */\r
1444 mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */\r
1445 JUMP (ea); /* set new PC */\r
1446 set_newflags (mb, TRUE); /* set new flags */\r
1447 pi_dismiss (); /* dismiss int */\r
1448 break;\r
1449\r
1450 case 014: /* JRST 14 = SFM */\r
1451 Write (ea, XWD (flags, 0), MM_OPND);\r
1452 break; \r
1453\r
1454 case 015: /* JRST 15 = XJRST */\r
1455 if (!T20PAG) goto MUUO; /* only in TOPS20 paging */\r
1456 JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */\r
1457 break;\r
1458 } /* end case subop */\r
1459 break;\r
1460 } /* end case op */\r
1461\r
1462if (its_2pr) { /* 1-proc trap? */\r
1463 its_1pr = its_2pr = 0; /* clear trap */\r
1464 if (Q_ITS) { /* better be ITS */\r
1465 WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */\r
1466 mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */\r
1467 JUMP (mb); /* set PC */\r
1468 set_newflags (mb, TRUE); /* set new flags */\r
1469 }\r
1470 } /* end if 2-proc */\r
1471} /* end for */\r
1472\r
1473/* Should never get here */\r
1474\r
1475ABORT (STOP_UNKNOWN);\r
1476}\r
1477\r
1478/* Single word integer routines */\r
1479\r
1480/* Integer add\r
1481\r
1482 Truth table for integer add\r
1483\r
1484 case a b r flags\r
1485 1 + + + none\r
1486 2 + + - AOV + C1\r
1487 3 + - + C0 + C1\r
1488 4 + - - -\r
1489 5 - + + C0 + C1\r
1490 6 - + - -\r
1491 7 - - + AOV + C0\r
1492 8 - - - C0 + C1\r
1493*/\r
1494\r
1495d10 add (d10 a, d10 b)\r
1496{\r
1497d10 r;\r
1498\r
1499r = (a + b) & DMASK;\r
1500if (TSTS (a & b)) { /* cases 7,8 */\r
1501 if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r
1502 else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r
1503 return r;\r
1504 }\r
1505if (!TSTS (a | b)) { /* cases 1,2 */\r
1506 if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r
1507 return r; /* case 1 */\r
1508 }\r
1509if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r
1510return r;\r
1511}\r
1512\r
1513/* Integer subtract - actually ac + ~op + 1 */\r
1514\r
1515d10 sub (d10 a, d10 b)\r
1516{\r
1517d10 r;\r
1518\r
1519r = (a - b) & DMASK;\r
1520if (TSTS (a & ~b)) { /* cases 7,8 */\r
1521 if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r
1522 else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r
1523 return r;\r
1524 }\r
1525if (!TSTS (a | ~b)) { /* cases 1,2 */\r
1526 if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r
1527 return r; /* case 1 */\r
1528 }\r
1529if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r
1530return r;\r
1531}\r
1532\r
1533\r
1534/* Logical shift */\r
1535\r
1536d10 lsh (d10 val, a10 ea)\r
1537{\r
1538int32 sc = LIT8 (ea);\r
1539\r
1540if (sc > 35) return 0;\r
1541if (ea & RSIGN) return (val >> sc);\r
1542return ((val << sc) & DMASK);\r
1543}\r
1544\r
1545/* Rotate */\r
1546\r
1547d10 rot (d10 val, a10 ea)\r
1548{\r
1549int32 sc = LIT8 (ea) % 36;\r
1550\r
1551if (sc == 0) return val;\r
1552if (ea & RSIGN) sc = 36 - sc;\r
1553return (((val << sc) | (val >> (36 - sc))) & DMASK);\r
1554}\r
1555\r
1556/* Double word integer instructions */\r
1557\r
1558/* Double add - see case table for single add */\r
1559\r
1560void dadd (int32 ac, d10 *rs)\r
1561{\r
1562d10 r;\r
1563int32 p1 = ADDAC (ac, 1);\r
1564\r
1565AC(p1) = CLRS (AC(p1)) + CLRS (rs[1]); /* add lo */\r
1566r = (AC(ac) + rs[0] + (TSTS (AC(p1))? 1: 0)) & DMASK; /* add hi+cry */\r
1567if (TSTS (AC(ac) & rs[0])) { /* cases 7,8 */\r
1568 if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r
1569 else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r
1570 }\r
1571else if (!TSTS (AC(ac) | rs[0])) { /* cases 1,2 */\r
1572 if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r
1573 }\r
1574else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r
1575AC(ac) = r;\r
1576AC(p1) = TSTS (r)? SETS (AC(p1)): CLRS (AC(p1));\r
1577return;\r
1578} \r
1579\r
1580/* Double subtract - see comments for single subtract */\r
1581\r
1582void dsub (int32 ac, d10 *rs)\r
1583{\r
1584d10 r;\r
1585int32 p1 = ADDAC (ac, 1);\r
1586\r
1587AC(p1) = CLRS (AC(p1)) - CLRS (rs[1]); /* sub lo */\r
1588r = (AC(ac) - rs[0] - (TSTS (AC(p1))? 1: 0)) & DMASK; /* sub hi,borrow */\r
1589if (TSTS (AC(ac) & ~rs[0])) { /* cases 7,8 */\r
1590 if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r
1591 else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r
1592 }\r
1593else if (!TSTS (AC(ac) | ~rs[0])) { /* cases 1,2 */\r
1594 if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r
1595 }\r
1596else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r
1597AC(ac) = r;\r
1598AC(p1) = (TSTS (r)? SETS (AC(p1)): CLRS (AC(p1))) & DMASK;\r
1599return;\r
1600} \r
1601\r
1602\r
1603/* Logical shift combined */\r
1604\r
1605void lshc (int32 ac, a10 ea)\r
1606{\r
1607int32 p1 = ADDAC (ac, 1);\r
1608int32 sc = LIT8 (ea);\r
1609\r
1610if (sc > 71) AC(ac) = AC(p1) = 0;\r
1611else if (ea & RSIGN) {\r
1612 if (sc >= 36) {\r
1613 AC(p1) = AC(ac) >> (sc - 36);\r
1614 AC(ac) = 0;\r
1615 }\r
1616 else {\r
1617 AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK;\r
1618 AC(ac) = AC(ac) >> sc;\r
1619 }\r
1620 }\r
1621else {\r
1622 if (sc >= 36) {\r
1623 AC(ac) = (AC(p1) << (sc - 36)) & DMASK;\r
1624 AC(p1) = 0;\r
1625 }\r
1626 else {\r
1627 AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK;\r
1628 AC(p1) = (AC(p1) << sc) & DMASK;\r
1629 }\r
1630 }\r
1631return;\r
1632}\r
1633\r
1634/* Rotate combined */\r
1635\r
1636void rotc (int32 ac, a10 ea)\r
1637{\r
1638int32 p1 = ADDAC (ac, 1);\r
1639int32 sc = LIT8 (ea) % 72;\r
1640d10 t = AC(ac);\r
1641\r
1642if (sc == 0) return;\r
1643if (ea & RSIGN) sc = 72 - sc;\r
1644if (sc >= 36) {\r
1645 AC(ac) = ((AC(p1) << (sc - 36)) | (t >> (72 - sc))) & DMASK;\r
1646 AC(p1) = ((t << (sc - 36)) | (AC(p1) >> (72 - sc))) & DMASK;\r
1647 }\r
1648else {\r
1649 AC(ac) = ((t << sc) | (AC(p1) >> (36 - sc))) & DMASK;\r
1650 AC(p1) = ((AC(p1) << sc) | (t >> (36 - sc))) & DMASK;\r
1651 }\r
1652return;\r
1653}\r
1654\r
1655/* Arithmetic shifts */\r
1656\r
1657d10 ash (d10 val, a10 ea)\r
1658{\r
1659int32 sc = LIT8 (ea);\r
1660d10 sign = TSTS (val);\r
1661d10 fill = sign? ONES: 0;\r
1662d10 so;\r
1663\r
1664if (sc == 0) return val;\r
1665if (sc > 35) sc = 35; /* cap sc at 35 */\r
1666if (ea & RSIGN)\r
1667 return (((val >> sc) | (fill << (36 - sc))) & DMASK);\r
1668so = val >> (35 - sc); /* bits lost left + sign */\r
1669if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1);\r
1670return (sign | ((val << sc) & MMASK));\r
1671}\r
1672\r
1673void ashc (int32 ac, a10 ea)\r
1674{\r
1675int32 sc = LIT8 (ea);\r
1676int32 p1 = ADDAC (ac, 1);\r
1677d10 sign = TSTS (AC(ac));\r
1678d10 fill = sign? ONES: 0;\r
1679d10 so;\r
1680\r
1681if (sc == 0) return;\r
1682if (sc > 70) sc = 70; /* cap sc at 70 */\r
1683AC(ac) = CLRS (AC(ac)); /* clear signs */\r
1684AC(p1) = CLRS (AC(p1));\r
1685if (ea & RSIGN) {\r
1686 if (sc >= 35) { /* right 36..70 */\r
1687 AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK;\r
1688 AC(ac) = fill;\r
1689 }\r
1690 else {\r
1691 AC(p1) = sign | /* right 1..35 */\r
1692 (((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK);\r
1693 AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK;\r
1694 }\r
1695 }\r
1696else {\r
1697 if (sc >= 35) { /* left 36..70 */\r
1698 so = AC(p1) >> (70 - sc); /* bits lost left */\r
1699 if ((AC(ac) != (sign? MMASK: 0)) ||\r
1700 (so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1);\r
1701 AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK);\r
1702 AC(p1) = sign;\r
1703 }\r
1704 else {\r
1705 so = AC(ac) >> (35 - sc); /* bits lost left */\r
1706 if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1);\r
1707 AC(ac) = sign |\r
1708 (((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK);\r
1709 AC(p1) = sign | ((AC(p1) << sc) & MMASK);\r
1710 }\r
1711 }\r
1712return;\r
1713}\r
1714\r
1715/* Effective address routines */\r
1716\r
1717/* Calculate effective address - used by byte instructions, extended\r
1718 instructions, and interrupts to get a different mapping context from\r
1719 the main loop. prv is either EABP_PXCT or MM_CUR.\r
1720*/\r
1721\r
1722a10 calc_ea (d10 inst, int32 prv)\r
1723{\r
1724int32 i, ea, xr;\r
1725d10 indrct;\r
1726\r
1727for (indrct = inst, i = 0; i < ind_max; i++) {\r
1728 ea = GET_ADDR (indrct);\r
1729 xr = GET_XR (indrct);\r
1730 if (xr) ea = (ea + ((a10) XR (xr, prv))) & AMASK;\r
1731 if (TST_IND (indrct)) indrct = Read (ea, prv);\r
1732 else break;\r
1733 }\r
1734if (i >= ind_max) ABORT (STOP_IND);\r
1735return ea;\r
1736}\r
1737\r
1738/* Calculate I/O effective address. Cases:\r
1739 - No index or indirect, return addr from instruction\r
1740 - Index only, index >= 0, return 36b sum of addr + index\r
1741 - Index only, index <= 0, return 18b sum of addr + index\r
1742 - Indirect, calculate 18b sum of addr + index, return\r
1743 entire word fetch (single level)\r
1744*/\r
1745\r
1746a10 calc_ioea (d10 inst, int32 pflgs)\r
1747{\r
1748int32 xr;\r
1749a10 ea;\r
1750\r
1751xr = GET_XR (inst);\r
1752ea = GET_ADDR (inst);\r
1753if (TST_IND (inst)) { /* indirect? */\r
1754 if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK;\r
1755 ea = (a10) Read (ea, MM_EA);\r
1756 }\r
1757else if (xr) { /* direct + idx? */\r
1758 ea = ea + ((a10) XR (xr, MM_EA));\r
1759 if (TSTS (XR (xr, MM_EA))) ea = ea & AMASK;\r
1760 }\r
1761return ea;\r
1762}\r
1763\r
1764/* Calculate JRSTF effective address. This routine preserves\r
1765 the left half of the effective address, to be the new flags.\r
1766*/\r
1767\r
1768d10 calc_jrstfea (d10 inst, int32 pflgs)\r
1769{\r
1770int32 i, xr;\r
1771d10 mb;\r
1772\r
1773for (i = 0; i < ind_max; i++) {\r
1774 mb = inst;\r
1775 xr = GET_XR (inst);\r
1776 if (xr) mb = (mb & AMASK) + XR (xr, MM_EA);\r
1777 if (TST_IND (inst)) inst = Read (((a10) mb) & AMASK, MM_EA);\r
1778 else break;\r
1779 }\r
1780if (i >= ind_max) ABORT (STOP_IND);\r
1781return (mb & DMASK);\r
1782}\r
1783\r
1784/* Byte pointer routines */\r
1785\r
1786/* Increment byte pointer - checked against KS10 ucode */\r
1787\r
1788void ibp (a10 ea, int32 pflgs)\r
1789{\r
1790int32 p, s;\r
1791d10 bp;\r
1792\r
1793bp = ReadM (ea, MM_OPND); /* get byte ptr */\r
1794p = GET_P (bp); /* get P and S */\r
1795s = GET_S (bp);\r
1796p = p - s; /* adv P */\r
1797if (p < 0) { /* end of word? */\r
1798 bp = (bp & LMASK) | (INCR (bp)); /* incr addr */\r
1799 p = (36 - s) & 077; /* reset P */\r
1800 }\r
1801bp = PUT_P (bp, p); /* store new P */\r
1802Write (ea, bp, MM_OPND); /* store byte ptr */\r
1803return;\r
1804}\r
1805\r
1806/* Load byte */\r
1807\r
1808d10 ldb (a10 ea, int32 pflgs)\r
1809{\r
1810a10 ba;\r
1811int32 p, s;\r
1812d10 bp, wd;\r
1813\r
1814bp = Read (ea, MM_OPND); /* get byte ptr */\r
1815p = GET_P (bp); /* get P and S */\r
1816s = GET_S (bp);\r
1817ba = calc_ea (bp, MM_EABP); /* get addr of byte */\r
1818wd = Read (ba, MM_BSTK); /* read word */\r
1819wd = (wd >> p); /* align byte */\r
1820wd = wd & bytemask[s]; /* mask to size */\r
1821return wd;\r
1822}\r
1823\r
1824/* Deposit byte - must use read and write to get page fail correct */\r
1825\r
1826void dpb (d10 val, a10 ea, int32 pflgs)\r
1827{\r
1828a10 ba;\r
1829int32 p, s;\r
1830d10 bp, wd, mask;\r
1831\r
1832bp = Read (ea, MM_OPND); /* get byte ptr */\r
1833p = GET_P (bp); /* get P and S */\r
1834s = GET_S (bp);\r
1835ba = calc_ea (bp, MM_EABP); /* get addr of byte */\r
1836wd = Read (ba, MM_BSTK); /* read word */\r
1837mask = bytemask[s] << p; /* shift mask, val */\r
1838val = val << p;\r
1839wd = (wd & ~mask) | (val & mask); /* insert byte */\r
1840Write (ba, wd & DMASK, MM_BSTK);\r
1841return;\r
1842}\r
1843\r
1844/* Adjust byte pointer - checked against KS10 ucode \r
1845 The KS10 divide checks if the bytes per word = 0, which is a simpler\r
1846 formulation of the processor reference manual check.\r
1847*/\r
1848\r
1849void adjbp (int32 ac, a10 ea, int32 pflgs)\r
1850{\r
1851int32 p, s;\r
1852d10 bp, newby, left, byadj, bywrd, val, wdadj;\r
1853\r
1854val = AC(ac); /* get adjustment */\r
1855bp = Read (ea, MM_OPND); /* get byte pointer */\r
1856p = GET_P (bp); /* get p */\r
1857s = GET_S (bp); /* get s */\r
1858if (s) {\r
1859 left = (36 - p) / s; /* bytes to left of p */\r
1860 bywrd = left + (p / s); /* bytes per word */\r
1861 if (bywrd == 0) { /* zero bytes? */\r
1862 SETF (F_AOV | F_T1 | F_DCK); /* set flags */\r
1863 return; /* abort operation */\r
1864 }\r
1865 newby = left + SXT (val); /* adjusted byte # */\r
1866 wdadj = newby / bywrd; /* word adjustment */\r
1867 byadj = (newby >= 0)? newby % bywrd: -((-newby) % bywrd);\r
1868 if (byadj <= 0) {\r
1869 byadj = byadj + bywrd; /* make adj positive */\r
1870 wdadj = wdadj - 1;\r
1871 }\r
1872 p = (36 - ((int32) byadj) * s) - ((36 - p) % s); /* new p */\r
1873 bp = (PUT_P (bp, p) & LMASK) | ((bp + wdadj) & RMASK);\r
1874 }\r
1875AC(ac) = bp; \r
1876return;\r
1877}\r
1878\r
1879/* Block transfer - checked against KS10 ucode\r
1880 The KS10 uses instruction specific recovery code in page fail\r
1881 to set the AC properly for restart. Lacking this mechanism,\r
1882 the simulator must test references in advance.\r
1883 The clocking test guarantees forward progress under single step.\r
1884*/\r
1885\r
1886void blt (int32 ac, a10 ea, int32 pflgs)\r
1887{\r
1888a10 srca = (a10) LRZ (AC(ac));\r
1889a10 dsta = (a10) RRZ (AC(ac));\r
1890a10 lnt = ea - dsta + 1;\r
1891d10 srcv;\r
1892int32 flg, t;\r
1893\r
1894AC(ac) = XWD (srca + lnt, dsta + lnt);\r
1895for (flg = 0; dsta <= ea; flg++) { /* loop */\r
1896 if (flg && (t = test_int ())) { /* timer event? */\r
1897 AC(ac) = XWD (srca, dsta); /* AC for intr */\r
1898 ABORT (t);\r
1899 }\r
1900 if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */\r
1901 AC(ac) = XWD (srca, dsta); /* AC for page fail */\r
1902 Read (srca & AMASK, MM_BSTK); /* force trap */\r
1903 }\r
1904 if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */\r
1905 AC(ac) = XWD (srca, dsta); /* AC for page fail */\r
1906 ReadM (dsta & AMASK, MM_OPND); /* force trap */\r
1907 }\r
1908 srcv = Read (srca & AMASK, MM_BSTK); /* read */\r
1909 Write (dsta & AMASK, srcv, MM_OPND); /* write */\r
1910 srca = srca + 1; /* incr addr */\r
1911 dsta = dsta + 1;\r
1912 }\r
1913return;\r
1914}\r
1915\r
1916/* I/O block transfers - byte to Unibus (0) and Unibus to byte (1) */\r
1917\r
1918#define BYTE1 0776000000000\r
1919#define BYTE2 0001774000000\r
1920#define BYTE3 0000003770000\r
1921#define BYTE4 0000000007760\r
1922/* unused 0000000000017 */\r
1923\r
1924void bltu (int32 ac, a10 ea, int32 pflgs, int dir)\r
1925{\r
1926a10 srca = (a10) LRZ (AC(ac));\r
1927a10 dsta = (a10) RRZ (AC(ac));\r
1928a10 lnt = ea - dsta + 1;\r
1929d10 srcv, dstv;\r
1930int32 flg, t;\r
1931\r
1932AC(ac) = XWD (srca + lnt, dsta + lnt);\r
1933for (flg = 0; dsta <= ea; flg++) { /* loop */\r
1934 if (flg && (t = test_int ())) { /* timer event? */\r
1935 AC(ac) = XWD (srca, dsta); /* AC for intr */\r
1936 ABORT (t);\r
1937 }\r
1938 if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */\r
1939 AC(ac) = XWD (srca, dsta); /* AC for page fail */\r
1940 Read (srca & AMASK, MM_BSTK); /* force trap */\r
1941 }\r
1942 if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */\r
1943 AC(ac) = XWD (srca, dsta); /* AC for page fail */\r
1944 ReadM (dsta & AMASK, MM_OPND); /* force trap */\r
1945 }\r
1946 srcv = Read (srca & AMASK, MM_BSTK); /* read */\r
1947 if (dir) dstv = ((srcv << 10) & BYTE1) | ((srcv >> 6) & BYTE2) |\r
1948 ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4);\r
1949 else dstv = ((srcv & BYTE1) >> 10) | ((srcv & BYTE2) << 6) |\r
1950 ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4);\r
1951 Write (dsta & AMASK, dstv, MM_OPND); /* write */\r
1952 srca = srca + 1; /* incr addr */\r
1953 dsta = dsta + 1;\r
1954 }\r
1955return;\r
1956}\r
1957\r
1958/* Utility routine to test for I/O event and interrupt */\r
1959\r
1960int32 test_int (void)\r
1961{\r
1962int32 t;\r
1963\r
1964if (sim_interval <= 0) { /* check queue */\r
1965 if (t = sim_process_event ()) return t; /* IO event? */\r
1966 if (pi_eval ()) return (INTERRUPT); /* interrupt? */\r
1967 }\r
1968else sim_interval--; /* count clock */\r
1969return 0;\r
1970}\r
1971\r
1972/* Adjust stack pointer\r
1973\r
1974 The reference manual says to trap on:\r
1975 1) E < 0, left changes from + to -\r
1976 2) E >= 0, left changes from - to +\r
1977 This is the same as trap on:\r
1978 1) E and left result have same signs\r
1979 2) initial value and left result have different signs\r
1980 */\r
1981\r
1982d10 adjsp (d10 val, a10 ea)\r
1983{\r
1984d10 imm = ea;\r
1985d10 left, right;\r
1986\r
1987left = ADDL (val, imm);\r
1988right = ADDR (val, imm);\r
1989if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) SETF (F_T2);\r
1990return (left | right);\r
1991}\r
1992\r
1993/* Jump if find first ones\r
1994 Takes advantage of 7 bit find first table for priority interrupts.\r
1995*/\r
1996\r
1997int32 jffo (d10 val)\r
1998{\r
1999int32 i, by;\r
2000\r
2001if ((val & DMASK) == 0) return 0;\r
2002for (i = 0; i <= 28; i = i + 7) { /* scan five bytes */\r
2003 by = (int32) ((val >> (29 - i)) & 0177);\r
2004 if (by) return (pi_m2lvl[by] + i - 1);\r
2005 }\r
2006return 35; /* must be bit 35 */\r
2007}\r
2008\r
2009/* Circulate - ITS only instruction\r
2010\r
2011 Bits rotated out of AC are rotated into the opposite end of AC+1 - why?\r
2012 No attempt is made to optimize this instruction.\r
2013*/\r
2014\r
2015void circ (int32 ac, int32 ea)\r
2016{\r
2017int32 sc = LIT8 (ea) % 72;\r
2018int32 p1 = ADDAC (ac,1);\r
2019int32 i;\r
2020d10 val;\r
2021\r
2022if (sc == 0) return; /* any shift? */\r
2023if (ea & RSIGN) sc = 72 - sc; /* if right, make left */\r
2024for (i = 0; i < sc; i++) { /* one bit at a time */\r
2025 val = TSTS (AC(ac)); /* shift out */\r
2026 AC(ac) = ((AC(ac) << 1) | (AC(p1) & 1)) & DMASK;\r
2027 AC(p1) = (AC(p1) >> 1) | val; /* shift in */\r
2028 }\r
2029return;\r
2030}\r
2031\r
2032/* Arithmetic processor (APR)\r
2033\r
2034 The APR subsystem includes miscellaneous interrupts that are individually\r
2035 maskable but which interrupt on a single, selectable level\r
2036\r
2037 Instructions for the arithmetic processor:\r
2038 APRID read system id \r
2039 WRAPR (CONO APR) write system flags\r
2040 RDAPR (CONI APR) read system flags\r
2041 (CONSO APR) test system flags\r
2042 (CONSZ APR) test system flags\r
2043*/\r
2044\r
2045t_bool aprid (a10 ea, int32 prv)\r
2046{\r
2047Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv);\r
2048return FALSE;\r
2049}\r
2050\r
2051/* Checked against KS10 ucode */\r
2052\r
2053t_bool wrapr (a10 ea, int32 prv)\r
2054{\r
2055int32 bits = APR_GETF (ea);\r
2056\r
2057apr_lvl = ea & APR_M_LVL;\r
2058if (ea & APR_SENB) apr_enb = apr_enb | bits; /* set enables? */\r
2059if (ea & APR_CENB) apr_enb = apr_enb & ~bits; /* clear enables? */\r
2060if (ea & APR_CFLG) apr_flg = apr_flg & ~bits; /* clear flags? */\r
2061if (ea & APR_SFLG) apr_flg = apr_flg | bits; /* set flags? */\r
2062if (apr_flg & APRF_ITC) { /* interrupt console? */\r
2063 fe_intr (); /* explicit callout */\r
2064 apr_flg = apr_flg & ~APRF_ITC; /* interrupt clears */\r
2065 }\r
2066pi_eval (); /* eval pi system */\r
2067return FALSE;\r
2068}\r
2069\r
2070t_bool rdapr (a10 ea, int32 prv)\r
2071{\r
2072Write (ea, (d10) APRWORD, prv);\r
2073return FALSE;\r
2074}\r
2075\r
2076t_bool czapr (a10 ea, int32 prv)\r
2077{\r
2078return ((APRHWORD & ea)? FALSE: TRUE);\r
2079}\r
2080\r
2081t_bool coapr (a10 ea, int32 prv)\r
2082{\r
2083return ((APRHWORD & ea)? TRUE: FALSE);\r
2084}\r
2085\r
2086/* Routine to change the processor flags, called from JRST, MUUO, interrupt.\r
2087 If jrst is TRUE, must munge flags for executive security.\r
2088 Because the KS10 lacks the public flag, these checks are simplified.\r
2089*/\r
2090\r
2091void set_newflags (d10 newf, t_bool jrst)\r
2092{\r
2093int32 fl = (int32) LRZ (newf);\r
2094\r
2095if (jrst && TSTF (F_USR)) { /* if in user now */\r
2096 fl = fl | F_USR; /* can't clear user */\r
2097 if (!TSTF (F_UIO)) fl = fl & ~F_UIO; /* if !UIO, can't set */\r
2098 }\r
2099if (Q_ITS && (fl & F_1PR)) { /* ITS 1-proceed? */\r
2100 its_1pr = 1; /* set flag */\r
2101 fl = fl & ~F_1PR; /* vanish bit */\r
2102 }\r
2103flags = fl & F_MASK; /* set new flags */\r
2104set_dyn_ptrs (); /* set new ptrs */\r
2105return;\r
2106}\r
2107\r
2108/* Priority interrupt system (PI)\r
2109\r
2110 The priority interrupt system has three sources of requests\r
2111 (pi_apr) system flags - synthesized on the fly\r
2112 (pi_ioq) I/O interrupts - synthesized on the fly\r
2113 pi_prq program requests\r
2114 APR and I/O requests are masked with the PI enable mask; the program\r
2115 requests are not. If priority interrupts are enabled, and there is\r
2116 a request at a level exceeding the currently active level, then an\r
2117 interrupt occurs.\r
2118\r
2119 Instructions for the priority interrupt system:\r
2120 WRPI (CONO PI) write pi system\r
2121 RDPI (CONI PI) read pi system\r
2122 (CONSO PI) test pi system\r
2123 (CONSZ PI) test pi system\r
2124\r
2125 Routines for the priority interrupt system:\r
2126 pi_eval return level number of highest interrupt\r
2127 pi_dismiss dismiss highest outstanding interrupt\r
2128\r
2129 Checked against KS10 ucode - KS10 UUO's if <18:21> are non-zero\r
2130*/\r
2131\r
2132t_bool wrpi (a10 ea, int32 prv)\r
2133{\r
2134int32 lvl = ea & PI_M_LVL;\r
2135\r
2136if (ea & PI_INIT) pi_on = pi_enb = pi_act = pi_prq = 0;\r
2137if (ea & PI_CPRQ) pi_prq = pi_prq & ~lvl; /* clear prog reqs? */\r
2138if (ea & PI_SPRQ) pi_prq = pi_prq | lvl; /* set prog reqs? */\r
2139if (ea & PI_SENB) pi_enb = pi_enb | lvl; /* enable levels? */\r
2140if (ea & PI_CENB) pi_enb = pi_enb & ~lvl; /* disable levels? */\r
2141if (ea & PI_SON) pi_on = 1; /* enable pi? */\r
2142if (ea & PI_CON) pi_on = 0; /* disable pi? */\r
2143pi_eval (); /* eval pi system */\r
2144return FALSE;\r
2145}\r
2146\r
2147t_bool rdpi (a10 ea, int32 prv)\r
2148{\r
2149Write (ea, (d10) PIWORD, prv);\r
2150return FALSE;\r
2151}\r
2152\r
2153t_bool czpi (a10 ea, int32 prv)\r
2154{\r
2155return ((PIHWORD & ea)? FALSE: TRUE);\r
2156}\r
2157\r
2158t_bool copi (a10 ea, int32 prv)\r
2159{\r
2160return ((PIHWORD & ea)? TRUE: FALSE);\r
2161}\r
2162\r
2163/* Priority interrupt evaluation\r
2164\r
2165 The Processor Reference Manuals says that program interrupt\r
2166 requests occur whether the corresponding level is enabled or\r
2167 not. However, the KS10, starting with microcode edit 47,\r
2168 masked program requests under the enable mask, just like APR\r
2169 and I/O requests. This is not formally documented but appears\r
2170 to be necessary for the TOPS20 console port to run correclty.\r
2171*/\r
2172\r
2173int32 pi_eval (void)\r
2174{\r
2175int32 reqlvl, actlvl;\r
2176extern int32 pi_ub_eval ();\r
2177\r
2178qintr = 0;\r
2179if (pi_on) {\r
2180 pi_apr = (apr_flg & apr_enb)? pi_l2bit[apr_lvl]: 0;\r
2181 pi_ioq = pi_ub_eval ();\r
2182 reqlvl = pi_m2lvl[((pi_apr | pi_ioq | pi_prq) & pi_enb)];\r
2183 actlvl = pi_m2lvl[pi_act];\r
2184 if ((actlvl == 0) || (reqlvl < actlvl)) qintr = reqlvl;\r
2185 }\r
2186return qintr;\r
2187}\r
2188\r
2189void pi_dismiss (void)\r
2190{\r
2191pi_act = pi_act & ~pi_l2bit[pi_m2lvl[pi_act]]; /* clr left most bit */\r
2192pi_eval (); /* eval pi system */\r
2193return;\r
2194}\r
2195\r
2196/* Reset routine */\r
2197\r
2198t_stat cpu_reset (DEVICE *dptr)\r
2199{\r
2200flags = 0; /* clear flags */\r
2201its_1pr = 0; /* clear 1-proceed */\r
2202ebr = ubr = 0; /* clear paging */\r
2203pi_enb = pi_act = pi_prq = 0; /* clear PI */\r
2204apr_enb = apr_flg = apr_lvl = 0; /* clear APR */\r
2205pcst = 0; /* clear PC samp */\r
2206rlog = 0; /* clear reg log */\r
2207hsb = (Q_ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */\r
2208set_dyn_ptrs ();\r
2209set_ac_display (ac_cur);\r
2210pi_eval ();\r
2211if (M == NULL) M = (d10 *) calloc (MAXMEMSIZE, sizeof (d10));\r
2212if (M == NULL) return SCPE_MEM;\r
2213pcq_r = find_reg ("PCQ", NULL, dptr);\r
2214if (pcq_r) pcq_r->qptr = 0;\r
2215else return SCPE_IERR;\r
2216sim_brk_types = sim_brk_dflt = SWMASK ('E');\r
2217return SCPE_OK;\r
2218}\r
2219\r
2220/* Memory examine */\r
2221\r
2222t_stat cpu_ex (t_value *vptr, t_addr ea, UNIT *uptr, int32 sw)\r
2223{\r
2224if (vptr == NULL) return SCPE_ARG;\r
2225if (ea < AC_NUM) *vptr = AC(ea) & DMASK;\r
2226else {\r
2227 if (sw & SWMASK ('V')) {\r
2228 ea = conmap (ea, PTF_CON, sw);\r
2229 if (ea >= MAXMEMSIZE) return SCPE_REL;\r
2230 }\r
2231 if (ea >= MEMSIZE) return SCPE_NXM;\r
2232 *vptr = M[ea] & DMASK;\r
2233 }\r
2234return SCPE_OK;\r
2235}\r
2236\r
2237/* Memory deposit */\r
2238\r
2239t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw)\r
2240{\r
2241if (ea < AC_NUM) AC(ea) = val & DMASK;\r
2242else {\r
2243 if (sw & SWMASK ('V')) {\r
2244 ea = conmap (ea, PTF_CON | PTF_WR, sw);\r
2245 if (ea >= MAXMEMSIZE) return SCPE_REL;\r
2246 }\r
2247 if (ea >= MEMSIZE) return SCPE_NXM;\r
2248 M[ea] = val & DMASK;\r
2249 }\r
2250return SCPE_OK;\r
2251}\r
2252\r
2253/* Set current AC pointers for SCP */\r
2254\r
2255void set_ac_display (d10 *acbase)\r
2256{\r
2257extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr);\r
2258REG *rptr;\r
2259int i;\r
2260\r
2261rptr = find_reg ("AC0", NULL, &cpu_dev);\r
2262if (rptr == NULL) return;\r
2263for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i);\r
2264return;\r
2265}\r
2266\r
2267/* Set history */\r
2268\r
2269t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)\r
2270{\r
2271int32 i, lnt;\r
2272t_stat r;\r
2273\r
2274if (cptr == NULL) {\r
2275 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;\r
2276 hst_p = 0;\r
2277 return SCPE_OK;\r
2278 }\r
2279lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);\r
2280if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;\r
2281hst_p = 0;\r
2282if (hst_lnt) {\r
2283 free (hst);\r
2284 hst_lnt = 0;\r
2285 hst = NULL;\r
2286 }\r
2287if (lnt) {\r
2288 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));\r
2289 if (hst == NULL) return SCPE_MEM;\r
2290 hst_lnt = lnt;\r
2291 }\r
2292return SCPE_OK;\r
2293}\r
2294\r
2295/* Show history */\r
2296\r
2297t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)\r
2298{\r
2299int32 k, di, lnt;\r
2300char *cptr = (char *) desc;\r
2301t_stat r;\r
2302t_value sim_eval;\r
2303InstHistory *h;\r
2304extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,\r
2305 UNIT *uptr, int32 sw);\r
2306\r
2307if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */\r
2308if (cptr) {\r
2309 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);\r
2310 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;\r
2311 }\r
2312else lnt = hst_lnt;\r
2313di = hst_p - lnt; /* work forward */\r
2314if (di < 0) di = di + hst_lnt;\r
2315fprintf (st, "PC AC EA IR\n\n");\r
2316for (k = 0; k < lnt; k++) { /* print specified */\r
2317 h = &hst[(++di) % hst_lnt]; /* entry pointer */\r
2318 if (h->pc & HIST_PC) { /* instruction? */\r
2319 fprintf (st, "%06o ", h->pc & AMASK);\r
2320 fprint_val (st, h->ac, 8, 36, PV_RZRO);\r
2321 fputs (" ", st);\r
2322 fprintf (st, "%06o ", h->ea);\r
2323 sim_eval = h->ir;\r
2324 if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) {\r
2325 fputs ("(undefined) ", st);\r
2326 fprint_val (st, h->ir, 8, 36, PV_RZRO);\r
2327 }\r
2328 fputc ('\n', st); /* end line */\r
2329 } /* end else instruction */\r
2330 } /* end for */\r
2331return SCPE_OK;\r
2332}\r