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