/* z80_macros.jscpp: Some commonly used z80 things as macros Copyright (c) 1999-2008 Philip Kendall, Matthew Westcott $Id$ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Contact details: Matthew Westcott, 14 Daisy Hill Drive, Adlington, Chorley, Lancs PR6 9NE UNITED KINGDOM */ #ifndef FUSE_Z80_MACROS_H #define FUSE_Z80_MACROS_H /* Macros used for accessing the registers */ #define A z80.a #define F z80.f #define AF !!z80.af.w #define AFR (z80.f | (z80.a << 8)) #define B z80.b #define C z80.c #define BC !!z80.bc.w #define BCR (z80.c | (z80.b << 8)) #define D z80.d #define E z80.e #define DE !!z80.de.w #define DER (z80.e | (z80.d << 8)) #define H z80.h #define L z80.l #define HL !!z80.hl.w #define HLR (z80.l | (z80.h << 8)) #define A_ z80.a_ #define F_ z80.f_ #define AF_ !!z80.af_.w #define AF_R (z80.f_ | (z80.a_ << 8)) #define B_ z80.b_ #define C_ z80.c_ #define BC_ !!z80.bc_.w #define BC_R (z80.c_ | (z80.b_ << 8)) #define D_ z80.d_ #define E_ z80.e_ #define DE_ !!z80.de_.w #define DE_R (z80.e_ | (z80.d_ << 8)) #define H_ z80.h_ #define L_ z80.l_ #define HL_ !!z80.hl_.w #define HL_R (z80.l_ | (z80.h_ << 8)) #define IXH z80.ixh #define IXL z80.ixl #define IX (z80.ixl | (z80.ixh << 8)) #define IYH z80.iyh #define IYL z80.iyl #define IY (z80.iyl | (z80.iyh << 8)) #define SPH !!z80.sp.b.h #define SPHR (z80.sp >> 8) #define SPL !!z80.sp.b.l #define SPLR (z80.sp & 0xff) #define SP z80.sp #define SPR z80.sp #define PCH !!z80.pc.b.h #define PCHR (z80.pc >> 8) #define PCL !!z80.pc.b.l #define PCLR (z80.pc & 0xff) #define PC z80.pc #define PCR z80.pc #define I z80.i #define R z80.r #define R7 z80.r7 #define IFF1 z80.iff1 #define IFF2 z80.iff2 #define IM z80.im /* The flags */ #define FLAG_C 0x01 #define FLAG_N 0x02 #define FLAG_P 0x04 #define FLAG_V FLAG_P #define FLAG_3 0x08 #define FLAG_H 0x10 #define FLAG_5 0x20 #define FLAG_Z 0x40 #define FLAG_S 0x80 /* Get the appropriate contended memory delay. Use this macro later to avoid a function call if memory contention is disabled */ /* #define contend(address,time) tstates += contend_memory( (address) ) + (time); */ /* #define contend_io(port,time) tstates += contend_port( (port) ) + (time); */ #define contend(address,time) tstates += (time); #define contend_io(port,time) tstates += (time); /* Some commonly used instructions */ #define AND(value)\ {\ A &= (value);\ F = FLAG_H | sz53p_table[A];\ } #define ADC(value)\ {\ var adctemp = A + (value) + ( F & FLAG_C ); \ var lookup = ( ( A & 0x88 ) >> 3 ) | \ ( ( (value) & 0x88 ) >> 2 ) | \ ( ( adctemp & 0x88 ) >> 1 ); \ A=adctemp & 0xff;\ F = ( adctemp & 0x100 ? FLAG_C : 0 ) |\ halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\ sz53_table[A];\ } #define ADC16(value)\ {\ var add16temp= HLR + (value) + ( F & FLAG_C ); \ var lookup = ( ( HLR & 0x8800 ) >> 11 ) | \ ( ( (value) & 0x8800 ) >> 10 ) | \ ( ( add16temp & 0x8800 ) >> 9 ); \ H = (add16temp >> 8) & 0xff; L = add16temp & 0xff;\ F = ( add16temp & 0x10000 ? FLAG_C : 0 )|\ overflow_add_table[lookup >> 4] |\ ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\ halfcarry_add_table[lookup&0x07]|\ ( HLR ? 0 : FLAG_Z );\ } #define ADD(value)\ {\ var addtemp = A + (value); \ var lookup = ( ( A & 0x88 ) >> 3 ) | \ ( ( (value) & 0x88 ) >> 2 ) | \ ( ( addtemp & 0x88 ) >> 1 ); \ A=addtemp & 0xff;\ F = ( addtemp & 0x100 ? FLAG_C : 0 ) |\ halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\ sz53_table[A];\ } #define ADD16(value1,value2, value1h, value1l)\ {\ var add16temp = (value1) + (value2); \ var lookup = ( ( (value1) & 0x0800 ) >> 11 ) | \ ( ( (value2) & 0x0800 ) >> 10 ) | \ ( ( add16temp & 0x0800 ) >> 9 ); \ tstates += 7;\ (value1h) = (add16temp >> 8) & 0xff; (value1l) = add16temp & 0xff;\ F = ( F & ( FLAG_V | FLAG_Z | FLAG_S ) ) |\ ( add16temp & 0x10000 ? FLAG_C : 0 )|\ ( ( add16temp >> 8 ) & ( FLAG_3 | FLAG_5 ) ) |\ halfcarry_add_table[lookup];\ } #define BIT(bit,value)\ {\ F = ( F & FLAG_C ) | FLAG_H | ( value & ( FLAG_3 | FLAG_5 ) ); \ if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \ if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \ } #define BIT_I( bit, value, address ) \ {\ F = ( F & FLAG_C ) | FLAG_H | ( ( address >> 8 ) & ( FLAG_3 | FLAG_5 ) ); \ if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \ if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \ } #define CALL()\ {\ var calltempl, calltemph; \ calltempl=readbyte(PC++);\ PC &= 0xffff;\ contend( PC, 1 );\ calltemph=readbyte(PC++);\ PC &= 0xffff;\ PUSH16W(PC);\ var pcl=calltempl; var pch=calltemph;\ PC = pcl | (pch << 8);\ } #define CP(value)\ {\ var cptemp = A - value; \ var lookup = ( ( A & 0x88 ) >> 3 ) | \ ( ( (value) & 0x88 ) >> 2 ) | \ ( ( cptemp & 0x88 ) >> 1 ); \ F = ( cptemp & 0x100 ? FLAG_C : ( cptemp ? 0 : FLAG_Z ) ) | FLAG_N |\ halfcarry_sub_table[lookup & 0x07] |\ overflow_sub_table[lookup >> 4] |\ ( value & ( FLAG_3 | FLAG_5 ) ) |\ ( cptemp & FLAG_S );\ } /* Macro for the {DD,FD} CB dd xx rotate/shift instructions */ #define DDFDCB_ROTATESHIFT(time, target, instruction)\ tstates+=(time);\ {\ (target) = readbyte( tempaddr );\ instruction( (target) );\ writebyte( tempaddr, (target) );\ }\ break #define DEC(value)\ {\ F = ( F & FLAG_C ) | ( (value)&0x0f ? 0 : FLAG_H ) | FLAG_N;\ (value) = ((value) - 1) & 0xff;\ F |= ( (value)==0x7f ? FLAG_V : 0 ) | sz53_table[value];\ } #define IN(reg,port)\ {\ contend_io( port, 3 );\ (reg)=readport((port));\ F = ( F & FLAG_C) | sz53p_table[(reg)];\ } #define INC(value)\ {\ (value) = ((value) + 1) & 0xff;\ F = ( F & FLAG_C ) | ( (value)==0x80 ? FLAG_V : 0 ) |\ ( (value)&0x0f ? 0 : FLAG_H ) | sz53_table[(value)];\ } #define LD16_NNRR(regl,regh)\ {\ var ldtemp; \ contend( PC, 3 );\ ldtemp=readbyte(PC++);\ PC &= 0xffff;\ contend( PC, 3 );\ ldtemp|=readbyte(PC++) << 8;\ PC &= 0xffff;\ contend( ldtemp, 3 );\ writebyte(ldtemp++,(regl));\ ldtemp &= 0xffff;\ contend( ldtemp, 3 );\ writebyte(ldtemp,(regh));\ break;\ } #define LD16_RRNN(regl,regh)\ {\ var ldtemp; \ contend( PC, 3 );\ ldtemp=readbyte(PC++);\ PC &= 0xffff;\ contend( PC, 3 );\ ldtemp|=readbyte(PC++) << 8;\ PC &= 0xffff;\ contend( ldtemp, 3 );\ (regl)=readbyte(ldtemp++);\ ldtemp &= 0xffff;\ contend( ldtemp, 3 );\ (regh)=readbyte(ldtemp);\ break;\ } #define LD16_RRNNW(reg)\ {\ var ldtemp; \ contend( PC, 3 );\ ldtemp=readbyte(PC++);\ PC &= 0xffff;\ contend( PC, 3 );\ ldtemp|=readbyte(PC++) << 8;\ PC &= 0xffff;\ contend( ldtemp, 3 );\ var regl = readbyte(ldtemp++);\ ldtemp &= 0xffff;\ contend( ldtemp, 3 );\ var regh =readbyte(ldtemp);\ reg = regl | (regh << 8);\ break;\ } #define JP()\ {\ var jptemp=PC; \ var pcl =readbyte(jptemp++);\ jptemp &= 0xffff;\ var pch =readbyte(jptemp);\ PC = pcl | (pch << 8);\ } #define JR()\ {\ contend( PC, 1 ); contend( PC, 1 ); contend( PC, 1 ); contend( PC, 1 );\ contend( PC, 1 );\ PC += sign_extend(readbyte( PC )); \ PC &= 0xffff; \ } #define OR(value)\ {\ A |= (value);\ F = sz53p_table[A];\ } #define OUT(port,reg)\ {\ contend_io( port, 3 );\ writeport(port,reg);\ } #define POP16(regl,regh)\ {\ contend( SP, 3 );\ (regl)=readbyte(SP++);\ SP &= 0xffff;\ contend( SP, 3 );\ (regh)=readbyte(SP++);\ SP &= 0xffff;\ } #define POP16W(reg)\ {\ contend( SP, 3 );\ var lowbyte =readbyte(SP++);\ SP &= 0xffff;\ contend( SP, 3 );\ var highbyte=readbyte(SP++);\ SP &= 0xffff;\ (reg) = lowbyte | (highbyte << 8);\ } #define PUSH16(regl,regh)\ {\ SP--; SP &= 0xffff; contend( SP, 3 );\ writebyte(SP,(regh));\ SP--; SP &= 0xffff; contend( SP, 3 );\ writebyte(SP,(regl));\ } #define PUSH16W(reg)\ {\ SP--; SP &= 0xffff; contend( SP, 3 );\ writebyte(SP,(reg) >> 8);\ SP--; SP &= 0xffff; contend( SP, 3 );\ writebyte(SP,(reg) & 0xff);\ } #define RET()\ {\ POP16W(PC);\ } #define RL(value)\ {\ var rltemp = (value); \ (value) = ( ((value) & 0x7f)<<1 ) | ( F & FLAG_C );\ F = ( rltemp >> 7 ) | sz53p_table[(value)];\ } #define RLC(value)\ {\ (value) = ( ((value) & 0x7f)<<1 ) | ( (value)>>7 );\ F = ( (value) & FLAG_C ) | sz53p_table[(value)];\ } #define RR(value)\ {\ var rrtemp = (value); \ (value) = ( (value)>>1 ) | ( (F & 0x01) << 7 );\ F = ( rrtemp & FLAG_C ) | sz53p_table[(value)];\ } #define RRC(value)\ {\ F = (value) & FLAG_C;\ (value) = ( (value)>>1 ) | ( ((value) & 0x01)<<7 );\ F |= sz53p_table[(value)];\ } #define RST(value)\ {\ PUSH16W(PC);\ PC=(value);\ } #define SBC(value)\ {\ var sbctemp = A - (value) - ( F & FLAG_C ); \ var lookup = ( ( A & 0x88 ) >> 3 ) | \ ( ( (value) & 0x88 ) >> 2 ) | \ ( ( sbctemp & 0x88 ) >> 1 ); \ A=sbctemp & 0xff;\ F = ( sbctemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\ halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\ sz53_table[A];\ } #define SBC16(value)\ {\ var sub16temp = HLR - (value) - (F & FLAG_C); \ var lookup = ( ( HLR & 0x8800 ) >> 11 ) | \ ( ( (value) & 0x8800 ) >> 10 ) | \ ( ( sub16temp & 0x8800 ) >> 9 ); \ H = (sub16temp >> 8) & 0xff; L = sub16temp & 0xff;\ F = ( sub16temp & 0x10000 ? FLAG_C : 0 ) |\ FLAG_N | overflow_sub_table[lookup >> 4] |\ ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\ halfcarry_sub_table[lookup&0x07] |\ ( HLR ? 0 : FLAG_Z) ;\ } #define SLA(value)\ {\ F = (value) >> 7;\ (value) <<= 1;\ (value) &= 0xff;\ F |= sz53p_table[(value)];\ } #define SLL(value)\ {\ F = (value) >> 7;\ (value) = ( (value) << 1 ) | 0x01;\ (value) &= 0xff;\ F |= sz53p_table[(value)];\ } #define SRA(value)\ {\ F = (value) & FLAG_C;\ (value) = ( (value) & 0x80 ) | ( (value) >> 1 );\ F |= sz53p_table[(value)];\ } #define SRL(value)\ {\ F = (value) & FLAG_C;\ (value) >>= 1;\ F |= sz53p_table[(value)];\ } #define SUB(value)\ {\ var subtemp = A - (value); \ var lookup = ( ( A & 0x88 ) >> 3 ) | \ ( ( (value) & 0x88 ) >> 2 ) | \ ( (subtemp & 0x88 ) >> 1 ); \ A=subtemp & 0xff;\ F = ( subtemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\ halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\ sz53_table[A];\ } #define XOR(value)\ {\ A ^= (value);\ F = sz53p_table[A];\ } /* speed tweaks */ /* #define readbyte readbyte_internal */ #define readbyte(b) memory[b] #define readbyte_internal(b) memory[b] #define writebyte writebyte_internal #endif /* #ifndef FUSE_Z80_MACROS_H */