Annotation of nono/vm/mpu88xx0.h, revision 1.1.1.12

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.11  root        7: //
                      8: // MPU (M88xx0)
                      9: //
1.1       root       10: 
                     11: #pragma once
                     12: 
                     13: #include "mpu.h"
1.1.1.12! root       14: #include "branchhistory.h"
        !            15: #include "event.h"
1.1       root       16: #include "m88100.h"
1.1.1.12! root       17: #include "m88200.h"
        !            18: #include <array>
1.1       root       19: 
1.1.1.12! root       20: class MPU88xx0Device : public MPUDevice, private M88100
1.1       root       21: {
1.1.1.2   root       22:        using inherited = MPUDevice;
1.1.1.12! root       23: 
        !            24:        static const uint32 CPU_STATE_NORMAL    = 0;
        !            25:        static const uint32 CPU_STATE_STOP              = 1;    // 疑似 STOP 状態
        !            26: 
        !            27:        enum ExceptionKind {
        !            28:                NORMAL,
        !            29:                DATA,
        !            30:                ERROR,
        !            31:                INTR,
        !            32:                TRAP,
        !            33:        };
        !            34: 
1.1       root       35:  public:
1.1.1.8   root       36:        MPU88xx0Device();
1.1.1.5   root       37:        virtual ~MPU88xx0Device() override;
                     38: 
                     39:        bool Init() override;
1.1.1.11  root       40:        void ResetHard(bool poweron) override;
1.1       root       41: 
1.1.1.12! root       42:        // MPU からのアクセスをエミュレートする。
        !            43:        // アドレスは論理アドレス。
        !            44:        // 空間は現在のデータ空間。
        !            45:        // ミスアラインドアクセスも可能。
        !            46:        // アクセスエラーは -1 を返す。
        !            47:        uint64 Read8(uint32 addr) override;
        !            48:        uint64 Read16(uint32 addr) override;
        !            49:        uint64 Read32(uint32 addr) override;
        !            50:        uint64 Write8(uint32 addr, uint32 data) override;
        !            51:        uint64 Write16(uint32 addr, uint32 data) override;
        !            52:        uint64 Write32(uint32 addr, uint32 data) override;
        !            53: 
1.1       root       54:        // 現在実行中の命令の PC を取得
1.1.1.12! root       55:        uint32 GetPPC() const override { return reg.xip; }
1.1       root       56: 
1.1.1.11  root       57:        // 現在の VBR を取得
1.1.1.12! root       58:        uint32 GetVBR() const override { return reg.vbr; }
        !            59: 
        !            60:        // スーパーバイザ/ユーザモードなら true
        !            61:        bool IsSuper() const            { return (reg.psr & PSR_SUPER) != 0; }
        !            62:        bool IsUser() const                     { return (reg.psr & PSR_SUPER) == 0; }
        !            63: 
        !            64:        // 割り込みが許可なら true
        !            65:        bool IsIntrEnable() const       { return (reg.psr & PSR_IND) == 0; }
        !            66: 
        !            67:        // CPU の実行状態 (uint32) を返す。
        !            68:        uint32 GetState() const         { return cpu_state; }
1.1.1.11  root       69: 
1.1       root       70:        // 現在アクセス中の論理アドレス、物理アドレスを取得。
1.1.1.7   root       71:        uint32 GetLaddr() const override;
                     72:        uint32 GetPaddr() const override;
1.1       root       73: 
1.1.1.4   root       74:        // アクセスウェイトを加算
1.1.1.12! root       75:        void AddCycle(int32 cycle) override {
        !            76:                // XXX 本来は今アクセスしてきている(= バスマスターの) CMMU に
        !            77:                // 対して加算するべき?かもだが、まだその辺の概念がない。
        !            78:                used_cycle += cycle;
        !            79:        }
1.1.1.4   root       80: 
1.1       root       81:        // 割り込み発生を MPU に通知
1.1.1.5   root       82:        void Interrupt(int level) override;
1.1       root       83: 
1.1.1.10  root       84:        // DOS call エミュレーションのコールバックを指定する
1.1.1.12! root       85:        void SetFLineCallback(bool (*callback)(MPU88xx0Device *, void *),
        !            86:                void *arg);
1.1.1.10  root       87: 
1.1.1.12! root       88:        // op が負数ならバスエラーが起きた
        !            89:        static bool OpIsBusErr(uint64 op) {
        !            90:                return (int64)op < 0;
        !            91:        }
        !            92: 
        !            93:        m88100reg reg {};
        !            94: 
        !            95:        // 直近のデータアクセスアドレス。
        !            96:        // XXX メモリブレークポイント用だがもう少しなんとかしたい
        !            97:        uint64 lastaddr {};
1.1.1.11  root       98: 
1.1       root       99:  private:
1.1.1.11  root      100:        // リセット例外コールバック
                    101:        void ResetCallback(Event& ev);
                    102: 
                    103:        // 命令実行系コールバック
                    104:        void ExecNormal(Event& ev);
                    105:        void ExecTrace(Event& ev);
                    106: 
                    107:        // トレース設定。デバッガから呼び出される。
                    108:        void SetTrace(bool trace_on) override;
                    109: 
1.1.1.12! root      110:        uint64 fetch() {
        !           111:                reg.nip = reg.fip;
        !           112:                reg.opF = cmmu[0]->load_32(reg.fip);
        !           113:                reg.fip += 4;
        !           114:                return reg.opF;
        !           115:        }
        !           116: 
        !           117:        void Prefetch();
        !           118: 
        !           119:        // PSR を newpsr に変更する。
        !           120:        // CY ビットは特別にこの関数を経由しないで変更してよいことにする。
        !           121:        void SetPSR(uint32 newpsr) {
        !           122:                reg.psr = newpsr;
        !           123:                SetPSR();
        !           124:        }
        !           125:        // 更新された psr に基づいて、PSR 変更によって必要な処理をする。
        !           126:        // CY ビットを変更した場合は呼ばなくてよいことにする。
        !           127:        void SetPSR() {
        !           128:                // CMMU に S/U 信号を出す
        !           129:                cmmu[0]->SetSuper(IsSuper());
        !           130:                cmmu[1]->SetSuper(IsSuper());
        !           131:        }
        !           132: 
        !           133:        // キャリーフラグが立っていれば 1 を返す
        !           134:        uint32 GetCY() const    { return (reg.psr >> 28) & 1; }
        !           135: 
        !           136:        // キャリーフラグをセットする。
        !           137:        // cy のうち最下位ビットのみ参照する (呼び出し側はマスクせず渡してよい)
        !           138:        void SetCY(uint cy) {
        !           139:                reg.psr &= ~PSR_C;
        !           140:                reg.psr |= ((cy & 1) << 28);
        !           141:        }
        !           142: 
        !           143:        // SFU1(FPU)が有効なら true
        !           144:        bool IsFPUEnable() const        { return (reg.psr & PSR_SFD1) == 0; }
        !           145: 
        !           146:        // MXM (Misaligned Access Enable) なら true
        !           147:        bool IsMXM() const                      { return (reg.psr & PSR_MXM) != 0; }
        !           148: 
        !           149:        // FPxS1, FPxS2 レジスタを設定
        !           150:        static void SetFPxS(uint32& h, uint32& l, double src, uint32 t);
        !           151:        void SetFPS1(double src, uint32 t1);
        !           152:        void SetFPS2(double src, uint32 t2);
        !           153:        void SetFPS1(uint32 src);
        !           154:        void SetFPS2(uint32 src);
        !           155:        // FP Result を FPIT, FPRH, FPRL レジスタに設定
        !           156:        void SetFPRx(double src);
        !           157: 
        !           158:        void Exception(int vec);
        !           159:        void ExceptionCore(int vec, ExceptionKind cause);
        !           160:        uint32 Calcdmt(uint32 flag);
        !           161:        void ReadDataException32(uint32 addr, uint32 flag);
        !           162:        void ReadDataException64(uint32 addr, uint32 flag);
        !           163:        void WriteDataException32(uint32 addr, uint32 flag);
        !           164:        void WriteDataException64(uint32 addr, uint32 flag);
        !           165:        void XmemDataException(uint32 addr, uint32 flag);
        !           166:        void FPPreciseException(uint32 cause, double s2);
        !           167:        void FPPreciseException(uint32 cause, double s1, double s2);
        !           168:        void FPPreciseException(uint32 cause);
        !           169:        void FPImpreciseException(uint32 cause);
        !           170: 
        !           171:        // ブランチ処理用
        !           172:        void DoBranch(uint32 toaddr, bool next_exec);
        !           173:        uint32 nop_counter {};  // STOP 検出用の nop 命令カウンタ
        !           174: 
        !           175:        // ロードストア命令用の下処理
        !           176:        bool ldst_usr(uint32& usr);
        !           177:        uint32 ldst_scale(uint32 size);
        !           178:        bool ldst_align(uint32 size, uint32& addr);
        !           179:        // 浮動小数点数命令用の処理
        !           180:        void ops_int(int mode);
        !           181: 
        !           182: #define OP_PROTO(name) void __CONCAT(op_,name)()
        !           183: #include "m88100ops.h"
        !           184: OP_PROTO(illegal);
        !           185: #undef OP_PROTO
        !           186: 
        !           187:        void fpu_unimpl();
        !           188: 
        !           189:        // float,double と整数値の相互変換
        !           190:        static float u2f(uint32 u) {
        !           191:                float v;
        !           192:                memcpy(&v, &u, sizeof(v));
        !           193:                return v;
        !           194:        }
        !           195:        static double u2d(uint64 u) {
        !           196:                double v;
        !           197:                memcpy(&v, &u, sizeof(v));
        !           198:                return v;
        !           199:        }
        !           200:        static uint32 f2u(float v) {
        !           201:                uint32 u;
        !           202:                memcpy(&u, &v, sizeof(u));
        !           203:                return u;
        !           204:        }
        !           205:        static uint64 d2u(double v) {
        !           206:                uint64 u;
        !           207:                memcpy(&u, &v, sizeof(u));
        !           208:                return u;
        !           209:        }
        !           210: 
        !           211:        // [0] 命令バス
        !           212:        // [1] データバス
        !           213:        std::array<std::unique_ptr<m88200>, 2> cmmu {};
        !           214: 
        !           215:        // ブランチ履歴 (例外履歴を含む)
        !           216:        BranchHistory_m88xx0 brhist { OBJ_MPU_BRHIST };
        !           217:        // 例外履歴のみ
        !           218:        BranchHistory_m88xx0 exhist { OBJ_MPU_EXHIST };
        !           219: 
        !           220:        // 今のところサイクルを正確に実装するのは無理なので
        !           221:        // 適当に全部積み上げてある。
        !           222: 
        !           223:        // 電源オンからの累積消費サイクル
        !           224:        uint64 used_cycle {};
        !           225: 
        !           226:        // ペンディング中の割り込みレベル
        !           227:        int intr_pending {};
        !           228: 
        !           229:        // CPU の状態
        !           230:        void ChangeState(uint32 new_state);
        !           231:        uint32 cpu_state {};
        !           232: 
        !           233:        // 疑似 STOP 状態に入る機能を有効にする場合 true
        !           234:        bool pseudo_stop_enable {};
        !           235: 
        !           236:        // DOS call エミュレーション
        !           237:        bool (*fline_callback)(MPU88xx0Device *, void *) = NULL;
        !           238:        void *fline_arg {};
        !           239: 
1.1.1.9   root      240:        // レジスタモニター
                    241:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    242:        Monitor monitor { this };
1.1.1.2   root      243: 
1.1.1.11  root      244:        // イベントコールバック
                    245:        EventCallback_t exec_normal {};
1.1.1.2   root      246: };
                    247: 
1.1.1.12! root      248: static inline MPU88xx0Device *GetMPU88xx0Device() {
        !           249:        return Object::GetObject<MPU88xx0Device>(OBJ_MPU);
        !           250: }

unix.superglobalmegacorp.com

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