First Commit of my working state
[simh.git] / ALTAIR / altair_cpu.c
1 /* altair_cpu.c: MITS Altair Intel 8080 CPU simulator
2
3 Copyright (c) 1997-2005, Charles E. Owen
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 Charles E. Owen 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 Charles E. Owen.
25
26 cpu 8080 CPU
27
28 08-Oct-02 RMS Tied off spurious compiler warnings
29
30 The register state for the 8080 CPU is:
31
32 A<0:7> Accumulator
33 BC<0:15> BC Register Pair
34 DE<0:15> DE Register Pair
35 HL<0:15> HL Register Pair
36 C carry flag
37 Z zero flag
38 S Sign bit
39 AC Aux carry
40 P Parity bit
41 PC<0:15> program counter
42 SP<0:15> Stack Pointer
43
44 The 8080 is an 8-bit CPU, which uses 16-bit registers to address
45 up to 64KB of memory.
46
47 The 78 basic instructions come in 1, 2, and 3-byte flavors.
48
49 This routine is the instruction decode routine for the 8080.
50 It is called from the simulator control program to execute
51 instructions in simulated memory, starting at the simulated PC.
52 It runs until 'reason' is set non-zero.
53
54 General notes:
55
56 1. Reasons to stop. The simulator can be stopped by:
57
58 HALT instruction
59 I/O error in I/O simulator
60 Invalid OP code (if ITRAP is set on CPU)
61
62 2. Interrupts.
63 There are 8 possible levels of interrupt, and in effect they
64 do a hardware CALL instruction to one of 8 possible low
65 memory addresses.
66
67 3. Non-existent memory. On the 8080, reads to non-existent memory
68 return 0377, and writes are ignored. In the simulator, the
69 largest possible memory is instantiated and initialized to zero.
70 Thus, only writes need be checked against actual memory size.
71
72 4. Adding I/O devices. These modules must be modified:
73
74 altair_cpu.c add I/O service routines to dev_table
75 altair_sys.c add pointer to data structures in sim_devices
76 */
77
78
79 #include <stdio.h>
80
81 #include "altair_defs.h"
82
83 #define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */
84 #define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
85 #define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */
86 #define UNIT_CHIP (1 << UNIT_V_CHIP)
87 #define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */
88 #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
89
90 unsigned char M[MAXMEMSIZE]; /* memory */
91 int32 A = 0; /* accumulator */
92 int32 BC = 0; /* BC register pair */
93 int32 DE = 0; /* DE register pair */
94 int32 HL = 0; /* HL register pair */
95 int32 SP = 0; /* Stack pointer */
96 int32 C = 0; /* carry flag */
97 int32 Z = 0; /* Zero flag */
98 int32 AC = 0; /* Aux carry */
99 int32 S = 0; /* sign flag */
100 int32 P = 0; /* parity flag */
101 int32 saved_PC = 0; /* program counter */
102 int32 SR = 0; /* switch register */
103 int32 INTE = 0; /* Interrupt Enable */
104 int32 int_req = 0; /* Interrupt request */
105 int32 chip = 0; /* 0 = 8080 chip, 1 = z80 chip */
106
107 int32 PCX; /* External view of PC */
108
109 extern int32 sim_int_char;
110 extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
111
112 /* function prototypes */
113
114 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
115 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
116 t_stat cpu_reset (DEVICE *dptr);
117 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
118 void setarith(int32 reg);
119 void setlogical(int32 reg);
120 void setinc(int32 reg);
121 int32 getreg(int32 reg);
122 void putreg(int32 reg, int32 val);
123 int32 getpair(int32 reg);
124 int32 getpush(int32 reg);
125 void putpush(int32 reg, int32 data);
126 void putpair(int32 reg, int32 val);
127 void parity(int32 reg);
128 int32 cond(int32 con);
129
130 extern int32 sio0s(int32 io, int32 data);
131 extern int32 sio0d(int32 io, int32 data);
132 extern int32 sio1s(int32 io, int32 data);
133 extern int32 sio1d(int32 io, int32 data);
134 extern int32 dsk10(int32 io, int32 data);
135 extern int32 dsk11(int32 io, int32 data);
136 extern int32 dsk12(int32 io, int32 data);
137 int32 nulldev(int32 io, int32 data);
138
139 /* This is the I/O configuration table. There are 255 possible
140 device addresses, if a device is plugged to a port it's routine
141 address is here, 'nulldev' means no device is available
142 */
143 struct idev {
144 int32 (*routine)();
145 };
146 struct idev dev_table[256] = {
147 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000 */
148 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004 */
149 {&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 010 */
150 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014 */
151 {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 020 */
152 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024 */
153 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030 */
154 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034 */
155 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040 */
156 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044 */
157 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050 */
158 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054 */
159 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060 */
160 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064 */
161 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070 */
162 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074 */
163 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100 */
164 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104 */
165 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110 */
166 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114 */
167 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120 */
168 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124 */
169 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130 */
170 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134 */
171 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140 */
172 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144 */
173 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150 */
174 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154 */
175 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160 */
176 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164 */
177 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170 */
178 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174 */
179 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200 */
180 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204 */
181 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210 */
182 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214 */
183 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220 */
184 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224 */
185 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230 */
186 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234 */
187 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240 */
188 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244 */
189 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250 */
190 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254 */
191 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260 */
192 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264 */
193 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270 */
194 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274 */
195 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300 */
196 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304 */
197 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310 */
198 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314 */
199 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320 */
200 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324 */
201 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330 */
202 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334 */
203 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340 */
204 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344 */
205 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350 */
206 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354 */
207 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360 */
208 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364 */
209 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370 */
210 {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 374 */
211 };
212
213 /* Altair MITS standard BOOT EPROM, fits in upper 256K of memory */
214
215 int32 bootrom[256] = {
216 0041, 0000, 0114, 0021, 0030, 0377, 0016, 0346,
217 0032, 0167, 0023, 0043, 0015, 0302, 0010, 0377,
218 0303, 0000, 0114, 0000, 0000, 0000, 0000, 0000,
219 0363, 0061, 0142, 0115, 0257, 0323, 0010, 0076, /* 46000 */
220 0004, 0323, 0011, 0303, 0031, 0114, 0333, 0010, /* 46010 */
221 0346, 0002, 0302, 0016, 0114, 0076, 0002, 0323, /* 46020 */
222 0011, 0333, 0010, 0346, 0100, 0302, 0016, 0114,
223 0021, 0000, 0000, 0006, 0000, 0333, 0010, 0346,
224 0004, 0302, 0045, 0114, 0076, 0020, 0365, 0325,
225 0305, 0325, 0021, 0206, 0200, 0041, 0324, 0114,
226 0333, 0011, 0037, 0332, 0070, 0114, 0346, 0037,
227 0270, 0302, 0070, 0114, 0333, 0010, 0267, 0372,
228 0104, 0114, 0333, 0012, 0167, 0043, 0035, 0312,
229 0132, 0114, 0035, 0333, 0012, 0167, 0043, 0302,
230 0104, 0114, 0341, 0021, 0327, 0114, 0001, 0200,
231 0000, 0032, 0167, 0276, 0302, 0301, 0114, 0200,
232 0107, 0023, 0043, 0015, 0302, 0141, 0114, 0032,
233 0376, 0377, 0302, 0170, 0114, 0023, 0032, 0270,
234 0301, 0353, 0302, 0265, 0114, 0361, 0361, 0052,
235 0325, 0114, 0325, 0021, 0000, 0377, 0315, 0316,
236 0114, 0321, 0332, 0276, 0114, 0315, 0316, 0114,
237 0322, 0256, 0114, 0004, 0004, 0170, 0376, 0040,
238 0332, 0054, 0114, 0006, 0001, 0312, 0054, 0114,
239 0333, 0010, 0346, 0002, 0302, 0240, 0114, 0076,
240 0001, 0323, 0011, 0303, 0043, 0114, 0076, 0200,
241 0323, 0010, 0303, 0000, 0000, 0321, 0361, 0075,
242 0302, 0056, 0114, 0076, 0103, 0001, 0076, 0117,
243 0001, 0076, 0115, 0107, 0076, 0200, 0323, 0010,
244 0170, 0323, 0001, 0303, 0311, 0114, 0172, 0274,
245 0300, 0173, 0275, 0311, 0204, 0000, 0114, 0044,
246 0026, 0126, 0026, 0000, 0000, 0000, 0000, 0000
247 };
248
249 /* CPU data structures
250
251 cpu_dev CPU device descriptor
252 cpu_unit CPU unit descriptor
253 cpu_reg CPU register list
254 cpu_mod CPU modifiers list
255 */
256
257 UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
258
259 REG cpu_reg[] = {
260 { ORDATA (PC, saved_PC, 16) },
261 { ORDATA (A, A, 8) },
262 { ORDATA (BC, BC, 16) },
263 { ORDATA (DE, DE, 16) },
264 { ORDATA (HL, HL, 16) },
265 { ORDATA (SP, SP, 16) },
266 { FLDATA (C, C, 16) },
267 { FLDATA (Z, Z, 16) },
268 { FLDATA (AC, AC, 16) },
269 { FLDATA (S, S, 16) },
270 { FLDATA (P, P, 16) },
271 { FLDATA (INTE, INTE, 16) },
272 { ORDATA (SR, SR, 16) },
273 { ORDATA (WRU, sim_int_char, 8) },
274 { NULL }
275 };
276
277 MTAB cpu_mod[] = {
278 { UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL },
279 { UNIT_CHIP, 0, "8080", "8080", NULL },
280 { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL },
281 { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL },
282 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
283 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
284 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
285 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
286 { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
287 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
288 { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
289 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
290 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
291 { UNIT_MSIZE, 65535, NULL, "64K", &cpu_set_size },
292 { 0 }
293 };
294
295 DEVICE cpu_dev = {
296 "CPU", &cpu_unit, cpu_reg, cpu_mod,
297 1, 8, 16, 1, 8, 8,
298 &cpu_ex, &cpu_dep, &cpu_reset,
299 NULL, NULL, NULL
300 };
301
302 int32 sim_instr (void)
303 {
304 extern int32 sim_interval;
305 int32 PC, IR, OP, DAR, reason, hi, lo, carry, i;
306
307 PC = saved_PC & ADDRMASK; /* load local PC */
308 C = C & 0200000;
309 reason = 0;
310
311 /* Main instruction fetch/decode loop */
312
313 while (reason == 0) { /* loop until halted */
314 if (sim_interval <= 0) { /* check clock queue */
315 if (reason = sim_process_event ()) break;
316 }
317
318 if (int_req > 0) { /* interrupt? */
319
320 /* 8080 interrupts not implemented yet. None were used,
321 on a standard Altair 8800. All I/O is programmed. */
322
323 } /* end interrupt */
324
325 if (sim_brk_summ &&
326 sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
327 reason = STOP_IBKPT; /* stop simulation */
328 break;
329 }
330
331 if (PC == 0177400) { /* BOOT PROM address */
332 for (i = 0; i < 250; i++) {
333 M[i + 0177400] = bootrom[i] & 0xFF;
334 }
335 }
336
337 PCX = PC;
338
339 IR = OP = M[PC]; /* fetch instruction */
340
341 PC = (PC + 1) & ADDRMASK; /* increment PC */
342
343 sim_interval--;
344
345 if (OP == 0166) { /* HLT Instruction*/
346 reason = STOP_HALT;
347 PC--;
348 continue;
349 }
350
351 /* Handle below all operations which refer to registers or
352 register pairs. After that, a large switch statement
353 takes care of all other opcodes */
354
355 if ((OP & 0xC0) == 0x40) { /* MOV */
356 DAR = getreg(OP & 0x07);
357 putreg((OP >> 3) & 0x07, DAR);
358 continue;
359 }
360 if ((OP & 0xC7) == 0x06) { /* MVI */
361 putreg((OP >> 3) & 0x07, M[PC]);
362 PC++;
363 continue;
364 }
365 if ((OP & 0xCF) == 0x01) { /* LXI */
366 DAR = M[PC] & 0x00ff;
367 PC++;
368 DAR = DAR | (M[PC] <<8) & 0xFF00;;
369 putpair((OP >> 4) & 0x03, DAR);
370 PC++;
371 continue;
372 }
373 if ((OP & 0xEF) == 0x0A) { /* LDAX */
374 DAR = getpair((OP >> 4) & 0x03);
375 putreg(7, M[DAR]);
376 continue;
377 }
378 if ((OP & 0xEF) == 0x02) { /* STAX */
379 DAR = getpair((OP >> 4) & 0x03);
380 M[DAR] = getreg(7);
381 continue;
382 }
383
384 if ((OP & 0xF8) == 0xB8) { /* CMP */
385 DAR = A & 0xFF;
386 DAR -= getreg(OP & 0x07);
387 setarith(DAR);
388 continue;
389 }
390 if ((OP & 0xC7) == 0xC2) { /* JMP <condition> */
391 if (cond((OP >> 3) & 0x07) == 1) {
392 lo = M[PC];
393 PC++;
394 hi = M[PC];
395 PC++;
396 PC = (hi << 8) + lo;
397 } else {
398 PC += 2;
399 }
400 continue;
401 }
402 if ((OP & 0xC7) == 0xC4) { /* CALL <condition> */
403 if (cond((OP >> 3) & 0x07) == 1) {
404 lo = M[PC];
405 PC++;
406 hi = M[PC];
407 PC++;
408 SP--;
409 M[SP] = (PC >> 8) & 0xff;
410 SP--;
411 M[SP] = PC & 0xff;
412 PC = (hi << 8) + lo;
413 } else {
414 PC += 2;
415 }
416 continue;
417 }
418 if ((OP & 0xC7) == 0xC0) { /* RET <condition> */
419 if (cond((OP >> 3) & 0x07) == 1) {
420 PC = M[SP];
421 SP++;
422 PC |= (M[SP] << 8) & 0xff00;
423 SP++;
424 }
425 continue;
426 }
427 if ((OP & 0xC7) == 0xC7) { /* RST */
428 SP--;
429 M[SP] = (PC >> 8) & 0xff;
430 SP--;
431 M[SP] = PC & 0xff;
432 PC = OP & 0x38;
433 continue;
434 }
435
436 if ((OP & 0xCF) == 0xC5) { /* PUSH */
437 DAR = getpush((OP >> 4) & 0x03);
438 SP--;
439 M[SP] = (DAR >> 8) & 0xff;
440 SP--;
441 M[SP] = DAR & 0xff;
442 continue;
443 }
444 if ((OP & 0xCF) == 0xC1) { /*POP */
445 DAR = M[SP];
446 SP++;
447 DAR |= M[SP] << 8;
448 SP++;
449 putpush((OP >> 4) & 0x03, DAR);
450 continue;
451 }
452 if ((OP & 0xF8) == 0x80) { /* ADD */
453 A += getreg(OP & 0x07);
454 setarith(A);
455 A = A & 0xFF;
456 continue;
457 }
458 if ((OP & 0xF8) == 0x88) { /* ADC */
459 carry = 0;
460 if (C) carry = 1;
461 A += getreg(OP & 0x07);
462 A += carry;
463 setarith(A);
464 A = A & 0xFF;
465 continue;
466 }
467 if ((OP & 0xF8) == 0x90) { /* SUB */
468 A -= getreg(OP & 0x07);
469 setarith(A);
470 A = A & 0xFF;
471 continue;
472 }
473 if ((OP & 0xF8) == 0x98) { /* SBB */
474 carry = 0;
475 if (C) carry = 1;
476 A -= (getreg(OP & 0x07)) + carry ;
477 setarith(A);
478 A = A & 0xFF;
479 continue;
480 }
481 if ((OP & 0xC7) == 0x04) { /* INR */
482 DAR = getreg((OP >> 3) & 0x07);
483 DAR++;
484 setinc(DAR);
485 DAR = DAR & 0xFF;
486 putreg((OP >> 3) & 0x07, DAR);
487 continue;
488 }
489 if ((OP & 0xC7) == 0x05) { /* DCR */
490 DAR = getreg((OP >> 3) & 0x07);
491 DAR--;
492 setinc(DAR);
493 DAR = DAR & 0xFF;
494 putreg((OP >> 3) & 0x07, DAR);
495 continue;
496 }
497 if ((OP & 0xCF) == 0x03) { /* INX */
498 DAR = getpair((OP >> 4) & 0x03);
499 DAR++;
500 DAR = DAR & 0xFFFF;
501 putpair((OP >> 4) & 0x03, DAR);
502 continue;
503 }
504 if ((OP & 0xCF) == 0x0B) { /* DCX */
505 DAR = getpair((OP >> 4) & 0x03);
506 DAR--;
507 DAR = DAR & 0xFFFF;
508 putpair((OP >> 4) & 0x03, DAR);
509 continue;
510 }
511 if ((OP & 0xCF) == 0x09) { /* DAD */
512 HL += getpair((OP >> 4) & 0x03);
513 C = 0;
514 if (HL & 0x10000)
515 C = 0200000;
516 HL = HL & 0xFFFF;
517 continue;
518 }
519 if ((OP & 0xF8) == 0xA0) { /* ANA */
520 A &= getreg(OP & 0x07);
521 C = 0;
522 setlogical(A);
523 A &= 0xFF;
524 continue;
525 }
526 if ((OP & 0xF8) == 0xA8) { /* XRA */
527 A ^= getreg(OP & 0x07);
528 C = 0;
529 setlogical(A);
530 A &= 0xFF;
531 continue;
532 }
533 if ((OP & 0xF8) == 0xB0) { /* ORA */
534 A |= getreg(OP & 0x07);
535 C = 0;
536 setlogical(A);
537 A &= 0xFF;
538 continue;
539 }
540
541
542
543 /* The Big Instruction Decode Switch */
544
545 switch (IR) {
546
547 /* Logical instructions */
548
549 case 0376: { /* CPI */
550 DAR = A & 0xFF;
551 DAR -= M[PC];
552 PC++;
553 setarith(DAR);
554 break;
555 }
556 case 0346: { /* ANI */
557 A &= M[PC];
558 PC++;
559 C = AC = 0;
560 setlogical(A);
561 A &= 0xFF;
562 break;
563 }
564 case 0356: { /* XRI */
565 A ^= M[PC];
566 PC++;
567 C = AC = 0;
568 setlogical(A);
569 A &= 0xFF;
570 break;
571 }
572 case 0366: { /* ORI */
573 A |= M[PC];
574 PC++;
575 C = AC = 0;
576 setlogical(A);
577 A &= 0xFF;
578 break;
579 }
580
581 /* Jump instructions */
582
583 case 0303: { /* JMP */
584 lo = M[PC];
585 PC++;
586 hi = M[PC];
587 PC++;
588 PC = (hi << 8) + lo;
589 break;
590 }
591 case 0351: { /* PCHL */
592 PC = HL;
593 break;
594 }
595 case 0315: { /* CALL */
596 lo = M[PC];
597 PC++;
598 hi = M[PC];
599 PC++;
600 SP--;
601 M[SP] = (PC >> 8) & 0xff;
602 SP--;
603 M[SP] = PC & 0xff;
604 PC = (hi << 8) + lo;
605 break;
606 }
607 case 0311: { /* RET */
608 PC = M[SP];
609 SP++;
610 PC |= (M[SP] << 8) & 0xff00;
611 SP++;
612 break;
613 }
614
615 /* Data Transfer Group */
616
617 case 062: { /* STA */
618 lo = M[PC];
619 PC++;
620 hi = M[PC];
621 PC++;
622 DAR = (hi << 8) + lo;
623 M[DAR] = A;
624 break;
625 }
626 case 072: { /* LDA */
627 lo = M[PC];
628 PC++;
629 hi = M[PC];
630 PC++;
631 DAR = (hi << 8) + lo;
632 A = M[DAR];
633 break;
634 }
635 case 042: { /* SHLD */
636 lo = M[PC];
637 PC++;
638 hi = M[PC];
639 PC++;
640 DAR = (hi << 8) + lo;
641 M[DAR] = HL;
642 DAR++;
643 M[DAR] = (HL >>8) & 0x00ff;
644 break;
645 }
646 case 052: { /* LHLD */
647 lo = M[PC];
648 PC++;
649 hi = M[PC];
650 PC++;
651 DAR = (hi << 8) + lo;
652 HL = M[DAR];
653 DAR++;
654 HL = HL | (M[DAR] <<8);
655 break;
656 }
657 case 0353: { /* XCHG */
658 DAR = HL;
659 HL = DE;
660 DE = DAR;
661 break;
662 }
663
664 /* Arithmetic Group */
665
666 case 0306: { /* ADI */
667 A += M[PC];
668 PC++;
669 setarith(A);
670 A = A & 0xFF;
671 break;
672 }
673 case 0316: { /* ACI */
674 carry = 0;
675 if (C) carry = 1;
676 A += M[PC];
677 A += carry;
678 PC++;
679 setarith(A);
680 A = A & 0xFF;
681 break;
682 }
683 case 0326: { /* SUI */
684 A -= M[PC];
685 PC++;
686 setarith(A);
687 A = A & 0xFF;
688 break;
689 }
690 case 0336: { /* SBI */
691 carry = 0;
692 if (C) carry = 1;
693 A -= (M[PC] + carry);
694 PC++;
695 setarith(A);
696 A = A & 0xFF;
697 break;
698 }
699 case 047: { /* DAA */
700 DAR = A & 0x0F;
701 if (DAR > 9 || AC > 0) {
702 DAR += 6;
703 A &= 0xF0;
704 A |= DAR & 0x0F;
705 if (DAR & 0x10)
706 AC = 0200000;
707 else
708 AC = 0;
709 }
710 DAR = (A >> 4) & 0x0F;
711 if (DAR > 9 || AC > 0) {
712 DAR += 6;
713 if (AC) DAR++;
714 A &= 0x0F;
715 A |= (DAR << 4);
716 }
717 if ((DAR << 4) & 0x100)
718 C = 0200000;
719 else
720 C = 0;
721 if (A & 0x80) {
722 S = 0200000;
723 } else {
724 S = 0;
725 }
726 if ((A & 0xff) == 0)
727 Z = 0200000;
728 else
729 Z = 0;
730 parity(A);
731 A = A & 0xFF;
732 break;
733 }
734 case 07: { /* RLC */
735 C = 0;
736 C = (A << 9) & 0200000;
737 A = (A << 1) & 0xFF;
738 if (C)
739 A |= 0x01;
740 break;
741 }
742 case 017: { /* RRC */
743 C = 0;
744 if ((A & 0x01) == 1)
745 C |= 0200000;
746 A = (A >> 1) & 0xFF;
747 if (C)
748 A |= 0x80;
749 break;
750 }
751 case 027: { /* RAL */
752 DAR = C;
753 C = 0;
754 C = (A << 9) & 0200000;
755 A = (A << 1) & 0xFF;
756 if (DAR)
757 A |= 1;
758 else
759 A &= 0xFE;
760 break;
761 }
762 case 037: { /* RAR */
763 DAR = C;
764 C = 0;
765 if ((A & 0x01) == 1)
766 C |= 0200000;
767 A = (A >> 1) & 0xFF;
768 if (DAR)
769 A |= 0x80;
770 else
771 A &= 0x7F;
772 break;
773 }
774 case 057: { /* CMA */
775 A = ~ A;
776 A &= 0xFF;
777 break;
778 }
779 case 077: { /* CMC */
780 C = ~ C;
781 C &= 0200000;
782 break;
783 }
784 case 067: { /* STC */
785 C = 0200000;
786 break;
787 }
788
789 /* Stack, I/O & Machine Control Group */
790
791 case 0: { /* NOP */
792 break;
793 }
794 case 0343: { /* XTHL */
795 lo = M[SP];
796 hi = M[SP + 1];
797 M[SP] = HL & 0xFF;
798 M[SP + 1] = (HL >> 8) & 0xFF;
799 HL = (hi << 8) + lo;
800 break;
801 }
802 case 0371: { /* SPHL */
803 SP = HL;
804 break;
805 }
806 case 0373: { /* EI */
807 INTE = 0200000;
808 break;
809 }
810 case 0363: { /* DI */
811 INTE = 0;
812 break;
813 }
814 case 0333: { /* IN */
815 DAR = M[PC] & 0xFF;
816 PC++;
817 if (DAR == 0xFF) {
818 A = (SR >> 8) & 0xFF;
819 } else {
820 A = dev_table[DAR].routine(0, 0);
821 }
822 break;
823 }
824 case 0323: { /* OUT */
825 DAR = M[PC] & 0xFF;
826 PC++;
827 dev_table[DAR].routine(1, A);
828 break;
829 }
830
831 default: {
832 if (cpu_unit.flags & UNIT_OPSTOP) {
833 reason = STOP_OPCODE;
834 PC--;
835 }
836 break;
837 }
838 }
839 }
840
841 /* Simulation halted */
842
843 saved_PC = PC;
844 return reason;
845 }
846
847 /* Test an 8080 flag condition and return 1 if true, 0 if false */
848 int32 cond(int32 con)
849 {
850 switch (con) {
851 case 0:
852 if (Z == 0) return (1);
853 break;
854 case 1:
855 if (Z != 0) return (1);
856 break;
857 case 2:
858 if (C == 0) return (1);
859 break;
860 case 3:
861 if (C != 0) return (1);
862 break;
863 case 4:
864 if (P == 0) return (1);
865 break;
866 case 5:
867 if (P != 0) return (1);
868 break;
869 case 6:
870 if (S == 0) return (1);
871 break;
872 case 7:
873 if (S != 0) return (1);
874 break;
875 default:
876 break;
877 }
878 return (0);
879 }
880
881 /* Set the <C>arry, <S>ign, <Z>ero and <P>arity flags following
882 an arithmetic operation on 'reg'.
883 */
884
885 void setarith(int32 reg)
886 {
887 int32 bc = 0;
888
889 if (reg & 0x100)
890 C = 0200000;
891 else
892 C = 0;
893 if (reg & 0x80) {
894 bc++;
895 S = 0200000;
896 } else {
897 S = 0;
898 }
899 if ((reg & 0xff) == 0)
900 Z = 0200000;
901 else
902 Z = 0;
903 AC = 0;
904 if (cpu_unit.flags & UNIT_CHIP) {
905 P = 0; /* parity is zero for *all* arith ops on Z80 */
906 } else {
907 parity(reg);
908 }
909 }
910
911 /* Set the <C>arry, <S>ign, <Z>ero amd <P>arity flags following
912 a logical (bitwise) operation on 'reg'.
913 */
914
915 void setlogical(int32 reg)
916 {
917 C = 0;
918 if (reg & 0x80) {
919 S = 0200000;
920 } else {
921 S = 0;
922 }
923 if ((reg & 0xff) == 0)
924 Z = 0200000;
925 else
926 Z = 0;
927 AC = 0;
928 parity(reg);
929 }
930
931 /* Set the Parity (P) flag based on parity of 'reg', i.e., number
932 of bits on even: P=0200000, else P=0
933 */
934
935 void parity(int32 reg)
936 {
937 int32 bc = 0;
938
939 if (reg & 0x01) bc++;
940 if (reg & 0x02) bc++;
941 if (reg & 0x04) bc++;
942 if (reg & 0x08) bc++;
943 if (reg & 0x10) bc++;
944 if (reg & 0x20) bc++;
945 if (reg & 0x40) bc++;
946 if (reg & 0x80) bc++;
947 P = ~(bc << 16);
948 P &= 0200000;
949 }
950
951 /* Set the <S>ign, <Z>ero amd <P>arity flags following
952 an INR/DCR operation on 'reg'.
953 */
954
955 void setinc(int32 reg)
956 {
957 int32 bc = 0;
958
959 if (reg & 0x80) {
960 bc++;
961 S = 0200000;
962 } else {
963 S = 0;
964 }
965 if ((reg & 0xff) == 0)
966 Z = 0200000;
967 else
968 Z = 0;
969 if (cpu_unit.flags & UNIT_CHIP) {
970 P = 0; /* parity is zero for *all* arith ops on Z80 */
971 } else {
972 parity(reg);
973 }
974 }
975
976 /* Get an 8080 register and return it */
977 int32 getreg(int32 reg)
978 {
979 switch (reg) {
980 case 0:
981 return ((BC >>8) & 0x00ff);
982 case 1:
983 return (BC & 0x00FF);
984 case 2:
985 return ((DE >>8) & 0x00ff);
986 case 3:
987 return (DE & 0x00ff);
988 case 4:
989 return ((HL >>8) & 0x00ff);
990 case 5:
991 return (HL & 0x00ff);
992 case 6:
993 return (M[HL]);
994 case 7:
995 return (A);
996 default:
997 break;
998 }
999 return 0;
1000 }
1001
1002 /* Put a value into an 8080 register from memory */
1003 void putreg(int32 reg, int32 val)
1004 {
1005 switch (reg) {
1006 case 0:
1007 BC = BC & 0x00FF;
1008 BC = BC | (val <<8);
1009 break;
1010 case 1:
1011 BC = BC & 0xFF00;
1012 BC = BC | val;
1013 break;
1014 case 2:
1015 DE = DE & 0x00FF;
1016 DE = DE | (val <<8);
1017 break;
1018 case 3:
1019 DE = DE & 0xFF00;
1020 DE = DE | val;
1021 break;
1022 case 4:
1023 HL = HL & 0x00FF;
1024 HL = HL | (val <<8);
1025 break;
1026 case 5:
1027 HL = HL & 0xFF00;
1028 HL = HL | val;
1029 break;
1030 case 6:
1031 M[HL] = val & 0xff;
1032 break;
1033 case 7:
1034 A = val & 0xff;
1035 default:
1036 break;
1037 }
1038 }
1039
1040 /* Return the value of a selected register pair */
1041 int32 getpair(int32 reg)
1042 {
1043 switch (reg) {
1044 case 0:
1045 return (BC);
1046 case 1:
1047 return (DE);
1048 case 2:
1049 return (HL);
1050 case 3:
1051 return (SP);
1052 default:
1053 break;
1054 }
1055 return 0;
1056 }
1057
1058 /* Return the value of a selected register pair, in PUSH
1059 format where 3 means A& flags, not SP */
1060 int32 getpush(int32 reg)
1061 {
1062 int32 stat;
1063
1064 switch (reg) {
1065 case 0:
1066 return (BC);
1067 case 1:
1068 return (DE);
1069 case 2:
1070 return (HL);
1071 case 3:
1072 stat = A << 8;
1073 if (S) stat |= 0x80;
1074 if (Z) stat |= 0x40;
1075 if (AC) stat |= 0x10;
1076 if (P) stat |= 0x04;
1077 stat |= 0x02;
1078 if (C) stat |= 0x01;
1079 return (stat);
1080 default:
1081 break;
1082 }
1083 return 0;
1084 }
1085
1086
1087 /* Place data into the indicated register pair, in PUSH
1088 format where 3 means A& flags, not SP */
1089 void putpush(int32 reg, int32 data)
1090 {
1091 switch (reg) {
1092 case 0:
1093 BC = data;
1094 break;
1095 case 1:
1096 DE = data;
1097 break;
1098 case 2:
1099 HL = data;
1100 break;
1101 case 3:
1102 A = (data >> 8) & 0xff;
1103 S = Z = AC = P = C = 0;
1104 if (data & 0x80) S = 0200000;
1105 if (data & 0x40) Z = 0200000;
1106 if (data & 0x10) AC = 0200000;
1107 if (data & 0x04) P = 0200000;
1108 if (data & 0x01) C = 0200000;
1109 break;
1110 default:
1111 break;
1112 }
1113 }
1114
1115
1116 /* Put a value into an 8080 register pair */
1117 void putpair(int32 reg, int32 val)
1118 {
1119 switch (reg) {
1120 case 0:
1121 BC = val;
1122 break;
1123 case 1:
1124 DE = val;
1125 break;
1126 case 2:
1127 HL = val;
1128 break;
1129 case 3:
1130 SP = val;
1131 break;
1132 default:
1133 break;
1134 }
1135 }
1136
1137
1138 /* Reset routine */
1139
1140 t_stat cpu_reset (DEVICE *dptr)
1141 {
1142 C = 0;
1143 Z = 0;
1144 saved_PC = 0;
1145 int_req = 0;
1146 sim_brk_types = sim_brk_dflt = SWMASK ('E');
1147 return SCPE_OK;
1148 }
1149
1150 /* Memory examine */
1151
1152 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
1153 {
1154 if (addr >= MEMSIZE) return SCPE_NXM;
1155 if (vptr != NULL) *vptr = M[addr] & 0377;
1156 return SCPE_OK;
1157 }
1158
1159 /* Memory deposit */
1160
1161 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
1162 {
1163 if (addr >= MEMSIZE) return SCPE_NXM;
1164 M[addr] = val & 0377;
1165 return SCPE_OK;
1166 }
1167
1168 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
1169 {
1170 int32 mc = 0;
1171 uint32 i;
1172
1173 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
1174 return SCPE_ARG;
1175 for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
1176 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
1177 return SCPE_OK;
1178 MEMSIZE = val;
1179 for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
1180 return SCPE_OK;
1181 }
1182
1183 int32 nulldev(int32 flag, int32 data)
1184 {
1185 if (flag == 0)
1186 return (0377);
1187 return 0;
1188 }
1189