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
716 if (CPU->ICount <= 0)
\r
721 else zIFF2 = (1 << 2);
\r
724 /*-----------------------------------------
\r
726 -----------------------------------------*/
\r
728 OP(0x03): // INC BC
\r
733 OP(0x13): // INC DE
\r
738 OP(0x23): // INC HL
\r
743 OP(0x33): // INC SP
\r
748 /*-----------------------------------------
\r
750 -----------------------------------------*/
\r
752 OP(0x0b): // DEC BC
\r
757 OP(0x1b): // DEC DE
\r
762 OP(0x2b): // DEC HL
\r
767 OP(0x3b): // DEC SP
\r
772 /*-----------------------------------------
\r
774 -----------------------------------------*/
\r
776 OP(0x39): // ADD xx,SP
\r
781 OP(0x29): // ADD xx,xx
\r
786 OP(0x09): // ADD xx,BC
\r
791 OP(0x19): // ADD xx,DE
\r
796 res = data->W + val;
\r
797 zF = (zF & (SF | ZF | VF)) |
\r
798 (((data->W ^ res ^ val) >> 8) & HF) |
\r
799 ((res >> 16) & CF) | ((res >> 8) & (YF | XF));
\r
800 data->W = (UINT16)res;
\r
803 /*-----------------------------------------
\r
805 -----------------------------------------*/
\r
814 zA = (A << 1) | (A >> 7);
\r
815 zF = (zF & (SF | ZF | PF)) | (zA & (YF | XF | CF));
\r
822 F = (F & (SF | ZF | PF)) | (A & CF);
\r
823 zA = (A >> 1) | (A << 7);
\r
824 zF = F | (zA & (YF | XF));
\r
831 zA = (A << 1) | (F & CF);
\r
832 zF = (F & (SF | ZF | PF)) | (A >> 7) | (zA & (YF | XF));
\r
839 zA = (A >> 1) | (F << 7);
\r
840 zF = (F & (SF | ZF | PF)) | (A & CF) | (zA & (YF | XF));
\r
844 /*-----------------------------------------
\r
846 -----------------------------------------*/
\r
850 res = READ_ARG16();
\r
854 OP(0xc2): // JP NZ,nn
\r
856 if (!(zF & ZF)) goto OP_JP;
\r
860 OP(0xca): // JP Z,nn
\r
862 if (zF & ZF) goto OP_JP;
\r
866 OP(0xd2): // JP NC,nn
\r
868 if (!(zF & CF)) goto OP_JP;
\r
872 OP(0xda): // JP C,nn
\r
874 if (zF & CF) goto OP_JP;
\r
878 OP(0xe2): // JP PO,nn
\r
880 if (!(zF & VF)) goto OP_JP;
\r
884 OP(0xea): // JP PE,nn
\r
886 if (zF & VF) goto OP_JP;
\r
890 OP(0xf2): // JP P,nn
\r
892 if (!(zF & SF)) goto OP_JP;
\r
896 OP(0xfa): // JP M,nn
\r
898 if (zF & SF) goto OP_JP;
\r
902 OP(0xe9): // JP (xx)
\r
908 /*-----------------------------------------
\r
910 -----------------------------------------*/
\r
912 OP(0x10): // DJNZ n
\r
915 if (--zB) goto OP_JR;
\r
921 adr = (INT8)READ_ARG();
\r
925 OP(0x20): // JR NZ,n
\r
927 if (!(zF & ZF)) goto OP_JR;
\r
931 OP(0x28): // JR Z,n
\r
933 if (zF & ZF) goto OP_JR;
\r
937 OP(0x38): // JR C,n
\r
939 if (zF & CF) goto OP_JR;
\r
943 OP(0x30): // JR NC,n
\r
945 if (!(zF & CF)) goto OP_JR;
\r
949 /*-----------------------------------------
\r
951 -----------------------------------------*/
\r
953 OP(0xcd): // CALL nn
\r
955 res = READ_ARG16();
\r
961 OP(0xc4): // CALL NZ,nn
\r
963 if (!(zF & ZF)) goto OP_CALL;
\r
967 OP(0xcc): // CALL Z,nn
\r
969 if (zF & ZF) goto OP_CALL;
\r
973 OP(0xd4): // CALL NC,nn
\r
975 if (!(zF & CF)) goto OP_CALL;
\r
979 OP(0xdc): // CALL C,nn
\r
981 if (zF & CF) goto OP_CALL;
\r
985 OP(0xe4): // CALL PO,nn
\r
987 if (!(zF & VF)) goto OP_CALL;
\r
991 OP(0xec): // CALL PE,nn
\r
993 if (zF & VF) goto OP_CALL;
\r
997 OP(0xf4): // CALL P,nn
\r
999 if (!(zF & SF)) goto OP_CALL;
\r
1003 OP(0xfc): // CALL M,nn
\r
1005 if (zF & SF) goto OP_CALL;
\r
1009 /*-----------------------------------------
\r
1011 -----------------------------------------*/
\r
1022 OP(0xc0): // RET NZ
\r
1024 if (!(zF & ZF)) goto OP_RET_COND;
\r
1027 OP(0xc8): // RET Z
\r
1029 if (zF & ZF) goto OP_RET_COND;
\r
1032 OP(0xd0): // RET NC
\r
1034 if (!(zF & CF)) goto OP_RET_COND;
\r
1037 OP(0xd8): // RET C
\r
1039 if (zF & CF) goto OP_RET_COND;
\r
1042 OP(0xe0): // RET PO
\r
1044 if (!(zF & VF)) goto OP_RET_COND;
\r
1047 OP(0xe8): // RET PE
\r
1049 if (zF & VF) goto OP_RET_COND;
\r
1052 OP(0xf0): // RET P
\r
1054 if (!(zF & SF)) goto OP_RET_COND;
\r
1057 OP(0xf8): // RET M
\r
1059 if (zF & SF) goto OP_RET_COND;
\r
1062 /*-----------------------------------------
\r
1064 -----------------------------------------*/
\r
1066 OP(0xc7): // RST 0
\r
1067 OP(0xcf): // RST 1
\r
1068 OP(0xd7): // RST 2
\r
1069 OP(0xdf): // RST 3
\r
1070 OP(0xe7): // RST 4
\r
1071 OP(0xef): // RST 5
\r
1072 OP(0xf7): // RST 6
\r
1073 OP(0xff): // RST 7
\r
1077 res = Opcode & 0x38;
\r
1081 /*-----------------------------------------
\r
1083 -----------------------------------------*/
\r
1085 OP(0xd3): // OUT (n),A
\r
1087 adr = (zA << 8) | READ_ARG();
\r
1091 /*-----------------------------------------
\r
1093 -----------------------------------------*/
\r
1095 OP(0xdb): // IN A,(n)
\r
1097 adr = (zA << 8) | READ_ARG();
\r
1101 /*-----------------------------------------
\r
1103 -----------------------------------------*/
\r
1105 OP(0xcb): // CB prefix (BIT & SHIFT INSTRUCTIONS)
\r
1110 Opcode = READ_OP();
\r
1111 #if CZ80_EMULATE_R_EXACTLY
\r
1114 #include "cz80_opCB.c"
\r
1117 OP(0xed): // ED prefix
\r
1120 Opcode = READ_OP();
\r
1121 #if CZ80_EMULATE_R_EXACTLY
\r
1124 #include "cz80_opED.c"
\r
1126 OP(0xdd): // DD prefix (IX)
\r
1131 OP(0xfd): // FD prefix (IY)
\r
1137 Opcode = READ_OP();
\r
1138 #if CZ80_EMULATE_R_EXACTLY
\r
1141 #include "cz80_opXY.c"
\r
1143 #if !CZ80_USE_JUMPTABLE
\r