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

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

unix.superglobalmegacorp.com

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