/*	
 *	clipdmgi.h
 *
 *	P/ECE DMG-CPU Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Thu Jan 15 20:09:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_DMGI_H__
#define __CLIP_DMGI_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

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

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

/*
 *	DMG構造体メンバアクセスの簡略表記
 */
/*===== レジスタ =====*/
#define A		HI(dmg->af)
#define F		LO(dmg->af)
#define B		HI(dmg->bc)
#define C		LO(dmg->bc)
#define D		HI(dmg->de)
#define E		LO(dmg->de)
#define H		HI(dmg->hl)
#define L		LO(dmg->hl)
#define AF		(dmg->af)
#define BC		(dmg->bc)
#define DE		(dmg->de)
#define HL		(dmg->hl)
#define SP		(dmg->sp)
#define PC		(dmg->pc)
/*===== 内部状態 =====*/
#define IME		(dmg->ime)
#define HALT		(dmg->halt)
#define CYCLE		(dmg->cycle)
/*===== 外部関数 =====*/
#define READ(a)		    ((dmg->read )(dmg, (unsigned short)(a)))
#define WRITE(a, n)	do { (dmg->write)(dmg, (unsigned short)(a), (unsigned char)(n)); } while(0)

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

/*
 *	16ビットレジスタの上位/下位8ビットアクセス
 */
#define LO(rr)		(*(((unsigned char*)&(rr)) + 0))
#define HI(rr)		(*(((unsigned char*)&(rr)) + 1))

/*
 *	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++);	\
	DMGTRACE("%02x ", (n));	\
} while(0)
#define EXEC()		do {							\
	DMGTRACE((op->name ? "[%s]" : ""), &dmg_op_name_table[op->name]);	\
	op->proc(dmg, code, arg);						\
	CYCLE -= op->cycle;							\
} while(0)

/****************************************************************************
 *	8-Bit ALU
 ****************************************************************************/

#define ADD(n)		do { dmg_ADD(dmg, (n)); } while(0)
#define ADC(n)		do { dmg_ADC(dmg, (n)); } while(0)
#define SUB(n)		do { dmg_SUB(dmg, (n)); } while(0)
#define SBC(n)		do { dmg_SBC(dmg, (n)); } while(0)
#define AND(n)		do { dmg_AND(dmg, (n)); } while(0)
#define XOR(n)		do { dmg_XOR(dmg, (n)); } while(0)
#define OR(n)		do { dmg_OR(dmg, (n)); } while(0)
#define CP(n)		do { dmg_CP(dmg, (n)); } while(0)
#define INC(n)		do { (n) = dmg_INC(dmg, (n)); } while(0)
#define DEC(n)		do { (n) = dmg_DEC(dmg, (n)); } while(0)

void dmg_ADD(DMG* dmg, unsigned char n);
void dmg_ADC(DMG* dmg, unsigned char n);
void dmg_SUB(DMG* dmg, unsigned char n);
void dmg_SBC(DMG* dmg, unsigned char n);
void dmg_AND(DMG* dmg, unsigned char n);
void dmg_XOR(DMG* dmg, unsigned char n);
void dmg_OR(DMG* dmg, unsigned char n);
void dmg_CP(DMG* dmg, unsigned char n);
unsigned char dmg_INC(DMG* dmg, unsigned char n);
unsigned char dmg_DEC(DMG* dmg, unsigned char n);

/****************************************************************************
 *	16-Bit Arithmetic
 ****************************************************************************/

#define ADDW(nn)	do { dmg_ADDW(dmg, (nn)); } while(0)

void dmg_ADDW(DMG* dmg, unsigned short nn);

/****************************************************************************
 *	Miscellaneous
 ****************************************************************************/

#define SWAP(n)		do { (n) = dmg_SWAP(dmg, (n)); } while(0)

unsigned char dmg_SWAP(DMG* dmg, unsigned char n);

/****************************************************************************
 *	Rotates & Shifts
 ****************************************************************************/

#define RLC(n)		do { (n) = dmg_RLC(dmg, (n)); } while(0)
#define RRC(n)		do { (n) = dmg_RRC(dmg, (n)); } while(0)
#define RL(n)		do { (n) = dmg_RL(dmg, (n)); } while(0)
#define RR(n)		do { (n) = dmg_RR(dmg, (n)); } while(0)
#define SLA(n)		do { (n) = dmg_SLA(dmg, (n)); } while(0)
#define SRA(n)		do { (n) = dmg_SRA(dmg, (n)); } while(0)
#define SRL(n)		do { (n) = dmg_SRL(dmg, (n)); } while(0)

unsigned char dmg_RLC(DMG* dmg, unsigned char n);
unsigned char dmg_RRC(DMG* dmg, unsigned char n);
unsigned char dmg_RL(DMG* dmg, unsigned char n);
unsigned char dmg_RR(DMG* dmg, unsigned char n);
unsigned char dmg_SLA(DMG* dmg, unsigned char n);
unsigned char dmg_SRA(DMG* dmg, unsigned char n);
unsigned char dmg_SRL(DMG* dmg, unsigned char n);

/****************************************************************************
 *	Bit Opcodes
 ****************************************************************************/

#define BIT(b, n)	do { dmg_BIT(dmg, (b), (n)); } while(0)
#define SET(b, n)	do { (n) |=  (1 << (b)); } while(0)
#define RES(b, n)	do { (n) &= ~(1 << (b)); } while(0)

void dmg_BIT(DMG* dmg, unsigned char b, unsigned char n);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_DMGI_H__*/
