/*	
 *	clipm69i.c
 *
 *	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
 *	- 作成開始。
 */
#include "clip.h"
#include "clipm69i.h"	/*M6809エミュレータ実装用マクロ*/

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

M6809FN_(ERR_INHERENT)
{
	DIE();
}

M6809FN_(10_INHERENT)
{
	M6809TRACE("\n"); /* レジスタダンプ画面表\示の位置ズレ防止 */
	m6809_one(m6809, m6809_op_table_10);
}

M6809FN_(11_INHERENT)
{
	M6809TRACE("\n"); /* レジスタダンプ画面表\示の位置ズレ防止 */
	m6809_one(m6809, m6809_op_table_11);
}

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

#ifndef M6809_ASM

int m6809_ADD(M6809* m6809, int a, int b) {
	int tmp = a + b;
	CC = (CC & ~0x2f) |
	     ((((a & 0xf) + (b & 0xf)) & 0x10) << 1) |		/* H */
	     ((tmp >> 4) & 8) |					/* N */
	     (!(tmp & 0xff) << 2) |				/* Z */
	     (((~(a ^ b) & (a ^ tmp)) >> 6) & 2) |		/* V */
	     ((tmp >> 8) & 1);					/* C */
	return tmp & 0xff;
}

int m6809_ADC(M6809* m6809, int a, int b) {
	int c = CC & 1;
	int tmp = a + b + c;
	CC = (CC & ~0x2f) |
	     ((((a & 0xf) + (b & 0xf) + c) & 0x10) << 1) |	/* H */
	     ((tmp >> 4) & 8) |					/* N */
	     (!(tmp & 0xff) << 2) |				/* Z */
	     (((~(a ^ b) & (a ^ tmp)) >> 6) & 2) |		/* V */
	     ((tmp >> 8) & 1);					/* C */
	return tmp & 0xff;
}

int m6809_SUB(M6809* m6809, int a, int b) {
	int tmp = a - b;
	CC = (CC & ~0xf) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!(tmp & 0xff) << 2) |				/* Z */
	     ((((a ^ b) & (a ^ tmp)) >> 6) & 2) |		/* V */
	     ((tmp >> 8) & 1);					/* C */
	return tmp & 0xff;
}

int m6809_SBC(M6809* m6809, int a, int b) {
	int c = CC & 1;
	int tmp = a - b - c;
	CC = (CC & ~0xf) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!(tmp & 0xff) << 2) |				/* Z */
	     ((((a ^ b) & (a ^ tmp)) >> 6) & 2) |		/* V */
	     ((tmp >> 8) & 1);					/* C */
	return tmp & 0xff;
}

int m6809_ADDW(M6809* m6809, int a, int b) {
	int tmp = a + b;
	CC = (CC & ~0xf) |
	     ((tmp >> 12) & 8) |				/* N */
	     (!(tmp & 0xffff) << 2) |				/* Z */
	     (((~(a ^ b) & (a ^ tmp)) >> 14) & 2) |		/* V */
	     ((tmp >> 16) & 1);					/* C */
	return tmp & 0xffff;
}

int m6809_SUBW(M6809* m6809, int a, int b) {
	int tmp = a - b;
	CC = (CC & ~0xf) |
	     ((tmp >> 12) & 8) |				/* N */
	     (!(tmp & 0xffff) << 2) |				/* Z */
	     ((((a ^ b) & (a ^ tmp)) >> 14) & 2) |		/* V */
	     ((tmp >> 16) & 1);					/* C */
	return tmp & 0xffff;
}

int m6809_AND(M6809* m6809, int a, int b) {
	a &= b;
	TEST(a);						/* N,Z,V */
	return a;
}

int m6809_OR(M6809* m6809, int a, int b) {
	a |= b;
	TEST(a);						/* N,Z,V */
	return a;
}

int m6809_EOR(M6809* m6809, int a, int b) {
	a ^= b;
	TEST(a);						/* N,Z,V */
	return a;
}

int m6809_INC(M6809* m6809, int a) {
	a = (a + 1) & 0xff;
	CC = (CC & ~0xe) |
	     ((a >> 4) & 8) |					/* N */
	     (!a << 2) |					/* Z */
	     ((a == 0x80) << 1);				/* V */
	return a;
}

int m6809_DEC(M6809* m6809, int a) {
	a = (a - 1) & 0xff;
	CC = (CC & ~0xe) |
	     ((a >> 4) & 8) |					/* N */
	     (!a << 2) |					/* Z */
	     ((a == 0x7f) << 1);				/* V */
	return a;
}

int m6809_COM(M6809* m6809, int a) {
	a = ~a & 0xff;
	CC = (CC & ~0xf) |
	     ((a >> 4) & 8) |					/* N */
	     (!a << 2) |					/* Z */
								/* V */
	     1;							/* C */
	return a;
}

/* M6800ではCC(C)の変化が変な仕様(本当!?)でしたが、M6809では自然なのでSUBが使えます。 */
int m6809_NEG(M6809* m6809, int a) {
	return SUB(0, a);					/* N,Z,V,C */
}

/* M6800ではCC(C)が変化しましたが、M6809では変化しません。 */
void m6809_TST(M6809* m6809, int a) {
	TEST(a);						/* N,Z,V */
}

#endif /*M6809_ASM*/

/* M6800とM6809で、CC(V)変化の仕様が違います。 */
int m6809_ASL(M6809* m6809, int a) {
	int tmp = (a << 1) & 0xff;
	CC = (CC & ~0xf) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!tmp << 2) |					/* Z */
	     (((a ^ tmp) >> 6) & 2) |				/* V=old[7]^new[7](仕様) */
	     ((a >> 7) & 1);					/* C */
	return tmp;
}

/* M6800ではCC(V)が変化しましたが、M6809では変化しません。 */
int m6809_ASR(M6809* m6809, int a) {
	int tmp = ((char)a >> 1) & 0xff;
	CC = (CC & ~0xd) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!tmp << 2) |					/* Z */
	     (a & 1);						/* C */
	return tmp;
}

/* M6800ではCC(V)が変化しましたが、M6809では変化しません。 */
int m6809_LSR(M6809* m6809, int a) {
	int tmp = a >> 1;
	CC = (CC & ~0xd) |
								/* N */
	     (!tmp << 2) |					/* Z */
	     (a & 1);						/* C */
	return tmp;
}

/* M6800とM6809で、CC(V)変化の仕様が違います。 */
int m6809_ROL(M6809* m6809, int a) {
	int tmp = ((a << 1) | (CC & 1)) & 0xff;
	CC = (CC & ~0xf) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!tmp << 2) |					/* Z */
	     (((a ^ tmp) >> 6) & 2) |				/* V=old[7]^new[7](仕様) */
	     ((a >> 7) & 1);					/* C */
	return tmp;
}

/* M6800ではCC(V)が変化しましたが、M6809では変化しません。 */
int m6809_ROR(M6809* m6809, int a) {
	int tmp = ((a >> 1) | (CC << 7)) & 0xff;
	CC = (CC & ~0xd) |
	     ((tmp >> 4) & 8) |					/* N */
	     (!tmp << 2) |					/* Z */
	     (a & 1);						/* C */
	return tmp;
}

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

#ifndef M6809_ASM	/****************************************************/

/* ADD (8-Bit) */
M6809FN_(ADDA_DATA)    { A = ADD(A, arg); }
M6809FN_(ADDB_DATA)    { B = ADD(B, arg); }
M6809FN_(ADDA_ADDRESS) { A = ADD(A, READ(arg)); }
M6809FN_(ADDB_ADDRESS) { B = ADD(B, READ(arg)); }

/* ADC */
M6809FN_(ADCA_DATA)    { A = ADC(A, arg); }
M6809FN_(ADCB_DATA)    { B = ADC(B, arg); }
M6809FN_(ADCA_ADDRESS) { A = ADC(A, READ(arg)); }
M6809FN_(ADCB_ADDRESS) { B = ADC(B, READ(arg)); }

/* SUB (8-Bit) */
M6809FN_(SUBA_DATA)    { A = SUB(A, arg); }
M6809FN_(SUBB_DATA)    { B = SUB(B, arg); }
M6809FN_(SUBA_ADDRESS) { A = SUB(A, READ(arg)); }
M6809FN_(SUBB_ADDRESS) { B = SUB(B, READ(arg)); }

/* SBC */
M6809FN_(SBCA_DATA)    { A = SBC(A, arg); }
M6809FN_(SBCB_DATA)    { B = SBC(B, arg); }
M6809FN_(SBCA_ADDRESS) { A = SBC(A, READ(arg)); }
M6809FN_(SBCB_ADDRESS) { B = SBC(B, READ(arg)); }

/* AND */
M6809FN_(ANDA_DATA)    { A = AND(A, arg); }
M6809FN_(ANDB_DATA)    { B = AND(B, arg); }
M6809FN_(ANDA_ADDRESS) { A = AND(A, READ(arg)); }
M6809FN_(ANDB_ADDRESS) { B = AND(B, READ(arg)); }

/* OR */
M6809FN_(ORA_DATA)    { A = OR(A, arg); }
M6809FN_(ORB_DATA)    { B = OR(B, arg); }
M6809FN_(ORA_ADDRESS) { A = OR(A, READ(arg)); }
M6809FN_(ORB_ADDRESS) { B = OR(B, READ(arg)); }

/* EOR */
M6809FN_(EORA_DATA)    { A = EOR(A, arg); }
M6809FN_(EORB_DATA)    { B = EOR(B, arg); }
M6809FN_(EORA_ADDRESS) { A = EOR(A, READ(arg)); }
M6809FN_(EORB_ADDRESS) { B = EOR(B, READ(arg)); }

/* INC */
M6809FN_(INCA_INHERENT) { A = INC(A); }
M6809FN_(INCB_INHERENT) { B = INC(B); }
M6809FN_(INC_ADDRESS)   { WRITE(arg, INC(READ(arg))); }

/* DEC */
M6809FN_(DECA_INHERENT) { A = DEC(A); }
M6809FN_(DECB_INHERENT) { B = DEC(B); }
M6809FN_(DEC_ADDRESS)   { WRITE(arg, DEC(READ(arg))); }

/* CMP (8-Bit) */
M6809FN_(CMPA_DATA)    { SUB(A, arg); }
M6809FN_(CMPB_DATA)    { SUB(B, arg); }
M6809FN_(CMPA_ADDRESS) { SUB(A, READ(arg)); }
M6809FN_(CMPB_ADDRESS) { SUB(B, READ(arg)); }

/* BIT */
M6809FN_(BITA_DATA)    { AND(A, arg); }
M6809FN_(BITB_DATA)    { AND(B, arg); }
M6809FN_(BITA_ADDRESS) { AND(A, READ(arg)); }
M6809FN_(BITB_ADDRESS) { AND(B, READ(arg)); }

/* COM */
M6809FN_(COMA_INHERENT) { A = COM(A); }
M6809FN_(COMB_INHERENT) { B = COM(B); }
M6809FN_(COM_ADDRESS)   { WRITE(arg, COM(READ(arg))); }

/* NEG */
M6809FN_(NEGA_INHERENT) { A = NEG(A); }
M6809FN_(NEGB_INHERENT) { B = NEG(B); }
M6809FN_(NEG_ADDRESS)   { WRITE(arg, NEG(READ(arg))); }

/* TST */
M6809FN_(TSTA_INHERENT) { TST(A); }
M6809FN_(TSTB_INHERENT) { TST(B); }
M6809FN_(TST_ADDRESS)   { TST(READ(arg)); }

/* ROL */
M6809FN_(ROLA_INHERENT) { A = ROL(A); }
M6809FN_(ROLB_INHERENT) { B = ROL(B); }
M6809FN_(ROL_ADDRESS)   { WRITE(arg, ROL(READ(arg))); }

/* ROR */
M6809FN_(RORA_INHERENT) { A = ROR(A); }
M6809FN_(RORB_INHERENT) { B = ROR(B); }
M6809FN_(ROR_ADDRESS)   { WRITE(arg, ROR(READ(arg))); }

/* ASL */
M6809FN_(ASLA_INHERENT) { A = ASL(A); }
M6809FN_(ASLB_INHERENT) { B = ASL(B); }
M6809FN_(ASL_ADDRESS)   { WRITE(arg, ASL(READ(arg))); }

/* ASR */
M6809FN_(ASRA_INHERENT) { A = ASR(A); }
M6809FN_(ASRB_INHERENT) { B = ASR(B); }
M6809FN_(ASR_ADDRESS)   { WRITE(arg, ASR(READ(arg))); }

/* LSR */
M6809FN_(LSRA_INHERENT) { A = LSR(A); }
M6809FN_(LSRB_INHERENT) { B = LSR(B); }
M6809FN_(LSR_ADDRESS)   { WRITE(arg, LSR(READ(arg))); }

/* LD (8-Bit) */
M6809FN_(LDA_DATA)    { A = arg;       TEST(A); }
M6809FN_(LDB_DATA)    { B = arg;       TEST(B); }
M6809FN_(LDA_ADDRESS) { A = READ(arg); TEST(A); }
M6809FN_(LDB_ADDRESS) { B = READ(arg); TEST(B); }

/* ST (8-Bit) */
M6809FN_(STA_ADDRESS) { WRITE(arg, A); TEST(A); }
M6809FN_(STB_ADDRESS) { WRITE(arg, B); TEST(B); }

/* Bcc */
M6809FN_(BHS_ADDRESS) { if(!(CC & 1)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BLO_ADDRESS) { if( (CC & 1)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BVC_ADDRESS) { if(!(CC & 2)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BVS_ADDRESS) { if( (CC & 2)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BNE_ADDRESS) { if(!(CC & 4)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BEQ_ADDRESS) { if( (CC & 4)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BPL_ADDRESS) { if(!(CC & 8)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BMI_ADDRESS) { if( (CC & 8)) { PC = arg; CYCLE -= 1; } }
M6809FN_(BGE_ADDRESS) { if(             !(((CC >> 2) ^ CC) & 2)) { PC = arg; CYCLE -= 1; } } /*       !(N^V) */
M6809FN_(BLT_ADDRESS) { if(              (((CC >> 2) ^ CC) & 2)) { PC = arg; CYCLE -= 1; } } /*        (N^V) */
M6809FN_(BGT_ADDRESS) { if(!(CC & 4) && !(((CC >> 2) ^ CC) & 2)) { PC = arg; CYCLE -= 1; } } /* !Z && !(N^V) */
M6809FN_(BLE_ADDRESS) { if( (CC & 4) ||  (((CC >> 2) ^ CC) & 2)) { PC = arg; CYCLE -= 1; } } /*  Z ||  (N^V) */
M6809FN_(BHI_ADDRESS) { if(!(CC & 5)) { PC = arg; CYCLE -= 1; } } /* !Z && !C */
M6809FN_(BLS_ADDRESS) { if( (CC & 5)) { PC = arg; CYCLE -= 1; } } /*  Z ||  C */

/* BSR */
M6809FN_(BSR_ADDRESS) { PUSHW(S, PC); PC = arg; }

/* RTS */
M6809FN_(RTS_INHERENT) { PULLW(S, PC); }

#endif /*M6809_ASM*/	/****************************************************/

/* ABX */
M6809FN_(ABX_INHERENT) { X += B; }

/* ADD (16-Bit) */
M6809FN_(ADDD_DATA)    { D = ADDW(D, arg); }
M6809FN_(ADDD_ADDRESS) { D = ADDW(D, READW(arg)); }

/* SUB (16-Bit) */
M6809FN_(SUBD_DATA)    { D = SUBW(D, arg); }
M6809FN_(SUBD_ADDRESS) { D = SUBW(D, READW(arg)); }

/* ANDCC */
M6809FN_(ANDCC_DATA) { CC &= arg; m6809_check_pending(m6809); } /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */

/* ORCC */
M6809FN_(ORCC_DATA) { CC |= arg; } /* CC(F,I)が1:禁止→0:許可に変化する可能\性はないので、m6809_check_pending()不要 */

/* CLR */
M6809FN_(CLRA_INHERENT) { A = 0;         CC = (CC & ~0xf) | 4; }
M6809FN_(CLRB_INHERENT) { B = 0;         CC = (CC & ~0xf) | 4; }
M6809FN_(CLR_ADDRESS)   { WRITE(arg, 0); CC = (CC & ~0xf) | 4; }

/* CMP (16-Bit) */
M6809FN_(CMPD_DATA)    { SUBW(D, arg); }
M6809FN_(CMPX_DATA)    { SUBW(X, arg); }
M6809FN_(CMPY_DATA)    { SUBW(Y, arg); }
M6809FN_(CMPS_DATA)    { SUBW(S, arg); }
M6809FN_(CMPU_DATA)    { SUBW(U, arg); }
M6809FN_(CMPD_ADDRESS) { SUBW(D, READ(arg)); }
M6809FN_(CMPX_ADDRESS) { SUBW(X, READ(arg)); }
M6809FN_(CMPY_ADDRESS) { SUBW(Y, READ(arg)); }
M6809FN_(CMPS_ADDRESS) { SUBW(S, READ(arg)); }
M6809FN_(CMPU_ADDRESS) { SUBW(U, READ(arg)); }

/* LD (16-Bit) */
M6809FN_(LDD_DATA)    { D = arg;        TESTW(D); }
M6809FN_(LDX_DATA)    { X = arg;        TESTW(X); }
M6809FN_(LDY_DATA)    { Y = arg;        TESTW(Y); }
M6809FN_(LDS_DATA)    { S = arg;        TESTW(S); }
M6809FN_(LDU_DATA)    { U = arg;        TESTW(U); }
M6809FN_(LDD_ADDRESS) { D = READW(arg); TESTW(D); }
M6809FN_(LDX_ADDRESS) { X = READW(arg); TESTW(X); }
M6809FN_(LDY_ADDRESS) { Y = READW(arg); TESTW(Y); }
M6809FN_(LDS_ADDRESS) { S = READW(arg); TESTW(S); }
M6809FN_(LDU_ADDRESS) { U = READW(arg); TESTW(U); }

/* ST (16-Bit) */
M6809FN_(STD_ADDRESS) { WRITEW(arg, D); TESTW(D); }
M6809FN_(STX_ADDRESS) { WRITEW(arg, X); TESTW(X); }
M6809FN_(STY_ADDRESS) { WRITEW(arg, Y); TESTW(Y); }
M6809FN_(STS_ADDRESS) { WRITEW(arg, S); TESTW(S); }
M6809FN_(STU_ADDRESS) { WRITEW(arg, U); TESTW(U); }

/* LEA */
M6809FN_(LEAX_ADDRESS) { X = arg; CC = (CC & ~4) | (!X << 2); }
M6809FN_(LEAY_ADDRESS) { Y = arg; CC = (CC & ~4) | (!Y << 2); }
M6809FN_(LEAS_ADDRESS) { S = arg; } /* フラグ変化なし!! */
M6809FN_(LEAU_ADDRESS) { U = arg; } /* フラグ変化なし!! */

/* MUL */
/* M6801ではCC(Z)は変化しませんでしたが、M6809では変化します。 */
M6809FN_(MUL_INHERENT) {
	D = A * B;
	CC = (CC & ~5) |
	     (!D << 2) |	/* Z */
	     ((D >> 7) & 1);	/* C=new[7](仕様) */
}

/* PSH */
M6809FN_(PSHS_DATA) {
	if(arg & 0x80) { PUSHW(S, PC); CYCLE -= 2; }
	if(arg & 0x40) { PUSHW(S, U);  CYCLE -= 2; }
	if(arg & 0x20) { PUSHW(S, Y);  CYCLE -= 2; }
	if(arg & 0x10) { PUSHW(S, X);  CYCLE -= 2; }
	if(arg & 0x08) { PUSH(S, DP);  CYCLE -= 1; }
	if(arg & 0x04) { PUSH(S, B);   CYCLE -= 1; }
	if(arg & 0x02) { PUSH(S, A);   CYCLE -= 1; }
	if(arg & 0x01) { PUSH(S, CC);  CYCLE -= 1; }
}
M6809FN_(PSHU_DATA) {
	if(arg & 0x80) { PUSHW(U, PC); CYCLE -= 2; }
	if(arg & 0x40) { PUSHW(U, S);  CYCLE -= 2; }
	if(arg & 0x20) { PUSHW(U, Y);  CYCLE -= 2; }
	if(arg & 0x10) { PUSHW(U, X);  CYCLE -= 2; }
	if(arg & 0x08) { PUSH(U, DP);  CYCLE -= 1; }
	if(arg & 0x04) { PUSH(U, B);   CYCLE -= 1; }
	if(arg & 0x02) { PUSH(U, A);   CYCLE -= 1; }
	if(arg & 0x01) { PUSH(U, CC);  CYCLE -= 1; }
}

/* PUL */
M6809FN_(PULS_DATA) {
	if(arg & 0x01) { PULL(S, CC);  CYCLE -= 1; }
	if(arg & 0x02) { PULL(S, A);   CYCLE -= 1; }
	if(arg & 0x04) { PULL(S, B);   CYCLE -= 1; }
	if(arg & 0x08) { PULL(S, DP);  CYCLE -= 1; }
	if(arg & 0x10) { PULLW(S, X);  CYCLE -= 2; }
	if(arg & 0x20) { PULLW(S, Y);  CYCLE -= 2; }
	if(arg & 0x40) { PULLW(S, U);  CYCLE -= 2; }
	if(arg & 0x80) { PULLW(S, PC); CYCLE -= 2; }
	m6809_check_pending(m6809); /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */
}
M6809FN_(PULU_DATA) {
	if(arg & 0x01) { PULL(U, CC);  CYCLE -= 1; }
	if(arg & 0x02) { PULL(U, A);   CYCLE -= 1; }
	if(arg & 0x04) { PULL(U, B);   CYCLE -= 1; }
	if(arg & 0x08) { PULL(U, DP);  CYCLE -= 1; }
	if(arg & 0x10) { PULLW(U, X);  CYCLE -= 2; }
	if(arg & 0x20) { PULLW(U, Y);  CYCLE -= 2; }
	if(arg & 0x40) { PULLW(U, S);  CYCLE -= 2; }
	if(arg & 0x80) { PULLW(U, PC); CYCLE -= 2; }
	m6809_check_pending(m6809); /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */
}

/* EXG */
M6809FN_(EXG_DATA) {
	int tmp;
	int hi = arg >> 4;
	int lo = arg & 0xf;
	if(hi & 8) { /* Source=8bit */
		unsigned char *a, *b;
		switch(hi) {
		case  8:  a = &A;  break;
		case  9:  a = &B;  break;
		case 10:  a = &CC; break;
		case 11:  a = &DP; break;
		default: DIE(); /* 12-15:未定義 */
		}
		switch(lo) {
		case  8:  b = &A;  break;
		case  9:  b = &B;  break;
		case 10:  b = &CC; break;
		case 11:  b = &DP; break;
		default: DIE(); /* 12-15:未定義、0-7:8bit<=>16bit不可 */
		}
		tmp = *a;
		      *a = *b;
		           *b = tmp;
		m6809_check_pending(m6809); /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */
	} else { /* Source=16bit */
		unsigned short *a, *b;
		switch(hi) {
		case 0:  a = &D;  break;
		case 1:  a = &X;  break;
		case 2:  a = &Y;  break;
		case 3:  a = &U;  break;
		case 4:  a = &S;  break;
		case 5:  a = &PC; break;
		default: DIE(); /* 6-7:未定義 */
		}
		switch(lo) {
		case 0:  b = &D;  break;
		case 1:  b = &X;  break;
		case 2:  b = &Y;  break;
		case 3:  b = &U;  break;
		case 4:  b = &S;  break;
		case 5:  b = &PC; break;
		default: DIE(); /* 6-7:未定義、8-15:8bit<=>16bit不可 */
		}
		tmp = *a;
		      *a = *b;
		           *b = tmp;
	}
}

/* TFR */
M6809FN_(TFR_DATA) {
	int tmp;
	int hi = arg >> 4;
	int lo = arg & 0xf;
	if((hi ^ lo) & 8) DIE(); /* 8bit<=>16bit不可 */
	switch(hi) {
	case  0:  tmp = D;  break;
	case  1:  tmp = X;  break;
	case  2:  tmp = Y;  break;
	case  3:  tmp = U;  break;
	case  4:  tmp = S;  break;
	case  5:  tmp = PC; break;
	case  8:  tmp = A;  break;
	case  9:  tmp = B;  break;
	case 10:  tmp = CC; break;
	case 11:  tmp = DP; break;
	default: DIE(); /* 6-7,12-15:未定義 */
	}
	switch(lo) {
	case  0:  D  = tmp; break;
	case  1:  X  = tmp; break;
	case  2:  Y  = tmp; break;
	case  3:  U  = tmp; break;
	case  4:  S  = tmp; break;
	case  5:  PC = tmp; break;
	case  8:  A  = tmp; break;
	case  9:  B  = tmp; break;
	case 10:  CC = tmp; break;
	case 11:  DP = tmp; break;
	default: DIE(); /* 6-7,12-15:未定義 */
	}
	m6809_check_pending(m6809); /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */
}

/* CWAI */
/* 本当はCC(E)をセットして全レジスタを退避してから停止します。厳密にはこの実装では正しくありません。 */
M6809FN_(CWAI_DATA) {
	WAIT = 1;
	CC &= arg;
	m6809_check_pending(m6809); /* CC(F,I)が1:禁止→0:許可に変化する可能\性があるので、m6809_check_pending()必要 */
}

/* NOP */
M6809FN_(NOP_INHERENT) { /** no job **/ }

/* BRA */
M6809FN_(BRA_ADDRESS) { PC = arg; }

/* BRN */
M6809FN_(BRN_ADDRESS) { /** no job **/ }

/* RTI */
M6809FN_(RTI_INHERENT) { m6809_rti(m6809); }

/* SEX */
M6809FN_(SEX_INHERENT) { D = (char)B; TESTW(D); }

/* DAA */
M6809FN_(DAA_INHERENT) { DIE(); } /* ※TODO:未実装 */

/* SWI */
M6809FN_(SWI_INHERENT)  { DIE(); } /* ※TODO:未実装 */
M6809FN_(SWI2_INHERENT) { DIE(); } /* ※TODO:未実装 */
M6809FN_(SWI3_INHERENT) { DIE(); } /* ※TODO:未実装 */

/* SYNC */
M6809FN_(SYNC_INHERENT) { DIE(); } /* ※TODO:未実装 */

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

