/*	
 *	clipz80i.h
 *
 *	P/ECE Z80 Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2003 Naoyuki Sawa
 *
 *	* Sat Nov 22 06:00:00 JST 2003 Naoyuki Sawa
 *	- 作成開始。
 */
#ifndef __CLIP_Z80I_H__
#define __CLIP_Z80I_H__

/*
 *	Z80コア実装用のマクロを定義します。
 *	マクロ名が単純すぎて、既存の他のマクロと衝突する恐れがあるので、
 *	Z80コアを実装するソースファイルからのみインクルードしてください。
 */

/****************************************************************************
 *
 ****************************************************************************/

/*
 *	Z80構造体メンバアクセスの簡略表記
 */
/*===== レジスタ =====*/
#define AF		(z80->af)
#define BC		(z80->bc)
#define DE		(z80->de)
#define HL		(z80->hl)
//
#define AF2		(z80->af2)
#define BC2		(z80->bc2)
#define DE2		(z80->de2)
#define HL2		(z80->hl2)
//
#define IX		(z80->ix)
#define IY		(z80->iy)
#define SP		(z80->sp)
#define PC		(z80->pc)
//
#define R		(z80->r)
#define I		(z80->i)
/*===== 内部状態 =====*/
#define IFF1		(z80->iff1)
#define IFF2		(z80->iff2)
#define IM		(z80->im)
#define HALT		(z80->halt)
#define CYCLE		(z80->cycle)
/*{{2005/01/07 INT要求保留対応のために追加*/
#define PENDING		(z80->pending)
#define PENDING_NO	(z80->pending_no)
/*}}2005/01/07 INT要求保留対応のために追加*/
/*===== 外部関数 =====*/
#define READ(a)		    ((z80->read )(z80, (unsigned short)(a)))
#define WRITE(a, n)	do { (z80->write)(z80, (unsigned short)(a), (unsigned char)(n)); } while(0)
#define IN(a)		    ((z80->in   )(z80, (unsigned short)(a)))
#define OUT(a, n)	do { (z80->out  )(z80, (unsigned short)(a), (unsigned char)(n)); } while(0)

/****************************************************************************
 *
 ****************************************************************************/

/*
 *	引数の簡略表記
 */
#define arg12	(arg1 | arg2 << 8)
#define IX_d	(IX + (char)arg1)
#define IY_d	(IY + (char)arg1)

/*
 *	16ビットレジスタの上位/下位8ビットアクセス
 */
#define LO(nn)		(*(((unsigned char*)&(nn)) + 0))
#define HI(nn)		(*(((unsigned char*)&(nn)) + 1))
//
#define A		HI(AF)
#define F		LO(AF)
#define B		HI(BC)
#define C		LO(BC)
#define D		HI(DE)
#define E		LO(DE)
#define H		HI(HL)
#define L		LO(HL)
//
#define A2		HI(AF2)
#define F2		LO(AF2)
#define B2		HI(BC2)
#define C2		LO(BC2)
#define D2		HI(DE2)
#define E2		LO(DE2)
#define H2		HI(HL2)
#define L2		LO(HL2)
//
#define IXL		LO(IX)
#define IXH		HI(IX)
#define IYL		LO(IY)
#define IYH		HI(IY)

/*
 *	16ビットメモリアクセス
 */
#define READ16(a)	(READ(a) | READ((a) + 1) << 8)
#define WRITE16(a, nn)	do { WRITE(a, LO(nn)); WRITE((a) + 1, HI(nn)); } while(0)

/*
 *	PUSH/POP
 */
#define PUSH(nn)	do { SP -= 2; WRITE16(SP, (nn)); } while(0)
#define POP(nn)		do { (nn) = READ16(SP); SP += 2; } while(0)

/*
 *	インストラクションフェッチ/実行
 */
#define FETCH(n)	do {	\
	(n) = READ(PC++);	\
	Z80TRACE("%02x ", (n));	\
} while(0)
#define EXEC()		do {							\
	Z80TRACE((op->name ? "[%s]" : ""), &z80_op_name_table[op->name]);	\
	op->proc(z80, code, arg1, arg2);					\
	CYCLE -= op->cycle;							\
} while(0)

/****************************************************************************
 *
 ****************************************************************************/

#define PARITY(n)	(z80_PARITY[n & 0xff])
#define ADD8(n)		do { z80_ADD8(z80, (n)); } while(0)
#define ADC8(n)		do { z80_ADC8(z80, (n)); } while(0)
#define SUB8(n)		do { z80_SUB8(z80, (n)); } while(0)
#define SBC8(n)		do { z80_SBC8(z80, (n)); } while(0)
#define AND(n)		do { z80_AND(z80, (n)); } while(0)
#define OR(n)		do { z80_OR(z80, (n)); } while(0)
#define XOR(n)		do { z80_XOR(z80, (n)); } while(0)
#define CP(n)		do { z80_CP(z80, (n)); } while(0)
#define INC8(r)		do { (r) = z80_INC8(z80, (r)); } while(0)
#define DEC8(r)		do { (r) = z80_DEC8(z80, (r)); } while(0)
#define ADD16(rr, nn)	do { (rr) = z80_ADD16(z80, (rr), (nn)); } while(0)
#define ADC16(rr, nn)	do { (rr) = z80_ADC16(z80, (rr), (nn)); } while(0)
#define SBC16(rr, nn)	do { (rr) = z80_SBC16(z80, (rr), (nn)); } while(0)
#define RL(r)		do { (r) = z80_RL(z80, (r)); } while(0)
#define RLC(r)		do { (r) = z80_RLC(z80, (r)); } while(0)
#define RR(r)		do { (r) = z80_RR(z80, (r)); } while(0)
#define RRC(r)		do { (r) = z80_RRC(z80, (r)); } while(0)
#define SLA(r)		do { (r) = z80_SLA(z80, (r)); } while(0)
#define SRA(r)		do { (r) = z80_SRA(z80, (r)); } while(0)
#define SRL(r)		do { (r) = z80_SRL(z80, (r)); } while(0)
#define BIT(n, r)	do { z80_BIT(z80, (n), (r)); } while(0)
#define SET(n, r)	do { (r) |=  (1 << (n)); } while(0)
#define RES(n, r)	do { (r) &= ~(1 << (n)); } while(0)
#define EX(rr, ss)	do { unsigned short tmp = rr; rr = ss; ss = tmp; } while(0)

extern const unsigned char z80_PARITY[256];
void z80_ADD8(Z80* z80, unsigned char n);
void z80_ADC8(Z80* z80, unsigned char n);
void z80_SUB8(Z80* z80, unsigned char n);
void z80_SBC8(Z80* z80, unsigned char n);
void z80_AND(Z80* z80, unsigned char n);
void z80_OR(Z80* z80, unsigned char n);
void z80_XOR(Z80* z80, unsigned char n);
void z80_CP(Z80* z80, unsigned char n);
unsigned char z80_INC8(Z80* z80, unsigned char r);
unsigned char z80_DEC8(Z80* z80, unsigned char r);
unsigned short z80_ADD16(Z80* z80, unsigned short rr, unsigned short nn);
unsigned short z80_ADC16(Z80* z80, unsigned short rr, unsigned short nn);
unsigned short z80_SBC16(Z80* z80, unsigned short rr, unsigned short nn);
unsigned char z80_RL(Z80* z80, unsigned char r);
unsigned char z80_RLC(Z80* z80, unsigned char r);
unsigned char z80_RR(Z80* z80, unsigned char r);
unsigned char z80_RRC(Z80* z80, unsigned char r);
unsigned char z80_SLA(Z80* z80, unsigned char r);
unsigned char z80_SRA(Z80* z80, unsigned char r);
unsigned char z80_SRL(Z80* z80, unsigned char r);
void z80_BIT(Z80* z80, unsigned char n, unsigned char r);

#endif /*__CLIP_Z80I_H__*/
