/* 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 */