First Commit of my working state
[simh.git] / GRI / gri_cpu.c
1 /* gri_cpu.c: GRI-909 CPU simulator
2
3 Copyright (c) 2001-2008, 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 GRI-909/GRI-99 CPU
27
28 14-Jan-08 RMS Added GRI-99 support
29 28-Apr-07 RMS Removed clock initialization
30 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
31 18-Jul-04 RMS Fixed missing ao_update calls in AX, AY write
32 17-Jul-04 RMS Revised MSR, EAO based on additional documentation
33 14-Mar-03 RMS Fixed bug in SC queue tracking
34
35 The system state for the GRI-909/GRI-99 is:
36
37 AX<15:0> arithmetic input
38 AY<15:0> arithmetic input
39 BSW<15:0> byte swapper
40 BPK<15:0> byte packer
41 GR[0:5]<15:0> extended general registers
42 MSR<15:0> machine status register
43 TRP<15:0> trap register (subroutine return)
44 SC<14:0> sequence counter
45 XR<15:0> index register (GRI-99 only)
46
47 The GRI-909 has, nominally, just one instruction format: move.
48
49 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
50 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
51 | source | op | destination | move
52 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
53
54 <6:9> operation
55
56 xx1x complement
57 01xx add 1
58 10xx rotate left 1
59 11xx rotate right 1
60
61 In fact, certain of the source and destination operators have side
62 effects, yielding four additional instruction formats: function out,
63 skip on function, memory reference, and conditional jump.
64
65 The function out format is:
66
67 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
68 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
69 | 0 0 0 0 1 0| pulse | destination | function out
70 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
71
72 The skip on function format is:
73
74 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
75 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
76 | source | skip |rv| 0 0 0 0 1 0| skip function
77 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
78
79 The memory reference format is (src and/or dst = 006):
80
81 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
82 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
83 | source | op | mode| destination | memory ref
84 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
85 | address or immediate |
86 +-----------------------------------------------+
87
88 <6:9> operation
89
90 xx0x direct, ea = M[SC+1]
91 xx1x immediate, ea = SC+1
92 xxx1 indirect, M[ea] = M[ea]+1, then ea = M[ea]
93 01xx add 1
94 10xx rotate left 1
95 11xx rotate right 1
96
97 The conditional jump format is (src != 006):
98
99 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
100 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
101 | source | cond|rv|df| 0 0 0 0 1 1| cond jump
102 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
103 | jump address |
104 +-----------------------------------------------+
105
106 <6:9> operation
107
108 xxx0 direct, ea = M[SC+1]
109 xxx1 indirect, ea = M[SC+1], M[ea] = M[ea]+1,
110 then ea = M[ea]
111 xx1x reverse conditional sense
112 x1xx jump if src == 0
113 1xxx jump if src < 0
114
115 This routine is the instruction decode routine for the GRI-909.
116 It is called from the simulator control program to execute
117 instructions in simulated memory, starting at the simulated PC.
118 It runs until 'reason' is set non-zero.
119
120 General notes:
121
122 1. Reasons to stop. The simulator can be stopped by:
123
124 HALT instruction
125 breakpoint encountered
126 unknown source or destination and STOP_OPR flag set
127 I/O error in I/O simulator
128
129 2. Interrupts. The interrupt structure is kept in two parallel variables:
130
131 dev_done device done flags
132 ISR interrupt status register (enables)
133
134 In addition, there is a master interrupt enable, and a one cycle
135 interrupt defer, both kept in dev_done.
136
137 3. Non-existent memory. On the GRI-909, reads to non-existent memory
138 return zero, and writes are ignored. In the simulator, the
139 largest possible memory is instantiated and initialized to zero.
140 Thus, only writes need be checked against actual memory size.
141
142 4. Adding I/O devices. These modules must be modified:
143
144 gri_defs.h add interrupt request definition
145 gri_cpu.c add dev_tab table entry
146 gri_sys.c add sim_devices table entry
147 */
148
149 #include "gri_defs.h"
150
151 #define SCQ_SIZE 64 /* must be 2**n */
152 #define SCQ_MASK (SCQ_SIZE - 1)
153 #define SCQ_ENTRY scq[scq_p = (scq_p - 1) & SCQ_MASK] = SC
154 #define UNIT_V_AO (UNIT_V_UF + 0) /* AO */
155 #define UNIT_AO (1u << UNIT_V_AO)
156 #define UNIT_V_EAO (UNIT_V_UF + 1) /* EAO */
157 #define UNIT_EAO (1u << UNIT_V_EAO)
158 #define UNIT_V_GPR (UNIT_V_UF + 2) /* GPR */
159 #define UNIT_GPR (1u << UNIT_V_GPR)
160 #define UNIT_V_BSWPK (UNIT_V_UF + 3) /* BSW-BPK */
161 #define UNIT_BSWPK (1u << UNIT_V_BSWPK)
162 #define UNIT_V_GRI99 (UNIT_V_UF + 4) /* GRI-99 */
163 #define UNIT_GRI99 (1u << UNIT_V_GRI99)
164 #define UNIT_V_MSIZE (UNIT_V_UF + 5) /* dummy mask */
165 #define UNIT_MSIZE (1u << UNIT_V_MSIZE)
166
167 #define IDX_ADD(x) ((((cpu_unit.flags & UNIT_GRI99) && ((x) & INDEX))? ((x) + XR): (x)) & AMASK)
168
169 uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
170 uint32 SC; /* sequence cntr */
171 uint32 AX, AY, AO; /* arithmetic unit */
172 uint32 IR; /* instr reg */
173 uint32 MA; /* memory addr */
174 uint32 TRP; /* subr return */
175 uint32 MSR; /* machine status */
176 uint32 ISR; /* interrupt status */
177 uint32 BSW, BPK; /* byte swap, pack */
178 uint32 GR[6]; /* extended general regs */
179 uint32 SWR; /* switch reg */
180 uint32 DR; /* display register */
181 uint32 XR; /* index register */
182 uint32 thwh = 0; /* thumbwheel */
183 uint32 dev_done = 0; /* device flags */
184 uint32 bkp = 0; /* bkpt pending */
185 uint32 stop_opr = 1; /* stop ill operator */
186 int16 scq[SCQ_SIZE] = { 0 }; /* PC queue */
187 int32 scq_p = 0; /* PC queue ptr */
188 REG *scq_r = NULL; /* PC queue reg ptr */
189
190 extern int32 sim_interval;
191 extern int32 sim_int_char;
192 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
193
194 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
195 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
196 t_stat cpu_reset (DEVICE *dptr);
197 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
198 t_stat bus_op (uint32 src, uint32 op, uint32 dst);
199
200 /* Dispatch tables for source, dest, function out, skip on function */
201
202 uint32 no_rd (uint32 src);
203 t_stat no_wr (uint32 dst, uint32 val);
204 t_stat no_fo (uint32 op);
205 uint32 no_sf (uint32 op);
206 uint32 zero_rd (uint32 src);
207 t_stat zero_wr (uint32 dst, uint32 val);
208 t_stat zero_fo (uint32 op);
209 uint32 zero_sf (uint32 op);
210 uint32 ir_rd (uint32 op);
211 t_stat ir_fo (uint32 op);
212 uint32 trp_rd (uint32 src);
213 t_stat trp_wr (uint32 dst, uint32 val);
214 uint32 atrp_rd (uint32 src);
215 t_stat atrp_wr (uint32 dst, uint32 val);
216 uint32 isr_rd (uint32 src);
217 t_stat isr_wr (uint32 dst, uint32 val);
218 t_stat isr_fo (uint32 op);
219 uint32 isr_sf (uint32 op);
220 uint32 ma_rd (uint32 src);
221 uint32 mem_rd (uint32 src);
222 t_stat mem_wr (uint32 dst, uint32 val);
223 uint32 sc_rd (uint32 src);
224 t_stat sc_wr (uint32 dst, uint32 val);
225 uint32 swr_rd (uint32 src);
226 uint32 ax_rd (uint32 src);
227 t_stat ax_wr (uint32 dst, uint32 val);
228 uint32 ay_rd (uint32 src);
229 t_stat ay_wr (uint32 dst, uint32 val);
230 uint32 ao_rd (uint32 src);
231 t_stat ao_fo (uint32 op);
232 uint32 ao_sf (uint32 op);
233 uint32 ao_update (void);
234 t_stat eao_fo (uint32 op);
235 uint32 msr_rd (uint32 src);
236 t_stat msr_wr (uint32 dst, uint32 val);
237 uint32 bsw_rd (uint32 src);
238 t_stat bsw_wr (uint32 dst, uint32 val);
239 uint32 bpk_rd (uint32 src);
240 t_stat bpk_wr (uint32 dst, uint32 val);
241 uint32 gr_rd (uint32 src);
242 t_stat gr_wr (uint32 dst, uint32 val);
243 uint32 xr_rd (uint32 src);
244 t_stat xr_wr (uint32 dst, uint32 val);
245
246 extern t_stat rtc_fo (uint32 op);
247 extern uint32 rtc_sf (uint32 op);
248 extern uint32 hsrp_rd (uint32 src);
249 extern t_stat hsrp_wr (uint32 dst, uint32 val);
250 extern t_stat hsrp_fo (uint32 op);
251 extern uint32 hsrp_sf (uint32 op);
252 extern uint32 tty_rd (uint32 src);
253 extern t_stat tty_wr (uint32 dst, uint32 val);
254 extern t_stat tty_fo (uint32 op);
255 extern uint32 tty_sf (uint32 op);
256
257 struct gdev dev_tab[64] = {
258 { &zero_rd, &zero_wr, &zero_fo, &zero_sf }, /* 00: zero */
259 { &ir_rd, &zero_wr, &ir_fo, &zero_sf }, /* ir */
260 { &no_rd, &no_wr, &no_fo, &no_sf }, /* fo/sf */
261 { &trp_rd, &trp_wr, &zero_fo, &zero_sf }, /* trp */
262 { &isr_rd, &isr_wr, &isr_fo, &isr_sf }, /* isr */
263 { &ma_rd, &no_wr, &no_fo, &no_sf }, /* ma */
264 { &mem_rd, &mem_wr, &zero_fo, &zero_sf }, /* memory */
265 { &sc_rd, &sc_wr, &zero_fo, &zero_sf }, /* sc */
266 { &swr_rd, &no_wr, &no_fo, &no_sf }, /* swr */
267 { &ax_rd, &ax_wr, &zero_fo, &zero_sf }, /* ax */
268 { &ay_rd, &ay_wr, &zero_fo, &zero_sf }, /* ay */
269 { &ao_rd, &zero_wr, &ao_fo, &ao_sf }, /* ao */
270 { &zero_rd, &zero_wr, &eao_fo, &zero_sf }, /* eao */
271 { &no_rd, &no_wr, &no_fo, &no_sf },
272 { &no_rd, &no_wr, &no_fo, &no_sf },
273 { &msr_rd, &msr_wr, &zero_fo, &zero_sf }, /* msr */
274 { &no_rd, &no_wr, &no_fo, &no_sf }, /* 20 */
275 { &no_rd, &no_wr, &no_fo, &no_sf },
276 { &xr_rd, &xr_wr, &no_fo, &no_sf }, /* xr */
277 { &atrp_rd, &atrp_wr, &no_fo, &no_sf },
278 { &bsw_rd, &bsw_wr, &no_fo, &no_sf }, /* bsw */
279 { &bpk_rd, &bpk_wr, &no_fo, &no_sf }, /* bpk */
280 { &no_rd, &no_wr, &no_fo, &no_sf },
281 { &no_rd, &no_wr, &no_fo, &no_sf },
282 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* 30: gr1 */
283 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr2 */
284 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr3 */
285 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr4 */
286 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr5 */
287 { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr6 */
288 { &no_rd, &no_wr, &no_fo, &no_sf },
289 { &no_rd, &no_wr, &no_fo, &no_sf },
290 { &no_rd, &no_wr, &no_fo, &no_sf }, /* 40 */
291 { &no_rd, &no_wr, &no_fo, &no_sf },
292 { &no_rd, &no_wr, &no_fo, &no_sf },
293 { &no_rd, &no_wr, &no_fo, &no_sf },
294 { &no_rd, &no_wr, &no_fo, &no_sf },
295 { &no_rd, &no_wr, &no_fo, &no_sf },
296 { &no_rd, &no_wr, &no_fo, &no_sf },
297 { &no_rd, &no_wr, &no_fo, &no_sf },
298 { &no_rd, &no_wr, &no_fo, &no_sf }, /* 50 */
299 { &no_rd, &no_wr, &no_fo, &no_sf },
300 { &no_rd, &no_wr, &no_fo, &no_sf },
301 { &no_rd, &no_wr, &no_fo, &no_sf },
302 { &no_rd, &no_wr, &no_fo, &no_sf },
303 { &no_rd, &no_wr, &no_fo, &no_sf },
304 { &no_rd, &no_wr, &no_fo, &no_sf },
305 { &no_rd, &no_wr, &no_fo, &no_sf },
306 { &no_rd, &no_wr, &no_fo, &no_sf }, /* 60 */
307 { &no_rd, &no_wr, &no_fo, &no_sf },
308 { &no_rd, &no_wr, &no_fo, &no_sf },
309 { &no_rd, &no_wr, &no_fo, &no_sf },
310 { &no_rd, &no_wr, &no_fo, &no_sf },
311 { &no_rd, &no_wr, &no_fo, &no_sf },
312 { &no_rd, &no_wr, &no_fo, &no_sf },
313 { &no_rd, &no_wr, &no_fo, &no_sf },
314 { &no_rd, &no_wr, &no_fo, &no_sf }, /* 70 */
315 { &no_rd, &no_wr, &no_fo, &no_sf },
316 { &no_rd, &no_wr, &no_fo, &no_sf },
317 { &no_rd, &no_wr, &no_fo, &no_sf },
318 { &no_rd, &no_wr, &no_fo, &no_sf },
319 { &zero_rd, &zero_wr, &rtc_fo, &rtc_sf }, /* rtc */
320 { &hsrp_rd, &hsrp_wr, &hsrp_fo, &hsrp_sf }, /* hsrp */
321 { &tty_rd, &tty_wr, &tty_fo, &tty_sf } /* tty */
322 };
323
324 static const int32 vec_map[16] = {
325 VEC_TTO, VEC_TTI, VEC_HSP, VEC_HSR,
326 -1, -1, -1, -1,
327 -1, -1, -1, VEC_RTC,
328 -1, -1, -1, -1
329 };
330
331 /* CPU data structures
332
333 cpu_dev CPU device descriptor
334 cpu_unit CPU unit descriptor
335 cpu_reg CPU register list
336 cpu_mod CPU modifiers list
337 */
338
339 UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_AO+UNIT_EAO+UNIT_GPR, MAXMEMSIZE) };
340
341 REG cpu_reg[] = {
342 { ORDATA (SC, SC, 15) },
343 { ORDATA (AX, AX, 16) },
344 { ORDATA (AY, AY, 16) },
345 { ORDATA (AO, AO, 16), REG_RO },
346 { ORDATA (TRP, TRP, 16) },
347 { ORDATA (MSR, MSR, 16) },
348 { ORDATA (ISR, ISR, 16) },
349 { ORDATA (BSW, BSW, 16) },
350 { ORDATA (BPK, BPK, 16) },
351 { ORDATA (GR1, GR[0], 16) },
352 { ORDATA (GR2, GR[1], 16) },
353 { ORDATA (GR3, GR[2], 16) },
354 { ORDATA (GR4, GR[3], 16) },
355 { ORDATA (GR5, GR[4], 16) },
356 { ORDATA (GR6, GR[5], 16) },
357 { ORDATA (XR, XR, 16) },
358 { FLDATA (BOV, MSR, MSR_V_BOV) },
359 { FLDATA (L, MSR, MSR_V_L) },
360 { GRDATA (FOA, MSR, 8, 2, MSR_V_FOA) },
361 { FLDATA (SOV, MSR, MSR_V_SOV) },
362 { FLDATA (AOV, MSR, MSR_V_AOV) },
363 { ORDATA (IR, IR, 16), REG_RO },
364 { ORDATA (MA, MA, 16), REG_RO },
365 { ORDATA (SWR, SWR, 16) },
366 { ORDATA (DR, DR, 16) },
367 { ORDATA (THW, thwh, 6) },
368 { ORDATA (IREQ, dev_done, INT_V_NODEF) },
369 { FLDATA (ION, dev_done, INT_V_ON) },
370 { FLDATA (INODEF, dev_done, INT_V_NODEF) },
371 { FLDATA (BKP, bkp, 0) },
372 { BRDATA (SCQ, scq, 8, 15, SCQ_SIZE), REG_RO + REG_CIRC },
373 { ORDATA (SCQP, scq_p, 6), REG_HRO },
374 { FLDATA (STOP_OPR, stop_opr, 0) },
375 { ORDATA (WRU, sim_int_char, 8) },
376 { NULL }
377 };
378
379 MTAB cpu_mod[] = {
380 { UNIT_GRI99, UNIT_GRI99, "GRI99", "GRI99", NULL },
381 { UNIT_GRI99, 0, "GRI909", "GRI909", NULL },
382 { UNIT_AO, UNIT_AO, "AO", "AO", NULL },
383 { UNIT_AO, 0, "no AO", "NOAO", NULL },
384 { UNIT_EAO, UNIT_EAO, "EAO", "EAO", NULL },
385 { UNIT_EAO, 0, "no EAO", "NOEAO", NULL },
386 { UNIT_GPR, UNIT_GPR, "GPR", "GPR", NULL },
387 { UNIT_GPR, 0, "no GPR", "NOGPR", NULL },
388 { UNIT_BSWPK, UNIT_BSWPK, "BSW-BPK", "BSW-BPK", NULL },
389 { UNIT_BSWPK, 0, "no BSW-BPK", "NOBSW-BPK", NULL },
390 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
391 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
392 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
393 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
394 { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
395 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
396 { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
397 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
398 { 0 }
399 };
400
401 DEVICE cpu_dev = {
402 "CPU", &cpu_unit, cpu_reg, cpu_mod,
403 1, 8, 15, 1, 8, 16,
404 &cpu_ex, &cpu_dep, &cpu_reset,
405 NULL, NULL, NULL
406 };
407
408 t_stat sim_instr (void)
409 {
410 uint32 src, dst, op, t, jmp;
411 t_stat reason;
412
413 /* Restore register state */
414
415 SC = SC & AMASK; /* load local PC */
416 reason = 0;
417 ao_update (); /* update AO */
418
419 /* Main instruction fetch/decode loop */
420
421 while (reason == 0) { /* loop until halted */
422
423 if (sim_interval <= 0) { /* check clock queue */
424 if (reason = sim_process_event ()) break;
425 }
426
427 if (bkp) { /* breakpoint? */
428 bkp = 0; /* clear request */
429 dev_done = dev_done & ~INT_ON; /* int off */
430 M[VEC_BKP] = SC; /* save SC */
431 SC = VEC_BKP + 1; /* new SC */
432 }
433
434 else if ((dev_done & (INT_PENDING | ISR)) > (INT_PENDING)) { /* intr? */
435 int32 i, vec;
436 t = dev_done & ISR; /* find hi pri */
437 for (i = 15; i >= 0; i--) {
438 if ((t >> i) & 1) break;
439 }
440 if ((i < 0) || ((vec = vec_map[i]) < 0)) { /* undefined? */
441 reason = STOP_ILLINT; /* stop */
442 break;
443 }
444 dev_done = dev_done & ~INT_ON; /* int off */
445 M[vec] = SC; /* save SC */
446 SC = vec + 1; /* new SC */
447 continue;
448 }
449
450 if (sim_brk_summ && sim_brk_test (SC, SWMASK ('E'))) { /* breakpoint? */
451 reason = STOP_IBKPT; /* stop simulation */
452 break;
453 }
454
455 MA = SC; /* set mem addr */
456 IR = M[MA]; /* fetch instr */
457 dev_done = dev_done | INT_NODEF; /* clr ion defer */
458 sim_interval = sim_interval - 1;
459
460 /* Decode instruction types */
461
462 src = I_GETSRC (IR); /* src unit */
463 dst = I_GETDST (IR); /* dst unit */
464 op = I_GETOP (IR); /* bus op */
465
466 if (src == U_FSK) { /* func out? */
467 reason = dev_tab[dst].FO (op); /* send function */
468 SC = (SC + 1) & AMASK; /* incr SC */
469 }
470
471 else if (dst == U_FSK) { /* skip func? */
472 t = dev_tab[src].SF (op & ~1); /* issue SF */
473 reason = t >> SF_V_REASON;
474 if ((t ^ op) & 1) SC = SC + 2; /* skip? */
475 SC = (SC + 1) & AMASK; /* incr SC */
476 }
477
478 else if ((src != U_MEM) && (dst == U_TRP)) { /* cond jump */
479 t = dev_tab[src].Src (src); /* get source */
480 switch (op >> 1) { /* case on jump */
481
482 case 00: /* never */
483 jmp = 0;
484 break;
485
486 case 01: /* always */
487 jmp = 1;
488 break;
489
490 case 02: /* src == 0 */
491 jmp = (t == 0);
492 break;
493
494 case 03: /* src != 0 */
495 jmp = (t != 0);
496 break;
497
498 case 04: /* src < 0 */
499 jmp = (t >= SIGN);
500 break;
501
502 case 05: /* src >= 0 */
503 jmp = (t < SIGN);
504 break;
505
506 case 06: /* src <= 0 */
507 jmp = (t == 0) || (t & SIGN);
508 break;
509
510 case 07: /* src > 0 */
511 jmp = (t != 0) && !(t & SIGN);
512 break;
513 }
514
515 if (jmp) { /* jump taken? */
516 SCQ_ENTRY; /* save SC */
517 SC = (SC + 1) & AMASK; /* incr SC once */
518 MA = M[SC]; /* get jump addr */
519 MA = IDX_ADD (MA); /* index? */
520 if (op & TRP_DEF) { /* defer? */
521 t = (M[MA] + 1) & DMASK; /* autoinc */
522 if (MEM_ADDR_OK (MA)) M[MA] = t;
523 MA = IDX_ADD (t); /* index? */
524 }
525 TRP = SC; /* save SC */
526 SC = MA; /* load new SC */
527 }
528 else SC = (SC + 2) & AMASK; /* incr SC twice */
529 }
530
531 else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */
532 reason = bus_op (src, op, dst); /* xmt and modify */
533 SC = (SC + 1) & AMASK; /* incr SC */
534 }
535
536 /* Memory reference. The second SC increment occurs after the first
537 execution cycle. For direct, defer, and immediate defer, this is
538 after the first memory read and before the bus transfer; but for
539 immediate, it is after the bus transfer.
540 */
541
542 else { /* memory reference */
543 SC = (SC + 1) & AMASK; /* incr SC */
544 switch (op & MEM_MOD) { /* case on addr mode */
545
546 case MEM_DIR: /* direct */
547 MA = M[SC]; /* get address */
548 MA = IDX_ADD (MA); /* index? */
549 SC = (SC + 1) & AMASK; /* incr SC again */
550 reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */
551 break;
552
553 case MEM_DEF: /* defer */
554 MA = M[SC]; /* get ind addr */
555 MA = IDX_ADD (MA); /* index? */
556 SC = (SC + 1) & AMASK; /* incr SC again */
557 t = (M[MA] + 1) & DMASK; /* autoinc */
558 if (MEM_ADDR_OK (MA)) M[MA] = t;
559 MA = IDX_ADD (t); /* index? */
560 reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */
561 break;
562
563 case MEM_IMM: /* immediate */
564 MA = SC; /* eff addr */
565 reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */
566 SC = (SC + 1) & AMASK; /* incr SC again */
567 break;
568
569 case MEM_IDF: /* immediate defer */
570 MA = SC; /* get ind addr */
571 t = (M[MA] + 1) & DMASK; /* autoinc */
572 if (MEM_ADDR_OK (MA)) M[MA] = t;
573 MA = IDX_ADD (t); /* index? */
574 SC = (SC + 1) & AMASK; /* incr SC again */
575 reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */
576 break;
577 } /* end switch */
578 } /* end mem ref */
579 } /* end while */
580
581 /* Simulation halted */
582
583 ao_update (); /* update AO */
584 scq_r->qptr = scq_p; /* update sc q ptr */
585 return reason;
586 }
587
588 /* Bus operations */
589
590 t_stat bus_op (uint32 src, uint32 op, uint32 dst)
591 {
592 uint32 t, old_t;
593
594 t = dev_tab[src].Src (src); /* get src */
595 if (op & BUS_COM) t = t ^ DMASK; /* complement? */
596 switch (op & BUS_FNC) { /* case op */
597
598 case BUS_P1: /* plus 1 */
599 t = t + 1; /* do add */
600 if (t & CBIT) MSR = MSR | MSR_BOV; /* set cry out */
601 else MSR = MSR & ~MSR_BOV;
602 break;
603
604 case BUS_L1: /* left 1 */
605 t = (t << 1) | ((MSR & MSR_L)? 1: 0); /* rotate */
606 if (t & CBIT) MSR = MSR | MSR_L; /* set link out */
607 else MSR = MSR & ~MSR_L;
608 break;
609
610 case BUS_R1: /* right 1 */
611 old_t = t;
612 t = (t >> 1) | ((MSR & MSR_L)? SIGN: 0); /* rotate */
613 if (old_t & 1) MSR = MSR | MSR_L; /* set link out */
614 else MSR = MSR & ~MSR_L;
615 break;
616 } /* end case op */
617
618 if (dst == thwh) DR = t & DMASK; /* display dst? */
619 return dev_tab[dst].Dst (dst, t & DMASK); /* store dst */
620 }
621
622 /* Non-existent device */
623
624 uint32 no_rd (uint32 src)
625 {
626 return 0;
627 }
628
629 t_stat no_wr (uint32 dst, uint32 dat)
630 {
631 return stop_opr;
632 }
633
634 t_stat no_fo (uint32 fnc)
635 {
636 return stop_opr;
637 }
638
639 uint32 no_sf (uint32 fnc)
640 {
641 return (stop_opr << SF_V_REASON);
642 }
643
644 /* Zero device */
645
646 uint32 zero_rd (uint32 src)
647 {
648 return 0;
649 }
650
651 t_stat zero_wr (uint32 dst, uint32 val)
652 {
653 return SCPE_OK;
654 }
655
656 t_stat zero_fo (uint32 op)
657 {
658 switch (op & 3) { /* FOM link */
659
660 case 1: /* CLL */
661 MSR = MSR & ~MSR_L;
662 break;
663
664 case 2: /* STL */
665 MSR = MSR | MSR_L;
666 break;
667
668 case 3: /* CML */
669 MSR = MSR ^ MSR_L;
670 break;
671 }
672
673 if (op & 4) return STOP_HALT; /* HALT */
674 return SCPE_OK;
675 }
676
677 uint32 zero_sf (uint32 op)
678 {
679 if ((op & 010) || /* power always ok */
680 ((op & 4) && (MSR & MSR_L)) || /* link set? */
681 ((op & 2) && (MSR & MSR_BOV))) return 1; /* BOV set? */
682 return 0;
683 }
684
685 /* Instruction register (01) */
686
687 uint32 ir_rd (uint32 src)
688 {
689 return IR;
690 }
691
692 t_stat ir_fo (uint32 op)
693 {
694 if (op & 2) bkp = 1;
695 return SCPE_OK;
696 }
697
698 /* Trap register (03) */
699
700 uint32 trp_rd (uint32 src)
701 {
702 return TRP;
703 }
704
705 t_stat trp_wr (uint32 dst, uint32 val)
706 {
707 TRP = val;
708 return SCPE_OK;
709 }
710
711 /* Interrupt status register (04) */
712
713 uint32 isr_rd (uint32 src)
714 {
715 return ISR;
716 }
717
718 t_stat isr_wr (uint32 dst, uint32 dat)
719 {
720 ISR = dat;
721 return SCPE_OK;
722 }
723
724 t_stat isr_fo (uint32 op)
725 {
726 if (op & ISR_ON) dev_done = (dev_done | INT_ON) & ~INT_NODEF;
727 if (op & ISR_OFF) dev_done = dev_done & ~INT_ON;
728 return SCPE_OK;
729 }
730
731 uint32 isr_sf (uint32 op)
732 {
733 return 0;
734 }
735
736 /* Memory address (05) */
737
738 uint32 ma_rd (uint32 src)
739 {
740 return MA;
741 }
742
743 /* Memory (06) */
744
745 uint32 mem_rd (uint32 src)
746 {
747 return M[MA];
748 }
749
750 t_stat mem_wr (uint32 dst, uint32 dat)
751 {
752
753 if (MEM_ADDR_OK (MA)) M[MA] = dat;
754 return SCPE_OK;
755 }
756
757 /* Sequence counter (07) */
758
759 uint32 sc_rd (uint32 src)
760 {
761 return SC;
762 }
763
764 t_stat sc_wr (uint32 dst, uint32 dat)
765 {
766 SCQ_ENTRY;
767 SC = IDX_ADD (dat);
768 return SCPE_OK;
769 }
770
771 /* Switch register (10) */
772
773 uint32 swr_rd (uint32 src)
774 {
775 return SWR;
776 }
777
778 /* Machine status register (17) */
779
780 uint32 msr_rd (uint32 src)
781 {
782 return MSR & MSR_RW;
783 }
784
785 t_stat msr_wr (uint32 src, uint32 dat)
786 {
787 MSR = dat & MSR_RW; /* new MSR */
788 ao_update (); /* update SOV,AOV */
789 return SCPE_OK;
790 }
791
792 /* Arithmetic operator (11:13) */
793
794 uint32 ao_update (void)
795 {
796 uint32 af = MSR_GET_FOA (MSR);
797
798 switch (af) {
799
800 case AO_ADD:
801 AO = (AX + AY) & DMASK; /* add */
802 break;
803
804 case AO_AND:
805 AO = AX & AY; /* and */
806 break;
807
808 case AO_XOR: /* xor */
809 AO = AX ^ AY;
810 break;
811
812 case AO_IOR:
813 AO = AX | AY; /* or */
814 break;
815 }
816
817 if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */
818 else MSR = MSR & ~MSR_AOV;
819 if (SIGN & ((AX ^ (AX + AY)) & (~AX ^ AY))) /* always calc SOV */
820 MSR = MSR | MSR_SOV;
821 else MSR = MSR & ~MSR_SOV;
822 return AO;
823 }
824
825 uint32 ax_rd (uint32 src)
826 {
827 if (cpu_unit.flags & UNIT_AO) return AX;
828 else return 0;
829 }
830
831 t_stat ax_wr (uint32 dst, uint32 dat)
832 {
833 if (cpu_unit.flags & UNIT_AO) {
834 AX = dat;
835 ao_update ();
836 return SCPE_OK;
837 }
838 return stop_opr;
839 }
840
841 uint32 ay_rd (uint32 src)
842 {
843 if (cpu_unit.flags & UNIT_AO) return AY;
844 else return 0;
845 }
846
847 t_stat ay_wr (uint32 dst, uint32 dat)
848 {
849 if (cpu_unit.flags & UNIT_AO) {
850 AY = dat;
851 ao_update ();
852 return SCPE_OK;
853 }
854 return stop_opr;
855 }
856
857 uint32 ao_rd (uint32 src)
858 {
859 if (cpu_unit.flags & UNIT_AO) return ao_update ();
860 else return 0;
861 }
862
863 t_stat ao_fo (uint32 op)
864 {
865 if (cpu_unit.flags & UNIT_AO) {
866 uint32 t = OP_GET_FOA (op); /* get func */
867 MSR = MSR_PUT_FOA (MSR, t); /* store in MSR */
868 ao_update (); /* update AOV */
869 return SCPE_OK;
870 }
871 return stop_opr;
872 }
873
874 uint32 ao_sf (uint32 op)
875 {
876 if (!(cpu_unit.flags & UNIT_AO)) /* not installed? */
877 return (stop_opr << SF_V_REASON);
878 if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */
879 ((op & 4) && (MSR & MSR_SOV))) return 1; /* arith overflow? */
880 return 0;
881 }
882
883 /* Extended arithmetic operator (14) */
884
885 t_stat eao_fo (uint32 op)
886 {
887 uint32 t;
888
889 if (!(cpu_unit.flags & UNIT_EAO)) /* EAO installed? */
890 return stop_opr;
891 switch (op) {
892
893 case EAO_MUL: /* mul? */
894 t = AX * AY; /* AX * AY */
895 AX = (t >> 16) & DMASK; /* to AX'GR1 */
896 GR[0] = t & DMASK;
897 break;
898
899 case EAO_DIV: /* div? */
900 if (AY && (AX < AY)) {
901 t = (AX << 16) | GR[0]; /* AX'GR1 / AY */
902 GR[0] = t / AY; /* quo to GR1 */
903 AX = t % AY; /* rem to AX */
904 MSR = MSR & ~MSR_L; /* clear link */
905 }
906 else MSR = MSR | MSR_L; /* set link */
907 break;
908
909 case EAO_ARS: /* arith right? */
910 t = 0; /* shift limiter */
911 if (AX & SIGN) MSR = MSR | MSR_L; /* L = sign */
912 else MSR = MSR & ~MSR_L;
913 do { /* shift one bit */
914 AY = ((AY >> 1) | (AX << 15)) & DMASK;
915 AX = (AX & SIGN) | (AX >> 1);
916 GR[0] = (GR[0] + 1) & DMASK;
917 }
918 while (GR[0] && (++t < 32)); /* until cnt or limit */
919 break;
920
921 case EAO_NORM: /* norm? */
922 if ((AX | AY) != 0) { /* can normalize? */
923 while ((AX & SIGN) != ((AX << 1) & SIGN)) { /* until AX15 != AX14 */
924 AX = ((AX << 1) | (AY >> 15)) & DMASK;
925 AY = (AY << 1) & DMASK;
926 GR[0] = (GR[0] + 1) & DMASK;
927 }
928 }
929 break;
930 }
931
932 // MSR = MSR_PUT_FOA (MSR, AO_ADD); /* AO fnc is add */
933 ao_update ();
934 return SCPE_OK;
935 }
936
937 /* Index register (GRI-99) (22) */
938
939 uint32 xr_rd (uint32 src)
940 {
941 if (cpu_unit.flags & UNIT_GRI99) return XR;
942 else return 0;
943 }
944
945 t_stat xr_wr (uint32 dst, uint32 val)
946 {
947 if (cpu_unit.flags & UNIT_GRI99) {
948 XR = val;
949 return SCPE_OK;
950 }
951 return stop_opr;
952 }
953
954 /* Alternate trap (GRI-99) (23) */
955
956 uint32 atrp_rd (uint32 src)
957 {
958 if (cpu_unit.flags & UNIT_GRI99) return TRP;
959 else return 0;
960 }
961
962 t_stat atrp_wr (uint32 dst, uint32 val)
963 {
964 if (cpu_unit.flags & UNIT_GRI99) {
965 TRP = val;
966 return SCPE_OK;
967 }
968 return stop_opr;
969 }
970
971 /* Byte swapper (24) */
972
973 uint32 bsw_rd (uint32 src)
974 {
975 if (cpu_unit.flags & UNIT_BSWPK) return BSW;
976 else return 0;
977 }
978
979 t_stat bsw_wr (uint32 dst, uint32 val)
980 {
981 if (cpu_unit.flags & UNIT_BSWPK) {
982 BSW = ((val >> 8) & 0377) | ((val & 0377) << 8);
983 return SCPE_OK;
984 }
985 return stop_opr;
986 }
987
988 /* Byte packer (25) */
989
990 uint32 bpk_rd (uint32 src)
991 {
992 if (cpu_unit.flags & UNIT_BSWPK) return BPK;
993 else return 0;
994 }
995
996 t_stat bpk_wr (uint32 dst, uint32 val)
997 {
998 if (cpu_unit.flags & UNIT_BSWPK) {
999 BPK = ((BPK & 0377) << 8) | (val & 0377);
1000 return SCPE_OK;
1001 }
1002 return stop_opr;
1003 }
1004
1005 /* General registers (30:35) */
1006
1007 uint32 gr_rd (uint32 src)
1008 {
1009 if (cpu_unit.flags & UNIT_GPR) return GR[src - U_GR];
1010 else return 0;
1011 }
1012
1013 t_stat gr_wr (uint32 dst, uint32 dat)
1014 {
1015 if (cpu_unit.flags & UNIT_GPR) {
1016 GR[dst - U_GR] = dat;
1017 return SCPE_OK;
1018 }
1019 return stop_opr;
1020 }
1021
1022 /* Reset routine */
1023
1024 t_stat cpu_reset (DEVICE *dptr)
1025 {
1026 int32 i;
1027
1028 AX = AY = AO = 0;
1029 XR = 0;
1030 TRP = 0;
1031 ISR = 0;
1032 MSR = 0;
1033 MA = IR = 0;
1034 BSW = BPK = 0;
1035 for (i = 0; i < 6; i++) GR[i] = 0;
1036 dev_done = dev_done & ~INT_PENDING;
1037 scq_r = find_reg ("SCQ", NULL, dptr);
1038 if (scq_r) scq_r->qptr = 0;
1039 else return SCPE_IERR;
1040 sim_brk_types = sim_brk_dflt = SWMASK ('E');
1041 return SCPE_OK;
1042 }
1043
1044 /* Memory examine */
1045
1046 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
1047 {
1048 if (addr >= MEMSIZE) return SCPE_NXM;
1049 if (vptr != NULL) *vptr = M[addr] & DMASK;
1050 return SCPE_OK;
1051 }
1052
1053 /* Memory deposit */
1054
1055 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
1056 {
1057 if (addr >= MEMSIZE) return SCPE_NXM;
1058 M[addr] = val & DMASK;
1059 return SCPE_OK;
1060 }
1061
1062 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
1063 {
1064 int32 mc = 0;
1065 uint32 i;
1066
1067 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
1068 return SCPE_ARG;
1069 for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
1070 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
1071 return SCPE_OK;
1072 MEMSIZE = val;
1073 for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
1074 return SCPE_OK;
1075 }