Annotation of nono/m88xx0/m88100.h, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2020 [email protected]
        !             4: //
        !             5: 
        !             6: #pragma once
        !             7: 
        !             8: #include "header.h"
        !             9: #include "bus.h"
        !            10: #include <atomic>
        !            11: 
        !            12: // 外部リクエストフラグ
        !            13: // XXX m680x0 側にもよく似たものがあってどうしたもんか
        !            14: #define CPU_REQ_TRACE          (0x00000004)    // デバッガ有効
        !            15: #define CPU_REQ_PROMPT         (0x00000008)    // デバッガプロンプト
        !            16: #define CPU_REQ_RELEASE                (0x00000010)    // 命令後に CPU 実行中断
        !            17: #define CPU_REQ_INTR           (0x00000020)    // 命令後に割り込みチェック
        !            18: 
        !            19: class m88200
        !            20: {
        !            21:  public:
        !            22:        m88200();
        !            23:        virtual ~m88200();
        !            24: 
        !            25:  public:
        !            26:        uint64 load_8(uint32 addr) {
        !            27:                return vm_phys_read_8(addr);
        !            28:        }
        !            29:        uint64 load_16(uint32 addr) {
        !            30:                return vm_phys_read_16(addr);
        !            31:        }
        !            32:        uint64 load_32(uint32 addr) {
        !            33:                return vm_phys_read_32(addr);
        !            34:        }
        !            35:        uint64 store_8(uint32 addr, uint32 data) {
        !            36:                return vm_phys_write_8(addr, data);
        !            37:        }
        !            38:        uint64 store_16(uint32 addr, uint32 data) {
        !            39:                return vm_phys_write_16(addr, data);
        !            40:        }
        !            41:        uint64 store_32(uint32 addr, uint32 data) {
        !            42:                return vm_phys_write_32(addr, data);
        !            43:        }
        !            44: 
        !            45:        uint32 idr = 0;
        !            46:        //:
        !            47: };
        !            48: 
        !            49: // m88100 レジスタイメージを保持する構造体。
        !            50: // この構造体はコピーや比較をするので、ポインタとかは置かないこと。
        !            51: struct m88100reg
        !            52: {
        !            53:        // PID(cr0)
        !            54:        static const uint32 PID_REV_MASK        = 0x0000ff00; // 0 = MC88100
        !            55:        static const uint32 PID_VER_MASK        = 0x000000fe;
        !            56:        static const uint32 PID_MASTER          = 0x00000001;
        !            57:        // PSR(cr1)
        !            58:        static const uint32 PSR_SUPER           = 0x80000000;
        !            59:        static const uint32 PSR_BO_LE           = 0x40000000; // ByteOrder(Little)
        !            60:        static const uint32 PSR_SER                     = 0x20000000;
        !            61:        static const uint32 PSR_C                       = 0x10000000; // Carry
        !            62:        static const uint32 PSR_SFD1            = 0x00000008; // SFU1 Disable
        !            63:        static const uint32 PSR_MXM                     = 0x00000004; // MisalignedAccessEnable
        !            64:        static const uint32 PSR_IND                     = 0x00000002; // Interrupt Disable
        !            65:        static const uint32 PSR_SFRZ            = 0x00000001; // Shadow Freeze
        !            66: 
        !            67:        // 例外処理で使用される S*IP
        !            68:        static const uint32 SIP_MASK            = 0xfffffffcU;
        !            69:        static const uint32 SIP_V                       = 0x00000002;
        !            70:        static const uint32 SIP_E                       = 0x00000001;
        !            71: 
        !            72:        // DMTn、データ例外
        !            73:        static const uint32 DM_BO                       = 0x00008000;
        !            74:        static const uint32 DM_DAS                      = 0x00004000;
        !            75:        static const uint32 DM_DOUB1            = 0x00002000;
        !            76:        static const uint32 DM_LOCK                     = 0x00001000;
        !            77:        static const uint32 DM_DREG_MASK        = 0x00000f80;
        !            78:        static const uint32 DM_SIGNED           = 0x00000040;
        !            79:        static const uint32 DM_EN3                      = 0x00000020;
        !            80:        static const uint32 DM_EN2                      = 0x00000010;
        !            81:        static const uint32 DM_EN1                      = 0x00000008;
        !            82:        static const uint32 DM_EN0                      = 0x00000004;
        !            83:        static const uint32 DM_EN_MASK          = (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
        !            84:        static const uint32 DM_WRITE            = 0x00000002;
        !            85:        static const uint32 DM_VALID            = 0x00000001;
        !            86:        // 内部識別フラグ
        !            87:        static const uint32 DM_SIZE_B           = (1U << 16) | DM_EN3;
        !            88:        static const uint32 DM_SIZE_H           = (1U << 17) | DM_EN3 | DM_EN2;
        !            89:        static const uint32 DM_SIZE_W           = (1U << 18) | DM_EN_MASK;
        !            90:        static const uint32 DM_USR                      = (1U << 20);
        !            91:        static const uint32 DM_BU                       = DM_SIZE_B;
        !            92:        static const uint32 DM_B                        = DM_SIZE_B | DM_SIGNED;
        !            93:        static const uint32 DM_HU                       = DM_SIZE_H;
        !            94:        static const uint32 DM_H                        = DM_SIZE_H | DM_SIGNED;
        !            95:        static const uint32 DM_W                        = DM_SIZE_W;
        !            96:        static const uint32 DM_D1                       = DM_SIZE_W | DM_DOUB1;
        !            97:        static const uint32 DM_D2                       = DM_SIZE_W;
        !            98: 
        !            99:        // 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。
        !           100: 
        !           101:        // 実行中の命令
        !           102:        uint64 opX = 0;
        !           103:        // プリフェッチ命令
        !           104:        uint64 opF = 0;
        !           105: 
        !           106:        uint32 xip = 0;
        !           107:        uint32 nip = 0;
        !           108:        uint32 fip = 0;
        !           109: 
        !           110:        uint32 r[32] {};
        !           111:        union {
        !           112:                uint32 cr[21] {};
        !           113:                struct {
        !           114:                        uint32 pid;             // cr0
        !           115:                        uint32 psr;             // cr1
        !           116:                        uint32 epsr;    // cr2
        !           117:                        uint32 ssbr;    // cr3
        !           118:                        uint32 sxip;    // cr4
        !           119:                        uint32 snip;    // cr5
        !           120:                        uint32 sfip;    // cr6
        !           121:                        uint32 vbr;             // cr7
        !           122:                        uint32 dmt0;    // cr8
        !           123:                        uint32 dmd0;    // cr9
        !           124:                        uint32 dma0;    // cr10
        !           125:                        uint32 dmt1;    // cr11
        !           126:                        uint32 dmd1;    // cr12
        !           127:                        uint32 dma1;    // cr13
        !           128:                        uint32 dmt2;    // cr14
        !           129:                        uint32 dmd2;    // cr15
        !           130:                        uint32 dma2;    // cr16
        !           131:                        uint32 sr[4];   // cr17,18,19,20
        !           132:                };
        !           133:        };
        !           134:        union {
        !           135:                uint32 fcr[11] {};
        !           136:                struct {
        !           137:                        uint32 fpecr;   // fcr0
        !           138:                        uint32 fphs1;   // fcr1
        !           139:                        uint32 fpls1;   // fcr2
        !           140:                        uint32 fphs2;   // fcr3
        !           141:                        uint32 fpls2;   // fcr4
        !           142:                        uint32 fppt;    // fcr5
        !           143:                        uint32 fprh;    // fcr6
        !           144:                        uint32 fprl;    // fcr7
        !           145:                        uint32 fpit;    // fcr8
        !           146:                        uint32 fpsr;    // fcr62 [9]
        !           147:                        uint32 fpcr;    // fcr63 [10]
        !           148:                };
        !           149:        };
        !           150: 
        !           151:        // 直近のデータアクセスアドレス
        !           152:        uint32 lastaddr;
        !           153: 
        !           154:        // スーパーバイザ/ユーザモードなら true
        !           155:        bool IsSuper()  const { return (psr & PSR_SUPER) != 0; }
        !           156:        bool IsUser()   const { return (psr & PSR_SUPER) == 0; }
        !           157: 
        !           158:        // MXM (Misaligned Access Enable) なら true
        !           159:        bool IsMXM()    const { return (psr & PSR_MXM) != 0; }
        !           160: 
        !           161:        // キャリーフラグが立っていれば 1 を返す
        !           162:        uint32 GetCY() const { return (psr >> 28) & 1; }
        !           163:        // キャリーフラグをセットする。cy は最下位ビットのみ参照する
        !           164:        void SetCY(uint cy) {
        !           165:                psr &= ~PSR_C;
        !           166:                psr |= ((cy & 1) << 28);
        !           167:        }
        !           168: 
        !           169:        static const char * const sipname[3];
        !           170: };
        !           171: 
        !           172: class m88kcpu : public m88100reg
        !           173: {
        !           174:  public:
        !           175:        m88kcpu();
        !           176:        virtual ~m88kcpu();
        !           177: 
        !           178:  public:
        !           179:        void Reset(uint32 reset_vector);
        !           180:        uint32 Run(uint64 request);
        !           181:        void Release();
        !           182: 
        !           183:        uint64 total_cycle = 0;         // 積算実行サイクル数
        !           184: 
        !           185:        void Interrupt();
        !           186: 
        !           187:  public:
        !           188:        // [0] 命令バス
        !           189:        // [1] データバス
        !           190:        m88200 cmmu[2];
        !           191: 
        !           192:        uint64 fetch() {
        !           193:                nip = fip;
        !           194:                opF = cmmu[0].load_32(fip);
        !           195:                fip += 4;
        !           196:                return opF;
        !           197:        }
        !           198: 
        !           199:        // op が>=0ならバスエラーは起きていない
        !           200:        //  そのときに DELAYSLOT bit が 0 ならば通常
        !           201:        //  bit32 が 1 ならば遅延スロット命令
        !           202:        // op が負数ならバスエラーが起きた
        !           203:        //  そのときに DELAYSLOT bit が 1 ならば通常バスエラー
        !           204:        //  bit32 が 0 ならば遅延スロットでのバスエラー
        !           205:        // バスエラーかどうかのチェックのほうが回数が多いため、
        !           206:        // バスエラー優先にしたい。
        !           207: 
        !           208: 
        !           209:        bool OpIsBusErr(uint64 op) const {
        !           210:                return (int64)op < 0;
        !           211:        }
        !           212:        bool OpIsDelay(uint64 op) const {
        !           213:                return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
        !           214:        }
        !           215: 
        !           216:        // クラス外部からの xip 取得
        !           217:        uint32 Getxip() const {
        !           218:                return xip;
        !           219:        }
        !           220: 
        !           221:        enum ExceptionKind
        !           222:        {
        !           223:                NORMAL,
        !           224:                ERROR,
        !           225:                INTR,
        !           226:                TRAP,
        !           227:        };
        !           228: 
        !           229:        void Exception(int vec);
        !           230:        void ExceptionCore(int vec, ExceptionKind cause);
        !           231:        void ReadDataException(uint32 addr, uint32 flag);
        !           232:        void WriteDataException(uint32 addr, uint32 data, uint32 flag);
        !           233: 
        !           234:        // FPU
        !           235:        bool IsFPUEnable() { return !(psr & PSR_SFD1); }
        !           236:        void fpu_unimpl();
        !           237: 
        !           238:        std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
        !           239: 
        !           240:  private:
        !           241:        const uint64 DELAYSLOT = 1ULL << 62;
        !           242: 
        !           243:        // OpSetDelay を一つの op に対して複数回呼ばないでください
        !           244:        uint64 OpSetDelay(uint64 op) const {
        !           245:                return op ^ DELAYSLOT;
        !           246:        }
        !           247: 
        !           248:        // ブランチ処理用
        !           249:        void EnterBranch();
        !           250:        void ExitBranch();
        !           251:        void ExitDelayBranch();
        !           252:        // ロードストア命令用の下処理
        !           253:        bool ldst_usr(uint32 size, uint32& usr);
        !           254:        uint32 ldst_scale(uint32 size);
        !           255:        bool ldst_align(uint32 size, uint32& addr);
        !           256: 
        !           257: #define OP_PROTO(name) void __CONCAT(op_,name)()
        !           258: #include "m88100ops.h"
        !           259: #undef OP_PROTO
        !           260: 
        !           261:        void op_unimpl() {
        !           262:                printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
        !           263:        }
        !           264: };
        !           265: 
        !           266: // とりあえず
        !           267: static inline uint32
        !           268: op32_to_12(uint32 op)
        !           269: {
        !           270:        uint32 op12 = ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
        !           271:        return op12;
        !           272: }

unix.superglobalmegacorp.com

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