File:  [Isaki's NoNo m68k/m88k emulator] / nono / m680x0 / m68030.h
Revision 1.1.1.14 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:26 2026 UTC (3 months 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
//

#pragma once

#include "bus.h"

// どこ?
__BEGIN_DECLS
#include "fpu_emulate.h"
__END_DECLS

// 定数
struct M68K
{
	// SR(CCR)
	static const uint32 SR_T			= 0xc000;
	static const uint32 SR_S			= 0x2000;
	static const uint32 SR_M			= 0x1000;
	static const uint32 SR_IMASK		= 0x0700;
	static const uint32 CCR_X			= 0x0010;
	static const uint32 CCR_N			= 0x0008;
	static const uint32 CCR_Z			= 0x0004;
	static const uint32 CCR_V			= 0x0002;
	static const uint32 CCR_C			= 0x0001;

	// SSW
	static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 4; }
	static const uint32 SSW_SIZE_LONG	= (0 << 4);
	static const uint32 SSW_SIZE_BYTE	= (1 << 4);
	static const uint32 SSW_SIZE_WORD	= (2 << 4);
	static const uint32 SSW_SIZE_3BYTES	= (3 << 4);
	static const uint32 SSW_SIZE_MASK	= (0x03 << 4);

	static const uint32 SSW_FC_MASK		= 0x0007;	// FC_*
	static const uint32 SSW_RW			= 0x0040;	// SSW_BUS_{R,W}
	static const uint32 SSW_RM			= 0x0080;
	static const uint32 SSW_DF			= 0x0100;	// Data Fault
	static const uint32 SSW_RB			= 0x1000;
	static const uint32 SSW_RC			= 0x2000;
	static const uint32 SSW_FB			= 0x4000;
	static const uint32 SSW_FC			= 0x8000;

	static const uint32 SSW_BUS_R		= 0x0040;
	static const uint32 SSW_BUS_W		= 0x0000;

	// FC
	static const uint32 FC_DATA			= 1;
	static const uint32 FC_PROG			= 2;
	static const uint32 FC_USER			= 0;
	static const uint32 FC_SUPER		= 4;
	static const uint32 FC_UD			= (FC_USER  | FC_DATA);
	static const uint32 FC_UP			= (FC_USER  | FC_PROG);
	static const uint32 FC_SD			= (FC_SUPER | FC_DATA);
	static const uint32 FC_SP			= (FC_SUPER | FC_PROG);

	// CACR
	static const uint32 CACR_EI			= 0x0001;
	static const uint32 CACR_FI			= 0x0002;
	static const uint32 CACR_CEI		= 0x0004;
	static const uint32 CACR_CI			= 0x0008;
	static const uint32 CACR_IBE		= 0x0010;
	static const uint32 CACR_ED			= 0x0100;
	static const uint32 CACR_FD			= 0x0200;
	static const uint32 CACR_CED		= 0x0400;
	static const uint32 CACR_CD			= 0x0800;
	static const uint32 CACR_DBE		= 0x1000;
	static const uint32 CACR_WA			= 0x2000;
	static const uint32 CACR_MASK		= 0x3f1f;

	// FP
	static const uint32 FPCR_MASK		= 0x0000fff0;
	static const uint32 FPSR_MASK		= 0x0ffffff8;

	// 例外
	// (型は core.cpp の try-catch と揃えること)
	static const uint EXCEP_RESET			= 0;
	static const uint EXCEP_BUSERR			= 2;
	static const uint EXCEP_ADDRERR			= 3;
	static const uint EXCEP_ILLEGAL			= 4;
	static const uint EXCEP_ZERODIV			= 5;
	static const uint EXCEP_CHK				= 6;
	static const uint EXCEP_TRAPV			= 7;
	static const uint EXCEP_PRIV			= 8;
	static const uint EXCEP_TRACE			= 9;
	static const uint EXCEP_ALINE			= 10;
	static const uint EXCEP_FLINE			= 11;
	static const uint EXCEP_COPRO			= 13;
	static const uint EXCEP_FORMAT			= 14;
	static const uint EXCEP_UNINIT_INTR		= 16;
	static const uint EXCEP_SPURIOUS		= 24;
	static const uint EXCEP_LEVEL_BASE		= 24;	// オートベクタ演算用
	static const uint EXCEP_LEVEL1			= 25;
	static const uint EXCEP_LEVEL7			= 31;
	static const uint EXCEP_TRAP0			= 32;
	static const uint EXCEP_TRAP15			= 47;
	static const uint EXCEP_FPCP_BRANCH		= 48;
	static const uint EXCEP_FPCP_INEXACT	= 49;
	static const uint EXCEP_FPCP_ZERODIV	= 50;
	static const uint EXCEP_FPCP_UNFL		= 51;
	static const uint EXCEP_FPCP_OPERR		= 52;
	static const uint EXCEP_FPCP_OVFL		= 53;
	static const uint EXCEP_FPCP_SNAN		= 54;
	static const uint EXCEP_MMU_CONFIG		= 56;
};

struct m68030ccr
{
 protected:
	// X フラグは、X の X_BIT が立っていれば 1
	// N フラグは、N の N_BIT が立っていれば 1
	// Z フラグは、Z == 0 なら 1
	// V フラグは、V の V_BIT が立っていれば 1
	// C フラグは、C の C_BIT が立っていれば 1
	static const uint32 X_BIT = 0x00000001;
	static const uint32 N_BIT = 0x80000000;
	static const uint32 V_BIT = 0x80000000;
	static const uint32 C_BIT = 0x00000001;

	uint32 X;
	uint32 V;
	uint32 N;
	DEF_UNION64(, CZ, C, Z);

 public:
	// value をフラグにセットする
	void SetX(bool value) { X = (value) ? X_BIT : 0; }
	void SetN(bool value) { N = (value) ? N_BIT : 0; }
	void SetZ(bool value) { Z = (value) ? 0 : 1; }
	void SetV(bool value) { V = (value) ? V_BIT : 0; }
	void SetC(bool value) { C = (value) ? C_BIT : 0; }

	// フラグが立っていれば真を返す
	bool IsX() const { return ((X & X_BIT) != 0); }
	bool IsN() const { return ((N & N_BIT) != 0); }
	bool IsZ() const { return (Z == 0); }
	bool IsV() const { return ((V & V_BIT) != 0); }
	bool IsC() const { return ((C & C_BIT) != 0); }

	// CCR レジスタの内容を作って返す
	uint8 Get() const {
		return (IsX() ? M68K::CCR_X : 0)
		     | (IsN() ? M68K::CCR_N : 0)
		     | (IsZ() ? M68K::CCR_Z : 0)
		     | (IsV() ? M68K::CCR_V : 0)
		     | (IsC() ? M68K::CCR_C : 0);
	}

	// CCR レジスタに val をセットする
	void Set(uint8 val) {
		SetX((val) & M68K::CCR_X);
		SetN((val) & M68K::CCR_N);
		SetZ((val) & M68K::CCR_Z);
		SetV((val) & M68K::CCR_V);
		SetC((val) & M68K::CCR_C);
	}

	bool CondT()  const { return true; }
	bool CondF()  const { return false; }
	bool CondHI() const { return !IsC() && !IsZ(); }
	bool CondLS() const { return IsC() || IsZ(); }
	bool CondCC() const { return !IsC(); }
	bool CondCS() const { return IsC(); }
	bool CondNE() const { return !IsZ(); }
	bool CondEQ() const { return IsZ(); }
	bool CondVC() const { return !IsV(); }
	bool CondVS() const { return IsV(); }
	bool CondPL() const { return !IsN(); }
	bool CondMI() const { return IsN(); }
	bool CondGE() const { return (IsN() && IsV()) || (!IsN() && !IsV()); }
	bool CondLT() const { return (IsN() && !IsV()) || (!IsN() && IsV()); }
	bool CondGT() const {
		return (IsN() && IsV() && !IsZ()) || (!IsN() && !IsV() && !IsZ());
	}
	bool CondLE() const {
		return IsZ() || (IsN() && !IsV()) || (!IsN() && IsV());
	}

	// cond で示される条件が成立すれば true を返す。
	inline bool Cond(uint cond) const {
		switch (cond) {
		 case 0:	// T
			return CondT();
		 case 1:	// F
			return CondF();
		 case 2:
			return CondHI();
		 case 3:
			return CondLS();
		 case 4:
			return CondCC();
		 case 5:
			return CondCS();
		 case 6:
			return CondNE();
		 case 7:
			return CondEQ();
		 case 8:
			return CondVC();
		 case 9:
			return CondVS();
		 case 10:
			return CondPL();
		 case 11:
			return CondMI();
		 case 12:
			return CondGE();
		 case 13:
			return CondLT();
		 case 14:
			return CondGT();
		 case 15:
			return CondLE();
		}
		__unreachable();
	}
};

// レジスタイメージを保持する構造体。
// この構造体はコピーとか比較をするのでポインタとかは置かないこと。
struct m68kreg
{
	uint32 pc;
	union {
		uint32 R[16] {};
		struct {
			uint32 D[8];
			uint32 A[8];
		};
	};

	m68030ccr ccr;
	bool s;				// SR の S ビット
	bool m;				// SR の M ビット
	int  intr_mask;		// SR の割り込みマスク (0-7)

	// 現在の SP は常に A[7]。A[7] が示しているときは対応する変数の
	// ほうは更新されないため無効 (図中 'x')。
	//
	// 						A[7]	usp		isp		msp
	//                  	----	---		---		---
	// ユーザ				USP		x		ISP		MSP
	// スーパーバイザ(I)	ISP		USP		x		MSP
	// スーパーバイザ(M)	MSP		USP		ISP		x
	uint32 usp;
	uint32 isp;
	uint32 msp;

	uint32 vbr;
	busaddr sfc;		// (R/W も含む)
	busaddr dfc;		// (R/W も含む)

	uint32 cacr;
	uint32 caar;

	union64 srp;
	union64 crp;
	uint32 tt[2];
	uint32 tc;
	uint16 mmusr;

	struct fpframe fpframe;

	// SR レジスタ全体を返す
	uint16 GetSR() const {
		return (s ? M68K::SR_S : 0)
		     | (m ? M68K::SR_M : 0)
		     | (intr_mask << 8)
		     | ccr.Get();
	}
	// SFC, DFC レジスタの値を返す
	uint32 GetSFC() const { return sfc.GetFC(); }
	uint32 GetDFC() const { return dfc.GetFC(); }
};

// バス状態
struct m68kbus
{
	// 論理アドレス。(R/W, FC2-0, Addr すべて使用)
	busaddr laddr;

	// 対応する物理アドレス (FC2, Addr のみ使用)
	busaddr paddr;

	// アクセスサイズ (SSW_SIZE_*)
	uint32 size;

	// データバス。
	// 今の所書き込みだけで使う。読み込みデータは戻り値のみ。
	uint32 data;

	// キャッシュ禁止。/CIIN
	bool ci;

	// Supervisor アクセスなら true を返す
	bool IsSuper() const { return laddr.IsSuper(); }

	// バスが Write なら true を返す
	bool IsWrite() const { return laddr.IsWrite(); }

	// FC を取得する。(これは MMU ルーチンから呼ばれる)
	uint GetFC() const { return laddr.GetFC(); }

	// SSW を取得する。
	uint32 GetSSW() const { return laddr.GetSSW() | size; }

	// アクセス方向(R/W)を設定する。
	void SetWrite(bool write_) { laddr.ChangeWrite(write_); }
};

// 仮
#define RegFP(n)	(reg.fpframe.fpf_regs[n])
#define RegFPCR		(reg.fpframe.fpf_fpcr)
#define RegFPSR		(reg.fpframe.fpf_fpsr)
#define RegFPIAR	(reg.fpframe.fpf_fpiar)

unix.superglobalmegacorp.com

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