1 /* z80_macros.h: Some commonly used z80 things as macros 2 Copyright (c) 1999-2011 Philip Kendall 3 4 $Id: z80_macros.h 4624 2012-01-09 20:59:35Z pak21 $ 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along 17 with this program; if not, write to the Free Software Foundation, Inc., 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 20 Author contact information: 21 22 E-mail: philip-fuse@shadowmagic.org.uk 23 24 */ 25 26 #ifndef FUSE_Z80_MACROS_H 27 #define FUSE_Z80_MACROS_H 28 29 /* Macros used for accessing the registers */ 30 #define A z80.af.b.h 31 #define F z80.af.b.l 32 #define AF z80.af.w 33 34 #define B z80.bc.b.h 35 #define C z80.bc.b.l 36 #define BC z80.bc.w 37 38 #define D z80.de.b.h 39 #define E z80.de.b.l 40 #define DE z80.de.w 41 42 #define H z80.hl.b.h 43 #define L z80.hl.b.l 44 #define HL z80.hl.w 45 46 #define A_ z80.af_.b.h 47 #define F_ z80.af_.b.l 48 #define AF_ z80.af_.w 49 50 #define B_ z80.bc_.b.h 51 #define C_ z80.bc_.b.l 52 #define BC_ z80.bc_.w 53 54 #define D_ z80.de_.b.h 55 #define E_ z80.de_.b.l 56 #define DE_ z80.de_.w 57 58 #define H_ z80.hl_.b.h 59 #define L_ z80.hl_.b.l 60 #define HL_ z80.hl_.w 61 62 #define IXH z80.ix.b.h 63 #define IXL z80.ix.b.l 64 #define IX z80.ix.w 65 66 #define IYH z80.iy.b.h 67 #define IYL z80.iy.b.l 68 #define IY z80.iy.w 69 70 #define SPH z80.sp.b.h 71 #define SPL z80.sp.b.l 72 #define SP z80.sp.w 73 74 #define PCH z80.pc.b.h 75 #define PCL z80.pc.b.l 76 #define PC z80.pc.w 77 78 #define I z80.i 79 #define R z80.r 80 #define R7 z80.r7 81 82 #define IFF1 z80.iff1 83 #define IFF2 z80.iff2 84 #define IM z80.im 85 86 #define IR ( ( z80.i ) << 8 | ( z80.r7 & 0x80 ) | ( z80.r & 0x7f ) ) 87 88 /* The flags */ 89 90 #define FLAG_C 0x01 91 #define FLAG_N 0x02 92 #define FLAG_P 0x04 93 #define FLAG_V FLAG_P 94 #define FLAG_3 0x08 95 #define FLAG_H 0x10 96 #define FLAG_5 0x20 97 #define FLAG_Z 0x40 98 #define FLAG_S 0x80 99 100 /* Get the appropriate contended memory delay. Use a macro for performance 101 reasons in the main core, but a function for flexibility when building 102 the core tester */ 103 104 #ifndef CORETEST 105 106 #define contend_read(address,time) \ 107 if( memory_map_read[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \ 108 tstates += ula_contention[ tstates ]; \ 109 tstates += (time); 110 111 #define contend_read_no_mreq(address,time) \ 112 if( memory_map_read[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \ 113 tstates += ula_contention_no_mreq[ tstates ]; \ 114 tstates += (time); 115 116 #define contend_write_no_mreq(address,time) \ 117 if( memory_map_write[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \ 118 tstates += ula_contention_no_mreq[ tstates ]; \ 119 tstates += (time); 120 121 #else /* #ifndef CORETEST */ 122 123 void contend_read( libspectrum_word address, libspectrum_dword time ); 124 void contend_read_no_mreq( libspectrum_word address, libspectrum_dword time ); 125 void contend_write_no_mreq( libspectrum_word address, libspectrum_dword time ); 126 127 #endif /* #ifndef CORETEST */ 128 129 /* Some commonly used instructions */ 130 #define AND(value)\ 131 {\ 132 A &= (value);\ 133 F = FLAG_H | sz53p_table[A];\ 134 } 135 136 #define ADC(value)\ 137 {\ 138 libspectrum_word adctemp = A + (value) + ( F & FLAG_C ); \ 139 libspectrum_byte lookup = ( ( A & 0x88 ) >> 3 ) | \ 140 ( ( (value) & 0x88 ) >> 2 ) | \ 141 ( ( adctemp & 0x88 ) >> 1 ); \ 142 A=adctemp;\ 143 F = ( adctemp & 0x100 ? FLAG_C : 0 ) |\ 144 halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\ 145 sz53_table[A];\ 146 } 147 148 #define ADC16(value)\ 149 {\ 150 libspectrum_dword add16temp= HL + (value) + ( F & FLAG_C ); \ 151 libspectrum_byte lookup = ( ( HL & 0x8800 ) >> 11 ) | \ 152 ( ( (value) & 0x8800 ) >> 10 ) | \ 153 ( ( add16temp & 0x8800 ) >> 9 ); \ 154 HL = add16temp;\ 155 F = ( add16temp & 0x10000 ? FLAG_C : 0 )|\ 156 overflow_add_table[lookup >> 4] |\ 157 ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\ 158 halfcarry_add_table[lookup&0x07]|\ 159 ( HL ? 0 : FLAG_Z );\ 160 } 161 162 #define ADD(value)\ 163 {\ 164 libspectrum_word addtemp = A + (value); \ 165 libspectrum_byte lookup = ( ( A & 0x88 ) >> 3 ) | \ 166 ( ( (value) & 0x88 ) >> 2 ) | \ 167 ( ( addtemp & 0x88 ) >> 1 ); \ 168 A=addtemp;\ 169 F = ( addtemp & 0x100 ? FLAG_C : 0 ) |\ 170 halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\ 171 sz53_table[A];\ 172 } 173 174 #define ADD16(value1,value2)\ 175 {\ 176 libspectrum_dword add16temp = (value1) + (value2); \ 177 libspectrum_byte lookup = ( ( (value1) & 0x0800 ) >> 11 ) | \ 178 ( ( (value2) & 0x0800 ) >> 10 ) | \ 179 ( ( add16temp & 0x0800 ) >> 9 ); \ 180 (value1) = add16temp;\ 181 F = ( F & ( FLAG_V | FLAG_Z | FLAG_S ) ) |\ 182 ( add16temp & 0x10000 ? FLAG_C : 0 )|\ 183 ( ( add16temp >> 8 ) & ( FLAG_3 | FLAG_5 ) ) |\ 184 halfcarry_add_table[lookup];\ 185 } 186 187 /* This may look fairly inefficient, but the (gcc) optimiser does the 188 right thing assuming it's given a constant for 'bit' */ 189 #define BIT( bit, value ) \ 190 { \ 191 F = ( F & FLAG_C ) | FLAG_H | ( value & ( FLAG_3 | FLAG_5 ) ); \ 192 if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \ 193 if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \ 194 } 195 196 #define BIT_I( bit, value, address ) \ 197 { \ 198 F = ( F & FLAG_C ) | FLAG_H | ( ( address >> 8 ) & ( FLAG_3 | FLAG_5 ) ); \ 199 if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \ 200 if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \ 201 } 202 203 #define CALL()\ 204 {\ 205 libspectrum_byte calltempl, calltemph; \ 206 calltempl=readbyte(PC++);\ 207 calltemph=readbyte( PC ); \ 208 contend_read_no_mreq( PC, 1 ); PC++;\ 209 PUSH16(PCL,PCH);\ 210 PCL=calltempl; PCH=calltemph;\ 211 } 212 213 #define CP(value)\ 214 {\ 215 libspectrum_word cptemp = A - value; \ 216 libspectrum_byte lookup = ( ( A & 0x88 ) >> 3 ) | \ 217 ( ( (value) & 0x88 ) >> 2 ) | \ 218 ( ( cptemp & 0x88 ) >> 1 ); \ 219 F = ( cptemp & 0x100 ? FLAG_C : ( cptemp ? 0 : FLAG_Z ) ) | FLAG_N |\ 220 halfcarry_sub_table[lookup & 0x07] |\ 221 overflow_sub_table[lookup >> 4] |\ 222 ( value & ( FLAG_3 | FLAG_5 ) ) |\ 223 ( cptemp & FLAG_S );\ 224 } 225 226 /* Macro for the {DD,FD} CB dd xx rotate/shift instructions */ 227 #define DDFDCB_ROTATESHIFT(time, target, instruction)\ 228 tstates+=(time);\ 229 {\ 230 (target) = readbyte( tempaddr );\ 231 instruction( (target) );\ 232 writebyte( tempaddr, (target) );\ 233 }\ 234 break 235 236 #define DEC(value)\ 237 {\ 238 F = ( F & FLAG_C ) | ( (value)&0x0f ? 0 : FLAG_H ) | FLAG_N;\ 239 (value)--;\ 240 F |= ( (value)==0x7f ? FLAG_V : 0 ) | sz53_table[value];\ 241 } 242 243 #define Z80_IN( reg, port )\ 244 {\ 245 (reg)=readport((port));\ 246 F = ( F & FLAG_C) | sz53p_table[(reg)];\ 247 } 248 249 #define INC(value)\ 250 {\ 251 (value)++;\ 252 F = ( F & FLAG_C ) | ( (value)==0x80 ? FLAG_V : 0 ) |\ 253 ( (value)&0x0f ? 0 : FLAG_H ) | sz53_table[(value)];\ 254 } 255 256 #define LD16_NNRR(regl,regh)\ 257 {\ 258 libspectrum_word ldtemp; \ 259 ldtemp=readbyte(PC++);\ 260 ldtemp|=readbyte(PC++) << 8;\ 261 writebyte(ldtemp++,(regl));\ 262 writebyte(ldtemp,(regh));\ 263 break;\ 264 } 265 266 #define LD16_RRNN(regl,regh)\ 267 {\ 268 libspectrum_word ldtemp; \ 269 ldtemp=readbyte(PC++);\ 270 ldtemp|=readbyte(PC++) << 8;\ 271 (regl)=readbyte(ldtemp++);\ 272 (regh)=readbyte(ldtemp);\ 273 break;\ 274 } 275 276 #define JP()\ 277 {\ 278 libspectrum_word jptemp=PC; \ 279 PCL=readbyte(jptemp++);\ 280 PCH=readbyte(jptemp);\ 281 } 282 283 #define JR()\ 284 {\ 285 libspectrum_signed_byte jrtemp = readbyte( PC ); \ 286 contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); \ 287 contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); \ 288 contend_read_no_mreq( PC, 1 ); \ 289 PC += jrtemp; \ 290 } 291 292 #define OR(value)\ 293 {\ 294 A |= (value);\ 295 F = sz53p_table[A];\ 296 } 297 298 #define POP16(regl,regh)\ 299 {\ 300 (regl)=readbyte(SP++);\ 301 (regh)=readbyte(SP++);\ 302 } 303 304 #define PUSH16(regl,regh)\ 305 {\ 306 writebyte( --SP, (regh) );\ 307 writebyte( --SP, (regl) );\ 308 } 309 310 #define RET()\ 311 {\ 312 POP16(PCL,PCH);\ 313 } 314 315 #define RL(value)\ 316 {\ 317 libspectrum_byte rltemp = (value); \ 318 (value) = ( (value)<<1 ) | ( F & FLAG_C );\ 319 F = ( rltemp >> 7 ) | sz53p_table[(value)];\ 320 } 321 322 #define RLC(value)\ 323 {\ 324 (value) = ( (value)<<1 ) | ( (value)>>7 );\ 325 F = ( (value) & FLAG_C ) | sz53p_table[(value)];\ 326 } 327 328 #define RR(value)\ 329 {\ 330 libspectrum_byte rrtemp = (value); \ 331 (value) = ( (value)>>1 ) | ( F << 7 );\ 332 F = ( rrtemp & FLAG_C ) | sz53p_table[(value)];\ 333 } 334 335 #define RRC(value)\ 336 {\ 337 F = (value) & FLAG_C;\ 338 (value) = ( (value)>>1 ) | ( (value)<<7 );\ 339 F |= sz53p_table[(value)];\ 340 } 341 342 #define RST(value)\ 343 {\ 344 PUSH16(PCL,PCH);\ 345 PC=(value);\ 346 } 347 348 #define SBC(value)\ 349 {\ 350 libspectrum_word sbctemp = A - (value) - ( F & FLAG_C ); \ 351 libspectrum_byte lookup = ( ( A & 0x88 ) >> 3 ) | \ 352 ( ( (value) & 0x88 ) >> 2 ) | \ 353 ( ( sbctemp & 0x88 ) >> 1 ); \ 354 A=sbctemp;\ 355 F = ( sbctemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\ 356 halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\ 357 sz53_table[A];\ 358 } 359 360 #define SBC16(value)\ 361 {\ 362 libspectrum_dword sub16temp = HL - (value) - (F & FLAG_C); \ 363 libspectrum_byte lookup = ( ( HL & 0x8800 ) >> 11 ) | \ 364 ( ( (value) & 0x8800 ) >> 10 ) | \ 365 ( ( sub16temp & 0x8800 ) >> 9 ); \ 366 HL = sub16temp;\ 367 F = ( sub16temp & 0x10000 ? FLAG_C : 0 ) |\ 368 FLAG_N | overflow_sub_table[lookup >> 4] |\ 369 ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\ 370 halfcarry_sub_table[lookup&0x07] |\ 371 ( HL ? 0 : FLAG_Z) ;\ 372 } 373 374 #define SLA(value)\ 375 {\ 376 F = (value) >> 7;\ 377 (value) <<= 1;\ 378 F |= sz53p_table[(value)];\ 379 } 380 381 #define SLL(value)\ 382 {\ 383 F = (value) >> 7;\ 384 (value) = ( (value) << 1 ) | 0x01;\ 385 F |= sz53p_table[(value)];\ 386 } 387 388 #define SRA(value)\ 389 {\ 390 F = (value) & FLAG_C;\ 391 (value) = ( (value) & 0x80 ) | ( (value) >> 1 );\ 392 F |= sz53p_table[(value)];\ 393 } 394 395 #define SRL(value)\ 396 {\ 397 F = (value) & FLAG_C;\ 398 (value) >>= 1;\ 399 F |= sz53p_table[(value)];\ 400 } 401 402 #define SUB(value)\ 403 {\ 404 libspectrum_word subtemp = A - (value); \ 405 libspectrum_byte lookup = ( ( A & 0x88 ) >> 3 ) | \ 406 ( ( (value) & 0x88 ) >> 2 ) | \ 407 ( (subtemp & 0x88 ) >> 1 ); \ 408 A=subtemp;\ 409 F = ( subtemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\ 410 halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\ 411 sz53_table[A];\ 412 } 413 414 #define XOR(value)\ 415 {\ 416 A ^= (value);\ 417 F = sz53p_table[A];\ 418 } 419 420 #endif /* #ifndef FUSE_Z80_MACROS_H */ 421