1 /*
2  * Copyright (c) 2019 Georg Brein. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <wchar.h>
38 #include <setjmp.h>
39 #include <signal.h>
40 #include <time.h>
41 
42 #include <sys/time.h>
43 #include <unistd.h>
44 
45 #include "tnylpo.h"
46 
47 
48 unsigned char *memory = NULL;
49 
50 
51 /*
52  * CPU status
53  */
54 static int flag_i = 0;
55 
56 
57 /*
58  * CPU registers and flags
59  */
60 int reg_sp = 0;
61 int reg_pc = 0;
62 unsigned char reg_a = 0;
63 unsigned char reg_b = 0;
64 unsigned char reg_c = 0;
65 unsigned char reg_d = 0;
66 unsigned char reg_e = 0;
67 unsigned char reg_h = 0;
68 unsigned char reg_l = 0;
69 static unsigned char alt_reg_a = 0;
70 static unsigned char alt_reg_b = 0;
71 static unsigned char alt_reg_c = 0;
72 static unsigned char alt_reg_d = 0;
73 static unsigned char alt_reg_e = 0;
74 static unsigned char alt_reg_h = 0;
75 static unsigned char alt_reg_l = 0;
76 static unsigned char reg_ixh = 0;
77 static unsigned char reg_ixl = 0;
78 static unsigned char reg_iyh = 0;
79 static unsigned char reg_iyl = 0;
80 static unsigned char reg_r = 0;
81 static unsigned char reg_i = 0;
82 static int flag_s = 0;
83 static int flag_z = 0;
84 static int flag_y = 0;
85 static int flag_h = 0;
86 static int flag_x = 0;
87 static int flag_p = 0;
88 #define flag_v flag_p
89 static int flag_n = 0;
90 static int flag_c = 0;
91 static int alt_flag_s = 0;
92 static int alt_flag_z = 0;
93 static int alt_flag_y = 0;
94 static int alt_flag_h = 0;
95 static int alt_flag_x = 0;
96 static int alt_flag_p = 0;
97 static int alt_flag_n = 0;
98 static int alt_flag_c = 0;
99 
100 
101 /*
102  * termination flag
103  */
104 int terminate = 0;
105 
106 
107 /*
108  * dump flag
109  */
110 static sig_atomic_t dump = 0;
111 
112 
113 /*
114  * reason for termination
115  */
116 enum reason term_reason = OK_NOTRUN;
117 
118 
119 /*
120  * start of current instruction including prefixes
121  */
122 static int current_instruction = (-1);
123 /*
124  * parts of the current instruction
125  */
126 static int prefix, opcode, opcode2, op_low, op_high, disp;
127 /*
128  * the mysterious internal register which is sometimes visible via X3, X5
129  */
130 static int internal = 0;
131 
132 
133 
134 /*
135  * get word from memory
136  */
137 static inline int
get_word(int address)138 get_word(int address) {
139 	int word = memory[(address + 1) & 0xffff];
140 	word <<= 8;
141 	word |= memory[address];
142 	return word;
143 }
144 
145 
146 /*
147  * store word to memory
148  */
149 static inline void
set_word(int address,int word)150 set_word(int address, int word) {
151 	memory[address] = (word & 0xff);
152 	memory[(address + 1) & 0xffff] = ((word >> 8) & 0xff);
153 }
154 
155 
156 static inline int
get_bc(void)157 get_bc(void) { int bc = reg_b; bc <<= 8; bc |= reg_c; return bc; }
158 
159 static inline void
set_bc(int bc)160 set_bc(int bc) { reg_c = bc & 0xff; reg_b = (bc >> 8) & 0xff; }
161 
162 static inline int
get_de(void)163 get_de(void) { int de = reg_d; de <<= 8; de |= reg_e; return de; }
164 
165 static inline void
set_de(int de)166 set_de(int de) { reg_e = de & 0xff; reg_d = (de >> 8) & 0xff; }
167 
168 static inline int
get_hl(void)169 get_hl(void) { int hl = reg_h; hl <<= 8; hl |= reg_l; return hl; }
170 
171 static inline void
set_hl(int hl)172 set_hl(int hl) { reg_l = hl & 0xff; reg_h = (hl >> 8) & 0xff; }
173 
174 static inline int
get_ix(void)175 get_ix(void) { int ix = reg_ixh; ix <<= 8; ix |= reg_ixl; return ix; }
176 
177 static inline void
set_ix(int ix)178 set_ix(int ix) { reg_ixl = ix & 0xff; reg_ixh = (ix >> 8) & 0xff; }
179 
180 static inline int
get_iy(void)181 get_iy(void) { int iy = reg_iyh; iy <<= 8; iy |= reg_iyl; return iy; }
182 
183 static inline void
set_iy(int iy)184 set_iy(int iy) { reg_iyl = iy & 0xff; reg_iyh = (iy >> 8) & 0xff; }
185 
186 
187 /*
188  * dump registers and memory to log file
189  */
190 static void
dump_machine(const char * label)191 dump_machine(const char *label) {
192 	plog("start of %s machine dump", label);
193 	plog("a=%02x f=%c%c%c%c%c%c%c%c bc=%04x de=%04x hl=%04x",
194 	    reg_a, flag_s ? 's' : '-', flag_z ? 'z' : '-',
195 	    flag_y ? 'y' : '-', flag_h ? 'h' : '-', flag_x ? 'x' : '-',
196 	    flag_p ? 'p' : '-', flag_n ? 'n' : '-', flag_c ? 'c' : '-',
197 	    get_bc(), get_de(), get_hl());
198 	plog("a\'=%02x f\'=%c%c%c%c%c%c%c%c bc\'=%04x de\'=%04x hl\'=%04x",
199 	    alt_reg_a, alt_flag_s ? 's' : '-',
200 	    alt_flag_z ? 'z' : '-', alt_flag_y ? 'y' : '-',
201 	    alt_flag_h ? 'h' : '-', alt_flag_x ? 'x' : '-',
202 	    alt_flag_p ? 'p' : '-', alt_flag_n ? 'n' : '-',
203 	    alt_flag_c ? 'c' : '-', (alt_reg_b << 8) | alt_reg_c,
204 	    (alt_reg_d << 8) | alt_reg_e, (alt_reg_h << 8) | alt_reg_l);
205 	plog("ix=%04x iy=%04x sp=%04x pc=%04x, r=%02x i=%02x",
206 	    get_ix(), get_iy(), reg_sp, reg_pc, reg_r, reg_i);
207 	plog("interrupts %s", flag_i ? "enabled" : "disabled");
208 	plog_dump(0, MEMORY_SIZE);
209 	plog("end of %s machine dump", label);
210 }
211 
212 
213 /*
214  * initialize the CPU emulator: allocate main memory, initialize OS emulation
215  */
216 int
cpu_init(void)217 cpu_init(void) {
218 	int rc = 0;
219 	struct timeval tv;
220 	/*
221 	 * allocate Z80 memory and fill it with HALT instructions
222 	 */
223 	memory = alloc(MEMORY_SIZE);
224 	memset(memory, 0x76 /* HALT */, MEMORY_SIZE);
225 	/*
226 	 * set register R to some random value; programs (e. g. Turbo Pascal)
227 	 * use R for generating random numbers
228 	 *
229 	 * No, this random number is not suitable for
230 	 * cryptographical purposes.
231 	 */
232 	gettimeofday(&tv, NULL);
233 	srand((unsigned) tv.tv_usec);
234 	reg_r = (rand() & 0x7f);
235 	/*
236 	 * initialize OS emulation
237 	 */
238 	rc = os_init();
239 	if (rc) goto premature_exit;
240 	/*
241 	 * perform startup dump
242 	 */
243 	if (conf_dump & DUMP_STARTUP) dump_machine("startup");
244 premature_exit:
245 	if (rc) free(memory);
246 	return rc;
247 }
248 
249 
250 /*
251  * get word from stack
252  */
253 static int
pop(void)254 pop(void) {
255 	int word;
256 	word = memory[reg_sp];
257 	reg_sp = ((reg_sp + 1) & 0xffff);
258 	word |= (((int) memory[reg_sp]) << 8);
259 	reg_sp = ((reg_sp + 1) & 0xffff);
260 	return word;
261 }
262 
263 
264 /*
265  * put word on stack
266  */
267 static void
push(int word)268 push(int word) {
269 	reg_sp = ((reg_sp + 0xffff) & 0xffff);
270 	memory[reg_sp] = ((word >> 8) & 0xff);
271 	reg_sp = ((reg_sp + 0xffff) & 0xffff);
272 	memory[reg_sp] = word & 0xff;
273 }
274 
275 
276 /*
277  * do nothing
278  */
279 static void
inst_nop(void)280 inst_nop(void) { }
281 
282 
283 /*
284  * load immediate extended
285  */
286 static void
inst_lxi(void)287 inst_lxi(void) {
288 	switch (opcode & 0x30) {
289 	case 0x00:
290 		reg_c = op_low;
291 		reg_b = op_high;
292 		break;
293 	case 0x10:
294 		reg_e = op_low;
295 		reg_d = op_high;
296 		break;
297 	case 0x20:
298 		if (prefix == 0xdd) {
299 			reg_ixl = op_low;
300 			reg_ixh = op_high;
301 		} else if (prefix == 0xfd) {
302 			reg_iyl = op_low;
303 			reg_iyh = op_high;
304 		} else {
305 			reg_l = op_low;
306 			reg_h = op_high;
307 		}
308 		break;
309 	case 0x30:
310 		reg_sp = op_high;
311 		reg_sp <<= 8;
312 		reg_sp |= op_low;
313 		break;
314 	}
315 }
316 
317 
318 /*
319  * store A extended
320  */
321 static void
inst_stax(void)322 inst_stax(void) {
323 	memory[(opcode & 0x10) ? get_de() : get_bc()] = reg_a;
324 }
325 
326 
327 /*
328  * load A extended
329  */
330 static void
inst_ldax(void)331 inst_ldax(void) {
332 	reg_a = memory[(opcode & 0x10) ? get_de() : get_bc()];
333 }
334 
335 
336 /*
337  * store A
338  */
339 static void
inst_sta(void)340 inst_sta(void) {
341 	int addr;
342 	addr = op_high;
343 	addr <<= 8;
344 	addr |= op_low;
345 	memory[addr] = reg_a;
346 }
347 
348 
349 /*
350  * load A
351  */
352 static void
inst_lda(void)353 inst_lda(void) {
354 	int addr;
355 	addr = op_high;
356 	addr <<= 8;
357 	addr |= op_low;
358 	reg_a = memory[addr];
359 }
360 
361 
362 /*
363  * store HL/IX/IY
364  */
365 static void
inst_shld(void)366 inst_shld(void) {
367 	int addr;
368 	unsigned char *lp, *hp;
369 	addr = op_high;
370 	addr <<= 8;
371 	addr |= op_low;
372 	lp = memory + addr;
373 	hp = memory + ((addr + 1) & 0xffff);
374 	switch (prefix) {
375 	case 0x00:
376 		*lp = reg_l;
377 		*hp = reg_h;
378 		break;
379 	case 0xdd:
380 		*lp = reg_ixl;
381 		*hp = reg_ixh;
382 		break;
383 	case 0xfd:
384 		*lp = reg_iyl;
385 		*hp = reg_iyh;
386 		break;
387 	}
388 }
389 
390 
391 /*
392  * load HL/IX/IY
393  */
394 static void
inst_lhld(void)395 inst_lhld(void) {
396 	int addr;
397 	unsigned char *lp, *hp;
398 	addr = op_high;
399 	addr <<= 8;
400 	addr |= op_low;
401 	lp = memory + addr;
402 	hp = memory + ((addr + 1) & 0xffff);
403 	switch (prefix) {
404 	case 0x00:
405 		reg_l = *lp;
406 		reg_h = *hp;
407 		break;
408 	case 0xdd:
409 		reg_ixl = *lp;
410 		reg_ixh = *hp;
411 		break;
412 	case 0xfd:
413 		reg_iyl = *lp;
414 		reg_iyh = *hp;
415 		break;
416 	}
417 }
418 
419 
420 /*
421  * relative jump
422  */
423 static void
inst_jr(void)424 inst_jr(void) {
425 	internal = op_low;
426 	if (internal & 0x80) internal |= 0xff00;
427 	internal = (internal + reg_pc) & 0xffff;
428 	reg_pc = internal;
429 }
430 
431 
432 /*
433  * conditional relative jump
434  */
435 static void
inst_jrcc(void)436 inst_jrcc(void) {
437 	switch (opcode & 0x18) {
438 	case 0x00: if (! flag_z) inst_jr(); break;
439 	case 0x08: if (flag_z) inst_jr(); break;
440 	case 0x10: if (! flag_c) inst_jr(); break;
441 	case 0x18: if (flag_c) inst_jr(); break;
442 	}
443 }
444 
445 
446 /*
447  * DJNZ
448  */
449 static void
inst_djnz(void)450 inst_djnz(void) {
451 	reg_b = reg_b ? reg_b - 1 : 0xff;
452 	if (reg_b) inst_jr();
453 }
454 
455 
456 /*
457  * EX AF,AF'
458  */
459 static void
inst_exaf(void)460 inst_exaf(void) {
461 	unsigned char uc;
462 	int i;
463 	uc = reg_a; reg_a = alt_reg_a; alt_reg_a = uc;
464 	i = flag_c; flag_c = alt_flag_c; alt_flag_c = i;
465 	i = flag_n; flag_n = alt_flag_n; alt_flag_n = i;
466 	i = flag_p; flag_v = alt_flag_p; alt_flag_p = i;
467 	i = flag_x; flag_x = alt_flag_x; alt_flag_x = i;
468 	i = flag_h; flag_h = alt_flag_h; alt_flag_h = i;
469 	i = flag_y; flag_y = alt_flag_y; alt_flag_y = i;
470 	i = flag_z; flag_z = alt_flag_z; alt_flag_z = i;
471 	i = flag_s; flag_s = alt_flag_s; alt_flag_s = i;
472 }
473 
474 
475 /*
476  * set carry flag
477  */
478 static void
inst_scf(void)479 inst_scf(void) {
480 	flag_y = ((reg_a & 0x20) != 0);
481 	flag_h = 0;
482 	flag_x = ((reg_a & 0x08) != 0);
483 	flag_n = 0;
484 	flag_c = 1;
485 }
486 
487 
488 /*
489  * complement carry flag
490  */
491 static void
inst_ccf(void)492 inst_ccf(void) {
493 	flag_y = ((reg_a & 0x20) != 0);
494 	flag_h = flag_c;
495 	flag_x = ((reg_a & 0x08) != 0);
496 	flag_n = 0;
497 	flag_c = (flag_c == 0);
498 }
499 
500 
501 /*
502  * halt CPU: terminates program execution
503  */
504 static void
inst_halt(void)505 inst_halt(void) {
506 	plog("0x%04x: HALT executed", current_instruction);
507 	terminate = 1;
508 	term_reason = ERR_HALT;
509 }
510 
511 
512 /*
513  * complement A
514  */
515 static void
inst_cpl(void)516 inst_cpl(void) {
517 	reg_a ^= 0xff;
518 	flag_y = ((reg_a & 0x20) != 0);
519 	flag_h = 1;
520 	flag_x = ((reg_a & 0x08) != 0);
521 	flag_n = 1;
522 }
523 
524 
525 /*
526  * helper function for inst_rla(), inst_rlca(), inst_rra(), and inst_rrca()
527  */
528 static void
rot_flags(void)529 rot_flags(void) {
530 	flag_y = ((reg_a & 0x20) != 0);
531 	flag_h = 0;
532 	flag_x = ((reg_a & 0x08) != 0);
533 	flag_n = 0;
534 }
535 
536 
537 /*
538  * 9-Bit rotation of A to the left
539  */
540 static void
inst_rla(void)541 inst_rla(void) {
542 	unsigned t;
543 	t = reg_a;
544 	t <<= 1;
545 	t |= flag_c;
546 	flag_c = ((t & 0x100) == 0x100);
547 	reg_a = (unsigned char) (t & 0xff);
548 	rot_flags();
549 }
550 
551 
552 /*
553  * 8-Bit rotation of A to the left
554  */
555 static void
inst_rlca(void)556 inst_rlca(void) {
557 	flag_c = ((reg_a & 0x80) == 0x80);
558 	reg_a <<= 1;
559 	reg_a &= 0xff;
560 	reg_a |= flag_c;
561 	rot_flags();
562 }
563 
564 
565 /*
566  * 9-Bit rotation of A to the right
567  */
568 static void
inst_rra(void)569 inst_rra(void) {
570 	unsigned t;
571 	t = reg_a;
572 	if (flag_c) t |= 0x100;
573 	flag_c = ((t & 0x01) == 0x01);
574 	t >>= 1;
575 	reg_a = (unsigned char) (t & 0xff);
576 	rot_flags();
577 }
578 
579 
580 /*
581  * 8-Bit rotation of A to the right
582  */
583 static void
inst_rrca(void)584 inst_rrca(void) {
585 	flag_c = ((reg_a & 0x01) == 0x01);
586 	reg_a >>= 1;
587 	if (flag_c) reg_a |= 0x80;
588 	rot_flags();
589 }
590 
591 
592 /*
593  * return address of 8-bit register/memory operand
594  * n is the 3-bit field from the opcode describing the register/memory operand:
595  * (0=b, 1=c, 2=d, 3=e, 4=h/ixh/iyh, 5=l/ixl/iyl, 6=(hl)/(ix+d)/(iy+d), 7=a)
596  * a is the second 3-bit operand field from the same opcode (or zero if
597  * there is none)
598  */
599 static unsigned char *
operand8(int n,int a)600 operand8(int n, int a) {
601 	switch (n) {
602 	case 0: return &reg_b;
603 	case 1: return &reg_c;
604 	case 2: return &reg_d;
605 	case 3: return &reg_e;
606 	case 4:
607 		if (a == 6) return &reg_h;
608 		switch (prefix) {
609 		case 0xdd: return &reg_ixh;
610 		case 0xfd: return &reg_iyh;
611 		default: return &reg_h;
612 		}
613 	case 5:
614 		if (a == 6) return &reg_l;
615 		switch (prefix) {
616 		case 0xdd: return &reg_ixl;
617 		case 0xfd: return &reg_iyl;
618 		default: return &reg_l;
619 		}
620 	case 6:
621 		switch (prefix) {
622 		case 0xdd:
623 			internal = disp;
624 			if (internal & 0x80) internal |= 0xff00;
625 			internal = (get_ix() + internal) & 0xffff;
626 			return memory + internal;
627 		case 0xfd:
628 			internal = disp;
629 			if (internal & 0x80) internal |= 0xff00;
630 			internal = (get_iy() + internal) & 0xffff;
631 			return memory + internal;
632 		default:
633 			return memory + get_hl();
634 		}
635 	default: return &reg_a;
636 	}
637 
638 }
639 
640 
641 /*
642  * move 8-bit data
643  */
644 static void
inst_mov(void)645 inst_mov(void) {
646 	int d, s;
647 	unsigned char *dp, *sp;
648 	d = ((opcode >> 3) & 0x07);
649 	s = (opcode & 0x07);
650 	dp = operand8(d, s);
651 	sp = operand8(s, d);
652 	*dp = *sp;
653 }
654 
655 
656 /*
657  * move 8-bit immediate
658  */
659 static void
inst_mvi(void)660 inst_mvi(void) {
661 	*operand8((opcode >> 3) & 0x07, 0) = op_low;
662 }
663 
664 
665 /*
666  * returns sumand1 + summand2 + carry, sets flags
667  */
668 static unsigned char
add8(unsigned char summand1,unsigned char summand2,int carry)669 add8(unsigned char summand1, unsigned char summand2, int carry) {
670 	int c6;
671 	unsigned s1 = summand1, s2 = summand2, su, cy = carry ? 1 : 0;
672 	/*
673 	 * unrolled loop
674 	 */
675 	su = (s1 ^ s2 ^ cy) & 0x01;
676 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x01;
677 	cy <<= 1;
678 	su |= (s1 ^ s2 ^ cy) & 0x02;
679 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x02;
680 	cy <<= 1;
681 	su |= (s1 ^ s2 ^ cy) & 0x04;
682 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x04;
683 	cy <<= 1;
684 	su |= (s1 ^ s2 ^ cy) & 0x08;
685 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x08;
686 	flag_h = (cy != 0);
687 	cy <<= 1;
688 	su |= (s1 ^ s2 ^ cy) & 0x10;
689 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x10;
690 	cy <<= 1;
691 	su |= (s1 ^ s2 ^ cy) & 0x20;
692 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x20;
693 	cy <<= 1;
694 	su |= (s1 ^ s2 ^ cy) & 0x40;
695 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x40;
696 	c6 = (cy != 0);
697 	cy <<= 1;
698 	su |= (s1 ^ s2 ^ cy) & 0x80;
699 	cy = ((s2 & cy) | (s1 & (s2 | cy))) & 0x80;
700 	flag_c = (cy != 0);
701 	flag_n = 0;
702 	flag_v = flag_c ^ c6;
703 	flag_x = ((su & 0x08) != 0);
704 	flag_y = ((su & 0x20) != 0);
705 	flag_z = (su == 0);
706 	flag_s = ((su & 0x80) != 0);
707 	return (unsigned char) su;
708 }
709 
710 
711 /*
712  * returns minuend - subtrahend - carry, sets flags
713  */
714 static unsigned char
sub8(unsigned char minuend,unsigned char subtrahend,int carry)715 sub8(unsigned char minuend, unsigned char subtrahend, int carry) {
716 	int c6;
717 	unsigned mi = minuend, sb = subtrahend, df, cy = carry ? 1 : 0;
718 	/*
719 	 * unrolled loop
720 	 */
721 	df = (mi ^ sb ^ cy) & 0x01;
722 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x01;
723 	cy <<= 1;
724 	df |= (mi ^ sb ^ cy) & 0x02;
725 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x02;
726 	cy <<= 1;
727 	df |= (mi ^ sb ^ cy) & 0x04;
728 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x04;
729 	cy <<= 1;
730 	df |= (mi ^ sb ^ cy) & 0x08;
731 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x08;
732 	flag_h = (cy != 0);
733 	cy <<= 1;
734 	df |= (mi ^ sb ^ cy) & 0x10;
735 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x10;
736 	cy <<= 1;
737 	df |= (mi ^ sb ^ cy) & 0x20;
738 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x20;
739 	cy <<= 1;
740 	df |= (mi ^ sb ^ cy) & 0x40;
741 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x40;
742 	c6 = (cy != 0);
743 	cy <<= 1;
744 	df |= (mi ^ sb ^ cy) & 0x80;
745 	cy = ((sb & cy) | (~mi & (sb | cy))) & 0x80;
746 	flag_c = (cy != 0);
747 	flag_n = 1;
748 	flag_v = flag_c ^ c6;
749 	flag_x = ((df & 0x08) != 0);
750 	flag_y = ((df & 0x20) != 0);
751 	flag_z = (df == 0);
752 	flag_s = ((df & 0x80) != 0);
753 	return (unsigned char) df;
754 }
755 
756 
757 /*
758  * returns s1 + s2 + carry, sets flags
759  */
760 static unsigned
add16(unsigned s1,unsigned s2,int carry)761 add16(unsigned s1, unsigned s2, int carry) {
762 	int c14 = 0, i;
763 	unsigned su = 0, cy = carry ? 1 : 0, ma = 1;
764 	for (i = 0; i < 16; i++) {
765 		su |= (s1 ^ s2 ^ cy) & ma;
766 		cy = ((s2 & cy) | (s1 & (s2 | cy))) & ma;
767 		if (i == 11) flag_h = (cy != 0);
768 		if (i == 14) c14 = (cy != 0);
769 		if (i == 15) flag_c = (cy != 0);
770 		cy <<= 1;
771 		ma <<= 1;
772 	}
773 	flag_n = 0;
774 	flag_v = flag_c ^ c14;
775 	flag_x = ((su & 0x0800) != 0);
776 	flag_y = ((su & 0x2000) != 0);
777 	flag_z = (su == 0);
778 	flag_s = ((su & 0x8000) != 0);
779 	return su;
780 }
781 
782 
783 /*
784  * returns s1 - s2 - carry, sets flags
785  */
786 static unsigned
sub16(unsigned mi,unsigned sb,int carry)787 sub16(unsigned mi, unsigned sb, int carry) {
788 	int c14 = 0, i;
789 	unsigned df = 0, cy = carry ? 1 : 0, ma = 1;
790 	for (i = 0; i < 16; i++) {
791 		df |= (mi ^ sb ^ cy) & ma;
792 		cy = ((sb & cy) | (~mi & (sb | cy))) & ma;
793 		if (i == 11) flag_h = (cy != 0);
794 		if (i == 14) c14 = (cy != 0);
795 		if (i == 15) flag_c = (cy != 0);
796 		cy <<= 1;
797 		ma <<= 1;
798 	}
799 	flag_n = 1;
800 	flag_v = flag_c ^ c14;
801 	flag_x = ((df & 0x0800) != 0);
802 	flag_y = ((df & 0x2000) != 0);
803 	flag_z = (df == 0);
804 	flag_s = ((df & 0x8000) != 0);
805 	return df;
806 }
807 
808 
809 /*
810  * 8-bit increment
811  */
812 static void
inst_inr(void)813 inst_inr(void) {
814 	unsigned char *dp;
815 	/*
816 	 * doesn't affect carry flag
817 	 */
818 	int old_c = flag_c;
819 	dp = operand8((opcode >> 3) & 0x07, 0);
820 	*dp = add8(*dp, 1, 0);
821 	flag_c = old_c;
822 }
823 
824 
825 /*
826  * 16-bit increment
827  */
828 static void
inst_inx(void)829 inst_inx(void) {
830 	switch (opcode & 0x30) {
831 	case 0x00: set_bc((get_bc() + 1) & 0xffff); break;
832 	case 0x10: set_de((get_de() + 1) & 0xffff); break;
833 	case 0x20:
834 		switch (prefix) {
835 		case 0x00: set_hl((get_hl() + 1) & 0xffff); break;
836 		case 0xdd: set_ix((get_ix() + 1) & 0xffff); break;
837 		case 0xfd: set_iy((get_iy() + 1) & 0xffff); break;
838 		}
839 		break;
840 	case 0x30: reg_sp = ((reg_sp + 1) & 0xffff); break;
841 	}
842 }
843 
844 
845 /*
846  * 8-bit decrement
847  */
848 static void
inst_dcr(void)849 inst_dcr(void) {
850 	unsigned char *dp;
851 	/*
852 	 * doesn't affect carry flag
853 	 */
854 	int old_c = flag_c;
855 	dp = operand8((opcode >> 3) & 0x07, 0);
856 	*dp = sub8(*dp, 1, 0);
857 	flag_c = old_c;
858 }
859 
860 
861 /*
862  * 16-bit decrement
863  */
864 static void
inst_dcx(void)865 inst_dcx(void) {
866 	switch (opcode & 0x30) {
867 	case 0x00: set_bc((get_bc() + 0xffff) & 0xffff); break;
868 	case 0x10: set_de((get_de() + 0xffff) & 0xffff); break;
869 	case 0x20:
870 		switch (prefix) {
871 		case 0x00: set_hl((get_hl() + 0xffff) & 0xffff); break;
872 		case 0xdd: set_ix((get_ix() + 0xffff) & 0xffff); break;
873 		case 0xfd: set_iy((get_iy() + 0xffff) & 0xffff); break;
874 		}
875 		break;
876 	case 0x30: reg_sp = ((reg_sp + 0xffff) & 0xffff); break;
877 	}
878 }
879 
880 
881 /*
882  * 16-bit addition without carry
883  */
884 static void
inst_dad(void)885 inst_dad(void) {
886 	/*
887 	 * flags S, Z, and P are not modified
888 	 */
889 	int old_s = flag_s, old_z = flag_z, old_p = flag_p;
890 	unsigned s = 0;
891 	switch (opcode & 0x30) {
892 	case 0x00: s = get_bc(); break;
893 	case 0x10: s = get_de(); break;
894 	case 0x20:
895 		switch (prefix) {
896 		case 0x00: s = get_hl(); break;
897 		case 0xdd: s = get_ix(); break;
898 		case 0xfd: s = get_iy(); break;
899 		}
900 		break;
901 	case 0x30: s = reg_sp; break;
902 	}
903 	switch (prefix) {
904 	case 0x00:
905 		internal = get_hl();
906 		set_hl(add16(internal, s, 0));
907 		break;
908 	case 0xdd:
909 		internal = get_ix();
910 		set_ix(add16(internal, s, 0));
911 		break;
912 	case 0xfd:
913 		internal = get_iy();
914 		set_iy(add16(internal, s, 0));
915 		break;
916 	}
917 	flag_s = old_s;
918 	flag_z = old_z;
919 	flag_p = old_p;
920 }
921 
922 
923 /*
924  * calculate parity of a byte (even number of bits: 1, odd number of bits: 0)
925  */
926 static int
parity(unsigned char byte)927 parity(unsigned char byte) {
928 	int p = 1;
929 	while (byte) {
930 		p ^= (byte & 0x01);
931 		byte >>= 1;
932 	}
933 	return p;
934 }
935 
936 
937 /*
938  * adjust A for BCD arithmetic after addition or subtraction
939  */
940 static void
inst_daa(void)941 inst_daa(void) {
942 	int high = (reg_a >> 4) & 0x0f, low = reg_a & 0x0f, new_c, new_h;
943 	unsigned char diff;
944 	/*
945 	 * calculate adjustment byte for A
946 	 */
947 	if (flag_c) {
948 		if (low < 0xa) {
949 			diff = flag_h ?  0x66 : 0x60;
950 		} else {
951 			diff = 0x66;
952 		}
953 	} else {
954 		if (low < 0xa) {
955 			if (high < 0xa) {
956 				diff = flag_h ? 0x06 : 0x00;
957 			} else {
958 				diff = flag_h ? 0x66 : 0x60;
959 			}
960 		} else {
961 			diff = (high < 0x9) ? 0x06 : 0x66;
962 		}
963 	}
964 	/*
965 	 * calculate new C flag
966 	 */
967 	if (flag_c) {
968 		new_c = 1;
969 	} else {
970 		if (low < 0xa) {
971 			new_c = (high < 0xa) ? 0 : 1;
972 		} else {
973 			new_c = (high < 0x9) ? 0 : 1;
974 		}
975 	}
976 	/*
977 	 * calculate new H flag
978 	 */
979 	if (flag_n) {
980 		if (flag_h) {
981 			new_h = (low < 0x6) ? 1 : 0;
982 		} else {
983 			new_h = 0;
984 		}
985 	} else {
986 		new_h = (low < 0xa) ? 0 : 1;
987 	}
988 	/*
989 	 * adjust A, set flags S, Z, Y, X, and N
990 	 */
991 	reg_a = flag_n ? sub8(reg_a, diff, 0) : add8(reg_a, diff, 0);
992 	/*
993 	 * set P/V flag from parity of A
994 	 */
995 	flag_p = parity(reg_a);
996 	/*
997 	 * set flags C and H calculated above
998 	 */
999 	flag_c = new_c;
1000 	flag_h = new_h;
1001 }
1002 
1003 
1004 /*
1005  * 8-bit add to A
1006  */
1007 static void
inst_add(void)1008 inst_add(void) { reg_a = add8(reg_a, *operand8(opcode & 0x07, 0), 0); }
1009 
1010 
1011 /*
1012  * 8-bit add to A immediate
1013  */
1014 static void
inst_adi(void)1015 inst_adi(void) { reg_a = add8(reg_a, op_low, 0); }
1016 
1017 
1018 /*
1019  * 8-bit add with carry to A
1020  */
1021 static void
inst_adc(void)1022 inst_adc(void) { reg_a = add8(reg_a, *operand8(opcode & 0x07, 0), flag_c); }
1023 
1024 
1025 /*
1026  * 8-bit add with carry to A immediate
1027  */
1028 static void
inst_aci(void)1029 inst_aci(void) { reg_a = add8(reg_a, op_low, flag_c); }
1030 
1031 
1032 /*
1033  * 8-bit subtract from A
1034  */
1035 static void
inst_sub(void)1036 inst_sub(void) { reg_a = sub8(reg_a, *operand8(opcode & 0x07, 0), 0); }
1037 
1038 
1039 /*
1040  * 8-bit subtract from A immediate
1041  */
1042 static void
inst_sui(void)1043 inst_sui(void) { reg_a = sub8(reg_a, op_low, 0); }
1044 
1045 
1046 /*
1047  * 8-bit subtract with borrow from A
1048  */
1049 static void
inst_sbca(void)1050 inst_sbca(void) { reg_a = sub8(reg_a, *operand8(opcode & 0x07, 0), flag_c); }
1051 
1052 
1053 /*
1054  * 8-bit subtract with borrow from A immediate
1055  */
1056 static void
inst_sbi(void)1057 inst_sbi(void) { reg_a = sub8(reg_a, op_low, flag_c); }
1058 
1059 
1060 /*
1061  * 8-bit compare to A
1062  */
1063 static void
inst_cmp(void)1064 inst_cmp(void) {
1065 	unsigned char op = *operand8(opcode & 0x07, 0);
1066 	sub8(reg_a, op, 0);
1067 	flag_x = ((op & 0x08) == 0x08);
1068 	flag_y = ((op & 0x20) == 0x20);
1069 }
1070 
1071 
1072 /*
1073  * 8-bit compare to A immediate
1074  */
1075 static void
inst_cmpi(void)1076 inst_cmpi(void) {
1077 	sub8(reg_a, op_low, 0);
1078 	flag_x = ((op_low & 0x08) == 0x08);
1079 	flag_y = ((op_low & 0x20) == 0x20);
1080 }
1081 
1082 
1083 /*
1084  * set flags after inst_and/ani/or/ori/xor/xri()
1085  */
1086 static void
log_flags(void)1087 log_flags(void) {
1088 	flag_s = ((reg_a & 0x80) == 0x80);
1089 	flag_z = reg_a ? 0 : 1;
1090 	flag_y = ((reg_a & 0x20) == 0x20);
1091 	flag_x = ((reg_a & 0x08) == 0x08);
1092 	flag_p = parity(reg_a);
1093 	flag_n = 0;
1094 	flag_c = 0;
1095 }
1096 
1097 
1098 /*
1099  * logical and with A
1100  */
1101 static void
inst_and(void)1102 inst_and(void) {
1103 	reg_a &= *operand8(opcode & 0x07, 0);
1104 	flag_h = 1;
1105 	log_flags();
1106 }
1107 
1108 
1109 /*
1110  * logical and with A immediate
1111  */
1112 static void
inst_ani(void)1113 inst_ani(void) {
1114 	reg_a &= op_low;
1115 	flag_h = 1;
1116 	log_flags();
1117 }
1118 
1119 
1120 /*
1121  * logical or with A
1122  */
1123 static void
inst_or(void)1124 inst_or(void) {
1125 	reg_a |= *operand8(opcode & 0x07, 0);
1126 	flag_h = 0;
1127 	log_flags();
1128 }
1129 
1130 
1131 /*
1132  * logical or with A immediate
1133  */
1134 static void
inst_ori(void)1135 inst_ori(void) {
1136 	reg_a |= op_low;
1137 	flag_h = 0;
1138 	log_flags();
1139 }
1140 
1141 
1142 /*
1143  * logical xor with A
1144  */
1145 static void
inst_xor(void)1146 inst_xor(void) {
1147 	reg_a ^= *operand8(opcode & 0x07, 0);
1148 	flag_h = 0;
1149 	log_flags();
1150 }
1151 
1152 
1153 /*
1154  * logical xor with A immediate
1155  */
1156 static void
inst_xri(void)1157 inst_xri(void) {
1158 	reg_a ^= op_low;
1159 	flag_h = 0;
1160 	log_flags();
1161 }
1162 
1163 
1164 /*
1165  * unconditional jump
1166  */
1167 static void
inst_jp(void)1168 inst_jp(void) {
1169 	reg_pc = op_high;
1170 	reg_pc <<= 8;
1171 	reg_pc |= op_low;
1172 }
1173 
1174 
1175 /*
1176  * common part of ret, ret cc, and retn
1177  */
1178 static void
do_ret(void)1179 do_ret(void) {
1180 	reg_pc = pop();
1181 }
1182 
1183 
1184 /*
1185  * unconditional return
1186  */
1187 static void
inst_ret(void)1188 inst_ret(void) {
1189 	/*
1190 	 * handle magic addresses for BDOS and BIOS calls
1191 	 */
1192 	if (current_instruction >= MAGIC_ADDRESS) {
1193 		os_call(current_instruction - MAGIC_ADDRESS);
1194 	}
1195 	do_ret();
1196 }
1197 
1198 
1199 /*
1200  * unconditional call
1201  */
1202 static void
inst_call(void)1203 inst_call(void) {
1204 	push(reg_pc);
1205 	inst_jp();
1206 }
1207 
1208 
1209 /*
1210  * restart
1211  */
1212 static void
inst_rst(void)1213 inst_rst(void) {
1214 	push(reg_pc);
1215 	reg_pc = (opcode & 0x38);
1216 }
1217 
1218 
1219 /*
1220  * return true if condition from jp cc, call cc, or ret cc is met
1221  */
1222 static int
condition_met(void)1223 condition_met(void) {
1224 	switch (opcode & 0x38) {
1225 	case 0x00: return (! flag_z);
1226 	case 0x08: return flag_z;
1227 	case 0x10: return (! flag_c);
1228 	case 0x18: return flag_c;
1229 	case 0x20: return (! flag_p);
1230 	case 0x28: return flag_p;
1231 	case 0x30: return (! flag_s);
1232 	default /* case 0x38 */: return flag_s;
1233 	}
1234 }
1235 
1236 
1237 /*
1238  * conditional jump
1239  */
1240 static void
inst_jpcc(void)1241 inst_jpcc(void) { if (condition_met()) inst_jp(); }
1242 
1243 
1244 /*
1245  * conditional return
1246  */
1247 static void
inst_retcc(void)1248 inst_retcc(void) { if (condition_met()) do_ret(); }
1249 
1250 
1251 /*
1252  * conditional call
1253  */
1254 static void
inst_callcc(void)1255 inst_callcc(void) { if (condition_met()) inst_call(); }
1256 
1257 
1258 /*
1259  * push word register to stack
1260  */
1261 static void
inst_push(void)1262 inst_push(void) {
1263 	int word;
1264 	switch (opcode & 0x30) {
1265 		/*
1266 		 * BC
1267 		 */
1268 	case 0x00: word = get_bc(); break;
1269 		/*
1270 		 * DE
1271 		 */
1272 	case 0x10: word = get_de(); break;
1273 	case 0x20:
1274 		switch (prefix) {
1275 		/*
1276 		 * IX
1277 		 */
1278 		case 0xdd: word = get_ix(); break;
1279 		/*
1280 		 * IY
1281 		 */
1282 		case 0xfd: word = get_iy(); break;
1283 		/*
1284 		 * HL
1285 		 */
1286 		default: word = get_hl(); break;
1287 		}
1288 		break;
1289 	default:
1290 		/*
1291 		 * AF
1292 		 */
1293 		word = reg_a;
1294 		word <<= 8;
1295 		if (flag_s) word |= 0x80;
1296 		if (flag_z) word |= 0x40;
1297 		if (flag_y) word |= 0x20;
1298 		if (flag_h) word |= 0x10;
1299 		if (flag_x) word |= 0x08;
1300 		if (flag_p) word |= 0x04;
1301 		if (flag_n) word |= 0x02;
1302 		if (flag_c) word |= 0x01;
1303 		break;
1304 	}
1305 	push(word);
1306 }
1307 
1308 
1309 /*
1310  * pop word register from stack
1311  */
1312 static void
inst_pop(void)1313 inst_pop(void) {
1314 	int word = pop();
1315 	switch (opcode & 0x30) {
1316 		/*
1317 		 * BC
1318 		 */
1319 	case 0x00: set_bc(word); break;
1320 		/*
1321 		 * DE
1322 		 */
1323 	case 0x10: set_de(word); break;
1324 	case 0x20:
1325 		switch (prefix) {
1326 		/*
1327 		 * IX
1328 		 */
1329 		case 0xdd: set_ix(word); break;
1330 		/*
1331 		 * IY
1332 		 */
1333 		case 0xfd: set_iy(word); break;
1334 		/*
1335 		 * HL
1336 		 */
1337 		default: set_hl(word); break;
1338 		}
1339 		break;
1340 	default:
1341 		/*
1342 		 * AF
1343 		 */
1344 		reg_a = ((word >> 8) & 0xff);
1345 		flag_s = ((word & 0x80) == 0x80);
1346 		flag_z = ((word & 0x40) == 0x40);
1347 		flag_y = ((word & 0x20) == 0x20);
1348 		flag_h = ((word & 0x10) == 0x10);
1349 		flag_x = ((word & 0x08) == 0x08);
1350 		flag_p = ((word & 0x04) == 0x04);
1351 		flag_n = ((word & 0x02) == 0x02);
1352 		flag_c = ((word & 0x01) == 0x01);
1353 		break;
1354 	}
1355 
1356 }
1357 
1358 
1359 /*
1360  * exchange word registers
1361  */
1362 static void
inst_exx(void)1363 inst_exx(void) {
1364 	unsigned char uc;
1365 	uc = reg_b; reg_b = alt_reg_b; alt_reg_b = uc;
1366 	uc = reg_c; reg_c = alt_reg_c; alt_reg_c = uc;
1367 	uc = reg_d; reg_d = alt_reg_d; alt_reg_d = uc;
1368 	uc = reg_e; reg_e = alt_reg_e; alt_reg_e = uc;
1369 	uc = reg_h; reg_h = alt_reg_h; alt_reg_h = uc;
1370 	uc = reg_l; reg_l = alt_reg_l; alt_reg_l = uc;
1371 }
1372 
1373 
1374 /*
1375  * exchange DE and HL
1376  */
1377 static void
inst_xchg(void)1378 inst_xchg(void) {
1379 	unsigned char uc;
1380 	uc = reg_h; reg_h = reg_d; reg_d = uc;
1381 	uc = reg_l; reg_l = reg_e; reg_e = uc;
1382 }
1383 
1384 
1385 /*
1386  * exchange HL, IX, or IY with top of stack
1387  */
1388 static void
inst_xthl(void)1389 inst_xthl(void) {
1390 	unsigned char *rlp, *rhp, *slp, *shp, uc;
1391 	switch (prefix) {
1392 	case 0xdd: rhp = &reg_ixh; rlp = &reg_ixl; break;
1393 	case 0xfd: rhp = &reg_iyh; rlp = &reg_iyl; break;
1394 	default: rhp = &reg_h; rlp = &reg_l; break;
1395 	}
1396 	slp = memory + reg_sp;
1397 	shp = memory + ((reg_sp + 1) & 0xffff);
1398 	uc = *slp; *slp = *rlp; *rlp = uc;
1399 	uc = *shp; *shp = *rhp; *rhp = uc;
1400 }
1401 
1402 
1403 /*
1404  * jump to address in HL, IX, or IY
1405  */
1406 static void
inst_pchl(void)1407 inst_pchl(void) {
1408 	switch (prefix) {
1409 	case 0xdd: reg_pc = get_ix(); break;
1410 	case 0xfd: reg_pc = get_iy(); break;
1411 	default: reg_pc = get_hl(); break;
1412 	}
1413 }
1414 
1415 
1416 /*
1417  * set SP to address in HL, IX, or IY
1418  */
1419 static void
inst_sphl(void)1420 inst_sphl(void) {
1421 	switch (prefix) {
1422 	case 0xdd: reg_sp = get_ix(); break;
1423 	case 0xfd: reg_sp = get_iy(); break;
1424 	default: reg_sp = get_hl(); break;
1425 	}
1426 }
1427 
1428 
1429 /*
1430  * get byte from port to A
1431  */
1432 static void
inst_ina(void)1433 inst_ina(void) {
1434 	reg_a = 0x00;
1435 }
1436 
1437 
1438 /*
1439  * put byte in A to port
1440  */
1441 static void
inst_outa(void)1442 inst_outa(void) { }
1443 
1444 
1445 /*
1446  * enable interrupts
1447  */
1448 static void
inst_ei(void)1449 inst_ei(void) {
1450 	flag_i = 1;
1451 }
1452 
1453 
1454 /*
1455  * disable interrupts
1456  */
1457 static void
inst_di(void)1458 inst_di(void) {
1459 	flag_i = 0;
1460 }
1461 
1462 
1463 /*
1464  * same as operand8(), but for I/O instructions: no modification by
1465  * prefixes, and code 6 doesn't reference (HL)
1466  */
1467 static unsigned char *
io_operand(int n)1468 io_operand(int n) {
1469 	switch (n) {
1470 	case 0: return &reg_b;
1471 	case 1: return &reg_c;
1472 	case 2: return &reg_d;
1473 	case 3: return &reg_e;
1474 	case 4: return &reg_h;
1475 	case 5: return &reg_l;
1476 	case 6: return NULL;
1477 	default: return &reg_a;
1478 	}
1479 }
1480 
1481 
1482 /*
1483  * IN r,(C) (dummy, always reads 0)
1484  */
1485 static void
inst_inc(void)1486 inst_inc(void) {
1487 	unsigned char *dp = io_operand((opcode2 >> 3) & 0x07);
1488 	if (dp) *dp = 0;
1489 	flag_s = 0; /* result 0 */
1490 	flag_z = 1; /* result 0 */
1491 	flag_y = 0; /* result 0 */
1492 	flag_h = 0;
1493 	flag_x = 0; /* result 0 */
1494 	flag_p = 0; /* result 0 */
1495 	flag_n = 0;
1496 }
1497 
1498 
1499 /*
1500  * OUT (C), r (dummy, doesn't do anything)
1501  */
1502 static void
inst_outc(void)1503 inst_outc(void) { }
1504 
1505 
1506 /*
1507  * decrease PC by two (used for LDIR/LDDR/CPIR/CPDR/INIR/INDR/OTIR/OTDR)
1508  */
1509 static void
repeat_block(void)1510 repeat_block(void) {
1511 	reg_pc = ((reg_pc + 0xfffe) & 0xffff);
1512 }
1513 
1514 
1515 /*
1516  * OUTI (dummy apart from its side effects, which are strange)
1517  */
1518 static void
inst_outi(void)1519 inst_outi(void) {
1520 	int hl = get_hl(), k = memory[hl], new_n, new_c, new_h, new_p;
1521 	set_hl((hl + 1) & 0xffff);
1522 	new_n = ((k & 0x80) == 0x80);
1523 	k += reg_l;
1524 	new_c = new_h = (k > 255);
1525 	new_p = parity((k & 7) ^ reg_b);
1526 	reg_b = sub8(reg_b, 1, 0);
1527 	flag_c = new_c;
1528 	flag_n = new_n;
1529 	flag_p = new_p;
1530 	flag_h = new_h;
1531 }
1532 
1533 
1534 /*
1535  * OTIR (like OUTI, but decrease PC by two if B != 0
1536  */
1537 static void
inst_otir(void)1538 inst_otir(void) {
1539 	inst_outi();
1540 	if (reg_b) repeat_block();
1541 }
1542 
1543 
1544 /*
1545  * OUTD (dummy apart from its side effects, which are strange)
1546  */
1547 static void
inst_outd(void)1548 inst_outd(void) {
1549 	int hl = get_hl(), k = memory[hl], new_n, new_c, new_h, new_p;
1550 	set_hl((hl + 0xffff) & 0xffff);
1551 	new_n = ((k & 0x80) == 0x80);
1552 	k += reg_l;
1553 	new_c = new_h = (k > 255);
1554 	new_p = parity((k & 7) ^ reg_b);
1555 	reg_b = sub8(reg_b, 1, 0);
1556 	flag_c = new_c;
1557 	flag_n = new_n;
1558 	flag_p = new_p;
1559 	flag_h = new_h;
1560 }
1561 
1562 
1563 /*
1564  * OTDR (like OUTD, but decrease PC by two if B != 0
1565  */
1566 static void
inst_otdr(void)1567 inst_otdr(void) {
1568 	inst_outd();
1569 	if (reg_b) repeat_block();
1570 }
1571 
1572 
1573 /*
1574  * INI (dummy apart from its side effects, which are strange)
1575  */
1576 static void
inst_ini(void)1577 inst_ini(void) {
1578 	int hl = get_hl(), k = 0, new_n, new_c, new_h, new_p;
1579 	memory[hl] = k;
1580 	set_hl((hl + 1) & 0xffff);
1581 	new_n = ((k & 0x80) == 0x80);
1582 	k += (reg_c + 1) & 0xff;
1583 	new_c = new_h = (k > 255);
1584 	new_p = parity((k & 7) ^ reg_b);
1585 	reg_b = sub8(reg_b, 1, 0);
1586 	flag_c = new_c;
1587 	flag_n = new_n;
1588 	flag_p = new_p;
1589 	flag_h = new_h;
1590 }
1591 
1592 
1593 /*
1594  * INIR (like INI, but decrease PC by two if B != 0
1595  */
1596 static void
inst_inir(void)1597 inst_inir(void) {
1598 	inst_ini();
1599 	if (reg_b) repeat_block();
1600 }
1601 
1602 
1603 /*
1604  * IND (dummy apart from its side effects, which are strange)
1605  */
1606 static void
inst_ind(void)1607 inst_ind(void) {
1608 	int hl = get_hl(), k = 0, new_n, new_c, new_h, new_p;
1609 	memory[hl] = k;
1610 	set_hl((hl + 0xffff) & 0xffff);
1611 	new_n = ((k & 0x80) == 0x80);
1612 	k += reg_c ? 0xff : reg_c - 1;
1613 	new_c = new_h = (k > 255);
1614 	new_p = parity((k & 7) ^ reg_b);
1615 	reg_b = sub8(reg_b, 1, 0);
1616 	flag_c = new_c;
1617 	flag_n = new_n;
1618 	flag_p = new_p;
1619 	flag_h = new_h;
1620 }
1621 
1622 
1623 /*
1624  * INDR (like IND, but decrease PC by two if B != 0
1625  */
1626 static void
inst_indr(void)1627 inst_indr(void) {
1628 	inst_ind();
1629 	if (reg_b) repeat_block();
1630 }
1631 
1632 
1633 /*
1634  * NEG
1635  */
1636 static void
inst_neg(void)1637 inst_neg(void) {
1638 	reg_a = sub8(0, reg_a, 0);
1639 }
1640 
1641 
1642 /*
1643  * RETN and RETI do the same (which is in this implementation the same
1644  * as a simple RET, since there is no NMI and no IFF2
1645  */
1646 static void
inst_retn(void)1647 inst_retn(void) {
1648 	do_ret();
1649 }
1650 
1651 
1652 /*
1653  * IM 0/1/2 are dummies, since there are no interrupts in this
1654  * implementation
1655  */
1656 static void
inst_im0(void)1657 inst_im0(void) { }
1658 
1659 
1660 static void
inst_im1(void)1661 inst_im1(void) { }
1662 
1663 
1664 static void
inst_im2(void)1665 inst_im2(void) { }
1666 
1667 
1668 /*
1669  * set flags for LD A,I and LD A,R
1670  */
1671 static void
ldair_flags(void)1672 ldair_flags(void) {
1673 	flag_s = ((reg_a & 0x80) == 0x80);
1674 	flag_z = (reg_a == 0);
1675 	flag_y = ((reg_a & 0x20) == 0x20);
1676 	flag_h = 0;
1677 	flag_x = ((reg_a & 0x08) == 0x08);
1678 	flag_p = flag_i;
1679 	flag_n = 0;
1680 }
1681 
1682 
1683 /*
1684  * LD A,I
1685  */
1686 static void
inst_ldai(void)1687 inst_ldai(void) {
1688 	reg_a = reg_i;
1689 	ldair_flags();
1690 }
1691 
1692 
1693 /*
1694  * LD I,A
1695  */
1696 static void
inst_ldia(void)1697 inst_ldia(void) {
1698 	reg_i = reg_a;
1699 }
1700 
1701 
1702 /*
1703  * LD A,R
1704  */
1705 static void
inst_ldar(void)1706 inst_ldar(void) {
1707 	reg_a = reg_r;
1708 	ldair_flags();
1709 }
1710 
1711 
1712 /*
1713  * LD R,A
1714  */
1715 static void
inst_ldra(void)1716 inst_ldra(void) {
1717 	reg_r = reg_a;
1718 }
1719 
1720 
1721 /*
1722  * ADC HL,rr
1723  */
1724 static void
inst_adchl(void)1725 inst_adchl(void) {
1726 	unsigned value;
1727 	internal = get_hl();
1728 	switch (opcode2 & 0x30) {
1729 	case 0x00: value = get_bc(); break;
1730 	case 0x10: value = get_de(); break;
1731 	case 0x20: value = internal; break;
1732 	default: value = reg_sp; break;
1733 	}
1734 	set_hl(add16(internal, value, flag_c));
1735 }
1736 
1737 
1738 /*
1739  * SBC HL,rr
1740  */
1741 static void
inst_sbchl(void)1742 inst_sbchl(void) {
1743 	unsigned value;
1744 	internal = get_hl();
1745 	switch (opcode2 & 0x30) {
1746 	case 0x00: value = get_bc(); break;
1747 	case 0x10: value = get_de(); break;
1748 	case 0x20: value = internal; break;
1749 	default: value = reg_sp; break;
1750 	}
1751 	set_hl(sub16(internal, value, flag_c));
1752 }
1753 
1754 
1755 /*
1756  * common part of LDI and LDD
1757  */
1758 static void
ldx(int up)1759 ldx(int up) {
1760 	int hl, de, bc, t;
1761 	bc = get_bc();
1762 	de = get_de();
1763 	hl = get_hl();
1764 	t = memory[de] = memory[hl];
1765 	t += reg_a;
1766 	if (up) {
1767 		hl = ((hl + 1) & 0xffff);
1768 		de = ((de + 1) & 0xffff);
1769 	} else {
1770 		hl = ((hl + 0xffff) & 0xffff);
1771 		de = ((de + 0xffff) & 0xffff);
1772 	}
1773 	bc = ((bc + 0xffff) & 0xffff);
1774 	set_bc(bc);
1775 	set_de(de);
1776 	set_hl(hl);
1777 	flag_y = (t & 0x02) == 0x02;
1778 	flag_h = 0;
1779 	flag_x = (t & 0x08) == 0x08;
1780 	flag_p = (bc != 0);
1781 	flag_n = 0;
1782 }
1783 
1784 
1785 /*
1786  * LDI
1787  */
1788 static void
inst_ldi(void)1789 inst_ldi(void) { ldx(1); }
1790 
1791 
1792 /*
1793  * LDIR (repeats LDI until P is clear, i. e. BC == 0)
1794  */
1795 static void
inst_ldir(void)1796 inst_ldir(void) {
1797 	inst_ldi();
1798 	if (flag_p) repeat_block();
1799 }
1800 
1801 
1802 /*
1803  * LDD
1804  */
1805 static void
inst_ldd(void)1806 inst_ldd(void) { ldx(0); }
1807 
1808 
1809 /*
1810  * LDDR (repeats LDD until P is clear, i. e. BC == 0)
1811  */
1812 static void
inst_lddr(void)1813 inst_lddr(void) {
1814 	inst_ldd();
1815 	if (flag_p) repeat_block();
1816 }
1817 
1818 
1819 /*
1820  * common part of CPI and CPD
1821  */
1822 static void
cpx(int up)1823 cpx(int up) {
1824 	int hl, bc, t, old_c;
1825 	old_c = flag_c;
1826 	bc = get_bc();
1827 	hl = get_hl();
1828 	t = sub8(reg_a, memory[hl], 0);
1829 	t += flag_h;
1830 	hl = up ? ((hl + 1) & 0xffff) : ((hl + 0xffff) & 0xffff);
1831 	bc = ((bc + 0xffff) & 0xffff);
1832 	set_bc(bc);
1833 	set_hl(hl);
1834 	flag_y = ((t & 0x02) == 0x02);
1835 	flag_x = ((t & 0x08) == 0x08);
1836 	flag_p = (bc != 0);
1837 	flag_c = old_c;
1838 }
1839 
1840 
1841 /*
1842  * CPI
1843  */
1844 static void
inst_cpi(void)1845 inst_cpi(void) { cpx(1); }
1846 
1847 
1848 /*
1849  * CPIR (repeats CPI until P is clear, i. e. BC == 0)
1850  */
1851 static void
inst_cpir(void)1852 inst_cpir(void) {
1853 	inst_cpi();
1854 	if (flag_p && ! flag_z) repeat_block();
1855 }
1856 
1857 
1858 /*
1859  * CPD
1860  */
1861 static void
inst_cpd(void)1862 inst_cpd(void) { cpx(0); }
1863 
1864 
1865 /*
1866  * CPDR (repeats CPD until P is clear, i. e. BC == 0)
1867  */
1868 static void
inst_cpdr(void)1869 inst_cpdr(void) {
1870 	inst_cpd();
1871 	if (flag_p && ! flag_z) repeat_block();
1872 }
1873 
1874 
1875 /*
1876  * LD rr,(nn)
1877  */
1878 static void
inst_lrrd(void)1879 inst_lrrd(void) {
1880 	int t;
1881 	t = op_high;
1882 	t <<= 8;
1883 	t |= op_low;
1884 	t = get_word(t);
1885 	switch (opcode2 & 0x30) {
1886 	case 0x00: set_bc(t); break;
1887 	case 0x10: set_de(t); break;
1888 	case 0x20: set_hl(t); break;
1889 	default: reg_sp = t; break;
1890 	}
1891 }
1892 
1893 
1894 /*
1895  * LD (nn),rr
1896  */
1897 static void
inst_srrd(void)1898 inst_srrd(void) {
1899 	int t;
1900 	t = op_high;
1901 	t <<= 8;
1902 	t |= op_low;
1903 	switch (opcode2 & 0x30) {
1904 	case 0x00: set_word(t, get_bc()); break;
1905 	case 0x10: set_word(t, get_de()); break;
1906 	case 0x20: set_word(t, get_hl()); break;
1907 	default: set_word(t, reg_sp); break;
1908 	}
1909 }
1910 
1911 
1912 /*
1913  * helper function to set the flags after Z80 (as opposed to
1914  * 8080) specific shift and rotate operations
1915  */
1916 static void
shift_flags(unsigned char data)1917 shift_flags(unsigned char data) {
1918 	flag_s = ((data & 0x80) == 0x80);
1919 	flag_z = (data == 0x00);
1920 	flag_y = ((data & 0x20) == 0x20);
1921 	flag_h = 0;
1922 	flag_x = ((data & 0x08) == 0x08);
1923 	flag_p = parity(data);
1924 	flag_n = 0;
1925 }
1926 
1927 
1928 /*
1929  * RLD
1930  */
1931 static void
inst_rld(void)1932 inst_rld(void) {
1933 	int t, hl = get_hl();
1934 	t = memory[hl];
1935 	memory[hl] = ((t << 4) & 0xf0) | (reg_a & 0x0f);
1936 	reg_a = (reg_a & 0xf0) | ((t >> 4) & 0xf);
1937 	shift_flags(reg_a);
1938 }
1939 
1940 
1941 /*
1942  * RRD
1943  */
1944 static void
inst_rrd(void)1945 inst_rrd(void) {
1946 	int t, hl = get_hl();
1947 	t = memory[hl];
1948 	memory[hl] = ((t >> 4) & 0x0f) | ((reg_a << 4) & 0x0f);
1949 	reg_a = (reg_a & 0xf0) | (t & 0xf);
1950 	shift_flags(reg_a);
1951 }
1952 
1953 
1954 /*
1955  * RLC/RRC/RL/RR/SLA/SRA/SLL/SRL/BIT/RES/SET
1956  *
1957  * two-byte opcodes starting in 0xcb; there are only 11 separate
1958  * instructions with a very similar structure, so this doesn't merit
1959  * a separate dispatch table.
1960  */
1961 static void
inst_cb(void)1962 inst_cb(void) {
1963 	int r = (opcode2 & 0x07), temp;
1964 	unsigned char *op1, *op2, byte;
1965 	if (prefix) {
1966 		/*
1967 		 * if there is a prefix, the source and one destination
1968 		 * operand is always an indexed memory location
1969 		 */
1970 		op1 = operand8(6, 0);
1971 		/*
1972 		 * only a register can be the other destination operand
1973 		 * and it is never i[xy][lh].
1974 		 */
1975 		op2 = (r == 6) ? NULL : operand8(r, 6);
1976 	} else {
1977 		/*
1978 		 * without a prefix there is only one operand (both
1979 		 * source and destination)
1980 		 */
1981 		op1 = operand8(r, 0);
1982 		op2 = NULL;
1983 	}
1984 	byte = *op1;
1985 	switch (opcode2 & 0xc0) {
1986 	case 0x00:
1987 		/*
1988 		 * shift and rotate instructions
1989 		 */
1990 		switch (opcode2 & 0x38) {
1991 		case 0x00:
1992 			/*
1993 			 * RLC: 8-bit rotate left
1994 			 */
1995 			flag_c = ((byte & 0x80) == 0x80);
1996 			byte = (((byte << 1) | flag_c) & 0xff);
1997 			break;
1998 		case 0x08:
1999 			/*
2000 			 * RRC: 8-bit rotate right
2001 			 */
2002 			flag_c = ((byte & 0x01) == 0x01);
2003 			byte = (((byte >> 1) | (flag_c ? 0x80 : 0x00)) & 0xff);
2004 			break;
2005 		case 0x10:
2006 			/*
2007 			 * RL: 9-bit rotate left
2008 			 */
2009 			temp = ((byte & 0x80) == 0x80);
2010 			byte = (((byte << 1) | flag_c) & 0xff);
2011 			flag_c = temp;
2012 			break;
2013 		case 0x18:
2014 			/*
2015 			 * RR: 9-bit rotate right
2016 			 */
2017 			temp = ((byte & 0x01) == 0x01);
2018 			byte = (((byte >> 1) | (flag_c ? 0x80 : 0x00)) & 0xff);
2019 			flag_c = temp;
2020 			break;
2021 		case 0x20:
2022 			/*
2023 			 * SLA: arithmetical (and logical) left shift
2024 			 */
2025 			flag_c = ((byte & 0x80) == 0x80);
2026 			byte = ((byte << 1) & 0xfe);
2027 			break;
2028 		case 0x28:
2029 			/*
2030 			 * SRA: arithmetical right shift
2031 			 */
2032 			temp = (byte & 0x80);
2033 			flag_c = ((byte & 0x01) == 0x01);
2034 			byte = (((byte >> 1) | temp)) & 0xff;
2035 			break;
2036 		case 0x30:
2037 			/*
2038 			 * SLL: like SLA, but shifts in 1
2039 			 */
2040 			flag_c = ((byte & 0x80) == 0x80);
2041 			byte = (((byte << 1) | 0x01) & 0xff);
2042 			break;
2043 		case 0x38:
2044 			/*
2045 			 * SRL: logical right shift
2046 			 */
2047 			flag_c = ((byte & 0x01) == 0x01);
2048 			byte = ((byte >> 1) & 0x7f);
2049 			break;
2050 		}
2051 		shift_flags(byte);
2052 		break;
2053 	case 0x40:
2054 		/*
2055 		 * BIT
2056 		 */
2057 		byte &= (1 << ((opcode2 >> 3) & 0x07));
2058 		flag_n = 0;
2059 		flag_p = flag_z = (byte == 0);
2060 		flag_h = 1;
2061 		flag_s = ((byte & 0x80) == 0x80);
2062 		/*
2063 		 * flags X and Y have complicated rules in this instructon
2064 		 */
2065 		if (r == 6) {
2066 			flag_x = ((internal & 0x0800) == 0x0800);
2067 			flag_y = ((internal & 0x2000) == 0x2000);
2068 		} else {
2069 			flag_x = ((byte & 0x08) == 0x08);
2070 			flag_y = ((byte & 0x20) == 0x20);
2071 		}
2072 		/*
2073 		 * no operand is modified by BIT
2074 		 */
2075 		goto no_save;
2076 	case 0x80:
2077 		/*
2078 		 * RES
2079 		 */
2080 		byte &= ~(1 << ((opcode2 >> 3) & 0x07));
2081 		break;
2082 	case 0xc0:
2083 		/*
2084 		 * SET
2085 		 */
2086 		byte |= 1 << ((opcode2 >> 3) & 0x07);
2087 		break;
2088 	}
2089 	*op1 = byte;
2090 	if (op2) *op2 = byte;
2091 no_save:
2092 	return;
2093 }
2094 
2095 
2096 /*
2097  * operand/displacement fetch
2098  */
2099 static inline int
fetch(void)2100 fetch(void) {
2101 	int byte;
2102 	byte = memory[reg_pc];
2103 	reg_pc = ((reg_pc + 1) & 0xffff);
2104 	return byte;
2105 }
2106 
2107 
2108 /*
2109  * opcode/prefix fetch: increase R
2110  */
2111 static inline int
fetch_m1(void)2112 fetch_m1(void) {
2113 	int t = reg_r;
2114 	int opcode = fetch();
2115 	/*
2116 	 * increase the lower 7 bits of R by 1, leave bit 7 unchanged
2117 	 */
2118 	reg_r = (t & 0x80) | ((t + 1) & 0x7f);
2119 	return opcode;
2120 }
2121 
2122 
2123 /*
2124  * flags and structures of the instruction dispatch tables
2125  */
2126 enum flags {
2127 	OP_0 = 0,
2128 	OP_INDEXED = 1, /* indexed addressing */
2129 	OP_ARG8 = 2, /* has an 8-bit displacement/operand */
2130 	OP_ARG16 = 4 /* has a 16-bit address/operand */
2131 };
2132 
2133 struct instruction {
2134 	void (*handler_p)(void);
2135 	enum flags flags;
2136 };
2137 
2138 
2139 /*
2140  * dispatcher table for instructions staring in 0xed
2141  */
2142 static const struct instruction ed_plane[256] = {
2143 /*00*/	{ inst_nop,	OP_0 },
2144 /*01*/	{ inst_nop,	OP_0 },
2145 /*02*/	{ inst_nop,	OP_0 },
2146 /*03*/	{ inst_nop,	OP_0 },
2147 /*04*/	{ inst_nop,	OP_0 },
2148 /*05*/	{ inst_nop,	OP_0 },
2149 /*06*/	{ inst_nop,	OP_0 },
2150 /*07*/	{ inst_nop,	OP_0 },
2151 /*08*/	{ inst_nop,	OP_0 },
2152 /*09*/	{ inst_nop,	OP_0 },
2153 /*0a*/	{ inst_nop,	OP_0 },
2154 /*0b*/	{ inst_nop,	OP_0 },
2155 /*0c*/	{ inst_nop,	OP_0 },
2156 /*0d*/	{ inst_nop,	OP_0 },
2157 /*0e*/	{ inst_nop,	OP_0 },
2158 /*0f*/	{ inst_nop,	OP_0 },
2159 /*10*/	{ inst_nop,	OP_0 },
2160 /*11*/	{ inst_nop,	OP_0 },
2161 /*12*/	{ inst_nop,	OP_0 },
2162 /*13*/	{ inst_nop,	OP_0 },
2163 /*14*/	{ inst_nop,	OP_0 },
2164 /*15*/	{ inst_nop,	OP_0 },
2165 /*16*/	{ inst_nop,	OP_0 },
2166 /*17*/	{ inst_nop,	OP_0 },
2167 /*18*/	{ inst_nop,	OP_0 },
2168 /*19*/	{ inst_nop,	OP_0 },
2169 /*1a*/	{ inst_nop,	OP_0 },
2170 /*1b*/	{ inst_nop,	OP_0 },
2171 /*1c*/	{ inst_nop,	OP_0 },
2172 /*1d*/	{ inst_nop,	OP_0 },
2173 /*1e*/	{ inst_nop,	OP_0 },
2174 /*1f*/	{ inst_nop,	OP_0 },
2175 /*20*/	{ inst_nop,	OP_0 },
2176 /*21*/	{ inst_nop,	OP_0 },
2177 /*22*/	{ inst_nop,	OP_0 },
2178 /*23*/	{ inst_nop,	OP_0 },
2179 /*24*/	{ inst_nop,	OP_0 },
2180 /*25*/	{ inst_nop,	OP_0 },
2181 /*26*/	{ inst_nop,	OP_0 },
2182 /*27*/	{ inst_nop,	OP_0 },
2183 /*28*/	{ inst_nop,	OP_0 },
2184 /*29*/	{ inst_nop,	OP_0 },
2185 /*2a*/	{ inst_nop,	OP_0 },
2186 /*2b*/	{ inst_nop,	OP_0 },
2187 /*2c*/	{ inst_nop,	OP_0 },
2188 /*2d*/	{ inst_nop,	OP_0 },
2189 /*2e*/	{ inst_nop,	OP_0 },
2190 /*2f*/	{ inst_nop,	OP_0 },
2191 /*30*/	{ inst_nop,	OP_0 },
2192 /*31*/	{ inst_nop,	OP_0 },
2193 /*32*/	{ inst_nop,	OP_0 },
2194 /*33*/	{ inst_nop,	OP_0 },
2195 /*34*/	{ inst_nop,	OP_0 },
2196 /*35*/	{ inst_nop,	OP_0 },
2197 /*36*/	{ inst_nop,	OP_0 },
2198 /*37*/	{ inst_nop,	OP_0 },
2199 /*38*/	{ inst_nop,	OP_0 },
2200 /*39*/	{ inst_nop,	OP_0 },
2201 /*3a*/	{ inst_nop,	OP_0 },
2202 /*3b*/	{ inst_nop,	OP_0 },
2203 /*3c*/	{ inst_nop,	OP_0 },
2204 /*3d*/	{ inst_nop,	OP_0 },
2205 /*3e*/	{ inst_nop,	OP_0 },
2206 /*3f*/	{ inst_nop,	OP_0 },
2207 /*40*/	{ inst_inc,	OP_0 },
2208 /*41*/	{ inst_outc,	OP_0 },
2209 /*42*/	{ inst_sbchl,	OP_0 },
2210 /*43*/	{ inst_srrd,	OP_ARG16 },
2211 /*44*/	{ inst_neg,	OP_0 },
2212 /*45*/	{ inst_retn,	OP_0 },
2213 /*46*/	{ inst_im0,	OP_0 },
2214 /*47*/	{ inst_ldia,	OP_0 },
2215 /*48*/	{ inst_inc,	OP_0 },
2216 /*49*/	{ inst_outc,	OP_0 },
2217 /*4a*/	{ inst_adchl,	OP_0 },
2218 /*4b*/	{ inst_lrrd,	OP_ARG16 },
2219 /*4c*/	{ inst_neg,	OP_0 },
2220 /*4d*/	{ inst_retn,	OP_0 },	/* reti */
2221 /*4e*/	{ inst_im0,	OP_0 },
2222 /*4f*/	{ inst_ldra,	OP_0 },
2223 /*50*/	{ inst_inc,	OP_0 },
2224 /*51*/	{ inst_outc,	OP_0 },
2225 /*52*/	{ inst_sbchl,	OP_0 },
2226 /*53*/	{ inst_srrd,	OP_ARG16 },
2227 /*54*/	{ inst_neg,	OP_0 },
2228 /*55*/	{ inst_retn,	OP_0 },
2229 /*56*/	{ inst_im1,	OP_0 },
2230 /*57*/	{ inst_ldai,	OP_0 },
2231 /*58*/	{ inst_inc,	OP_0 },
2232 /*59*/	{ inst_outc,	OP_0 },
2233 /*5a*/	{ inst_adchl,	OP_0 },
2234 /*5b*/	{ inst_lrrd,	OP_ARG16 },
2235 /*5c*/	{ inst_neg,	OP_0 },
2236 /*5d*/	{ inst_retn,	OP_0 },
2237 /*5e*/	{ inst_im2,	OP_0 },
2238 /*5f*/	{ inst_ldar,	OP_0 },
2239 /*60*/	{ inst_inc,	OP_0 },
2240 /*61*/	{ inst_outc,	OP_0 },
2241 /*62*/	{ inst_sbchl,	OP_0 },
2242 /*63*/	{ inst_srrd,	OP_ARG16 },
2243 /*64*/	{ inst_neg,	OP_0 },
2244 /*65*/	{ inst_retn,	OP_0 },
2245 /*66*/	{ inst_im0,	OP_0 },
2246 /*67*/	{ inst_rrd,	OP_0 },
2247 /*68*/	{ inst_inc,	OP_0 },
2248 /*69*/	{ inst_outc,	OP_0 },
2249 /*6a*/	{ inst_adchl,	OP_0 },
2250 /*6b*/	{ inst_lrrd,	OP_ARG16 },
2251 /*6c*/	{ inst_neg,	OP_0 },
2252 /*6d*/	{ inst_retn,	OP_0 },
2253 /*6e*/	{ inst_im0,	OP_0 },
2254 /*6f*/	{ inst_rld,	OP_0 },
2255 /*70*/	{ inst_inc,	OP_0 },
2256 /*71*/	{ inst_outc,	OP_0 },
2257 /*72*/	{ inst_sbchl,	OP_0 },
2258 /*73*/	{ inst_srrd,	OP_ARG16 },
2259 /*74*/	{ inst_neg,	OP_0 },
2260 /*75*/	{ inst_retn,	OP_0 },
2261 /*76*/	{ inst_im1,	OP_0 },
2262 /*77*/	{ inst_nop,	OP_0 },
2263 /*78*/	{ inst_inc,	OP_0 },
2264 /*79*/	{ inst_outc,	OP_0 },
2265 /*7a*/	{ inst_adchl,	OP_0 },
2266 /*7b*/	{ inst_lrrd,	OP_ARG16 },
2267 /*7c*/	{ inst_neg,	OP_0 },
2268 /*7d*/	{ inst_retn,	OP_0 },
2269 /*7e*/	{ inst_im2,	OP_0 },
2270 /*7f*/	{ inst_nop,	OP_0 },
2271 /*80*/	{ inst_nop,	OP_0 },
2272 /*81*/	{ inst_nop,	OP_0 },
2273 /*82*/	{ inst_nop,	OP_0 },
2274 /*83*/	{ inst_nop,	OP_0 },
2275 /*84*/	{ inst_nop,	OP_0 },
2276 /*85*/	{ inst_nop,	OP_0 },
2277 /*86*/	{ inst_nop,	OP_0 },
2278 /*87*/	{ inst_nop,	OP_0 },
2279 /*88*/	{ inst_nop,	OP_0 },
2280 /*89*/	{ inst_nop,	OP_0 },
2281 /*8a*/	{ inst_nop,	OP_0 },
2282 /*8b*/	{ inst_nop,	OP_0 },
2283 /*8c*/	{ inst_nop,	OP_0 },
2284 /*8d*/	{ inst_nop,	OP_0 },
2285 /*8e*/	{ inst_nop,	OP_0 },
2286 /*8f*/	{ inst_nop,	OP_0 },
2287 /*90*/	{ inst_nop,	OP_0 },
2288 /*91*/	{ inst_nop,	OP_0 },
2289 /*92*/	{ inst_nop,	OP_0 },
2290 /*93*/	{ inst_nop,	OP_0 },
2291 /*94*/	{ inst_nop,	OP_0 },
2292 /*95*/	{ inst_nop,	OP_0 },
2293 /*96*/	{ inst_nop,	OP_0 },
2294 /*97*/	{ inst_nop,	OP_0 },
2295 /*98*/	{ inst_nop,	OP_0 },
2296 /*99*/	{ inst_nop,	OP_0 },
2297 /*9a*/	{ inst_nop,	OP_0 },
2298 /*9b*/	{ inst_nop,	OP_0 },
2299 /*9c*/	{ inst_nop,	OP_0 },
2300 /*9d*/	{ inst_nop,	OP_0 },
2301 /*9e*/	{ inst_nop,	OP_0 },
2302 /*9f*/	{ inst_nop,	OP_0 },
2303 /*a0*/	{ inst_ldi,	OP_0 },
2304 /*a1*/	{ inst_cpi,	OP_0 },
2305 /*a2*/	{ inst_ini,	OP_0 },
2306 /*a3*/	{ inst_outi,	OP_0 },
2307 /*a4*/	{ inst_nop,	OP_0 },
2308 /*a5*/	{ inst_nop,	OP_0 },
2309 /*a6*/	{ inst_nop,	OP_0 },
2310 /*a7*/	{ inst_nop,	OP_0 },
2311 /*a8*/	{ inst_ldd,	OP_0 },
2312 /*a9*/	{ inst_cpd,	OP_0 },
2313 /*aa*/	{ inst_ind,	OP_0 },
2314 /*ab*/	{ inst_outd,	OP_0 },
2315 /*ac*/	{ inst_nop,	OP_0 },
2316 /*ad*/	{ inst_nop,	OP_0 },
2317 /*ae*/	{ inst_nop,	OP_0 },
2318 /*af*/	{ inst_nop,	OP_0 },
2319 /*b0*/	{ inst_ldir,	OP_0 },
2320 /*b1*/	{ inst_cpir,	OP_0 },
2321 /*b2*/	{ inst_inir,	OP_0 },
2322 /*b3*/	{ inst_otir,	OP_0 },
2323 /*b4*/	{ inst_nop,	OP_0 },
2324 /*b5*/	{ inst_nop,	OP_0 },
2325 /*b6*/	{ inst_nop,	OP_0 },
2326 /*b7*/	{ inst_nop,	OP_0 },
2327 /*b8*/	{ inst_lddr,	OP_0 },
2328 /*b9*/	{ inst_cpdr,	OP_0 },
2329 /*ba*/	{ inst_indr,	OP_0 },
2330 /*bb*/	{ inst_otdr,	OP_0 },
2331 /*bc*/	{ inst_nop,	OP_0 },
2332 /*bd*/	{ inst_nop,	OP_0 },
2333 /*be*/	{ inst_nop,	OP_0 },
2334 /*bf*/	{ inst_nop,	OP_0 },
2335 /*c0*/	{ inst_nop,	OP_0 },
2336 /*c1*/	{ inst_nop,	OP_0 },
2337 /*c2*/	{ inst_nop,	OP_0 },
2338 /*c3*/	{ inst_nop,	OP_0 },
2339 /*c4*/	{ inst_nop,	OP_0 },
2340 /*c5*/	{ inst_nop,	OP_0 },
2341 /*c6*/	{ inst_nop,	OP_0 },
2342 /*c7*/	{ inst_nop,	OP_0 },
2343 /*c8*/	{ inst_nop,	OP_0 },
2344 /*c9*/	{ inst_nop,	OP_0 },
2345 /*ca*/	{ inst_nop,	OP_0 },
2346 /*cb*/	{ inst_nop,	OP_0 },
2347 /*cc*/	{ inst_nop,	OP_0 },
2348 /*cd*/	{ inst_nop,	OP_0 },
2349 /*ce*/	{ inst_nop,	OP_0 },
2350 /*cf*/	{ inst_nop,	OP_0 },
2351 /*d0*/	{ inst_nop,	OP_0 },
2352 /*d1*/	{ inst_nop,	OP_0 },
2353 /*d2*/	{ inst_nop,	OP_0 },
2354 /*d3*/	{ inst_nop,	OP_0 },
2355 /*d4*/	{ inst_nop,	OP_0 },
2356 /*d5*/	{ inst_nop,	OP_0 },
2357 /*d6*/	{ inst_nop,	OP_0 },
2358 /*d7*/	{ inst_nop,	OP_0 },
2359 /*d8*/	{ inst_nop,	OP_0 },
2360 /*d9*/	{ inst_nop,	OP_0 },
2361 /*da*/	{ inst_nop,	OP_0 },
2362 /*db*/	{ inst_nop,	OP_0 },
2363 /*dc*/	{ inst_nop,	OP_0 },
2364 /*dd*/	{ inst_nop,	OP_0 },
2365 /*de*/	{ inst_nop,	OP_0 },
2366 /*df*/	{ inst_nop,	OP_0 },
2367 /*e0*/	{ inst_nop,	OP_0 },
2368 /*e1*/	{ inst_nop,	OP_0 },
2369 /*e2*/	{ inst_nop,	OP_0 },
2370 /*e3*/	{ inst_nop,	OP_0 },
2371 /*e4*/	{ inst_nop,	OP_0 },
2372 /*e5*/	{ inst_nop,	OP_0 },
2373 /*e6*/	{ inst_nop,	OP_0 },
2374 /*e7*/	{ inst_nop,	OP_0 },
2375 /*e8*/	{ inst_nop,	OP_0 },
2376 /*e9*/	{ inst_nop,	OP_0 },
2377 /*ea*/	{ inst_nop,	OP_0 },
2378 /*eb*/	{ inst_nop,	OP_0 },
2379 /*ec*/	{ inst_nop,	OP_0 },
2380 /*ed*/	{ inst_nop,	OP_0 },
2381 /*ee*/	{ inst_nop,	OP_0 },
2382 /*ef*/	{ inst_nop,	OP_0 },
2383 /*f0*/	{ inst_nop,	OP_0 },
2384 /*f1*/	{ inst_nop,	OP_0 },
2385 /*f2*/	{ inst_nop,	OP_0 },
2386 /*f3*/	{ inst_nop,	OP_0 },
2387 /*f4*/	{ inst_nop,	OP_0 },
2388 /*f5*/	{ inst_nop,	OP_0 },
2389 /*f6*/	{ inst_nop,	OP_0 },
2390 /*f7*/	{ inst_nop,	OP_0 },
2391 /*f8*/	{ inst_nop,	OP_0 },
2392 /*f9*/	{ inst_nop,	OP_0 },
2393 /*fa*/	{ inst_nop,	OP_0 },
2394 /*fb*/	{ inst_nop,	OP_0 },
2395 /*fc*/	{ inst_nop,	OP_0 },
2396 /*fd*/	{ inst_nop,	OP_0 },
2397 /*fe*/	{ inst_nop,	OP_0 },
2398 /*ff*/	{ inst_nop,	OP_0 }
2399 };
2400 
2401 
2402 /*
2403  * base plane function dispatcher table
2404  * (contains more or less the 8080-compatible instructions)
2405  */
2406 static const struct instruction base_plane[256] = {
2407 /*00*/	{ inst_nop,	OP_0 },
2408 /*01*/	{ inst_lxi,	OP_ARG16 },
2409 /*02*/	{ inst_stax,	OP_0 },
2410 /*03*/	{ inst_inx,	OP_0 },
2411 /*04*/	{ inst_inr,	OP_0 },
2412 /*05*/	{ inst_dcr,	OP_0 },
2413 /*06*/	{ inst_mvi,	OP_ARG8 },
2414 /*07*/	{ inst_rlca,	OP_0 },
2415 /*08*/	{ inst_exaf,	OP_0 },
2416 /*09*/	{ inst_dad,	OP_0 },
2417 /*0a*/	{ inst_ldax,	OP_0 },
2418 /*0b*/	{ inst_dcx,	OP_0 },
2419 /*0c*/	{ inst_inr,	OP_0 },
2420 /*0d*/	{ inst_dcr,	OP_0 },
2421 /*0e*/	{ inst_mvi,	OP_ARG8 },
2422 /*0f*/	{ inst_rrca,	OP_0 },
2423 /*10*/	{ inst_djnz,	OP_ARG8 },
2424 /*11*/	{ inst_lxi,	OP_ARG16 },
2425 /*12*/	{ inst_stax,	OP_0 },
2426 /*13*/	{ inst_inx,	OP_0 },
2427 /*14*/	{ inst_inr,	OP_0 },
2428 /*15*/	{ inst_dcr,	OP_0 },
2429 /*16*/	{ inst_mvi,	OP_ARG8 },
2430 /*17*/	{ inst_rla,	OP_0 },
2431 /*18*/	{ inst_jr,	OP_ARG8 },
2432 /*19*/	{ inst_dad,	OP_0 },
2433 /*1a*/	{ inst_ldax,	OP_0 },
2434 /*1b*/	{ inst_dcx,	OP_0 },
2435 /*1c*/	{ inst_inr,	OP_0 },
2436 /*1d*/	{ inst_dcr,	OP_0 },
2437 /*1e*/	{ inst_mvi,	OP_ARG8 },
2438 /*1f*/	{ inst_rra,	OP_0 },
2439 /*20*/	{ inst_jrcc,	OP_ARG8 },
2440 /*21*/	{ inst_lxi,	OP_ARG16 },
2441 /*22*/	{ inst_shld,	OP_ARG16 },
2442 /*23*/	{ inst_inx,	OP_0 },
2443 /*24*/	{ inst_inr,	OP_0 },
2444 /*25*/	{ inst_dcr,	OP_0 },
2445 /*26*/	{ inst_mvi,	OP_ARG8 },
2446 /*27*/	{ inst_daa,	OP_0 },
2447 /*28*/	{ inst_jrcc,	OP_ARG8 },
2448 /*29*/	{ inst_dad,	OP_0 },
2449 /*2a*/	{ inst_lhld,	OP_ARG16 },
2450 /*2b*/	{ inst_dcx,	OP_0 },
2451 /*2c*/	{ inst_inr,	OP_0 },
2452 /*2d*/	{ inst_dcr,	OP_0 },
2453 /*2e*/	{ inst_mvi,	OP_ARG8 },
2454 /*2f*/	{ inst_cpl,	OP_0 },
2455 /*30*/	{ inst_jrcc,	OP_ARG8 },
2456 /*31*/	{ inst_lxi,	OP_ARG16 },
2457 /*32*/	{ inst_sta,	OP_ARG16 },
2458 /*33*/	{ inst_inx,	OP_0 },
2459 /*34*/	{ inst_inr,	OP_INDEXED },
2460 /*35*/	{ inst_dcr,	OP_INDEXED },
2461 /*36*/	{ inst_mvi,	OP_INDEXED|OP_ARG8 },
2462 /*37*/	{ inst_scf,	OP_0 },
2463 /*38*/	{ inst_jrcc,	OP_ARG8 },
2464 /*39*/	{ inst_dad,	OP_0 },
2465 /*3a*/	{ inst_lda,	OP_ARG16 },
2466 /*3b*/	{ inst_dcx,	OP_0 },
2467 /*3c*/	{ inst_inr,	OP_0 },
2468 /*3d*/	{ inst_dcr,	OP_0 },
2469 /*3e*/	{ inst_mvi,	OP_ARG8 },
2470 /*3f*/	{ inst_ccf,	OP_0 },
2471 /*40*/	{ inst_mov,	OP_0 },
2472 /*41*/	{ inst_mov,	OP_0 },
2473 /*42*/	{ inst_mov,	OP_0 },
2474 /*43*/	{ inst_mov,	OP_0 },
2475 /*44*/	{ inst_mov,	OP_0 },
2476 /*45*/	{ inst_mov,	OP_0 },
2477 /*46*/	{ inst_mov,	OP_INDEXED },
2478 /*47*/	{ inst_mov,	OP_0 },
2479 /*48*/	{ inst_mov,	OP_0 },
2480 /*49*/	{ inst_mov,	OP_0 },
2481 /*4a*/	{ inst_mov,	OP_0 },
2482 /*4b*/	{ inst_mov,	OP_0 },
2483 /*4c*/	{ inst_mov,	OP_0 },
2484 /*4d*/	{ inst_mov,	OP_0 },
2485 /*4e*/	{ inst_mov,	OP_INDEXED },
2486 /*4f*/	{ inst_mov,	OP_0 },
2487 /*50*/	{ inst_mov,	OP_0 },
2488 /*51*/	{ inst_mov,	OP_0 },
2489 /*52*/	{ inst_mov,	OP_0 },
2490 /*53*/	{ inst_mov,	OP_0 },
2491 /*54*/	{ inst_mov,	OP_0 },
2492 /*55*/	{ inst_mov,	OP_0 },
2493 /*56*/	{ inst_mov,	OP_INDEXED },
2494 /*57*/	{ inst_mov,	OP_0 },
2495 /*58*/	{ inst_mov,	OP_0 },
2496 /*59*/	{ inst_mov,	OP_0 },
2497 /*5a*/	{ inst_mov,	OP_0 },
2498 /*5b*/	{ inst_mov,	OP_0 },
2499 /*5c*/	{ inst_mov,	OP_0 },
2500 /*5d*/	{ inst_mov,	OP_0 },
2501 /*5e*/	{ inst_mov,	OP_INDEXED },
2502 /*5f*/	{ inst_mov,	OP_0 },
2503 /*60*/	{ inst_mov,	OP_0 },
2504 /*61*/	{ inst_mov,	OP_0 },
2505 /*62*/	{ inst_mov,	OP_0 },
2506 /*63*/	{ inst_mov,	OP_0 },
2507 /*64*/	{ inst_mov,	OP_0 },
2508 /*65*/	{ inst_mov,	OP_0 },
2509 /*66*/	{ inst_mov,	OP_INDEXED },
2510 /*67*/	{ inst_mov,	OP_0 },
2511 /*68*/	{ inst_mov,	OP_0 },
2512 /*69*/	{ inst_mov,	OP_0 },
2513 /*6a*/	{ inst_mov,	OP_0 },
2514 /*6b*/	{ inst_mov,	OP_0 },
2515 /*6c*/	{ inst_mov,	OP_0 },
2516 /*6d*/	{ inst_mov,	OP_0 },
2517 /*6e*/	{ inst_mov,	OP_INDEXED },
2518 /*6f*/	{ inst_mov,	OP_0 },
2519 /*70*/	{ inst_mov,	OP_INDEXED },
2520 /*71*/	{ inst_mov,	OP_INDEXED },
2521 /*72*/	{ inst_mov,	OP_INDEXED },
2522 /*73*/	{ inst_mov,	OP_INDEXED },
2523 /*74*/	{ inst_mov,	OP_INDEXED },
2524 /*75*/	{ inst_mov,	OP_INDEXED },
2525 /*76*/	{ inst_halt,	OP_0 },
2526 /*77*/	{ inst_mov,	OP_INDEXED },
2527 /*78*/	{ inst_mov,	OP_0 },
2528 /*79*/	{ inst_mov,	OP_0 },
2529 /*7a*/	{ inst_mov,	OP_0 },
2530 /*7b*/	{ inst_mov,	OP_0 },
2531 /*7c*/	{ inst_mov,	OP_0 },
2532 /*7d*/	{ inst_mov,	OP_0 },
2533 /*7e*/	{ inst_mov,	OP_INDEXED },
2534 /*7f*/	{ inst_mov,	OP_0 },
2535 /*80*/	{ inst_add,	OP_0 },
2536 /*81*/	{ inst_add,	OP_0 },
2537 /*82*/	{ inst_add,	OP_0 },
2538 /*83*/	{ inst_add,	OP_0 },
2539 /*84*/	{ inst_add,	OP_0 },
2540 /*85*/	{ inst_add,	OP_0 },
2541 /*86*/	{ inst_add,	OP_INDEXED },
2542 /*87*/	{ inst_add,	OP_0 },
2543 /*88*/	{ inst_adc,	OP_0 },
2544 /*89*/	{ inst_adc,	OP_0 },
2545 /*8a*/	{ inst_adc,	OP_0 },
2546 /*8b*/	{ inst_adc,	OP_0 },
2547 /*8c*/	{ inst_adc,	OP_0 },
2548 /*8d*/	{ inst_adc,	OP_0 },
2549 /*8e*/	{ inst_adc,	OP_INDEXED },
2550 /*8f*/	{ inst_adc,	OP_0 },
2551 /*90*/	{ inst_sub,	OP_0 },
2552 /*91*/	{ inst_sub,	OP_0 },
2553 /*92*/	{ inst_sub,	OP_0 },
2554 /*93*/	{ inst_sub,	OP_0 },
2555 /*94*/	{ inst_sub,	OP_0 },
2556 /*95*/	{ inst_sub,	OP_0 },
2557 /*96*/	{ inst_sub,	OP_INDEXED },
2558 /*97*/	{ inst_sub,	OP_0 },
2559 /*98*/	{ inst_sbca,	OP_0 },
2560 /*99*/	{ inst_sbca,	OP_0 },
2561 /*9a*/	{ inst_sbca,	OP_0 },
2562 /*9b*/	{ inst_sbca,	OP_0 },
2563 /*9c*/	{ inst_sbca,	OP_0 },
2564 /*9d*/	{ inst_sbca,	OP_0 },
2565 /*9e*/	{ inst_sbca,	OP_INDEXED },
2566 /*9f*/	{ inst_sbca,	OP_0 },
2567 /*a0*/	{ inst_and,	OP_0 },
2568 /*a1*/	{ inst_and,	OP_0 },
2569 /*a2*/	{ inst_and,	OP_0 },
2570 /*a3*/	{ inst_and,	OP_0 },
2571 /*a4*/	{ inst_and,	OP_0 },
2572 /*a5*/	{ inst_and,	OP_0 },
2573 /*a6*/	{ inst_and,	OP_INDEXED },
2574 /*a7*/	{ inst_and,	OP_0 },
2575 /*a8*/	{ inst_xor,	OP_0 },
2576 /*a9*/	{ inst_xor,	OP_0 },
2577 /*aa*/	{ inst_xor,	OP_0 },
2578 /*ab*/	{ inst_xor,	OP_0 },
2579 /*ac*/	{ inst_xor,	OP_0 },
2580 /*ad*/	{ inst_xor,	OP_0 },
2581 /*ae*/	{ inst_xor,	OP_INDEXED },
2582 /*af*/	{ inst_xor,	OP_0 },
2583 /*b0*/	{ inst_or,	OP_0 },
2584 /*b1*/	{ inst_or,	OP_0 },
2585 /*b2*/	{ inst_or,	OP_0 },
2586 /*b3*/	{ inst_or,	OP_0 },
2587 /*b4*/	{ inst_or,	OP_0 },
2588 /*b5*/	{ inst_or,	OP_0 },
2589 /*b6*/	{ inst_or,	OP_INDEXED },
2590 /*b7*/	{ inst_or,	OP_0 },
2591 /*b8*/	{ inst_cmp,	OP_0 },
2592 /*b9*/	{ inst_cmp,	OP_0 },
2593 /*ba*/	{ inst_cmp,	OP_0 },
2594 /*bb*/	{ inst_cmp,	OP_0 },
2595 /*bc*/	{ inst_cmp,	OP_0 },
2596 /*bd*/	{ inst_cmp,	OP_0 },
2597 /*be*/	{ inst_cmp,	OP_INDEXED },
2598 /*bf*/	{ inst_cmp,	OP_0 },
2599 /*c0*/	{ inst_retcc,	OP_0 },
2600 /*c1*/	{ inst_pop,	OP_0 },
2601 /*c2*/	{ inst_jpcc,	OP_ARG16 },
2602 /*c3*/	{ inst_jp,	OP_ARG16 },
2603 /*c4*/	{ inst_callcc,	OP_ARG16 },
2604 /*c5*/	{ inst_push,	OP_0 },
2605 /*c6*/	{ inst_adi,	OP_ARG8 },
2606 /*c7*/	{ inst_rst,	OP_0 },
2607 /*c8*/	{ inst_retcc,	OP_0 },
2608 /*c9*/	{ inst_ret,	OP_0 },
2609 /*ca*/	{ inst_jpcc,	OP_ARG16 },
2610 /*cb*/	{ inst_cb,	OP_INDEXED },
2611 /*cc*/	{ inst_callcc,	OP_ARG16 },
2612 /*cd*/	{ inst_call,	OP_ARG16 },
2613 /*ce*/	{ inst_aci,	OP_ARG8 },
2614 /*cf*/	{ inst_rst,	OP_0 },
2615 /*d0*/	{ inst_retcc,	OP_0 },
2616 /*d1*/	{ inst_pop,	OP_0 },
2617 /*d2*/	{ inst_jpcc,	OP_ARG16 },
2618 /*d3*/	{ inst_outa,	OP_ARG8 },
2619 /*d4*/	{ inst_callcc,	OP_ARG16 },
2620 /*d5*/	{ inst_push,	OP_0 },
2621 /*d6*/	{ inst_sui,	OP_ARG8 },
2622 /*d7*/	{ inst_rst,	OP_0 },
2623 /*d8*/	{ inst_retcc,	OP_0 },
2624 /*d9*/	{ inst_exx,	OP_0 },
2625 /*da*/	{ inst_jpcc,	OP_ARG16 },
2626 /*db*/	{ inst_ina,	OP_ARG8 },
2627 /*dc*/	{ inst_callcc,	OP_ARG16 },
2628 /*dd*/	{ NULL,	OP_0 },
2629 /*de*/	{ inst_sbi,	OP_ARG8 },
2630 /*df*/	{ inst_rst,	OP_0 },
2631 /*e0*/	{ inst_retcc,	OP_0 },
2632 /*e1*/	{ inst_pop,	OP_0 },
2633 /*e2*/	{ inst_jpcc,	OP_ARG16 },
2634 /*e3*/	{ inst_xthl,	OP_0 },
2635 /*e4*/	{ inst_callcc,	OP_ARG16 },
2636 /*e5*/	{ inst_push,	OP_0 },
2637 /*e6*/	{ inst_ani,	OP_ARG8 },
2638 /*e7*/	{ inst_rst,	OP_0 },
2639 /*e8*/	{ inst_retcc,	OP_0 },
2640 /*e9*/	{ inst_pchl,	OP_0 },
2641 /*ea*/	{ inst_jpcc,	OP_ARG16 },
2642 /*eb*/	{ inst_xchg,	OP_0 },
2643 /*ec*/	{ inst_callcc,	OP_ARG16 },
2644 /*ed*/	{ NULL,	OP_0 },
2645 /*ee*/	{ inst_xri,	OP_ARG8 },
2646 /*ef*/	{ inst_rst,	OP_0 },
2647 /*f0*/	{ inst_retcc,	OP_0 },
2648 /*f1*/	{ inst_pop,	OP_0 },
2649 /*f2*/	{ inst_jpcc,	OP_ARG16 },
2650 /*f3*/	{ inst_di,	OP_0 },
2651 /*f4*/	{ inst_callcc,	OP_ARG16 },
2652 /*f5*/	{ inst_push,	OP_0 },
2653 /*f6*/	{ inst_ori,	OP_ARG8 },
2654 /*f7*/	{ inst_rst,	OP_0 },
2655 /*f8*/	{ inst_retcc,	OP_0 },
2656 /*f9*/	{ inst_sphl,	OP_0 },
2657 /*fa*/	{ inst_jpcc,	OP_ARG16 },
2658 /*fb*/	{ inst_ei,	OP_0 },
2659 /*fc*/	{ inst_callcc,	OP_ARG16 },
2660 /*fd*/	{ NULL,	OP_0 },
2661 /*fe*/	{ inst_cmpi,	OP_ARG8 },
2662 /*ff*/	{ inst_rst,	OP_0 }
2663 };
2664 
2665 
2666 /*
2667  * instruction counters
2668  */
2669 static unsigned long counters[256];
2670 static unsigned long ed_counters[256];
2671 static unsigned long cb_counters[256];
2672 static unsigned long dd_counters[256];
2673 static unsigned long fd_counters[256];
2674 static unsigned long dd_cb_counters[256];
2675 static unsigned long fd_cb_counters[256];
2676 
2677 
2678 /*
2679  * longjmp on reception of SIGINT, SIGTERM, or SIGQUIT
2680  */
2681 static jmp_buf signal_jmp;
2682 
2683 
2684 /*
2685  * signal handler just jumps to the top of the main loop
2686  */
handler(int s)2687 static void handler(int s) {
2688 	struct sigaction sa;
2689 	switch (s) {
2690 	case SIGTERM:
2691 	case SIGQUIT:
2692 	case SIGINT:
2693 		/*
2694 		 * these signals are handled only once; repeated
2695 		 * occurrences are ignored
2696 		 */
2697 		sa.sa_handler = SIG_IGN;
2698 		sigemptyset(&sa.sa_mask);
2699 		sa.sa_flags = 0;
2700 		sigaction(SIGTERM, &sa, NULL);
2701 		sigaction(SIGQUIT, &sa, NULL);
2702 		sigaction(SIGINT, &sa, NULL);
2703 		longjmp(signal_jmp, 1);
2704 		break;
2705 	case SIGUSR1:
2706 		dump = 1;
2707 		break;
2708 	}
2709 }
2710 
2711 
2712 /*
2713  * after this number of instructions, the console is polled
2714  */
2715 #define POLL_INTERVAL (128 * 1024)
2716 
2717 
2718 /*
2719  * start emulation proper
2720  */
2721 void
cpu_run(void)2722 cpu_run(void) {
2723 	int poll_counter = 0, delay_counter = 0;
2724 	const struct instruction *inst_p;
2725 	struct sigaction sa;
2726 	struct timespec delay;
2727 	/*
2728 	 * initialize the nanosecond delay value
2729 	 */
2730 	if (delay_nanoseconds > 0) {
2731 		memset(&delay, 0, sizeof delay);
2732 		delay.tv_sec = delay_nanoseconds / 1000000000;
2733 		delay.tv_nsec = delay_nanoseconds % 1000000000;
2734 	}
2735 	/*
2736 	 * catch signals for termination of a runaway program
2737 	 */
2738 	if (setjmp(signal_jmp)) {
2739 		if (! terminate) {
2740 			terminate = 1;
2741 			term_reason = ERR_SIGNAL;
2742 		}
2743 	} else {
2744 		/*
2745 		 * signals causing the emulation to terminate with
2746 		 * status ERR_SIGNAL; the handlers block the occurrence
2747 		 * of the other signals to avoid calling logjmp() twice.
2748 		 */
2749 		sa.sa_handler = handler;
2750 		sigemptyset(&sa.sa_mask);
2751 		sigaddset(&sa.sa_mask, SIGTERM);
2752 		sigaddset(&sa.sa_mask, SIGQUIT);
2753 		sigaddset(&sa.sa_mask, SIGINT);
2754 		sa.sa_flags = 0;
2755 		sigaction(SIGTERM, &sa, NULL);
2756 		sigaction(SIGQUIT, &sa, NULL);
2757 		sigaction(SIGINT, &sa, NULL);
2758 	}
2759 	/*
2760 	 * install signal handler if dump signals are requested
2761 	 */
2762 	if (conf_dump & DUMP_SIGNAL) {
2763 		sa.sa_handler = handler;
2764 		sigemptyset(&sa.sa_mask);
2765 		sa.sa_flags = 0;
2766 		sigaction(SIGUSR1, &sa, NULL);
2767 	}
2768 	while (! terminate) {
2769 		/*
2770 		 * dump machine state
2771 		 */
2772 		if (dump) {
2773 			dump = 0;
2774 			dump_machine("signal");
2775 		}
2776 		/*
2777 		 * mark start of new instruction
2778 		 */
2779 		current_instruction = reg_pc;
2780 		/*
2781 		 * fetch next opcode, handle instruction prefixes
2782 		 */
2783 		prefix = 0x00;
2784 		for (;;) {
2785 			opcode = fetch_m1();
2786 			if (opcode != 0xdd && opcode != 0xfd) break;
2787 			prefix = opcode;
2788 		}
2789 		inst_p = base_plane + opcode;
2790 		/*
2791 		 * get optional displacement
2792 		 */
2793 		if (prefix && (inst_p->flags & OP_INDEXED)) disp = fetch();
2794 		/*
2795 		 * instructions starting in 0xed are handled in
2796 		 * a slightly different way (contrary to those starting in
2797 		 * 0xcb they are not influenced by prefixes and have
2798 		 * non-uniform arguments)
2799 		 */
2800 		if (opcode == 0xcb) {
2801 			opcode2 = prefix ? fetch_m1() : fetch();
2802 			if (log_level >= LL_COUNTERS) {
2803 				switch (prefix) {
2804 				case 0xdd: dd_cb_counters[opcode2]++; break;
2805 				case 0xfd: fd_cb_counters[opcode2]++; break;
2806 				default: cb_counters[opcode2]++; break;
2807 				}
2808 			}
2809 		} else if (opcode == 0xed) {
2810 			opcode2 = fetch_m1();
2811 			inst_p = ed_plane + opcode2;
2812 			if (log_level >= LL_COUNTERS) {
2813 				ed_counters[opcode2]++;
2814 			}
2815 		} else {
2816 			if (log_level >= LL_COUNTERS) {
2817 				switch (prefix) {
2818 				case 0xdd: dd_counters[opcode]++; break;
2819 				case 0xfd: fd_counters[opcode]++; break;
2820 				default: counters[opcode]++; break;
2821 				}
2822 			}
2823 		}
2824 		/*
2825 		 * get optional 8-bit argument
2826 		 */
2827 		if (inst_p->flags & OP_ARG8) op_low = fetch();
2828 		/*
2829 		 * get optional 16-bit argument
2830 		 */
2831 		if (inst_p->flags & OP_ARG16) {
2832 			op_low = fetch();
2833 			op_high = fetch();
2834 		}
2835 		/*
2836 		 * execute instruction
2837 		 */
2838 		(*inst_p->handler_p)();
2839 		/*
2840 		 * Poll the console in regular intervals; this is a rather
2841 		 * clumsy solution to keep the VT52 emulation happy even
2842 		 * if a program doesn't care about console input for a
2843 		 * prolonged period.
2844 		 */
2845 		poll_counter++;
2846 		if (poll_counter == POLL_INTERVAL) {
2847 			poll_counter = 0;
2848 			console_poll();
2849 		}
2850 		if (delay_count > 0) {
2851 			/*
2852 			 * add a delay of delay_nanoseconds every
2853 			 * delay_count emulated instructions
2854 			 */
2855 			delay_counter++;
2856 			if (delay_counter >= delay_count) {
2857 				delay_counter = 0;
2858 				nanosleep(&delay, NULL);
2859 			}
2860 		}
2861 	}
2862 }
2863 
2864 
2865 /*
2866  * copy the instruction call counters of a instruction plane to the log
2867  */
2868 static void
dump_plane(unsigned long counters[256],const char * name)2869 dump_plane(unsigned long counters[256], const char *name) {
2870 	int low, high, n;
2871 	char buffer[1024], *cp;
2872 	/*
2873 	 * check if all counters in the plane are zero
2874 	 */
2875 	for (n = 0; n < 256 && ! counters[n]; n++);
2876 	if (n == 256) {
2877 		/*
2878 		 * all counters are zero: log a single line
2879 		 * (this will be the case for planes other than the
2880 		 * base plane after executing a 8080 program)
2881 		 */
2882 		plog("instruction counters for %s: all zero", name);
2883 	} else {
2884 		/*
2885 		 * at least one counter is greater than zero:
2886 		 * log full table
2887 		 */
2888 		plog("instruction counters for %s:", name);
2889 		cp = buffer;
2890 		cp += sprintf(cp, "  ");
2891 		for (high = 0; high < 16; high++) {
2892 			cp += sprintf(cp, "         %1xy", high);
2893 		}
2894 		plog("%s", buffer);
2895 		for (low = 0; low < 16; low++) {
2896 			cp = buffer;
2897 			cp += sprintf(cp, "x%1x", low);
2898 			for (high = 0; high < 16; high++) {
2899 				n = high * 16 + low;
2900 				if (counters[n]) {
2901 					cp += sprintf(cp, " %10lu",
2902 					    counters[n]);
2903 				} else {
2904 					cp += sprintf(cp, "          -");
2905 				}
2906 			}
2907 			plog("%s", buffer);
2908 		}
2909 	}
2910 }
2911 
2912 
2913 /*
2914  * save (parts of) the Z80 memory as an Intel Hex file
2915  */
2916 static int
save_memory_hex(void)2917 save_memory_hex(void) {
2918 	int rc = 0;
2919 	int addr, bytes, checksum, i;
2920 	FILE *fp = NULL;
2921 	/*
2922 	 * create text file
2923 	 */
2924 	fp = fopen(conf_save_file, "w");
2925 	if (! fp) {
2926 		perr("cannot create %s: %s", conf_save_file, strerror(errno));
2927 		rc = (-1);
2928 		goto premature_exit;
2929 	}
2930 	/*
2931 	 * save data in records of at most 32 bytes
2932 	 */
2933 	addr = conf_save_start;
2934 	while (addr <= conf_save_end) {
2935 		bytes = conf_save_end - addr + 1;
2936 		if (bytes > 32) bytes = 32;
2937 		checksum = bytes + ((addr >> 8) & 0xff) + (addr & 0xff);
2938 		fprintf(fp, ":%02X%04X00", bytes, addr);
2939 		for (i = 0; i < bytes; i++) {
2940 			fprintf(fp, "%02X", memory[addr + i]);
2941 			checksum += memory[addr + i];
2942 		}
2943 		checksum = ((0x100 - (checksum & 0xff)) & 0xff);
2944 		fprintf(fp, "%02X\n", checksum);
2945 		addr += bytes;
2946 	}
2947 	/*
2948 	 * write EOF record
2949 	 */
2950 	checksum = 0 + ((conf_save_start >> 8) & 0xff) +
2951 	    (conf_save_start & 0xff) + 1;
2952 	checksum = ((0x100 - (checksum & 0xff)) & 0xff);
2953 	fprintf(fp, ":00%04X01%02X\n", conf_save_start, checksum);
2954 	/*
2955 	 * summary error check
2956 	 */
2957 	if (ferror(fp)) {
2958 		perr("write error in %s: %s", conf_save_file, strerror(errno));
2959 		rc = (-1);
2960 	}
2961 premature_exit:
2962 	if (fp) {
2963 		/*
2964 		 * close text file
2965 		 */
2966 		if (fclose(fp)) {
2967 			perr("cannot close %s: %s", conf_save_file,
2968 			    strerror(errno));
2969 			rc = (-1);
2970 		}
2971 	}
2972 	return rc;
2973 }
2974 
2975 
2976 /*
2977  * save (parts of) the Z80 memory as a binary file
2978  */
2979 static int
save_memory_bin(void)2980 save_memory_bin(void) {
2981 	int rc = 0;
2982 	size_t n;
2983 	FILE *fp = NULL;
2984 	/*
2985 	 * create binary file
2986 	 */
2987 	fp = fopen(conf_save_file, "wb");
2988 	if (! fp) {
2989 		perr("cannot create %s: %s", conf_save_file, strerror(errno));
2990 		rc = (-1);
2991 		goto premature_exit;
2992 	}
2993 	/*
2994 	 * write memory contents
2995 	 */
2996 	n = conf_save_end - conf_save_start + 1;
2997 	if (fwrite(memory + conf_save_start, sizeof memory[0], n, fp) != n) {
2998 		perr("write error on %s: %s", conf_save_file, strerror(errno));
2999 		rc = (-1);
3000 	}
3001 premature_exit:
3002 	if (fp) {
3003 		/*
3004 		 * close binary file
3005 		 */
3006 		if (fclose(fp)) {
3007 			perr("cannot close %s: %s", conf_save_file,
3008 			    strerror(errno));
3009 			rc = (-1);
3010 		}
3011 	}
3012 	return rc;
3013 }
3014 
3015 
3016 /*
3017  * clean up after emulation run
3018  */
3019 int
cpu_exit(void)3020 cpu_exit(void) {
3021 	int rc = 0;
3022 	/*
3023 	 * finalize OS emulation
3024 	 */
3025 	rc = os_exit();
3026 	/*
3027 	 * perform exit or error dump
3028 	 */
3029 	if (conf_dump & DUMP_EXIT) {
3030 		dump_machine("exit");
3031 	} else if (conf_dump & DUMP_ERROR) {
3032 		if (term_reason > OK_CTRLC) dump_machine("error");
3033 	}
3034 	/*
3035 	 * display reason for program termination
3036 	 */
3037 	switch (term_reason) {
3038 	case OK_NOTRUN:
3039 		break;
3040 	case OK_TERM:
3041 		break;
3042 	case OK_CTRLC:
3043 		break;
3044 	case ERR_BOOT:
3045 		perr("BIOS cold boot entry called");
3046 		break;
3047 	case ERR_BDOSARG:
3048 		perr("invalid argument in BDOS call");
3049 		break;
3050 	case ERR_SELECT:
3051 		perr("access to invalid/unconfigured disk");
3052 		break;
3053 	case ERR_RODISK:
3054 		perr("attempted write access to read-only disk");
3055 		break;
3056 	case ERR_ROFILE:
3057 		perr("attempted write access to read-only file");
3058 		break;
3059 	case ERR_HOST:
3060 		perr("host system call failed");
3061 		break;
3062 	case ERR_LOGIC:
3063 		perr("guest program logic error");
3064 		break;
3065 	case ERR_SIGNAL:
3066 		perr("program execution stopped by signal");
3067 		break;
3068 	case ERR_HALT:
3069 		perr("HALT instruction executed");
3070 		break;
3071 	}
3072 	if (term_reason <= OK_CTRLC) {
3073 		if (conf_save_file) {
3074 			/*
3075 			 * save (part of) the Z80 memory area
3076 			 * on regular program termination
3077 			 */
3078 			if (conf_save_hex) {
3079 				if (save_memory_hex()) rc = (-1);
3080 			} else {
3081 				if (save_memory_bin()) rc = (-1);
3082 			}
3083 		}
3084 	} else {
3085 		rc = (-1);
3086 	}
3087 	/*
3088 	 * deallocate memory
3089 	 */
3090 	free(memory);
3091 	/*
3092 	 * dump instruction counters
3093 	 */
3094 	if (log_level >= LL_COUNTERS) {
3095 		dump_plane(counters, "base plane");
3096 		dump_plane(cb_counters, "0xcb plane");
3097 		dump_plane(dd_counters, "0xdd base plane");
3098 		dump_plane(dd_cb_counters, "0xdd 0xcb plane");
3099 		dump_plane(ed_counters, "0xed plane");
3100 		dump_plane(fd_counters, "0xfd base plane");
3101 		dump_plane(fd_cb_counters, "0xfd 0xcb plane");
3102 	}
3103 	return rc;
3104 }
3105