1print <<"EOT";
2/* Z80 instruction set simulator.
3   Copyright (C) 1995  Frank D. Cringle.
4
5This file is part of yaze - yet another Z80 emulator.
6
7Yaze is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2 of the License, or (at your
10option) any later version.
11
12This program is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21EOT
22
23
24# This perl script generates the z80 instruction set simulator simz80().
25
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.
31
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.
40
41$combine = 0;
42
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.
46
47$optab = 0;
48
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.
53
54$cb_inline = 1;
55$dfd_inline = 1;
56$ed_inline = 1;
57# ****************
58
59##### end of configuration options ####
60
61$f = __FILE__;
62print <<"EOT";
63/* This file was generated from $f
64   with the following choice of options */
65char *perl_params =
66    "combine=$combine,"
67    "optab=$optab,"
68    "cb_inline=$cb_inline,"
69    "dfd_inline=$dfd_inline,"
70    "ed_inline=$ed_inline";
71
72EOT
73
74$tab = "\t";
75$cblabno = 0;
76
77&preamble;			# generate the function header and switch
78
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_pp(PC));\n";
86&case(0x07, "RLCA");		print <<"EOT";
87		AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
88			(AF & 0xc4) | ((AF >> 15) & 1);
89EOT
90&case(0x08, "EX AF,AF'");	print <<"EOT";
91		af[af_sel] = AF;
92		af_sel = 1 - af_sel;
93		AF = af[af_sel];
94EOT
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_pp(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);
106EOT
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_pp(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);
117EOT
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_pp(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);
130EOT
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_pp(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;
149			}
150			if (hd)		/* adjust high digit */
151				acu -= 0x160;
152		}
153		else {			/* last operation was an add */
154			if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
155				SETFLAG(H, (temp > 9));
156				acu += 6;
157			}
158			if (cbits || ((acu & 0x1f0) > 0x90)) /* adjust high digit */
159				acu += 0x60;
160		}
161		cbits |= (acu >> 8) & 1;
162		acu &= 0xff;
163		AF = (acu << 8) | (acu & 0xa8) | ((acu == 0) << 6) |
164			(AF & 0x12) | partab[acu] | cbits;
165EOT
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_pp(PC));\n";
173&case(0x2F, "CPL");		print <<"EOT";
174		AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
175EOT
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_pp(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_pp(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_pp(PC)");
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_pp(PC)");
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_pp(PC), hreg(AF));\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_pp(PC)");
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;
354EOT
355&case(0xDA, "JP C,nnnn");	print "\t\tJPC(TSTFLAG(C));\n";
356&case(0xDB, "IN A,(nn)");	print "\t\tSethreg(AF, Input(GetBYTE_pp(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_pp(PC)");
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_pp(PC)");
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_pp(PC)");
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_pp(PC)");
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_pp(PC)");
392&case(0xFF, "RST 38H");		print "\t\tPUSH(PC); PC = 0x38;\n";
393
394&postamble;
395
396sub case {
397    local($op,$cmnt) = @_;
398    if ($needbreak) {
399	print $optab ? "${tab}\tcontinue;\n" : "${tab}\tbreak;\n";
400    }
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;
404}
405
406sub JRcond {
407    local($cond) = @_;
408    print "${tab}\tPC += ($cond) ? (signed char) GetBYTE(PC) + 1 : 1;\n";
409}
410
411sub 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;
418    }
419    else {
420	$labpcp2 = 1;
421	print "${tab}labpcp2:\n" if $combine;
422	print "${tab}\tPC += 2;\n";
423    }
424}
425
426sub 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;
433    }
434    else {
435	$labpcp2 = 1;
436	print "${tab}labpcp2:\n" if $combine;
437	print "${tab}\tPC += 2;\n";
438	# print "/* not necessary because GetWORD_pppp --> PC += 2; */\n";
439    }
440}
441
442sub LDddmem {
443    local($reg) = @_;
444    print "${tab}\ttemp = GetWORD(PC);\n";
445    print "${tab}\t$reg = GetWORD(temp);\n";
446    if ($combine && $labpcp2) {
447	print "${tab}\tgoto labpcp2;\n";
448	$needbreak = 0;
449    }
450    else {
451	$labpcp2 = 1;
452	print "${tab}labpcp2:\n" if $combine;
453	print "${tab}\tPC += 2;\n";
454    }
455}
456
457sub LDmemdd {
458    local($reg) = @_;
459    print "${tab}\ttemp = GetWORD(PC);\n";
460    print "${tab}\tPutWORD(temp, $reg);\n";
461    if ($combine && $labpcp2) {
462	print "${tab}\tgoto labpcp2;\n";
463	$needbreak = 0;
464    }
465    else {
466	$labpcp2 = 1;
467	print "${tab}labpcp2:\n" if $combine;
468	print "${tab}\tPC += 2;\n";
469    }
470}
471
472sub LDddnn {
473    local($reg) = @_;
474    print "${tab}\t$reg = GetWORD(PC);\n";
475    if ($combine && $labpcp2) {
476	print "${tab}\tgoto labpcp2;\n";
477	$needbreak = 0;
478    }
479    else {
480	$labpcp2 = 1;
481	print "${tab}labpcp2:\n" if $combine;
482	print "${tab}\tPC += 2;\n";
483    }
484}
485
486sub INCr {
487    local($reg,$which) = @_;
488    if ($which eq "h") {
489	print "${tab}\t$reg += 0x100;\n${tab}\ttemp = hreg($reg);\n";
490    }
491    else {
492	print "${tab}\ttemp = ${which}reg($reg)+1;\n${tab}\tSet${which}reg($reg, temp);\n";
493    }
494    if ($combine && $labincr) {
495	print "${tab}\tgoto labincr;\n";
496	$needbreak = 0;
497    }
498    else {
499	$labincr = 1;
500	print "${tab}labincr:\n" if $combine;
501	print <<"EOT";
502$tab	AF = (AF & ~0xfe) | (temp & 0xa8) |
503$tab		(((temp & 0xff) == 0) << 6) |
504$tab		(((temp & 0xf) == 0) << 4) |
505$tab		((temp == 0x80) << 2);
506EOT
507    }
508}
509
510sub INCm {
511    local($reg) = @_;
512    print "${tab}\ttemp = GetBYTE($reg)+1;\n${tab}\tPutBYTE($reg, temp);\n";
513    if ($combine && $labincr) {
514	print "${tab}\tgoto labincr;\n";
515	$needbreak = 0;
516    }
517    else {
518	$labincr = 1;
519	print "${tab}labincr:\n" if $combine;
520	print <<"EOT";
521$tab	AF = (AF & ~0xfe) | (temp & 0xa8) |
522$tab		(((temp & 0xff) == 0) << 6) |
523$tab		(((temp & 0xf) == 0) << 4) |
524$tab		((temp == 0x80) << 2);
525EOT
526    }
527}
528
529sub DECr {
530    local($reg,$which) = @_;
531    if ($which eq "h") {
532	print "${tab}\t$reg -= 0x100;\n${tab}\ttemp = hreg($reg);\n";
533    }
534    else {
535	print "${tab}\ttemp = ${which}reg($reg)-1;\n${tab}\tSet${which}reg($reg, temp);\n";
536    }
537    if ($combine && $labdecr) {
538	print "${tab}\tgoto labdecr;\n";
539	$needbreak = 0;
540    }
541    else {
542	$labdecr = 1;
543	print "${tab}labdecr:\n" if $combine;
544	print <<"EOT";
545$tab	AF = (AF & ~0xfe) | (temp & 0xa8) |
546$tab		(((temp & 0xff) == 0) << 6) |
547$tab		(((temp & 0xf) == 0xf) << 4) |
548$tab		((temp == 0x7f) << 2) | 2;
549EOT
550    }
551}
552
553sub DECm {
554    local($reg) = @_;
555    print "${tab}\ttemp = GetBYTE($reg)-1;\n${tab}\tPutBYTE($reg, temp);\n";
556    if ($combine && $labdecr) {
557	print "${tab}\tgoto labdecr;\n";
558	$needbreak = 0;
559    }
560    else {
561	$labdecr = 1;
562	print "${tab}labdecr:\n" if $combine;
563	print <<"EOT";
564$tab	AF = (AF & ~0xfe) | (temp & 0xa8) |
565$tab		(((temp & 0xff) == 0) << 6) |
566$tab		(((temp & 0xf) == 0xf) << 4) |
567$tab		((temp == 0x7f) << 2) | 2;
568EOT
569    }
570}
571
572sub ADDAr {
573    local($val) = @_;
574    print "${tab}\ttemp = $val;\n";
575    if ($combine && $labaddar) {
576	print "${tab}\tgoto labaddar;\n";
577	$needbreak = 0;
578    }
579    else {
580	$labaddar = 1;
581		print "${tab}labaddar:\n" if $combine;
582		print <<"EOT";
583$tab	acu = hreg(AF);
584$tab	sum = acu + temp;
585$tab	cbits = acu ^ temp ^ sum;
586$tab	AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
587$tab		(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
588$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) |
589$tab		((cbits >> 8) & 1);
590EOT
591    }
592}
593
594sub ADCAr {
595    local($val) = @_;
596    print "${tab}\ttemp = $val;\n";
597    if ($combine && $labadcar) {
598	print "${tab}\tgoto labadcar;\n";
599	$needbreak = 0;
600    }
601    else {
602	$labadcar = 1;
603		print "${tab}labadcar:\n" if $combine;
604		print <<"EOT";
605$tab	acu = hreg(AF);
606$tab	sum = acu + temp + TSTFLAG(C);
607$tab	cbits = acu ^ temp ^ sum;
608$tab	AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
609$tab		(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
610$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) |
611$tab		((cbits >> 8) & 1);
612EOT
613    }
614}
615
616sub SUBAr {
617    local($val) = @_;
618    print "${tab}\ttemp = $val;\n";
619    if ($combine && $labsubar) {
620	print "${tab}\tgoto labsubar;\n";
621	$needbreak = 0;
622    }
623    else {
624	$labsubar = 1;
625		print "${tab}labsubar:\n" if $combine;
626		print <<"EOT";
627$tab	acu = hreg(AF);
628$tab	sum = acu - temp;
629$tab	cbits = acu ^ temp ^ sum;
630$tab	AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
631$tab		(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
632$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
633$tab		((cbits >> 8) & 1);
634EOT
635    }
636}
637
638sub SBCAr {
639    local($val) = @_;
640    print "${tab}\ttemp = $val;\n";
641    if ($combine && $labsbcar) {
642	print "${tab}\tgoto labsbcar;\n";
643	$needbreak = 0;
644    }
645    else {
646	$labsbcar = 1;
647	print "${tab}labsbcar:\n" if $combine;
648	print <<"EOT";
649$tab	acu = hreg(AF);
650$tab	sum = acu - temp - TSTFLAG(C);
651$tab	cbits = acu ^ temp ^ sum;
652$tab	AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
653$tab		(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
654$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
655$tab		((cbits >> 8) & 1);
656EOT
657    }
658}
659
660sub ANDAh {
661    local($op, $reg) = @_;
662    print "${tab}\tsum = ((AF $op ($reg)) >> 8) & 0xff;\n";
663    if ($combine && $labandar) {
664	print "${tab}\tgoto labandar;\n";
665	$needbreak = 0;
666    }
667    else {
668	$labandar = 1;
669	print "${tab}labandar:\n" if $combine;
670	print "${tab}\tAF = (sum << 8) | (sum & 0xa8) |\n";
671	print "${tab}\t\t((sum == 0) << 6) | 0x10 | partab[sum];\n";
672    }
673}
674
675sub ANDAl {
676    local($op, $reg) = @_;
677    print "${tab}\tsum = ((AF >> 8) $op $reg) & 0xff;\n";
678    if ($combine && $labandar) {
679	print "${tab}\tgoto labandar;\n";
680	$needbreak = 0;
681    }
682    else {
683	$labandar = 1;
684	print "${tab}labandar:\n" if $combine;
685	print "${tab}\tAF = (sum << 8) | (sum & 0xa8) | 0x10 |\n";
686	print "${tab}\t\t((sum == 0) << 6) | partab[sum];\n";
687    }
688}
689
690sub LOGAh {
691    local($op, $reg) = @_;
692    print "${tab}\tsum = ((AF $op ($reg)) >> 8) & 0xff;\n";
693    if ($combine && $lablogar) {
694	print "${tab}\tgoto lablogar;\n";
695	$needbreak = 0;
696    }
697    else {
698	$lablogar = 1;
699	print "${tab}lablogar:\n" if $combine;
700	print
701"${tab}\tAF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];\n";
702    }
703}
704
705sub LOGAl {
706    local($op, $reg) = @_;
707    print "${tab}\tsum = ((AF >> 8) $op $reg) & 0xff;\n";
708    if ($combine && $lablogar) {
709	print "${tab}\tgoto lablogar;\n";
710	$needbreak = 0;
711    }
712    else {
713	$lablogar = 1;
714	print "${tab}lablogar:\n" if $combine;
715	print
716"${tab}\tAF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];\n";
717    }
718}
719
720sub CPAr {
721    local($reg) = @_;
722    print "${tab}\ttemp = $reg;\n";
723    print "${tab}\tAF = (AF & ~0x28) | (temp & 0x28);\n";
724    if ($combine && $labcpar) {
725	print "${tab}\tgoto labcpar;\n";
726	$needbreak = 0;
727    }
728    else {
729	$labcpar = 1;
730	print "${tab}labcpar:\n" if $combine;
731	print <<"EOT";
732$tab	acu = hreg(AF);
733$tab	sum = acu - temp;
734$tab	cbits = acu ^ temp ^ sum;
735$tab	AF = (AF & ~0xff) | (sum & 0x80) |
736$tab		(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
737$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
738$tab		(cbits & 0x10) | ((cbits >> 8) & 1);
739EOT
740    }
741}
742
743sub ADDdd {
744    local($r1,$r2) = @_;
745    print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
746    print <<"EOT";
747$tab	$r2 &= 0xffff;
748$tab	sum = $r1 + $r2;
749$tab	cbits = ($r1 ^ $r2 ^ sum) >> 8;
750$tab	$r1 = sum;
751EOT
752    if ($combine && $labadddd) {
753	print "${tab}\tgoto labadddd;\n";
754	$needbreak = 0;
755    }
756    else {
757	$labadddd = 1;
758	print "${tab}labadddd:\n" if $combine;
759	print <<"EOT";
760$tab	AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
761$tab		(cbits & 0x10) | ((cbits >> 8) & 1);
762EOT
763    }
764}
765
766sub ADCdd {
767    local($r1,$r2) = @_;
768    print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
769    print <<"EOT";
770$tab	$r2 &= 0xffff;
771$tab	sum = $r1 + $r2 + TSTFLAG(C);
772$tab	cbits = ($r1 ^ $r2 ^ sum) >> 8;
773$tab	$r1 = sum;
774EOT
775    if ($combine && $labadcdd) {
776	print "${tab}\tgoto labadcdd;\n";
777	$needbreak = 0;
778    }
779    else {
780	$labadcdd = 1;
781	print "${tab}labadcdd:\n" if $combine;
782	print <<"EOT";
783$tab	AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
784$tab		(((sum & 0xffff) == 0) << 6) |
785$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) |
786$tab		(cbits & 0x10) | ((cbits >> 8) & 1);
787EOT
788    }
789}
790
791sub SBCdd {
792    local($r1,$r2) = @_;
793    print "${tab}\t$r1 &= 0xffff;\n" if ($r1 ne $r2);
794    print <<"EOT";
795$tab	$r2 &= 0xffff;
796$tab	sum = $r1 - $r2 - TSTFLAG(C);
797$tab	cbits = ($r1 ^ $r2 ^ sum) >> 8;
798$tab	$r1 = sum;
799EOT
800    if ($combine && $labsbcdd) {
801	print "${tab}\tgoto labsbcdd;\n";
802	$needbreak = 0;
803    }
804    else {
805	$labsbcdd = 1;
806	print "${tab}labsbcdd:\n" if $combine;
807	print <<"EOT";
808$tab	AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
809$tab		(((sum & 0xffff) == 0) << 6) |
810$tab		(((cbits >> 6) ^ (cbits >> 5)) & 4) |
811$tab		(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
812EOT
813    }
814}
815
816sub INP {
817    local($reg,$which) = @_;
818    print <<"EOT";
819$tab	temp = Input(lreg(BC));
820$tab	Set${which}reg($reg, temp);
821$tab	AF = (AF & ~0xfe) | (temp & 0xa8) |
822$tab		(((temp & 0xff) == 0) << 6) |
823$tab		parity(temp);
824EOT
825}
826
827sub OUTP {
828    local($reg,$which) = @_;
829    print <<"EOT";
830$tab	Output(lreg(BC), $reg);
831EOT
832}
833
834sub CB {
835    local($reg) = @_;
836    if ($cb_inline) {
837	print "${tab}\tadr = $reg;\n";
838	&cb_switch;
839    }
840    else {
841	print <<"EOT";
842$tab	SAVE_STATE();
843$tab	cb_prefix($reg);
844$tab	LOAD_STATE();
845EOT
846    }
847}
848
849sub cb_switch {
850    local($optabsav) = $optab;
851    $optab = 0;
852    $cblabno += 1;
853    print <<"EOT";
854$tab	switch ((op = GetBYTE(PC)) & 7) {
855$tab	case 0: ++PC; acu = hreg(BC); break;
856$tab	case 1: ++PC; acu = lreg(BC); break;
857$tab	case 2: ++PC; acu = hreg(DE); break;
858$tab	case 3: ++PC; acu = lreg(DE); break;
859$tab	case 4: ++PC; acu = hreg(HL); break;
860$tab	case 5: ++PC; acu = lreg(HL); break;
861$tab	case 6: ++PC; acu = GetBYTE(adr);  break;
862$tab	case 7: ++PC; acu = hreg(AF); break;
863$tab	}
864$tab	switch (op & 0xc0) {
865$tab	case 0x00:		/* shift/rotate */
866$tab		switch (op & 0x38) {
867$tab		case 0x00:	/* RLC */
868$tab			temp = (acu << 1) | (acu >> 7);
869$tab			cbits = temp & 1;
870$tab			goto cbshflg$cblabno;
871$tab		case 0x08:	/* RRC */
872$tab			temp = (acu >> 1) | (acu << 7);
873$tab			cbits = temp & 0x80;
874$tab			goto cbshflg$cblabno;
875$tab		case 0x10:	/* RL */
876$tab			temp = (acu << 1) | TSTFLAG(C);
877$tab			cbits = acu & 0x80;
878$tab			goto cbshflg$cblabno;
879$tab		case 0x18:	/* RR */
880$tab			temp = (acu >> 1) | (TSTFLAG(C) << 7);
881$tab			cbits = acu & 1;
882$tab			goto cbshflg$cblabno;
883$tab		case 0x20:	/* SLA */
884$tab			temp = acu << 1;
885$tab			cbits = acu & 0x80;
886$tab			goto cbshflg$cblabno;
887$tab		case 0x28:	/* SRA */
888$tab			temp = (acu >> 1) | (acu & 0x80);
889$tab			cbits = acu & 1;
890$tab			goto cbshflg$cblabno;
891$tab		case 0x30:	/* SLIA */
892$tab			temp = (acu << 1) | 1;
893$tab			cbits = acu & 0x80;
894$tab			goto cbshflg$cblabno;
895$tab		case 0x38:	/* SRL */
896$tab			temp = acu >> 1;
897$tab			cbits = acu & 1;
898$tab		cbshflg$cblabno:
899$tab			AF = (AF & ~0xff) | (temp & 0xa8) |
900$tab				(((temp & 0xff) == 0) << 6) |
901$tab				parity(temp) | !!cbits;
902$tab		}
903$tab		break;
904$tab	case 0x40:		/* BIT */
905$tab		if (acu & (1 << ((op >> 3) & 7)))
906$tab			AF = (AF & ~0xfe) | 0x10 |
907$tab			(((op & 0x38) == 0x38) << 7);
908$tab		else
909$tab			AF = (AF & ~0xfe) | 0x54;
910$tab		if ((op&7) != 6)
911$tab			AF |= (acu & 0x28);
912$tab		temp = acu;
913$tab		break;
914$tab	case 0x80:		/* RES */
915$tab		temp = acu & ~(1 << ((op >> 3) & 7));
916$tab		break;
917$tab	case 0xc0:		/* SET */
918$tab		temp = acu | (1 << ((op >> 3) & 7));
919$tab		break;
920$tab	}
921$tab	switch (op & 7) {
922$tab	case 0: Sethreg(BC, temp); break;
923$tab	case 1: Setlreg(BC, temp); break;
924$tab	case 2: Sethreg(DE, temp); break;
925$tab	case 3: Setlreg(DE, temp); break;
926$tab	case 4: Sethreg(HL, temp); break;
927$tab	case 5: Setlreg(HL, temp); break;
928$tab	case 6: PutBYTE(adr, temp);  break;
929$tab	case 7: Sethreg(AF, temp); break;
930$tab	}
931EOT
932    $optab = $optabsav;
933}
934
935
936sub DFD {
937    local($reg) = @_;
938    if ($dfd_inline) {
939	&dfd_switch($reg);
940    }
941    else {
942	print <<"EOT";
943$tab	SAVE_STATE();
944$tab	$reg = dfd_prefix($reg);
945$tab	LOAD_STATE();
946EOT
947    }
948}
949
950sub Offsadr {
951    local($reg) = @_;
952    print "${tab}\tadr = $reg + (signed char) GetBYTE_pp(PC);\n";
953}
954
955sub dfd_switch {
956    local($reg) = @_;
957    local($optabsav) = $optab;
958    $optab = 0;
959    print "${tab}\tswitch (op = GetBYTE_pp(PC)) {\n";
960    $tab = "\t\t";
961    $needbreak = 0;
962    &case(0x09, "ADD $reg,BC");		&ADDdd($reg, BC);
963    &case(0x19, "ADD $reg,DE");		&ADDdd($reg, DE);
964    &case(0x21, "LD $reg,nnnn");	&LDddnn($reg);
965    &case(0x22, "LD (nnnn),$reg");	&LDmemdd($reg);
966    &case(0x23, "INC $reg");		print "${tab}\t++$reg;\n";
967    &case(0x24, "INC ${reg}H");		&INCr($reg, "h");
968    &case(0x25, "DEC ${reg}H");		&DECr($reg, "h");
969    &case(0x26, "LD ${reg}H,nn");	print "${tab}\tSethreg($reg, GetBYTE_pp(PC));\n";
970    &case(0x29, "ADD $reg,$reg");	&ADDdd($reg, $reg);
971    &case(0x2A, "LD $reg,(nnnn)");	&LDddmem($reg);
972    &case(0x2B, "DEC $reg");		print "${tab}\t--$reg;\n";
973    &case(0x2C, "INC ${reg}L");		&INCr($reg, "l");
974    &case(0x2D, "DEC ${reg}L");		&DECr($reg, "l");
975    &case(0x2E, "LD ${reg}L,nn");	print "${tab}\tSetlreg($reg, GetBYTE_pp(PC));\n";
976    &case(0x34, "INC ($reg+dd)");	&Offsadr($reg); &INCm("adr");
977    &case(0x35, "DEC ($reg+dd)");	&Offsadr($reg); &DECm("adr");
978    &case(0x36, "LD ($reg+dd),nn");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, GetBYTE_pp(PC));\n";
979    &case(0x39, "ADD $reg,SP");		&ADDdd($reg, SP);
980    &case(0x44, "LD B,${reg}H");	print "${tab}\tSethreg(BC, hreg($reg));\n";
981    &case(0x45, "LD B,${reg}L");	print "${tab}\tSethreg(BC, lreg($reg));\n";
982    &case(0x46, "LD B,($reg+dd)");	&Offsadr($reg); print "${tab}\tSethreg(BC, GetBYTE(adr));\n";
983    &case(0x4C, "LD C,${reg}H");	print "${tab}\tSetlreg(BC, hreg($reg));\n";
984    &case(0x4D, "LD C,${reg}L");	print "${tab}\tSetlreg(BC, lreg($reg));\n";
985    &case(0x4E, "LD C,($reg+dd)");	&Offsadr($reg); print "${tab}\tSetlreg(BC, GetBYTE(adr));\n";
986    &case(0x54, "LD D,${reg}H");	print "${tab}\tSethreg(DE, hreg($reg));\n";
987    &case(0x55, "LD D,${reg}L");	print "${tab}\tSethreg(DE, lreg($reg));\n";
988    &case(0x56, "LD D,($reg+dd)");	&Offsadr($reg); print "${tab}\tSethreg(DE, GetBYTE(adr));\n";
989    &case(0x5C, "LD E,H");		print "${tab}\tSetlreg(DE, hreg($reg));\n";
990    &case(0x5D, "LD E,L");		print "${tab}\tSetlreg(DE, lreg($reg));\n";
991    &case(0x5E, "LD E,($reg+dd)");	&Offsadr($reg); print "${tab}\tSetlreg(DE, GetBYTE(adr));\n";
992    &case(0x60, "LD ${reg}H,B");	print "${tab}\tSethreg($reg, hreg(BC));\n";
993    &case(0x61, "LD ${reg}H,C");	print "${tab}\tSethreg($reg, lreg(BC));\n";
994    &case(0x62, "LD ${reg}H,D");	print "${tab}\tSethreg($reg, hreg(DE));\n";
995    &case(0x63, "LD ${reg}H,E");	print "${tab}\tSethreg($reg, lreg(DE));\n";
996    &case(0x64, "LD ${reg}H,${reg}H");	print "${tab}\t/* nop */\n";
997    &case(0x65, "LD ${reg}H,${reg}L");	print "${tab}\tSethreg($reg, lreg($reg));\n";
998    &case(0x66, "LD H,($reg+dd)");	&Offsadr($reg); print "${tab}\tSethreg(HL, GetBYTE(adr));\n";
999    &case(0x67, "LD ${reg}H,A");	print "${tab}\tSethreg($reg, hreg(AF));\n";
1000    &case(0x68, "LD ${reg}L,B");	print "${tab}\tSetlreg($reg, hreg(BC));\n";
1001    &case(0x69, "LD ${reg}L,C");	print "${tab}\tSetlreg($reg, lreg(BC));\n";
1002    &case(0x6A, "LD ${reg}L,D");	print "${tab}\tSetlreg($reg, hreg(DE));\n";
1003    &case(0x6B, "LD ${reg}L,E");	print "${tab}\tSetlreg($reg, lreg(DE));\n";
1004    &case(0x6C, "LD ${reg}L,${reg}H");	print "${tab}\tSetlreg($reg, hreg($reg));\n";
1005    &case(0x6D, "LD ${reg}L,${reg}L");	print "${tab}\t/* nop */\n";
1006    &case(0x6E, "LD L,($reg+dd)");	&Offsadr($reg); print "${tab}\tSetlreg(HL, GetBYTE(adr));\n";
1007    &case(0x6F, "LD ${reg}L,A");	print "${tab}\tSetlreg($reg, hreg(AF));\n";
1008    &case(0x70, "LD ($reg+dd),B");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(BC));\n";
1009    &case(0x71, "LD ($reg+dd),C");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(BC));\n";
1010    &case(0x72, "LD ($reg+dd),D");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(DE));\n";
1011    &case(0x73, "LD ($reg+dd),E");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(DE));\n";
1012    &case(0x74, "LD ($reg+dd),H");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(HL));\n";
1013    &case(0x75, "LD ($reg+dd),L");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, lreg(HL));\n";
1014    &case(0x77, "LD ($reg+dd),A");	&Offsadr($reg); print "${tab}\tPutBYTE(adr, hreg(AF));\n";
1015    &case(0x7C, "LD A,${reg}H");	print "${tab}\tSethreg(AF, hreg($reg));\n";
1016    &case(0x7D, "LD A,${reg}L");	print "${tab}\tSethreg(AF, lreg($reg));\n";
1017    &case(0x7E, "LD A,($reg+dd)");	&Offsadr($reg); print "${tab}\tSethreg(AF, GetBYTE(adr));\n";
1018    &case(0x84, "ADD A,${reg}H");	&ADDAr("hreg($reg)");
1019    &case(0x85, "ADD A,${reg}L");	&ADDAr("lreg($reg)");
1020    &case(0x86, "ADD A,($reg+dd)");	&Offsadr($reg); &ADDAr("GetBYTE(adr)");
1021    &case(0x8C, "ADC A,${reg}H");	&ADCAr("hreg($reg)");
1022    &case(0x8D, "ADC A,${reg}L");	&ADCAr("lreg($reg)");
1023    &case(0x8E, "ADC A,($reg+dd)");	&Offsadr($reg); &ADCAr("GetBYTE(adr)");
1024    &case(0x94, "SUB ${reg}H");		&SUBAr("hreg($reg)");
1025    &case(0x95, "SUB ${reg}L");		&SUBAr("lreg($reg)");
1026    &case(0x96, "SUB ($reg+dd)");	&Offsadr($reg); &SUBAr("GetBYTE(adr)");
1027    &case(0x9C, "SBC A,${reg}H");	&SBCAr("hreg($reg)");
1028    &case(0x9D, "SBC A,${reg}L");	&SBCAr("lreg($reg)");
1029    &case(0x9E, "SBC A,($reg+dd)");	&Offsadr($reg); &SBCAr("GetBYTE(adr)");
1030    &case(0xA4, "AND ${reg}H");		&ANDAh("&", "$reg");
1031    &case(0xA5, "AND ${reg}L");		&ANDAl("&", "$reg");
1032    &case(0xA6, "AND ($reg+dd)");	&Offsadr($reg); &ANDAl("&", "GetBYTE(adr)");
1033    &case(0xAC, "XOR ${reg}H");		&LOGAh("^", "$reg");
1034    &case(0xAD, "XOR ${reg}L");		&LOGAl("^", "$reg");
1035    &case(0xAE, "XOR ($reg+dd)");	&Offsadr($reg); &LOGAl("^", "GetBYTE(adr)");
1036    &case(0xB4, "OR ${reg}H");		&LOGAh("|", "$reg");
1037    &case(0xB5, "OR ${reg}L");		&LOGAl("|", "$reg");
1038    &case(0xB6, "OR ($reg+dd)");	&Offsadr($reg); &LOGAl("|", "GetBYTE(adr)");
1039    &case(0xBC, "CP ${reg}H");		&CPAr("hreg($reg)");
1040    &case(0xBD, "CP ${reg}L");		&CPAr("lreg($reg)");
1041    &case(0xBE, "CP ($reg+dd)");	&Offsadr($reg); &CPAr("GetBYTE(adr)");
1042    &case(0xCB, "CB prefix");		&Offsadr($reg); &CB("adr");
1043    &case(0xE1, "POP $reg");		print "${tab}\tPOP($reg);\n";
1044    &case(0xE3, "EX (SP),$reg");	print "${tab}\ttemp = $reg; POP($reg); PUSH(temp);\n";
1045    &case(0xE5, "PUSH $reg");		print "${tab}\tPUSH($reg);\n";
1046    &case(0xE9, "JP ($reg)");		print "${tab}\tPC = $reg;\n";
1047    &case(0xF9, "LD SP,$reg");		print "${tab}\tSP = $reg;\n";
1048    print "${tab}\tbreak;\n${tab}default: PC--;\t\t/* ignore DD */\n";
1049    print "${tab}}\n";
1050    $tab = "\t";
1051    $optab = $optabsav;
1052}
1053
1054sub ED {
1055    local($reg) = @_;
1056    if ($ed_inline) {
1057	&ed_switch;
1058    }
1059    else {
1060	print <<"EOT";
1061$tab	SAVE_STATE();
1062$tab	ed_prefix();
1063$tab	LOAD_STATE();
1064EOT
1065    }
1066}
1067
1068sub ed_switch {
1069    local($optabsav) = $optab;
1070    $optab = 0;
1071    print "${tab}\tswitch (op = GetBYTE_pp(PC)) {\n";
1072    $tab = "\t\t";
1073    $needbreak = 0;
1074    &case(0x40, "IN B,(C)");		&INP(BC, "h");
1075    &case(0x41, "OUT (C),B");		&OUTP(BC, "h");
1076    &case(0x42, "SBC HL,BC");		&SBCdd(HL, BC);
1077    &case(0x43, "LD (nnnn),BC");	&LDmemdd(BC);
1078    &case(0x44, "NEG");			print <<"EOT";
1079			temp = hreg(AF);
1080			AF = (-(AF & 0xff00) & 0xff00);
1081			AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) |
1082				(((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) |
1083				2 | (temp != 0);
1084EOT
1085    &case(0x45, "RETN");		print "\t\t\tIFF |= IFF >> 1;\n\t\t\tPOP(PC);\n";
1086    &case(0x46, "IM 0");		print "\t\t\t/* interrupt mode 0 */\n";
1087    &case(0x47, "LD I,A");		print "\t\t\tir = (ir & 255) | (AF & ~255);\n";
1088    &case(0x48, "IN C,(C)");		&INP(BC, "l");
1089    &case(0x49, "OUT (C),C");		&OUTP(BC, "l");
1090    &case(0x4A, "ADC HL,BC");		&ADCdd(HL, BC);
1091    &case(0x4B, "LD BC,(nnnn)");	&LDddmem(BC);
1092    &case(0x4D, "RETI");		print "\t\t\tIFF |= IFF >> 1;\n\t\t\tPOP(PC);\n";
1093    &case(0x4F, "LD R,A");		print "\t\t\tir = (ir & ~255) | ((AF >> 8) & 255);\n";
1094    &case(0x50, "IN D,(C)");		&INP(DE, "h");
1095    &case(0x51, "OUT (C),D");		&OUTP(DE, "h");
1096    &case(0x52, "SBC HL,DE");		&SBCdd(HL, DE);
1097    &case(0x53, "LD (nnnn),DE");	&LDmemdd(DE);
1098    &case(0x56, "IM 1");		print "\t\t\t/* interrupt mode 1 */\n";
1099    &case(0x57, "LD A,I");		print "\t\t\tAF = (AF & 0x29) | (ir & ~255) | ",
1100					      "((ir >> 8) & 0x80) | (((ir & ~255) == 0) << 6)",
1101					      " | ((IFF & 2) << 1);\n";
1102    &case(0x58, "IN E,(C)");		&INP(DE, "l");
1103    &case(0x59, "OUT (C),E");		&OUTP(DE, "l");
1104    &case(0x5A, "ADC HL,DE");		&ADCdd(HL, DE);
1105    &case(0x5B, "LD DE,(nnnn)");	&LDddmem(DE);
1106    &case(0x5E, "IM 2");		print "\t\t\t/* interrupt mode 2 */\n";
1107    &case(0x5F, "LD A,R");		print "\t\t\tAF = (AF & 0x29) | ((ir & 255) << 8) | ",
1108					      "(ir & 0x80) | (((ir & 255) == 0) << 6)",
1109					      " | ((IFF & 2) << 1);\n";
1110    &case(0x60, "IN H,(C)");		&INP(HL, "h");
1111    &case(0x61, "OUT (C),H");		&OUTP(HL, "h");
1112    &case(0x62, "SBC HL,HL");		&SBCdd(HL, HL);
1113    &case(0x63, "LD (nnnn),HL");	&LDmemdd(HL);
1114    &case(0x67, "RRD");			print <<"EOT";
1115			temp = GetBYTE(HL);
1116			acu = hreg(AF);
1117			PutBYTE(HL, hdig(temp) | (ldig(acu) << 4));
1118			acu = (acu & 0xf0) | ldig(temp);
1119			AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
1120				partab[acu] | (AF & 1);
1121EOT
1122    &case(0x68, "IN L,(C)");		&INP(HL, "l");
1123    &case(0x69, "OUT (C),L");		&OUTP(HL, "l");
1124    &case(0x6A, "ADC HL,HL");		&ADCdd(HL, HL);
1125    &case(0x6B, "LD HL,(nnnn)");	&LDddmem(HL);
1126    &case(0x6F, "RLD");			print <<"EOT";
1127			temp = GetBYTE(HL);
1128			acu = hreg(AF);
1129			PutBYTE(HL, (ldig(temp) << 4) | ldig(acu));
1130			acu = (acu & 0xf0) | hdig(temp);
1131			AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
1132				partab[acu] | (AF & 1);
1133EOT
1134    &case(0x70, "IN (C)");		&INP("temp", "l");
1135    &case(0x71, "OUT (C),0");		&OUTP(0, "l");
1136    &case(0x72, "SBC HL,SP");		&SBCdd(HL, SP);
1137    &case(0x73, "LD (nnnn),SP");	&LDmemdd(SP);
1138    &case(0x78, "IN A,(C)");		&INP(AF, "h");
1139    &case(0x79, "OUT (C),A");		&OUTP(AF, "h");
1140    &case(0x7A, "ADC HL,SP");		&ADCdd(HL, SP);
1141    &case(0x7B, "LD SP,(nnnn)");	&LDddmem(SP);
1142    &case(0xA0, "LDI");			print <<"EOT";
1143			acu = GetBYTE_pp(HL);
1144			PutBYTE_pp(DE, acu);
1145			acu += hreg(AF);
1146			AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
1147				(((--BC & 0xffff) != 0) << 2);
1148EOT
1149    &case(0xA1, "CPI");			print <<"EOT";
1150			acu = hreg(AF);
1151			temp = GetBYTE_pp(HL);
1152			sum = acu - temp;
1153			cbits = acu ^ temp ^ sum;
1154			AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1155				(((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
1156				((sum - ((cbits >> 4) & 1)) & 8) |
1157				((--BC & 0xffff) != 0) << 2 | 2;
1158			if ((sum & 15) == 8 && (cbits & 16) != 0)
1159				AF &= ~8;
1160EOT
1161    &case(0xA2, "INI");			print <<"EOT";
1162			PutBYTE(HL, Input(lreg(BC))); ++HL;
1163			SETFLAG(N, 1);
1164			Sethreg(BC, lreg(BC) - 1);
1165                        SETFLAG(Z, lreg(BC) == 0);
1166EOT
1167    &case(0xA3, "OUTI");		print <<"EOT";
1168			Output(lreg(BC), GetBYTE(HL)); ++HL;
1169			SETFLAG(N, 1);
1170			Sethreg(BC, hreg(BC) - 1);
1171			SETFLAG(Z, hreg(BC) == 0);
1172EOT
1173    &case(0xA8, "LDD");			print <<"EOT";
1174			acu = GetBYTE_mm(HL);
1175			PutBYTE_mm(DE, acu);
1176			acu += hreg(AF);
1177			AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
1178				(((--BC & 0xffff) != 0) << 2);
1179EOT
1180    &case(0xA9, "CPD");			print <<"EOT";
1181			acu = hreg(AF);
1182			temp = GetBYTE_mm(HL);
1183			sum = acu - temp;
1184			cbits = acu ^ temp ^ sum;
1185			AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1186				(((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
1187				((sum - ((cbits >> 4) & 1)) & 8) |
1188				((--BC & 0xffff) != 0) << 2 | 2;
1189			if ((sum & 15) == 8 && (cbits & 16) != 0)
1190				AF &= ~8;
1191EOT
1192    &case(0xAA, "IND");			print <<"EOT";
1193			PutBYTE(HL, Input(lreg(BC))); --HL;
1194			SETFLAG(N, 1);
1195			Sethreg(BC, lreg(BC) - 1);
1196			SETFLAG(Z, lreg(BC) == 0);
1197EOT
1198    &case(0xAB, "OUTD");		print <<"EOT";
1199			Output(lreg(BC), GetBYTE(HL)); --HL;
1200			SETFLAG(N, 1);
1201			Sethreg(BC, hreg(BC) - 1);
1202			SETFLAG(Z, hreg(BC) == 0);
1203EOT
1204    &case(0xB0, "LDIR");		print <<"EOT";
1205			acu = hreg(AF);
1206			BC &= 0xffff;
1207			do {
1208				acu = GetBYTE_pp(HL);
1209				PutBYTE_pp(DE, acu);
1210			} while (--BC);
1211			acu += hreg(AF);
1212			AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
1213EOT
1214    &case(0xB1, "CPIR");		print <<"EOT";
1215			acu = hreg(AF);
1216			BC &= 0xffff;
1217			do {
1218				temp = GetBYTE_pp(HL);
1219				op = --BC != 0;
1220				sum = acu - temp;
1221			} while (op && sum != 0);
1222			cbits = acu ^ temp ^ sum;
1223			AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1224				(((sum - ((cbits&16)>>4))&2) << 4) |
1225				(cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
1226				op << 2 | 2;
1227			if ((sum & 15) == 8 && (cbits & 16) != 0)
1228				AF &= ~8;
1229EOT
1230    &case(0xB2, "INIR");		print <<"EOT";
1231			temp = hreg(BC);
1232			do {
1233				PutBYTE(HL, Input(lreg(BC))); ++HL;
1234			} while (--temp);
1235			Sethreg(BC, 0);
1236			SETFLAG(N, 1);
1237			SETFLAG(Z, 1);
1238EOT
1239    &case(0xB3, "OTIR");		print <<"EOT";
1240			temp = hreg(BC);
1241			do {
1242				Output(lreg(BC), GetBYTE(HL)); ++HL;
1243			} while (--temp);
1244			Sethreg(BC, 0);
1245			SETFLAG(N, 1);
1246			SETFLAG(Z, 1);
1247EOT
1248    &case(0xB8, "LDDR");		print <<"EOT";
1249			BC &= 0xffff;
1250			do {
1251				acu = GetBYTE_mm(HL);
1252				PutBYTE_mm(DE, acu);
1253			} while (--BC);
1254			acu += hreg(AF);
1255			AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
1256EOT
1257    &case(0xB9, "CPDR");		print <<"EOT";
1258			acu = hreg(AF);
1259			BC &= 0xffff;
1260			do {
1261				temp = GetBYTE_mm(HL);
1262				op = --BC != 0;
1263				sum = acu - temp;
1264			} while (op && sum != 0);
1265			cbits = acu ^ temp ^ sum;
1266			AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
1267				(((sum - ((cbits&16)>>4))&2) << 4) |
1268				(cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
1269				op << 2 | 2;
1270			if ((sum & 15) == 8 && (cbits & 16) != 0)
1271				AF &= ~8;
1272EOT
1273    &case(0xBA, "INDR");		print <<"EOT";
1274			temp = hreg(BC);
1275			do {
1276				PutBYTE(HL, Input(lreg(BC))); --HL;
1277			} while (--temp);
1278			Sethreg(BC, 0);
1279			SETFLAG(N, 1);
1280			SETFLAG(Z, 1);
1281EOT
1282    &case(0xBB, "OTDR");		print <<"EOT";
1283			temp = hreg(BC);
1284			do {
1285				Output(lreg(BC), GetBYTE(HL)); --HL;
1286			} while (--temp);
1287			Sethreg(BC, 0);
1288			SETFLAG(N, 1);
1289			SETFLAG(Z, 1);
1290EOT
1291    print "${tab}\tbreak;\n${tab}default: if (0x40 <= op && op <= 0x7f) PC--;\t\t/* ignore ED */\n";
1292    print "${tab}}\n";
1293    $tab = "\t";
1294    $optab = $optabsav;
1295}
1296
1297sub reslabs {
1298    $labpcp2 = 0;
1299    $labcpar = 0;
1300    $lablogar = 0;
1301    $labandar = 0;
1302    $labsbcar = 0;
1303    $labsubar = 0;
1304    $labadcar = 0;
1305    $labaddar = 0;
1306    $labadddd = 0;
1307    $labdecr = 0;
1308    $labincr = 0;
1309}
1310
1311
1312sub preamble {
1313    print "#include \"mem_mmu.h\"\n";
1314    print "#include \"simz80.h\"\n\n";
1315
1316    print "static const unsigned char partab[256] = {\n";
1317    for (0..255) {
1318	print "\t" if (($_ & 15) == 0);
1319	$x = ($_>>4) ^ ($_&15);
1320	$x = ($x>>2) ^ ($x&3);
1321	$x = ($x>>1) ^ ($x&1);
1322	print $x ? "0," : "4,";
1323	print "\n" if (($_ & 15) == 15);
1324    }
1325    print <<'EOT';
1326};
1327
1328#define parity(x)	partab[(x)&0xff]
1329
1330#ifdef DEBUG
1331volatile int stopsim;
1332#endif
1333
1334#define POP(x)	do {							\
1335	FASTREG y = RAM_pp(SP);						\
1336	x = y + (RAM_pp(SP) << 8);					\
1337} while (0)
1338
1339#define PUSH(x) do {							\
1340	mm_RAM(SP) = (x) >> 8;						\
1341	mm_RAM(SP) = x;							\
1342} while (0)
1343
1344#define JPC(cond) PC = cond ? GetWORD(PC) : PC+2
1345
1346#define CALLC(cond) {							\
1347    if (cond) {								\
1348	FASTREG adrr = GetWORD(PC);					\
1349	PUSH(PC+2);							\
1350	PC = adrr;							\
1351    }									\
1352    else								\
1353	PC += 2;							\
1354}
1355
1356/* load Z80 registers into (we hope) host registers */
1357#define LOAD_STATE()							\
1358    PC = pc;								\
1359    AF = af[af_sel];							\
1360    BC = regs[regs_sel].bc;						\
1361    DE = regs[regs_sel].de;						\
1362    HL = regs[regs_sel].hl;						\
1363EOT
1364    if ($dfd_inline) {
1365	print <<'EOT';
1366    IX = ix;								\
1367    IY = iy;								\
1368EOT
1369    }
1370    print <<'EOT';
1371    SP = sp
1372
1373/* load Z80 registers into (we hope) host registers */
1374#define DECLARE_STATE()							\
1375    FASTREG PC = pc;							\
1376    FASTREG AF = af[af_sel];						\
1377    FASTREG BC = regs[regs_sel].bc;					\
1378    FASTREG DE = regs[regs_sel].de;					\
1379    FASTREG HL = regs[regs_sel].hl;					\
1380EOT
1381    if ($dfd_inline) {
1382	print <<'EOT';
1383    FASTREG IX = ix;							\
1384    FASTREG IY = iy;							\
1385EOT
1386    }
1387    print <<'EOT';
1388    FASTREG SP = sp
1389
1390/* save Z80 registers back into memory */
1391#define SAVE_STATE()							\
1392    pc = PC;								\
1393    af[af_sel] = AF;							\
1394    regs[regs_sel].bc = BC;						\
1395    regs[regs_sel].de = DE;						\
1396    regs[regs_sel].hl = HL;						\
1397EOT
1398    if ($dfd_inline) {
1399	print <<'EOT';
1400    ix = IX;								\
1401    iy = IY;								\
1402EOT
1403    }
1404    print <<'EOT';
1405    sp = SP
1406
1407EOT
1408
1409    if (!$cb_inline) {
1410	print <<'EOT';
1411static void
1412cb_prefix(FASTREG adr)
1413{
1414    DECLARE_STATE();
1415    FASTWORK temp, acu, op, cbits;
1416
1417EOT
1418	&cb_switch;
1419	print <<'EOT';
1420    SAVE_STATE();
1421}
1422
1423EOT
1424}
1425
1426    if (!$dfd_inline) {
1427	print <<'EOT';
1428static FASTREG
1429dfd_prefix(FASTREG IXY)
1430{
1431    DECLARE_STATE();
1432    FASTWORK temp, adr, acu, op, sum, cbits;
1433
1434EOT
1435	local(@labs) = ($labpcp2, $labcpar, $lablogar,
1436			$labandar, $labsbcar, $labsubar,
1437			$labadcar, $labaddar, $labadddd,
1438			$labdecr, $labincr);
1439	&dfd_switch("IXY");
1440	($labpcp2, $labcpar, $lablogar,
1441	 $labandar, $labsbcar, $labsubar,
1442	 $labadcar, $labaddar, $labadddd,
1443	 $labdecr, $labincr) = @labs;
1444	print <<'EOT';
1445    SAVE_STATE();
1446    return(IXY);
1447}
1448
1449EOT
1450}
1451
1452    if (!$ed_inline) {
1453	print <<'EOT';
1454static void
1455ed_prefix(void)
1456{
1457    DECLARE_STATE();
1458    FASTWORK temp, acu, op, sum, cbits;
1459
1460EOT
1461	local(@labs) = ($labpcp2, $labcpar, $lablogar,
1462			$labandar, $labsbcar, $labsubar,
1463			$labadcar, $labaddar, $labadddd,
1464			$labdecr, $labincr);
1465	&ed_switch;
1466	($labpcp2, $labcpar, $lablogar,
1467	 $labandar, $labsbcar, $labsubar,
1468	 $labadcar, $labaddar, $labadddd,
1469	 $labdecr, $labincr) = @labs;
1470	print <<'EOT';
1471    SAVE_STATE();
1472}
1473
1474EOT
1475}
1476
1477    print <<'EOT';
1478FASTWORK
1479simz80(FASTREG PC)
1480{
1481    FASTREG AF = af[af_sel];
1482    FASTREG BC = regs[regs_sel].bc;
1483    FASTREG DE = regs[regs_sel].de;
1484    FASTREG HL = regs[regs_sel].hl;
1485    FASTREG SP = sp;
1486EOT
1487    if ($dfd_inline) {
1488	print <<'EOT';
1489    FASTREG IX = ix;
1490    FASTREG IY = iy;
1491EOT
1492    }
1493    print "    FASTWORK temp, acu, sum, cbits;\n";
1494    print "    FASTWORK op, adr;\n" if ($cb_inline + $dfd_inline +
1495				  $ed_inline != 0);
1496
1497    if ($optab) {
1498	print "static void *optab[256] = {\n";
1499	for (0..255) {
1500	    print "\t" if (($_ & 7) == 0);
1501	    printf("&&op_%02x,", $_);
1502	    print "\n" if (($_ & 7) == 7);
1503	}
1504	print "};\n";
1505    }
1506print <<'EOT';
1507
1508#ifdef DEBUG
1509    while (!stopsim) {
1510#else
1511    while (1) {
1512#endif
1513EOT
1514    if ($optab) {
1515#	print "    goto *optab[++PC,RAM(PC-1)]; {\n";
1516	print "    goto *optab[RAM_pp(PC)]; {\n";
1517    }
1518    else {
1519	print "    switch(RAM_pp(PC)) {\n";
1520    }
1521    $needbreak = 0;
1522}
1523
1524sub postamble {
1525    print <<'EOT';
1526    }
1527    }
1528/* make registers visible for debugging if interrupted */
1529    SAVE_STATE();
1530    return (PC&0xffff)|0x10000;	/* flag non-bios stop */
1531}
1532EOT
1533}
1534