First Commit of my working state
[simh.git] / H316 / h316_cpu.c
1 /* h316_cpu.c: Honeywell 316/516 CPU simulator
2
3 Copyright (c) 1999-2007, Robert M. Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 cpu H316/H516 CPU
27
28 28-Apr-07 RMS Removed clock initialization
29 03-Apr-06 RMS Fixed bugs in LLL, LRL (from Theo Engel)
30 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
31 16-Aug-05 RMS Fixed C++ declaration and cast problems
32 15-Feb-05 RMS Added start button interrupt
33 01-Dec-04 RMS Fixed bug in DIV
34 06-Nov-04 RMS Added =n to SHOW HISTORY
35 04-Jan-04 RMS Removed unnecessary compare
36 31-Dec-03 RMS Fixed bug in cpu_set_hist
37 24-Oct-03 RMS Added DMA/DMC support, instruction history
38 30-Dec-01 RMS Added old PC queue
39 03-Nov-01 RMS Fixed NOHSA modifier
40 30-Nov-01 RMS Added extended SET/SHOW support
41
42 The register state for the Honeywell 316/516 CPU is:
43
44 AR<1:16> A register
45 BR<1:16> B register
46 XR<1:16> X register
47 PC<1:16> P register (program counter)
48 Y<1:16> memory address register
49 MB<1:16> memory data register
50 C overflow flag
51 EXT extend mode flag
52 DP double precision mode flag
53 SC<1:5> shift count
54 SR[1:4]<0> sense switches 1-4
55
56 The Honeywell 316/516 has six instruction formats: memory reference,
57 I/O, control, shift, skip, and operate.
58
59 The memory reference format is:
60
61 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
62 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
63 |in|xr| op |sc| offset | memory reference
64 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
65
66 <13:10> mnemonic action
67
68 0000 (other) see control, shift, skip, operate instructions
69 0001 JMP P = MA
70 0010 LDA A = M[MA]
71 0011 ANA A = A & M[MA]
72 0100 STA M[MA] = A
73 0101 ERA A = A ^ M[MA]
74 0110 ADD A = A + M[MA]
75 0111 SUB A = A - M[MA]
76 1000 JST M[MA] = P, P = MA + 1
77 1001 CAS skip if A == M[MA], double skip if A < M[MA]
78 1010 IRS M[MA] = M[MA] + 1, skip if M[MA] == 0
79 1011 IMA A <=> M[MA]
80 1100 (I/O) see I/O instructions
81 1101 LDX/STX X = M[MA] (xr = 1), M[MA] = x (xr = 0)
82 1110 MPY multiply
83 1111 DIV divide
84
85 In non-extend mode, memory reference instructions can access an address
86 space of 16K words. Multiple levels of indirection are supported, and
87 each indirect word supplies its own indirect and index bits.
88
89 <1,2,7> mode action
90
91 0,0,0 sector zero direct MA = IR<8:0>
92 0,0,1 current direct MA = P<13:9>'IR<8:0>
93 0,1,0 sector zero indexed MA = IR<8:0> + X
94 0,1,1 current direct MA = P<13:9>'IR<8:0> + X
95 1,0,0 sector zero indirect MA = M[IR<8:0>]
96 1,0,1 current indirect MA = M[P<13:9>'IR<8:0>]
97 1,1,0 sector zero indirect indexed MA = M[IR<8:0> + X]
98 1,1,1 current indirect indexed MA = M[MA = P<13:9>'IR<8:0> + X]
99
100 In extend mode, memory reference instructions can access an address
101 space of 32K words. Multiple levels of indirection are supported, but
102 only post-indexing, based on the original instruction word index flag,
103 is allowed.
104
105 The control format is:
106
107 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
108 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
109 | 0 0 0 0 0 0| opcode | control
110 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
111
112 The shift format is:
113
114 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
115 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
116 | 0 1 0 0 0 0|dr|sz|type | shift count | shift
117 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
118 | | \-+-/
119 | | |
120 | | +--------------------- type
121 | +------------------------- long/A only
122 +---------------------------- right/left
123
124 The skip format is:
125
126 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
127 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
128 | 1 0 0 0 0 0|rv|po|pe|ev|ze|s1|s2|s3|s4|cz| skip
129 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
130 | | | | | | | | | |
131 | | | | | | | | | +- skip if C = 0
132 | | | | | | | | +---- skip if ssw 4 = 0
133 | | | | | | | +------- skip if ssw 3 = 0
134 | | | | | | +---------- skip if ssw 2 = 0
135 | | | | | +------------- skip if ssw 1 = 0
136 | | | | +---------------- skip if A == 0
137 | | | +------------------- skip if A<0> == 0
138 | | +---------------------- skip if mem par err
139 | +------------------------- skip if A<15> = 0
140 +---------------------------- reverse skip sense
141
142 The operate format is:
143
144 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
145 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
146 | 1 1 0 0 0 0| opcode | operate
147 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
148
149 The I/O format is:
150
151 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
152 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
153 | op | 1 1 0 0| function | device | I/O transfer
154 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
155
156 The IO transfer instruction controls the specified device.
157 Depending on the opcode, the instruction may set or clear
158 the device flag, start or stop I/O, or read or write data.
159
160 This routine is the instruction decode routine for the Honeywell
161 316/516. It is called from the simulator control program to execute
162 instructions in simulated memory, starting at the simulated PC.
163 It runs until 'reason' is set non-zero.
164
165 General notes:
166
167 1. Reasons to stop. The simulator can be stopped by:
168
169 HALT instruction
170 breakpoint encountered
171 infinite indirection loop
172 unimplemented instruction and stop_inst flag set
173 unknown I/O device and stop_dev flag set
174 I/O error in I/O simulator
175
176 2. Interrupts. Interrupts are maintained by two parallel variables:
177
178 dev_int device interrupt flags
179 dev_enb device interrupt enable flags
180
181 In addition, dev_int contains the interrupt enable and interrupt no
182 defer flags. If interrupt enable and interrupt no defer are set, and
183 at least one interrupt request is pending, then an interrupt occurs.
184 The order of flags in these variables corresponds to the order
185 in the SMK instruction.
186
187 3. Non-existent memory. On the H316/516, reads to non-existent memory
188 return zero, and writes are ignored. In the simulator, the
189 largest possible memory is instantiated and initialized to zero.
190 Thus, only writes need be checked against actual memory size.
191
192 4. Adding I/O devices. These modules must be modified:
193
194 h316_defs.h add interrupt request definition
195 h316_cpu.c add device dispatch table entry
196 h316_sys.c add sim_devices table entry
197 */
198
199 #include "h316_defs.h"
200
201 #define PCQ_SIZE 64 /* must be 2**n */
202 #define PCQ_MASK (PCQ_SIZE - 1)
203 #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
204 #define PCQ_TOP pcq[pcq_p]
205 #define m7 0001000 /* for generics */
206 #define m8 0000400
207 #define m9 0000200
208 #define m10 0000100
209 #define m11 0000040
210 #define m12 0000020
211 #define m13 0000010
212 #define m14 0000004
213 #define m15 0000002
214 #define m16 0000001
215
216 #define HIST_PC 0x40000000
217 #define HIST_C 0x20000000
218 #define HIST_EA 0x10000000
219 #define HIST_MIN 64
220 #define HIST_MAX 65536
221
222 typedef struct {
223 int32 pc;
224 int32 ir;
225 int32 ar;
226 int32 br;
227 int32 xr;
228 int32 ea;
229 int32 opnd;
230 } InstHistory;
231
232 uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
233 int32 saved_AR = 0; /* A register */
234 int32 saved_BR = 0; /* B register */
235 int32 saved_XR = 0; /* X register */
236 int32 PC = 0; /* P register */
237 int32 C = 0; /* C register */
238 int32 ext = 0; /* extend mode */
239 int32 pme = 0; /* prev mode extend */
240 int32 extoff_pending = 0; /* extend off pending */
241 int32 dp = 0; /* double mode */
242 int32 sc = 0; /* shift count */
243 int32 ss[4]; /* sense switches */
244 int32 dev_int = 0; /* dev ready */
245 int32 dev_enb = 0; /* dev enable */
246 int32 ind_max = 8; /* iadr nest limit */
247 int32 stop_inst = 1; /* stop on ill inst */
248 int32 stop_dev = 2; /* stop on ill dev */
249 uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
250 int32 pcq_p = 0; /* PC queue ptr */
251 REG *pcq_r = NULL; /* PC queue reg ptr */
252 uint32 dma_nch = DMA_MAX; /* number of chan */
253 uint32 dma_ad[DMA_MAX] = { 0 }; /* DMA addresses */
254 uint32 dma_wc[DMA_MAX] = { 0 }; /* DMA word count */
255 uint32 dma_eor[DMA_MAX] = { 0 }; /* DMA end of range */
256 uint32 chan_req = 0; /* channel requests */
257 uint32 chan_map[DMA_MAX + DMC_MAX] = { 0 }; /* chan->dev map */
258 int32 (*iotab[DEV_MAX])(int32 inst, int32 fnc, int32 dat, int32 dev) = { NULL };
259 int32 hst_p = 0; /* history pointer */
260 int32 hst_lnt = 0; /* history length */
261 InstHistory *hst = NULL; /* instruction history */
262
263 extern int32 sim_int_char;
264 extern int32 sim_interval;
265 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
266 extern FILE *sim_log;
267 extern DEVICE *sim_devices[];
268
269 t_bool devtab_init (void);
270 int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev);
271 int32 undio (int32 inst, int32 fnc, int32 dat, int32 dev);
272 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
273 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
274 t_stat cpu_reset (DEVICE *dptr);
275 t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc);
276 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
277 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
278 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
279 t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc);
280 t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
281 t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc);
282
283 extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
284 UNIT *uptr, int32 sw);
285
286 /* CPU data structures
287
288 cpu_dev CPU device descriptor
289 cpu_unit CPU unit descriptor
290 cpu_reg CPU register list
291 cpu_mod CPU modifiers list
292 */
293
294 DIB cpu_dib = { DMA, IOBUS, 1, &dmaio };
295
296 UNIT cpu_unit = {
297 UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_EXT+UNIT_HSA+UNIT_DMC, MAXMEMSIZE)
298 };
299
300 REG cpu_reg[] = {
301 { ORDATA (P, PC, 15) },
302 { ORDATA (A, saved_AR, 16) },
303 { ORDATA (B, saved_BR, 16) },
304 { ORDATA (X, XR, 16) },
305 { ORDATA (SC, sc, 16) },
306 { FLDATA (C, C, 0) },
307 { FLDATA (EXT, ext, 0) },
308 { FLDATA (PME, pme, 0) },
309 { FLDATA (EXT_OFF, extoff_pending, 0) },
310 { FLDATA (DP, dp, 0) },
311 { FLDATA (SS1, ss[0], 0) },
312 { FLDATA (SS2, ss[1], 0) },
313 { FLDATA (SS3, ss[2], 0) },
314 { FLDATA (SS4, ss[3], 0) },
315 { FLDATA (ION, dev_int, INT_V_ON) },
316 { FLDATA (INODEF, dev_int, INT_V_NODEF) },
317 { FLDATA (START, dev_int, INT_V_START) },
318 { ORDATA (DEVINT, dev_int, 16), REG_RO },
319 { ORDATA (DEVENB, dev_enb, 16), REG_RO },
320 { ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) },
321 { BRDATA (DMAAD, dma_ad, 8, 16, DMA_MAX) },
322 { BRDATA (DMAWC, dma_wc, 8, 16, DMA_MAX) },
323 { BRDATA (DMAEOR, dma_eor, 8, 1, DMA_MAX) },
324 { ORDATA (DMANCH, dma_nch, 3), REG_HRO },
325 { FLDATA (MPERDY, dev_int, INT_V_MPE) },
326 { FLDATA (MPEENB, dev_enb, INT_V_MPE) },
327 { FLDATA (STOP_INST, stop_inst, 0) },
328 { FLDATA (STOP_DEV, stop_dev, 1) },
329 { DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT },
330 { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC },
331 { ORDATA (PCQP, pcq_p, 6), REG_HRO },
332 { ORDATA (WRU, sim_int_char, 8) },
333 { NULL }
334 };
335
336 MTAB cpu_mod[] = {
337 { UNIT_EXT, 0, "no extend", "NOEXTEND", &cpu_set_noext },
338 { UNIT_EXT, UNIT_EXT, "extend", "EXTEND", NULL },
339 { UNIT_HSA, 0, "no HSA", "NOHSA", NULL },
340 { UNIT_HSA, UNIT_HSA, "HSA", "HSA", NULL },
341 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
342 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
343 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
344 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
345 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
346 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
347 { MTAB_XTD | MTAB_VDV, 0, "channels", "CHANNELS",
348 &cpu_set_nchan, &cpu_show_nchan, NULL },
349 { UNIT_DMC, 0, "no DMC", "NODMC", NULL },
350 { UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL },
351 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
352 &cpu_set_hist, &cpu_show_hist },
353 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL,
354 NULL, &cpu_show_dma, NULL },
355 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DMA2", NULL,
356 NULL, &cpu_show_dma, NULL },
357 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "DMA3", NULL,
358 NULL, &cpu_show_dma, NULL },
359 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "DMA4", NULL,
360 NULL, &cpu_show_dma, NULL },
361 { 0 }
362 };
363
364 DEVICE cpu_dev = {
365 "CPU", &cpu_unit, cpu_reg, cpu_mod,
366 1, 8, 15, 1, 8, 16,
367 &cpu_ex, &cpu_dep, &cpu_reset,
368 NULL, NULL, NULL,
369 &cpu_dib, 0
370 };
371
372 t_stat sim_instr (void)
373 {
374 int32 AR, BR, MB, Y, t1, t2, t3, skip, dev;
375 uint32 ut;
376 t_stat reason;
377 t_stat Ea (int32 inst, int32 *addr);
378 void Write (int32 addr, int32 val);
379 int32 Add16 (int32 val1, int32 val2);
380 int32 Add31 (int32 val1, int32 val2);
381 int32 Operate (int32 MB, int32 AR);
382
383 #define Read(ad) M[(ad)]
384 #define GETDBL_S(h,l) (((h) << 15) | ((l) & MMASK))
385 #define GETDBL_U(h,l) (((h) << 16) | (l))
386 #define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \
387 BR = (BR & SIGN) | ((x) & MMASK)
388 #define PUTDBL_U(x) AR = ((x) >> 16) & DMASK; \
389 BR = (x) & DMASK
390 #define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))
391 #define NEWA(c,n) (ext? (((c) & ~X_AMASK) | ((n) & X_AMASK)): \
392 (((c) & ~NX_AMASK) | ((n) & NX_AMASK)))
393
394 /* Restore register state */
395
396 if (devtab_init ()) return SCPE_STOP; /* init tables */
397 AR = saved_AR & DMASK; /* restore reg */
398 BR = saved_BR & DMASK;
399 XR = saved_XR & DMASK;
400 PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */
401 reason = 0;
402
403 /* Main instruction fetch/decode loop */
404
405 while (reason == 0) { /* loop until halted */
406
407 if (sim_interval <= 0) { /* check clock queue */
408 if (reason = sim_process_event ()) break;
409 }
410
411 /* Channel breaks (DMA and DMC) */
412
413 if (chan_req) { /* channel request? */
414 int32 i, t, ch, dev, st, end, ad, dmcad;
415 t_stat r;
416 for (i = 0, ch = chan_req; ch != 0; i++, ch = ch >> 1) {
417 if (ch & 1) { /* req on chan i? */
418 dev = chan_map[i]; /* get dev for chan */
419 if (iotab[dev] == &undio) return SCPE_IERR;
420 chan_req = chan_req & ~(1 << i); /* clear req */
421 if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */
422 else { /* DMC */
423 dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1);
424 st = Read (dmcad); /* DMC ctrl word */
425 }
426 ad = st & X_AMASK; /* get curr addr */
427 if (st & DMA_IN) { /* input? */
428 t = iotab[dev] (ioINA, 0, 0, dev); /* input word */
429 if ((t & IOT_SKIP) == 0) return STOP_DMAER;
430 if ((r = t >> IOT_V_REASON) != 0) return r;
431 Write (ad, t & DMASK); /* write to mem */
432 }
433 else { /* no, output */
434 t = iotab[dev] (ioOTA, 0, Read (ad), dev); /* output word */
435 if ((t & IOT_SKIP) == 0) return STOP_DMAER;
436 if (r = (t >> IOT_V_REASON)) return r;
437 }
438 if (Q_DMA (i)) { /* DMA? */
439 dma_ad[i] = (dma_ad[i] & DMA_IN) | ((ad + 1) & X_AMASK);
440 dma_wc[i] = (dma_wc[i] + 1) & 077777; /* update wc */
441 if (dma_wc[i] == 0) { /* done? */
442 dma_eor[i] = 1; /* set end of range */
443 t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
444 if ((r = t >> IOT_V_REASON) != 0) return r;
445 }
446 }
447 else { /* DMC */
448 st = (st & DMA_IN) | ((ad + 1) & X_AMASK);
449 Write (dmcad, st); /* update start */
450 end = Read (dmcad + 1); /* get end */
451 if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */
452 t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
453 if ((r = t >> IOT_V_REASON) != 0) return r;
454 } /* end if end range */
455 } /* end else DMC */
456 } /* end if chan i */
457 } /* end for */
458 } /* end if chan_req */
459
460
461 /* Interrupts */
462
463 if ((dev_int & (INT_PEND|INT_NMI|dev_enb)) > INT_PEND) {/* int req? */
464 pme = ext; /* save extend */
465 if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */
466 dev_int = dev_int & ~INT_ON; /* intr off */
467 MB = 0120000 | M_INT; /* inst = JST* 63 */
468 }
469
470 /* Instruction fetch */
471
472 else {
473 if (sim_brk_summ &&
474 sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
475 reason = STOP_IBKPT; /* stop simulation */
476 break;
477 }
478 Y = PC; /* set mem addr */
479 MB = Read (Y); /* fetch instr */
480 PC = NEWA (Y, Y + 1); /* incr PC */
481 dev_int = dev_int | INT_NODEF;
482 }
483
484 dev_int = dev_int & ~INT_START; /* clr start button int */
485 sim_interval = sim_interval - 1;
486 if (hst_lnt) { /* instr hist? */
487 hst_p = (hst_p + 1); /* next entry */
488 if (hst_p >= hst_lnt) hst_p = 0;
489 hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */
490 hst[hst_p].ir = MB;
491 hst[hst_p].ar = AR;
492 hst[hst_p].br = BR;
493 hst[hst_p].xr = XR;
494 }
495
496 /* Memory reference instructions */
497
498 switch (I_GETOP (MB)) { /* case on <1:6> */
499
500 case 001: case 021: case 041: case 061: /* JMP */
501 if (reason = Ea (MB, &Y)) break; /* eff addr */
502 PCQ_ENTRY; /* save PC */
503 PC = NEWA (PC, Y); /* set new PC */
504 if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */
505 break;
506
507 case 002: case 022: case 042: case 062: /* LDA */
508 if (reason = Ea (MB, &Y)) break; /* eff addr */
509 if (dp) { /* double prec? */
510 AR = Read (Y & ~1); /* get doubleword */
511 BR = Read (Y | 1);
512 sc = 0;
513 }
514 else AR = Read (Y); /* no, get word */
515 break;
516
517 case 003: case 023: case 043: case 063: /* ANA */
518 if (reason = Ea (MB, &Y)) break; /* eff addr */
519 AR = AR & Read (Y);
520 break;
521
522 case 004: case 024: case 044: case 064: /* STA */
523 if (reason = Ea (MB, &Y)) break; /* eff addr */
524 Write (Y, AR); /* store A */
525 if (dp) { /* double prec? */
526 Write (Y | 1, BR); /* store B */
527 sc = 0;
528 }
529 break;
530
531 case 005: case 025: case 045: case 065: /* ERA */
532 if (reason = Ea (MB, &Y)) break; /* eff addr */
533 AR = AR ^ Read (Y);
534 break;
535
536 case 006: case 026: case 046: case 066: /* ADD */
537 if (reason = Ea (MB, &Y)) break; /* eff addr */
538 if (dp) { /* double prec? */
539 t1 = GETDBL_S (AR, BR); /* get A'B */
540 t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1));
541 t1 = Add31 (t1, t2); /* 31b add */
542 PUTDBL_S (t1);
543 sc = 0;
544 }
545 else AR = Add16 (AR, Read (Y)); /* no, 16b add */
546 break;
547
548 case 007: case 027: case 047: case 067: /* SUB */
549 if (reason = Ea (MB, &Y)) break; /* eff addr */
550 if (dp) { /* double prec? */
551 t1 = GETDBL_S (AR, BR); /* get A'B */
552 t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1));
553 t1 = Add31 (t1, -t2); /* 31b sub */
554 PUTDBL_S (t1);
555 sc = 0;
556 }
557 else AR = Add16 (AR, (-Read (Y)) & DMASK); /* no, 16b sub */
558 break;
559
560 case 010: case 030: case 050: case 070: /* JST */
561 if (reason = Ea (MB, &Y)) break; /* eff addr */
562 MB = NEWA (Read (Y), PC); /* merge old PC */
563 Write (Y, MB);
564 PCQ_ENTRY;
565 PC = NEWA (PC, Y + 1); /* set new PC */
566 break;
567
568 case 011: case 031: case 051: case 071: /* CAS */
569 if (reason = Ea (MB, &Y)) break; /* eff addr */
570 MB = Read (Y);
571 if (AR == MB) PC = NEWA (PC, PC + 1);
572 else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2);
573 break;
574
575 case 012: case 032: case 052: case 072: /* IRS */
576 if (reason = Ea (MB, &Y)) break; /* eff addr */
577 MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */
578 Write (Y, MB);
579 if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */
580 break;
581
582 case 013: case 033: case 053: case 073: /* IMA */
583 if (reason = Ea (MB, &Y)) break; /* eff addr */
584 MB = Read (Y);
585 Write (Y, AR); /* A to mem */
586 AR = MB; /* mem to A */
587 break;
588
589 case 015: case 055: /* STX */
590 if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
591 Write (Y, XR); /* store XR */
592 break;
593
594 case 035: case 075: /* LDX */
595 if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
596 XR = Read (Y); /* load XR */
597 break;
598
599 case 016: case 036: case 056: case 076: /* MPY */
600 if (cpu_unit.flags & UNIT_HSA) { /* installed? */
601 if (reason = Ea (MB, &Y)) break; /* eff addr */
602 t1 = SEXT (AR) * SEXT (Read (Y));
603 PUTDBL_S (t1);
604 sc = 0;
605 }
606 else reason = stop_inst;
607 break;
608
609 case 017: case 037: case 057: case 077: /* DIV */
610 if (cpu_unit.flags & UNIT_HSA) { /* installed? */
611 if (reason = Ea (MB, &Y)) break; /* eff addr */
612 t2 = SEXT (Read (Y)); /* divr */
613 if (t2) { /* divr != 0? */
614 t1 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */
615 BR = (t1 % t2) & DMASK; /* remainder */
616 t1 = t1 / t2; /* quotient */
617 AR = t1 & DMASK;
618 if ((t1 > MMASK) || (t1 < (-SIGN))) C = 1;
619 else C = 0;
620 sc = 0;
621 }
622 else C = 1;
623 }
624 else reason = stop_inst;
625 break;
626
627 /* I/O instructions */
628
629 case 014: /* OCP */
630 dev = MB & DEVMASK;
631 t2 = iotab[dev] (ioOCP, I_GETFNC (MB), AR, dev);
632 reason = t2 >> IOT_V_REASON;
633 break;
634
635 case 034: /* SKS */
636 dev = MB & DEVMASK;
637 t2 = iotab[dev] (ioSKS, I_GETFNC (MB), AR, dev);
638 reason = t2 >> IOT_V_REASON;
639 if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
640 break;
641
642 case 054: /* INA */
643 dev = MB & DEVMASK;
644 if (MB & INCLRA) AR = 0;
645 t2 = iotab[dev] (ioINA, I_GETFNC (MB & ~INCLRA), AR, dev);
646 reason = t2 >> IOT_V_REASON;
647 if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
648 AR = t2 & DMASK; /* data */
649 break;
650
651 case 074: /* OTA */
652 dev = MB & DEVMASK;
653 t2 = iotab[dev] (ioOTA, I_GETFNC (MB), AR, dev);
654 reason = t2 >> IOT_V_REASON;
655 if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
656 break;
657
658 /* Control */
659
660 case 000:
661 if ((MB & 1) == 0) { /* HLT */
662 if ((reason = sim_process_event ()) != SCPE_OK) break;
663 reason = STOP_HALT;
664 break;
665 }
666 if (MB & m14) { /* SGL, DBL */
667 if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0;
668 else reason = stop_inst;
669 }
670 if (MB & m13) { /* DXA, EXA */
671 if (!(cpu_unit.flags & UNIT_EXT)) reason = stop_inst;
672 else if (MB & m15) { /* EXA */
673 ext = 1;
674 extoff_pending = 0; /* DXA */
675 }
676 else extoff_pending = 1;
677 }
678 if (MB & m12) CLR_INT (INT_MPE); /* RMP */
679 if (MB & m11) { /* SCA, INK */
680 if (MB & m15) /* INK */
681 AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037);
682 else if (cpu_unit.flags & UNIT_HSA) /* SCA */
683 AR = sc & 037;
684 else reason = stop_inst;
685 }
686 else if (MB & m10) { /* NRM */
687 if (cpu_unit.flags & UNIT_HSA) {
688 for (sc = 0;
689 (sc <= 32) && ((AR & SIGN) != ((AR << 1) & SIGN));
690 sc++) {
691 AR = (AR & SIGN) | ((AR << 1) & MMASK) |
692 ((BR >> 14) & 1);
693 BR = (BR & SIGN) | ((BR << 1) & MMASK);
694 }
695 sc = sc & 037;
696 }
697 else reason = stop_inst;
698 }
699 else if (MB & m9) { /* IAB */
700 sc = BR;
701 BR = AR;
702 AR = sc;
703 }
704 if (MB & m8) /* ENB */
705 dev_int = (dev_int | INT_ON) & ~INT_NODEF;
706 if (MB & m7) /* INH */
707 dev_int = dev_int & ~INT_ON;
708 break;
709
710 /* Shift
711
712 Shifts are microcoded as follows:
713
714 op<7> = right/left
715 op<8> = long/short
716 op<9> = shift/rotate (rotate bits "or" into new position)
717 op<10> = logical/arithmetic
718
719 If !op<7> && op<10> (right arithmetic), A<1> propagates rightward
720 If op<7> && op<10> (left arithmetic), C is set if A<1> changes state
721 If !op<8> && op<10> (long arithmetic), B<1> is skipped
722
723 This microcoding "explains" how the 4 undefined opcodes actually work
724 003 = long arith rotate right, skip B<1>, propagate A<1>,
725 bits rotated out "or" into A<1>
726 007 = short arith rotate right, propagate A<1>,
727 bits rotated out "or" into A<1>
728 013 = long arith rotate left, skip B<1>, C = overflow
729 017 = short arith rotate left, C = overflow
730 */
731
732 case 020:
733 C = 0; /* clear C */
734 sc = 0; /* clear sc */
735 if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */
736 switch (I_GETFNC (MB)) { /* case shift fnc */
737
738 case 000: /* LRL */
739 if (t1 > 32) ut = 0; /* >32? all 0 */
740 else {
741 ut = GETDBL_U (AR, BR); /* get A'B */
742 C = (ut >> (t1 - 1)) & 1; /* C = last out */
743 if (t1 == 32) ut = 0; /* =32? all 0 */
744 else ut = ut >> t1; /* log right */
745 }
746 PUTDBL_U (ut); /* store A,B */
747 break;
748
749 case 001: /* LRS */
750 if (t1 > 31) t1 = 31; /* limit to 31 */
751 t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */
752 C = (t2 >> (t1 - 1)) & 1; /* C = last out */
753 t2 = t2 >> t1; /* arith right */
754 PUTDBL_S (t2); /* store A,B */
755 break;
756
757 case 002: /* LRR */
758 t2 = t1 % 32; /* mod 32 */
759 ut = GETDBL_U (AR, BR); /* get A'B */
760 ut = (ut >> t2) | (ut << (32 - t2)); /* rot right */
761 C = (ut >> 31) & 1; /* C = A<1> */
762 PUTDBL_U (ut); /* store A,B */
763 break;
764
765 case 003: /* "long right arot" */
766 if (reason = stop_inst) break; /* stop on undef? */
767 for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
768 C = BR & 1; /* C = last out */
769 BR = (BR & SIGN) | ((AR & 1) << 14) |
770 ((BR & MMASK) >> 1);
771 AR = ((AR & SIGN) | (C << 15)) | (AR >> 1);
772 }
773 break;
774
775 case 004: /* LGR */
776 if (t1 > 16) AR = 0; /* > 16? all 0 */
777 else {
778 C = (AR >> (t1 - 1)) & 1; /* C = last out */
779 AR = (AR >> t1) & DMASK; /* log right */
780 }
781 break;
782
783 case 005: /* ARS */
784 if (t1 > 16) t1 = 16; /* limit to 16 */
785 C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */
786 AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */
787 break;
788
789 case 006: /* ARR */
790 t2 = t1 % 16; /* mod 16 */
791 AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK;
792 C = (AR >> 15) & 1; /* C = A<1> */
793 break;
794
795 case 007: /* "short right arot" */
796 if (reason = stop_inst) break; /* stop on undef? */
797 for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
798 C = AR & 1; /* C = last out */
799 AR = ((AR & SIGN) | (C << 15)) | (AR >> 1);
800 }
801 break;
802
803 case 010: /* LLL */
804 if (t1 > 32) ut = 0; /* > 32? all 0 */
805 else {
806 ut = GETDBL_U (AR, BR); /* get A'B */
807 C = (ut >> (32 - t1)) & 1; /* C = last out */
808 if (t1 == 32) ut = 0; /* =32? all 0 */
809 else ut = ut << t1; /* log left */
810 }
811 PUTDBL_U (ut); /* store A,B */
812 break;
813
814 case 011: /* LLS */
815 if (t1 > 31) t1 = 31; /* limit to 31 */
816 t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */
817 t3 = t2 << t1; /* "arith" left */
818 PUTDBL_S (t3); /* store A'B */
819 if ((t2 >> (31 - t1)) != /* shf out = sgn? */
820 ((AR & SIGN)? -1: 0)) C = 1;
821 break;
822
823 case 012: /* LLR */
824 t2 = t1 % 32; /* mod 32 */
825 ut = GETDBL_U (AR, BR); /* get A'B */
826 ut = (ut << t2) | (ut >> (32 - t2)); /* rot left */
827 C = ut & 1; /* C = B<16> */
828 PUTDBL_U (ut); /* store A,B */
829 break;
830
831 case 013: /* "long left arot" */
832 if (reason = stop_inst) break; /* stop on undef? */
833 for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
834 AR = (AR << 1) | ((BR >> 14) & 1);
835 BR = (BR & SIGN) | ((BR << 1) & MMASK) |
836 ((AR >> 16) & 1);
837 if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1;
838 AR = AR & DMASK;
839 }
840 break;
841
842 case 014: /* LGL */
843 if (t1 > 16) AR = 0; /* > 16? all 0 */
844 else {
845 C = (AR >> (16 - t1)) & 1; /* C = last out */
846 AR = (AR << t1) & DMASK; /* log left */
847 }
848 break;
849
850 case 015: /* ALS */
851 if (t1 > 16) t1 = 16; /* limit to 16 */
852 t2 = SEXT (AR); /* save AR */
853 AR = (AR << t1) & DMASK; /* "arith" left */
854 if ((t2 >> (16 - t1)) != /* shf out + sgn */
855 ((AR & SIGN)? -1: 0)) C = 1;
856 break;
857
858 case 016: /* ALR */
859 t2 = t1 % 16; /* mod 16 */
860 AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK;
861 C = AR & 1; /* C = A<16> */
862 break;
863
864 case 017: /* "short left arot" */
865 if (reason = stop_inst) break; /* stop on undef? */
866 for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
867 if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1;
868 AR = ((AR << 1) | (AR >> 15)) & DMASK;
869 }
870 break; /* end case fnc */
871 }
872 break;
873
874 /* Skip */
875
876 case 040:
877 skip = 0;
878 if (((MB & 000001) && C) || /* SSC */
879 ((MB & 000002) && ss[3]) || /* SS4 */
880 ((MB & 000004) && ss[2]) || /* SS3 */
881 ((MB & 000010) && ss[1]) || /* SS2 */
882 ((MB & 000020) && ss[0]) || /* SS1 */
883 ((MB & 000040) && AR) || /* SNZ */
884 ((MB & 000100) && (AR & 1)) || /* SLN */
885 ((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */
886 ((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */
887 if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */
888 PC = NEWA (PC, PC + skip);
889 break;
890
891 /* Operate */
892
893 case 060:
894 if (MB == 0140024) AR = AR ^ SIGN; /* CHS */
895 else if (MB == 0140040) AR = 0; /* CRA */
896 else if (MB == 0140100) AR = AR & ~SIGN; /* SSP */
897 else if (MB == 0140200) C = 0; /* RCB */
898 else if (MB == 0140320) { /* CSA */
899 C = (AR & SIGN) >> 15;
900 AR = AR & ~SIGN;
901 }
902 else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */
903 else if (MB == 0140407) { /* TCA */
904 AR = (-AR) & DMASK;
905 sc = 0;
906 }
907 else if (MB == 0140500) AR = AR | SIGN; /* SSM */
908 else if (MB == 0140600) C = 1; /* SCB */
909 else if (MB == 0141044) AR = AR & 0177400; /* CAR */
910 else if (MB == 0141050) AR = AR & 0377; /* CAL */
911 else if (MB == 0141140) AR = AR >> 8; /* ICL */
912 else if (MB == 0141206) AR = Add16 (AR, 1); /* AOA */
913 else if (MB == 0141216) AR = Add16 (AR, C); /* ACA */
914 else if (MB == 0141240) AR = (AR << 8) & DMASK; /* ICR */
915 else if (MB == 0141340) /* ICA */
916 AR = ((AR << 8) | (AR >> 8)) & DMASK;
917 else if (reason = stop_inst) break;
918 else AR = Operate (MB, AR); /* undefined */
919 break;
920 } /* end case op */
921 } /* end while */
922
923 saved_AR = AR & DMASK;
924 saved_BR = BR & DMASK;
925 saved_XR = XR & DMASK;
926 pcq_r->qptr = pcq_p; /* update pc q ptr */
927 return reason;
928 }
929
930 /* Effective address
931
932 The effective address calculation consists of three phases:
933 - base address calculation: 0/pagenumber'displacement
934 - (extend): indirect address resolution
935 (non-extend): pre-indexing
936 - (extend): post-indexing
937 (non-extend): indirect address/post-indexing resolution
938
939 In extend mode, address calculations are carried out to 16b
940 and masked to 15b at exit. In non-extend mode, address bits
941 <1:2> are preserved by the NEWA macro; address bit <1> is
942 masked at exit.
943 */
944
945 t_stat Ea (int32 IR, int32 *addr)
946 {
947 int32 i;
948 int32 Y = IR & (IA | DISP); /* ind + disp */
949
950 if (IR & SC) Y = ((PC - 1) & PAGENO) | Y; /* cur sec? + pageno */
951 if (ext) { /* extend mode? */
952 for (i = 0; (i < ind_max) && (Y & IA); i++) { /* resolve ind addr */
953 Y = Read (Y & X_AMASK); /* get ind addr */
954 }
955 if (IR & IDX) Y = Y + XR; /* post-index */
956 } /* end if ext */
957 else { /* non-extend */
958 Y = NEWA (PC, Y + ((IR & IDX)? XR: 0)); /* pre-index */
959 for (i = 0; (i < ind_max) && (IR & IA); i++) { /* resolve ind addr */
960 IR = Read (Y & X_AMASK); /* get ind addr */
961 Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); /* post-index */
962 }
963 } /* end else */
964 *addr = Y = Y & X_AMASK; /* return addr */
965 if (hst_lnt) { /* history? */
966 hst[hst_p].pc = hst[hst_p].pc | HIST_EA;
967 hst[hst_p].ea = Y;
968 hst[hst_p].opnd = Read (Y);
969 }
970 if (i >= ind_max) return STOP_IND; /* too many ind? */
971 return SCPE_OK;
972 }
973
974 /* Write memory */
975
976 void Write (int32 addr, int32 val)
977 {
978 if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr))
979 M[addr] = val;
980 return;
981 }
982
983 /* Add */
984
985 int32 Add16 (int32 v1, int32 v2)
986 {
987 int32 r = v1 + v2;
988
989 if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1;
990 else C = 0;
991 return (r & DMASK);
992 }
993
994 int32 Add31 (int32 v1, int32 v2)
995 {
996 int32 r = v1 + v2;
997
998 if (((v1 ^ ~v2) & (v1 ^ r)) & DP_SIGN) C = 1;
999 else C = 0;
1000 return r;
1001 }
1002
1003 /* Unimplemented I/O device */
1004
1005 int32 undio (int32 op, int32 fnc, int32 val, int32 dev)
1006 {
1007 return ((stop_dev << IOT_V_REASON) | val);
1008 }
1009
1010 /* DMA control */
1011
1012 int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev)
1013 {
1014 int32 ch = (fnc - 1) & 03;
1015
1016 switch (inst) { /* case on opcode */
1017
1018 case ioOCP: /* OCP */
1019 if ((fnc >= 001) && (fnc <= 004)) { /* load addr ctr */
1020 dma_ad[ch] = dat;
1021 dma_wc[ch] = 0;
1022 dma_eor[ch] = 0;
1023 }
1024 else if ((fnc >= 011) && (fnc <= 014)) /* load range ctr */
1025 dma_wc[ch] = (dma_wc[ch] | dat) & 077777;
1026 else return IOBADFNC (dat); /* undefined */
1027 break;
1028
1029 case ioINA: /* INA */
1030 if ((fnc >= 011) && (fnc <= 014)) {
1031 if (dma_eor[ch]) return dat; /* end range? nop */
1032 return IOSKIP (0100000 | dma_wc[ch]); /* return range */
1033 }
1034 else return IOBADFNC (dat);
1035 }
1036
1037 return dat;
1038 }
1039
1040 /* Undefined operate instruction. This code is reached when the
1041 opcode does not correspond to a standard operate instruction.
1042 It simulates the behavior of the actual logic.
1043
1044 An operate instruction executes in 4 or 6 phases. A 'normal'
1045 instruction takes 4 phases:
1046
1047 t1 t1
1048 t2/tlate t2/t2 extended into t3
1049 t3/tlate t3
1050 t4 t4
1051
1052 A '1.5 cycle' instruction takes 6 phases:
1053
1054 t1 t1
1055 t2/tlate t2/t2 extended into t3
1056 t3/tlate t3
1057 t2/tlate 'special' t2/t2 extended into t3
1058 t3/tlate t3
1059 t4 t4
1060
1061 The key signals, by phase, are the following
1062
1063 tlate EASTL enable A to sum leg 1 (else 0)
1064 (((m12+m16)x!azzzz)+(m9+m11+azzzz)
1065 EASBM enable 0 to sum leg 2 (else 177777)
1066 (m9+m11+azzzz)
1067 JAMKN jam carry network to 0 = force XOR
1068 ((m12+m16)x!azzzz)
1069 EIKI7 force carry into adder
1070 ((m15x(C+!m13))x!JAMKN)
1071
1072 t3 CLDTR set D to 177777 (always)
1073 ESDTS enable adder sum to D (always)
1074 SETAZ enable repeat cycle = set azzzz
1075 (m8xm15)
1076
1077 if azzzz {
1078 t2 CLATR clear A register (due to azzzz)
1079 EDAHS enable D high to A high register (due to azzzz)
1080 EDALS enable D low to A low register (due to azzzz)
1081
1082 tlate, t3 as above
1083 }
1084
1085 t4 CLATR clear A register
1086 (m11+m15+m16)
1087 CLA1R clear A1 register
1088 (m10+m14)
1089 EDAHS enable D high to A high register
1090 ((m11xm14)+m15+m16)
1091 EDALS enable D low to A low register
1092 ((m11xm13)+m15+m16)
1093 ETAHS enable D transposed to A high register
1094 (m9xm11)
1095 ETALS enable D transposed to A low register
1096 (m10xm11)
1097 EDA1R enable D1 to A1 register
1098 ((m8xm10)+m14)
1099 CBITL clear C, conditionally set C from adder output
1100 (m9x!m11)
1101 CBITG conditionally set C if D1
1102 (m10xm12xD1)
1103 CBITE unconditionally set C
1104 (m8xm9)
1105 */
1106
1107 int32 Operate (int32 MB, int32 AR)
1108 {
1109 int32 D, jamkn, eiki7, easbm, eastl, setaz;
1110 int32 clatr, cla1r, edahs, edals, etahs, etals, eda1r;
1111 int32 cbitl, cbitg, cbite;
1112 int32 aleg, bleg, ARx;
1113
1114 /* Phase tlate */
1115
1116 ARx = AR; /* default */
1117 jamkn = (MB & (m12+m16)) != 0; /* m12+m16 */
1118 easbm = (MB & (m9+m11)) != 0; /* m9+m11 */
1119 eastl = jamkn || easbm; /* m9+m11+m12+m16 */
1120 setaz = (MB & (m8+m15)) == (m8+m15); /* m8xm15*/
1121 eiki7 = (MB & m15) && (C || !(MB & m13)); /* cin */
1122 aleg = eastl? AR: 0; /* a input */
1123 bleg = easbm? 0: DMASK; /* b input */
1124 if (jamkn) D = aleg ^ bleg; /* jammin? xor */
1125 else D = (aleg + bleg + eiki7) & DMASK; /* else add */
1126
1127 /* Possible repeat at end of tlate - special t2, repeat tlate */
1128
1129 if (setaz) {
1130 ARx = D; /* forced: t2 */
1131 aleg = ARx; /* forced: tlate */
1132 bleg = 0; /* forced */
1133 jamkn = 0; /* forced */
1134 D = (aleg + bleg + eiki7) & DMASK; /* forced add */
1135 sc = 0; /* ends repeat */
1136 }
1137
1138 /* Phase t4 */
1139
1140 clatr = (MB & (m11+m15+m16)) != 0; /* m11+m15+m16 */
1141 cla1r = (MB & (m10+m14)) != 0; /* m10+m14 */
1142 edahs = ((MB & (m11+m14)) == (m11+m14)) || /* (m11xm14)+m15+m16 */
1143 (MB & (m15+m16));
1144 edals = ((MB & (m11+m13)) == (m11+m13)) || /* (m11xm13)+m15+m16 */
1145 (MB & (m15+m16));
1146 etahs = (MB & (m9+m11)) == (m9+m11); /* m9xm11 */
1147 etals = (MB & (m10+m11)) == (m10+m11); /* m10xm11 */
1148 eda1r = ((MB & (m8+m10)) == (m8+m10)) || (MB & m14); /* (m8xm10)+m14 */
1149 cbitl = (MB & (m9+m11)) == m9; /* m9x!m11 */
1150 cbite = (MB & (m8+m9)) == (m8+m9); /* m8xm9 */
1151 cbitg = (MB & (m10+m12)) == (m10+m12); /* m10xm12 */
1152
1153 if (clatr) ARx = 0; /* clear A */
1154 if (cla1r) ARx = ARx & ~SIGN; /* clear A1 */
1155 if (edahs) ARx = ARx | (D & 0177400); /* D hi to A hi */
1156 if (edals) ARx = ARx | (D & 0000377); /* D lo to A lo */
1157 if (etahs) ARx = ARx | ((D << 8) & 0177400); /* D lo to A hi */
1158 if (etals) ARx = ARx | ((D >> 8) & 0000377); /* D hi to A lo */
1159 if (eda1r) ARx = ARx | (D & SIGN); /* D1 to A1 */
1160 if (cbitl) { /* ovflo to C */
1161
1162 /* Overflow calculation. Cases:
1163
1164 aleg bleg cin overflow
1165
1166 0 x x can't overflow
1167 A 0 0 can't overflow
1168 A -1 1 can't overflow
1169 A 0 1 overflow if 77777->100000
1170 A -1 0 overflow if 100000->77777
1171 */
1172
1173 if (!jamkn &&
1174 ((bleg && !eiki7 && (D == 0077777)) ||
1175 (!bleg && eiki7 && (D == 0100000)))) C = 1;
1176 else C = 0;
1177 }
1178 if (cbite || (cbitg && (D & SIGN))) C = 1; /* C = 1 */
1179 return ARx;
1180 }
1181
1182 /* Reset routines */
1183
1184 t_stat cpu_reset (DEVICE *dptr)
1185 {
1186 int32 i;
1187
1188 saved_AR = saved_BR = saved_XR = 0;
1189 C = 0;
1190 dp = 0;
1191 ext = pme = extoff_pending = 0;
1192 dev_int = dev_int & ~(INT_PEND|INT_NMI);
1193 dev_enb = 0;
1194 for (i = 0; i < DMA_MAX; i++) dma_ad[i] = dma_wc[i] = dma_eor[i] = 0;
1195 chan_req = 0;
1196 pcq_r = find_reg ("PCQ", NULL, dptr);
1197 if (pcq_r) pcq_r->qptr = 0;
1198 else return SCPE_IERR;
1199 sim_brk_types = sim_brk_dflt = SWMASK ('E');
1200 return SCPE_OK;
1201 }
1202
1203 /* Memory examine */
1204
1205 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
1206 {
1207 int32 d;
1208
1209 if (addr >= MEMSIZE) return SCPE_NXM;
1210 if (addr == 0) d = saved_XR;
1211 else d = M[addr];
1212 if (vptr != NULL) *vptr = d & DMASK;
1213 return SCPE_OK;
1214 }
1215
1216 /* Memory deposit */
1217
1218 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
1219 {
1220 if (addr >= MEMSIZE) return SCPE_NXM;
1221 if (addr == 0) saved_XR = val & DMASK;
1222 else M[addr] = val & DMASK;
1223 return SCPE_OK;
1224 }
1225
1226 /* Option processors */
1227
1228 t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc)
1229 {
1230 if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG;
1231 return SCPE_OK;
1232 }
1233
1234 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
1235 {
1236 int32 mc = 0;
1237 uint32 i;
1238
1239 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) ||
1240 (((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1))))
1241 return SCPE_ARG;
1242 for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
1243 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
1244 return SCPE_OK;
1245 MEMSIZE = val;
1246 for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
1247 return SCPE_OK;
1248 }
1249
1250 t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc)
1251 {
1252 uint32 i, newmax;
1253 t_stat r;
1254
1255 if (cptr == NULL) return SCPE_ARG;
1256 newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */
1257 if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */
1258 dma_nch = newmax; /* set new max */
1259 for (i = newmax; i < DMA_MAX; i++) { /* reset chan */
1260 dma_ad[i] = dma_wc[i] = dma_eor[i] = 0;
1261 chan_req = chan_req & ~(1 << i);
1262 }
1263 return SCPE_OK;
1264 }
1265
1266 /* Show DMA channels */
1267
1268 t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc)
1269 {
1270 if (dma_nch) fprintf (st, "DMA channels = %d", dma_nch);
1271 else fprintf (st, "no DMA channels");
1272 return SCPE_OK;
1273 }
1274
1275 /* Show channel state */
1276
1277 t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc)
1278 {
1279 if ((val < 0) || (val >= DMA_MAX)) return SCPE_IERR;
1280 fputs ((dma_ad[val] & DMA_IN)? "Input": "Output", st);
1281 fprintf (st, ", addr = %06o, count = %06o, ", dma_ad[val] & X_AMASK, dma_wc[val]);
1282 fprintf (st, "end of range %s\n", (dma_eor[val]? "set": "clear"));
1283 return SCPE_OK;
1284 }
1285
1286 /* Set I/O device to IOBUS / DMA channel / DMC channel */
1287
1288 t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc)
1289 {
1290 DEVICE *dptr;
1291 DIB *dibp;
1292
1293 if (val || cptr || (uptr == NULL)) return SCPE_IERR;
1294 dptr = find_dev_from_unit (uptr);
1295 if (dptr == NULL) return SCPE_IERR;
1296 dibp = (DIB *) dptr->ctxt;
1297 if (dibp == NULL) return SCPE_IERR;
1298 dibp->chan = 0;
1299 return SCPE_OK;
1300 }
1301
1302 t_stat io_set_dma (UNIT *uptr, int32 val, char *cptr, void *desc)
1303 {
1304 DEVICE *dptr;
1305 DIB *dibp;
1306 uint32 newc;
1307 t_stat r;
1308
1309 if ((cptr == NULL) || (uptr == NULL)) return SCPE_IERR;
1310 dptr = find_dev_from_unit (uptr);
1311 if (dptr == NULL) return SCPE_IERR;
1312 dibp = (DIB *) dptr->ctxt;
1313 if (dibp == NULL) return SCPE_IERR;
1314 if (dma_nch == 0) return SCPE_NOFNC;
1315 newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */
1316 if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) return SCPE_ARG;
1317 dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */
1318 return SCPE_OK;
1319 }
1320
1321 t_stat io_set_dmc (UNIT *uptr, int32 val, char *cptr, void *desc)
1322 {
1323 DEVICE *dptr;
1324 DIB *dibp;
1325 uint32 newc;
1326 t_stat r;
1327
1328 if ((cptr == NULL) || (uptr == NULL)) return SCPE_IERR;
1329 dptr = find_dev_from_unit (uptr);
1330 if (dptr == NULL) return SCPE_IERR;
1331 dibp = (DIB *) dptr->ctxt;
1332 if (dibp == NULL) return SCPE_IERR;
1333 if (!(cpu_unit.flags & UNIT_DMC)) return SCPE_NOFNC;
1334 newc = get_uint (cptr, 10, DMC_MAX, &r); /* get new */
1335 if ((r != SCPE_OK) || (newc == 0)) return SCPE_ARG;
1336 dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */
1337 return SCPE_OK;
1338 }
1339
1340 /* Show channel configuration */
1341
1342 t_stat io_show_chan (FILE *st, UNIT *uptr, int32 val, void *desc)
1343 {
1344 DEVICE *dptr;
1345 DIB *dibp;
1346
1347 if (uptr == NULL) return SCPE_IERR;
1348 dptr = find_dev_from_unit (uptr);
1349 if (dptr == NULL) return SCPE_IERR;
1350 dibp = (DIB *) dptr->ctxt;
1351 if (dibp == NULL) return SCPE_IERR;
1352 if (dibp->chan == 0) fprintf (st, "IO bus");
1353 else if (dibp->chan < (DMC_V_DMC1 + 1))
1354 fprintf (st, "DMA channel %d", dibp->chan);
1355 else fprintf (st, "DMC channel %d", dibp->chan - DMC_V_DMC1);
1356 return SCPE_OK;
1357 }
1358
1359 /* Set up I/O dispatch and channel maps */
1360
1361 t_bool devtab_init (void)
1362 {
1363 DEVICE *dptr;
1364 DIB *dibp;
1365 uint32 i, j, dno, chan;
1366
1367 for (i = 0; i < DEV_MAX; i++) iotab[i] = NULL;
1368 for (i = 0; i < (DMA_MAX + DMC_MAX); i++) chan_map[i] = 0;
1369 for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
1370 dibp = (DIB *) dptr->ctxt; /* get DIB */
1371 if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */
1372 dno = dibp->dev; /* device number */
1373 for (j = 0; j < dibp->num; j++) { /* repeat for slots */
1374 if (iotab[dno + j]) { /* conflict? */
1375 printf ("%s device number conflict, devno = %02o\n",
1376 sim_dname (dptr), dno + j);
1377 if (sim_log) fprintf (sim_log,
1378 "%s device number conflict, devno = %02o\n",
1379 sim_dname (dptr), dno + j);
1380 return TRUE;
1381 }
1382 iotab[dno + j] = dibp->io; /* set I/O routine */
1383 } /* end for */
1384 if (dibp->chan) { /* DMA/DMC? */
1385 chan = dibp->chan - 1;
1386 if ((chan < DMC_V_DMC1) && (chan >= dma_nch)) {
1387 printf ("%s configured for DMA channel %d\n",
1388 sim_dname (dptr), chan + 1);
1389 if (sim_log) fprintf (sim_log,
1390 "%s configured for DMA channel %d\n",
1391 sim_dname (dptr), chan + 1);
1392 return TRUE;
1393 }
1394 if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) {
1395 printf ("%s configured for DMC, option disabled\n",
1396 sim_dname (dptr));
1397 if (sim_log) fprintf (sim_log,
1398 "%s configured for DMC, option disabled\n",
1399 sim_dname (dptr));
1400 return TRUE;
1401 }
1402 if (chan_map[chan]) { /* channel conflict? */
1403 printf ("%s DMA/DMC channel conflict, devno = %02o\n",
1404 sim_dname (dptr), dno);
1405 if (sim_log) fprintf (sim_log,
1406 "%s DMA/DMC channel conflict, devno = %02o\n",
1407 sim_dname (dptr), dno);
1408 return TRUE;
1409 }
1410 chan_map[chan] = dno; /* channel back map */
1411 }
1412 } /* end for */
1413 for (i = 0; i < DEV_MAX; i++) { /* fill in blanks */
1414 if (iotab[i] == NULL) iotab[i] = &undio;
1415 }
1416 return FALSE;
1417 }
1418
1419 /* Set history */
1420
1421 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
1422 {
1423 int32 i, lnt;
1424 t_stat r;
1425
1426 if (cptr == NULL) {
1427 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
1428 hst_p = 0;
1429 return SCPE_OK;
1430 }
1431 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
1432 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
1433 hst_p = 0;
1434 if (hst_lnt) {
1435 free (hst);
1436 hst_lnt = 0;
1437 hst = NULL;
1438 }
1439 if (lnt) {
1440 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
1441 if (hst == NULL) return SCPE_MEM;
1442 hst_lnt = lnt;
1443 }
1444 return SCPE_OK;
1445 }
1446
1447 /* Show history */
1448
1449 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
1450 {
1451 int32 cr, k, di, op, lnt;
1452 char *cptr = (char *) desc;
1453 t_value sim_eval;
1454 t_stat r;
1455 InstHistory *h;
1456 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
1457 UNIT *uptr, int32 sw);
1458 static uint8 has_opnd[16] = {
1459 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1
1460 };
1461
1462 if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
1463 if (cptr) {
1464 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
1465 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;
1466 }
1467 else lnt = hst_lnt;
1468 di = hst_p - lnt; /* work forward */
1469 if (di < 0) di = di + hst_lnt;
1470 fprintf (st, "PC C A B X ea IR\n\n");
1471 for (k = 0; k < lnt; k++) { /* print specified */
1472 h = &hst[(++di) % hst_lnt]; /* entry pointer */
1473 if (h->pc & HIST_PC) { /* instruction? */
1474 cr = (h->pc & HIST_C)? 1: 0; /* carry */
1475 fprintf (st, "%05o %o %06o %06o %06o ",
1476 h->pc & X_AMASK, cr, h->ar, h->br, h->xr);
1477 if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea);
1478 else fprintf (st, " ");
1479 sim_eval = h->ir;
1480 if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval,
1481 &cpu_unit, SWMASK ('M'))) > 0)
1482 fprintf (st, "(undefined) %06o", h->ir);
1483 op = I_GETOP (h->ir) & 017; /* base op */
1484 if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd);
1485 fputc ('\n', st); /* end line */
1486 } /* end else instruction */
1487 } /* end for */
1488 return SCPE_OK;
1489 }