740d66f72048f4930ceb4e67dc5ab59c94988457
1 /* altair_cpu.c: MITS Altair Intel 8080 CPU simulator
3 Copyright (c) 1997-2005, Charles E. Owen
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 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.
28 08-Oct-02 RMS Tied off spurious compiler warnings
30 The register state for the 8080 CPU is:
33 BC<0:15> BC Register Pair
34 DE<0:15> DE Register Pair
35 HL<0:15> HL Register Pair
41 PC<0:15> program counter
42 SP<0:15> Stack Pointer
44 The 8080 is an 8-bit CPU, which uses 16-bit registers to address
47 The 78 basic instructions come in 1, 2, and 3-byte flavors.
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.
56 1. Reasons to stop. The simulator can be stopped by:
59 I/O error in I/O simulator
60 Invalid OP code (if ITRAP is set on CPU)
63 There are 8 possible levels of interrupt, and in effect they
64 do a hardware CALL instruction to one of 8 possible low
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.
72 4. Adding I/O devices. These modules must be modified:
74 altair_cpu.c add I/O service routines to dev_table
75 altair_sys.c add pointer to data structures in sim_devices
81 #include "altair_defs.h"
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)
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 */
107 int32 PCX
; /* External view of PC */
109 extern int32 sim_int_char
;
110 extern int32 sim_brk_types
, sim_brk_dflt
, sim_brk_summ
; /* breakpoint info */
112 /* function prototypes */
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
);
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
);
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
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 */
213 /* Altair MITS standard BOOT EPROM, fits in upper 256K of memory */
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
249 /* CPU data structures
251 cpu_dev CPU device descriptor
252 cpu_unit CPU unit descriptor
253 cpu_reg CPU register list
254 cpu_mod CPU modifiers list
257 UNIT cpu_unit
= { UDATA (NULL
, UNIT_FIX
+ UNIT_BINK
, MAXMEMSIZE
) };
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) },
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
},
296 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
298 &cpu_ex
, &cpu_dep
, &cpu_reset
,
302 int32
sim_instr (void)
304 extern int32 sim_interval
;
305 int32 PC
, IR
, OP
, DAR
, reason
, hi
, lo
, carry
, i
;
307 PC
= saved_PC
& ADDRMASK
; /* load local PC */
311 /* Main instruction fetch/decode loop */
313 while (reason
== 0) { /* loop until halted */
314 if (sim_interval
<= 0) { /* check clock queue */
315 if (reason
= sim_process_event ()) break;
318 if (int_req
> 0) { /* interrupt? */
320 /* 8080 interrupts not implemented yet. None were used,
321 on a standard Altair 8800. All I/O is programmed. */
323 } /* end interrupt */
326 sim_brk_test (PC
, SWMASK ('E'))) { /* breakpoint? */
327 reason
= STOP_IBKPT
; /* stop simulation */
331 if (PC
== 0177400) { /* BOOT PROM address */
332 for (i
= 0; i
< 250; i
++) {
333 M
[i
+ 0177400] = bootrom
[i
] & 0xFF;
339 IR
= OP
= M
[PC
]; /* fetch instruction */
341 PC
= (PC
+ 1) & ADDRMASK
; /* increment PC */
345 if (OP
== 0166) { /* HLT Instruction*/
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 */
355 if ((OP
& 0xC0) == 0x40) { /* MOV */
356 DAR
= getreg(OP
& 0x07);
357 putreg((OP
>> 3) & 0x07, DAR
);
360 if ((OP
& 0xC7) == 0x06) { /* MVI */
361 putreg((OP
>> 3) & 0x07, M
[PC
]);
365 if ((OP
& 0xCF) == 0x01) { /* LXI */
366 DAR
= M
[PC
] & 0x00ff;
368 DAR
= DAR
| (M
[PC
] <<8) & 0xFF00;;
369 putpair((OP
>> 4) & 0x03, DAR
);
373 if ((OP
& 0xEF) == 0x0A) { /* LDAX */
374 DAR
= getpair((OP
>> 4) & 0x03);
378 if ((OP
& 0xEF) == 0x02) { /* STAX */
379 DAR
= getpair((OP
>> 4) & 0x03);
384 if ((OP
& 0xF8) == 0xB8) { /* CMP */
386 DAR
-= getreg(OP
& 0x07);
390 if ((OP
& 0xC7) == 0xC2) { /* JMP <condition> */
391 if (cond((OP
>> 3) & 0x07) == 1) {
402 if ((OP
& 0xC7) == 0xC4) { /* CALL <condition> */
403 if (cond((OP
>> 3) & 0x07) == 1) {
409 M
[SP
] = (PC
>> 8) & 0xff;
418 if ((OP
& 0xC7) == 0xC0) { /* RET <condition> */
419 if (cond((OP
>> 3) & 0x07) == 1) {
422 PC
|= (M
[SP
] << 8) & 0xff00;
427 if ((OP
& 0xC7) == 0xC7) { /* RST */
429 M
[SP
] = (PC
>> 8) & 0xff;
436 if ((OP
& 0xCF) == 0xC5) { /* PUSH */
437 DAR
= getpush((OP
>> 4) & 0x03);
439 M
[SP
] = (DAR
>> 8) & 0xff;
444 if ((OP
& 0xCF) == 0xC1) { /*POP */
449 putpush((OP
>> 4) & 0x03, DAR
);
452 if ((OP
& 0xF8) == 0x80) { /* ADD */
453 A
+= getreg(OP
& 0x07);
458 if ((OP
& 0xF8) == 0x88) { /* ADC */
461 A
+= getreg(OP
& 0x07);
467 if ((OP
& 0xF8) == 0x90) { /* SUB */
468 A
-= getreg(OP
& 0x07);
473 if ((OP
& 0xF8) == 0x98) { /* SBB */
476 A
-= (getreg(OP
& 0x07)) + carry
;
481 if ((OP
& 0xC7) == 0x04) { /* INR */
482 DAR
= getreg((OP
>> 3) & 0x07);
486 putreg((OP
>> 3) & 0x07, DAR
);
489 if ((OP
& 0xC7) == 0x05) { /* DCR */
490 DAR
= getreg((OP
>> 3) & 0x07);
494 putreg((OP
>> 3) & 0x07, DAR
);
497 if ((OP
& 0xCF) == 0x03) { /* INX */
498 DAR
= getpair((OP
>> 4) & 0x03);
501 putpair((OP
>> 4) & 0x03, DAR
);
504 if ((OP
& 0xCF) == 0x0B) { /* DCX */
505 DAR
= getpair((OP
>> 4) & 0x03);
508 putpair((OP
>> 4) & 0x03, DAR
);
511 if ((OP
& 0xCF) == 0x09) { /* DAD */
512 HL
+= getpair((OP
>> 4) & 0x03);
519 if ((OP
& 0xF8) == 0xA0) { /* ANA */
520 A
&= getreg(OP
& 0x07);
526 if ((OP
& 0xF8) == 0xA8) { /* XRA */
527 A
^= getreg(OP
& 0x07);
533 if ((OP
& 0xF8) == 0xB0) { /* ORA */
534 A
|= getreg(OP
& 0x07);
543 /* The Big Instruction Decode Switch */
547 /* Logical instructions */
549 case 0376: { /* CPI */
556 case 0346: { /* ANI */
564 case 0356: { /* XRI */
572 case 0366: { /* ORI */
581 /* Jump instructions */
583 case 0303: { /* JMP */
591 case 0351: { /* PCHL */
595 case 0315: { /* CALL */
601 M
[SP
] = (PC
>> 8) & 0xff;
607 case 0311: { /* RET */
610 PC
|= (M
[SP
] << 8) & 0xff00;
615 /* Data Transfer Group */
617 case 062: { /* STA */
622 DAR
= (hi
<< 8) + lo
;
626 case 072: { /* LDA */
631 DAR
= (hi
<< 8) + lo
;
635 case 042: { /* SHLD */
640 DAR
= (hi
<< 8) + lo
;
643 M
[DAR
] = (HL
>>8) & 0x00ff;
646 case 052: { /* LHLD */
651 DAR
= (hi
<< 8) + lo
;
654 HL
= HL
| (M
[DAR
] <<8);
657 case 0353: { /* XCHG */
664 /* Arithmetic Group */
666 case 0306: { /* ADI */
673 case 0316: { /* ACI */
683 case 0326: { /* SUI */
690 case 0336: { /* SBI */
693 A
-= (M
[PC
] + carry
);
699 case 047: { /* DAA */
701 if (DAR
> 9 || AC
> 0) {
710 DAR
= (A
>> 4) & 0x0F;
711 if (DAR
> 9 || AC
> 0) {
717 if ((DAR
<< 4) & 0x100)
736 C
= (A
<< 9) & 0200000;
742 case 017: { /* RRC */
751 case 027: { /* RAL */
754 C
= (A
<< 9) & 0200000;
762 case 037: { /* RAR */
774 case 057: { /* CMA */
779 case 077: { /* CMC */
784 case 067: { /* STC */
789 /* Stack, I/O & Machine Control Group */
794 case 0343: { /* XTHL */
798 M
[SP
+ 1] = (HL
>> 8) & 0xFF;
802 case 0371: { /* SPHL */
806 case 0373: { /* EI */
810 case 0363: { /* DI */
814 case 0333: { /* IN */
818 A
= (SR
>> 8) & 0xFF;
820 A
= dev_table
[DAR
].routine(0, 0);
824 case 0323: { /* OUT */
827 dev_table
[DAR
].routine(1, A
);
832 if (cpu_unit
.flags
& UNIT_OPSTOP
) {
833 reason
= STOP_OPCODE
;
841 /* Simulation halted */
847 /* Test an 8080 flag condition and return 1 if true, 0 if false */
848 int32
cond(int32 con
)
852 if (Z
== 0) return (1);
855 if (Z
!= 0) return (1);
858 if (C
== 0) return (1);
861 if (C
!= 0) return (1);
864 if (P
== 0) return (1);
867 if (P
!= 0) return (1);
870 if (S
== 0) return (1);
873 if (S
!= 0) return (1);
881 /* Set the <C>arry, <S>ign, <Z>ero and <P>arity flags following
882 an arithmetic operation on 'reg'.
885 void setarith(int32 reg
)
899 if ((reg
& 0xff) == 0)
904 if (cpu_unit
.flags
& UNIT_CHIP
) {
905 P
= 0; /* parity is zero for *all* arith ops on Z80 */
911 /* Set the <C>arry, <S>ign, <Z>ero amd <P>arity flags following
912 a logical (bitwise) operation on 'reg'.
915 void setlogical(int32 reg
)
923 if ((reg
& 0xff) == 0)
931 /* Set the Parity (P) flag based on parity of 'reg', i.e., number
932 of bits on even: P=0200000, else P=0
935 void parity(int32 reg
)
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
++;
951 /* Set the <S>ign, <Z>ero amd <P>arity flags following
952 an INR/DCR operation on 'reg'.
955 void setinc(int32 reg
)
965 if ((reg
& 0xff) == 0)
969 if (cpu_unit
.flags
& UNIT_CHIP
) {
970 P
= 0; /* parity is zero for *all* arith ops on Z80 */
976 /* Get an 8080 register and return it */
977 int32
getreg(int32 reg
)
981 return ((BC
>>8) & 0x00ff);
983 return (BC
& 0x00FF);
985 return ((DE
>>8) & 0x00ff);
987 return (DE
& 0x00ff);
989 return ((HL
>>8) & 0x00ff);
991 return (HL
& 0x00ff);
1002 /* Put a value into an 8080 register from memory */
1003 void putreg(int32 reg
, int32 val
)
1008 BC
= BC
| (val
<<8);
1016 DE
= DE
| (val
<<8);
1024 HL
= HL
| (val
<<8);
1040 /* Return the value of a selected register pair */
1041 int32
getpair(int32 reg
)
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
)
1073 if (S
) stat
|= 0x80;
1074 if (Z
) stat
|= 0x40;
1075 if (AC
) stat
|= 0x10;
1076 if (P
) stat
|= 0x04;
1078 if (C
) stat
|= 0x01;
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
)
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;
1116 /* Put a value into an 8080 register pair */
1117 void putpair(int32 reg
, int32 val
)
1140 t_stat
cpu_reset (DEVICE
*dptr
)
1146 sim_brk_types
= sim_brk_dflt
= SWMASK ('E');
1150 /* Memory examine */
1152 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1154 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1155 if (vptr
!= NULL
) *vptr
= M
[addr
] & 0377;
1159 /* Memory deposit */
1161 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1163 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1164 M
[addr
] = val
& 0377;
1168 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1173 if ((val
<= 0) || (val
> MAXMEMSIZE
) || ((val
& 07777) != 0))
1175 for (i
= val
; i
< MEMSIZE
; i
++) mc
= mc
| M
[i
];
1176 if ((mc
!= 0) && (!get_yn ("Really truncate memory [N]?", FALSE
)))
1179 for (i
= MEMSIZE
; i
< MAXMEMSIZE
; i
++) M
[i
] = 0;
1183 int32
nulldev(int32 flag
, int32 data
)