|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #pragma once ! 8: ! 9: #include "bus.h" ! 10: ! 11: // どこ? ! 12: __BEGIN_DECLS ! 13: #include "fpu_emulate.h" ! 14: __END_DECLS ! 15: ! 16: // MPU 種別 ! 17: enum class m680x0MPUType ! 18: { ! 19: NONE = 0, ! 20: M68030 = (1U << 1), ! 21: M68040 = (1U << 2), ! 22: }; ! 23: ! 24: // FPU 種別 ! 25: struct m680x0FPUType ! 26: { ! 27: enum m680x0FPUType_ { ! 28: M68030_NOFPU = 0, // 68030 without 6888x ! 29: M68LC040 = (1U << 0), ! 30: M68LC060 = (1U << 1), // (reserved) ! 31: M68040 = (1U << 2), ! 32: M68060 = (1U << 3), // (reserved) ! 33: M68881 = (1U << 4), ! 34: M68882 = (1U << 5), ! 35: ! 36: M68LC0x0 = (M68LC040 | M68LC060), ! 37: M680x0 = (M68040 | M68060), ! 38: M6888x = (M68881 | M68882), ! 39: } type {}; ! 40: ! 41: // コンストラクタ ! 42: m680x0FPUType() { ! 43: } ! 44: m680x0FPUType(m680x0FPUType_ type_) ! 45: : type(type_) ! 46: { ! 47: } ! 48: ! 49: bool IsNoFPU() const noexcept { return (type == M68030_NOFPU); } ! 50: bool Is4060LC() const noexcept { return (type & M68LC0x0) != 0; } ! 51: bool Is40FPU() const noexcept { return (type & M68040) != 0; } ! 52: bool Is4060FPU() const noexcept { return (type & M680x0) != 0; } ! 53: bool Is6888x() const noexcept { return (type & M6888x) != 0; } ! 54: }; ! 55: static inline bool operator==(const m680x0FPUType& a, const m680x0FPUType& b) { ! 56: return (a.type == b.type); ! 57: } ! 58: static inline bool operator!=(const m680x0FPUType& a, const m680x0FPUType& b) { ! 59: return !(a == b); ! 60: } ! 61: ! 62: // 定数 ! 63: struct M68K ! 64: { ! 65: // SR(CCR) ! 66: static const uint32 SR_T = 0xc000; ! 67: static const uint32 SR_S = 0x2000; ! 68: static const uint32 SR_M = 0x1000; ! 69: static const uint32 SR_IMASK = 0x0700; ! 70: static const uint32 CCR_X = 0x0010; ! 71: static const uint32 CCR_N = 0x0008; ! 72: static const uint32 CCR_Z = 0x0004; ! 73: static const uint32 CCR_V = 0x0002; ! 74: static const uint32 CCR_C = 0x0001; ! 75: ! 76: // FC ! 77: static const uint32 FC_DATA = 1; ! 78: static const uint32 FC_PROG = 2; ! 79: static const uint32 FC_USER = 0; ! 80: static const uint32 FC_SUPER = 4; ! 81: static const uint32 FC_UD = (FC_USER | FC_DATA); ! 82: static const uint32 FC_UP = (FC_USER | FC_PROG); ! 83: static const uint32 FC_SD = (FC_SUPER | FC_DATA); ! 84: static const uint32 FC_SP = (FC_SUPER | FC_PROG); ! 85: ! 86: // FP ! 87: static const uint32 FPCR_MASK = 0x0000fff0; ! 88: static const uint32 FPSR_MASK = 0x0ffffff8; ! 89: ! 90: // 例外 (型は core.cpp の try-catch と揃えること)。 ! 91: // FPU_NOIMPL (浮動小数点未実装命令例外) はベクタ番号が 11 ($b) で ! 92: // F ラインと同じだが処理が色々違うので帯域外のビットで判別する。 ! 93: static const uint EXCEP_RESET = 0; ! 94: static const uint EXCEP_BUSERR = 2; ! 95: static const uint EXCEP_ADDRERR = 3; ! 96: static const uint EXCEP_ILLEGAL = 4; ! 97: static const uint EXCEP_ZERODIV = 5; ! 98: static const uint EXCEP_CHK = 6; ! 99: static const uint EXCEP_TRAPV = 7; ! 100: static const uint EXCEP_PRIV = 8; ! 101: static const uint EXCEP_TRACE = 9; ! 102: static const uint EXCEP_ALINE = 10; ! 103: static const uint EXCEP_FLINE = 11; ! 104: static const uint EXCEP_FP_UNIMPL = (11 | 0x100); ! 105: static const uint EXCEP_COPRO = 13; ! 106: static const uint EXCEP_FORMAT = 14; ! 107: static const uint EXCEP_UNINIT_INTR = 16; ! 108: static const uint EXCEP_SPURIOUS = 24; ! 109: static const uint EXCEP_LEVEL_BASE = 24; // オートベクタ演算用 ! 110: static const uint EXCEP_LEVEL1 = 25; ! 111: static const uint EXCEP_LEVEL7 = 31; ! 112: static const uint EXCEP_TRAP0 = 32; ! 113: static const uint EXCEP_TRAP15 = 47; ! 114: static const uint EXCEP_FP_BSUN = 48; ! 115: static const uint EXCEP_FP_INEX = 49; ! 116: static const uint EXCEP_FP_ZERODIV = 50; ! 117: static const uint EXCEP_FP_UNFL = 51; ! 118: static const uint EXCEP_FP_OPERR = 52; ! 119: static const uint EXCEP_FP_OVFL = 53; ! 120: static const uint EXCEP_FP_SNAN = 54; ! 121: static const uint EXCEP_FP_UNSUPP = 55; ! 122: static const uint EXCEP_MMU_CONFIG = 56; ! 123: }; ! 124: ! 125: // 定数 ! 126: struct M68030 ! 127: { ! 128: // SSW ! 129: static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 4; } ! 130: static const uint32 SSW_SIZE_LONG = (0 << 4); ! 131: static const uint32 SSW_SIZE_BYTE = (1 << 4); ! 132: static const uint32 SSW_SIZE_WORD = (2 << 4); ! 133: static const uint32 SSW_SIZE_3BYTES = (3 << 4); ! 134: static const uint32 SSW_SIZE_MASK = (0x03 << 4); ! 135: ! 136: static const uint32 SSW_FC_MASK = 0x0007; // FC_* ! 137: static const uint32 SSW_RW = 0x0040; // SSW_BUS_{R,W} ! 138: static const uint32 SSW_RM = 0x0080; ! 139: static const uint32 SSW_DF = 0x0100; // Data Fault ! 140: static const uint32 SSW_RB = 0x1000; ! 141: static const uint32 SSW_RC = 0x2000; ! 142: static const uint32 SSW_FB = 0x4000; ! 143: static const uint32 SSW_FC = 0x8000; ! 144: ! 145: static const uint32 SSW_BUS_R = 0x0040; ! 146: static const uint32 SSW_BUS_W = 0x0000; ! 147: ! 148: // CACR ! 149: static const uint32 CACR_EI = 0x0001; ! 150: static const uint32 CACR_FI = 0x0002; ! 151: static const uint32 CACR_CEI = 0x0004; ! 152: static const uint32 CACR_CI = 0x0008; ! 153: static const uint32 CACR_IBE = 0x0010; ! 154: static const uint32 CACR_ED = 0x0100; ! 155: static const uint32 CACR_FD = 0x0200; ! 156: static const uint32 CACR_CED = 0x0400; ! 157: static const uint32 CACR_CD = 0x0800; ! 158: static const uint32 CACR_DBE = 0x1000; ! 159: static const uint32 CACR_WA = 0x2000; ! 160: static const uint32 CACR_MASK = 0x3f1f; ! 161: }; ! 162: ! 163: // 定数 ! 164: struct M68040 ! 165: { ! 166: // SSW ! 167: static const uint32 SSW_TM_MASK = 0x0007; ! 168: static const uint32 SSW_TT_MASK = 0x0018; ! 169: static const uint32 SSW_SIZE_MASK = 0x0060; // (0x03 << 5) ! 170: static const uint32 SSW_RW = 0x0100; ! 171: static const uint32 SSW_LK = 0x0200; ! 172: static const uint32 SSW_ATC = 0x0400; ! 173: static const uint32 SSW_MA = 0x0800; ! 174: static const uint32 SSW_CM = 0x1000; ! 175: static const uint32 SSW_CT = 0x2000; ! 176: static const uint32 SSW_CU = 0x4000; ! 177: static const uint32 SSW_CP = 0x8000; ! 178: ! 179: static const uint32 SSW_SIZE_LONG = (0x00 << 5); ! 180: static const uint32 SSW_SIZE_BYTE = (0x01 << 5); ! 181: static const uint32 SSW_SIZE_WORD = (0x02 << 5); ! 182: static const uint32 SSW_SIZE_LINE = (0x03 << 5); ! 183: // バイトサイズから SSW_SIZE フィールドを作成する。1, 2, 4 バイトのみ。 ! 184: static constexpr uint32 SSW_SIZE(uint32 x) { return ((x) & 0x03) << 5; } ! 185: ! 186: // CACR ! 187: static const uint32 CACR_MASK = 0x80008000; ! 188: static const uint32 CACR_DE = 0x80000000; ! 189: static const uint32 CACR_IE = 0x00008000; ! 190: }; ! 191: ! 192: struct m680x0CCR ! 193: { ! 194: protected: ! 195: // X フラグは、X の X_BIT が立っていれば 1 ! 196: // N フラグは、N の N_BIT が立っていれば 1 ! 197: // Z フラグは、Z == 0 なら 1 ! 198: // V フラグは、V の V_BIT が立っていれば 1 ! 199: // C フラグは、C の C_BIT が立っていれば 1 ! 200: static const uint32 X_BIT = 0x00000001; ! 201: static const uint32 N_BIT = 0x80000000; ! 202: static const uint32 V_BIT = 0x80000000; ! 203: static const uint32 C_BIT = 0x00000001; ! 204: ! 205: uint32 X; ! 206: uint32 V; ! 207: uint32 N; ! 208: DEF_UNION64(, CZ, C, Z); ! 209: ! 210: public: ! 211: // value をフラグにセットする ! 212: void SetX(bool value) { X = (value) ? X_BIT : 0; } ! 213: void SetN(bool value) { N = (value) ? N_BIT : 0; } ! 214: void SetZ(bool value) { Z = (value) ? 0 : 1; } ! 215: void SetV(bool value) { V = (value) ? V_BIT : 0; } ! 216: void SetC(bool value) { C = (value) ? C_BIT : 0; } ! 217: ! 218: // フラグが立っていれば真を返す ! 219: bool IsX() const { return ((X & X_BIT) != 0); } ! 220: bool IsN() const { return ((N & N_BIT) != 0); } ! 221: bool IsZ() const { return (Z == 0); } ! 222: bool IsV() const { return ((V & V_BIT) != 0); } ! 223: bool IsC() const { return ((C & C_BIT) != 0); } ! 224: ! 225: // CCR レジスタの内容を作って返す ! 226: uint8 Get() const { ! 227: return (IsX() ? M68K::CCR_X : 0) ! 228: | (IsN() ? M68K::CCR_N : 0) ! 229: | (IsZ() ? M68K::CCR_Z : 0) ! 230: | (IsV() ? M68K::CCR_V : 0) ! 231: | (IsC() ? M68K::CCR_C : 0); ! 232: } ! 233: ! 234: // CCR レジスタに val をセットする ! 235: void Set(uint8 val) { ! 236: SetX((val) & M68K::CCR_X); ! 237: SetN((val) & M68K::CCR_N); ! 238: SetZ((val) & M68K::CCR_Z); ! 239: SetV((val) & M68K::CCR_V); ! 240: SetC((val) & M68K::CCR_C); ! 241: } ! 242: ! 243: bool CondT() const { return true; } ! 244: bool CondF() const { return false; } ! 245: bool CondHI() const { return !IsC() && !IsZ(); } ! 246: bool CondLS() const { return IsC() || IsZ(); } ! 247: bool CondCC() const { return !IsC(); } ! 248: bool CondCS() const { return IsC(); } ! 249: bool CondNE() const { return !IsZ(); } ! 250: bool CondEQ() const { return IsZ(); } ! 251: bool CondVC() const { return !IsV(); } ! 252: bool CondVS() const { return IsV(); } ! 253: bool CondPL() const { return !IsN(); } ! 254: bool CondMI() const { return IsN(); } ! 255: bool CondGE() const { return (IsN() && IsV()) || (!IsN() && !IsV()); } ! 256: bool CondLT() const { return (IsN() && !IsV()) || (!IsN() && IsV()); } ! 257: bool CondGT() const { ! 258: return (IsN() && IsV() && !IsZ()) || (!IsN() && !IsV() && !IsZ()); ! 259: } ! 260: bool CondLE() const { ! 261: return IsZ() || (IsN() && !IsV()) || (!IsN() && IsV()); ! 262: } ! 263: ! 264: // cond で示される条件が成立すれば true を返す。 ! 265: inline bool Cond(uint cond) const { ! 266: switch (cond) { ! 267: case 0: // T ! 268: return CondT(); ! 269: case 1: // F ! 270: return CondF(); ! 271: case 2: ! 272: return CondHI(); ! 273: case 3: ! 274: return CondLS(); ! 275: case 4: ! 276: return CondCC(); ! 277: case 5: ! 278: return CondCS(); ! 279: case 6: ! 280: return CondNE(); ! 281: case 7: ! 282: return CondEQ(); ! 283: case 8: ! 284: return CondVC(); ! 285: case 9: ! 286: return CondVS(); ! 287: case 10: ! 288: return CondPL(); ! 289: case 11: ! 290: return CondMI(); ! 291: case 12: ! 292: return CondGE(); ! 293: case 13: ! 294: return CondLT(); ! 295: case 14: ! 296: return CondGT(); ! 297: case 15: ! 298: return CondLE(); ! 299: } ! 300: __unreachable(); ! 301: } ! 302: }; ! 303: ! 304: // レジスタイメージを保持する構造体。 ! 305: // この構造体はコピーとか比較をするのでポインタとかは置かないこと。 ! 306: struct m68kreg ! 307: { ! 308: uint32 pc; ! 309: union { ! 310: uint32 R[16] {}; ! 311: struct { ! 312: uint32 D[8]; ! 313: uint32 A[8]; ! 314: }; ! 315: }; ! 316: ! 317: m680x0CCR ccr; ! 318: bool s; // SR の S ビット ! 319: bool m; // SR の M ビット ! 320: int intr_mask; // SR の割り込みマスク (0-7) ! 321: ! 322: // 現在の SP は常に A[7]。A[7] が示しているときは対応する変数の ! 323: // ほうは更新されないため無効 (図中 'x')。 ! 324: // ! 325: // A[7] usp isp msp ! 326: // ---- --- --- --- ! 327: // ユーザ USP x ISP MSP ! 328: // スーパーバイザ(I) ISP USP x MSP ! 329: // スーパーバイザ(M) MSP USP ISP x ! 330: uint32 usp; ! 331: uint32 isp; ! 332: uint32 msp; ! 333: ! 334: uint32 vbr; ! 335: busaddr sfc; // (R/W も含む) ! 336: busaddr dfc; // (R/W も含む) ! 337: ! 338: uint32 cacr; ! 339: uint32 caar; ! 340: ! 341: // 68030 MMU ! 342: union64 srp; ! 343: union64 crp; ! 344: uint32 tt[2]; ! 345: uint32 tc; ! 346: uint16 mmusr; ! 347: ! 348: // 68040 MMU ! 349: uint32 itt[2]; ! 350: uint32 dtt[2]; ! 351: uint32 srp40; ! 352: uint32 urp40; ! 353: uint16 tc40; ! 354: uint32 mmusr40; ! 355: ! 356: struct fpframe fpframe; ! 357: ! 358: // SR レジスタ全体を返す ! 359: uint16 GetSR() const { ! 360: return (s ? M68K::SR_S : 0) ! 361: | (m ? M68K::SR_M : 0) ! 362: | (intr_mask << 8) ! 363: | ccr.Get(); ! 364: } ! 365: // SFC, DFC レジスタの値を返す ! 366: uint32 GetSFC() const { return sfc.GetFC(); } ! 367: uint32 GetDFC() const { return dfc.GetFC(); } ! 368: }; ! 369: ! 370: // バス状態 ! 371: struct m68kbus ! 372: { ! 373: // 論理アドレス。(R/W, FC2-0, Addr すべて使用) ! 374: busaddr laddr; ! 375: ! 376: // 対応する物理アドレス (FC2, Addr のみ使用) ! 377: busaddr paddr; ! 378: ! 379: // アクセスサイズ (バイト数で表す) ! 380: uint32 size; ! 381: ! 382: // データバス。 ! 383: // 今の所書き込みだけで使う。読み込みデータは戻り値のみ。 ! 384: uint32 data; ! 385: ! 386: // キャッシュ禁止。/CIIN ! 387: bool ci; ! 388: ! 389: // ATC フォールト (68040 only) ! 390: bool atcfault; ! 391: ! 392: // ATC フォールトが2ページ目で起きたら true (68040 only) ! 393: bool atcfault2; ! 394: ! 395: // Supervisor アクセスなら true を返す ! 396: bool IsSuper() const { return laddr.IsSuper(); } ! 397: ! 398: // バスが Write なら true を返す ! 399: bool IsWrite() const { return laddr.IsWrite(); } ! 400: }; ! 401: ! 402: // 仮 ! 403: #define RegFP(n) (reg.fpframe.fpf_regs[(n) * 3]) ! 404: #define RegFPCR (reg.fpframe.fpf_fpcr) ! 405: #define RegFPSR (reg.fpframe.fpf_fpsr) ! 406: #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.