Version 1.9
[virtual-nascom.git] / simz80.pl
blobf19c662fc10b0cac4323b7b5c9dc470765915cf1
1 print <<"EOT";
2 /* Z80 instruction set simulator.
3 Copyright (C) 1995 Frank D. Cringle.
5 This file is part of yaze - yet another Z80 emulator.
7 Yaze is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 EOT
24 # This perl script generates the z80 instruction set simulator simz80().
26 # Because simz80() is the function which determines the speed of the
27 # emulator, it can be interesting to experiment with different coding
28 # styles. Using perl to generate the final C code helps to separate
29 # the logic of the emulator from implementation details, such as whether
30 # to use sub-functions or inline code for handling extended opcodes.
32 # Set $combine = 1 to insert goto's where possible to combine
33 # identical instruction sequences at the end of switch branches.
34 # If $combine is not set (or set = 0), the generated code will be
35 # larger but there will be fewer jump instructions during execution.
36 # Thus the code may execute faster on a machine with slow branches and
37 # no cache or one with a large instruction cache. The compiler and
38 # optimizer will also play a role, so the best choice for a particular
39 # environment must by found empirically.
41 $combine = 0;
43 # Set $optab = 1 to use an array of labels instead of a switch for the
44 # main op-code dispatch function. This only works with gcc, and
45 # actually produces worse code with gcc-2.6.1 on a sparc.
47 $optab = 0;
49 # Set $xx_inline = 1 to generate inline code for the instruction prefix xx.
50 # If $xx_inline is undefined or 0, prefix xx will be handled by a separate
51 # function which does not have access to the local variables of the main
52 # simz80() function.
54 $cb_inline = 0;
55 $dfd_inline = 0;
56 $ed_inline = 1;
57 # ****************
59 ##### end of configuration options ####
61 $f = __FILE__;
62 print <<"EOT";
63 /* This file was generated from $f
64 with the following choice of options */
65 char *perl_params =
66 "combine=$combine,"
67 "optab=$optab,"
68 "cb_inline=$cb_inline,"
69 "dfd_inline=$dfd_inline,"
70 "ed_inline=$ed_inline";
72 EOT
74 $tab = "\t";
75 $cblabno = 0;
77 &preamble; # generate the function header and switch
79 &case(0x00, "NOP");
80 &case(0x01, "LD BC,nnnn"); &LDddnn(BC);
81 &case(0x02, "LD (BC),A"); print "\t\tPutBYTE(BC, hreg(AF));\n";
82 &case(0x03, "INC BC"); print "\t\t++BC;\n";
83 &case(0x04, "INC B"); &INCr(BC, "h");
84 &case(0x05, "DEC B"); &DECr(BC, "h");
85 &case(0x06, "LD B,nn"); print "\t\tSethreg(BC, GetBYTE(PC)); ++PC;\n";
86 &case(0x07, "RLCA"); print <<"EOT";
87 AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
88 (AF & 0xc4) | ((AF >> 15) & 1);
89 EOT
90 &case(0x08, "EX AF,AF'"); print <<"EOT";
91 af[af_sel] = AF;
92 af_sel = 1 - af_sel;
93 AF = af[af_sel];
94 EOT
95 &case(0x09, "ADD HL,BC"); &ADDdd(HL, BC);
96 &case(0x0A, "LD A,(BC)"); print "\t\tSethreg(AF, GetBYTE(BC));\n";
97 &case(0x0B, "DEC BC"); print "\t\t--BC;\n";
98 &case(0x0C, "INC C"); &INCr(BC, "l");
99 &case(0x0D, "DEC C"); &DECr(BC, "l");
100 &case(0x0E, "LD C,nn"); print "\t\tSetlreg(BC, GetBYTE(PC)); ++PC;\n";
101 &case(0x0F, "RRCA"); print <<"EOT";
102 temp = hreg(AF);
103 sum = temp >> 1;
104 AF = ((temp & 1) << 15) | (sum << 8) |
105 (sum & 0x28) | (AF & 0xc4) | (temp & 1);
107 &case(0x10, "DJNZ dd"); &JRcond("(BC -= 0x100) & 0xff00");
108 &case(0x11, "LD DE,nnnn"); &LDddnn(DE);
109 &case(0x12, "LD (DE),A"); print "\t\tPutBYTE(DE, hreg(AF));\n";
110 &case(0x13, "INC DE"); print "\t\t++DE;\n";
111 &case(0x14, "INC D"); &INCr(DE, "h");
112 &case(0x15, "DEC D"); &DECr(DE, "h");
113 &case(0x16, "LD D,nn"); print "\t\tSethreg(DE, GetBYTE(PC)); ++PC;\n";
114 &case(0x17, "RLA"); print <<"EOT";
115 AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
116 (AF & 0xc4) | ((AF >> 15) & 1);
118 &case(0x18, "JR dd"); &JRcond(1);
119 &case(0x19, "ADD HL,DE"); &ADDdd(HL, DE);
120 &case(0x1A, "LD A,(DE)"); print "\t\tSethreg(AF, GetBYTE(DE));\n";
121 &case(0x1B, "DEC DE"); print "\t\t--DE;\n";
122 &case(0x1C, "INC E"); &INCr(DE, "l");
123 &case(0x1D, "DEC E"); &DECr(DE, "l");
124 &case(0x1E, "LD E,nn"); print "\t\tSetlreg(DE, GetBYTE(PC)); ++PC;\n";
125 &case(0x1F, "RRA"); print <<"EOT";
126 temp = hreg(AF);
127 sum = temp >> 1;
128 AF = ((AF & 1) << 15) | (sum << 8) |
129 (sum & 0x28) | (AF & 0xc4) | (temp & 1);
131 &case(0x20, "JR NZ,dd"); &JRcond("!TSTFLAG(Z)");
132 &case(0x21, "LD HL,nnnn"); &LDddnn(HL);
133 &case(0x22, "LD (nnnn),HL"); &LDmemdd(HL);
134 &case(0x23, "INC HL"); print "\t\t++HL;\n";
135 &case(0x24, "INC H"); &INCr(HL, "h");
136 &case(0x25, "DEC H"); &DECr(HL, "h");
137 &case(0x26, "LD H,nn"); print "\t\tSethreg(HL, GetBYTE(PC)); ++PC;\n";
138 &case(0x27, "DAA"); print <<"EOT";
139 acu = hreg(AF);
140 temp = ldig(acu);
141 cbits = TSTFLAG(C);
142 if (TSTFLAG(N)) { /* last operation was a subtract */
143 int hd = cbits || acu > 0x99;
144 if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
145 if (temp > 5)
146 SETFLAG(H, 0);
147 acu -= 6;
148 acu &= 0xff;
150 if (hd) /* adjust high digit */
151 acu -= 0x160;
153 else { /* last operation was an add */
154 if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
155 SETFLAG(H, (temp > 9));
156 acu += 6;
158 if (cbits || ((acu & 0x1f0) > 0x90)) /* adjust high digit */
159 acu += 0x60;
161 cbits |= (acu >> 8) & 1;
162 acu &= 0xff;
163 AF = (acu << 8) | (acu & 0xa8) | ((acu == 0) << 6) |
164 (AF & 0x12) | partab[acu] | cbits;
166 &case(0x28, "JR Z,dd"); &JRcond("TSTFLAG(Z)");
167 &case(0x29, "ADD HL,HL"); &ADDdd(HL, HL);
168 &case(0x2A, "LD HL,(nnnn)"); &LDddmem(HL);
169 &case(0x2B, "DEC HL"); print "\t\t--HL;\n";
170 &case(0x2C, "INC L"); &INCr(HL, "l");
171 &case(0x2D, "DEC L"); &DECr(HL, "l");
172 &case(0x2E, "LD L,nn"); print "\t\tSetlreg(HL, GetBYTE(PC)); ++PC;\n";
173 &case(0x2F, "CPL"); print <<"EOT";
174 AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
176 &case(0x30, "JR NC,dd"); &JRcond("!TSTFLAG(C)");
177 &case(0x31, "LD SP,nnnn"); &LDddnn(SP);
178 &case(0x32, "LD (nnnn),A"); &LDmemr(AF, "h");
179 &case(0x33, "INC SP"); print "\t\t++SP;\n";
180 &case(0x34, "INC (HL)"); &INCm(HL);
181 &case(0x35, "DEC (HL)"); &DECm(HL);
182 &case(0x36, "LD (HL),nn"); print "\t\tPutBYTE(HL, GetBYTE(PC)); ++PC;\n";
183 &case(0x37, "SCF"); print "\t\tAF = (AF&~0x3b)|((AF>>8)&0x28)|1;\n";
184 &case(0x38, "JR C,dd"); &JRcond("TSTFLAG(C)");
185 &case(0x39, "ADD HL,SP"); &ADDdd(HL, SP);
186 &case(0x3A, "LD A,(nnnn)"); &LDrmem(AF, "h");
187 &case(0x3B, "DEC SP"); print "\t\t--SP;\n";
188 &case(0x3C, "INC A"); &INCr(AF, "h");
189 &case(0x3D, "DEC A"); &DECr(AF, "h");
190 &case(0x3E, "LD A,nn"); print "\t\tSethreg(AF, GetBYTE(PC)); ++PC;\n";
191 &case(0x3F, "CCF");
192 print "\t\tAF = (AF&~0x3b)|((AF>>8)&0x28)|((AF&1)<<4)|(~AF&1);\n";
193 &case(0x40, "LD B,B"); print "\t\t/* nop */\n";
194 &case(0x41, "LD B,C"); print "\t\tBC = (BC & 255) | ((BC & 255) << 8);\n";
195 &case(0x42, "LD B,D"); print "\t\tBC = (BC & 255) | (DE & ~255);\n";
196 &case(0x43, "LD B,E"); print "\t\tBC = (BC & 255) | ((DE & 255) << 8);\n";
197 &case(0x44, "LD B,H"); print "\t\tBC = (BC & 255) | (HL & ~255);\n";
198 &case(0x45, "LD B,L"); print "\t\tBC = (BC & 255) | ((HL & 255) << 8);\n";
199 &case(0x46, "LD B,(HL)"); print "\t\tSethreg(BC, GetBYTE(HL));\n";
200 &case(0x47, "LD B,A"); print "\t\tBC = (BC & 255) | (AF & ~255);\n";
201 &case(0x48, "LD C,B"); print "\t\tBC = (BC & ~255) | ((BC >> 8) & 255);\n";
202 &case(0x49, "LD C,C"); print "\t\t/* nop */\n";
203 &case(0x4A, "LD C,D"); print "\t\tBC = (BC & ~255) | ((DE >> 8) & 255);\n";
204 &case(0x4B, "LD C,E"); print "\t\tBC = (BC & ~255) | (DE & 255);\n";
205 &case(0x4C, "LD C,H"); print "\t\tBC = (BC & ~255) | ((HL >> 8) & 255);\n";
206 &case(0x4D, "LD C,L"); print "\t\tBC = (BC & ~255) | (HL & 255);\n";
207 &case(0x4E, "LD C,(HL)"); print "\t\tSetlreg(BC, GetBYTE(HL));\n";
208 &case(0x4F, "LD C,A"); print "\t\tBC = (BC & ~255) | ((AF >> 8) & 255);\n";
209 &case(0x50, "LD D,B"); print "\t\tDE = (DE & 255) | (BC & ~255);\n";
210 &case(0x51, "LD D,C"); print "\t\tDE = (DE & 255) | ((BC & 255) << 8);\n";
211 &case(0x52, "LD D,D"); print "\t\t/* nop */\n";
212 &case(0x53, "LD D,E"); print "\t\tDE = (DE & 255) | ((DE & 255) << 8);\n";
213 &case(0x54, "LD D,H"); print "\t\tDE = (DE & 255) | (HL & ~255);\n";
214 &case(0x55, "LD D,L"); print "\t\tDE = (DE & 255) | ((HL & 255) << 8);\n";
215 &case(0x56, "LD D,(HL)"); print "\t\tSethreg(DE, GetBYTE(HL));\n";
216 &case(0x57, "LD D,A"); print "\t\tDE = (DE & 255) | (AF & ~255);\n";
217 &case(0x58, "LD E,B"); print "\t\tDE = (DE & ~255) | ((BC >> 8) & 255);\n";
218 &case(0x59, "LD E,C"); print "\t\tDE = (DE & ~255) | (BC & 255);\n";
219 &case(0x5A, "LD E,D"); print "\t\tDE = (DE & ~255) | ((DE >> 8) & 255);\n";
220 &case(0x5B, "LD E,E"); print "\t\t/* nop */\n";
221 &case(0x5C, "LD E,H"); print "\t\tDE = (DE & ~255) | ((HL >> 8) & 255);\n";
222 &case(0x5D, "LD E,L"); print "\t\tDE = (DE & ~255) | (HL & 255);\n";
223 &case(0x5E, "LD E,(HL)"); print "\t\tSetlreg(DE, GetBYTE(HL));\n";
224 &case(0x5F, "LD E,A"); print "\t\tDE = (DE & ~255) | ((AF >> 8) & 255);\n";
225 &case(0x60, "LD H,B"); print "\t\tHL = (HL & 255) | (BC & ~255);\n";
226 &case(0x61, "LD H,C"); print "\t\tHL = (HL & 255) | ((BC & 255) << 8);\n";
227 &case(0x62, "LD H,D"); print "\t\tHL = (HL & 255) | (DE & ~255);\n";
228 &case(0x63, "LD H,E"); print "\t\tHL = (HL & 255) | ((DE & 255) << 8);\n";
229 &case(0x64, "LD H,H"); print "\t\t/* nop */\n";
230 &case(0x65, "LD H,L"); print "\t\tHL = (HL & 255) | ((HL & 255) << 8);\n";
231 &case(0x66, "LD H,(HL)"); print "\t\tSethreg(HL, GetBYTE(HL));\n";
232 &case(0x67, "LD H,A"); print "\t\tHL = (HL & 255) | (AF & ~255);\n";
233 &case(0x68, "LD L,B"); print "\t\tHL = (HL & ~255) | ((BC >> 8) & 255);\n";
234 &case(0x69, "LD L,C"); print "\t\tHL = (HL & ~255) | (BC & 255);\n";
235 &case(0x6A, "LD L,D"); print "\t\tHL = (HL & ~255) | ((DE >> 8) & 255);\n";
236 &case(0x6B, "LD L,E"); print "\t\tHL = (HL & ~255) | (DE & 255);\n";
237 &case(0x6C, "LD L,H"); print "\t\tHL = (HL & ~255) | ((HL >> 8) & 255);\n";
238 &case(0x6D, "LD L,L"); print "\t\t/* nop */\n";
239 &case(0x6E, "LD L,(HL)"); print "\t\tSetlreg(HL, GetBYTE(HL));\n";
240 &case(0x6F, "LD L,A"); print "\t\tHL = (HL & ~255) | ((AF >> 8) & 255);\n";
241 &case(0x70, "LD (HL),B"); print "\t\tPutBYTE(HL, hreg(BC));\n";
242 &case(0x71, "LD (HL),C"); print "\t\tPutBYTE(HL, lreg(BC));\n";
243 &case(0x72, "LD (HL),D"); print "\t\tPutBYTE(HL, hreg(DE));\n";
244 &case(0x73, "LD (HL),E"); print "\t\tPutBYTE(HL, lreg(DE));\n";
245 &case(0x74, "LD (HL),H"); print "\t\tPutBYTE(HL, hreg(HL));\n";
246 &case(0x75, "LD (HL),L"); print "\t\tPutBYTE(HL, lreg(HL));\n";
247 &case(0x76, "HALT"); print "\t\tSAVE_STATE();\n\t\treturn PC&0xffff;\n"; $needbreak = 0;
248 &case(0x77, "LD (HL),A"); print "\t\tPutBYTE(HL, hreg(AF));\n";
249 &case(0x78, "LD A,B"); print "\t\tAF = (AF & 255) | (BC & ~255);\n";
250 &case(0x79, "LD A,C"); print "\t\tAF = (AF & 255) | ((BC & 255) << 8);\n";
251 &case(0x7A, "LD A,D"); print "\t\tAF = (AF & 255) | (DE & ~255);\n";
252 &case(0x7B, "LD A,E"); print "\t\tAF = (AF & 255) | ((DE & 255) << 8);\n";
253 &case(0x7C, "LD A,H"); print "\t\tAF = (AF & 255) | (HL & ~255);\n";
254 &case(0x7D, "LD A,L"); print "\t\tAF = (AF & 255) | ((HL & 255) << 8);\n";
255 &case(0x7E, "LD A,(HL)"); print "\t\tSethreg(AF, GetBYTE(HL));\n";
256 &case(0x7F, "LD A,A"); print "\t\t/* nop */\n";
257 &case(0x80, "ADD A,B"); &ADDAr("hreg(BC)");
258 &case(0x81, "ADD A,C"); &ADDAr("lreg(BC)");
259 &case(0x82, "ADD A,D"); &ADDAr("hreg(DE)");
260 &case(0x83, "ADD A,E"); &ADDAr("lreg(DE)");
261 &case(0x84, "ADD A,H"); &ADDAr("hreg(HL)");
262 &case(0x85, "ADD A,L"); &ADDAr("lreg(HL)");
263 &case(0x86, "ADD A,(HL)"); &ADDAr("GetBYTE(HL)");
264 &case(0x87, "ADD A,A"); &ADDAr("hreg(AF)");
265 &case(0x88, "ADC A,B"); &ADCAr("hreg(BC)");
266 &case(0x89, "ADC A,C"); &ADCAr("lreg(BC)");
267 &case(0x8A, "ADC A,D"); &ADCAr("hreg(DE)");
268 &case(0x8B, "ADC A,E"); &ADCAr("lreg(DE)");
269 &case(0x8C, "ADC A,H"); &ADCAr("hreg(HL)");
270 &case(0x8D, "ADC A,L"); &ADCAr("lreg(HL)");
271 &case(0x8E, "ADC A,(HL)"); &ADCAr("GetBYTE(HL)");
272 &case(0x8F, "ADC A,A"); &ADCAr("hreg(AF)");
273 &case(0x90, "SUB B"); &SUBAr("hreg(BC)");
274 &case(0x91, "SUB C"); &SUBAr("lreg(BC)");
275 &case(0x92, "SUB D"); &SUBAr("hreg(DE)");
276 &case(0x93, "SUB E"); &SUBAr("lreg(DE)");
277 &case(0x94, "SUB H"); &SUBAr("hreg(HL)");
278 &case(0x95, "SUB L"); &SUBAr("lreg(HL)");
279 &case(0x96, "SUB (HL)"); &SUBAr("GetBYTE(HL)");
280 &case(0x97, "SUB A"); &SUBAr("hreg(AF)");
281 &case(0x98, "SBC A,B"); &SBCAr("hreg(BC)");
282 &case(0x99, "SBC A,C"); &SBCAr("lreg(BC)");
283 &case(0x9A, "SBC A,D"); &SBCAr("hreg(DE)");
284 &case(0x9B, "SBC A,E"); &SBCAr("lreg(DE)");
285 &case(0x9C, "SBC A,H"); &SBCAr("hreg(HL)");
286 &case(0x9D, "SBC A,L"); &SBCAr("lreg(HL)");
287 &case(0x9E, "SBC A,(HL)"); &SBCAr("GetBYTE(HL)");
288 &case(0x9F, "SBC A,A"); &SBCAr("hreg(AF)");
289 &case(0xA0, "AND B"); &ANDAh("&", "BC");
290 &case(0xA1, "AND C"); &ANDAl("&", "BC");
291 &case(0xA2, "AND D"); &ANDAh("&", "DE");
292 &case(0xA3, "AND E"); &ANDAl("&", "DE");
293 &case(0xA4, "AND H"); &ANDAh("&", "HL");
294 &case(0xA5, "AND L"); &ANDAl("&", "HL");
295 &case(0xA6, "AND (HL)"); &ANDAl("&", "GetBYTE(HL)");
296 &case(0xA7, "AND A"); &ANDAh("&", "AF");
297 &case(0xA8, "XOR B"); &LOGAh("^", "BC");
298 &case(0xA9, "XOR C"); &LOGAl("^", "BC");
299 &case(0xAA, "XOR D"); &LOGAh("^", "DE");
300 &case(0xAB, "XOR E"); &LOGAl("^", "DE");
301 &case(0xAC, "XOR H"); &LOGAh("^", "HL");
302 &case(0xAD, "XOR L"); &LOGAl("^", "HL");
303 &case(0xAE, "XOR (HL)"); &LOGAl("^", "GetBYTE(HL)");
304 &case(0xAF, "XOR A"); &LOGAh("^", "AF");
305 &case(0xB0, "OR B"); &LOGAh("|", "BC");
306 &case(0xB1, "OR C"); &LOGAl("|", "BC");
307 &case(0xB2, "OR D"); &LOGAh("|", "DE");
308 &case(0xB3, "OR E"); &LOGAl("|", "DE");
309 &case(0xB4, "OR H"); &LOGAh("|", "HL");
310 &case(0xB5, "OR L"); &LOGAl("|", "HL");
311 &case(0xB6, "OR (HL)"); &LOGAl("|", "GetBYTE(HL)");
312 &case(0xB7, "OR A"); &LOGAh("|", "AF");
313 &case(0xB8, "CP B"); &CPAr("hreg(BC)");
314 &case(0xB9, "CP C"); &CPAr("lreg(BC)");
315 &case(0xBA, "CP D"); &CPAr("hreg(DE)");
316 &case(0xBB, "CP E"); &CPAr("lreg(DE)");
317 &case(0xBC, "CP H"); &CPAr("hreg(HL)");
318 &case(0xBD, "CP L"); &CPAr("lreg(HL)");
319 &case(0xBE, "CP (HL)"); &CPAr("GetBYTE(HL)");
320 &case(0xBF, "CP A"); &CPAr("hreg(AF)");
321 &case(0xC0, "RET NZ"); print "\t\tif (!TSTFLAG(Z)) POP(PC);\n";
322 &case(0xC1, "POP BC"); print "\t\tPOP(BC);\n";
323 &case(0xC2, "JP NZ,nnnn"); print "\t\tJPC(!TSTFLAG(Z));\n";
324 &case(0xC3, "JP nnnn"); print "\t\tJPC(1);\n";
325 &case(0xC4, "CALL NZ,nnnn"); print "\t\tCALLC(!TSTFLAG(Z));\n";
326 &case(0xC5, "PUSH BC"); print "\t\tPUSH(BC);\n";
327 &case(0xC6, "ADD A,nn"); &ADDAr("GetBYTE(PC)"); print "\t\t++PC;\n";
328 &case(0xC7, "RST 0"); print "\t\tPUSH(PC); PC = 0;\n";
329 &case(0xC8, "RET Z"); print "\t\tif (TSTFLAG(Z)) POP(PC);\n";
330 &case(0xC9, "RET"); print "\t\tPOP(PC);\n";
331 &case(0xCA, "JP Z,nnnn"); print "\t\tJPC(TSTFLAG(Z));\n";
332 &case(0xCB, "CB prefix"); &CB("HL");
333 &case(0xCC, "CALL Z,nnnn"); print "\t\tCALLC(TSTFLAG(Z));\n";
334 &case(0xCD, "CALL nnnn"); print "\t\tCALLC(1);\n";
335 &case(0xCE, "ADC A,nn"); &ADCAr("GetBYTE(PC)"); print "\t\t++PC;\n";
336 &case(0xCF, "RST 8"); print "\t\tPUSH(PC); PC = 8;\n";
337 &case(0xD0, "RET NC"); print "\t\tif (!TSTFLAG(C)) POP(PC);\n";
338 &case(0xD1, "POP DE"); print "\t\tPOP(DE);\n";
339 &case(0xD2, "JP NC,nnnn"); print "\t\tJPC(!TSTFLAG(C));\n";
340 &case(0xD3, "OUT (nn),A"); print "\t\tOutput(GetBYTE(PC), hreg(AF)); ++PC;\n";
341 &case(0xD4, "CALL NC,nnnn"); print "\t\tCALLC(!TSTFLAG(C));\n";
342 &case(0xD5, "PUSH DE"); print "\t\tPUSH(DE);\n";
343 &case(0xD6, "SUB nn"); &SUBAr("GetBYTE(PC)"); print "\t\t++PC;\n";
344 &case(0xD7, "RST 10H"); print "\t\tPUSH(PC); PC = 0x10;\n";
345 &case(0xD8, "RET C"); print "\t\tif (TSTFLAG(C)) POP(PC);\n";
346 &case(0xD9, "EXX"); print <<"EOT";
347 regs[regs_sel].bc = BC;
348 regs[regs_sel].de = DE;
349 regs[regs_sel].hl = HL;
350 regs_sel = 1 - regs_sel;
351 BC = regs[regs_sel].bc;
352 DE = regs[regs_sel].de;
353 HL = regs[regs_sel].hl;
355 &case(0xDA, "JP C,nnnn"); print "\t\tJPC(TSTFLAG(C));\n";
356 &case(0xDB, "IN A,(nn)"); print "\t\tSethreg(AF, Input(GetBYTE(PC))); ++PC;\n";
357 &case(0xDC, "CALL C,nnnn"); print "\t\tCALLC(TSTFLAG(C));\n";
358 &case(0xDD, "DD prefix"); $dfd_inline ? &DFD("IX") : &DFD("ix");
359 &case(0xDE, "SBC A,nn"); &SBCAr("GetBYTE(PC)"); print "\t\t++PC;\n";
360 &case(0xDF, "RST 18H"); print "\t\tPUSH(PC); PC = 0x18;\n";
361 &case(0xE0, "RET PO"); print "\t\tif (!TSTFLAG(P)) POP(PC);\n";
362 &case(0xE1, "POP HL"); print "\t\tPOP(HL);\n";
363 &case(0xE2, "JP PO,nnnn"); print "\t\tJPC(!TSTFLAG(P));\n";
364 &case(0xE3, "EX (SP),HL"); print "\t\ttemp = HL; POP(HL); PUSH(temp);\n";
365 &case(0xE4, "CALL PO,nnnn"); print "\t\tCALLC(!TSTFLAG(P));\n";
366 &case(0xE5, "PUSH HL"); print "\t\tPUSH(HL);\n";
367 &case(0xE6, "AND nn"); &ANDAl("&", "GetBYTE(PC)"); print "\t\t++PC;\n";
368 &case(0xE7, "RST 20H"); print "\t\tPUSH(PC); PC = 0x20;\n";
369 &case(0xE8, "RET PE"); print "\t\tif (TSTFLAG(P)) POP(PC);\n";
370 &case(0xE9, "JP (HL)"); print "\t\tPC = HL;\n";
371 &case(0xEA, "JP PE,nnnn"); print "\t\tJPC(TSTFLAG(P));\n";
372 &case(0xEB, "EX DE,HL"); print "\t\ttemp = HL; HL = DE; DE = temp;\n";
373 &case(0xEC, "CALL PE,nnnn"); print "\t\tCALLC(TSTFLAG(P));\n";
374 &case(0xED, "ED prefix"); &ED("HL");
375 &case(0xEE, "XOR nn"); &LOGAl("^", "GetBYTE(PC)"); print "\t\t++PC;\n";
376 &case(0xEF, "RST 28H"); print "\t\tPUSH(PC); PC = 0x28;\n";
377 &case(0xF0, "RET P"); print "\t\tif (!TSTFLAG(S)) POP(PC);\n";
378 &case(0xF1, "POP AF"); print "\t\tPOP(AF);\n";
379 &case(0xF2, "JP P,nnnn"); print "\t\tJPC(!TSTFLAG(S));\n";
380 &case(0xF3, "DI"); print "\t\tIFF = 0;\n";
381 &case(0xF4, "CALL P,nnnn"); print "\t\tCALLC(!TSTFLAG(S));\n";
382 &case(0xF5, "PUSH AF"); print "\t\tPUSH(AF);\n";
383 &case(0xF6, "OR nn"); &LOGAl("|", "GetBYTE(PC)"); print "\t\t++PC;\n";
384 &case(0xF7, "RST 30H"); print "\t\tPUSH(PC); PC = 0x30;\n";
385 &case(0xF8, "RET M"); print "\t\tif (TSTFLAG(S)) POP(PC);\n";
386 &case(0xF9, "LD SP,HL"); print "\t\tSP = HL;\n";
387 &case(0xFA, "JP M,nnnn"); print "\t\tJPC(TSTFLAG(S));\n";
388 &case(0xFB, "EI"); print "\t\tIFF = 3;\n";
389 &case(0xFC, "CALL M,nnnn"); print "\t\tCALLC(TSTFLAG(S));\n";
390 &case(0xFD, "FD prefix"); $dfd_inline ? &DFD("IY") : &DFD("iy");
391 &case(0xFE, "CP nn"); &CPAr("GetBYTE(PC)"); print "\t\t++PC;\n";
392 &case(0xFF, "RST 38H"); print "\t\tPUSH(PC); PC = 0x38;\n";
394 &postamble;
396 sub case {
397 local($op,$cmnt) = @_;
398 if ($needbreak) {
399 print $optab ? "${tab}\tcontinue;\n" : "${tab}\tbreak;\n";
401 $needbreak = 1;
402 printf("${tab}case 0x%02X:\t\t\t/* $cmnt */\n", $op) if !$optab;
403 printf("${tab}op_%02x:\t\t\t/* $cmnt */\n", $op) if $optab;
406 sub JRcond {
407 local($cond) = @_;
408 print "${tab}\tPC += ($cond) ? (signed char) GetBYTE(PC) + 1 : 1;\n";
411 sub LDmemr {
412 local($reg,$which) = @_;
413 print "${tab}\ttemp = GetWORD(PC);\n";
414 print "${tab}\tPutBYTE(temp, ${which}reg($reg));\n";
415 if ($combine && $labpcp2) {
416 print "${tab}\tgoto labpcp2;\n";
417 $needbreak = 0;
419 else {
420 $labpcp2 = 1;
421 print "${tab}labpcp2:\n" if $combine;
422 print "${tab}\tPC += 2;\n";
426 sub LDrmem {
427 local($reg,$which) = @_;
428 print "${tab}\ttemp = GetWORD(PC);\n";
429 print "${tab}\tSet${which}reg($reg, GetBYTE(temp));\n";
430 if ($combine && $labpcp2) {
431 print "${tab}\tgoto labpcp2;\n";
432 $needbreak = 0;
434 else {
435 $labpcp2 = 1;
436 print "${tab}labpcp2:\n" if $combine;
437 print "${tab}\tPC += 2;\n";
441 sub LDddmem {
442 local($reg) = @_;
443 print "${tab}\ttemp = GetWORD(PC);\n";
444 print "${tab}\t$reg = GetWORD(temp);\n";
445 if ($combine && $labpcp2) {
446 print "${tab}\tgoto labpcp2;\n";
447 $needbreak = 0;
449 else {
450 $labpcp2 = 1;
451 print "${tab}labpcp2:\n" if $combine;
452 print "${tab}\tPC += 2;\n";
456 sub LDmemdd {
457 local($reg) = @_;
458 print "${tab}\ttemp = GetWORD(PC);\n";
459 print "${tab}\tPutWORD(temp, $reg);\n";
460 if ($combine && $labpcp2) {
461 print "${tab}\tgoto labpcp2;\n";
462 $needbreak = 0;
464 else {
465 $labpcp2 = 1;
466 print "${tab}labpcp2:\n" if $combine;
467 print "${tab}\tPC += 2;\n";
471 sub LDddnn {
472 local($reg) = @_;
473 print "${tab}\t$reg = GetWORD(PC);\n";
474 if ($combine && $labpcp2) {
475 print "${tab}\tgoto labpcp2;\n";
476 $needbreak = 0;
478 else {
479 $labpcp2 = 1;
480 print "${tab}labpcp2:\n" if $combine;
481 print "${tab}\tPC += 2;\n";
485 sub INCr {
486 local($reg,$which) = @_;
487 if ($which eq "h") {
488 print "${tab}\t$reg += 0x100;\n${tab}\ttemp = hreg($reg);\n";
490 else {
491 print "${tab}\ttemp = ${which}reg($reg)+1;\n${tab}\tSet${which}reg($reg, temp);\n";
493 if ($combine && $labincr) {
494 print "${tab}\tgoto labincr;\n";
495 $needbreak = 0;
497 else {
498 $labincr = 1;
499 print "${tab}labincr:\n" if $combine;
500 print <<"EOT";
501 $tab AF = (AF & ~0xfe) | (temp & 0xa8) |
502 $tab (((temp & 0xff) == 0) << 6) |
503 $tab (((temp & 0xf) == 0) << 4) |
504 $tab ((temp == 0x80) << 2);
509 sub INCm {
510 local($reg) = @_;
511 print "${tab}\ttemp = GetBYTE($reg)+1;\n${tab}\tPutBYTE($reg, temp);\n";
512 if ($combine && $labincr) {
513 print "${tab}\tgoto labincr;\n";
514 $needbreak = 0;
516 else {
517 $labincr = 1;
518 print "${tab}labincr:\n" if $combine;
519 print <<"EOT";
520 $tab AF = (AF & ~0xfe) | (temp & 0xa8) |
521 $tab (((temp & 0xff) == 0) << 6) |
522 $tab (((temp & 0xf) == 0) << 4) |
523 $tab ((temp == 0x80) << 2);
528 sub DECr {
529 local($reg,$which) = @_;
530 if ($which eq "h") {
531 print "${tab}\t$reg -= 0x100;\n${tab}\ttemp = hreg($reg);\n";
533 else {
534 print "${tab}\ttemp = ${which}reg($reg)-1;\n${tab}\tSet${which}reg($reg, temp);\n";
536 if ($combine && $labdecr) {
537 print "${tab}\tgoto labdecr;\n";
538 $needbreak = 0;
540 else {
541 $labdecr = 1;
542 print "${tab}labdecr:\n" if $combine;
543 print <<"EOT";
544 $tab AF = (AF & ~0xfe) | (temp & 0xa8) |
545 $tab (((temp & 0xff) == 0) << 6) |
546 $tab (((temp & 0xf) == 0xf) << 4) |
547 $tab ((temp == 0x7f) << 2) | 2;
552 sub DECm {
553 local($reg) = @_;
554 print "${tab}\ttemp = GetBYTE($reg)-1;\n${tab}\tPutBYTE($reg, temp);\n";
555 if ($combine && $labdecr) {
556 print "${tab}\tgoto labdecr;\n";
557 $needbreak = 0;
559 else {
560 $labdecr = 1;
561 print "${tab}labdecr:\n" if $combine;
562 print <<"EOT";
563 $tab AF = (AF & ~0xfe) | (temp & 0xa8) |
564 $tab (((temp & 0xff) == 0) << 6) |
565 $tab (((temp & 0xf) == 0xf) << 4) |
566 $tab ((temp == 0x7f) << 2) | 2;
571 sub ADDAr {
572 local($val) = @_;
573 print "${tab}\ttemp = $val;\n";
574 if ($combine && $labaddar) {
575 print "${tab}\tgoto labaddar;\n";
576 $needbreak = 0;
578 else {
579 $labaddar = 1;
580 print "${tab}labaddar:\n" if $combine;
581 print <<"EOT";
582 $tab acu = hreg(AF);
583 $tab sum = acu + temp;
584 $tab cbits = acu ^ temp ^ sum;
585 $tab AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
586 $tab (((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
587 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) |
588 $tab ((cbits >> 8) & 1);
593 sub ADCAr {
594 local($val) = @_;
595 print "${tab}\ttemp = $val;\n";
596 if ($combine && $labadcar) {
597 print "${tab}\tgoto labadcar;\n";
598 $needbreak = 0;
600 else {
601 $labadcar = 1;
602 print "${tab}labadcar:\n" if $combine;
603 print <<"EOT";
604 $tab acu = hreg(AF);
605 $tab sum = acu + temp + TSTFLAG(C);
606 $tab cbits = acu ^ temp ^ sum;
607 $tab AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
608 $tab (((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
609 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) |
610 $tab ((cbits >> 8) & 1);
615 sub SUBAr {
616 local($val) = @_;
617 print "${tab}\ttemp = $val;\n";
618 if ($combine && $labsubar) {
619 print "${tab}\tgoto labsubar;\n";
620 $needbreak = 0;
622 else {
623 $labsubar = 1;
624 print "${tab}labsubar:\n" if $combine;
625 print <<"EOT";
626 $tab acu = hreg(AF);
627 $tab sum = acu - temp;
628 $tab cbits = acu ^ temp ^ sum;
629 $tab AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
630 $tab (((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
631 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
632 $tab ((cbits >> 8) & 1);
637 sub SBCAr {
638 local($val) = @_;
639 print "${tab}\ttemp = $val;\n";
640 if ($combine && $labsbcar) {
641 print "${tab}\tgoto labsbcar;\n";
642 $needbreak = 0;
644 else {
645 $labsbcar = 1;
646 print "${tab}labsbcar:\n" if $combine;
647 print <<"EOT";
648 $tab acu = hreg(AF);
649 $tab sum = acu - temp - TSTFLAG(C);
650 $tab cbits = acu ^ temp ^ sum;
651 $tab AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
652 $tab (((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
653 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
654 $tab ((cbits >> 8) & 1);
659 sub ANDAh {
660 local($op, $reg) = @_;
661 print "${tab}\tsum = ((AF $op ($reg)) >> 8) & 0xff;\n";
662 if ($combine && $labandar) {
663 print "${tab}\tgoto labandar;\n";
664 $needbreak = 0;
666 else {
667 $labandar = 1;
668 print "${tab}labandar:\n" if $combine;
669 print "${tab}\tAF = (sum << 8) | (sum & 0xa8) |\n";
670 print "${tab}\t\t((sum == 0) << 6) | 0x10 | partab[sum];\n";
674 sub ANDAl {
675 local($op, $reg) = @_;
676 print "${tab}\tsum = ((AF >> 8) $op $reg) & 0xff;\n";
677 if ($combine && $labandar) {
678 print "${tab}\tgoto labandar;\n";
679 $needbreak = 0;
681 else {
682 $labandar = 1;
683 print "${tab}labandar:\n" if $combine;
684 print "${tab}\tAF = (sum << 8) | (sum & 0xa8) | 0x10 |\n";
685 print "${tab}\t\t((sum == 0) << 6) | partab[sum];\n";
689 sub LOGAh {
690 local($op, $reg) = @_;
691 print "${tab}\tsum = ((AF $op ($reg)) >> 8) & 0xff;\n";
692 if ($combine && $lablogar) {
693 print "${tab}\tgoto lablogar;\n";
694 $needbreak = 0;
696 else {
697 $lablogar = 1;
698 print "${tab}lablogar:\n" if $combine;
699 print
700 "${tab}\tAF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];\n";
704 sub LOGAl {
705 local($op, $reg) = @_;
706 print "${tab}\tsum = ((AF >> 8) $op $reg) & 0xff;\n";
707 if ($combine && $lablogar) {
708 print "${tab}\tgoto lablogar;\n";
709 $needbreak = 0;
711 else {
712 $lablogar = 1;
713 print "${tab}lablogar:\n" if $combine;
714 print
715 "${tab}\tAF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];\n";
719 sub CPAr {
720 local($reg) = @_;
721 print "${tab}\ttemp = $reg;\n";
722 print "${tab}\tAF = (AF & ~0x28) | (temp & 0x28);\n";
723 if ($combine && $labcpar) {
724 print "${tab}\tgoto labcpar;\n";
725 $needbreak = 0;
727 else {
728 $labcpar = 1;
729 print "${tab}labcpar:\n" if $combine;
730 print <<"EOT";
731 $tab acu = hreg(AF);
732 $tab sum = acu - temp;
733 $tab cbits = acu ^ temp ^ sum;
734 $tab AF = (AF & ~0xff) | (sum & 0x80) |
735 $tab (((sum & 0xff) == 0) << 6) | (temp & 0x28) |
736 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
737 $tab (cbits & 0x10) | ((cbits >> 8) & 1);
742 sub ADDdd {
743 local($r1,$r2) = @_;
744 print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
745 print <<"EOT";
746 $tab $r2 &= 0xffff;
747 $tab sum = $r1 + $r2;
748 $tab cbits = ($r1 ^ $r2 ^ sum) >> 8;
749 $tab $r1 = sum;
751 if ($combine && $labadddd) {
752 print "${tab}\tgoto labadddd;\n";
753 $needbreak = 0;
755 else {
756 $labadddd = 1;
757 print "${tab}labadddd:\n" if $combine;
758 print <<"EOT";
759 $tab AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
760 $tab (cbits & 0x10) | ((cbits >> 8) & 1);
765 sub ADCdd {
766 local($r1,$r2) = @_;
767 print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
768 print <<"EOT";
769 $tab $r2 &= 0xffff;
770 $tab sum = $r1 + $r2 + TSTFLAG(C);
771 $tab cbits = ($r1 ^ $r2 ^ sum) >> 8;
772 $tab $r1 = sum;
774 if ($combine && $labadcdd) {
775 print "${tab}\tgoto labadcdd;\n";
776 $needbreak = 0;
778 else {
779 $labadcdd = 1;
780 print "${tab}labadcdd:\n" if $combine;
781 print <<"EOT";
782 $tab AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
783 $tab (((sum & 0xffff) == 0) << 6) |
784 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) |
785 $tab (cbits & 0x10) | ((cbits >> 8) & 1);
790 sub SBCdd {
791 local($r1,$r2) = @_;
792 print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
793 print <<"EOT";
794 $tab $r2 &= 0xffff;
795 $tab sum = $r1 - $r2 - TSTFLAG(C);
796 $tab cbits = ($r1 ^ $r2 ^ sum) >> 8;
797 $tab $r1 = sum;
799 if ($combine && $labsbcdd) {
800 print "${tab}\tgoto labsbcdd;\n";
801 $needbreak = 0;
803 else {
804 $labsbcdd = 1;
805 print "${tab}labsbcdd:\n" if $combine;
806 print <<"EOT";
807 $tab AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
808 $tab (((sum & 0xffff) == 0) << 6) |
809 $tab (((cbits >> 6) ^ (cbits >> 5)) & 4) |
810 $tab (cbits & 0x10) | 2 | ((cbits >> 8) & 1);
815 sub INP {
816 local($reg,$which) = @_;
817 print <<"EOT";
818 $tab temp = Input(lreg(BC));
819 $tab Set${which}reg($reg, temp);
820 $tab AF = (AF & ~0xfe) | (temp & 0xa8) |
821 $tab (((temp & 0xff) == 0) << 6) |
822 $tab parity(temp);
826 sub OUTP {
827 local($reg,$which) = @_;
828 print <<"EOT";
829 $tab Output(lreg(BC), $reg);
833 sub CB {
834 local($reg) = @_;
835 if ($cb_inline) {
836 print "${tab}\tadr = $reg;\n";
837 &cb_switch;
839 else {
840 print <<"EOT";
841 $tab SAVE_STATE();
842 $tab cb_prefix($reg);
843 $tab LOAD_STATE();
848 sub cb_switch {
849 local($optabsav) = $optab;
850 $optab = 0;
851 $cblabno += 1;
852 print <<"EOT";
853 $tab switch ((op = GetBYTE(PC)) & 7) {
854 $tab case 0: ++PC; acu = hreg(BC); break;
855 $tab case 1: ++PC; acu = lreg(BC); break;
856 $tab case 2: ++PC; acu = hreg(DE); break;
857 $tab case 3: ++PC; acu = lreg(DE); break;
858 $tab case 4: ++PC; acu = hreg(HL); break;
859 $tab case 5: ++PC; acu = lreg(HL); break;
860 $tab case 6: ++PC; acu = GetBYTE(adr); break;
861 $tab case 7: ++PC; acu = hreg(AF); break;
862 $tab }
863 $tab switch (op & 0xc0) {
864 $tab case 0x00: /* shift/rotate */
865 $tab switch (op & 0x38) {
866 $tab case 0x00: /* RLC */
867 $tab temp = (acu << 1) | (acu >> 7);
868 $tab cbits = temp & 1;
869 $tab goto cbshflg$cblabno;
870 $tab case 0x08: /* RRC */
871 $tab temp = (acu >> 1) | (acu << 7);
872 $tab cbits = temp & 0x80;
873 $tab goto cbshflg$cblabno;
874 $tab case 0x10: /* RL */
875 $tab temp = (acu << 1) | TSTFLAG(C);
876 $tab cbits = acu & 0x80;
877 $tab goto cbshflg$cblabno;
878 $tab case 0x18: /* RR */
879 $tab temp = (acu >> 1) | (TSTFLAG(C) << 7);
880 $tab cbits = acu & 1;
881 $tab goto cbshflg$cblabno;
882 $tab case 0x20: /* SLA */
883 $tab temp = acu << 1;
884 $tab cbits = acu & 0x80;
885 $tab goto cbshflg$cblabno;
886 $tab case 0x28: /* SRA */
887 $tab temp = (acu >> 1) | (acu & 0x80);
888 $tab cbits = acu & 1;
889 $tab goto cbshflg$cblabno;
890 $tab case 0x30: /* SLIA */
891 $tab temp = (acu << 1) | 1;
892 $tab cbits = acu & 0x80;
893 $tab goto cbshflg$cblabno;
894 $tab case 0x38: /* SRL */
895 $tab temp = acu >> 1;
896 $tab cbits = acu & 1;
897 $tab cbshflg$cblabno:
898 $tab AF = (AF & ~0xff) | (temp & 0xa8) |
899 $tab (((temp & 0xff) == 0) << 6) |
900 $tab parity(temp) | !!cbits;
901 $tab }
902 $tab break;
903 $tab case 0x40: /* BIT */
904 $tab if (acu & (1 << ((op >> 3) & 7)))
905 $tab AF = (AF & ~0xfe) | 0x10 |
906 $tab (((op & 0x38) == 0x38) << 7);
907 $tab else
908 $tab AF = (AF & ~0xfe) | 0x54;
909 $tab if ((op&7) != 6)
910 $tab AF |= (acu & 0x28);
911 $tab temp = acu;
912 $tab break;
913 $tab case 0x80: /* RES */
914 $tab temp = acu & ~(1 << ((op >> 3) & 7));
915 $tab break;
916 $tab case 0xc0: /* SET */
917 $tab temp = acu | (1 << ((op >> 3) & 7));
918 $tab break;
919 $tab }
920 $tab switch (op & 7) {
921 $tab case 0: Sethreg(BC, temp); break;
922 $tab case 1: Setlreg(BC, temp); break;
923 $tab case 2: Sethreg(DE, temp); break;
924 $tab case 3: Setlreg(DE, temp); break;
925 $tab case 4: Sethreg(HL, temp); break;
926 $tab case 5: Setlreg(HL, temp); break;
927 $tab case 6: PutBYTE(adr, temp); break;
928 $tab case 7: Sethreg(AF, temp); break;
929 $tab }
931 $optab = $optabsav;
935 sub DFD {
936 local($reg) = @_;
937 if ($dfd_inline) {
938 &dfd_switch($reg);
940 else {
941 print <<"EOT";
942 $tab SAVE_STATE();
943 $tab $reg = dfd_prefix($reg);
944 $tab LOAD_STATE();
949 sub Offsadr {
950 local($reg) = @_;
951 print "${tab}\tadr = $reg + (signed char) GetBYTE(PC); ++PC;\n";
954 sub dfd_switch {
955 local($reg) = @_;
956 local($optabsav) = $optab;
957 $optab = 0;
958 print "${tab}\tswitch (++PC, op = GetBYTE(PC-1)) {\n";
959 $tab = "\t\t";
960 $needbreak = 0;
961 &case(0x09, "ADD $reg,BC"); &ADDdd($reg, BC);
962 &case(0x19, "ADD $reg,DE"); &ADDdd($reg, DE);
963 &case(0x21, "LD $reg,nnnn"); &LDddnn($reg);
964 &case(0x22, "LD (nnnn),$reg"); &LDmemdd($reg);
965 &case(0x23, "INC $reg"); print "${tab}\t++$reg;\n";
966 &case(0x24, "INC ${reg}H"); &INCr($reg, "h");
967 &case(0x25, "DEC ${reg}H"); &DECr($reg, "h");
968 &case(0x26, "LD ${reg}H,nn"); print "${tab}\tSethreg($reg, GetBYTE(PC)); ++PC;\n";
969 &case(0x29, "ADD $reg,$reg"); &ADDdd($reg, $reg);
970 &case(0x2A, "LD $reg,(nnnn)"); &LDddmem($reg);
971 &case(0x2B, "DEC $reg"); print "${tab}\t--$reg;\n";
972 &case(0x2C, "INC ${reg}L"); &INCr($reg, "l");
973 &case(0x2D, "DEC ${reg}L"); &DECr($reg, "l");
974 &case(0x2E, "LD ${reg}L,nn"); print "${tab}\tSetlreg($reg, GetBYTE(PC)); ++PC;\n";
975 &case(0x34, "INC ($reg+dd)"); &Offsadr($reg); &INCm("adr");
976 &case(0x35, "DEC ($reg+dd)"); &Offsadr($reg); &DECm("adr");
977 &case(0x36, "LD ($reg+dd),nn"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, GetBYTE(PC)); ++PC;\n";
978 &case(0x39, "ADD $reg,SP"); &ADDdd($reg, SP);
979 &case(0x44, "LD B,${reg}H"); print "${tab}\tSethreg(BC, hreg($reg));\n";
980 &case(0x45, "LD B,${reg}L"); print "${tab}\tSethreg(BC, lreg($reg));\n";
981 &case(0x46, "LD B,($reg+dd)"); &Offsadr($reg); print "${tab}\tSethreg(BC, GetBYTE(adr));\n";
982 &case(0x4C, "LD C,${reg}H"); print "${tab}\tSetlreg(BC, hreg($reg));\n";
983 &case(0x4D, "LD C,${reg}L"); print "${tab}\tSetlreg(BC, lreg($reg));\n";
984 &case(0x4E, "LD C,($reg+dd)"); &Offsadr($reg); print "${tab}\tSetlreg(BC, GetBYTE(adr));\n";
985 &case(0x54, "LD D,${reg}H"); print "${tab}\tSethreg(DE, hreg($reg));\n";
986 &case(0x55, "LD D,${reg}L"); print "${tab}\tSethreg(DE, lreg($reg));\n";
987 &case(0x56, "LD D,($reg+dd)"); &Offsadr($reg); print "${tab}\tSethreg(DE, GetBYTE(adr));\n";
988 &case(0x5C, "LD E,H"); print "${tab}\tSetlreg(DE, hreg($reg));\n";
989 &case(0x5D, "LD E,L"); print "${tab}\tSetlreg(DE, lreg($reg));\n";
990 &case(0x5E, "LD E,($reg+dd)"); &Offsadr($reg); print "${tab}\tSetlreg(DE, GetBYTE(adr));\n";
991 &case(0x60, "LD ${reg}H,B"); print "${tab}\tSethreg($reg, hreg(BC));\n";
992 &case(0x61, "LD ${reg}H,C"); print "${tab}\tSethreg($reg, lreg(BC));\n";
993 &case(0x62, "LD ${reg}H,D"); print "${tab}\tSethreg($reg, hreg(DE));\n";
994 &case(0x63, "LD ${reg}H,E"); print "${tab}\tSethreg($reg, lreg(DE));\n";
995 &case(0x64, "LD ${reg}H,${reg}H"); print "${tab}\t/* nop */\n";
996 &case(0x65, "LD ${reg}H,${reg}L"); print "${tab}\tSethreg($reg, lreg($reg));\n";
997 &case(0x66, "LD H,($reg+dd)"); &Offsadr($reg); print "${tab}\tSethreg(HL, GetBYTE(adr));\n";
998 &case(0x67, "LD ${reg}H,A"); print "${tab}\tSethreg($reg, hreg(AF));\n";
999 &case(0x68, "LD ${reg}L,B"); print "${tab}\tSetlreg($reg, hreg(BC));\n";
1000 &case(0x69, "LD ${reg}L,C"); print "${tab}\tSetlreg($reg, lreg(BC));\n";
1001 &case(0x6A, "LD ${reg}L,D"); print "${tab}\tSetlreg($reg, hreg(DE));\n";
1002 &case(0x6B, "LD ${reg}L,E"); print "${tab}\tSetlreg($reg, lreg(DE));\n";
1003 &case(0x6C, "LD ${reg}L,${reg}H"); print "${tab}\tSetlreg($reg, hreg($reg));\n";
1004 &case(0x6D, "LD ${reg}L,${reg}L"); print "${tab}\t/* nop */\n";
1005 &case(0x6E, "LD L,($reg+dd)"); &Offsadr($reg); print "${tab}\tSetlreg(HL, GetBYTE(adr));\n";
1006 &case(0x6F, "LD ${reg}L,A"); print "${tab}\tSetlreg($reg, hreg(AF));\n";
1007 &case(0x70, "LD ($reg+dd),B"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(BC));\n";
1008 &case(0x71, "LD ($reg+dd),C"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(BC));\n";
1009 &case(0x72, "LD ($reg+dd),D"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(DE));\n";
1010 &case(0x73, "LD ($reg+dd),E"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(DE));\n";
1011 &case(0x74, "LD ($reg+dd),H"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(HL));\n";
1012 &case(0x75, "LD ($reg+dd),L"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(HL));\n";
1013 &case(0x77, "LD ($reg+dd),A"); &Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(AF));\n";
1014 &case(0x7C, "LD A,${reg}H"); print "${tab}\tSethreg(AF, hreg($reg));\n";
1015 &case(0x7D, "LD A,${reg}L"); print "${tab}\tSethreg(AF, lreg($reg));\n";
1016 &case(0x7E, "LD A,($reg+dd)"); &Offsadr($reg); print "${tab}\tSethreg(AF, GetBYTE(adr));\n";
1017 &case(0x84, "ADD A,${reg}H"); &ADDAr("hreg($reg)");
1018 &case(0x85, "ADD A,${reg}L"); &ADDAr("lreg($reg)");
1019 &case(0x86, "ADD A,($reg+dd)"); &Offsadr($reg); &ADDAr("GetBYTE(adr)");
1020 &case(0x8C, "ADC A,${reg}H"); &ADCAr("hreg($reg)");
1021 &case(0x8D, "ADC A,${reg}L"); &ADCAr("lreg($reg)");
1022 &case(0x8E, "ADC A,($reg+dd)"); &Offsadr($reg); &ADCAr("GetBYTE(adr)");
1023 &case(0x94, "SUB ${reg}H"); &SUBAr("hreg($reg)");
1024 &case(0x95, "SUB ${reg}L"); &SUBAr("lreg($reg)");
1025 &case(0x96, "SUB ($reg+dd)"); &Offsadr($reg); &SUBAr("GetBYTE(adr)");
1026 &case(0x9C, "SBC A,${reg}H"); &SBCAr("hreg($reg)");
1027 &case(0x9D, "SBC A,${reg}L"); &SBCAr("lreg($reg)");
1028 &case(0x9E, "SBC A,($reg+dd)"); &Offsadr($reg); &SBCAr("GetBYTE(adr)");
1029 &case(0xA4, "AND ${reg}H"); &ANDAh("&", "$reg");
1030 &case(0xA5, "AND ${reg}L"); &ANDAl("&", "$reg");
1031 &case(0xA6, "AND ($reg+dd)"); &Offsadr($reg); &ANDAl("&", "GetBYTE(adr)");
1032 &case(0xAC, "XOR ${reg}H"); &LOGAh("^", "$reg");
1033 &case(0xAD, "XOR ${reg}L"); &LOGAl("^", "$reg");
1034 &case(0xAE, "XOR ($reg+dd)"); &Offsadr($reg); &LOGAl("^", "GetBYTE(adr)");
1035 &case(0xB4, "OR ${reg}H"); &LOGAh("|", "$reg");
1036 &case(0xB5, "OR ${reg}L"); &LOGAl("|", "$reg");
1037 &case(0xB6, "OR ($reg+dd)"); &Offsadr($reg); &LOGAl("|", "GetBYTE(adr)");
1038 &case(0xBC, "CP ${reg}H"); &CPAr("hreg($reg)");
1039 &case(0xBD, "CP ${reg}L"); &CPAr("lreg($reg)");
1040 &case(0xBE, "CP ($reg+dd)"); &Offsadr($reg); &CPAr("GetBYTE(adr)");
1041 &case(0xCB, "CB prefix"); &Offsadr($reg); &CB("adr");
1042 &case(0xE1, "POP $reg"); print "${tab}\tPOP($reg);\n";
1043 &case(0xE3, "EX (SP),$reg"); print "${tab}\ttemp = $reg; POP($reg); PUSH(temp);\n";
1044 &case(0xE5, "PUSH $reg"); print "${tab}\tPUSH($reg);\n";
1045 &case(0xE9, "JP ($reg)"); print "${tab}\tPC = $reg;\n";
1046 &case(0xF9, "LD SP,$reg"); print "${tab}\tSP = $reg;\n";
1047 print "${tab}\tbreak;\n${tab}default: PC--;\t\t/* ignore DD */\n";
1048 print "${tab}}\n";
1049 $tab = "\t";
1050 $optab = $optabsav;
1053 sub ED {
1054 local($reg) = @_;
1055 if ($ed_inline) {
1056 &ed_switch;
1058 else {
1059 print <<"EOT";
1060 $tab SAVE_STATE();
1061 $tab ed_prefix();
1062 $tab LOAD_STATE();
1067 sub ed_switch {
1068 local($optabsav) = $optab;
1069 $optab = 0;
1070 print "${tab}\tswitch (++PC, op = GetBYTE(PC-1)) {\n";
1071 $tab = "\t\t";
1072 $needbreak = 0;
1073 &case(0x40, "IN B,(C)"); &INP(BC, "h");
1074 &case(0x41, "OUT (C),B"); &OUTP(BC, "h");
1075 &case(0x42, "SBC HL,BC"); &SBCdd(HL, BC);
1076 &case(0x43, "LD (nnnn),BC"); &LDmemdd(BC);
1077 &case(0x44, "NEG"); print <<"EOT";
1078 temp = hreg(AF);
1079 AF = (-(AF & 0xff00) & 0xff00);
1080 AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) |
1081 (((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) |
1082 2 | (temp != 0);
1084 &case(0x45, "RETN"); print "\t\t\tIFF |= IFF >> 1;\n\t\t\tPOP(PC);\n";
1085 &case(0x46, "IM 0"); print "\t\t\t/* interrupt mode 0 */\n";
1086 &case(0x47, "LD I,A"); print "\t\t\tir = (ir & 255) | (AF & ~255);\n";
1087 &case(0x48, "IN C,(C)"); &INP(BC, "l");
1088 &case(0x49, "OUT (C),C"); &OUTP(BC, "l");
1089 &case(0x4A, "ADC HL,BC"); &ADCdd(HL, BC);
1090 &case(0x4B, "LD BC,(nnnn)"); &LDddmem(BC);
1091 &case(0x4D, "RETI"); print "\t\t\tIFF |= IFF >> 1;\n\t\t\tPOP(PC);\n";
1092 &case(0x4F, "LD R,A"); print "\t\t\tir = (ir & ~255) | ((AF >> 8) & 255);\n";
1093 &case(0x50, "IN D,(C)"); &INP(DE, "h");
1094 &case(0x51, "OUT (C),D"); &OUTP(DE, "h");
1095 &case(0x52, "SBC HL,DE"); &SBCdd(HL, DE);
1096 &case(0x53, "LD (nnnn),DE"); &LDmemdd(DE);
1097 &case(0x56, "IM 1"); print "\t\t\t/* interrupt mode 1 */\n";
1098 &case(0x57, "LD A,I"); print "\t\t\tAF = (AF & 0x29) | (ir & ~255) | ",
1099 "((ir >> 8) & 0x80) | (((ir & ~255) == 0) << 6)",
1100 " | ((IFF & 2) << 1);\n";
1101 &case(0x58, "IN E,(C)"); &INP(DE, "l");
1102 &case(0x59, "OUT (C),E"); &OUTP(DE, "l");
1103 &case(0x5A, "ADC HL,DE"); &ADCdd(HL, DE);
1104 &case(0x5B, "LD DE,(nnnn)"); &LDddmem(DE);
1105 &case(0x5E, "IM 2"); print "\t\t\t/* interrupt mode 2 */\n";
1106 &case(0x5F, "LD A,R"); print "\t\t\tAF = (AF & 0x29) | ((ir & 255) << 8) | ",
1107 "(ir & 0x80) | (((ir & 255) == 0) << 6)",
1108 " | ((IFF & 2) << 1);\n";
1109 &case(0x60, "IN H,(C)"); &INP(HL, "h");
1110 &case(0x61, "OUT (C),H"); &OUTP(HL, "h");
1111 &case(0x62, "SBC HL,HL"); &SBCdd(HL, HL);
1112 &case(0x63, "LD (nnnn),HL"); &LDmemdd(HL);
1113 &case(0x67, "RRD"); print <<"EOT";
1114 temp = GetBYTE(HL);
1115 acu = hreg(AF);
1116 PutBYTE(HL, hdig(temp) | (ldig(acu) << 4));
1117 acu = (acu & 0xf0) | ldig(temp);
1118 AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
1119 partab[acu] | (AF & 1);
1121 &case(0x68, "IN L,(C)"); &INP(HL, "l");
1122 &case(0x69, "OUT (C),L"); &OUTP(HL, "l");
1123 &case(0x6A, "ADC HL,HL"); &ADCdd(HL, HL);
1124 &case(0x6B, "LD HL,(nnnn)"); &LDddmem(HL);
1125 &case(0x6F, "RLD"); print <<"EOT";
1126 temp = GetBYTE(HL);
1127 acu = hreg(AF);
1128 PutBYTE(HL, (ldig(temp) << 4) | ldig(acu));
1129 acu = (acu & 0xf0) | hdig(temp);
1130 AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
1131 partab[acu] | (AF & 1);
1133 &case(0x70, "IN (C)"); &INP("temp", "l");
1134 &case(0x71, "OUT (C),0"); &OUTP(0, "l");
1135 &case(0x72, "SBC HL,SP"); &SBCdd(HL, SP);
1136 &case(0x73, "LD (nnnn),SP"); &LDmemdd(SP);
1137 &case(0x78, "IN A,(C)"); &INP(AF, "h");
1138 &case(0x79, "OUT (C),A"); &OUTP(AF, "h");
1139 &case(0x7A, "ADC HL,SP"); &ADCdd(HL, SP);
1140 &case(0x7B, "LD SP,(nnnn)"); &LDddmem(SP);
1141 &case(0xA0, "LDI"); print <<"EOT";
1142 acu = GetBYTE(HL); ++HL;
1143 PutBYTE(DE, acu); ++DE;
1144 acu += hreg(AF);
1145 AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
1146 (((--BC & 0xffff) != 0) << 2);
1148 &case(0xA1, "CPI"); print <<"EOT";
1149 acu = hreg(AF);
1150 temp = GetBYTE(HL); ++HL;
1151 sum = acu - temp;
1152 cbits = acu ^ temp ^ sum;
1153 AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1154 (((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
1155 ((sum - ((cbits >> 4) & 1)) & 8) |
1156 ((--BC & 0xffff) != 0) << 2 | 2;
1157 if ((sum & 15) == 8 && (cbits & 16) != 0)
1158 AF &= ~8;
1160 &case(0xA2, "INI"); print <<"EOT";
1161 PutBYTE(HL, Input(lreg(BC))); ++HL;
1162 SETFLAG(N, 1);
1163 SETFLAG(P, (--BC & 0xffff) != 0);
1165 &case(0xA3, "OUTI"); print <<"EOT";
1166 Output(lreg(BC), GetBYTE(HL)); ++HL;
1167 SETFLAG(N, 1);
1168 Sethreg(BC, lreg(BC) - 1);
1169 SETFLAG(Z, lreg(BC) == 0);
1171 &case(0xA8, "LDD"); print <<"EOT";
1172 acu = GetBYTE(HL); --HL;
1173 PutBYTE(DE, acu); --DE;
1174 acu += hreg(AF);
1175 AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
1176 (((--BC & 0xffff) != 0) << 2);
1178 &case(0xA9, "CPD"); print <<"EOT";
1179 acu = hreg(AF);
1180 temp = GetBYTE(HL); --HL;
1181 sum = acu - temp;
1182 cbits = acu ^ temp ^ sum;
1183 AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1184 (((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
1185 ((sum - ((cbits >> 4) & 1)) & 8) |
1186 ((--BC & 0xffff) != 0) << 2 | 2;
1187 if ((sum & 15) == 8 && (cbits & 16) != 0)
1188 AF &= ~8;
1190 &case(0xAA, "IND"); print <<"EOT";
1191 PutBYTE(HL, Input(lreg(BC))); --HL;
1192 SETFLAG(N, 1);
1193 Sethreg(BC, lreg(BC) - 1);
1194 SETFLAG(Z, lreg(BC) == 0);
1196 &case(0xAB, "OUTD"); print <<"EOT";
1197 Output(lreg(BC), GetBYTE(HL)); --HL;
1198 SETFLAG(N, 1);
1199 Sethreg(BC, lreg(BC) - 1);
1200 SETFLAG(Z, lreg(BC) == 0);
1202 &case(0xB0, "LDIR"); print <<"EOT";
1203 acu = hreg(AF);
1204 BC &= 0xffff;
1205 do {
1206 acu = GetBYTE(HL); ++HL;
1207 PutBYTE(DE, acu); ++DE;
1208 } while (--BC);
1209 acu += hreg(AF);
1210 AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
1212 &case(0xB1, "CPIR"); print <<"EOT";
1213 acu = hreg(AF);
1214 BC &= 0xffff;
1215 do {
1216 temp = GetBYTE(HL); ++HL;
1217 op = --BC != 0;
1218 sum = acu - temp;
1219 } while (op && sum != 0);
1220 cbits = acu ^ temp ^ sum;
1221 AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1222 (((sum - ((cbits&16)>>4))&2) << 4) |
1223 (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
1224 op << 2 | 2;
1225 if ((sum & 15) == 8 && (cbits & 16) != 0)
1226 AF &= ~8;
1228 &case(0xB2, "INIR"); print <<"EOT";
1229 temp = hreg(BC);
1230 do {
1231 PutBYTE(HL, Input(lreg(BC))); ++HL;
1232 } while (--temp);
1233 Sethreg(BC, 0);
1234 SETFLAG(N, 1);
1235 SETFLAG(Z, 1);
1237 &case(0xB3, "OTIR"); print <<"EOT";
1238 temp = hreg(BC);
1239 do {
1240 Output(lreg(BC), GetBYTE(HL)); ++HL;
1241 } while (--temp);
1242 Sethreg(BC, 0);
1243 SETFLAG(N, 1);
1244 SETFLAG(Z, 1);
1246 &case(0xB8, "LDDR"); print <<"EOT";
1247 BC &= 0xffff;
1248 do {
1249 acu = GetBYTE(HL); --HL;
1250 PutBYTE(DE, acu); --DE;
1251 } while (--BC);
1252 acu += hreg(AF);
1253 AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
1255 &case(0xB9, "CPDR"); print <<"EOT";
1256 acu = hreg(AF);
1257 BC &= 0xffff;
1258 do {
1259 temp = GetBYTE(HL); --HL;
1260 op = --BC != 0;
1261 sum = acu - temp;
1262 } while (op && sum != 0);
1263 cbits = acu ^ temp ^ sum;
1264 AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1265 (((sum - ((cbits&16)>>4))&2) << 4) |
1266 (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
1267 op << 2 | 2;
1268 if ((sum & 15) == 8 && (cbits & 16) != 0)
1269 AF &= ~8;
1271 &case(0xBA, "INDR"); print <<"EOT";
1272 temp = hreg(BC);
1273 do {
1274 PutBYTE(HL, Input(lreg(BC))); --HL;
1275 } while (--temp);
1276 Sethreg(BC, 0);
1277 SETFLAG(N, 1);
1278 SETFLAG(Z, 1);
1280 &case(0xBB, "OTDR"); print <<"EOT";
1281 temp = hreg(BC);
1282 do {
1283 Output(lreg(BC), GetBYTE(HL)); --HL;
1284 } while (--temp);
1285 Sethreg(BC, 0);
1286 SETFLAG(N, 1);
1287 SETFLAG(Z, 1);
1289 print "${tab}\tbreak;\n${tab}default: if (0x40 <= op && op <= 0x7f) PC--;\t\t/* ignore ED */\n";
1290 print "${tab}}\n";
1291 $tab = "\t";
1292 $optab = $optabsav;
1295 sub reslabs {
1296 $labpcp2 = 0;
1297 $labcpar = 0;
1298 $lablogar = 0;
1299 $labandar = 0;
1300 $labsbcar = 0;
1301 $labsubar = 0;
1302 $labadcar = 0;
1303 $labaddar = 0;
1304 $labadddd = 0;
1305 $labdecr = 0;
1306 $labincr = 0;
1310 sub preamble {
1311 print "#include \"simz80.h\"\n\n";
1313 print "static const unsigned char partab[256] = {\n";
1314 for (0..255) {
1315 print "\t" if (($_ & 15) == 0);
1316 $x = ($_>>4) ^ ($_&15);
1317 $x = ($x>>2) ^ ($x&3);
1318 $x = ($x>>1) ^ ($x&1);
1319 print $x ? "0," : "4,";
1320 print "\n" if (($_ & 15) == 15);
1322 print <<'EOT';
1325 #define parity(x) partab[(x)&0xff]
1327 #ifdef DEBUG
1328 volatile int stopsim;
1329 #endif
1331 #define POP(x) do { \
1332 FASTREG y = RAM(SP); SP++; \
1333 x = y + (RAM(SP) << 8); SP++; \
1334 } while (0)
1336 #define PUSH(x) do { \
1337 --SP; RAM(SP) = (x) >> 8; \
1338 --SP; RAM(SP) = x; \
1339 } while (0)
1341 #define JPC(cond) PC = cond ? GetWORD(PC) : PC+2
1343 #define CALLC(cond) { \
1344 if (cond) { \
1345 FASTREG adrr = GetWORD(PC); \
1346 PUSH(PC+2); \
1347 PC = adrr; \
1349 else \
1350 PC += 2; \
1353 /* load Z80 registers into (we hope) host registers */
1354 #define LOAD_STATE() \
1355 PC = pc; \
1356 AF = af[af_sel]; \
1357 BC = regs[regs_sel].bc; \
1358 DE = regs[regs_sel].de; \
1359 HL = regs[regs_sel].hl; \
1361 if ($dfd_inline) {
1362 print <<'EOT';
1363 IX = ix; \
1364 IY = iy; \
1367 print <<'EOT';
1368 SP = sp
1370 /* load Z80 registers into (we hope) host registers */
1371 #define DECLARE_STATE() \
1372 FASTREG PC = pc; \
1373 FASTREG AF = af[af_sel]; \
1374 FASTREG BC = regs[regs_sel].bc; \
1375 FASTREG DE = regs[regs_sel].de; \
1376 FASTREG HL = regs[regs_sel].hl; \
1378 if ($dfd_inline) {
1379 print <<'EOT';
1380 FASTREG IX = ix; \
1381 FASTREG IY = iy; \
1384 print <<'EOT';
1385 FASTREG SP = sp
1387 /* save Z80 registers back into memory */
1388 #define SAVE_STATE() \
1389 pc = PC; \
1390 af[af_sel] = AF; \
1391 regs[regs_sel].bc = BC; \
1392 regs[regs_sel].de = DE; \
1393 regs[regs_sel].hl = HL; \
1395 if ($dfd_inline) {
1396 print <<'EOT';
1397 ix = IX; \
1398 iy = IY; \
1401 print <<'EOT';
1402 sp = SP
1406 if (!$cb_inline) {
1407 print <<'EOT';
1408 static void
1409 cb_prefix(FASTREG adr)
1411 DECLARE_STATE();
1412 FASTWORK temp, acu, op, cbits;
1415 &cb_switch;
1416 print <<'EOT';
1417 SAVE_STATE();
1423 if (!$dfd_inline) {
1424 print <<'EOT';
1425 static FASTREG
1426 dfd_prefix(FASTREG IXY)
1428 DECLARE_STATE();
1429 FASTWORK temp, adr, acu, op, sum, cbits;
1432 local(@labs) = ($labpcp2, $labcpar, $lablogar,
1433 $labandar, $labsbcar, $labsubar,
1434 $labadcar, $labaddar, $labadddd,
1435 $labdecr, $labincr);
1436 &dfd_switch("IXY");
1437 ($labpcp2, $labcpar, $lablogar,
1438 $labandar, $labsbcar, $labsubar,
1439 $labadcar, $labaddar, $labadddd,
1440 $labdecr, $labincr) = @labs;
1441 print <<'EOT';
1442 SAVE_STATE();
1443 return(IXY);
1449 if (!$ed_inline) {
1450 print <<'EOT';
1451 static void
1452 ed_prefix(void)
1454 DECLARE_STATE();
1455 FASTWORK temp, acu, op, sum, cbits;
1458 local(@labs) = ($labpcp2, $labcpar, $lablogar,
1459 $labandar, $labsbcar, $labsubar,
1460 $labadcar, $labaddar, $labadddd,
1461 $labdecr, $labincr);
1462 &ed_switch;
1463 ($labpcp2, $labcpar, $lablogar,
1464 $labandar, $labsbcar, $labsubar,
1465 $labadcar, $labaddar, $labadddd,
1466 $labdecr, $labincr) = @labs;
1467 print <<'EOT';
1468 SAVE_STATE();
1474 print <<'EOT';
1475 FASTWORK
1476 simz80(FASTREG PC)
1478 FASTREG AF = af[af_sel];
1479 FASTREG BC = regs[regs_sel].bc;
1480 FASTREG DE = regs[regs_sel].de;
1481 FASTREG HL = regs[regs_sel].hl;
1482 FASTREG SP = sp;
1484 if ($dfd_inline) {
1485 print <<'EOT';
1486 FASTREG IX = ix;
1487 FASTREG IY = iy;
1490 print " FASTWORK temp, acu, sum, cbits;\n";
1491 print " FASTWORK op, adr;\n" if ($cb_inline + $dfd_inline +
1492 $ed_inline != 0);
1494 if ($optab) {
1495 print "static void *optab[256] = {\n";
1496 for (0..255) {
1497 print "\t" if (($_ & 7) == 0);
1498 printf("&&op_%02x,", $_);
1499 print "\n" if (($_ & 7) == 7);
1501 print "};\n";
1503 print <<'EOT';
1505 #ifdef DEBUG
1506 while (!stopsim) {
1507 #else
1508 while (1) {
1509 #endif
1511 if ($optab) {
1512 print " goto *optab[++PC,RAM(PC-1)]; {\n";
1514 else {
1515 print " switch(++PC,RAM(PC-1)) {\n";
1517 $needbreak = 0;
1520 sub postamble {
1521 print <<'EOT';
1524 /* make registers visible for debugging if interrupted */
1525 SAVE_STATE();
1526 return (PC&0xffff)|0x10000; /* flag non-bios stop */