|
|
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)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.