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