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

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

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

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

/*
 *	M6809構造体メンバアクセスの簡略表記
 */
/*===== レジスタ =====*/
#define CC		(m6809->cc)
#define DP		(m6809->dp)
#define D		(m6809->d)
#define X		(m6809->x)
#define Y		(m6809->y)
#define U		(m6809->u)
#define S		(m6809->s)
#define PC		(m6809->pc)
/*===== 内部状態 =====*/
#define PENDING		(m6809->pending)
#define WAIT		(m6809->wait)
#define CYCLE		(m6809->cycle)
/*===== 外部関数 =====*/
#define READ(a)		    ((m6809->read )(m6809, (unsigned short)(a)))
#define WRITE(a, n)	do { (m6809->write)(m6809, (unsigned short)(a), (unsigned char)(n)); } while(0)

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

/*
 *	16ビットレジスタの上位/下位8ビットアクセス
 *
 *	* エミュレーションホスト上(S1C33,Pentium,etc)の処理なので、LittleEndianです。
 */
#define LO(rr)		(*(((unsigned char*)&(rr)) + 0))				/* LittleEndian */
#define HI(rr)		(*(((unsigned char*)&(rr)) + 1))				/* LittleEndian */
#define A		HI(D)
#define B		LO(D)

/*
 *	16ビットメモリアクセス
 *
 *	* エミュレーションターゲット上(M6809)の処理なので、BigEndianです。
 */
#define READW(a)	(READ(a) << 8 | READ((a) + 1))					/* BigEndian */
#define WRITEW(a, nn)	do { WRITE(a, HI(nn)); WRITE((a) + 1, LO(nn)); } while(0)	/* BigEndian */

/*
 *	PUSH/PULL
 *
 *	* エミュレーションターゲット上(M6809)の処理なので、BigEndianです。
 *	* 6800/1/3はポストデクリメント・プリインクリメントでしたが、6809は逆です。
 *	  8080/Z80等と同じ、プリデクリメント・ポストインクリメントです。
 */
#define PUSH(sp, r)	do { (sp)--; WRITE((sp), (r)); } while(0)
#define PULL(sp, r)	do { (r) = READ((sp)); (sp)++; } while(0)
#define PUSHW(sp, rr)	do { PUSH((sp), LO(rr)); PUSH((sp), HI(rr)); } while(0)		/* BigEndian */
#define PULLW(sp, rr)	do { PULL((sp), HI(rr)); PULL((sp), LO(rr)); } while(0)		/* BigEndian */

/*
 *	インストラクションフェッチ/実行
 */
#define FETCH(n)	do {		\
	(n) = READ(PC++);		\
	M6809TRACE("%02x ", (n));	\
} while(0)
#define FETCHW(nn)	do {		\
	int hi, lo;			\
	FETCH(hi);			\
	FETCH(lo);			\
	(nn) = hi << 8 | lo;		\
} while(0)
#define EXEC()		do {							\
	M6809TRACE((op->name ? "[%s]" : ""), &m6809_op_name_table[op->name]);	\
	op->proc(m6809, code, arg);						\
	CYCLE -= op->cycle;							\
} while(0)

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

/* N,Zをセットorリセット、Vをクリア、それ以外は保持します。★注意!!Vは常にクリアします!!★ */
#define TEST(n)		do { CC = (CC & ~0xe) | ((( n) >>  4) & 8) | (!( n) << 2); } while(0)
#define TESTW(nn)	do { CC = (CC & ~0xe) | (((nn) >> 12) & 8) | (!(nn) << 2); } while(0)

#define ADD(a, b)	m6809_ADD(m6809, a, b)
int m6809_ADD(M6809* m6809, int a, int b);
#define ADC(a, b)	m6809_ADC(m6809, a, b)
int m6809_ADC(M6809* m6809, int a, int b);
#define SUB(a, b)	m6809_SUB(m6809, a, b)
int m6809_SUB(M6809* m6809, int a, int b);
#define SBC(a, b)	m6809_SBC(m6809, a, b)
int m6809_SBC(M6809* m6809, int a, int b);

#define ADDW(a, b)	m6809_ADDW(m6809, a, b)
int m6809_ADDW(M6809* m6809, int a, int b);
#define SUBW(a, b)	m6809_SUBW(m6809, a, b)
int m6809_SUBW(M6809* m6809, int a, int b);

#define AND(a, b)	m6809_AND(m6809, a, b)
int m6809_AND(M6809* m6809, int a, int b);
#define OR(a, b)	m6809_OR(m6809, a, b)
int m6809_OR(M6809* m6809, int a, int b);
#define EOR(a, b)	m6809_EOR(m6809, a, b)
int m6809_EOR(M6809* m6809, int a, int b);

#define INC(a)		m6809_INC(m6809, a)
int m6809_INC(M6809* m6809, int a);
#define DEC(a)		m6809_DEC(m6809, a)
int m6809_DEC(M6809* m6809, int a);

#define COM(a)		m6809_COM(m6809, a)
int m6809_COM(M6809* m6809, int a);
#define NEG(a)		m6809_NEG(m6809, a)
int m6809_NEG(M6809* m6809, int a);
#define TST(a)		m6809_TST(m6809, a)
void m6809_TST(M6809* m6809, int a);

#define ROL(a)		m6809_ROL(m6809, a)
int m6809_ROL(M6809* m6809, int a);
#define ROR(a)		m6809_ROR(m6809, a)
int m6809_ROR(M6809* m6809, int a);
#define ASL(a)		m6809_ASL(m6809, a)
int m6809_ASL(M6809* m6809, int a);
#define ASR(a)		m6809_ASR(m6809, a)
int m6809_ASR(M6809* m6809, int a);
#define LSR(a)		m6809_LSR(m6809, a)
int m6809_LSR(M6809* m6809, int a);

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

#endif /*__CLIP_M69I_H__*/
