├── .gitattributes ├── readme.md ├── .gitignore ├── MyZ80.vcxproj.filters ├── MyZ80.sln ├── MyZ80.vcxproj └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## MyZ80 - Mockba's yet another Z80 emulator 2 | 3 | This is a project I am writing with the intent to have a Z80 emulator code on my RunCPM and at the same time use the same code as a model on Proteus. 4 | 5 | The code is still in its infancy, but some of the Z80 instructions are already working. 6 | 7 | There's still a lot to be done, but it is here in case anyone is interested. 8 | 9 | The method I am using to emulate the Z80 is the one described on http://www.z80.info/decoding.htm 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /MyZ80.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /MyZ80.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyZ80", "MyZ80.vcxproj", "{AAF4208E-4584-468F-8E34-DA0FC05F6C01}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Debug|x64.ActiveCfg = Debug|x64 17 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Debug|x64.Build.0 = Debug|x64 18 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Debug|x86.ActiveCfg = Debug|Win32 19 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Debug|x86.Build.0 = Debug|Win32 20 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Release|x64.ActiveCfg = Release|x64 21 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Release|x64.Build.0 = Release|x64 22 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Release|x86.ActiveCfg = Release|Win32 23 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /MyZ80.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {AAF4208E-4584-468F-8E34-DA0FC05F6C01} 23 | MyZ80 24 | 8.1 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | MultiByte 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | MultiByte 39 | 40 | 41 | Application 42 | true 43 | v140 44 | MultiByte 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Level3 75 | Disabled 76 | true 77 | 78 | 79 | 80 | 81 | Level3 82 | Disabled 83 | true 84 | 85 | 86 | 87 | 88 | Level3 89 | MaxSpeed 90 | true 91 | true 92 | true 93 | 94 | 95 | true 96 | true 97 | 98 | 99 | 100 | 101 | Level3 102 | MaxSpeed 103 | true 104 | true 105 | true 106 | 107 | 108 | true 109 | true 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BIG_ENDIAN // Define if host CPU is Big Endian 5 | 6 | typedef bool pin; 7 | 8 | typedef uint8_t Byte; 9 | typedef uint16_t Word; 10 | typedef uint8_t Reg8; 11 | typedef uint16_t Reg16; 12 | typedef uint32_t Reg32; 13 | 14 | #define RAMSIZE 65536 15 | 16 | Byte Ram[RAMSIZE]; // RAM Memory 17 | 18 | pin Clock = 1; 19 | pin nReset = 1; 20 | 21 | Byte Instr; // Current (fetched) instruction 22 | Byte M; // Current (fetched) memory byte 23 | 24 | // Instruction Decoding x x y y y z z z 25 | // - - p p q - - - 26 | // 27 | #define GetX(i) ((i & 0b11000000) >> 6) 28 | #define GetY(i) ((i & 0b00111000) >> 3) 29 | #define GetZ(i) (i & 0b00000111) 30 | #define GetP(i) ((i & 0b00110000) >> 4) 31 | #define GetQ(i) ((i & 0b00001000) >> 3) 32 | 33 | // Register table 34 | // 0 1 2 3 4 5 6 7 8 9 10 12 14 15 16 17 18 19 20 21 22 23 24 25 35 | // B C D E H L IXh IXl IYh IYl SP PC A F B' C' D' E' H' L' A' F' I R 36 | Reg8 Regs[26]; 37 | 38 | #ifdef BIG_ENDIAN 39 | //Pointers to the 8 bit registers 40 | Reg8 *pB = &Regs[1]; 41 | Reg8 *pC = &Regs[0]; 42 | Reg8 *pD = &Regs[3]; 43 | Reg8 *pE = &Regs[2]; 44 | Reg8 *pH = &Regs[5]; 45 | Reg8 *pL = &Regs[4]; 46 | Reg8 *pIXh = &Regs[7]; 47 | Reg8 *pIXl = &Regs[6]; 48 | Reg8 *pIYh = &Regs[9]; 49 | Reg8 *pIYl = &Regs[8]; 50 | Reg8 *pA = &Regs[15]; 51 | Reg8 *pF = &Regs[14]; 52 | Reg8 *pB_ = &Regs[17]; 53 | Reg8 *pC_ = &Regs[16]; 54 | Reg8 *pD_ = &Regs[19]; 55 | Reg8 *pE_ = &Regs[18]; 56 | Reg8 *pH_ = &Regs[21]; 57 | Reg8 *pL_ = &Regs[20]; 58 | Reg8 *pA_ = &Regs[23]; 59 | Reg8 *pF_ = &Regs[22]; 60 | Reg8 *pI = &Regs[25]; 61 | Reg8 *pR = &Regs[24]; 62 | #else 63 | Reg8 *pB = &Regs[0]; 64 | Reg8 *pC = &Regs[1]; 65 | Reg8 *pD = &Regs[2]; 66 | Reg8 *pE = &Regs[3]; 67 | Reg8 *pH = &Regs[4]; 68 | Reg8 *pL = &Regs[5]; 69 | Reg8 *pIXh = &Regs[6]; 70 | Reg8 *pIXl = &Regs[7]; 71 | Reg8 *pIYh = &Regs[8]; 72 | Reg8 *pIYl = &Regs[9]; 73 | Reg8 *pA = &Regs[14]; 74 | Reg8 *pF = &Regs[15]; 75 | Reg8 *pB_ = &Regs[16]; 76 | Reg8 *pC_ = &Regs[17]; 77 | Reg8 *pD_ = &Regs[18]; 78 | Reg8 *pE_ = &Regs[19]; 79 | Reg8 *pH_ = &Regs[20]; 80 | Reg8 *pL_ = &Regs[21]; 81 | Reg8 *pA_ = &Regs[22]; 82 | Reg8 *pF_ = &Regs[23]; 83 | Reg8 *pI = &Regs[24]; 84 | Reg8 *pR = &Regs[25]; 85 | #endif 86 | 87 | // Pointers to the 16 bit registers 88 | Reg16 *pBC = (Reg16*)&Regs[0]; 89 | Reg16 *pDE = (Reg16*)&Regs[2]; 90 | Reg16 *pHL = (Reg16*)&Regs[4]; 91 | Reg16 *pIX = (Reg16*)&Regs[6]; 92 | Reg16 *pIY = (Reg16*)&Regs[8]; 93 | Reg16 *pSP = (Reg16*)&Regs[10]; 94 | Reg16 *pPC = (Reg16*)&Regs[12]; 95 | Reg16 *pAF = (Reg16*)&Regs[14]; 96 | Reg16 *pBC_ = (Reg16*)&Regs[16]; 97 | Reg16 *pDE_ = (Reg16*)&Regs[18]; 98 | Reg16 *pHL_ = (Reg16*)&Regs[20]; 99 | Reg16 *pAF_ = (Reg16*)&Regs[22]; 100 | 101 | // 8 Bit registers (renaming the pointers) 102 | #define B (*pB) 103 | #define C (*pC) 104 | #define D (*pD) 105 | #define E (*pE) 106 | #define H (*pH) 107 | #define L (*pL) 108 | #define IXh (*pIXh) 109 | #define IXl (*pIXl) 110 | #define IYh (*pIYh) 111 | #define IYl (*pIYl) 112 | #define A (*pA) 113 | #define F (*pF) 114 | #define B_ (*pB_) 115 | #define C_ (*pC_) 116 | #define D_ (*pD_) 117 | #define E_ (*pE_) 118 | #define H_ (*pH_) 119 | #define L_ (*pL_) 120 | #define A_ (*pA_) 121 | #define F_ (*pF_) 122 | #define I (*pI) 123 | #define R (*pR) 124 | 125 | // 16 Bit registers (renaming the pointers) 126 | #define BC (*pBC) 127 | #define DE (*pDE) 128 | #define HL (*pHL) 129 | #define IX (*pIX) 130 | #define IY (*pIY) 131 | #define SP (*pSP) 132 | #define PC (*pPC) 133 | #define AF (*pAF) 134 | #define BC_ (*pBC_) 135 | #define DE_ (*pDE_) 136 | #define HL_ (*pHL_) 137 | #define AF_ (*pAF_) 138 | 139 | // Flags (SZ5H3PNC) 140 | #define fS (F & 0b10000000) 141 | #define fZ (F & 0b01000000) 142 | #define fY (F & 0b00100000) 143 | #define fH (F & 0b00010000) 144 | #define fX (F & 0b00001000) 145 | #define fP (F & 0b00000100) 146 | #define fN (F & 0b00000010) 147 | #define fC (F & 0b00000001) 148 | 149 | // Data tables 150 | Reg16 *rp[4]; // BC DE HL SP 151 | Reg16 *rp2[4]; // BC DE HL AF 152 | Reg8 *r[8]; // B C D E H L (HL) A 153 | 154 | /* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */ 155 | static const Byte parityTable[256] = { 156 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 157 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 158 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 159 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 160 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 161 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 162 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 163 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 164 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 165 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 166 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 167 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 168 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 169 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 170 | 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, 171 | 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, 172 | }; 173 | 174 | /* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */ 175 | static const Byte incTable[257] = { 176 | 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 177 | 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 178 | 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 179 | 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 180 | 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 181 | 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 182 | 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 183 | 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 184 | 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, 185 | 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, 186 | 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 187 | 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 188 | 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, 189 | 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, 190 | 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 191 | 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80 192 | }; 193 | 194 | /* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */ 195 | static const Byte decTable[256] = { 196 | 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, 197 | 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, 198 | 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, 199 | 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, 200 | 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, 201 | 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, 202 | 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, 203 | 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, 204 | 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, 205 | 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, 206 | 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, 207 | 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, 208 | 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, 209 | 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, 210 | 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, 211 | 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, 212 | }; 213 | 214 | /* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */ 215 | static const Byte cbitsTable[512] = { 216 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 218 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 220 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 222 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 224 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 226 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 228 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 230 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231 | 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 232 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 233 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 234 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 235 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 236 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 237 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 238 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 239 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 240 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 241 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 242 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 243 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 244 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 245 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 246 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 247 | 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 248 | }; 249 | 250 | /* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */ 251 | static const Word addTable[512] = { 252 | 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, 253 | 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, 254 | 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, 255 | 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, 256 | 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, 257 | 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, 258 | 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, 259 | 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, 260 | 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, 261 | 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, 262 | 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, 263 | 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, 264 | 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, 265 | 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, 266 | 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, 267 | 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, 268 | 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, 269 | 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, 270 | 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, 271 | 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, 272 | 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, 273 | 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, 274 | 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, 275 | 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, 276 | 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, 277 | 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, 278 | 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, 279 | 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, 280 | 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, 281 | 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, 282 | 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, 283 | 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, 284 | 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, 285 | 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, 286 | 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, 287 | 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, 288 | 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, 289 | 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, 290 | 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, 291 | 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, 292 | 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, 293 | 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, 294 | 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, 295 | 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, 296 | 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, 297 | 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, 298 | 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, 299 | 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, 300 | 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, 301 | 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, 302 | 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, 303 | 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, 304 | 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, 305 | 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, 306 | 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, 307 | 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, 308 | 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, 309 | 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, 310 | 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, 311 | 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, 312 | 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, 313 | 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, 314 | 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, 315 | 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, 316 | }; 317 | 318 | /* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */ 319 | static const Word subTable[256] = { 320 | 0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702, 321 | 0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a, 322 | 0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702, 323 | 0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a, 324 | 0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722, 325 | 0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a, 326 | 0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722, 327 | 0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a, 328 | 0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702, 329 | 0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a, 330 | 0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702, 331 | 0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a, 332 | 0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722, 333 | 0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a, 334 | 0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722, 335 | 0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a, 336 | 0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782, 337 | 0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a, 338 | 0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782, 339 | 0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a, 340 | 0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2, 341 | 0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa, 342 | 0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2, 343 | 0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa, 344 | 0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782, 345 | 0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a, 346 | 0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782, 347 | 0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a, 348 | 0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2, 349 | 0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa, 350 | 0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2, 351 | 0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa, 352 | }; 353 | 354 | /* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */ 355 | static const Byte andTable[256] = { 356 | 0x54,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 357 | 0x18,0x1c,0x1c,0x18,0x1c,0x18,0x18,0x1c, 358 | 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 359 | 0x1c,0x18,0x18,0x1c,0x18,0x1c,0x1c,0x18, 360 | 0x30,0x34,0x34,0x30,0x34,0x30,0x30,0x34, 361 | 0x3c,0x38,0x38,0x3c,0x38,0x3c,0x3c,0x38, 362 | 0x34,0x30,0x30,0x34,0x30,0x34,0x34,0x30, 363 | 0x38,0x3c,0x3c,0x38,0x3c,0x38,0x38,0x3c, 364 | 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 365 | 0x1c,0x18,0x18,0x1c,0x18,0x1c,0x1c,0x18, 366 | 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 367 | 0x18,0x1c,0x1c,0x18,0x1c,0x18,0x18,0x1c, 368 | 0x34,0x30,0x30,0x34,0x30,0x34,0x34,0x30, 369 | 0x38,0x3c,0x3c,0x38,0x3c,0x38,0x38,0x3c, 370 | 0x30,0x34,0x34,0x30,0x34,0x30,0x30,0x34, 371 | 0x3c,0x38,0x38,0x3c,0x38,0x3c,0x3c,0x38, 372 | 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94, 373 | 0x9c,0x98,0x98,0x9c,0x98,0x9c,0x9c,0x98, 374 | 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 375 | 0x98,0x9c,0x9c,0x98,0x9c,0x98,0x98,0x9c, 376 | 0xb4,0xb0,0xb0,0xb4,0xb0,0xb4,0xb4,0xb0, 377 | 0xb8,0xbc,0xbc,0xb8,0xbc,0xb8,0xb8,0xbc, 378 | 0xb0,0xb4,0xb4,0xb0,0xb4,0xb0,0xb0,0xb4, 379 | 0xbc,0xb8,0xb8,0xbc,0xb8,0xbc,0xbc,0xb8, 380 | 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 381 | 0x98,0x9c,0x9c,0x98,0x9c,0x98,0x98,0x9c, 382 | 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94, 383 | 0x9c,0x98,0x98,0x9c,0x98,0x9c,0x9c,0x98, 384 | 0xb0,0xb4,0xb4,0xb0,0xb4,0xb0,0xb0,0xb4, 385 | 0xbc,0xb8,0xb8,0xbc,0xb8,0xbc,0xbc,0xb8, 386 | 0xb4,0xb0,0xb0,0xb4,0xb0,0xb4,0xb4,0xb0, 387 | 0xb8,0xbc,0xbc,0xb8,0xbc,0xb8,0xb8,0xbc, 388 | }; 389 | 390 | /* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */ 391 | static const Byte xororTable[256] = { 392 | 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 393 | 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c, 394 | 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 395 | 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08, 396 | 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24, 397 | 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28, 398 | 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20, 399 | 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c, 400 | 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 401 | 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08, 402 | 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 403 | 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c, 404 | 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20, 405 | 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c, 406 | 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24, 407 | 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28, 408 | 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, 409 | 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88, 410 | 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 411 | 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c, 412 | 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0, 413 | 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac, 414 | 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4, 415 | 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8, 416 | 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 417 | 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c, 418 | 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, 419 | 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88, 420 | 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4, 421 | 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8, 422 | 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0, 423 | 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac, 424 | }; 425 | 426 | #define SET_PVS(s) (((Tmp16_2 >> 6) ^ (Tmp16_2 >> 5)) & 4) 427 | #define SET_PV (SET_PVS(Tmp16_1)) 428 | #define SET_PV2(x) ((Tmp8_1 == (x)) << 2) 429 | 430 | // Memory manipulation functions 431 | // (Must be different for hardware based emulation) 432 | Byte Fetch8(Word Addr) { 433 | return(Ram[Addr]); 434 | } 435 | 436 | void Write8(Word Addr, Byte Value) { 437 | Ram[Addr] = Value; 438 | } 439 | 440 | Word Fetch16(Word Addr) { 441 | #ifdef BIG_ENDIAN 442 | return((Ram[Addr + 1] << 8) + Ram[Addr]); 443 | #else 444 | return((Ram[Addr] << 8) + Ram[Addr + 1]); 445 | #endif 446 | } 447 | 448 | void Write16(Word Addr, Word Value) { 449 | #ifdef BIG_ENDIAN 450 | Ram[Addr + 1] = (Value & 0xff); 451 | Ram[Addr] = ((Value >> 8) & 0xff); 452 | #else 453 | Ram[Addr] = (Value & 0xff); 454 | Ram[Addr + 1] = ((Value >> 8) & 0xff); 455 | #endif 456 | } 457 | 458 | void TestLoad(void) { // Loads the memory with a small test application 459 | int i = 0; 460 | 461 | // Ram[i++] = 0x00; // NOP 462 | Ram[i++] = 0x01; // LD BC, 0x0F29 463 | Ram[i++] = 0x29; 464 | Ram[i++] = 0x0F; 465 | // Ram[i++] = 0x02; // LD (BC), A 466 | // Ram[i++] = 0x03; // INC BC 467 | // Ram[i++] = 0x04; // INC B 468 | // Ram[i++] = 0x05; // DEC B 469 | // Ram[i++] = 0x06; // LD B, 0x7F 470 | // Ram[i++] = 0x7F; 471 | // Ram[i++] = 0x06; // LD B, 0x00 472 | // Ram[i++] = 0x00; 473 | // Ram[i++] = 0x0E; // LD C, 0x03 474 | // Ram[i++] = 0x03; 475 | // Ram[i++] = 0x08; // EX AF, AF' 476 | // Ram[i++] = 0x10; // DJNZ, -2 477 | // Ram[i++] = 0xFE; 478 | Ram[i++] = 0x21; // LD HL, 0x0200 479 | Ram[i++] = 0x00; 480 | Ram[i++] = 0x02; 481 | Ram[i++] = 0x09; // ADD HL, BC 482 | Ram[i++] = 0x76; // HLT 483 | 484 | } 485 | 486 | void Z80Init(void) { // Must be called before anything else 487 | 488 | // Prepare register pair table 489 | rp[0] = pBC; 490 | rp[1] = pDE; 491 | rp[2] = pHL; 492 | rp[3] = pSP; 493 | 494 | // Prepare second register pair table 495 | rp2[0] = pBC; 496 | rp2[1] = pDE; 497 | rp2[2] = pHL; 498 | rp2[3] = pAF; 499 | 500 | // Prepare register table 501 | r[0] = pB; 502 | r[1] = pC; 503 | r[2] = pD; 504 | r[3] = pE; 505 | r[4] = pH; 506 | r[5] = pL; 507 | r[7] = pA; 508 | 509 | } 510 | 511 | void Z80Reset(void) { // Resets all Z80 registers (and other stuff) to their initial values 512 | Byte i; 513 | for (i = 0; i < 26; i++) { 514 | Regs[i] = 0; 515 | } 516 | } 517 | 518 | Byte Z80DecodeCB(void) { // Decodes and executes the CB prefix instruction 519 | Byte Result = 0; 520 | Byte x, y, z, p, q; 521 | Reg8 Tmp8; 522 | Reg16 Tmp16; 523 | 524 | Instr = Fetch8(PC++); 525 | x = GetX(Instr); 526 | y = GetY(Instr); 527 | z = GetZ(Instr); 528 | p = GetP(Instr); 529 | q = GetQ(Instr); 530 | 531 | R++; 532 | 533 | if (x == 0) { // rot[y] r[z] 534 | 535 | } 536 | if (x == 1) { // BIT y, r[z] 537 | 538 | } 539 | if (x == 2) { // RES y, r[z] 540 | 541 | } 542 | if (x == 3) { // SET y, r[z] 543 | 544 | } 545 | return(Result); 546 | } 547 | 548 | Byte Z80DecodeDD(void) { // Decodes and executes the CB prefix instruction 549 | Byte Result = 0; 550 | Byte x, y, z, p, q; 551 | Reg8 Tmp8; 552 | Reg16 Tmp16; 553 | 554 | Instr = Fetch8(PC++); 555 | x = GetX(Instr); 556 | y = GetY(Instr); 557 | z = GetZ(Instr); 558 | p = GetP(Instr); 559 | q = GetQ(Instr); 560 | 561 | R++; 562 | 563 | return(Result); 564 | } 565 | 566 | Byte Z80DecodeED(void) { // Decodes and executes the CB prefix instruction 567 | Byte Result = 0; 568 | Byte x, y, z, p, q; 569 | Reg8 Tmp8; 570 | Reg16 Tmp16; 571 | 572 | Instr = Fetch8(PC++); 573 | x = GetX(Instr); 574 | y = GetY(Instr); 575 | z = GetZ(Instr); 576 | p = GetP(Instr); 577 | q = GetQ(Instr); 578 | 579 | R++; 580 | 581 | return(Result); 582 | } 583 | 584 | Byte Z80DecodeFD(void) { // Decodes and executes the CB prefix instruction 585 | Byte Result = 0; 586 | Byte x, y, z, p, q; 587 | Reg8 Tmp8; 588 | Reg16 Tmp16; 589 | 590 | Instr = Fetch8(PC++); 591 | x = GetX(Instr); 592 | y = GetY(Instr); 593 | z = GetZ(Instr); 594 | p = GetP(Instr); 595 | q = GetQ(Instr); 596 | 597 | R++; 598 | 599 | return(Result); 600 | } 601 | 602 | Byte Z80Decode(void) { // Decodes and executes the instruction pointed at by PC 603 | Byte Result = 0; 604 | Byte x, y, z, p, q; 605 | Reg8 Tmp8_1; 606 | Reg16 Tmp16_1, Tmp16_2; 607 | Reg32 Tmp32; 608 | 609 | if (Clock) { 610 | Instr = Fetch8(PC++); 611 | x = GetX(Instr); 612 | y = GetY(Instr); 613 | z = GetZ(Instr); 614 | p = GetP(Instr); 615 | q = GetQ(Instr); 616 | 617 | R++; 618 | 619 | if (x == 0) { 620 | if (z == 0) { 621 | if (y == 0) { // NOP 622 | // Do nothing 623 | } 624 | if (y == 1) { // EX AF,AF' 625 | Tmp16_1 = AF; AF = AF_; AF_ = Tmp16_1; 626 | } 627 | if (y == 2) { // DJNZ d 628 | Tmp8_1 = Fetch8(PC++); 629 | if (--BC) { 630 | PC += (int8_t)Tmp8_1; 631 | } 632 | } 633 | if (y == 3) { // JR d 634 | Tmp8_1 = Fetch8(PC++); 635 | PC += (int8_t)Tmp8_1; 636 | } 637 | if (y > 3) { // JR cc[y-4], d 638 | Tmp8_1 = Fetch8(PC++); 639 | if (y == 4) { // JR NZ, d 640 | if (!fZ) 641 | PC += (int8_t)Tmp8_1; 642 | } 643 | if (y == 5) { // JR Z, d 644 | if (fZ) 645 | PC += (int8_t)Tmp8_1; 646 | } 647 | if (y == 6) { // JR NC, d 648 | if (!fC) 649 | PC += (int8_t)Tmp8_1; 650 | } 651 | if (y == 7) { // JR C, d 652 | if (fC) 653 | PC += (int8_t)Tmp8_1; 654 | } 655 | } 656 | } 657 | if (z == 1) { 658 | if (q == 0) { // LD rp[p], nn 659 | Tmp16_1 = Fetch16(PC); PC += 2; 660 | *rp[p] = Tmp16_1; 661 | } 662 | if (q == 1) { // ADD HL, rp[p] 663 | Tmp32 = HL + *rp[p]; 664 | F = (F & ~0x3b) | ((Tmp32 >> 8) & 0x28) | cbitsTable[(HL ^ *rp[p] ^ Tmp32) >> 8]; 665 | HL = Tmp32; 666 | } 667 | } 668 | if (z == 2) { 669 | if (q == 0) { 670 | if (p == 0) { // LD (BC), A 671 | Write8(BC, A); 672 | } 673 | if (p == 1) { // LD (DE), A 674 | Write8(DE, A); 675 | } 676 | if (p == 2) { // LD (nn), HL 677 | Tmp16_1 = Fetch16(PC); PC += 2; 678 | Write16(Tmp16_1, HL); 679 | } 680 | if (p == 3) { // LD (nn), A 681 | Tmp16_1 = Fetch16(PC); PC += 2; 682 | Write8(Tmp16_1, A); 683 | } 684 | } 685 | if (q == 1) { 686 | if (p == 0) { // LD A, (BC) 687 | A = Fetch8(BC); 688 | } 689 | if (p == 1) { // LD A, (DE) 690 | A = Fetch8(DE); 691 | } 692 | if (p == 2) { // LD HL, (nn) 693 | Tmp16_1 = Fetch16(PC); PC += 2; 694 | HL = Fetch16(Tmp16_1); 695 | } 696 | if (p == 3) { // LD A, (nn) 697 | Tmp16_1 = Fetch16(PC); PC += 2; 698 | A = Fetch8(Tmp16_1); 699 | } 700 | } 701 | } 702 | if (z == 3) { 703 | if (q == 0) { // INC rp[p] 704 | (*rp[p])++; 705 | } 706 | if (q == 1) { // DEC rp[p] 707 | (*rp[p])--; 708 | } 709 | } 710 | if (z == 4) { // INC r[y] 711 | if (y == 6) { 712 | Tmp8_1 = Fetch8(HL); 713 | Tmp8_1++; 714 | Write8(HL, Tmp8_1); 715 | } else { 716 | Tmp8_1 = (*r[y]); 717 | Tmp8_1++; 718 | } 719 | F = (F & ~0xfe) | incTable[*r[y]] | SET_PV2(0x80); 720 | } 721 | if (z == 5) { // DEC r[y] 722 | if (y == 6) { 723 | Tmp8_1 = Fetch8(HL); 724 | Tmp8_1--; 725 | Write8(HL, Tmp8_1); 726 | } else { 727 | Tmp8_1 = (*r[y]); 728 | Tmp8_1--; 729 | } 730 | F = (F & ~0xfe) | decTable[*r[y]] | SET_PV2(0x7f); 731 | } 732 | if (z == 6) { // LD r[y], n 733 | Tmp8_1 = Fetch8(PC++); 734 | if (y == 6) { 735 | Write8(HL, Tmp8_1); 736 | } else { 737 | (*r[y]) = Tmp8_1; 738 | } 739 | } 740 | if (z == 7) { 741 | if (y == 0) { // RLCA 742 | Tmp8_1 = (A & 0x80) >> 7; 743 | A = (A << 1) & Tmp8_1; 744 | F = (F & 0xc4) | (A & 0x28) | Tmp8_1; 745 | } 746 | if (y == 1) { // RRCA 747 | Tmp8_1 = (A & 0x01); 748 | A = (A >> 1) & (Tmp8_1 << 7); 749 | F = (F & 0xc4) | (A & 0x28) | Tmp8_1; 750 | } 751 | if (y == 2) { // RLA 752 | Tmp8_1 = (A & 0x80) >> 7; 753 | A = (A << 1) & (F & 0x01); 754 | F = (F & 0xc4) | (A & 0x28) | Tmp8_1; 755 | } 756 | if (y == 3) { // RRA 757 | Tmp8_1 = (A & 0x01); 758 | A = (A >> 1) & (F << 7); 759 | F = (F & 0xc4) | (A & 0x28) | Tmp8_1; 760 | } 761 | if (y == 4) { // DAA 762 | Tmp8_1 = A; 763 | if (fN) { 764 | if (fH || (A & 0x0f) > 9) Tmp8_1 -= 6; 765 | if (fC || A > 0x99) Tmp8_1 -= 0x60; 766 | } else { 767 | if (fH || (A & 0x0f) > 9) Tmp8_1 += 6; 768 | if (fC || A > 0x99) Tmp8_1 += 0x60; 769 | } 770 | F = (F & 0x03) | parityTable[Tmp8_1] | (A > 0x99) | ((A^Tmp8_1) & 0x10); 771 | A = Tmp8_1; 772 | } 773 | if (y == 5) { // CPL 774 | A = ~A; 775 | F = (F & 0xc5) | (A & 0x28) | 0x12; 776 | } 777 | if (y == 6) { // SCF 778 | F = (F & 0xc4) | (A & 0x28) | 0x01; 779 | } 780 | if (y == 7) { // CCF 781 | Tmp8_1 = ~F & 0x01; 782 | F = (F & 0xc4) | (A & 0x28) | (fC << 4) | Tmp8_1; 783 | } 784 | } 785 | } 786 | if (x == 1) { 787 | if (z == 6) { 788 | if (y == 6) { // HLT (replaces LD (HL), (HL)) 789 | Result = 1; 790 | } else { // LD r[y], (HL) 791 | Tmp8_1 = Fetch8(HL); 792 | (*r[y]) = Tmp8_1; 793 | } 794 | } else { 795 | if (y == 6) { // LD (HL), r[z] 796 | Write8(HL, (*r[z])); 797 | } else { // LD r[y], r[z] 798 | (*r[y]) = (*r[z]); 799 | } 800 | } 801 | } 802 | if (x == 2) { // alu[y] r[z] 803 | if (z == 6) { 804 | Tmp8_1 = Fetch8(HL); 805 | } else { 806 | Tmp8_1 = (*r[z]); 807 | } 808 | if (y == 0) { // ADD A, r[z] 809 | Tmp16_1 = A + Tmp8_1; 810 | Tmp16_2 = A ^ Tmp8_1 ^ Tmp16_1; 811 | AF = addTable[Tmp16_1] | cbitsTable[Tmp16_2] | (SET_PV); 812 | } 813 | if (y == 1) { // ADC A, r[z] 814 | Tmp16_1 = A + Tmp8_1 + (fC != 0); 815 | Tmp16_2 = A ^ Tmp8_1 ^ Tmp16_1; 816 | AF = addTable[Tmp16_1] | cbitsTable[Tmp16_2] | (SET_PV); 817 | } 818 | if (y == 2) { // SUB r[z] 819 | Tmp16_1 = A - Tmp8_1; 820 | Tmp16_2 = A ^ Tmp8_1 ^ Tmp16_1; 821 | AF = subTable[Tmp16_1 & 0xff] | cbitsTable[Tmp16_2 & 0x1ff] | (SET_PV); 822 | } 823 | if (y == 3) { // SBC A, 824 | Tmp16_1 = A - Tmp8_1 - (fC != 0); 825 | Tmp16_2 = A ^ Tmp8_1 ^ Tmp16_1; 826 | AF = subTable[Tmp16_1 & 0xff] | cbitsTable[Tmp16_2 & 0x1ff] | (SET_PV); 827 | } 828 | if (y == 4) { // AND 829 | A = A & Tmp8_1; 830 | F = andTable[A]; 831 | } 832 | if (y == 5) { // XOR 833 | A = A ^ Tmp8_1; 834 | F = xororTable[A]; 835 | } 836 | if (y == 6) { // OR 837 | A = A | Tmp8_1; 838 | F = xororTable[A]; 839 | } 840 | if (y == 7) { // CP 841 | 842 | } 843 | } 844 | if (x == 3) { 845 | if (z == 0) { // RET cc[y] 846 | 847 | } 848 | if (z == 1) { 849 | if (q == 0) { // POP rp2[p] 850 | 851 | } else { 852 | if (p == 0) { // RET 853 | 854 | } 855 | if (p == 1) { // EXX 856 | 857 | } 858 | if (p == 2) { // JP HL 859 | 860 | } 861 | if (p == 3) { // LD SP,HL 862 | 863 | } 864 | } 865 | 866 | } 867 | if (z == 2) { // JP cc[y], nn 868 | 869 | } 870 | if (z == 3) { 871 | if (y == 0) { // JP nn 872 | 873 | } 874 | if (y == 1) { // (CB prefix) 875 | Z80DecodeCB(); 876 | } 877 | if (y == 2) { // OUT (n), A 878 | 879 | } 880 | if (y == 3) { // IN A, (n) 881 | 882 | } 883 | if (y == 4) { // EX (SP), HL 884 | 885 | } 886 | if (y == 5) { // EX DE, HL 887 | 888 | } 889 | if (y == 6) { // DI 890 | 891 | } 892 | if (y == 7) { // EI 893 | 894 | } 895 | } 896 | if (z == 4) { // CALL cc[y], nn 897 | 898 | } 899 | if (z == 5) { 900 | if (q == 0) { // PUSH rp2[p] 901 | 902 | } else { 903 | if (p == 0) { // CALL nn 904 | 905 | } 906 | if (p == 1) { // (DD prefix) 907 | Z80DecodeDD(); 908 | } 909 | if (p == 2) { // (ED prefix) 910 | Z80DecodeED(); 911 | } 912 | if (p == 3) { // (FD prefix) 913 | Z80DecodeFD(); 914 | } 915 | } 916 | if (z == 6) { // alu[y] n 917 | 918 | } 919 | if (z == 7) { // RST y*8 920 | 921 | } 922 | } 923 | } 924 | } 925 | return(Result); 926 | } 927 | 928 | int main(void) { 929 | printf("MyZ80 Test Interface\n"); 930 | printf("Copyright (C) 2016 Marcelo F. Dantas\n"); 931 | 932 | Z80Init(); 933 | 934 | TestLoad(); 935 | 936 | Z80Reset(); 937 | while (true) { 938 | if (Z80Decode()) { 939 | break; 940 | } 941 | } 942 | } --------------------------------------------------------------------------------