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