Annotation of nono/m680x0/m680x0.h, revision 1.1

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)

unix.superglobalmegacorp.com

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