1 /* Emulations of the Z80 CPU instruction set - part of xz80.
2 * Copyright (C) 1994 Ian Collier.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* PENDING: Forward definitions. */
20 void handleRST08(struct sregs
*pregs
);
22 #define instr(opcode,cycles) case opcode: {tstates+=cycles
23 #define endinstr }; break
29 /** Parity/Overflow */
43 /** Parity/Overflow */
58 #define setxh(x) (h=(x))
59 #define setxl(x) (l=(x))
60 #define inc(var) /* 8-bit increment */ ( var++,\
62 ((!(var&15))<<4)|((!var)<<6)|\
65 #define dec(var) /* 8-bit decrement */ ( f=(f&1)|((!(var&15))<<4)|2,\
67 f|=(var&0xa8)|((var==127)<<2)|\
70 #define swap(x,y) {unsigned char t=x; x=y; y=t;}
71 #define addhl(hi,lo) /* 16-bit add */ do {\
74 f=(f&0xc4)|(((t>>=8)+(h&0x0f)+((hi)&0x0f)>15)<<4);\
76 f|=(h&0x28)|(t>>8); } while(0)
78 #define adda(x,c) /* 8-bit add */ do{unsigned short y;\
81 f=(y&0xa8)|(y>>8)|(((a&0x0f)+(z&0x0f)+(c)>15)<<4)|\
82 (((~a^z)&0x80&(y^a))>>5);\
85 #define suba(x,c) /* 8-bit subtract */ do{unsigned short y;\
88 f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f)+(c))<<4)|\
89 (((a^z)&0x80&(y^a))>>5)|2;\
92 #define cpa(x) /* 8-bit compare */ do{unsigned short y;\
95 f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f))<<4)|\
96 (((a^z)&0x80&(y^a))>>5)|2|((!y)<<6);\
98 #define anda(x) /* logical and */ do{\
100 f=(a&0xa8)|((!a)<<6)|0x10;\
102 #define xora(x) /* logical xor */ do{\
104 f=(a&0xa8)|((!a)<<6);\
106 #define ora(x) /* logical or */ do{\
108 f=(a&0xa8)|((!a)<<6);\
111 #define jr /* execute relative jump */ do{int j=(signed char)fetch(pc);\
114 #define jp /* execute jump */ (pc=fetch2(pc))
115 #define call /* execute call */ do{\
117 if (flags&DPROFILE) \
118 push_callback(fetch2(pc));\
121 #define ret /* execute return */ do{\
122 if (flags&DPROFILE) \
126 #define pop2(var) /* pop 16-bit register */ (var=fetch2(sp),sp+=2)
127 #define pop1(v1,v2) /* pop register pair */ (v2=fetch(sp),\
128 v1=fetch(sp+1),sp+=2)
129 #define push2(val) /* push 16-bit register */ do{sp-=2;store2(sp,(val));}\
131 #define push1(v1,v2) /* push register pair */ do{sp-=2;\
169 instr(8,20); /* Old Ex AF,AF' - new LD (nnnn),SP NYT */
171 unsigned addr
=fetch2(pc
);
207 instr(16,4); /* Old DJNZ - new STOP (taken as abort) */
241 f
=(f
&0xc4)|(a
&0x28)|t
;
276 f
=(f
&0xc4)|(a
&0x28)|t
;
290 instr(34,8); /* LD (HL+),A */
295 instr(35,8); /* INC HL */
314 unsigned char incr
=0, carry
=cy
;
315 if((f
&0x10) || (a
&0x0f)>9) incr
=6;
316 if((f
&1) || (a
>>4)>9) incr
|=0x60;
319 if(a
>0x90 && (a
&15)>9)incr
|=0x60;
335 instr(0x2A,8); /* LD A,(HL+) */
340 instr(43,8); /* DEC HL */
359 f
=(f
&0xc5)|(a
&0x28)|0x12;
372 instr(50,8); /* LD (HL-),A */
382 {unsigned char t
=fetch(hl
);
389 {unsigned char t
=fetch(hl
);
401 f
=(f
&0xc4)|1|(a
&0x28);
410 addhl((sp
>>8),(sp
&0xff));
413 instr(58,8); /* LD A,(HL-) */
435 f
=(f
&0xc4)|(cy
^1)|(cy
<<4)|(a
&0x28);
655 /* no interrupt support, so effectively a nop */
686 instr(0x7e,8); /* LD A,(HL) */
981 instr(0xc7,32); /* Old RST 00 - new End emulator */
1018 instr(0xcf,32); /* Old RST 08 - new print following string */
1037 instr(0xd3,8); /* Old OUT (nn),a */
1038 /* tstates+=out(a,fetch(pc),a);
1056 instr(0xd7,32); /* Old RST 10 */
1065 instr(0xd9,8); /* Old EXX - now RETI */
1066 ret
; /* xxx not what the GB really does */
1074 #ifdef INCLUDE_UNIMP
1078 a=t=in(a,fetch(pc));
1090 #ifdef INCLUDE_UNIMP
1091 /* Old IX/IY commands */
1097 suba(fetch(pc
),cy
); /* SBC A,nn */
1101 instr(0xdf,32); /* Old RST 18 - new start timing */
1102 startTime
= tstates
;
1107 #ifdef INCLUDE_UNIMP
1108 instr(0xe0,12); /* Old RET PO - now LD ($FF00+nn),A */
1109 /* if(!(f&4))ret; */
1113 instr(0xe1,12); /* POP HL */
1117 #ifdef INCLUDE_UNIMP
1118 instr(0xe2,8); /* Old JP PO - now LD ($FF00+C),A */
1124 /* Old EX (SP),HL */
1127 unsigned short t=fetch2(sp);
1133 unsigned short t=fetch2(sp);
1138 unsigned short t=fetch2(sp);
1159 instr(0xe7,32); /* Old RST 20 - new print time */
1162 printf("Time: %lu\n", tstates
-startTime
);
1165 instr(0xe8,16); /* Old RET PE - now ADD SP,shortint */
1166 sp
+=(signed char)fetch(pc
);
1175 instr(0xea,16); /* Old JP PE - now LD (nnnn),A */
1176 {unsigned short addr
=fetch2(pc
);
1194 /* Old ED commands */
1203 instr(0xef,32); /* Old RST 28 - new print float */
1208 #ifdef INCLUDE_UNIMP
1209 instr(0xf0,12); /* Old RET P - now LD A,($FF00+nn) NYI */
1210 /* if(!(f&0x80))ret; */
1218 #ifdef INCLUDE_UNIMP
1219 instr(0xf2,8); /* Old JP P - now LD A,(C) NYT */
1246 instr(0xf7,32); /* Old RST 30 - new switch bank */
1249 switchBank( a
, hl
);
1252 instr(0xf8,12); /* Old RET M - new LD HL,SP+nn NYT */
1254 unsigned j
= (unsigned)(sp
+(signed char)fetch(pc
));
1257 f
&= ~(ZBIT
| NBIT
| CBIT
| HBIT
);
1258 /* Set carry and half carry as appropriate */
1259 /* PENDING: Set half carry. */
1263 /* if(f&0x80)ret; */
1270 instr(0xfa,16); /* Old JP M - new LD A,(nnnn) */
1271 {unsigned short addr
=fetch2(pc
);
1300 instr(0xff,32); /* Old RST 38 - New system call */