1 /* gri_cpu.c: GRI-909 CPU simulator
3 Copyright (c) 2001-2008, Robert M. Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
26 cpu GRI-909/GRI-99 CPU
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
35 The system state for the GRI-909/GRI-99 is:
37 AX<15:0> arithmetic input
38 AY<15:0> arithmetic input
39 BSW<15:0> byte swapper
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)
47 The GRI-909 has, nominally, just one instruction format: move.
49 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
50 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
51 | source | op | destination | move
52 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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.
65 The function out format is:
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
72 The skip on function format is:
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
79 The memory reference format is (src and/or dst = 006):
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 +-----------------------------------------------+
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]
97 The conditional jump format is (src != 006):
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
104 +-----------------------------------------------+
108 xxx0 direct, ea = M[SC+1]
109 xxx1 indirect, ea = M[SC+1], M[ea] = M[ea]+1,
111 xx1x reverse conditional sense
112 x1xx jump if src == 0
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.
122 1. Reasons to stop. The simulator can be stopped by:
125 breakpoint encountered
126 unknown source or destination and STOP_OPR flag set
127 I/O error in I/O simulator
129 2. Interrupts. The interrupt structure is kept in two parallel variables:
131 dev_done device done flags
132 ISR interrupt status register (enables)
134 In addition, there is a master interrupt enable, and a one cycle
135 interrupt defer, both kept in dev_done.
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.
142 4. Adding I/O devices. These modules must be modified:
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
149 #include "gri_defs.h"
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)
167 #define IDX_ADD(x) ((((cpu_unit.flags & UNIT_GRI99) && ((x) & INDEX))? ((x) + XR): (x)) & AMASK)
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 */
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 */
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
);
200 /* Dispatch tables for source, dest, function out, skip on function */
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
);
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
);
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 */
324 static const int32 vec_map
[16] = {
325 VEC_TTO
, VEC_TTI
, VEC_HSP
, VEC_HSR
,
331 /* CPU data structures
333 cpu_dev CPU device descriptor
334 cpu_unit CPU unit descriptor
335 cpu_reg CPU register list
336 cpu_mod CPU modifiers list
339 UNIT cpu_unit
= { UDATA (NULL
, UNIT_FIX
+UNIT_BINK
+UNIT_AO
+UNIT_EAO
+UNIT_GPR
, MAXMEMSIZE
) };
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) },
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
},
402 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
404 &cpu_ex
, &cpu_dep
, &cpu_reset
,
408 t_stat
sim_instr (void)
410 uint32 src
, dst
, op
, t
, jmp
;
413 /* Restore register state */
415 SC
= SC
& AMASK
; /* load local PC */
417 ao_update (); /* update AO */
419 /* Main instruction fetch/decode loop */
421 while (reason
== 0) { /* loop until halted */
423 if (sim_interval
<= 0) { /* check clock queue */
424 if (reason
= sim_process_event ()) break;
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 */
434 else if ((dev_done
& (INT_PENDING
| ISR
)) > (INT_PENDING
)) { /* intr? */
436 t
= dev_done
& ISR
; /* find hi pri */
437 for (i
= 15; i
>= 0; i
--) {
438 if ((t
>> i
) & 1) break;
440 if ((i
< 0) || ((vec
= vec_map
[i
]) < 0)) { /* undefined? */
441 reason
= STOP_ILLINT
; /* stop */
444 dev_done
= dev_done
& ~INT_ON
; /* int off */
445 M
[vec
] = SC
; /* save SC */
446 SC
= vec
+ 1; /* new SC */
450 if (sim_brk_summ
&& sim_brk_test (SC
, SWMASK ('E'))) { /* breakpoint? */
451 reason
= STOP_IBKPT
; /* stop simulation */
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;
460 /* Decode instruction types */
462 src
= I_GETSRC (IR
); /* src unit */
463 dst
= I_GETDST (IR
); /* dst unit */
464 op
= I_GETOP (IR
); /* bus op */
466 if (src
== U_FSK
) { /* func out? */
467 reason
= dev_tab
[dst
].FO (op
); /* send function */
468 SC
= (SC
+ 1) & AMASK
; /* incr SC */
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 */
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 */
486 case 01: /* always */
490 case 02: /* src == 0 */
494 case 03: /* src != 0 */
498 case 04: /* src < 0 */
502 case 05: /* src >= 0 */
506 case 06: /* src <= 0 */
507 jmp
= (t
== 0) || (t
& SIGN
);
510 case 07: /* src > 0 */
511 jmp
= (t
!= 0) && !(t
& SIGN
);
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? */
525 TRP
= SC
; /* save SC */
526 SC
= MA
; /* load new SC */
528 else SC
= (SC
+ 2) & AMASK
; /* incr SC twice */
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 */
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.
542 else { /* memory reference */
543 SC
= (SC
+ 1) & AMASK
; /* incr SC */
544 switch (op
& MEM_MOD
) { /* case on addr mode */
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 */
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 */
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 */
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 */
581 /* Simulation halted */
583 ao_update (); /* update AO */
584 scq_r
->qptr
= scq_p
; /* update sc q ptr */
590 t_stat
bus_op (uint32 src
, uint32 op
, uint32 dst
)
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 */
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
;
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
;
610 case BUS_R1
: /* right 1 */
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
;
618 if (dst
== thwh
) DR
= t
& DMASK
; /* display dst? */
619 return dev_tab
[dst
].Dst (dst
, t
& DMASK
); /* store dst */
622 /* Non-existent device */
624 uint32
no_rd (uint32 src
)
629 t_stat
no_wr (uint32 dst
, uint32 dat
)
634 t_stat
no_fo (uint32 fnc
)
639 uint32
no_sf (uint32 fnc
)
641 return (stop_opr
<< SF_V_REASON
);
646 uint32
zero_rd (uint32 src
)
651 t_stat
zero_wr (uint32 dst
, uint32 val
)
656 t_stat
zero_fo (uint32 op
)
658 switch (op
& 3) { /* FOM link */
673 if (op
& 4) return STOP_HALT
; /* HALT */
677 uint32
zero_sf (uint32 op
)
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? */
685 /* Instruction register (01) */
687 uint32
ir_rd (uint32 src
)
692 t_stat
ir_fo (uint32 op
)
698 /* Trap register (03) */
700 uint32
trp_rd (uint32 src
)
705 t_stat
trp_wr (uint32 dst
, uint32 val
)
711 /* Interrupt status register (04) */
713 uint32
isr_rd (uint32 src
)
718 t_stat
isr_wr (uint32 dst
, uint32 dat
)
724 t_stat
isr_fo (uint32 op
)
726 if (op
& ISR_ON
) dev_done
= (dev_done
| INT_ON
) & ~INT_NODEF
;
727 if (op
& ISR_OFF
) dev_done
= dev_done
& ~INT_ON
;
731 uint32
isr_sf (uint32 op
)
736 /* Memory address (05) */
738 uint32
ma_rd (uint32 src
)
745 uint32
mem_rd (uint32 src
)
750 t_stat
mem_wr (uint32 dst
, uint32 dat
)
753 if (MEM_ADDR_OK (MA
)) M
[MA
] = dat
;
757 /* Sequence counter (07) */
759 uint32
sc_rd (uint32 src
)
764 t_stat
sc_wr (uint32 dst
, uint32 dat
)
771 /* Switch register (10) */
773 uint32
swr_rd (uint32 src
)
778 /* Machine status register (17) */
780 uint32
msr_rd (uint32 src
)
785 t_stat
msr_wr (uint32 src
, uint32 dat
)
787 MSR
= dat
& MSR_RW
; /* new MSR */
788 ao_update (); /* update SOV,AOV */
792 /* Arithmetic operator (11:13) */
794 uint32
ao_update (void)
796 uint32 af
= MSR_GET_FOA (MSR
);
801 AO
= (AX
+ AY
) & DMASK
; /* add */
805 AO
= AX
& AY
; /* and */
808 case AO_XOR
: /* xor */
813 AO
= AX
| AY
; /* or */
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 */
821 else MSR
= MSR
& ~MSR_SOV
;
825 uint32
ax_rd (uint32 src
)
827 if (cpu_unit
.flags
& UNIT_AO
) return AX
;
831 t_stat
ax_wr (uint32 dst
, uint32 dat
)
833 if (cpu_unit
.flags
& UNIT_AO
) {
841 uint32
ay_rd (uint32 src
)
843 if (cpu_unit
.flags
& UNIT_AO
) return AY
;
847 t_stat
ay_wr (uint32 dst
, uint32 dat
)
849 if (cpu_unit
.flags
& UNIT_AO
) {
857 uint32
ao_rd (uint32 src
)
859 if (cpu_unit
.flags
& UNIT_AO
) return ao_update ();
863 t_stat
ao_fo (uint32 op
)
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 */
874 uint32
ao_sf (uint32 op
)
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? */
883 /* Extended arithmetic operator (14) */
885 t_stat
eao_fo (uint32 op
)
889 if (!(cpu_unit
.flags
& UNIT_EAO
)) /* EAO installed? */
893 case EAO_MUL
: /* mul? */
894 t
= AX
* AY
; /* AX * AY */
895 AX
= (t
>> 16) & DMASK
; /* to AX'GR1 */
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 */
906 else MSR
= MSR
| MSR_L
; /* set link */
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
;
918 while (GR
[0] && (++t
< 32)); /* until cnt or limit */
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
;
932 // MSR = MSR_PUT_FOA (MSR, AO_ADD); /* AO fnc is add */
937 /* Index register (GRI-99) (22) */
939 uint32
xr_rd (uint32 src
)
941 if (cpu_unit
.flags
& UNIT_GRI99
) return XR
;
945 t_stat
xr_wr (uint32 dst
, uint32 val
)
947 if (cpu_unit
.flags
& UNIT_GRI99
) {
954 /* Alternate trap (GRI-99) (23) */
956 uint32
atrp_rd (uint32 src
)
958 if (cpu_unit
.flags
& UNIT_GRI99
) return TRP
;
962 t_stat
atrp_wr (uint32 dst
, uint32 val
)
964 if (cpu_unit
.flags
& UNIT_GRI99
) {
971 /* Byte swapper (24) */
973 uint32
bsw_rd (uint32 src
)
975 if (cpu_unit
.flags
& UNIT_BSWPK
) return BSW
;
979 t_stat
bsw_wr (uint32 dst
, uint32 val
)
981 if (cpu_unit
.flags
& UNIT_BSWPK
) {
982 BSW
= ((val
>> 8) & 0377) | ((val
& 0377) << 8);
988 /* Byte packer (25) */
990 uint32
bpk_rd (uint32 src
)
992 if (cpu_unit
.flags
& UNIT_BSWPK
) return BPK
;
996 t_stat
bpk_wr (uint32 dst
, uint32 val
)
998 if (cpu_unit
.flags
& UNIT_BSWPK
) {
999 BPK
= ((BPK
& 0377) << 8) | (val
& 0377);
1005 /* General registers (30:35) */
1007 uint32
gr_rd (uint32 src
)
1009 if (cpu_unit
.flags
& UNIT_GPR
) return GR
[src
- U_GR
];
1013 t_stat
gr_wr (uint32 dst
, uint32 dat
)
1015 if (cpu_unit
.flags
& UNIT_GPR
) {
1016 GR
[dst
- U_GR
] = dat
;
1024 t_stat
cpu_reset (DEVICE
*dptr
)
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');
1044 /* Memory examine */
1046 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1048 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1049 if (vptr
!= NULL
) *vptr
= M
[addr
] & DMASK
;
1053 /* Memory deposit */
1055 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1057 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1058 M
[addr
] = val
& DMASK
;
1062 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1067 if ((val
<= 0) || (val
> MAXMEMSIZE
) || ((val
& 07777) != 0))
1069 for (i
= val
; i
< MEMSIZE
; i
++) mc
= mc
| M
[i
];
1070 if ((mc
!= 0) && (!get_yn ("Really truncate memory [N]?", FALSE
)))
1073 for (i
= MEMSIZE
; i
< MAXMEMSIZE
; i
++) M
[i
] = 0;