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