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