www.pudn.com > ncdzsrc.rar > i68k.c


/*************************************************************************** 
 
	i68k.c 
 
	MC68000 簡易インタプリタ (調整中) 
 
    以下の命令は未サポート 
     MOVEP (to Dn) MOVEP (from Dn) 
     PEA LINK UNLK 
     CHK TRAP TRAPV 
     ABCD NBCD SBCD 
     RTR 
     特権命令全て 
 
    (サポートしている命令でも実装していないオペレーションあり) 
 
    元々デバッガ用に作成した、処理内容を画面に出力する関数だった為、 
    サイクル数等は一切考慮していません。速度もそれなりに遅いです。 
 
***************************************************************************/ 
 
#include "neogeocd.h" 
 
#define VERBOSE 0 
#if VERBOSE 
#define LOG(x) { if (i68k_verbose) { logerror x; } } 
#else 
#define LOG(x) 
#endif 
 
 
/**************************************************************************** 
	マクロ 
 ***************************************************************************/ 
 
#define An   	0	// address register 
#define Dn   	1	// data register 
#define AI   	2	// address register indirect 
#define PI		3	// postincrement 
#define PI7		4	// postincrement (A7) 
#define PD   	5	// predecrement 
#define PD7  	6	// predecrement (A7) 
#define IX   	7	// indirect + index 
#define IM 	 	8	// immidiate 
#define AA 	 	9	// absolute addressing 
#define MM 		10	// movem register list 
#define CCR		11	// condition code register 
#define SR 		12	// status register 
#define NA 		-1	// N/A 
 
#define SIZE_B	1 
#define SIZE_W	2 
#define SIZE_L	4 
 
#define NOTFOUND	0 
#define SET1		1 
#define SET2		2 
#define TEST		3 
#define INVALID		4 
#define OTHER		5 
 
#define OPCODE(x)	(strcmp(opcode, x) == 0) 
 
#define MAKE_INT_8(A)  (INT8)((A) & 0xff) 
#define MAKE_INT_16(A) (INT16)((A) & 0xffff) 
#define MAKE_INT_32(A) (INT32)((A) & 0xffffffff) 
 
#define HI		(C == 0 && Z == 0) 
#define LS		(C != 0 || Z != 0) 
#define CC		(C == 0) 
#define CS		(C != 0) 
#define NE		(Z == 0) 
#define EQ		(Z != 0) 
#define VC		(V == 0) 
#define VS		(V != 0) 
#define PL		(N == 0) 
#define MI		(N != 0) 
#define GE		((N == 0) == (V == 0)) 
#define LT		((N == 0) != (V == 0)) 
#define GT		(Z == 0 && (N == 0) == (V == 0)) 
#define LE		(Z != 0 || (N == 0) != (V == 0)) 
 
#define read8(addr)			m68000_read_memory_8(addr) 
#define read16(addr)		m68000_read_memory_16(addr) 
#define read32(addr)		m68000_read_memory_32(addr) 
 
#define write8(addr, data)	m68000_write_memory_8(addr, data) 
#define write16(addr, data)	m68000_write_memory_16(addr, data) 
#define write32(addr, data)	m68000_write_memory_32(addr, data) 
 
 
/**************************************************************************** 
	プロトタイプ 
 ***************************************************************************/ 
 
int m68k_disassemble(char *str_buff, int pc); 
 
 
/**************************************************************************** 
	ローカル変数 
 ***************************************************************************/ 
 
int i68k_verbose = 0; 
 
static UINT32 value1, value2, addr1, addr2; 
static UINT32 a[8], d[8]; 
static UINT16 sr; 
static int X, N, Z, V, C; 
 
 
/*************************************************************************** 
	文字列解析 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	buf1の文字列からデータの種類を判別し、計算しやすい 
	形に変換してbuf2に格納する 
 
	引  数: char *buf1    元の文字列 
	        char *buf2    変換した文字列の格納先 
	        UINT32 pc     現在のPC(OPCODE含む) 
 
	戻り値: 文字列の種類 
 
    アドレスレジスタ及びデータレジスタはbuf[0]に 
    レジスタ番号が数値で入ります 
 
 -------------------------------------------------------*/ 
 
static int check_type(char *buf1, char *buf2, UINT32 pc) 
{ 
	int i, j; 
 
	memset(buf2, 0, 256); 
 
	switch (buf1[0]) 
	{ 
	case '[': 
		// movem - 表記を変更してあります 
		for (i = 1; buf1[i] != ']'; i++) 
			buf2[i - 1] = buf1[i]; 
		return MM; 
 
	case 'A': 
		// アドレスレジスタ 
		buf2[0] = buf1[1] - '0'; 
		return An; 
 
	case 'D':	// データレジスタ 
		buf2[0] = buf1[1] - '0'; 
		return Dn; 
 
	case 'C':	// CCR 
		buf2[0] = 0; 
		return SR; 
 
	case 'S':	// ステータスレジスタ 
		buf2[0] = 0; 
		return SR; 
 
	case '#':	// イミディエイト 
		i = 1; 
		j = 0; 
		while (1) 
		{ 
			if (buf1[i] == '\0' 
			||	buf1[i] == ',' 
			||  buf1[i] == '.') 
			{ 
				break; 
			} 
			else 
			if ((buf1[i] == '-') 
			||  (buf1[i] >= '0' && buf1[i] <= '9') 
			||	(buf1[i] >= 'a' && buf1[i] <= 'f')) 
			{ 
				buf2[j++] = buf1[i]; 
			} 
			i++; 
		} 
		return IM; 
 
	case '$':	// アドレス直接指定 
		strcpy(buf2, &buf1[1]); 
		*strchr(buf2, '.') = '\0'; 
		return AA; 
 
	case '-':	// プレデクリメント 
		buf2[0] = buf1[2]; 
		buf2[1] = buf1[3]; 
		return (buf1[3] == '7') ? PD7 : PD; 
 
	case '(': 
		if (buf1[1] == 'A' && buf1[3] == ')') 
		{ 
			buf2[0] = buf1[1]; 
			buf2[1] = buf1[2]; 
 
			if (buf1[4] == '+') 
			{ 
				// ポストインクリメント 
				return (buf1[2] == '7') ? PI7 : PI; 
			} 
			else 
			{ 
				// アドレスレジスタ間接参照 
				return AI; 
			} 
		} 
 
		i = 1; 
		j = 0; 
		while (1) 
		{ 
			if (buf1[i] == ')') 
				break; 
 
			else if (buf1[i] == ',') 
			{ 
				buf2[j++] = ','; 
			} 
			else 
			if (buf1[i] == 'P') 
			{ 
				char tmp[16]; 
 
				// PCは数値に変換しておく 
				sprintf(tmp, "%x", pc + 2); 
				strcat(buf2, tmp); 
				i++; 
				j += strlen(tmp); 
			} 
			else 
			if ((buf1[i] == 'A') 
			||	(buf1[i] == 'D') 
			||	(buf1[i] == '-') 
			||  (buf1[i] >= '0' && buf1[i] <= '9') 
			||	(buf1[i] >= 'a' && buf1[i] <= 'f')) 
			{ 
				buf2[j++] = buf1[i]; 
			} 
			i++; 
		} 
		return IX; 
 
	default: 
		return NA; 
	} 
} 
 
 
/*************************************************************************** 
	レジスタ操作 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	データレジスタの値を取得 
 
	引  数: int n         レジスタ番号 
	        int size      サイズ (バイト) 
	戻り値: レジスタのの値 
 
 -------------------------------------------------------*/ 
 
static UINT32 get_d(int n, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: return d[n] & 0xff; 
	case SIZE_W: return d[n] & 0xffff; 
	} 
	return d[n]; 
} 
 
 
/*-------------------------------------------------------- 
 
	データレジスタの値を設定 
 
	引  数: int n         レジスタ番号 
	        UINT32 value  設定する値 
	        int size      サイズ (バイト) 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void set_d(int n, UINT32 value, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: 
		d[n] &= 0xffffff00; 
		d[n] |= value & 0xff; 
		return; 
 
	case SIZE_W: 
		d[n] &= 0xffff0000; 
		d[n] |= value & 0xffff; 
		return; 
	} 
	d[n] = value; 
} 
 
 
/*-------------------------------------------------------- 
 
	アドレスレジスタの値を取得 
 
	引  数: int n         レジスタ番号 
	        int size      サイズ (バイト) 
	戻り値: レジスタのの値 
 
  ※現状常にLONGの値を返します 
 
 -------------------------------------------------------*/ 
 
static UINT32 get_a(int n) 
{ 
	return a[n]; 
} 
 
 
/*-------------------------------------------------------- 
 
	アドレスレジスタの値を設定 
 
	引  数: int n         レジスタ番号 
	        UINT32 value  設定する値 
	        int size      サイズ (バイト) 
	戻り値: なし 
 
  ※現状常にLONGの値を設定します 
 
 -------------------------------------------------------*/ 
 
static void set_a(int n, UINT32 value) 
{ 
	a[n] = value; 
} 
 
 
/*************************************************************************** 
	イミディエイト値操作 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	即値の文字列を数値に変換して取得 
 
	引  数: char *buf     文字列のバッファ 
	        int size      サイズ (バイト) 
	戻り値: 値 
 
 -------------------------------------------------------*/ 
 
static UINT32 get_imm(char *buf, int size) 
{ 
	int value; 
 
	if (buf[0] == '-') 
	{ 
		sscanf(&buf[1], "%x", &value); 
		value = 0 - value; 
	} 
	else 
	{ 
		sscanf(buf, "%x", &value); 
	} 
 
	switch (size) 
	{ 
	case SIZE_B: return value & 0xff; 
	case SIZE_W: return value & 0xffff; 
	} 
	return value; 
} 
 
 
/*************************************************************************** 
	エフェクティブアドレス操作 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	アドレスの文字列を数値に変換して取得 
 
	引  数: char *buf     文字列のバッファ 
	        int size      サイズ (バイト) 
	戻り値: アドレスの値 
 
 -------------------------------------------------------*/ 
 
static int get_ea(char *buf, int *a, int *d, int type, int size) 
{ 
	int n, res = 0; 
	char *p; 
 
	switch (type) 
	{ 
	case AI: 
		n = buf[1] - '0'; 
		res = a[n]; 
		break; 
 
	case PD: 
	case PD7: 
		n = buf[1] - '0'; 
		a[n] -= size; 
		res = a[n]; 
		break; 
 
	case PI: 
	case PI7: 
		n = buf[1] - '0'; 
		res = a[n]; 
		a[n] += size; 
		break; 
 
	case AA: 
		sscanf(buf, "%x", &res); 
		break; 
 
	case IX: 
		p = strtok(buf, ",\n\0"); 
 
		while (p) 
		{ 
			if ((p[0] == '-') || (p[0] >= '0' && p[0] <= '9') || (p[0] >= 'a' && p[0] <= 'f')) 
			{ 
				int value; 
 
				if (p[0] == '-') 
				{ 
					sscanf(&p[1], "%x", &value); 
					value = 0 - value; 
				} 
				else 
				{ 
					sscanf(p, "%x", &value); 
				} 
				res += value; 
			} 
			else if (p[0] == 'A') 
			{ 
				n = p[1] - '0'; 
				res += a[n]; 
			} 
			else if (p[0] == 'D') 
			{ 
				n = p[1] - '0'; 
				res += MAKE_INT_16(d[n]); 
			} 
 
			p = strtok(NULL, ",\n\0"); 
		} 
		break; 
	} 
 
	return res; 
} 
 
 
/*-------------------------------------------------------- 
 
	アドレスのデータを取得 
 
	引  数: int addr      アドレス 
	        int size      サイズ (バイト) 
	戻り値: アドレスの値 
 
 -------------------------------------------------------*/ 
 
static UINT32 read_ea(int addr, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: return read8(addr); 
	case SIZE_W: return read16(addr); 
	} 
	return read32(addr); 
} 
 
 
/*-------------------------------------------------------- 
 
	アドレスのデータを設定 
 
	引  数: int addr      アドレス 
	        UINT32 value  設定する値 
	        int size      サイズ (バイト) 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void write_ea(int addr, UINT32 value, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: write8(addr, value & 0xff); return; 
	case SIZE_W: write16(addr, value & 0xffff); return; 
	} 
	write32(addr, value); 
} 
 
 
/*************************************************************************** 
	オペレーション & フラグセット 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	ネガティブフラグ取得 
 
	引  数: UINT32 result  オペレーションの結果の値 
	        int size       サイズ (バイト) 
	戻り値: Nフラグの値 
 
 -------------------------------------------------------*/ 
 
static int NFLAG(UINT32 result, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: return (result & 0x80) != 0; 
	case SIZE_W: return (result & 0x8000) != 0; 
	} 
	return (result & 0x80000000) != 0; 
} 
 
 
/*-------------------------------------------------------- 
 
	ゼロフラグ取得 
 
	引  数: UINT32 result  オペレーションの結果の値 
	        int size       サイズ (バイト) 
	戻り値: Zフラグの値 
 
 -------------------------------------------------------*/ 
 
static int ZFLAG(UINT32 result, int size) 
{ 
	switch (size) 
	{ 
	case SIZE_B: return (result & 0xff) == 0; 
	case SIZE_W: return (result & 0xffff) == 0; 
	} 
	return (result & 0xffffffff) == 0; 
} 
 
 
/*-------------------------------------------------------- 
 
	ADDを実行し、演算結果を返す 
 
	引  数: UINT32 s       ソース 
	        UINT32 d       デスティネーション 
	        int size       サイズ (バイト) 
	戻り値: 演算結果 
 
  ※同時にフラグも設定します 
 
 -------------------------------------------------------*/ 
 
#define VFLAG_ADD(s, d, r) ((s ^ r) & (d ^ r)) 
 
static UINT32 op_add(UINT32 s, UINT32 d, int size) 
{ 
	UINT32 result; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		s &= 0x000000ff; 
		d &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		s &= 0x0000ffff; 
		d &= 0x0000ffff; 
		break; 
	} 
 
	result = d + s; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		C = result; 
		V = VFLAG_ADD(s, d, result); 
		result &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		C = result >> 8; 
		V = VFLAG_ADD(s, d, result) >> 8; 
		result &= 0x0000ffff; 
		break; 
 
	case SIZE_L: 
		C = ((s & d & 1) + (s >> 1) + (d >> 1)) >> 23; 
		V = VFLAG_ADD(s, d, result) >> 24; 
		break; 
	} 
 
	C = (C & 0x100) != 0; 
	V = (V & 0x80) != 0; 
	N = NFLAG(result, size); 
	Z = ZFLAG(result, size); 
 
#if VERBOSE 
	switch (size) 
	{ 
	case SIZE_B: LOG(("%02x + %02x (=%02x) -> ", d, s, result)); break; 
	case SIZE_W: LOG(("%04x + %04x (=%04x) -> ", d, s, result)); break; 
	case SIZE_L: LOG(("%08x + %08x (=%08x) -> ", d, s, result)); break; 
	} 
#endif 
 
	return result; 
} 
 
 
/*-------------------------------------------------------- 
 
	SUBを実行し、演算結果を返す 
 
	引  数: UINT32 s       ソース 
	        UINT32 d       デスティネーション 
	        int size       サイズ (バイト) 
	戻り値: 演算結果 
 
  ※同時にフラグも設定します 
 
 -------------------------------------------------------*/ 
 
#define VFLAG_SUB(s, d, r) ((s ^ d) & (r ^ d)) 
 
static UINT32 op_sub(UINT32 s, UINT32 d, int size) 
{ 
	UINT32 result; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		s &= 0x000000ff; 
		d &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		s &= 0x0000ffff; 
		d &= 0x0000ffff; 
		break; 
	} 
 
	result = d - s; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		C = result; 
		V = VFLAG_SUB(s, d, result); 
		result &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		C = result >> 8; 
		V = VFLAG_SUB(s, d, result) >> 8; 
		result &= 0x0000ffff; 
		break; 
 
	case SIZE_L: 
		C = ((s & result & 1) + (s >> 1) + (result >> 1)) >> 23; 
		V = VFLAG_SUB(s, d, result) >> 24; 
		break; 
	} 
 
	C = (C & 0x100) != 0; 
	V = (V & 0x80) != 0; 
	N = NFLAG(result, size); 
	Z = ZFLAG(result, size); 
 
#if VERBOSE 
	switch (size) 
	{ 
	case SIZE_B: LOG(("%02x - %02x (=%02x) -> ", d, s, result)); break; 
	case SIZE_W: LOG(("%04x - %04x (=%04x) -> ", d, s, result)); break; 
	case SIZE_L: LOG(("%08x - %08x (=%08x) -> ", d, s, result)); break; 
	} 
#endif 
 
	return result; 
} 
 
 
/*-------------------------------------------------------- 
 
	ANDを実行し、演算結果を返す 
 
	引  数: UINT32 s       ソース 
	        UINT32 d       デスティネーション 
	        int size       サイズ (バイト) 
	戻り値: 演算結果 
 
  ※同時にフラグも設定します 
 
 -------------------------------------------------------*/ 
 
static UINT32 op_and(UINT32 s, UINT32 d, int size) 
{ 
	UINT32 result; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		s &= 0x000000ff; 
		d &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		s &= 0x0000ffff; 
		d &= 0x0000ffff; 
		break; 
	} 
 
	result = d & s; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		result &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		result &= 0x0000ffff; 
		break; 
	} 
 
	C = 0; 
	V = 0; 
	N = NFLAG(result, size); 
	Z = ZFLAG(result, size); 
 
#if VERBOSE 
	switch (size) 
	{ 
	case SIZE_B: LOG(("%02x & %02x (=%02x) -> ", d, s, result)); break; 
	case SIZE_W: LOG(("%04x & %04x (=%04x) -> ", d, s, result)); break; 
	case SIZE_L: LOG(("%08x & %08x (=%08x) -> ", d, s, result)); break; 
	} 
#endif 
 
	return result; 
} 
 
 
/*-------------------------------------------------------- 
 
	EORを実行し、演算結果を返す 
 
	引  数: UINT32 s       ソース 
	        UINT32 d       デスティネーション 
	        int size       サイズ (バイト) 
	戻り値: 演算結果 
 
  ※同時にフラグも設定します 
 
 -------------------------------------------------------*/ 
 
static UINT32 op_eor(UINT32 s, UINT32 d, int size) 
{ 
	UINT32 result; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		s &= 0x000000ff; 
		d &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		s &= 0x0000ffff; 
		d &= 0x0000ffff; 
		break; 
	} 
 
	result = d ^ s; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		result &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		result &= 0x0000ffff; 
		break; 
	} 
 
	C = 0; 
	V = 0; 
	N = NFLAG(result, size); 
	Z = ZFLAG(result, size); 
 
#if VERBOSE 
	switch (size) 
	{ 
	case SIZE_B: LOG(("%02x ^ %02x (=%02x) -> ", d, s, result)); break; 
	case SIZE_W: LOG(("%04x ^ %04x (=%04x) -> ", d, s, result)); break; 
	case SIZE_L: LOG(("%08x ^ %08x (=%08x) -> ", d, s, result)); break; 
	} 
#endif 
 
	return result; 
} 
 
 
/*-------------------------------------------------------- 
 
	ORを実行し、演算結果を返す 
 
	引  数: UINT32 s       ソース 
	        UINT32 d       デスティネーション 
	        int size       サイズ (バイト) 
	戻り値: 演算結果 
 
  ※同時にフラグも設定します 
 
 -------------------------------------------------------*/ 
 
static UINT32 op_or(UINT32 s, UINT32 d, int size) 
{ 
	UINT32 result; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		s &= 0x000000ff; 
		d &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		s &= 0x0000ffff; 
		d &= 0x0000ffff; 
		break; 
	} 
 
	result = d | s; 
 
	switch (size) 
	{ 
	case SIZE_B: 
		result &= 0x000000ff; 
		break; 
 
	case SIZE_W: 
		result &= 0x0000ffff; 
		break; 
	} 
 
	C = 0; 
	V = 0; 
	N = NFLAG(result, size); 
	Z = ZFLAG(result, size); 
 
#if VERBOSE 
	switch (size) 
	{ 
	case SIZE_B: LOG(("%02x | %02x (=%02x) -> ", d, s, result)); break; 
	case SIZE_W: LOG(("%04x | %04x (=%04x) -> ", d, s, result)); break; 
	case SIZE_L: LOG(("%08x | %08x (=%08x) -> ", d, s, result)); break; 
	} 
#endif 
 
	return result; 
} 
 
 
/*************************************************************************** 
	文字列から値を取得 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	値1(ソースまたはデスティネーションのみの場合) 
 
	引  数: char *buf       文字列のバッファ 
	        int type        check_type()で取得した値 
	        int size        サイズ (バイト) 
	戻り値: なし 
 
  ※value1に値を、EAの場合はaddr1にアドレスを設定します 
 
 -------------------------------------------------------*/ 
 
INLINE void get_value1(char *buf, int type, int size) 
{ 
	switch (type) 
	{ 
	case NA: 
		LOG(("(error) ")); 
		break; 
 
	case CCR: 
		value1 = ((X << 4) | (N << 3) | (Z << 2) | (V << 1) | C); 
		break; 
 
	case SR: 
		value1 = (SR & 0xffe1) | ((X << 4) | (N << 3) | (Z << 2) | (V << 1) | C); 
		break; 
 
	case An: 
		value1 = a[(int)buf[0]]; 
		break; 
 
	case Dn: 
		value1 = get_d(buf[0], size); 
		break; 
 
	case IM: 
		value1 = get_imm(buf, size); 
		break; 
 
	default: 
		addr1 = get_ea(buf, a, d, type, size); 
		value1 = read_ea(addr1, size); 
		break; 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	値2 (デスティネーション) 
 
	引  数: char *buf       文字列のバッファ 
	        int type        check_type()で取得した値 
	        int size        サイズ (バイト) 
	戻り値: なし 
 
  ※value2に値を、EAの場合はaddr2にアドレスを設定します 
 
 -------------------------------------------------------*/ 
 
INLINE void get_value2(char *buf, int type, int size) 
{ 
	switch (type) 
	{ 
	case NA: 
		LOG(("(error) ")); 
		break; 
 
	case CCR: 
		value1 = ((X << 4) | (N << 3) | (Z << 2) | (V << 1) | C); 
		break; 
 
	case SR: 
		value1 = (SR & 0xffe1) | ((X << 4) | (N << 3) | (Z << 2) | (V << 1) | C); 
		break; 
 
	case An: 
		value2 = a[(int)buf[0]]; 
		break; 
 
	case Dn: 
		value2 = get_d(buf[0], size); 
		break; 
 
	case IM: 
		value2 = get_imm(buf, size); 
		break; 
 
	default: 
		addr2 = get_ea(buf, a, d, type, size); 
		value2 = read_ea(addr2, size); 
		break; 
	} 
} 
 
 
/*************************************************************************** 
	インタプリタコア 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	MC68000 簡易インタプリタ 
 
	引  数: UINT32 start_pc    開始PC 
	        UINT32 break_point ブレークポイント 
	戻り値: なし 
 
  ※ブレークポイントが'0'の場合は、開始PCと同じレベルの 
    処理が終了した時点で停止します 
 
 -------------------------------------------------------*/ 
 
void m68000_interpreter(UINT32 start_pc, UINT32 break_point) 
{ 
	UINT32 pc, nest_pc[256]; 
	int type1, type2, size; 
	char buf[256], src[256], dst[256]; 
	char *opcode, *p, *tmp1, *tmp2; 
	UINT32 mask, msb, nest_count, result; 
	int i, n1, n2, opcode_len, op; 
 
	pc = start_pc; 
	nest_count= 0; 
 
	for (i = 0; i < 8; i++) 
	{ 
		a[i] = m68000_get_reg(M68K_A0 + i); 
		d[i] = m68000_get_reg(M68K_D0 + i); 
	} 
 
	sr = m68000_get_reg(M68K_SR); 
	C = sr & (1 << 0); 
	V = sr & (1 << 1); 
	Z = sr & (1 << 2); 
	N = sr & (1 << 3); 
	X = sr & (1 << 4); 
 
	// NEOGEO CD用 
	a[5] = 0x108000; 
	a[7] -= 4 * 8 * 2;	// スタックを破壊しないように念の為 
 
	result = 0; 
	n1 = 0; 
	n2 = 0; 
 
	LOG(("\n-- start --\n")); 
 
	while (pc != break_point) 
	{ 
		opcode_len = m68k_disassemble(buf, pc); 
 
		if ((p = strchr(buf, ';')) != NULL) *p = '\0';	// コメント削除 
 
		LOG(("%06x: %-32s", pc, buf)); 
 
		opcode = strtok(buf, " \n"); 
		tmp1 = strtok(NULL, " \n"); 
		tmp2 = strtok(NULL, " \n"); 
 
		if (tmp1 != NULL) 
			type1 = check_type(tmp1, src, pc); 
		else 
			type1 = NA; 
 
		if (tmp2 != NULL) 
			type2 = check_type(tmp2, dst, pc); 
		else 
			type2 = NA; 
 
		if ((p = strchr(buf, '.')) != NULL) 
		{ 
			switch (*(p + 1)) 
			{ 
			case 'b': 
				size = SIZE_B; 
				mask = 0x000000ff; 
				msb  = 0x00000080; 
				break; 
 
			case 'w': 
				size = SIZE_W; 
				mask = 0x0000ffff; 
				msb  = 0x00008000; 
				break; 
 
			default: 
				size = SIZE_L; 
				mask = 0xffffffff; 
				msb  = 0x80000000; 
				break; 
			} 
			*p = '\0'; 
		} 
		else 
		{ 
			size = SIZE_L; 
			mask = 0xffffffff; 
			msb  = 0x80000000; 
		} 
 
		if (type2 == An && size == SIZE_B) 
		{ 
			LOG(("%s\tbyte size oparation (illegal).\n")); 
			pc += opcode_len; 
			continue; 
		} 
 
		LOG(("%s\t", opcode)); 
 
		if (type1 == An || type1 == Dn) n1 = src[0]; 
		if (type2 == An || type2 == Dn) n2 = dst[0]; 
 
		// 実行 
		op = NOTFOUND; 
 
		switch (opcode[0]) 
		{ 
		case 'a': 
			if (OPCODE("add") || OPCODE("addi")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_add(value1, value2, size); 
				X = C; 
 
				op = SET2; 
			} 
			else if (OPCODE("adda")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, SIZE_L); 
 
				if (size == SIZE_W && type1 != An) 
					value1 = MAKE_INT_16(value1); 
 
				result = value2 + value1; 
 
				LOG(("%06x + %08x (=%06x) -> ", value2, value1, result)); 
 
				op = SET2; 
			} 
			else if (OPCODE("addq")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				if (type2 == An) 
				{ 
					if (size == SIZE_W && type1 != An) 
						value1 = MAKE_INT_16(value1); 
 
					result = value2 + value1; 
 
					LOG(("%06x + %08x (=%06x) -> ", value2, value1, result)); 
				} 
				else 
				{ 
					result = op_add(value1, value2, size); 
					X = C; 
				} 
 
				op = SET2; 
			} 
			else if (OPCODE("addx")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_add(value1 + X, value2, size); 
				X = C; 
 
				op = SET2; 
			} 
			else if (OPCODE("and") || OPCODE("andi")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_and(value1, value2, size); 
 
				op = SET2; 
			} 
			else if (OPCODE("asl")) 
			{ 
				UINT32 msb_bit1, msb_bit2; 
 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					msb_bit1 = result & msb; 
					X = C = (result & (msb >> (value1 - 1))) != 0; 
 
					msb_bit2 = msb_bit1; 
 
					for (i = 0; i < value1; i++) 
					{ 
						result = (result << 1) & mask; 
						V = (msb_bit2 != (result & msb)); 
						msb_bit2 = result & msb; 
					} 
 
					result = (result & ~msb) | msb_bit1; 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x << %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x << %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x << %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
 
				op = SET2; 
			} 
			else if (OPCODE("asr")) 
			{ 
				UINT32 msb_bit1, msb_bit2; 
 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					msb_bit1 = result & msb; 
					X = C = (result & (1 << (value1 - 1))) != 0; 
 
					msb_bit2 = msb_bit1; 
 
					for (i = 0; i < value1; i++) 
					{ 
						result = (result >> 1) & mask; 
						V = (msb_bit2 != (result & msb)); 
						msb_bit2 = result & msb; 
					} 
 
					result = (result & ~msb) | msb_bit1; 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x >> %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x >> %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x >> %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
 
				op = SET2; 
			} 
			break; 
 
		case 'b': 
			if (OPCODE("bchg") || OPCODE("bclr") || OPCODE("bset") || OPCODE("btst")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
 
					value1 %= 32; 
 
					Z = (value2 & (1 << value1)) == 0; 
 
					LOG(("%08x & bit%d -> Z (= %d)", value2, value1, Z)); 
				} 
				else 
				{ 
					size = SIZE_B; 
					mask = 0x000000ff; 
					msb  = 0x00000080; 
 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
 
					value1 %= 8; 
 
					Z = (value2 & (1 << value1)) == 0; 
 
					LOG(("%02x & bit%d -> Z (= %d)", value2, value1, Z)); 
				} 
 
				if (opcode[2] != 's') 
				{ 
					switch (opcode[2]) 
					{ 
					case 'h':	// bchg 
						result = value2 ^ (value2 & (1 << value1)); 
						break; 
 
					case 'l':	// bclr 
						result = value2 & ~(value2 & (1 << value1)); 
						break; 
 
					case 'e':	// bset 
						result = value2 | (value2 & (1 << value1)); 
						break; 
					} 
					LOG((", %08x -> ", result)); 
 
					op = SET2; 
				} 
				else 
				{ 
					LOG(("\n")); 
					op = OTHER;	// TEST 
				} 
			} 
			else if (OPCODE("bsr")) 
			{ 
				nest_pc[nest_count++] = pc + opcode_len; 
				pc = (pc + 2) + MAKE_INT_16(get_imm(src, SIZE_W)); 
				LOG(("(branch to sub routine %06x)\n\n", pc)); 
				continue; 
			} 
			else if (OPCODE("bra") || OPCODE("bf")) 
			{ 
				pc = (pc + 2) + MAKE_INT_16(get_imm(src, SIZE_W)); 
				LOG(("(branch to %06x)\n", pc)); 
				continue; 
			} 
			else if (OPCODE("bcc") || OPCODE("bcs") || OPCODE("beq") || OPCODE("bge") || 
					 OPCODE("bgt") || OPCODE("bhi") || OPCODE("ble") || OPCODE("bls") || 
					 OPCODE("blt") || OPCODE("bmi") || OPCODE("bne") || OPCODE("bpl") || 
					 OPCODE("bvc") || OPCODE("bvs") || OPCODE("bt")) 
			{ 
				switch (opcode[1]) 
				{ 
				case 'e': result = EQ; break; 
				case 'h': result = HI; break; 
				case 'm': result = MI; break; 
				case 'n': result = NE; break; 
				case 'p': result = PL; break; 
				case 't': result = 1; break; 
 
				case 'c': result = (opcode[2] == 'c') ? CC : CS; break; 
				case 'g': result = (opcode[2] == 'e') ? GE : GT; break; 
				case 'v': result = (opcode[2] == 'c') ? VC : VS; break; 
 
				case 'l': 
					switch (opcode[2]) 
					{ 
					case 'e': result = LE; break; 
					case 's': result = LS; break; 
					case 't': result = LT; break; 
					} 
					break; 
				} 
 
				if (result) 
				{ 
					pc = (pc + 2) + MAKE_INT_16(get_imm(src, SIZE_W)); 
					LOG(("(branch to %06x)\n", pc)); 
					continue; 
				} 
				LOG(("(pass)\n")); 
 
				op = OTHER; 
			} 
			break; 
 
		case 'c': 
			if (OPCODE("clr")) 
			{ 
				get_value1(src, type1, size); 
 
				result = 0; 
 
				C = 0; 
				Z = 1; 
				N = 0; 
				V = 0; 
#if VERBOSE 
				switch (size) 
				{ 
				case 1: LOG(("%02x -> %02x ", value1, 0)); break; 
				case 2: LOG(("%04x -> %04x ", value1, 0)); break; 
				case 4: LOG(("%08x -> %08x ", value1, 0)); break; 
				} 
#endif 
				op = SET1; 
			} 
			else if (OPCODE("cmp") || OPCODE("cmpi") || OPCODE("cmpm")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				op_sub(value1, value2, size); 
 
				op = TEST; 
			} 
			else if (OPCODE("cmpa")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				if (size == SIZE_W && type1 != An) 
					value1 = MAKE_INT_16(value1); 
 
				op_sub(value1, value2, SIZE_L); 
 
				op = TEST; 
			} 
			break; 
 
		case 'd': 
			if (OPCODE("dbra") || OPCODE("dbf")) 
			{ 
				get_value1(src, type1, SIZE_W); 
				value1 -= 1; 
				value1 &= 0xffff; 
				set_d(n1, value1, SIZE_W); 
 
				if (value1 != 0xffff) 
				{ 
					pc = (pc + 2) + MAKE_INT_8(get_imm(dst, SIZE_B)); 
					LOG(("--D%d = %04x (branch to %06x)\n", src[0], value1, pc)); 
					continue; 
				} 
				LOG(("--D%d = %04x (pass)\n", src[0], value1)); 
 
				op = OTHER; 
			} 
			else if (OPCODE("dbcc") || OPCODE("dbcs") || OPCODE("dbeq") || OPCODE("dbge") || 
					 OPCODE("dbgt") || OPCODE("dbhi") || OPCODE("dble") || OPCODE("dbls") || 
					 OPCODE("dblt") || OPCODE("dbmi") || OPCODE("dbne") || OPCODE("dbpl") || 
					 OPCODE("dbvc") || OPCODE("dbvs") || OPCODE("dbt")) 
			{ 
				switch (opcode[2]) 
				{ 
				case 'e': result = EQ; break; 
				case 'h': result = HI; break; 
				case 'm': result = MI; break; 
				case 'n': result = NE; break; 
				case 'p': result = PL; break; 
				case 't': result = 1; break; 
 
				case 'c': result = (opcode[3] == 'c') ? CC : CS; break; 
				case 'g': result = (opcode[3] == 'e') ? GE : GT; break; 
				case 'v': result = (opcode[3] == 'c') ? VC : VS; break; 
 
				case 'l': 
					switch (opcode[3]) 
					{ 
					case 'e': result = LE; break; 
					case 's': result = LS; break; 
					case 't': result = LT; break; 
					} 
					break; 
				} 
 
				if (!result) 
				{ 
					get_value1(src, type1, SIZE_W); 
					value1 -= 1; 
					value1 &= 0xffff; 
					set_d(n1, value1, SIZE_W); 
 
					if (value1 != 0xffff) 
					{ 
						pc = (pc + 2) + MAKE_INT_8(get_imm(dst, SIZE_B)); 
						LOG(("--D%d = %04x (branch to %06x)\n", n1, value1, pc)); 
						continue; 
					} 
 
					LOG(("--D%d = %04x (pass)\n", n1, value1)); 
				} 
#if VERBOSE 
				else 
				{ 
					LOG(("D%d = %04x (pass)\n", n1, get_d(n1, SIZE_W))); 
				} 
#endif 
 
				op = OTHER; 
			} 
			else if (OPCODE("divu")) 
			{ 
				get_value1(src, type1, SIZE_W); 
				get_value2(dst, type2, size); 
 
				if (value1 != 0) 
				{ 
					int modulo; 
 
#if VERBOSE 
					switch (size) 
					{ 
					case SIZE_W: LOG(("%04x / %04x ", value2, value1)); break; 
					case SIZE_L: LOG(("%08x / %04x ", value2, value1)); break; 
					} 
#endif 
					switch (type2) 
					{ 
					case Dn: 
						result = (value2 / value1) & 0xffff; 
						modulo = (value2 % value1) & 0xffff; 
						set_d(n2, (modulo << 16) | result, 4); 
						LOG(("(=%04x, modulo=%04x) -> D%d\n", result, modulo, n2)); 
						break; 
 
					default: 
						result = (value2 / value1) & 0xffff; 
						modulo = (value2 % value1) & 0xffff; 
						write_ea(addr2, (modulo << 16) | result, 4); 
						LOG(("(=%04x, modulo=%04x) -> %06x\n", result, modulo, addr2)); 
						break; 
					} 
 
					C = 0; 
					Z = ZFLAG(result, 2); 
					N = NFLAG(result, 2); 
					V = 0; 
 
					op = OTHER;	// SET2 
				} 
				else 
				{ 
					LOG(("(divide by zero)\n")); 
					op = INVALID; 
				} 
			} 
			else if (OPCODE("divs")) 
			{ 
				get_value1(src, type1, SIZE_W); 
				get_value2(dst, type2, size); 
 
				value1 = MAKE_INT_16(value1); 
 
				if (value1 != 0) 
				{ 
					int modulo; 
#if VERBOSE 
					switch (size) 
					{ 
					case SIZE_W: LOG(("%04x / %04x ", value2, value1 & 0xffff)); break; 
					case SIZE_L: LOG(("%08x / %04x ", value2, value1 & 0xffff)); break; 
					} 
#endif 
					switch (type2) 
					{ 
					case Dn: 
						result = (value2 / value1) & 0xffff; 
						modulo = (value2 % value1) & 0xffff; 
						set_d(n2, (modulo << 16) | result, 4); 
						LOG(("(=%04x, modulo=%04x) -> D%d\n", result, modulo, n2)); 
						break; 
 
					default: 
						result = (value2 / value1) & 0xffff; 
						modulo = (value2 % value1) & 0xffff; 
						write_ea(addr2, (modulo << 16) | result, 4); 
						LOG(("(=%04x, modulo=%04x) -> %06x\n", result, modulo, addr2)); 
						break; 
					} 
 
					C = 0; 
					Z = ZFLAG(result, 2); 
					N = NFLAG(result, 2); 
					V = 0; 
 
					op = OTHER;	// SET2 
				} 
				else 
				{ 
					LOG(("(divide by zero)\n")); 
					op = INVALID; 
				} 
			} 
			break; 
 
		case 'e': 
			if (OPCODE("eor") || OPCODE("eori")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_eor(value1, value2, size); 
 
				op = SET2; 
			} 
			else if (OPCODE("exg")) 
			{ 
				switch (type2) 
				{ 
				case An: 
					switch (type1) 
					{ 
					case An: 
						value1 = a[n1]; 
						a[n1] = a[n2]; 
						a[n2] = value1; 
						LOG(("A%d <--> A%d\n", opcode, n1, n2)); 
						break; 
 
					case Dn: 
						value1 = d[n1]; 
						d[n1] = a[n2]; 
						a[n2] = value1; 
						LOG(("D%d <--> A%d\n", n1, n2)); 
						break; 
					} 
					break; 
 
				case Dn: 
					switch (type1) 
					{ 
					case An: 
						value1 = a[n1]; 
						a[n1] = d[n2]; 
						d[n2] = value1; 
						LOG(("A%d <--> D%d\n", opcode, n1, n2)); 
						break; 
 
					case Dn: 
						value1 = d[n1]; 
						d[n1] = d[n2]; 
						d[n2] = value1; 
						LOG(("D%d <--> D%d\n", n1, n2)); 
						break; 
					} 
					break; 
				} 
 
				op = OTHER; 
			} 
			else if (OPCODE("ext")) 
			{ 
				get_value1(src, type1, size); 
 
				switch (size) 
				{ 
				case SIZE_B: 
					result = MAKE_INT_8(value1); 
					LOG(("%s\t%02x -> %04x ", opcode, value1, result & 0xffff)); 
					break; 
 
				case SIZE_W: 
					result = MAKE_INT_16(value1); 
					LOG(("%s\t%04x -> %08x ", opcode, value1, result)); 
					break; 
				} 
 
				size *= 2; 
 
				C = 0; 
				Z = ZFLAG(value1, size); 
				N = NFLAG(value1, size); 
				V = 0; 
 
				op = SET1; 
			} 
			break; 
 
		case 'j': 
			if (OPCODE("jmp")) 
			{ 
				pc = get_ea(src, a, d, type1, size); 
				LOG(("06x\n", pc)); 
				continue; 
			} 
			else if (OPCODE("jsr")) 
			{ 
				nest_pc[nest_count++] = pc + opcode_len; 
				pc = get_ea(src, a, d, type1, size); 
				LOG(("%06x\n\n", pc)); 
				continue; 
			} 
			break; 
 
		case 'l': 
			if (OPCODE("lea")) 
			{ 
				get_value1(src, type1, SIZE_L); 
 
				result = addr1; 
 
				LOG(("%06x -> ", result)); 
 
				op = SET2; 
			} 
			else if (OPCODE("lsl")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					X = C = (result & (msb >> (value1 - 1))) != 0; 
 
					for (i = 0; i < value1; i++) 
						result = (result << 1) & mask; 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x << %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x << %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x << %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			else if (OPCODE("lsr")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					X = C = (result & (1 << (value1 - 1))) != 0; 
 
					for (i = 0; i < value1; i++) 
						result = (result >> 1) & mask; 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x >> %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x >> %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x >> %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			break; 
 
		case 'm': 
			if (OPCODE("move")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				switch (type2) 
				{ 
				case An: 
					LOG(("(Illigal)\n")); 
					break; 
 
				case Dn: 
					set_d(n2, value1, size); 
#if VERBOSE 
					result = get_d(n2, SIZE_L); 
					switch (size) 
					{ 
					case SIZE_B: LOG(("%02x -> D%d (=%08x)\n", value1, n2, result)); break; 
					case SIZE_W: LOG(("%04x -> D%d (=%08x)\n", value1, n2, result)); break; 
					case SIZE_L: LOG(("%08x -> D%d (=%08x)\n", value1, n2, result)); break; 
					} 
#endif 
					break; 
 
				case CCR: 
					C = value1 & (1 << 0); 
					V = value1 & (1 << 1); 
					Z = value1 & (1 << 2); 
					N = value1 & (1 << 3); 
					X = value1 & (1 << 4); 
					LOG(("%04x -> CCR (XZNVC = %d%d%d%d%d)\n", value1, X, Z, N, V, C)); 
					break; 
 
				case SR: 
					sr = value1; 
					C = sr & (1 << 0); 
					V = sr & (1 << 1); 
					Z = sr & (1 << 2); 
					N = sr & (1 << 3); 
					X = sr & (1 << 4); 
					LOG(("%04x -> SR (=%04x)\n", value1)); 
					break; 
 
				default: 
					write_ea(addr2, value1, size); 
#if VERBOSE 
					switch (size) 
					{ 
					case SIZE_B: LOG(("%02x -> %06x\n", value1, addr2)); break; 
					case SIZE_W: LOG(("%04x -> %06x\n", value1, addr2)); break; 
					case SIZE_L: LOG(("%08x -> %06x\n", value1, addr2)); break; 
					} 
					break; 
#endif 
				} 
 
				C = 0; 
				Z = ZFLAG(value1, size); 
				N = NFLAG(value1, size); 
				V = 0; 
 
				op = OTHER; // SET2 
			} 
			else if (OPCODE("movea")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, SIZE_L); 
 
				if (size == SIZE_W) 
					value1 = MAKE_INT_16(value1); 
 
				result = value1; 
 
				LOG(("%08x -> ", result)); 
 
				op = SET2; 
			} 
			else if (OPCODE("movem")) 
			{ 
				int i, n; 
				char *p; 
 
				p = (type1 == MM) ? src : dst; 
				i = 0; 
 
				if (type1 == MM) 
				{ 
					if (type2 == PD7) 
					{ 
						LOG(("%s -> -(A7)\n", src)); 
 
						if (p[0] == 'A') 
						{ 
							i = 1; 
							while (p[i]) 
							{ 
								if (p[i] == '/') 
								{ 
									i++; 
									break; 
								} 
 
								n = p[i] - '0'; 
								a[7] -= SIZE_L; 
								write_ea(a[7], a[n], SIZE_L); 
								i++; 
							} 
						} 
						if (p[i] == 'D') 
						{ 
							i++; 
							while (p[i]) 
							{ 
								n = p[i] - '0'; 
								a[7] -= SIZE_L; 
								write_ea(a[7], d[n], SIZE_L); 
								i++; 
							} 
						} 
					} 
					else 
					{ 
						addr2 = get_ea(dst, a, d, type2, size); 
 
						LOG(("%s -> %06x\n", src, addr2)); 
 
						if (p[0] == 'D') 
						{ 
							i = 1; 
 
							while (p[i]) 
							{ 
								if (p[i] == '/') 
								{ 
									i++; 
									break; 
								} 
 
								n = p[i] - '0'; 
								write_ea(addr2, d[n], size); 
								addr2 += size; 
								i++; 
							} 
						} 
						if (p[i] == 'A') 
						{ 
							i++; 
							while (p[i]) 
							{ 
								n = p[i] - '0'; 
								write_ea(addr2, a[n], size); 
								addr2 += size; 
								i++; 
							} 
						} 
					} 
				} 
				else 
				{ 
					if (type2 == PI7) 
					{ 
						LOG(("(A7)+ -> %s\n", dst)); 
 
						if (p[0] == 'D') 
						{ 
							i = 1; 
							while (p[i]) 
							{ 
								if (p[i] == '/') 
								{ 
									i++; 
									break; 
								} 
 
								n = p[i] - '0'; 
								d[n] = read_ea(a[7], SIZE_L); 
								a[7] += SIZE_L; 
								i++; 
							} 
						} 
						if (p[i] == 'A') 
						{ 
							i++; 
							while (p[i]) 
							{ 
								n = p[i] - '0'; 
								a[n] = read_ea(a[7], SIZE_L); 
								a[7] += SIZE_L; 
								i++; 
							} 
						} 
					} 
					else 
					{ 
						addr1 = get_ea(src, a, d, type1, size); 
 
						LOG(("%06x -> %s\n",  addr1, dst)); 
 
						if (p[0] == 'D') 
						{ 
							i++; 
							while (p[i]) 
							{ 
								if (p[i] == '/') 
								{ 
									i++; 
									break; 
								} 
 
								n = p[i] - '0'; 
								value1 = read_ea(addr1, size); 
								d[n] = (d[n] & ~mask) | value1; 
								addr1 += size; 
								i++; 
							} 
						} 
						if (p[i] == 'A') 
						{ 
							i++; 
							while (p[i]) 
							{ 
								n = p[i] - '0'; 
								value1 = read_ea(addr1, size); 
								a[n] = (a[n] & ~mask) | value1; 
								addr1 += size; 
								i++; 
							} 
						} 
					} 
				} 
				op = OTHER; 
			} 
			else if (OPCODE("moveq")) 
			{ 
				get_value1(src, type1, size); 
				result = MAKE_INT_8(value1); 
				set_d(n2, result, SIZE_L); 
 
				C = 0; 
				Z = ZFLAG(result, SIZE_L); 
				N = NFLAG(result, SIZE_L); 
				V = 0; 
 
				LOG(("%02x -> D%d (=%08x)\n", value1, n2, result)); 
 
				op = OTHER;	// SET2 
			} 
			else if (OPCODE("mulu")) 
			{ 
				get_value1(src, type1, SIZE_W); 
				get_value2(dst, type2, SIZE_W); 
 
				result = value1 * value2; 
 
				LOG(("%04x * %04x (=%08x) ->", value1, value2, result)); 
 
				size *= 2; 
 
				C = 0; 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			else if (OPCODE("muls")) 
			{ 
				get_value1(src, type1, SIZE_W); 
				get_value2(dst, type2, SIZE_W); 
 
				value1 = MAKE_INT_16(value1); 
				value2 = MAKE_INT_16(value2); 
 
				result = value1 * value2; 
 
				LOG(("%04x * %04x (=%08x) ->", value1 & 0xffff, value2 & 0xffff, result)); 
 
				size *= 2; 
 
				C = 0; 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			break; 
 
		case 'n': 
			if (OPCODE("nop")) 
			{ 
				LOG(("\n")); 
				op = OTHER; 
			} 
			else if (OPCODE("neg")) 
			{ 
				get_value1(src, type1, size); 
 
				result = op_sub(value1, 0, size); 
 
				op = SET1; 
			} 
			else if (OPCODE("negx")) 
			{ 
				get_value1(src, type1, size); 
 
				result = op_sub(value1 - X, 0, size); 
 
				op = SET1; 
			} 
			else if (OPCODE("not")) 
			{ 
				get_value1(src, type1, size); 
 
				result = (~value1) & mask; 
#if VERBOSE 
				switch (size) 
				{ 
				case 1: LOG(("~%02x (=%02x) -> ", value1, result)); break; 
				case 2: LOG(("~%04x (=%02x) -> ", value1, result)); break; 
				case 4: LOG(("~%08x (=%02x) -> ", value1, result)); break; 
				} 
#endif 
				C = 0; 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET1; 
			} 
			break; 
 
		case 'o': 
			if (OPCODE("or") || OPCODE("ori")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_or(value1, value2, size); 
 
				op = SET2; 
			} 
			break; 
 
		case 'r': 
			if (OPCODE("rts")) 
			{ 
				if (nest_count == 0) 
				{ 
					pc = break_point; 
					LOG(("(break)\n")); 
					continue; 
				} 
				else 
				{ 
					pc = nest_pc[--nest_count]; 
					LOG(("(return to %06x)\n\n", pc)); 
					continue; 
				} 
			} 
			else if (OPCODE("rol")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					for (i = 0; i < value1; i++) 
					{ 
						C = (result & 1) != 0; 
						result = ((result << 1) & mask) | C; 
					} 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x << %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x << %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x << %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			else if (OPCODE("ror")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					for (i = 0; i < value1; i++) 
					{ 
						C = (result & 1) != 0; 
						result = ((result >> 1) & mask) | (C * msb); 
					} 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x >> %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x >> %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x >> %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			else if (OPCODE("roxl")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					C = 0; 
				} 
				else 
				{ 
					for (i = 0; i < value1; i++) 
					{ 
						C = (result & 1) != 0; 
						result = ((result << 1) & mask) | X; 
						X = C; 
					} 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x << %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x << %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x << %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			else if (OPCODE("roxr")) 
			{ 
				if (type2 == Dn) 
				{ 
					get_value1(src, type1, size); 
					get_value2(dst, type2, size); 
				} 
				else 
				{ 
					size = SIZE_W; 
					mask = 0x0000ffff; 
					msb = 0x00008000; 
					value1 = 1; 
					get_value2(src, type1, size); 
				} 
 
				result = value2; 
 
				if (value1 == 0) 
				{ 
					X = C = 0; 
				} 
				else 
				{ 
					for (i = 0; i < value1; i++) 
					{ 
						C = (result & 1) != 0; 
						result = ((result >> 1) & mask) | (X * msb); 
						X = C; 
					} 
				} 
#if VERBOSE 
				switch (size) 
				{ 
				case SIZE_B: LOG(("%02x >> %d (=%02x) -> ", value2, value1, result)); break; 
				case SIZE_W: LOG(("%04x >> %d (=%04x) -> ", value2, value1, result)); break; 
				case SIZE_L: LOG(("%08x >> %d (=%08x) -> ", value2, value1, result)); break; 
				} 
#endif 
				Z = ZFLAG(result, size); 
				N = NFLAG(result, size); 
				V = 0; 
 
				op = SET2; 
			} 
			break; 
 
		case 's': 
			if (OPCODE("sub") || OPCODE("subi")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_sub(value1, value2, size); 
				X = C; 
 
				op = SET2; 
			} 
			else if (OPCODE("suba")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, SIZE_L); 
 
				if (size == SIZE_W) 
					value1 = MAKE_INT_16(value1); 
 
				result = value2 - value1; 
 
				LOG(("%06x - %06x (=%06x) -> ", value2, value1, result)); 
 
				op = SET2; 
			} 
			else if (OPCODE("subq")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				if (type2 == An) 
				{ 
					if (size == SIZE_W) 
						value1 = MAKE_INT_16(value1); 
 
					result = value2 - value1; 
 
					LOG(("%06x - %08x (=%06x) -> ", value2, value1, result)); 
				} 
				else 
				{ 
					result = op_sub(value1, value2, size); 
					X = C; 
				} 
 
				op = SET2; 
			} 
			else if (OPCODE("subx")) 
			{ 
				get_value1(src, type1, size); 
				get_value2(dst, type2, size); 
 
				result = op_sub(value1 - X, value2, size); 
				X = C; 
 
				op = SET2; 
			} 
			else if (OPCODE("swap")) 
			{ 
				get_value1(src, type1, SIZE_L); 
				value2 = (value1 & 0xffff0000) >> 16; 
				result = (value1 & 0x0000ffff) << 16; 
				result |= value2; 
				LOG(("D%d %08x -> D%d %08x\n", n1, value1, n1, result)); 
				set_d(n1, result, SIZE_L); 
 
				op = OTHER; 
			} 
			else if (OPCODE("scc") || OPCODE("scs") || OPCODE("seq") || OPCODE("sge") || 
					 OPCODE("sgt") || OPCODE("shi") || OPCODE("sle") || OPCODE("sls") || 
					 OPCODE("slt") || OPCODE("smi") || OPCODE("sne") || OPCODE("spl") || 
					 OPCODE("svc") || OPCODE("svs") || OPCODE("st")  || OPCODE("sf")) 
			{ 
				size = SIZE_B; 
				get_value1(src, type1, size); 
 
				switch (opcode[1]) 
				{ 
				case 'e': result = EQ; break; 
				case 'h': result = HI; break; 
				case 'm': result = MI; break; 
				case 'n': result = NE; break; 
				case 'p': result = PL; break; 
				case 't': result = 1; break; 
				case 'f': result = 0; break; 
 
				case 'c': result = (opcode[2] == 'c') ? CC : CS; break; 
				case 'g': result = (opcode[2] == 'e') ? GE : GT; break; 
				case 'v': result = (opcode[2] == 'c') ? VC : VS; break; 
 
				case 'l': 
					switch (opcode[2]) 
					{ 
					case 'e': result = LE; break; 
					case 's': result = LS; break; 
					case 't': result = LT; break; 
					} 
					break; 
				} 
 
				result = (result != 0) ? 0xff : 0; 
				LOG(("%02x -> ", result)); 
 
				op = SET1; 
			} 
			break; 
 
		case 't': 
			if (OPCODE("tst")) 
			{ 
				get_value1(src, type1, size); 
				op_and(mask, value1, size); 
				op = TEST; 
			} 
			break; 
		} 
 
		// 結果 
		switch (op) 
		{ 
		case NOTFOUND: 
			LOG(("not inplemented.\n")); 
			break; 
 
		case SET1: 
			switch (type1) 
			{ 
			case An: 
				set_a(n1, result); 
				LOG(("A%d\n", n1)); 
				break; 
 
			case Dn: 
				set_d(n1, result, size); 
				LOG(("D%d\n", n1)); 
				break; 
 
			default: 
				write_ea(addr1, result, size); 
				LOG(("$%06x\n", addr1)); 
				break; 
			} 
			break; 
 
		case SET2: 
			switch (type2) 
			{ 
			case An: 
				set_a(n2, result); 
				LOG(("A%d\n", n2)); 
				break; 
 
			case CCR: 
				C = value1 & (1 << 0); 
				V = value1 & (1 << 1); 
				Z = value1 & (1 << 2); 
				N = value1 & (1 << 3); 
				X = value1 & (1 << 4); 
				LOG(("CCR\n")); 
				break; 
 
			case Dn: 
				set_d(n2, result, size); 
				LOG(("D%d\n", n2)); 
				break; 
 
			default: 
				write_ea(addr2, result, size); 
				LOG(("$%06x\n", addr2)); 
				break; 
			} 
			break; 
 
		case TEST: 
			LOG(("CCR (XVNZC = %d%d%d%d%d)\n", X, V, N, Z, C)); 
			break; 
 
		default: 
			break; 
		} 
 
		pc += opcode_len; 
	} 
 
	LOG(("-- end --\n\n")); 
}