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 
45 namespace 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 
247 int getParity(int val)
248 {
249  val ^= val >> 4;
250  val &= 0xf;
251  return !((0x6996 >> val) & 1);
252 }
253 
254 
255 static const int half_carry_table[] = { 0, 0, 1, 0, 1, 0, 1, 1 };
256 static const int sub_half_carry_table[] = { 0, 1, 1, 1, 0, 0, 0, 1 };
257 
258 
259 void 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 
274 void 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 
287 void 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 
297 int 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
Definition: canvas.cpp:32
This file contains fabgl::i8080 definition.