FabGL
ESP32 Display Controller and Graphics Library
i8080.cpp
1// Intel 8080 (KR580VM80A) microprocessor core model
2//
3// Copyright (C) 2012 Alexander Demin <alexander@demin.ws>
4//
5// Credits
6//
7// Viacheslav Slavinsky, Vector-06C FPGA Replica
8// http://code.google.com/p/vector06cc/
9//
10// Dmitry Tselikov, Bashrikia-2M and Radio-86RK on Altera DE1
11// http://bashkiria-2m.narod.ru/fpga.html
12//
13// Ian Bartholomew, 8080/8085 CPU Exerciser
14// http://www.idb.me.uk/sunhillow/8080.html
15//
16// Frank Cringle, The original exerciser for the Z80.
17//
18// Thanks to zx.pk.ru and nedopc.org/forum communities.
19//
20// This program is free software; you can redistribute it and/or modify
21// it under the terms of the GNU General Public License as published by
22// the Free Software Foundation; either version 2, or (at your option)
23// any later version.
24//
25// This program is distributed in the hope that it will be useful,
26// but WITHOUT ANY WARRANTY; without even the implied warranty of
27// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28// GNU General Public License for more details.
29//
30// You should have received a copy of the GNU General Public License
31// along with this program; if not, write to the Free Software
32// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33//
34//
35// 2020 adapted by Fabrizio Di Vittorio for fabgl ESP32 library
36
37
38
39#include "i8080.h"
40
41
42#pragma GCC optimize ("O2")
43
44
45namespace fabgl {
46
47
48#define RD_BYTE(addr) m_readByte(m_context, addr)
49#define RD_WORD(addr) m_readWord(m_context, addr)
50
51#define WR_BYTE(addr, value) m_writeByte(m_context, addr, value)
52#define WR_WORD(addr, value) m_writeWord(m_context, addr, value)
53
54
55
56
57
58#define FLAGS cpu.f
59#define AF cpu.af.w
60#define BC cpu.bc.w
61#define DE cpu.de.w
62#define HL cpu.hl.w
63#define SP cpu.sp.w
64#define PC cpu.pc.w
65#define A cpu.af.b.h
66#define F cpu.af.b.l
67#define B cpu.bc.b.h
68#define C cpu.bc.b.l
69#define D cpu.de.b.h
70#define E cpu.de.b.l
71#define H cpu.hl.b.h
72#define L cpu.hl.b.l
73#define HSP cpu.sp.b.h
74#define LSP cpu.sp.b.l
75#define HPC cpu.pc.b.h
76#define LPC cpu.pc.b.l
77#define IFF cpu.iff
78
79#define F_CARRY 0x01
80#define F_UN1 0x02
81#define F_PARITY 0x04
82#define F_UN3 0x08
83#define F_HCARRY 0x10
84#define F_UN5 0x20
85#define F_ZERO 0x40
86#define F_NEG 0x80
87
88#define C_FLAG FLAGS.carry_flag
89#define P_FLAG FLAGS.parity_flag
90#define H_FLAG FLAGS.half_carry_flag
91#define Z_FLAG FLAGS.zero_flag
92#define S_FLAG FLAGS.sign_flag
93#define UN1_FLAG FLAGS.unused1
94#define UN3_FLAG FLAGS.unused3
95#define UN5_FLAG FLAGS.unused5
96
97#define SET(flag) (flag = 1)
98#define CLR(flag) (flag = 0)
99#define TST(flag) (flag)
100#define CPL(flag) (flag = !flag)
101
102#define POP(reg) { (reg) = RD_WORD(SP); SP += 2; }
103#define PUSH(reg) { SP -= 2; WR_WORD(SP, (reg)); }
104#define RET() { POP(PC); }
105#define STC() { SET(C_FLAG); }
106#define CMC() { CPL(C_FLAG); }
107
108#define INR(reg) \
109{ \
110 ++(reg); \
111 S_FLAG = (((reg) & 0x80) != 0); \
112 Z_FLAG = ((reg) == 0); \
113 H_FLAG = (((reg) & 0x0f) == 0); \
114 P_FLAG = PARITY(reg); \
115}
116
117#define DCR(reg) \
118{ \
119 --(reg); \
120 S_FLAG = (((reg) & 0x80) != 0); \
121 Z_FLAG = ((reg) == 0); \
122 H_FLAG = !(((reg) & 0x0f) == 0x0f); \
123 P_FLAG = PARITY(reg); \
124}
125
126#define ADD(val) \
127{ \
128 work16 = (uint16_t)A + (val); \
129 index = ((A & 0x88) >> 1) | \
130 (((val) & 0x88) >> 2) | \
131 ((work16 & 0x88) >> 3); \
132 A = work16 & 0xff; \
133 S_FLAG = ((A & 0x80) != 0); \
134 Z_FLAG = (A == 0); \
135 H_FLAG = half_carry_table[index & 0x7]; \
136 P_FLAG = PARITY(A); \
137 C_FLAG = ((work16 & 0x0100) != 0); \
138}
139
140#define ADC(val) \
141{ \
142 work16 = (uint16_t)A + (val) + C_FLAG; \
143 index = ((A & 0x88) >> 1) | \
144 (((val) & 0x88) >> 2) | \
145 ((work16 & 0x88) >> 3); \
146 A = work16 & 0xff; \
147 S_FLAG = ((A & 0x80) != 0); \
148 Z_FLAG = (A == 0); \
149 H_FLAG = half_carry_table[index & 0x7]; \
150 P_FLAG = PARITY(A); \
151 C_FLAG = ((work16 & 0x0100) != 0); \
152}
153
154#define SUB(val) \
155{ \
156 work16 = (uint16_t)A - (val); \
157 index = ((A & 0x88) >> 1) | \
158 (((val) & 0x88) >> 2) | \
159 ((work16 & 0x88) >> 3); \
160 A = work16 & 0xff; \
161 S_FLAG = ((A & 0x80) != 0); \
162 Z_FLAG = (A == 0); \
163 H_FLAG = !sub_half_carry_table[index & 0x7]; \
164 P_FLAG = PARITY(A); \
165 C_FLAG = ((work16 & 0x0100) != 0); \
166}
167
168#define SBB(val) \
169{ \
170 work16 = (uint16_t)A - (val) - C_FLAG; \
171 index = ((A & 0x88) >> 1) | \
172 (((val) & 0x88) >> 2) | \
173 ((work16 & 0x88) >> 3); \
174 A = work16 & 0xff; \
175 S_FLAG = ((A & 0x80) != 0); \
176 Z_FLAG = (A == 0); \
177 H_FLAG = !sub_half_carry_table[index & 0x7]; \
178 P_FLAG = PARITY(A); \
179 C_FLAG = ((work16 & 0x0100) != 0); \
180}
181
182#define CMP(val) \
183{ \
184 work16 = (uint16_t)A - (val); \
185 index = ((A & 0x88) >> 1) | \
186 (((val) & 0x88) >> 2) | \
187 ((work16 & 0x88) >> 3); \
188 S_FLAG = ((work16 & 0x80) != 0); \
189 Z_FLAG = ((work16 & 0xff) == 0); \
190 H_FLAG = !sub_half_carry_table[index & 0x7]; \
191 C_FLAG = ((work16 & 0x0100) != 0); \
192 P_FLAG = PARITY(work16 & 0xff); \
193}
194
195#define ANA(val) \
196{ \
197 H_FLAG = ((A | val) & 0x08) != 0; \
198 A &= (val); \
199 S_FLAG = ((A & 0x80) != 0); \
200 Z_FLAG = (A == 0); \
201 P_FLAG = PARITY(A); \
202 CLR(C_FLAG); \
203}
204
205#define XRA(val) \
206{ \
207 A ^= (val); \
208 S_FLAG = ((A & 0x80) != 0); \
209 Z_FLAG = (A == 0); \
210 CLR(H_FLAG); \
211 P_FLAG = PARITY(A); \
212 CLR(C_FLAG); \
213}
214
215#define ORA(val) \
216{ \
217 A |= (val); \
218 S_FLAG = ((A & 0x80) != 0); \
219 Z_FLAG = (A == 0); \
220 CLR(H_FLAG); \
221 P_FLAG = PARITY(A); \
222 CLR(C_FLAG); \
223}
224
225#define DAD(reg) \
226{ \
227 work32 = (uint32_t)HL + (reg); \
228 HL = work32 & 0xffff; \
229 C_FLAG = ((work32 & 0x10000L) != 0); \
230}
231
232#define CALL \
233{ \
234 PUSH(PC + 2); \
235 PC = RD_WORD(PC); \
236}
237
238#define RST(addr) \
239{ \
240 PUSH(PC); \
241 PC = (addr); \
242}
243
244#define PARITY(reg) getParity(reg)
245
246
247int getParity(int val)
248{
249 val ^= val >> 4;
250 val &= 0xf;
251 return !((0x6996 >> val) & 1);
252}
253
254
255static const int half_carry_table[] = { 0, 0, 1, 0, 1, 0, 1, 1 };
256static const int sub_half_carry_table[] = { 0, 1, 1, 1, 0, 0, 0, 1 };
257
258
259void i8080::reset()
260{
261 C_FLAG = 0;
262 S_FLAG = 0;
263 Z_FLAG = 0;
264 H_FLAG = 0;
265 P_FLAG = 0;
266 UN1_FLAG = 1;
267 UN3_FLAG = 0;
268 UN5_FLAG = 0;
269
270 PC = 0xF800;
271}
272
273
274void i8080::store_flags()
275{
276 if (S_FLAG) F |= F_NEG; else F &= ~F_NEG;
277 if (Z_FLAG) F |= F_ZERO; else F &= ~F_ZERO;
278 if (H_FLAG) F |= F_HCARRY; else F &= ~F_HCARRY;
279 if (P_FLAG) F |= F_PARITY; else F &= ~F_PARITY;
280 if (C_FLAG) F |= F_CARRY; else F &= ~F_CARRY;
281 F |= F_UN1; // UN1_FLAG is always 1.
282 F &= ~F_UN3; // UN3_FLAG is always 0.
283 F &= ~F_UN5; // UN5_FLAG is always 0.
284}
285
286
287void i8080::retrieve_flags()
288{
289 S_FLAG = F & F_NEG ? 1 : 0;
290 Z_FLAG = F & F_ZERO ? 1 : 0;
291 H_FLAG = F & F_HCARRY ? 1 : 0;
292 P_FLAG = F & F_PARITY ? 1 : 0;
293 C_FLAG = F & F_CARRY ? 1 : 0;
294}
295
296
297int i8080::step()
298{
299 int opcode = RD_BYTE(PC++);
300
301 int cpu_cycles;
302
303 switch (opcode) {
304 case 0x00: /* nop */
305 // Undocumented NOP.
306 case 0x08: /* nop */
307 case 0x10: /* nop */
308 case 0x18: /* nop */
309 case 0x20: /* nop */
310 case 0x28: /* nop */
311 case 0x30: /* nop */
312 case 0x38: /* nop */
313 cpu_cycles = 4;
314 break;
315
316 case 0x01: /* lxi b, data16 */
317 cpu_cycles = 10;
318 BC = RD_WORD(PC);
319 PC += 2;
320 break;
321
322 case 0x02: /* stax b */
323 cpu_cycles = 7;
324 WR_BYTE(BC, A);
325 break;
326
327 case 0x03: /* inx b */
328 cpu_cycles = 5;
329 BC++;
330 break;
331
332 case 0x04: /* inr b */
333 cpu_cycles = 5;
334 INR(B);
335 break;
336
337 case 0x05: /* dcr b */
338 cpu_cycles = 5;
339 DCR(B);
340 break;
341
342 case 0x06: /* mvi b, data8 */
343 cpu_cycles = 7;
344 B = RD_BYTE(PC++);
345 break;
346
347 case 0x07: /* rlc */
348 cpu_cycles = 4;
349 C_FLAG = ((A & 0x80) != 0);
350 A = (A << 1) | C_FLAG;
351 break;
352
353 case 0x09: /* dad b */
354 cpu_cycles = 10;
355 DAD(BC);
356 break;
357
358 case 0x0A: /* ldax b */
359 cpu_cycles = 7;
360 A = RD_BYTE(BC);
361 break;
362
363 case 0x0B: /* dcx b */
364 cpu_cycles = 5;
365 BC--;
366 break;
367
368 case 0x0C: /* inr c */
369 cpu_cycles = 5;
370 INR(C);
371 break;
372
373 case 0x0D: /* dcr c */
374 cpu_cycles = 5;
375 DCR(C);
376 break;
377
378 case 0x0E: /* mvi c, data8 */
379 cpu_cycles = 7;
380 C = RD_BYTE(PC++);
381 break;
382
383 case 0x0F: /* rrc */
384 cpu_cycles = 4;
385 C_FLAG = A & 0x01;
386 A = (A >> 1) | (C_FLAG << 7);
387 break;
388
389 case 0x11: /* lxi d, data16 */
390 cpu_cycles = 10;
391 DE = RD_WORD(PC);
392 PC += 2;
393 break;
394
395 case 0x12: /* stax d */
396 cpu_cycles = 7;
397 WR_BYTE(DE, A);
398 break;
399
400 case 0x13: /* inx d */
401 cpu_cycles = 5;
402 DE++;
403 break;
404
405 case 0x14: /* inr d */
406 cpu_cycles = 5;
407 INR(D);
408 break;
409
410 case 0x15: /* dcr d */
411 cpu_cycles = 5;
412 DCR(D);
413 break;
414
415 case 0x16: /* mvi d, data8 */
416 cpu_cycles = 7;
417 D = RD_BYTE(PC++);
418 break;
419
420 case 0x17: /* ral */
421 cpu_cycles = 4;
422 work8 = (uint8_t)C_FLAG;
423 C_FLAG = ((A & 0x80) != 0);
424 A = (A << 1) | work8;
425 break;
426
427 case 0x19: /* dad d */
428 cpu_cycles = 10;
429 DAD(DE);
430 break;
431
432 case 0x1A: /* ldax d */
433 cpu_cycles = 7;
434 A = RD_BYTE(DE);
435 break;
436
437 case 0x1B: /* dcx d */
438 cpu_cycles = 5;
439 DE--;
440 break;
441
442 case 0x1C: /* inr e */
443 cpu_cycles = 5;
444 INR(E);
445 break;
446
447 case 0x1D: /* dcr e */
448 cpu_cycles = 5;
449 DCR(E);
450 break;
451
452 case 0x1E: /* mvi e, data8 */
453 cpu_cycles = 7;
454 E = RD_BYTE(PC++);
455 break;
456
457 case 0x1F: /* rar */
458 cpu_cycles = 4;
459 work8 = (uint8_t)C_FLAG;
460 C_FLAG = A & 0x01;
461 A = (A >> 1) | (work8 << 7);
462 break;
463
464 case 0x21: /* lxi h, data16 */
465 cpu_cycles = 10;
466 HL = RD_WORD(PC);
467 PC += 2;
468 break;
469
470 case 0x22: /* shld addr */
471 cpu_cycles = 16;
472 WR_WORD(RD_WORD(PC), HL);
473 PC += 2;
474 break;
475
476 case 0x23: /* inx h */
477 cpu_cycles = 5;
478 HL++;
479 break;
480
481 case 0x24: /* inr h */
482 cpu_cycles = 5;
483 INR(H);
484 break;
485
486 case 0x25: /* dcr h */
487 cpu_cycles = 5;
488 DCR(H);
489 break;
490
491 case 0x26: /* mvi h, data8 */
492 cpu_cycles = 7;
493 H = RD_BYTE(PC++);
494 break;
495
496 case 0x27: /* daa */
497 cpu_cycles = 4;
498 carry = (uint8_t)C_FLAG;
499 add = 0;
500 if (H_FLAG || (A & 0x0f) > 9) {
501 add = 0x06;
502 }
503 if (C_FLAG || (A >> 4) > 9 || ((A >> 4) >= 9 && (A & 0x0f) > 9)) {
504 add |= 0x60;
505 carry = 1;
506 }
507 ADD(add);
508 P_FLAG = PARITY(A);
509 C_FLAG = carry;
510 break;
511
512 case 0x29: /* dad hl */
513 cpu_cycles = 10;
514 DAD(HL);
515 break;
516
517 case 0x2A: /* ldhl addr */
518 cpu_cycles = 16;
519 HL = RD_WORD(RD_WORD(PC));
520 PC += 2;
521 break;
522
523 case 0x2B: /* dcx h */
524 cpu_cycles = 5;
525 HL--;
526 break;
527
528 case 0x2C: /* inr l */
529 cpu_cycles = 5;
530 INR(L);
531 break;
532
533 case 0x2D: /* dcr l */
534 cpu_cycles = 5;
535 DCR(L);
536 break;
537
538 case 0x2E: /* mvi l, data8 */
539 cpu_cycles = 7;
540 L = RD_BYTE(PC++);
541 break;
542
543 case 0x2F: /* cma */
544 cpu_cycles = 4;
545 A ^= 0xff;
546 break;
547
548 case 0x31: /* lxi sp, data16 */
549 cpu_cycles = 10;
550 SP = RD_WORD(PC);
551 PC += 2;
552 break;
553
554 case 0x32: /* sta addr */
555 cpu_cycles = 13;
556 WR_BYTE(RD_WORD(PC), A);
557 PC += 2;
558 break;
559
560 case 0x33: /* inx sp */
561 cpu_cycles = 5;
562 SP++;
563 break;
564
565 case 0x34: /* inr m */
566 cpu_cycles = 10;
567 work8 = RD_BYTE(HL);
568 INR(work8);
569 WR_BYTE(HL, work8);
570 break;
571
572 case 0x35: /* dcr m */
573 cpu_cycles = 10;
574 work8 = RD_BYTE(HL);
575 DCR(work8);
576 WR_BYTE(HL, work8);
577 break;
578
579 case 0x36: /* mvi m, data8 */
580 cpu_cycles = 10;
581 WR_BYTE(HL, RD_BYTE(PC++));
582 break;
583
584 case 0x37: /* stc */
585 cpu_cycles = 4;
586 SET(C_FLAG);
587 break;
588
589 case 0x39: /* dad sp */
590 cpu_cycles = 10;
591 DAD(SP);
592 break;
593
594 case 0x3A: /* lda addr */
595 cpu_cycles = 13;
596 A = RD_BYTE(RD_WORD(PC));
597 PC += 2;
598 break;
599
600 case 0x3B: /* dcx sp */
601 cpu_cycles = 5;
602 SP--;
603 break;
604
605 case 0x3C: /* inr a */
606 cpu_cycles = 5;
607 INR(A);
608 break;
609
610 case 0x3D: /* dcr a */
611 cpu_cycles = 5;
612 DCR(A);
613 break;
614
615 case 0x3E: /* mvi a, data8 */
616 cpu_cycles = 7;
617 A = RD_BYTE(PC++);
618 break;
619
620 case 0x3F: /* cmc */
621 cpu_cycles = 4;
622 CPL(C_FLAG);
623 break;
624
625 case 0x40: /* mov b, b */
626 cpu_cycles = 4;
627 break;
628
629 case 0x41: /* mov b, c */
630 cpu_cycles = 5;
631 B = C;
632 break;
633
634 case 0x42: /* mov b, d */
635 cpu_cycles = 5;
636 B = D;
637 break;
638
639 case 0x43: /* mov b, e */
640 cpu_cycles = 5;
641 B = E;
642 break;
643
644 case 0x44: /* mov b, h */
645 cpu_cycles = 5;
646 B = H;
647 break;
648
649 case 0x45: /* mov b, l */
650 cpu_cycles = 5;
651 B = L;
652 break;
653
654 case 0x46: /* mov b, m */
655 cpu_cycles = 7;
656 B = RD_BYTE(HL);
657 break;
658
659 case 0x47: /* mov b, a */
660 cpu_cycles = 5;
661 B = A;
662 break;
663
664 case 0x48: /* mov c, b */
665 cpu_cycles = 5;
666 C = B;
667 break;
668
669 case 0x49: /* mov c, c */
670 cpu_cycles = 5;
671 break;
672
673 case 0x4A: /* mov c, d */
674 cpu_cycles = 5;
675 C = D;
676 break;
677
678 case 0x4B: /* mov c, e */
679 cpu_cycles = 5;
680 C = E;
681 break;
682
683 case 0x4C: /* mov c, h */
684 cpu_cycles = 5;
685 C = H;
686 break;
687
688 case 0x4D: /* mov c, l */
689 cpu_cycles = 5;
690 C = L;
691 break;
692
693 case 0x4E: /* mov c, m */
694 cpu_cycles = 7;
695 C = RD_BYTE(HL);
696 break;
697
698 case 0x4F: /* mov c, a */
699 cpu_cycles = 5;
700 C = A;
701 break;
702
703 case 0x50: /* mov d, b */
704 cpu_cycles = 5;
705 D = B;
706 break;
707
708 case 0x51: /* mov d, c */
709 cpu_cycles = 5;
710 D = C;
711 break;
712
713 case 0x52: /* mov d, d */
714 cpu_cycles = 5;
715 break;
716
717 case 0x53: /* mov d, e */
718 cpu_cycles = 5;
719 D = E;
720 break;
721
722 case 0x54: /* mov d, h */
723 cpu_cycles = 5;
724 D = H;
725 break;
726
727 case 0x55: /* mov d, l */
728 cpu_cycles = 5;
729 D = L;
730 break;
731
732 case 0x56: /* mov d, m */
733 cpu_cycles = 7;
734 D = RD_BYTE(HL);
735 break;
736
737 case 0x57: /* mov d, a */
738 cpu_cycles = 5;
739 D = A;
740 break;
741
742 case 0x58: /* mov e, b */
743 cpu_cycles = 5;
744 E = B;
745 break;
746
747 case 0x59: /* mov e, c */
748 cpu_cycles = 5;
749 E = C;
750 break;
751
752 case 0x5A: /* mov e, d */
753 cpu_cycles = 5;
754 E = D;
755 break;
756
757 case 0x5B: /* mov e, e */
758 cpu_cycles = 5;
759 break;
760
761 case 0x5C: /* mov c, h */
762 cpu_cycles = 5;
763 E = H;
764 break;
765
766 case 0x5D: /* mov c, l */
767 cpu_cycles = 5;
768 E = L;
769 break;
770
771 case 0x5E: /* mov c, m */
772 cpu_cycles = 7;
773 E = RD_BYTE(HL);
774 break;
775
776 case 0x5F: /* mov c, a */
777 cpu_cycles = 5;
778 E = A;
779 break;
780
781 case 0x60: /* mov h, b */
782 cpu_cycles = 5;
783 H = B;
784 break;
785
786 case 0x61: /* mov h, c */
787 cpu_cycles = 5;
788 H = C;
789 break;
790
791 case 0x62: /* mov h, d */
792 cpu_cycles = 5;
793 H = D;
794 break;
795
796 case 0x63: /* mov h, e */
797 cpu_cycles = 5;
798 H = E;
799 break;
800
801 case 0x64: /* mov h, h */
802 cpu_cycles = 5;
803 break;
804
805 case 0x65: /* mov h, l */
806 cpu_cycles = 5;
807 H = L;
808 break;
809
810 case 0x66: /* mov h, m */
811 cpu_cycles = 7;
812 H = RD_BYTE(HL);
813 break;
814
815 case 0x67: /* mov h, a */
816 cpu_cycles = 5;
817 H = A;
818 break;
819
820 case 0x68: /* mov l, b */
821 cpu_cycles = 5;
822 L = B;
823 break;
824
825 case 0x69: /* mov l, c */
826 cpu_cycles = 5;
827 L = C;
828 break;
829
830 case 0x6A: /* mov l, d */
831 cpu_cycles = 5;
832 L = D;
833 break;
834
835 case 0x6B: /* mov l, e */
836 cpu_cycles = 5;
837 L = E;
838 break;
839
840 case 0x6C: /* mov l, h */
841 cpu_cycles = 5;
842 L = H;
843 break;
844
845 case 0x6D: /* mov l, l */
846 cpu_cycles = 5;
847 break;
848
849 case 0x6E: /* mov l, m */
850 cpu_cycles = 7;
851 L = RD_BYTE(HL);
852 break;
853
854 case 0x6F: /* mov l, a */
855 cpu_cycles = 5;
856 L = A;
857 break;
858
859 case 0x70: /* mov m, b */
860 cpu_cycles = 7;
861 WR_BYTE(HL, B);
862 break;
863
864 case 0x71: /* mov m, c */
865 cpu_cycles = 7;
866 WR_BYTE(HL, C);
867 break;
868
869 case 0x72: /* mov m, d */
870 cpu_cycles = 7;
871 WR_BYTE(HL, D);
872 break;
873
874 case 0x73: /* mov m, e */
875 cpu_cycles = 7;
876 WR_BYTE(HL, E);
877 break;
878
879 case 0x74: /* mov m, h */
880 cpu_cycles = 7;
881 WR_BYTE(HL, H);
882 break;
883
884 case 0x75: /* mov m, l */
885 cpu_cycles = 7;
886 WR_BYTE(HL, L);
887 break;
888
889 case 0x76: /* hlt */
890 cpu_cycles = 4;
891 PC--;
892 break;
893
894 case 0x77: /* mov m, a */
895 cpu_cycles = 7;
896 WR_BYTE(HL, A);
897 break;
898
899 case 0x78: /* mov a, b */
900 cpu_cycles = 5;
901 A = B;
902 break;
903
904 case 0x79: /* mov a, c */
905 cpu_cycles = 5;
906 A = C;
907 break;
908
909 case 0x7A: /* mov a, d */
910 cpu_cycles = 5;
911 A = D;
912 break;
913
914 case 0x7B: /* mov a, e */
915 cpu_cycles = 5;
916 A = E;
917 break;
918
919 case 0x7C: /* mov a, h */
920 cpu_cycles = 5;
921 A = H;
922 break;
923
924 case 0x7D: /* mov a, l */
925 cpu_cycles = 5;
926 A = L;
927 break;
928
929 case 0x7E: /* mov a, m */
930 cpu_cycles = 7;
931 A = RD_BYTE(HL);
932 break;
933
934 case 0x7F: /* mov a, a */
935 cpu_cycles = 5;
936 break;
937
938 case 0x80: /* add b */
939 cpu_cycles = 4;
940 ADD(B);
941 break;
942
943 case 0x81: /* add c */
944 cpu_cycles = 4;
945 ADD(C);
946 break;
947
948 case 0x82: /* add d */
949 cpu_cycles = 4;
950 ADD(D);
951 break;
952
953 case 0x83: /* add e */
954 cpu_cycles = 4;
955 ADD(E);
956 break;
957
958 case 0x84: /* add h */
959 cpu_cycles = 4;
960 ADD(H);
961 break;
962
963 case 0x85: /* add l */
964 cpu_cycles = 4;
965 ADD(L);
966 break;
967
968 case 0x86: /* add m */
969 cpu_cycles = 7;
970 work8 = RD_BYTE(HL);
971 ADD(work8);
972 break;
973
974 case 0x87: /* add a */
975 cpu_cycles = 4;
976 ADD(A);
977 break;
978
979 case 0x88: /* adc b */
980 cpu_cycles = 4;
981 ADC(B);
982 break;
983
984 case 0x89: /* adc c */
985 cpu_cycles = 4;
986 ADC(C);
987 break;
988
989 case 0x8A: /* adc d */
990 cpu_cycles = 4;
991 ADC(D);
992 break;
993
994 case 0x8B: /* adc e */
995 cpu_cycles = 4;
996 ADC(E);
997 break;
998
999 case 0x8C: /* adc h */
1000 cpu_cycles = 4;
1001 ADC(H);
1002 break;
1003
1004 case 0x8D: /* adc l */
1005 cpu_cycles = 4;
1006 ADC(L);
1007 break;
1008
1009 case 0x8E: /* adc m */
1010 cpu_cycles = 7;
1011 work8 = RD_BYTE(HL);
1012 ADC(work8);
1013 break;
1014
1015 case 0x8F: /* adc a */
1016 cpu_cycles = 4;
1017 ADC(A);
1018 break;
1019
1020 case 0x90: /* sub b */
1021 cpu_cycles = 4;
1022 SUB(B);
1023 break;
1024
1025 case 0x91: /* sub c */
1026 cpu_cycles = 4;
1027 SUB(C);
1028 break;
1029
1030 case 0x92: /* sub d */
1031 cpu_cycles = 4;
1032 SUB(D);
1033 break;
1034
1035 case 0x93: /* sub e */
1036 cpu_cycles = 4;
1037 SUB(E);
1038 break;
1039
1040 case 0x94: /* sub h */
1041 cpu_cycles = 4;
1042 SUB(H);
1043 break;
1044
1045 case 0x95: /* sub l */
1046 cpu_cycles = 4;
1047 SUB(L);
1048 break;
1049
1050 case 0x96: /* sub m */
1051 cpu_cycles = 7;
1052 work8 = RD_BYTE(HL);
1053 SUB(work8);
1054 break;
1055
1056 case 0x97: /* sub a */
1057 cpu_cycles = 4;
1058 SUB(A);
1059 break;
1060
1061 case 0x98: /* sbb b */
1062 cpu_cycles = 4;
1063 SBB(B);
1064 break;
1065
1066 case 0x99: /* sbb c */
1067 cpu_cycles = 4;
1068 SBB(C);
1069 break;
1070
1071 case 0x9A: /* sbb d */
1072 cpu_cycles = 4;
1073 SBB(D);
1074 break;
1075
1076 case 0x9B: /* sbb e */
1077 cpu_cycles = 4;
1078 SBB(E);
1079 break;
1080
1081 case 0x9C: /* sbb h */
1082 cpu_cycles = 4;
1083 SBB(H);
1084 break;
1085
1086 case 0x9D: /* sbb l */
1087 cpu_cycles = 4;
1088 SBB(L);
1089 break;
1090
1091 case 0x9E: /* sbb m */
1092 cpu_cycles = 7;
1093 work8 = RD_BYTE(HL);
1094 SBB(work8);
1095 break;
1096
1097 case 0x9F: /* sbb a */
1098 cpu_cycles = 4;
1099 SBB(A);
1100 break;
1101
1102 case 0xA0: /* ana b */
1103 cpu_cycles = 4;
1104 ANA(B);
1105 break;
1106
1107 case 0xA1: /* ana c */
1108 cpu_cycles = 4;
1109 ANA(C);
1110 break;
1111
1112 case 0xA2: /* ana d */
1113 cpu_cycles = 4;
1114 ANA(D);
1115 break;
1116
1117 case 0xA3: /* ana e */
1118 cpu_cycles = 4;
1119 ANA(E);
1120 break;
1121
1122 case 0xA4: /* ana h */
1123 cpu_cycles = 4;
1124 ANA(H);
1125 break;
1126
1127 case 0xA5: /* ana l */
1128 cpu_cycles = 4;
1129 ANA(L);
1130 break;
1131
1132 case 0xA6: /* ana m */
1133 cpu_cycles = 7;
1134 work8 = RD_BYTE(HL);
1135 ANA(work8);
1136 break;
1137
1138 case 0xA7: /* ana a */
1139 cpu_cycles = 4;
1140 ANA(A);
1141 break;
1142
1143 case 0xA8: /* xra b */
1144 cpu_cycles = 4;
1145 XRA(B);
1146 break;
1147
1148 case 0xA9: /* xra c */
1149 cpu_cycles = 4;
1150 XRA(C);
1151 break;
1152
1153 case 0xAA: /* xra d */
1154 cpu_cycles = 4;
1155 XRA(D);
1156 break;
1157
1158 case 0xAB: /* xra e */
1159 cpu_cycles = 4;
1160 XRA(E);
1161 break;
1162
1163 case 0xAC: /* xra h */
1164 cpu_cycles = 4;
1165 XRA(H);
1166 break;
1167
1168 case 0xAD: /* xra l */
1169 cpu_cycles = 4;
1170 XRA(L);
1171 break;
1172
1173 case 0xAE: /* xra m */
1174 cpu_cycles = 7;
1175 work8 = RD_BYTE(HL);
1176 XRA(work8);
1177 break;
1178
1179 case 0xAF: /* xra a */
1180 cpu_cycles = 4;
1181 XRA(A);
1182 break;
1183
1184 case 0xB0: /* ora b */
1185 cpu_cycles = 4;
1186 ORA(B);
1187 break;
1188
1189 case 0xB1: /* ora c */
1190 cpu_cycles = 4;
1191 ORA(C);
1192 break;
1193
1194 case 0xB2: /* ora d */
1195 cpu_cycles = 4;
1196 ORA(D);
1197 break;
1198
1199 case 0xB3: /* ora e */
1200 cpu_cycles = 4;
1201 ORA(E);
1202 break;
1203
1204 case 0xB4: /* ora h */
1205 cpu_cycles = 4;
1206 ORA(H);
1207 break;
1208
1209 case 0xB5: /* ora l */
1210 cpu_cycles = 4;
1211 ORA(L);
1212 break;
1213
1214 case 0xB6: /* ora m */
1215 cpu_cycles = 7;
1216 work8 = RD_BYTE(HL);
1217 ORA(work8);
1218 break;
1219
1220 case 0xB7: /* ora a */
1221 cpu_cycles = 4;
1222 ORA(A);
1223 break;
1224
1225 case 0xB8: /* cmp b */
1226 cpu_cycles = 4;
1227 CMP(B);
1228 break;
1229
1230 case 0xB9: /* cmp c */
1231 cpu_cycles = 4;
1232 CMP(C);
1233 break;
1234
1235 case 0xBA: /* cmp d */
1236 cpu_cycles = 4;
1237 CMP(D);
1238 break;
1239
1240 case 0xBB: /* cmp e */
1241 cpu_cycles = 4;
1242 CMP(E);
1243 break;
1244
1245 case 0xBC: /* cmp h */
1246 cpu_cycles = 4;
1247 CMP(H);
1248 break;
1249
1250 case 0xBD: /* cmp l */
1251 cpu_cycles = 4;
1252 CMP(L);
1253 break;
1254
1255 case 0xBE: /* cmp m */
1256 cpu_cycles = 7;
1257 work8 = RD_BYTE(HL);
1258 CMP(work8);
1259 break;
1260
1261 case 0xBF: /* cmp a */
1262 cpu_cycles = 4;
1263 CMP(A);
1264 break;
1265
1266 case 0xC0: /* rnz */
1267 cpu_cycles = 5;
1268 if (!TST(Z_FLAG)) {
1269 cpu_cycles = 11;
1270 POP(PC);
1271 }
1272 break;
1273
1274 case 0xC1: /* pop b */
1275 cpu_cycles = 11;
1276 POP(BC);
1277 break;
1278
1279 case 0xC2: /* jnz addr */
1280 cpu_cycles = 10;
1281 if (!TST(Z_FLAG)) {
1282 PC = RD_WORD(PC);
1283 }
1284 else {
1285 PC += 2;
1286 }
1287 break;
1288
1289 case 0xC3: /* jmp addr */
1290 case 0xCB: /* jmp addr, undocumented */
1291 cpu_cycles = 10;
1292 PC = RD_WORD(PC);
1293 break;
1294
1295 case 0xC4: /* cnz addr */
1296 if (!TST(Z_FLAG)) {
1297 cpu_cycles = 17;
1298 CALL;
1299 } else {
1300 cpu_cycles = 11;
1301 PC += 2;
1302 }
1303 break;
1304
1305 case 0xC5: /* push b */
1306 cpu_cycles = 11;
1307 PUSH(BC);
1308 break;
1309
1310 case 0xC6: /* adi data8 */
1311 cpu_cycles = 7;
1312 work8 = RD_BYTE(PC++);
1313 ADD(work8);
1314 break;
1315
1316 case 0xC7: /* rst 0 */
1317 cpu_cycles = 11;
1318 RST(0x0000);
1319 break;
1320
1321 case 0xC8: /* rz */
1322 cpu_cycles = 5;
1323 if (TST(Z_FLAG)) {
1324 cpu_cycles = 11;
1325 POP(PC);
1326 }
1327 break;
1328
1329 case 0xC9: /* ret */
1330 case 0xD9: /* ret, undocumented */
1331 cpu_cycles = 10;
1332 POP(PC);
1333 break;
1334
1335 case 0xCA: /* jz addr */
1336 cpu_cycles = 10;
1337 if (TST(Z_FLAG)) {
1338 PC = RD_WORD(PC);
1339 } else {
1340 PC += 2;
1341 }
1342 break;
1343
1344 case 0xCC: /* cz addr */
1345 if (TST(Z_FLAG)) {
1346 cpu_cycles = 17;
1347 CALL;
1348 } else {
1349 cpu_cycles = 11;
1350 PC += 2;
1351 }
1352 break;
1353
1354 case 0xCD: /* call addr */
1355 case 0xDD: /* call, undocumented */
1356 case 0xED:
1357 case 0xFD:
1358 cpu_cycles = 17;
1359 CALL;
1360 break;
1361
1362 case 0xCE: /* aci data8 */
1363 cpu_cycles = 7;
1364 work8 = RD_BYTE(PC++);
1365 ADC(work8);
1366 break;
1367
1368 case 0xCF: /* rst 1 */
1369 cpu_cycles = 11;
1370 RST(0x0008);
1371 break;
1372
1373 case 0xD0: /* rnc */
1374 cpu_cycles = 5;
1375 if (!TST(C_FLAG)) {
1376 cpu_cycles = 11;
1377 POP(PC);
1378 }
1379 break;
1380
1381 case 0xD1: /* pop d */
1382 cpu_cycles = 11;
1383 POP(DE);
1384 break;
1385
1386 case 0xD2: /* jnc addr */
1387 cpu_cycles = 10;
1388 if (!TST(C_FLAG)) {
1389 PC = RD_WORD(PC);
1390 } else {
1391 PC += 2;
1392 }
1393 break;
1394
1395 case 0xD3: /* out port8 */
1396 cpu_cycles = 10;
1397 m_writeIO(m_context, RD_BYTE(PC++), A);
1398 break;
1399
1400 case 0xD4: /* cnc addr */
1401 if (!TST(C_FLAG)) {
1402 cpu_cycles = 17;
1403 CALL;
1404 } else {
1405 cpu_cycles = 11;
1406 PC += 2;
1407 }
1408 break;
1409
1410 case 0xD5: /* push d */
1411 cpu_cycles = 11;
1412 PUSH(DE);
1413 break;
1414
1415 case 0xD6: /* sui data8 */
1416 cpu_cycles = 7;
1417 work8 = RD_BYTE(PC++);
1418 SUB(work8);
1419 break;
1420
1421 case 0xD7: /* rst 2 */
1422 cpu_cycles = 11;
1423 RST(0x0010);
1424 break;
1425
1426 case 0xD8: /* rc */
1427 cpu_cycles = 5;
1428 if (TST(C_FLAG)) {
1429 cpu_cycles = 11;
1430 POP(PC);
1431 }
1432 break;
1433
1434 case 0xDA: /* jc addr */
1435 cpu_cycles = 10;
1436 if (TST(C_FLAG)) {
1437 PC = RD_WORD(PC);
1438 } else {
1439 PC += 2;
1440 }
1441 break;
1442
1443 case 0xDB: /* in port8 */
1444 cpu_cycles = 10;
1445 A = m_readIO(m_context, RD_BYTE(PC++));
1446 break;
1447
1448 case 0xDC: /* cc addr */
1449 if (TST(C_FLAG)) {
1450 cpu_cycles = 17;
1451 CALL;
1452 } else {
1453 cpu_cycles = 11;
1454 PC += 2;
1455 }
1456 break;
1457
1458 case 0xDE: /* sbi data8 */
1459 cpu_cycles = 7;
1460 work8 = RD_BYTE(PC++);
1461 SBB(work8);
1462 break;
1463
1464 case 0xDF: /* rst 3 */
1465 cpu_cycles = 11;
1466 RST(0x0018);
1467 break;
1468
1469 case 0xE0: /* rpo */
1470 cpu_cycles = 5;
1471 if (!TST(P_FLAG)) {
1472 cpu_cycles = 11;
1473 POP(PC);
1474 }
1475 break;
1476
1477 case 0xE1: /* pop h */
1478 cpu_cycles = 11;
1479 POP(HL);
1480 break;
1481
1482 case 0xE2: /* jpo addr */
1483 cpu_cycles = 10;
1484 if (!TST(P_FLAG)) {
1485 PC = RD_WORD(PC);
1486 }
1487 else {
1488 PC += 2;
1489 }
1490 break;
1491
1492 case 0xE3: /* xthl */
1493 cpu_cycles = 18;
1494 work16 = RD_WORD(SP);
1495 WR_WORD(SP, HL);
1496 HL = work16;
1497 break;
1498
1499 case 0xE4: /* cpo addr */
1500 if (!TST(P_FLAG)) {
1501 cpu_cycles = 17;
1502 CALL;
1503 } else {
1504 cpu_cycles = 11;
1505 PC += 2;
1506 }
1507 break;
1508
1509 case 0xE5: /* push h */
1510 cpu_cycles = 11;
1511 PUSH(HL);
1512 break;
1513
1514 case 0xE6: /* ani data8 */
1515 cpu_cycles = 7;
1516 work8 = RD_BYTE(PC++);
1517 ANA(work8);
1518 break;
1519
1520 case 0xE7: /* rst 4 */
1521 cpu_cycles = 11;
1522 RST(0x0020);
1523 break;
1524
1525 case 0xE8: /* rpe */
1526 cpu_cycles = 5;
1527 if (TST(P_FLAG)) {
1528 cpu_cycles = 11;
1529 POP(PC);
1530 }
1531 break;
1532
1533 case 0xE9: /* pchl */
1534 cpu_cycles = 5;
1535 PC = HL;
1536 break;
1537
1538 case 0xEA: /* jpe addr */
1539 cpu_cycles = 10;
1540 if (TST(P_FLAG)) {
1541 PC = RD_WORD(PC);
1542 } else {
1543 PC += 2;
1544 }
1545 break;
1546
1547 case 0xEB: /* xchg */
1548 cpu_cycles = 4;
1549 work16 = DE;
1550 DE = HL;
1551 HL = work16;
1552 break;
1553
1554 case 0xEC: /* cpe addr */
1555 if (TST(P_FLAG)) {
1556 cpu_cycles = 17;
1557 CALL;
1558 } else {
1559 cpu_cycles = 11;
1560 PC += 2;
1561 }
1562 break;
1563
1564 case 0xEE: /* xri data8 */
1565 cpu_cycles = 7;
1566 work8 = RD_BYTE(PC++);
1567 XRA(work8);
1568 break;
1569
1570 case 0xEF: /* rst 5 */
1571 cpu_cycles = 11;
1572 RST(0x0028);
1573 break;
1574
1575 case 0xF0: /* rp */
1576 cpu_cycles = 5;
1577 if (!TST(S_FLAG)) {
1578 cpu_cycles = 11;
1579 POP(PC);
1580 }
1581 break;
1582
1583 case 0xF1: /* pop psw */
1584 cpu_cycles = 10;
1585 POP(AF);
1586 retrieve_flags();
1587 break;
1588
1589 case 0xF2: /* jp addr */
1590 cpu_cycles = 10;
1591 if (!TST(S_FLAG)) {
1592 PC = RD_WORD(PC);
1593 } else {
1594 PC += 2;
1595 }
1596 break;
1597
1598 case 0xF3: /* di */
1599 cpu_cycles = 4;
1600 IFF = 0;
1601 break;
1602
1603 case 0xF4: /* cp addr */
1604 if (!TST(S_FLAG)) {
1605 cpu_cycles = 17;
1606 CALL;
1607 } else {
1608 cpu_cycles = 11;
1609 PC += 2;
1610 }
1611 break;
1612
1613 case 0xF5: /* push psw */
1614 cpu_cycles = 11;
1615 store_flags();
1616 PUSH(AF);
1617 break;
1618
1619 case 0xF6: /* ori data8 */
1620 cpu_cycles = 7;
1621 work8 = RD_BYTE(PC++);
1622 ORA(work8);
1623 break;
1624
1625 case 0xF7: /* rst 6 */
1626 cpu_cycles = 11;
1627 RST(0x0030);
1628 break;
1629
1630 case 0xF8: /* rm */
1631 cpu_cycles = 5;
1632 if (TST(S_FLAG)) {
1633 cpu_cycles = 11;
1634 POP(PC);
1635 }
1636 break;
1637
1638 case 0xF9: /* sphl */
1639 cpu_cycles = 5;
1640 SP = HL;
1641 break;
1642
1643 case 0xFA: /* jm addr */
1644 cpu_cycles = 10;
1645 if (TST(S_FLAG)) {
1646 PC = RD_WORD(PC);
1647 } else {
1648 PC += 2;
1649 }
1650 break;
1651
1652 case 0xFB: /* ei */
1653 cpu_cycles = 4;
1654 IFF = 1;
1655 break;
1656
1657 case 0xFC: /* cm addr */
1658 if (TST(S_FLAG)) {
1659 cpu_cycles = 17;
1660 CALL;
1661 } else {
1662 cpu_cycles = 11;
1663 PC += 2;
1664 }
1665 break;
1666
1667 case 0xFE: /* cpi data8 */
1668 cpu_cycles = 7;
1669 work8 = RD_BYTE(PC++);
1670 CMP(work8);
1671 break;
1672
1673 case 0xFF: /* rst 7 */
1674 cpu_cycles = 11;
1675 RST(0x0038);
1676 break;
1677
1678 default:
1679 cpu_cycles = -1; /* Shouldn't be really here. */
1680 break;
1681 }
1682 return cpu_cycles;
1683}
1684
1685
1686
1687}; // fabgl namespace
uint8_t B
This file contains fabgl::i8080 definition.