File:  [Isaki's NoNo m68k/m88k emulator] / nono / m680x0 / m68030ea.cpp
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:26 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v020, HEAD
nono 1.0.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

// EA は大別して5種類。
//
// |d m  rxwp |	制御	CalcCtrl		サイズ不問
// |dam+-rxw  |	可変	CalcData		B/W/L
// |  m  rxwp |	MMU		CalcMMU			サイズ不問
// |dam+-rxwpi|	FPU		CalcFPU			B/W/L/S/D/X/P
// |d m+-rxwpi|	データ	FetchData		B/W/L
// |dam+-rxwpi|	All		FetchAll		B/W/L
//
// CalcCtrl はユーザーズマニュアルで「制御(Control)」と呼ばれている
// グループで、デスティネーション側のため EA の計算のみ。
// また (An)+/-(An) を含まないため、サイズに関係なく1種類だけでよい。
//
// CalcData はユーザーズマニュアルで「可変」と呼ばれているグループで、
// デスティネーション側のため EA の計算のみ。サイズは B/W/L。
// (An)+/-(An) ならレジスタを保存する。
//
// CalcMMU は対 MMU 用に勝手に用意したもの。
//
// CalcFPU は対 FPU 用。ソースであっても CalcFPU を使用する。
// サイズは B/W/L/S/D/X/P。
// (An)+/-(An) ならレジスタを保存する。
// フェッチサイクルは別途存在するはずだが不詳。
//
// FetchData はユーザーズマニュアルで「データ(Data)」と呼ばれている
// グループで、ソース側のため EA 計算および値の取得。サイズは B/W/L。
// (An)+/-(An) ならレジスタを保存する。
//
// FetchAll はユーザーズマニュアルのここには記載がないグループで、
// ソース側のため EA 計算および値の取得。サイズは B/W/L。
// (An)+/-(An) ならレジスタを保存する。
//
// CalcCtrl、CalcData でアドレッシングモードに D や A が含まれている場合は
// その命令のデスティネーションに Dn、An が指定できるという意味であり、
// EA 処理であるここには関係ない。
// EA 計算より前に呼出側で条件分けして処理すること。
//
// CalcCtrl、CalcData と FetchData には (*) 印の例外があるので留意。
//
// (CalcCtrl)
// |  m  rxwp | CMP2/CHK2
// |  m  rxwp | JMP/JSR
// |  m  rxwp | LEA/PEA
// |d m  rxwp | BFEXT*/BFFFO/BFTST
// |d m  rxw  | (*) BFCHG/BFCLR/BFINS/BFSET <ea>{#o:#w}
//
// (CalcData)
// |  m+-rxw  | ADD/SUB/CMP Dx,<ea>
// |  m+-rxw  | CAS/TAS <ea>
// |  m+-rxw  | MOVES <ea>,Rn
// |  m+-rxw  | shift/rotate.W <ea>
// |  m+-rxw  | BCHG/BCLR/BSET src,<ea>
// |d m+-rxw  | ADDI/SUBI Dx,<ea>
// |d m+-rwx  | NBCD <ea>
// |d m+-rxw  | AND/OR/EOR Dx,<ea>
// |d m+-rxw  | CLR/NEG/NEGX/NOT/TST/Scc <ea>
// |d m+-rxw  | MOVE CCR/SR,<ea>
// |dam+-rxw  | ADDQ/SUBQ #qqq,<ea>
// |dam+-rxw  | (*) MOVE の dst 側。EA の分類的には CalcData だが、
//              下位6ビットの IR ではないので、cea_data_NN() ではなく
//              各々 cea_XXXX() のほうを個別に呼ぶこと。
//
// (CalcMMU)
// |  m  rxw  | MMU
//
// (CalcFPU)
// |d m+-rxw  | FScc.B <ea>
// |dam+-rxw  | FMOVE.f FPn,<ea>
// |dam+-rxw  | FMOVE.L ctl,<ea>
// |dam+-rxw  | FMOVEM.L ctl,<ea>
// |d m+-rxwpi| Fgen <ea>,FPn
// |d m+-rxwpi| FMOVE.f <ea>,FPn
// |dam+-rwxpi| FMOVE.L <ea>,ctl
// |dam+-rxwpi| FMOVEM.L <ea>,ctl
// 実際にどのアドレッシングモードが有効かどうかは極力個別の命令内で判断する?
// ここは実行サイクル数的な分類。
//
// (FetchData)
// |d m+-rxwpi| AND/OR/CHK <ea>,Dn
// |d m+-rxwpi| MOVE.B <ea>,dst
// |d m+-rxwpi| MOVE <ea>,CCR/SR
// |d m+-rxwpi| MUL*/DIV* <ea>,Dn
// |d m+-rxwp | (*) TST.B <ea>
// |d m+-rxwp | (*) CMPI #<data>,<ea>
// |  m+-rxwp | (*) BTST.B #<data>,<ea>
// |  m+-rxwpi| (*) BTST.B Dx,<ea>
//
// (FetchAll)
// |dam+-rxwpi| ADD/SUB/CMP <ea>,Dn
// |dam+-rxwpi| MOVEA/ADDA/SUBA/CMPA <ea>,An
// |dam+-rxwpi| TST.WL <ea>
// |dam+-rxwpi| MOVE.WL <ea>,dst
//
// (たぶん別対応)
// |  m -rxw  | MOVEM list,<ea>
// |  m -rxw  | FMOVEM.X reg,<ea>
// |  m -rxw  | FSAVE <ea>
// |  m+ rxwp | MOVEM <ea>,list
// |  m+ rxwp | FMOVEM.X <ea>,reg
// |  m+ rxwp | FRESTORE <ea>

#include "mpu680x0.h"

//
// Calc EA
//

// 個別 EA は (An)+/-(An) でもレジスタを保存しない。
// 自動的に保存する cea_data() 等を介さずこれらを呼ぶ時は
// レジスタ保存のタイミングや回数に注意すること。

uint32
MPU680x0Device::cea_anin(uint n)
{
	CYCLE(2);
	return internal_ea_anin(n);
}

uint32
MPU680x0Device::cea_anpi_1(uint n)
{
	CYCLE(2);
	return internal_ea_anpi_1(n);
}

uint32
MPU680x0Device::cea_anpi_2(uint n)
{
	CYCLE(2);
	return internal_ea_anpi_2(n);
}

uint32
MPU680x0Device::cea_anpi_4(uint n)
{
	CYCLE(2);
	return internal_ea_anpi_4(n);
}

uint32
MPU680x0Device::cea_anpd_1(uint n)
{
	CYCLE(2);
	return internal_ea_anpd_1(n);
}

uint32
MPU680x0Device::cea_anpd_2(uint n)
{
	CYCLE(2);
	return internal_ea_anpd_2(n);
}

uint32
MPU680x0Device::cea_anpd_4(uint n)
{
	CYCLE(2);
	return internal_ea_anpd_4(n);
}

uint32
MPU680x0Device::cea_andi(uint n)
{
	CYCLE(2);
	return internal_ea_andi(n);
}

uint32
MPU680x0Device::cea_anix(uint n)
{
	CYCLE(10);	// XXX 4,4-18,20
	return internal_ea_anix(n);
}

uint32
MPU680x0Device::cea_absw()
{
	CYCLE(2);
	return internal_ea_absw();
}

uint32
MPU680x0Device::cea_absl()
{
	CYCLE(4);
	return internal_ea_absl();
}

uint32
MPU680x0Device::cea_pcdi()
{
	CYCLE(2);
	return internal_ea_pcdi();
}

uint32
MPU680x0Device::cea_pcix()
{
	CYCLE(10);	// XXX 4,4-18,20
	return internal_ea_pcix();
}

//
// Fetch EA
//

inline uint32
MPU680x0Device::fea_anin()
{
	CYCLE(3);
	return internal_ea_anin(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpi_1()
{
	CYCLE(3);
	return internal_ea_anpi_1(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpi_2()
{
	CYCLE(3);
	return internal_ea_anpi_2(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpi_4()
{
	CYCLE(3);
	return internal_ea_anpi_4(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpd_1()
{
	CYCLE(4);
	return internal_ea_anpd_1(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpd_2()
{
	CYCLE(4);
	return internal_ea_anpd_2(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anpd_4()
{
	CYCLE(4);
	return internal_ea_anpd_4(eanum(ir));
}

inline uint32
MPU680x0Device::fea_andi()
{
	CYCLE(4);
	return internal_ea_andi(eanum(ir));
}

inline uint32
MPU680x0Device::fea_anix()
{
	CYCLE2(12, 14);	// XXX 6,6-18,21
	return internal_ea_anix(eanum(ir));
}

inline uint32
MPU680x0Device::fea_absw()
{
	CYCLE(4);
	return internal_ea_absw();
}

inline uint32
MPU680x0Device::fea_absl()
{
	CYCLE2(4, 5);
	return internal_ea_absl();
}

inline uint32
MPU680x0Device::fea_pcdi()
{
	CYCLE(4);
	return internal_ea_pcdi();
}

inline uint32
MPU680x0Device::fea_pcix()
{
	CYCLE2(12, 14);	// XXX 6,6-18,21
	return internal_ea_pcix();
}

inline void
MPU680x0Device::fea_imm_2()
{
	CYCLE(2);
}

inline void
MPU680x0Device::fea_imm_4()
{
	CYCLE(4);
}

//
// EA の拡張ワード
//

uint32
MPU680x0Device::internal_ea_ix(uint32 anpc)
{
	uint16 ext = fetch_2();
	uint rn = (ext >> 12) & 15;
	bool idx_long = (ext & 0x0800);
	uint scale = (ext >> 9) & 3;

	if ((ext & 0x0100) == 0) {
		// Brief extension
		//
		//   F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0
		// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
		// | DA|     n     | WL| SCALE | 0 |             disp              |
		// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
		//
		// WL: インデックスレジスタ(Rn)のサイズ 1=.L 0=.W
		// SCALE: スケールファクタ %00=*1 %01=*2 %10=*4 %11=*8

		CYCLE(4);
		int32 disp = (int32)(int8)(ext & 0xff);
		uint32 idx;

		if (idx_long) {
			idx = reg.R[rn];
		} else {
			idx = (int32)(int16)(reg.R[rn] & 0xffff);
		}
		idx <<= scale;
		return anpc + (int32)idx + disp;
	} else {
		// Full extension
		//
		//   F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0
		// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
		// | DA|     n     | WL| SCALE | 1 | BS| IS|  BDSZ | 0 |   I/IS    |
		// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
		//
		// BS=1: ベースレジスタ・サプレス
		// IS=1: インデックスオペランド・サプレス
		// BDSZ: ベースディスプレースメントのサイズ %01=null %10=.W %11=.L
		// I/IS: モード

		// クロックは概略値なので完全に正確ではないがまず基本は以下の2通り。
		//  メモリ間接なし			(6,  6)
		//  メモリ間接あり			(10, 10)
		// これを元に必要に応じて以下をそれぞれ加算する。
		//  bd16					(+2, +3)
		//  bd32 (メモリ間接なし)	(+4, +6)
		//  bd32 (メモリ間接あり)	(+6, +6)
		//  outer (W/L 不問)		(+2, +3)
		// ただしここでは実行順の都合で bd32 はいずれも (+4, +6) とした。

		bool bs = (ext & 0x0080);
		bool is = (ext & 0x0040);
		uint bdsize = (ext >> 4) & 3;
		uint iis = (ext & 7);

		// ベースレジスタ
		if (bs) {
			anpc = 0;
		}

		// ベース・ディスプレースメント
		uint32 base = 0;
		switch (bdsize) {
		 case 0:	// 予約
			// XXX 未定義命令列になるんだろうか?
			PANIC("BDSIZE==0 not impl");
		 case 1:	// ベースはヌル
			break;
		 case 2:	// ベース.W
			base = (int32)(int16)fetch_2();
			CYCLE2(2, 3);
			break;
		 case 3:	// ベース.L
			base = fetch_4();
			CYCLE2(4, 6);
			break;
		 default:
			__unreachable();
		}

		uint32 outer;
		if (is == 0) {
			// インデックス
			uint32 idx = 0;
			if (idx_long) {
				idx = reg.R[rn];
			} else {
				idx = (int32)(int16)(reg.R[rn] & 0xffff);
			}
			idx <<= scale;

			switch (iis) {
			 case 0:	// no memory indirection
				CYCLE(6);
				return anpc + base + idx;

			 case 1:	// indirect pre-index with null outer
				CYCLE(10);
				return read_4(anpc + base + idx);
			 case 2:	// indirect pre-index with word outer
				CYCLE2(10+2, 10+3);
				outer = (int32)(int16)fetch_2();
				return read_4(anpc + base + idx) + outer;
			 case 3:	// indirect pre-index with long outer
				CYCLE2(10+2, 10+3);
				outer = fetch_4();
				return read_4(anpc + base + idx) + outer;

			 case 4:
				PANIC("iis==4 reserved");

			 case 5:	// indirect post-index with null outer
				CYCLE(10);
				return read_4(anpc + base) + idx;
			 case 6:	// indirect post-index with word outer
				CYCLE2(10+2, 10+3);
				outer = (int32)(int16)fetch_2();
				return read_4(anpc + base) + idx + outer;
			 case 7:	// indirect post-index with long outer
				CYCLE2(10+2, 10+3);
				outer = fetch_4();
				return read_4(anpc + base) + idx + outer;
			 default:
				__unreachable();
			}
		} else {
			switch (iis) {
			 case 0:	// no memory indirection
				CYCLE(6);
				return anpc + base;

			 case 1:	// memory indirect with null outer
				CYCLE(10);
				return read_4(anpc + base);
			 case 2:	// memory indirect with word outer
				CYCLE2(10+2, 10+3);
				outer = (int32)(int16)fetch_2();
				return read_4(anpc + base) + outer;
			 case 3:	// memory indirect with long outer
				CYCLE2(10+2, 10+3);
				outer = fetch_4();
				return read_4(anpc + base) + outer;
			 default:
				PANIC("is==1 && iis>3 reserved");
			}
		}
	}
}

//
// Calc EA
//

uint32
MPU680x0Device::cea_ctrl()
{
	switch (eamode(ir)) {
	 case 2:	// (An)
		return cea_anin(eanum(ir));
	 case 5:	// d16(An)
		return cea_andi(eanum(ir));
	 case 6:	// (An,IX)
		return cea_anix(eanum(ir));
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			return cea_absw();
		 case 1:	// Abs.L
			return cea_absl();
		 case 2:	// d16(PC)
			return cea_pcdi();
		 case 3:	// (PC,IX)
			return cea_pcix();
		 default:
			break;
		}
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::cea_data_1()
{
	switch (eamode(ir)) {
	 case 2:	// (An)
		return cea_anin(eanum(ir));
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		return cea_anpi_1(eanum(ir));
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		return cea_anpd_1(eanum(ir));
	 case 5:	// d16(An)
		return cea_andi(eanum(ir));
	 case 6:	// (An,IX)
		return cea_anix(eanum(ir));
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			return cea_absw();
		 case 1:	// Abs.L
			return cea_absl();
		 default:
			break;
		}
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::cea_data_2()
{
	switch (eamode(ir)) {
	 case 2:	// (An)
		return cea_anin(eanum(ir));
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		return cea_anpi_2(eanum(ir));
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		return cea_anpd_2(eanum(ir));
	 case 5:	// d16(An)
		return cea_andi(eanum(ir));
	 case 6:	// (An,IX)
		return cea_anix(eanum(ir));
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			return cea_absw();
		 case 1:	// Abs.L
			return cea_absl();
		 default:
			break;
		}
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::cea_data_4()
{
	switch (eamode(ir)) {
	 case 2:	// (An)
		return cea_anin(eanum(ir));
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		return cea_anpi_4(eanum(ir));
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		return cea_anpd_4(eanum(ir));
	 case 5:	// d16(An)
		return cea_andi(eanum(ir));
	 case 6:	// (An,IX)
		return cea_anix(eanum(ir));
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			return cea_absw();
		 case 1:	// Abs.L
			return cea_absl();
		 default:
			break;
		}
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

// MMU からの呼び出し用。
uint32
MPU680x0Device::cea_copro()
{
	switch (eamode(ir)) {
	 case 2:	// (An)
		CYCLE(4);
		return internal_ea_anin(eanum(ir));
	 case 5:	// d16(An)
		CYCLE(4);
		return internal_ea_andi(eanum(ir));
	 case 6:	// (An,IX)
		CYCLE(4);
		return internal_ea_anix(eanum(ir));
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			CYCLE(4);
			return internal_ea_absw();
		 case 1:	// Abs.L
			CYCLE(6);
			return internal_ea_absl();
		 default:
			break;
		}
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

//
// Fetch EA
//

uint32
MPU680x0Device::fea_data_1()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
		return reg.D[eanum(ir)] & 0xff;
	 case 2:	// (An)
		ea = fea_anin();
		return read_1(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_1();
		return read_1(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_1();
		return read_1(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_1(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_1(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_1(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_1(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_1(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_1(ea);
		 case 4:	// #imm
			fea_imm_2();
			return fetch_2() & 0xff;
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::fea_data_2()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
		return reg.D[eanum(ir)] & 0xffff;
	 case 2:	// (An)
		ea = fea_anin();
		return read_2(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_2();
		return read_2(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_2();
		return read_2(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_2(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_2(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_2(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_2(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_2(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_2(ea);
		 case 4:	// #imm
			fea_imm_2();
			return fetch_2();
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::fea_data_4()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
		return reg.D[eanum(ir)];
	 case 2:	// (An)
		ea = fea_anin();
		return read_4(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_4();
		return read_4(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_4();
		return read_4(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_4(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_4(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_4(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_4(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_4(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_4(ea);
		 case 4:	// #imm
			fea_imm_4();
			return fetch_4();
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::fea_all_1()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
		return reg.D[eanum(ir)] & 0xff;
	 case 1:	// An
		// An.B は不当命令
		break;
	 case 2:	// (An)
		ea = fea_anin();
		return read_1(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_1();
		return read_1(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_1();
		return read_1(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_1(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_1(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_1(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_1(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_1(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_1(ea);
		 case 4:	// #imm
			fea_imm_2();
			return fetch_2() & 0xff;
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::fea_all_2()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
	 case 1:	// An
		return reg.R[ir & 15] & 0xffff;
	 case 2:	// (An)
		ea = fea_anin();
		return read_2(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_2();
		return read_2(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_2();
		return read_2(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_2(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_2(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_2(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_2(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_2(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_2(ea);
		 case 4:	// #imm
			fea_imm_2();
			return fetch_2();
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

uint32
MPU680x0Device::fea_all_4()
{
	uint32 ea;

	switch (eamode(ir)) {
	 case 0:	// Dn
	 case 1:	// An
		return reg.R[ir & 15];
	 case 2:	// (An)
		ea = fea_anin();
		return read_4(ea);
	 case 3:	// (An)+
		save_reg_pi(eanum(ir));
		ea = fea_anpi_4();
		return read_4(ea);
	 case 4:	// -(An)
		save_reg_pd(eanum(ir));
		ea = fea_anpd_4();
		return read_4(ea);
	 case 5:	// d16(An)
		ea = fea_andi();
		return read_4(ea);
	 case 6:	// (An,IX)
		ea = fea_anix();
		return read_4(ea);
	 case 7:
		switch (eanum(ir)) {
		 case 0:	// Abs.W
			ea = fea_absw();
			return read_4(ea);
		 case 1:	// Abs.L
			ea = fea_absl();
			return read_4(ea);
		 case 2:	// d16(PC)
			ea = fea_pcdi();
			return read_4(ea);
		 case 3:	// (PC,IX)
			ea = fea_pcix();
			return read_4(ea);
		 case 4:	// #imm
			fea_imm_4();
			return fetch_4();
		 default:
			break;
		}
		break;
	 default:
		break;
	}
	// 不当命令
	throw M68K::EXCEP_ILLEGAL;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.