1 /******************************************************************************
\r
3 * CZ80 opcode include source file
\r
4 * CZ80 emulator version 0.9
\r
5 * Copyright 2004-2005 Stéphane Dallongeville
\r
9 *****************************************************************************/
\r
11 #if CZ80_USE_JUMPTABLE
\r
12 goto *JumpTable[Opcode];
\r
18 /*-----------------------------------------
\r
20 -----------------------------------------*/
\r
24 /*-----------------------------------------
\r
25 LD r8 (same register)
\r
26 -----------------------------------------*/
\r
37 /*-----------------------------------------
\r
39 -----------------------------------------*/
\r
90 zR8((Opcode >> 3) & 7) = zR8(Opcode & 7);
\r
93 OP(0x06): // LD B,#imm
\r
94 OP(0x0e): // LD C,#imm
\r
95 OP(0x16): // LD D,#imm
\r
96 OP(0x1e): // LD E,#imm
\r
97 OP(0x26): // LD H,#imm
\r
98 OP(0x2e): // LD L,#imm
\r
99 OP(0x3e): // LD A,#imm
\r
101 zR8(Opcode >> 3) = READ_ARG();
\r
104 OP(0x46): // LD B,(HL)
\r
105 OP(0x4e): // LD C,(HL)
\r
106 OP(0x56): // LD D,(HL)
\r
107 OP(0x5e): // LD E,(HL)
\r
108 OP(0x66): // LD H,(HL)
\r
109 OP(0x6e): // LD L,(HL)
\r
110 OP(0x7e): // LD A,(HL)
\r
111 zR8((Opcode >> 3) & 7) = READ_MEM8(zHL);
\r
114 OP(0x70): // LD (HL),B
\r
115 OP(0x71): // LD (HL),C
\r
116 OP(0x72): // LD (HL),D
\r
117 OP(0x73): // LD (HL),E
\r
118 OP(0x74): // LD (HL),H
\r
119 OP(0x75): // LD (HL),L
\r
120 OP(0x77): // LD (HL),A
\r
121 WRITE_MEM8(zHL, zR8(Opcode & 7));
\r
124 OP(0x36): // LD (HL), #imm
\r
125 WRITE_MEM8(zHL, READ_ARG());
\r
128 OP(0x0a): // LD A,(BC)
\r
131 goto OP_LOAD_A_mxx;
\r
133 OP(0x1a): // LD A,(DE)
\r
138 zA = READ_MEM8(adr);
\r
141 OP(0x3a): // LD A,(nn)
\r
143 adr = READ_ARG16();
\r
144 zA = READ_MEM8(adr);
\r
147 OP(0x02): // LD (BC),A
\r
150 goto OP_LOAD_mxx_A;
\r
152 OP(0x12): // LD (DE),A
\r
157 WRITE_MEM8(adr, zA);
\r
160 OP(0x32): // LD (nn),A
\r
162 adr = READ_ARG16();
\r
163 WRITE_MEM8(adr, zA);
\r
166 /*-----------------------------------------
\r
168 -----------------------------------------*/
\r
170 OP(0x01): // LD BC,nn
\r
171 OP(0x11): // LD DE,nn
\r
172 OP(0x21): // LD HL,nn
\r
174 zR16(Opcode >> 4) = READ_ARG16();
\r
177 OP(0x31): // LD SP,nn
\r
179 zSP = READ_ARG16();
\r
182 OP(0xf9): // LD SP,HL
\r
187 OP(0x2a): // LD HL,(nn)
\r
189 adr = READ_ARG16();
\r
190 data->W = READ_MEM16(adr);
\r
193 OP(0x22): // LD (nn),HL
\r
195 adr = READ_ARG16();
\r
196 WRITE_MEM16(adr, data->W);
\r
199 /*-----------------------------------------
\r
201 -----------------------------------------*/
\r
203 OP(0xc1): // POP BC
\r
204 OP(0xd1): // POP DE
\r
205 OP(0xf1): // POP AF
\r
207 data = CPU->pzR16[(Opcode >> 4) & 3];
\r
209 OP(0xe1): // POP HL
\r
214 /*-----------------------------------------
\r
216 -----------------------------------------*/
\r
218 OP(0xc5): // PUSH BC
\r
219 OP(0xd5): // PUSH DE
\r
220 OP(0xf5): // PUSH AF
\r
222 data = CPU->pzR16[(Opcode >> 4) & 3];
\r
224 OP(0xe5): // PUSH HL
\r
229 /*-----------------------------------------
\r
231 -----------------------------------------*/
\r
233 OP(0x08): // EX AF,AF'
\r
240 OP(0xeb): // EX DE,HL
\r
260 OP(0xe3): // EX HL,(SP)
\r
264 data->W = READ_MEM16(adr);
\r
265 WRITE_MEM16(adr, res);
\r
268 /*-----------------------------------------
\r
270 -----------------------------------------*/
\r
280 zR8(Opcode >> 3)++;
\r
281 zF = (zF & CF) | SZHV_inc[zR8(Opcode >> 3)];
\r
284 OP(0x34): // INC (HL)
\r
288 res = READ_MEM8(adr);
\r
289 res = (res + 1) & 0xff;
\r
290 zF = (zF & CF) | SZHV_inc[res];
\r
291 WRITE_MEM8(adr, res);
\r
294 /*-----------------------------------------
\r
296 -----------------------------------------*/
\r
306 zR8(Opcode >> 3)--;
\r
307 zF = (zF & CF) | SZHV_dec[zR8(Opcode >> 3)];
\r
310 OP(0x35): // DEC (HL)
\r
314 res = READ_MEM8(adr);
\r
315 res = (res - 1) & 0xff;
\r
316 zF = (zF & CF) | SZHV_dec[res];
\r
317 WRITE_MEM8(adr, res);
\r
320 /*-----------------------------------------
\r
322 -----------------------------------------*/
\r
324 OP(0x86): // ADD A,(HL)
\r
325 val = READ_MEM8(zHL);
\r
329 OP(0xc6): // ADD A,n
\r
335 OP(0x80): // ADD A,B
\r
336 OP(0x81): // ADD A,C
\r
337 OP(0x82): // ADD A,D
\r
338 OP(0x83): // ADD A,E
\r
339 OP(0x84): // ADD A,H
\r
340 OP(0x85): // ADD A,L
\r
341 OP(0x87): // ADD A,A
\r
343 val = zR8(Opcode & 7);
\r
346 #if CZ80_BIG_FLAGS_ARRAY
\r
349 res = (UINT8)(A + val);
\r
350 zF = SZHVC_add[(A << 8) | res];
\r
355 zF = SZ[(UINT8)res] | ((res >> 8) & CF) |
\r
356 ((zA ^ res ^ val) & HF) |
\r
357 (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5);
\r
362 /*-----------------------------------------
\r
364 -----------------------------------------*/
\r
366 OP(0x8e): // ADC A,(HL)
\r
367 val = READ_MEM8(zHL);
\r
371 OP(0xce): // ADC A,n
\r
377 OP(0x88): // ADC A,B
\r
378 OP(0x89): // ADC A,C
\r
379 OP(0x8a): // ADC A,D
\r
380 OP(0x8b): // ADC A,E
\r
381 OP(0x8c): // ADC A,H
\r
382 OP(0x8d): // ADC A,L
\r
383 OP(0x8f): // ADC A,A
\r
385 val = zR8(Opcode & 7);
\r
388 #if CZ80_BIG_FLAGS_ARRAY
\r
392 res = (UINT8)(A + val + c);
\r
393 zF = SZHVC_add[(c << 16) | (A << 8) | res];
\r
397 res = zA + val + (zF & CF);
\r
398 zF = SZ[res & 0xff] | ((res >> 8) & CF) |
\r
399 ((zA ^ res ^ val) & HF) |
\r
400 (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5);
\r
405 /*-----------------------------------------
\r
407 -----------------------------------------*/
\r
409 OP(0x96): // SUB (HL)
\r
410 val = READ_MEM8(zHL);
\r
414 OP(0xd6): // SUB A,n
\r
428 val = zR8(Opcode & 7);
\r
431 #if CZ80_BIG_FLAGS_ARRAY
\r
434 res = (UINT8)(A - val);
\r
435 zF = SZHVC_sub[(A << 8) | res];
\r
440 zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF |
\r
441 ((zA ^ res ^ val) & HF) |
\r
442 (((val ^ zA) & (zA ^ res) & 0x80) >> 5);
\r
447 /*-----------------------------------------
\r
449 -----------------------------------------*/
\r
451 OP(0x9e): // SBC A,(HL)
\r
452 val = READ_MEM8(zHL);
\r
456 OP(0xde): // SBC A,n
\r
462 OP(0x98): // SBC A,B
\r
463 OP(0x99): // SBC A,C
\r
464 OP(0x9a): // SBC A,D
\r
465 OP(0x9b): // SBC A,E
\r
466 OP(0x9c): // SBC A,H
\r
467 OP(0x9d): // SBC A,L
\r
468 OP(0x9f): // SBC A,A
\r
470 val = zR8(Opcode & 7);
\r
473 #if CZ80_BIG_FLAGS_ARRAY
\r
477 res = (UINT8)(A - val - c);
\r
478 zF = SZHVC_sub[(c << 16) | (A << 8) | res];
\r
482 res = zA - val - (zF & CF);
\r
483 zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF |
\r
484 ((zA ^ res ^ val) & HF) |
\r
485 (((val ^ zA) & (zA ^ res) & 0x80) >> 5);
\r
490 /*-----------------------------------------
\r
492 -----------------------------------------*/
\r
494 OP(0xbe): // CP (HL)
\r
495 val = READ_MEM8(zHL);
\r
513 val = zR8(Opcode & 7);
\r
516 #if CZ80_BIG_FLAGS_ARRAY
\r
519 res = (UINT8)(A - val);
\r
520 zF = (SZHVC_sub[(A << 8) | res] & ~(YF | XF)) |
\r
525 zF = (SZ[res & 0xff] & (SF | ZF)) |
\r
526 (val & (YF | XF)) | ((res >> 8) & CF) | NF |
\r
527 ((zA ^ res ^ val) & HF) |
\r
528 (((val ^ zA) & (zA ^ res) >> 5) & VF);
\r
532 /*-----------------------------------------
\r
534 -----------------------------------------*/
\r
536 OP(0xa6): // AND (HL)
\r
537 val = READ_MEM8(zHL);
\r
541 OP(0xe6): // AND A,n
\r
555 val = zR8(Opcode & 7);
\r
562 /*-----------------------------------------
\r
564 -----------------------------------------*/
\r
566 OP(0xae): // XOR (HL)
\r
567 val = READ_MEM8(zHL);
\r
571 OP(0xee): // XOR A,n
\r
585 val = zR8(Opcode & 7);
\r
592 /*-----------------------------------------
\r
594 -----------------------------------------*/
\r
596 OP(0xb6): // OR (HL)
\r
597 val = READ_MEM8(zHL);
\r
601 OP(0xf6): // OR A,n
\r
615 val = zR8(Opcode & 7);
\r
622 /*-----------------------------------------
\r
623 MISC ARITHMETIC & CPU CONTROL
\r
624 -----------------------------------------*/
\r
630 UINT8 cf, nf, hf, lo, hi, diff;
\r
641 diff = (lo <= 9 && !hf) ? 0x60 : 0x66;
\r
647 diff = hi <= 8 ? 0x06 : 0x66;
\r
653 diff = hf ? 0x66 : 0x60;
\r
657 diff = hf ? 0x06 : 0x00;
\r
661 if (nf) zA -= diff;
\r
664 F = SZP[zA] | (F & NF);
\r
665 if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= CF;
\r
666 if (nf ? hf && lo <= 5 : lo >= 10) F |= HF;
\r
674 zF = (zF & (SF | ZF | PF | CF)) | HF | NF | (zA & (YF | XF));
\r
679 zF = (zF & (SF | ZF | PF)) | CF | (zA & (YF | XF));
\r
684 zF = ((zF & (SF | ZF | PF | CF)) | ((zF & CF) << 4) | (zA & (YF | XF))) ^ CF;
\r
689 CPU->HaltState = 1;
\r
691 goto Cz80_Check_Interrupt;
\r
703 zIFF1 = zIFF2 = (1 << 2);
\r
704 while (GET_OP() == 0xfb)
\r
708 #if CZ80_EMULATE_R_EXACTLY
\r
715 CPU->ExtraCycles += 1 - CPU->ICount;
\r
719 else zIFF2 = (1 << 2);
\r
720 goto Cz80_Exec_nocheck;
\r
722 /*-----------------------------------------
\r
724 -----------------------------------------*/
\r
726 OP(0x03): // INC BC
\r
731 OP(0x13): // INC DE
\r
736 OP(0x23): // INC HL
\r
741 OP(0x33): // INC SP
\r
746 /*-----------------------------------------
\r
748 -----------------------------------------*/
\r
750 OP(0x0b): // DEC BC
\r
755 OP(0x1b): // DEC DE
\r
760 OP(0x2b): // DEC HL
\r
765 OP(0x3b): // DEC SP
\r
770 /*-----------------------------------------
\r
772 -----------------------------------------*/
\r
774 OP(0x39): // ADD xx,SP
\r
779 OP(0x29): // ADD xx,xx
\r
784 OP(0x09): // ADD xx,BC
\r
789 OP(0x19): // ADD xx,DE
\r
794 res = data->W + val;
\r
795 zF = (zF & (SF | ZF | VF)) |
\r
796 (((data->W ^ res ^ val) >> 8) & HF) |
\r
797 ((res >> 16) & CF) | ((res >> 8) & (YF | XF));
\r
798 data->W = (UINT16)res;
\r
801 /*-----------------------------------------
\r
803 -----------------------------------------*/
\r
812 zA = (A << 1) | (A >> 7);
\r
813 zF = (zF & (SF | ZF | PF)) | (zA & (YF | XF | CF));
\r
820 F = (F & (SF | ZF | PF)) | (A & CF);
\r
821 zA = (A >> 1) | (A << 7);
\r
822 zF = F | (zA & (YF | XF));
\r
829 zA = (A << 1) | (F & CF);
\r
830 zF = (F & (SF | ZF | PF)) | (A >> 7) | (zA & (YF | XF));
\r
837 zA = (A >> 1) | (F << 7);
\r
838 zF = (F & (SF | ZF | PF)) | (A & CF) | (zA & (YF | XF));
\r
842 /*-----------------------------------------
\r
844 -----------------------------------------*/
\r
848 res = READ_ARG16();
\r
852 OP(0xc2): // JP NZ,nn
\r
854 if (!(zF & ZF)) goto OP_JP;
\r
858 OP(0xca): // JP Z,nn
\r
860 if (zF & ZF) goto OP_JP;
\r
864 OP(0xd2): // JP NC,nn
\r
866 if (!(zF & CF)) goto OP_JP;
\r
870 OP(0xda): // JP C,nn
\r
872 if (zF & CF) goto OP_JP;
\r
876 OP(0xe2): // JP PO,nn
\r
878 if (!(zF & VF)) goto OP_JP;
\r
882 OP(0xea): // JP PE,nn
\r
884 if (zF & VF) goto OP_JP;
\r
888 OP(0xf2): // JP P,nn
\r
890 if (!(zF & SF)) goto OP_JP;
\r
894 OP(0xfa): // JP M,nn
\r
896 if (zF & SF) goto OP_JP;
\r
900 OP(0xe9): // JP (xx)
\r
906 /*-----------------------------------------
\r
908 -----------------------------------------*/
\r
910 OP(0x10): // DJNZ n
\r
913 if (--zB) goto OP_JR;
\r
919 adr = (INT8)READ_ARG();
\r
923 OP(0x20): // JR NZ,n
\r
925 if (!(zF & ZF)) goto OP_JR;
\r
929 OP(0x28): // JR Z,n
\r
931 if (zF & ZF) goto OP_JR;
\r
935 OP(0x38): // JR C,n
\r
937 if (zF & CF) goto OP_JR;
\r
941 OP(0x30): // JR NC,n
\r
943 if (!(zF & CF)) goto OP_JR;
\r
947 /*-----------------------------------------
\r
949 -----------------------------------------*/
\r
951 OP(0xcd): // CALL nn
\r
953 res = READ_ARG16();
\r
959 OP(0xc4): // CALL NZ,nn
\r
961 if (!(zF & ZF)) goto OP_CALL;
\r
965 OP(0xcc): // CALL Z,nn
\r
967 if (zF & ZF) goto OP_CALL;
\r
971 OP(0xd4): // CALL NC,nn
\r
973 if (!(zF & CF)) goto OP_CALL;
\r
977 OP(0xdc): // CALL C,nn
\r
979 if (zF & CF) goto OP_CALL;
\r
983 OP(0xe4): // CALL PO,nn
\r
985 if (!(zF & VF)) goto OP_CALL;
\r
989 OP(0xec): // CALL PE,nn
\r
991 if (zF & VF) goto OP_CALL;
\r
995 OP(0xf4): // CALL P,nn
\r
997 if (!(zF & SF)) goto OP_CALL;
\r
1001 OP(0xfc): // CALL M,nn
\r
1003 if (zF & SF) goto OP_CALL;
\r
1007 /*-----------------------------------------
\r
1009 -----------------------------------------*/
\r
1020 OP(0xc0): // RET NZ
\r
1022 if (!(zF & ZF)) goto OP_RET_COND;
\r
1025 OP(0xc8): // RET Z
\r
1027 if (zF & ZF) goto OP_RET_COND;
\r
1030 OP(0xd0): // RET NC
\r
1032 if (!(zF & CF)) goto OP_RET_COND;
\r
1035 OP(0xd8): // RET C
\r
1037 if (zF & CF) goto OP_RET_COND;
\r
1040 OP(0xe0): // RET PO
\r
1042 if (!(zF & VF)) goto OP_RET_COND;
\r
1045 OP(0xe8): // RET PE
\r
1047 if (zF & VF) goto OP_RET_COND;
\r
1050 OP(0xf0): // RET P
\r
1052 if (!(zF & SF)) goto OP_RET_COND;
\r
1055 OP(0xf8): // RET M
\r
1057 if (zF & SF) goto OP_RET_COND;
\r
1060 /*-----------------------------------------
\r
1062 -----------------------------------------*/
\r
1064 OP(0xc7): // RST 0
\r
1065 OP(0xcf): // RST 1
\r
1066 OP(0xd7): // RST 2
\r
1067 OP(0xdf): // RST 3
\r
1068 OP(0xe7): // RST 4
\r
1069 OP(0xef): // RST 5
\r
1070 OP(0xf7): // RST 6
\r
1071 OP(0xff): // RST 7
\r
1075 res = Opcode & 0x38;
\r
1079 /*-----------------------------------------
\r
1081 -----------------------------------------*/
\r
1083 OP(0xd3): // OUT (n),A
\r
1085 adr = (zA << 8) | READ_ARG();
\r
1089 /*-----------------------------------------
\r
1091 -----------------------------------------*/
\r
1093 OP(0xdb): // IN A,(n)
\r
1095 adr = (zA << 8) | READ_ARG();
\r
1099 /*-----------------------------------------
\r
1101 -----------------------------------------*/
\r
1103 OP(0xcb): // CB prefix (BIT & SHIFT INSTRUCTIONS)
\r
1108 Opcode = READ_OP();
\r
1109 #if CZ80_EMULATE_R_EXACTLY
\r
1112 #include "cz80_opCB.c"
\r
1115 OP(0xed): // ED prefix
\r
1118 Opcode = READ_OP();
\r
1119 #if CZ80_EMULATE_R_EXACTLY
\r
1122 #include "cz80_opED.c"
\r
1124 OP(0xdd): // DD prefix (IX)
\r
1129 OP(0xfd): // FD prefix (IY)
\r
1135 Opcode = READ_OP();
\r
1136 #if CZ80_EMULATE_R_EXACTLY
\r
1139 #include "cz80_opXY.c"
\r
1141 #if !CZ80_USE_JUMPTABLE
\r