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

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

unix.superglobalmegacorp.com

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