1 /* Emulations of the ED operations of the Z80 instruction set. 2 * Copyright (C) 1994 Ian Collier. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 #define input(var) { unsigned short u;\ 20 var=u=in(b,c);\ 21 tstates+=u>>8;\ 22 f=(f&1)|(var&0xa8)|((!var)<<6)|parity(var);\ 23 } 24 #define sbchl(x) { unsigned short z=(x);\ 25 unsigned long t=(hl-z-cy)&0x1ffff;\ 26 f=((t>>8)&0xa8)|(t>>16)|2|\ 27 (((hl&0xfff)<(z&0xfff)+cy)<<4)|\ 28 (((hl^z)&(hl^t)&0x8000)>>13)|\ 29 ((!(t&0xffff))<<6)|2;\ 30 l=t;\ 31 h=t>>8;\ 32 } 33 34 #define adchl(x) { unsigned short z=(x);\ 35 unsigned long t=hl+z+cy;\ 36 f=((t>>8)&0xa8)|(t>>16)|\ 37 (((hl&0xfff)+(z&0xfff)+cy>0xfff)<<4)|\ 38 (((~hl^z)&(hl^t)&0x8000)>>13)|\ 39 ((!(t&0xffff))<<6)|2;\ 40 l=t;\ 41 h=t>>8;\ 42 } 43 44 #define neg (a=-a,\ 45 f=(a&0xa8)|((!a)<<6)|(((a&15)>0)<<4)|((a==128)<<2)|2|(a>0)) 46 47 { 48 unsigned char op=fetch(pc); 49 pc++; 50 radjust++; 51 switch(op){ 52 instr(0x40,8); 53 input(b); 54 endinstr; 55 56 instr(0x41,8); 57 tstates+=out(b,c,b); 58 endinstr; 59 60 instr(0x42,11); 61 sbchl(bc); 62 endinstr; 63 64 instr(0x43,16); 65 {unsigned short addr=fetch2(pc); 66 pc+=2; 67 store2b(addr,b,c); 68 } 69 endinstr; 70 71 instr(0x44,4); 72 neg; 73 endinstr; 74 75 instr(0x45,4); 76 iff1=iff2; 77 ret; 78 endinstr; 79 80 instr(0x46,4); 81 im=0; 82 endinstr; 83 84 instr(0x47,5); 85 i=a; 86 endinstr; 87 88 instr(0x48,8); 89 input(c); 90 endinstr; 91 92 instr(0x49,8); 93 tstates+=out(b,c,c); 94 endinstr; 95 96 instr(0x4a,11); 97 adchl(bc); 98 endinstr; 99 100 instr(0x4b,16); 101 {unsigned short addr=fetch2(pc); 102 pc+=2; 103 c=fetch(addr); 104 b=fetch(addr+1); 105 } 106 endinstr; 107 108 instr(0x4c,4); 109 neg; 110 endinstr; 111 112 instr(0x4d,4); 113 ret; 114 endinstr; 115 116 instr(0x4e,4); 117 im=1; 118 endinstr; 119 120 instr(0x4f,5); 121 r=a; 122 radjust=r; 123 endinstr; 124 125 instr(0x50,8); 126 input(d); 127 endinstr; 128 129 instr(0x51,8); 130 tstates+=out(b,c,d); 131 endinstr; 132 133 instr(0x52,11); 134 sbchl(de); 135 endinstr; 136 137 instr(0x53,16); 138 {unsigned short addr=fetch2(pc); 139 pc+=2; 140 store2b(addr,d,e); 141 } 142 endinstr; 143 144 instr(0x54,4); 145 neg; 146 endinstr; 147 148 instr(0x55,4); 149 ret; 150 endinstr; 151 152 instr(0x56,4); 153 im=2; 154 endinstr; 155 156 instr(0x57,5); 157 a=i; 158 f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2); 159 endinstr; 160 161 instr(0x58,8); 162 input(e); 163 endinstr; 164 165 instr(0x59,8); 166 tstates+=out(b,c,e); 167 endinstr; 168 169 instr(0x5a,11); 170 adchl(de); 171 endinstr; 172 173 instr(0x5b,16); 174 {unsigned short addr=fetch2(pc); 175 pc+=2; 176 e=fetch(addr); 177 d=fetch(addr+1); 178 } 179 endinstr; 180 181 instr(0x5c,4); 182 neg; 183 endinstr; 184 185 instr(0x5d,4); 186 ret; 187 endinstr; 188 189 instr(0x5e,4); 190 im=3; 191 endinstr; 192 193 instr(0x5f,5); 194 r=(r&0x80)|(radjust&0x7f); 195 a=r; 196 f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2); 197 endinstr; 198 199 instr(0x60,8); 200 input(h); 201 endinstr; 202 203 instr(0x61,8); 204 tstates+=out(b,c,h); 205 endinstr; 206 207 instr(0x62,11); 208 sbchl(hl); 209 endinstr; 210 211 instr(0x63,16); 212 {unsigned short addr=fetch2(pc); 213 pc+=2; 214 store2b(addr,h,l); 215 } 216 endinstr; 217 218 instr(0x64,4); 219 neg; 220 endinstr; 221 222 instr(0x65,4); 223 ret; 224 endinstr; 225 226 instr(0x66,4); 227 im=0; 228 endinstr; 229 230 instr(0x67,14); 231 {unsigned char t=fetch(hl); 232 unsigned char u=(a<<4)|(t>>4); 233 a=(a&0xf0)|(t&0x0f); 234 store(hl,u); 235 f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a); 236 } 237 endinstr; 238 239 instr(0x68,8); 240 input(l); 241 endinstr; 242 243 instr(0x69,8); 244 tstates+=out(b,c,l); 245 endinstr; 246 247 instr(0x6a,11); 248 adchl(hl); 249 endinstr; 250 251 instr(0x6b,16); 252 {unsigned short addr=fetch2(pc); 253 pc+=2; 254 l=fetch(addr); 255 h=fetch(addr+1); 256 } 257 endinstr; 258 259 instr(0x6c,4); 260 neg; 261 endinstr; 262 263 instr(0x6d,4); 264 ret; 265 endinstr; 266 267 instr(0x6e,4); 268 im=1; 269 endinstr; 270 271 instr(0x6f,5); 272 {unsigned char t=fetch(hl); 273 unsigned char u=(a&0x0f)|(t<<4); 274 a=(a&0xf0)|(t>>4); 275 store(hl,u); 276 f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a); 277 } 278 endinstr; 279 280 instr(0x70,8); 281 {unsigned char x;input(x);} 282 endinstr; 283 284 instr(0x71,8); 285 tstates+=out(b,c,0); 286 endinstr; 287 288 instr(0x72,11); 289 sbchl(sp); 290 endinstr; 291 292 instr(0x73,16); 293 {unsigned short addr=fetch2(pc); 294 pc+=2; 295 store2(addr,sp); 296 } 297 endinstr; 298 299 instr(0x74,4); 300 neg; 301 endinstr; 302 303 instr(0x75,4); 304 ret; 305 endinstr; 306 307 instr(0x76,4); 308 im=2; 309 endinstr; 310 311 instr(0x78,8); 312 input(a); 313 endinstr; 314 315 instr(0x79,8); 316 tstates+=out(b,c,a); 317 endinstr; 318 319 instr(0x7a,11); 320 adchl(sp); 321 endinstr; 322 323 instr(0x7b,16); 324 {unsigned short addr=fetch2(pc); 325 pc+=2; 326 sp=fetch2(addr); 327 } 328 endinstr; 329 330 instr(0x7c,4); 331 neg; 332 endinstr; 333 334 instr(0x7d,4); 335 ret; 336 endinstr; 337 338 instr(0x7e,4); 339 im=3; 340 endinstr; 341 342 instr(0xa0,12); 343 {unsigned char x=fetch(hl); 344 store(de,x); 345 if(!++l)h++; 346 if(!++e)d++; 347 if(!c--)b--; 348 f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2); 349 } 350 endinstr; 351 352 instr(0xa1,12); 353 {unsigned char carry=cy; 354 cpa(fetch(hl)); 355 if(!++l)h++; 356 if(!c--)b--; 357 f=(f&0xfa)|carry|(((b|c)>0)<<2); 358 } 359 endinstr; 360 361 instr(0xa2,12); 362 {unsigned short t=in(b,c); 363 store(hl,t); 364 tstates+=t>>8; 365 if(!++l)h++; 366 b--; 367 f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4); 368 } 369 endinstr; 370 371 instr(0xa3,12); /* I can't determine the correct flags outcome for the 372 block OUT instructions. Spec says that the carry 373 flag is left unchanged and N is set to 1, but that 374 doesn't seem to be the case... */ 375 {unsigned char x=fetch(hl); 376 tstates+=out(b,c,x); 377 if(!++l)h++; 378 b--; 379 f=(f&1)|0x12|(b&0xa8)|((b==0)<<6); 380 } 381 endinstr; 382 383 instr(0xa8,12); 384 {unsigned char x=fetch(hl); 385 store(de,x); 386 if(!l--)h--; 387 if(!e--)d--; 388 if(!c--)b--; 389 f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2); 390 } 391 endinstr; 392 393 instr(0xa9,12); 394 {unsigned char carry=cy; 395 cpa(fetch(hl)); 396 if(!l--)h--; 397 if(!c--)b--; 398 f=(f&0xfa)|carry|(((b|c)>0)<<2); 399 } 400 endinstr; 401 402 instr(0xaa,12); 403 {unsigned short t=in(b,c); 404 store(hl,t); 405 tstates+=t>>8; 406 if(!l--)h--; 407 b--; 408 f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4); 409 } 410 endinstr; 411 412 instr(0xab,12); 413 {unsigned char x=fetch(hl); 414 tstates+=out(b,c,x); 415 if(!l--)h--; 416 b--; 417 f=(f&1)|0x12|(b&0xa8)|((b==0)<<6); 418 } 419 endinstr; 420 421 /* Note: the Z80 implements "*R" as "*" followed by JR -2. No reason 422 to change this... */ 423 424 instr(0xb0,12); 425 {unsigned char x=fetch(hl); 426 store(de,x); 427 if(!++l)h++; 428 if(!++e)d++; 429 if(!c--)b--; 430 f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2); 431 if(b|c)pc-=2,tstates+=5; 432 } 433 endinstr; 434 435 instr(0xb1,12); 436 {unsigned char carry=cy; 437 cpa(fetch(hl)); 438 if(!++l)h++; 439 if(!c--)b--; 440 f=(f&0xfa)|carry|(((b|c)>0)<<2); 441 if((f&0x44)==4)pc-=2,tstates+=5; 442 } 443 endinstr; 444 445 instr(0xb2,12); 446 {unsigned short t=in(b,c); 447 store(hl,t); 448 tstates+=t>>8; 449 if(!++l)h++; 450 b--; 451 f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4); 452 if(b)pc-=2,tstates+=5; 453 } 454 endinstr; 455 456 instr(0xb3,12); 457 {unsigned char x=fetch(hl); 458 tstates+=out(b,c,x); 459 if(!++l)h++; 460 b--; 461 f=(f&1)|0x12|(b&0xa8)|((b==0)<<6); 462 if(b)pc-=2,tstates+=5; 463 } 464 endinstr; 465 466 instr(0xb8,12); 467 {unsigned char x=fetch(hl); 468 store(de,x); 469 if(!l--)h--; 470 if(!e--)d--; 471 if(!c--)b--; 472 f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2); 473 if(b|c)pc-=2,tstates+=5; 474 } 475 endinstr; 476 477 instr(0xb9,12); 478 {unsigned char carry=cy; 479 cpa(fetch(hl)); 480 if(!l--)h--; 481 if(!c--)b--; 482 f=(f&0xfa)|carry|(((b|c)>0)<<2); 483 if((f&0x44)==4)pc-=2,tstates+=5; 484 } 485 endinstr; 486 487 instr(0xba,12); 488 {unsigned short t=in(b,c); 489 store(hl,t); 490 tstates+=t>>8; 491 if(!l--)h--; 492 b--; 493 f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4); 494 if(b)pc-=2,tstates+=5; 495 } 496 endinstr; 497 498 instr(0xbb,12); 499 {unsigned char x=fetch(hl); 500 tstates+=out(b,c,x); 501 if(!l--)h--; 502 b--; 503 f=(f&1)|0x12|(b&0xa8)|((b==0)<<6); 504 if(b)pc-=2,tstates+=5; 505 } 506 endinstr; 507 508 default: tstates+=4; 509 510 }} 511