- reorganized project directory structure
[z80comp2] / emu / src / cpu.c
1 #include <stdint.h>
2 #include "cpu.h"
3 #include "emu.h"
4
5 enum {
6         FLAGS_C         = 0x01,
7         FLAGS_N         = 0x02,
8         FLAGS_PV        = 0x04,
9         FLAGS_H         = 0x10,
10         FLAGS_Z         = 0x40,
11         FLAGS_S         = 0x80
12 };
13
14 enum {
15         R_B     = 0,
16         R_C     = 1,
17         R_D     = 2,
18         R_E     = 3,
19         R_H     = 4,
20         R_L     = 5,
21         R_INVAL = 6,
22         R_A     = 7
23 };
24
25 #define RRSET2  4
26 enum {
27         RR_BC = 0,
28         RR_DE = 1,
29         RR_HL = 2,
30         RR_SP = 3,
31
32         RR2_BC = RRSET2 | RR_BC,
33         RR2_DE = RRSET2 | RR_DE,
34         RR2_HL = RRSET2 | RR_HL,
35         RR2_AF = RRSET2 | RR_SP
36 };
37
38 enum {
39         PREFIX_ED       = 1,
40         PREFIX_CB       = 2,
41         PREFIX_DD       = 4,
42         PREFIX_FD       = 8
43 };
44
45 enum {
46         ALUOP_ADD       = 0,
47         ALUOP_ADC       = 1,
48         ALUOP_SUB       = 2,
49         ALUOP_SBC       = 3,
50         ALUOP_AND       = 4,
51         ALUOP_XOR       = 5,
52         ALUOP_OR        = 6,
53         ALUOP_CP        = 7
54 };
55
56 enum {
57         CC_NZ   = 0,
58         CC_Z    = 1,
59         CC_NC   = 2,
60         CC_C    = 3,
61         CC_PO   = 4,
62         CC_PE   = 5,
63         CC_P    = 6,
64         CC_M    = 7
65 };
66
67 struct regs8 {
68         uint8_t a, f, b, c, d, e, h, l;
69 };
70 struct regs16 {
71         uint16_t af, bc, de, hl;
72 };
73
74 union genregs {
75         struct regs8 r;
76         struct regs16 rr;
77 };
78
79 struct registers {
80         union genregs g, shadow;        /* general purpose and shadow registers */
81         uint8_t i, r;
82         uint16_t ix, iy, sp, pc;
83         uint8_t iff, imode;
84 };
85
86 static void runop_main(uint8_t op);
87 static void runop_ed(uint8_t op);
88 static void runop_cb(uint8_t op);
89 static void runop_dd(uint8_t op);
90 static void runop_fd(uint8_t op);
91 static void runop_ddcb(uint8_t op);
92 static void runop_fdcb(uint8_t op);
93
94 static void op_load_reg8_reg8(int rdest, int rsrc);
95 static void op_load_reg8_imm8(int rdest, uint8_t imm);
96 static void op_load_reg8_mem(int rdest, uint16_t addr);
97 static void op_store_mem_reg8(uint16_t addr, int rsrc);
98 static void op_store_mem_imm8(uint16_t addr, uint8_t imm);
99 static void op_store_mem_reg16(uint16_t addr, int rsrc);
100 static void op_load_reg16_imm16(int rdest, uint16_t imm);
101 static void op_load_reg16_reg16(int rdest, int rsrc);
102 static void op_exch_mem_reg16(uint16_t addr, int rr);
103 static void op_alu_reg8(int op, int r);
104 static void op_alu_imm8(int op, uint8_t imm);
105 static void op_incdec_reg8(int r, int adj);
106 static void op_incdec_reg16(int r, int adj);
107 static void op_incdec_mem(uint16_t addr, int adj);
108 static void op_add_reg16_reg16(int rdest, int rsrc);
109 static void op_rl_reg8(int r, int width);
110 static void op_rr_reg8(int r, int width);
111 static void op_push_reg16(int r);
112 static void op_pop_reg16(int r);
113 static void op_call(uint16_t addr);
114 static void op_ret(void);
115 static void op_input(int r, uint16_t addr);
116 static void op_output(uint16_t addr, int r);
117
118 static struct registers regs;
119 static int halt;
120
121 static void (*runop[16])(uint8_t op) = {
122         runop_main,             /* 0000: no prefix */
123         runop_ed,               /* 0001: ED prefix */
124         runop_cb,               /* 0010: CB prefix */
125         0,                              /* 0011: CBED invalid */
126         runop_dd,               /* 0100: DD prefix */
127         0,                              /* 0101: DDED invalid */
128         runop_ddcb,             /* 0110: DDCB prefix */
129         0,                              /* 0111: DDCBED invalid */
130         runop_fd,               /* 1000: FD prefix */
131         0,                              /* 1001: FDED invalid */
132         runop_fdcb,             /* 1010: FDCB prefix */
133         0, 0, 0, 0, 0   /* all the rest combinations are invalid */
134 };
135
136 static uint8_t *regptr8[8] = {
137         &regs.g.r.b, &regs.g.r.c,
138         &regs.g.r.d, &regs.g.r.e,
139         &regs.g.r.h, &regs.g.r.l,
140         0, &regs.g.r.a
141 };
142
143 static uint16_t *regptr16[] = {
144         &regs.g.rr.bc,
145         &regs.g.rr.de,
146         &regs.g.rr.hl,
147         &regs.sp,
148
149         &regs.g.rr.bc,
150         &regs.g.rr.de,
151         &regs.g.rr.hl,
152         &regs.g.rr.af
153 };
154
155 void cpu_reset(void)
156 {
157         regs.iff = 0;
158         regs.pc = 0;
159         regs.i = regs.r = 0;
160         regs.imode = 0;
161 }
162
163 static uint8_t fetch_byte(void)
164 {
165         return emu_mem_read(regs.pc++);
166 }
167
168 static uint16_t fetch_imm16(void)
169 {
170         uint16_t lsb = emu_mem_read(regs.pc++);
171         uint16_t msb = emu_mem_read(regs.pc++);
172         return lsb | (msb << 8);
173 }
174
175 static unsigned int prefix_bit(uint8_t op)
176 {
177         switch(op) {
178         case 0xed: return PREFIX_ED;
179         case 0xcb: return PREFIX_CB;
180         case 0xdd: return PREFIX_DD;
181         case 0xfd: return PREFIX_FD;
182         default:
183                 break;
184         }
185         return 0;
186 }
187
188 void cpu_step(void)
189 {
190         unsigned int pbit, prefix = 0;
191         uint8_t op;
192
193         if(halt) return;
194
195         op = fetch_byte();
196         if((pbit = prefix_bit(op))) {
197                 prefix = pbit;
198                 op = fetch_byte();
199
200                 /* only treat the next byte as another prefix if the previous was dd or fd */
201                 if((pbit = prefix_bit(op)) && (prefix == 0xdd || prefix == 0xfd)) {
202                         prefix |= pbit;
203                         op = fetch_byte();
204                 }
205         }
206
207         if(runop[prefix]) {
208                 runop[prefix](op);
209         }
210 }
211
212 static int cond(int cc)
213 {
214         switch(cc) {
215         case CC_NZ: return ~regs.g.r.f & FLAGS_Z;
216         case CC_Z:  return regs.g.r.f & FLAGS_Z;
217         case CC_NC: return ~regs.g.r.f & FLAGS_C;
218         case CC_C:  return regs.g.r.f & FLAGS_C;
219         case CC_PO: return ~regs.g.r.f & FLAGS_PV;
220         case CC_PE: return regs.g.r.f & FLAGS_PV;
221         case CC_P:  return ~regs.g.r.f & FLAGS_S;
222         case CC_M:  return regs.g.r.f & FLAGS_S;
223         default:
224                 break;
225         }
226         return 0;
227 }
228
229 #define ALUOP(x)                (((x) >> 3) & 7)
230 #define DEST_R(x)               (((x) >> 3) & 7)
231 #define OPCOND(x)               (((x) >> 3) & 7)
232 #define SRC_R(x)                ((x) & 7)
233 #define OP_RR(x)                (((x) >> 4) & 3)
234 #define RST_ADDR(x)             ((x) & 0x38)
235
236 #define SWAP_RR(a, b) \
237         do { \
238                 uint16_t tmp = a; \
239                 a = b; \
240                 b = tmp; \
241         } while(0)
242
243 static void runop_main(uint8_t op)
244 {
245         int b67 = op >> 6;
246         uint8_t disp;
247         uint16_t addr;
248
249         switch(op) {
250                 /* 8-bit load group except ld r,r/ld r,imm/ld r,(hl)/ld (hl),r in default */
251         case 0x36:
252                 op_store_mem_imm8(regs.g.rr.hl, fetch_byte());
253                 break;
254         case 0x0a:
255                 op_load_reg8_mem(R_A, regs.g.rr.bc);
256                 break;
257         case 0x1a:
258                 op_load_reg8_mem(R_A, regs.g.rr.de);
259                 break;
260         case 0x3a:
261                 op_load_reg8_mem(R_A, fetch_imm16());
262                 break;
263         case 0x02:
264                 op_store_mem_reg8(regs.g.rr.bc, R_A);
265                 break;
266         case 0x12:
267                 op_store_mem_reg8(regs.g.rr.de, R_A);
268                 break;
269         case 0x32:
270                 op_store_mem_reg8(fetch_imm16(), R_A);
271                 break;
272
273                 /* 16-bit load group */
274         case 0x01:
275         case 0x11:
276         case 0x21:
277         case 0x31:
278                 op_load_reg16_imm16(OP_RR(op), fetch_imm16());
279                 break;
280         case 0x2a:
281                 op_load_reg16_imm16(RR_HL, fetch_imm16());
282                 break;
283         case 0x22:
284                 op_store_mem_reg16(fetch_imm16(), RR_HL);
285                 break;
286         case 0xf9:
287                 op_load_reg16_reg16(RR_SP, RR_HL);
288                 break;
289         case 0xc5:
290         case 0xd5:
291         case 0xe0:
292         case 0xf5:
293                 op_push_reg16(RRSET2 | OP_RR(op));
294                 break;
295         case 0xc1:
296         case 0xd1:
297         case 0xe1:
298         case 0xf1:
299                 op_pop_reg16(RRSET2 | OP_RR(op));
300                 break;
301
302                 /* exchange, block transfer, block search groups */
303         case 0xeb:
304                 SWAP_RR(regs.g.rr.de, regs.g.rr.hl);
305                 break;
306         case 0x08:
307                 SWAP_RR(regs.g.rr.af, regs.shadow.rr.af);
308                 break;
309         case 0xd9:
310                 SWAP_RR(regs.g.rr.bc, regs.shadow.rr.bc);
311                 SWAP_RR(regs.g.rr.de, regs.shadow.rr.de);
312                 SWAP_RR(regs.g.rr.hl, regs.shadow.rr.hl);
313                 break;
314         case 0xe3:
315                 op_exch_mem_reg16(regs.sp, RR_HL);
316                 break;
317
318                 /* general purpose arithmetic and cpu control groups */
319         case 0x27:
320                 break;  /* TODO implement DAA */
321         case 0x2f:      /* cpl a */
322                 regs.g.r.a = ~regs.g.r.a;
323                 regs.g.r.f |= FLAGS_H | FLAGS_N;
324                 break;
325         case 0x3f:      /* ccf */
326                 regs.g.r.f ^= FLAGS_C;
327                 break;
328         case 0x37:      /* scf */
329                 regs.g.r.f |= FLAGS_C;
330         case 0x00:      /* nop */
331                 break;
332         case 0x76:      /* halt */
333                 halt = 1;
334                 break;
335         case 0xf3:      /* di */
336                 regs.iff = 0;
337                 break;
338         case 0xfb:      /* ei */
339                 regs.iff = 1;
340                 break;
341
342                 /* 16-bit arithmetic group */
343         case 0x09:
344         case 0x19:
345         case 0x29:
346         case 0x39:
347                 op_add_reg16_reg16(RR_HL, OP_RR(op));
348                 break;
349         case 0x03:
350         case 0x13:
351         case 0x23:
352         case 0x33:
353                 op_incdec_reg16(OP_RR(op), 1);
354                 break;
355         case 0x0b:
356         case 0x1b:
357         case 0x2b:
358         case 0x3b:
359                 op_incdec_reg16(OP_RR(op), -1);
360                 break;
361
362                 /* rotate and shift group */
363         case 0x07:      /* rlca */
364                 op_rl_reg8(R_A, 8);
365                 break;
366         case 0x17:      /* rla */
367                 op_rl_reg8(R_A, 9);
368                 break;
369         case 0x0f:      /* rrca */
370                 op_rr_reg8(R_A, 8);
371                 break;
372         case 0x1f:      /* rra */
373                 op_rr_reg8(R_A, 9);
374                 break;
375
376                 /* jump group except jp cc, imm16 in default */
377         case 0xc3:      /* jp imm16 */
378                 regs.pc = fetch_imm16();
379                 break;
380         case 0x18:      /* jr imm8 */
381                 regs.pc += fetch_byte();
382                 break;
383         case 0x38:      /* jr c, imm8 */
384                 disp = fetch_byte();
385                 if(cond(CC_C)) regs.pc += disp;
386                 break;
387         case 0x30:      /* jr nc, imm8 */
388                 disp = fetch_byte();
389                 if(cond(CC_NC)) regs.pc += disp;
390                 break;
391         case 0x28:      /* jr z, imm8 */
392                 disp = fetch_byte();
393                 if(cond(CC_Z)) regs.pc += disp;
394                 break;
395         case 0x20:      /* jr nz, imm8 */
396                 disp = fetch_byte();
397                 if(cond(CC_NZ)) regs.pc += disp;
398                 break;
399         case 0xe9:      /* jp (hl) */
400                 regs.pc = regs.g.rr.hl;
401                 break;
402         case 0x10:      /* djnz, imm8 */
403                 disp = fetch_byte();
404                 if(--regs.g.r.b) regs.pc += disp;
405                 break;
406
407                 /* call and return group except call cc,imm16/ret cc,imm16/rst */
408         case 0xcd:
409                 op_call(fetch_imm16());
410                 break;
411         case 0xc9:
412                 op_ret();
413                 break;
414
415                 /* input and output group */
416         case 0xdb:
417                 op_input(R_A, ((uint16_t)regs.g.r.a << 8) | fetch_byte());
418                 break;
419         case 0xd3:
420                 op_output(((uint16_t)regs.g.r.a << 8) | fetch_byte(), R_A);
421                 break;
422
423         default:
424                 switch(b67) {
425                 case 0:
426                         if(SRC_R(op) == 6) {
427                                 op_load_reg8_imm8(DEST_R(op), fetch_byte());
428                         } else if(SRC_R(op) == 4 || SRC_R(op) == 5) {
429                                 int adj = (op & 1) ? -1 : 1;
430                                 if(DEST_R(op) != 6) {
431                                         op_incdec_reg8(DEST_R(op), adj);
432                                 } else {
433                                         op_incdec_mem(regs.g.rr.hl, adj);
434                                 }
435                         }
436                         break;
437
438                 case 1:
439                         if(DEST_R(op) != 6 && SRC_R(op) != 6) {
440                                 op_load_reg8_reg8(DEST_R(op), SRC_R(op));
441                         } else {
442                                 if(SRC_R(op) == 6) {
443                                         op_load_reg8_mem(DEST_R(op), regs.g.rr.hl);
444                                 } else if(DEST_R(op) == 6) {
445                                         op_store_mem_reg8(regs.g.rr.hl, SRC_R(op));
446                                 }
447                         }
448                         break;
449
450                 case 2:
451                         if(SRC_R(op) != 6) {
452                                 op_alu_reg8(ALUOP(op), SRC_R(op));
453                         }
454                         break;
455
456                 case 3:
457                         if(SRC_R(op) == 6) {    /* alu-op a, imm8 */
458                                 op_alu_imm8(ALUOP(op), fetch_byte());
459
460                         } else if(SRC_R(op) == 2) { /* jp cc, imm16 */
461                                 addr = fetch_imm16();
462                                 if(cond(OPCOND(op))) {
463                                         regs.pc = addr;
464                                 }
465
466                         } else if(SRC_R(op) == 4) { /* call cc, imm16 */
467                                 addr = fetch_imm16();
468                                 if(cond(OPCOND(op))) op_call(addr);
469
470                         } else if(SRC_R(op) == 0) { /* ret cc, imm16 */
471                                 addr = fetch_imm16();
472                                 if(cond(OPCOND(op))) op_ret();
473
474                         } else if(SRC_R(op) == 7) { /* rst */
475                                 op_call(RST_ADDR(op));
476                         }
477                         break;
478
479                 default:
480                         break;
481                 }
482
483                 break;  /* treat any unknown opcodes as nops */
484         }
485 }
486
487 static void runop_ed(uint8_t op)
488 {
489 }
490
491 static void runop_cb(uint8_t op)
492 {
493 }
494
495 static void runop_dd(uint8_t op)
496 {
497 }
498
499 static void runop_fd(uint8_t op)
500 {
501 }
502
503 static void runop_ddcb(uint8_t op)
504 {
505 }
506
507 static void runop_fdcb(uint8_t op)
508 {
509 }
510
511 static void set_reg8(int r, uint8_t val)
512 {
513         *regptr8[r] = val;
514 }
515
516 static void set_reg8s(int r, int8_t val)
517 {
518         *regptr8[r] = *(uint8_t*)&val;
519 }
520
521 static uint8_t get_reg8(int r)
522 {
523         return *regptr8[r];
524 }
525
526 static int8_t get_reg8s(int r)
527 {
528         return *(int8_t*)regptr8[r];
529 }
530
531 static void set_reg16(int r, uint16_t val)
532 {
533         *regptr16[r] = val;
534 }
535
536 static void set_reg16s(int r, int16_t val)
537 {
538         *regptr16[r] = *(uint16_t*)&val;
539 }
540
541 static uint16_t get_reg16(int r)
542 {
543         return *regptr16[r];
544 }
545
546 static int16_t get_reg16s(int r)
547 {
548         return *(int16_t*)regptr16[r];
549 }
550
551 static void set_flag(unsigned int flag, int val)
552 {
553         if(val) {
554                 regs.g.r.f |= flag;
555         } else {
556                 regs.g.r.f &= ~flag;
557         }
558 }
559
560 static int parity(int x)
561 {
562         int i, s = 0;
563         for(i=0; i<8; i++) {
564                 s += x & 1;
565                 x >>= 1;
566         }
567         return s & 1;
568 }
569
570 static int overflow(int x)
571 {
572         return x > 127 || x < -128;
573 }
574
575 static int overflow16(int x)
576 {
577         return x > 32767 || x < -32768;
578 }
579
580 static void op_load_reg8_reg8(int rdest, int rsrc)
581 {
582         set_reg8(rdest, get_reg8(rsrc));
583 }
584
585 static void op_load_reg8_imm8(int rdest, uint8_t imm)
586 {
587         set_reg8(rdest, imm);
588 }
589
590 static void op_load_reg8_mem(int rdest, uint16_t addr)
591 {
592         set_reg8(rdest, emu_mem_read(addr));
593 }
594
595 static void op_store_mem_reg8(uint16_t addr, int rsrc)
596 {
597         emu_mem_write(addr, get_reg8(rsrc));
598 }
599
600 static void op_store_mem_imm8(uint16_t addr, uint8_t imm)
601 {
602         emu_mem_write(addr, imm);
603 }
604
605 static void op_store_mem_reg16(uint16_t addr, int rsrc)
606 {
607         uint16_t val = get_reg16(rsrc);
608         emu_mem_write(addr, val);
609         emu_mem_write(addr + 1, val >> 8);
610 }
611
612 static void op_load_reg16_imm16(int rdest, uint16_t imm)
613 {
614         set_reg16(rdest, imm);
615 }
616
617 static void op_load_reg16_reg16(int rdest, int rsrc)
618 {
619         set_reg16(rdest, get_reg16(rsrc));
620 }
621
622 static void op_exch_mem_reg16(uint16_t addr, int rr)
623 {
624         uint16_t val = get_reg16(rr);
625         uint16_t lsb = emu_mem_read(addr);
626         uint16_t msb = emu_mem_read(addr + 1);
627         set_reg16(rr, lsb | (msb << 8));
628         emu_mem_write(addr, val);
629         emu_mem_write(addr + 1, val >> 8);
630 }
631
632 #define CARRY (regs.g.r.f & 1)
633
634 static void op_alu_reg8(int op, int r)
635 {
636         op_alu_imm8(op, get_reg8(r));
637 }
638
639 static void op_alu_imm8(int op, uint8_t imm)
640 {
641         int c, h, pv, n = 0;
642         int acc = get_reg8s(R_A);
643         int rval = *(int8_t*)&imm;
644         c = CARRY;
645
646         switch(op) {
647         case ALUOP_ADD:
648                 if(0) {
649         case ALUOP_SUB:
650         case ALUOP_CP:
651                         rval = -rval;
652                         c = -c;
653                         n = 1;
654                 }
655                 h = ((acc & 0xf) + (rval + 0xf)) & 0x10;
656                 acc += rval;
657                 c = acc & 0x100;
658                 pv = overflow(acc);
659                 break;
660
661         case ALUOP_ADC:
662                 if(0) {
663         case ALUOP_SBC:
664                         rval = -rval;
665                         c = -c;
666                         n = 1;
667                 }
668                 h = ((acc & 0xf) + (rval + 0xf) + CARRY) & 0x10;
669                 acc += rval + CARRY;
670                 c = acc & 0x100;
671                 pv = overflow(acc);
672                 break;
673
674         case ALUOP_AND:
675                 acc &= rval;
676                 c = 0;
677                 h = 1;
678                 pv = parity(acc);
679                 break;
680         case ALUOP_XOR:
681                 acc ^= rval;
682                 c = 0;
683                 h = 0;
684                 pv = parity(acc);
685                 break;
686         case ALUOP_OR:
687                 acc |= rval;
688                 c = 0;
689                 h = 0;
690                 pv = parity(acc);
691                 break;
692         default:
693                 return;
694         }
695
696         set_flag(FLAGS_S, acc & 0x80);
697         set_flag(FLAGS_Z, acc == 0);
698         set_flag(FLAGS_H, h);
699         set_flag(FLAGS_PV, pv);
700         set_flag(FLAGS_N, n);
701         set_flag(FLAGS_C, c);
702
703         if(op != ALUOP_CP) {
704                 set_reg8s(R_A, acc);
705         }
706 }
707
708 static void op_incdec_reg8(int r, int adj)
709 {
710         int prev = get_reg8s(r);
711         int val = prev + adj;
712
713         set_flag(FLAGS_S, val & 0x80);
714         set_flag(FLAGS_Z, val == 0);
715         set_flag(FLAGS_H, ((prev & 0xf) + adj) & 0x10);
716         set_flag(FLAGS_PV, overflow(val));
717         set_flag(FLAGS_N, adj < 0);
718
719         set_reg8s(r, val);
720 }
721
722 static void op_incdec_reg16(int r, int adj)
723 {
724         set_reg16s(r, get_reg16s(r) + adj);
725 }
726
727 static void op_incdec_mem(uint16_t addr, int adj)
728 {
729         uint16_t lsb = emu_mem_read(addr);
730         uint16_t msb = emu_mem_read(addr + 1);
731         int prev, val;
732
733         lsb |= msb << 8;
734         prev = *(int16_t*)&lsb;
735         val = prev + adj;
736
737         set_flag(FLAGS_S, val & 0x8000);
738         set_flag(FLAGS_Z, val == 0);
739         set_flag(FLAGS_H, ((prev & 0xfff) + adj) & 0x1000);
740         set_flag(FLAGS_PV, overflow16(val));
741         set_flag(FLAGS_N, adj < 0);
742
743         lsb = *(uint16_t*)&val;
744         emu_mem_write(addr, lsb);
745         emu_mem_write(addr + 1, lsb >> 8);
746 }
747
748 static void op_add_reg16_reg16(int rdest, int rsrc)
749 {
750 }
751
752 static void op_rl_reg8(int r, int width)
753 {
754 }
755
756 static void op_rr_reg8(int r, int width)
757 {
758 }
759
760 static void op_push_reg16(int r)
761 {
762 }
763
764 static void op_pop_reg16(int r)
765 {
766 }
767
768 static void op_call(uint16_t addr)
769 {
770 }
771
772 static void op_ret(void)
773 {
774 }
775
776 static void op_input(int r, uint16_t addr)
777 {
778         set_reg8(r, emu_io_read(addr));
779 }
780
781 static void op_output(uint16_t addr, int r)
782 {
783         emu_io_write(addr, get_reg8(r));
784 }