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