Annotation of nono/vm/mpu680x0.h, revision 1.1.1.11

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.10  root        7: //
                      8: // MPU (MC68030)
                      9: //
1.1       root       10: 
                     11: #pragma once
                     12: 
                     13: #include "mpu.h"
1.1.1.11! root       14: #include "branchhistory.h"
        !            15: #include "event.h"
1.1       root       16: #include "m68030.h"
1.1.1.11! root       17: #include "m68030mmu.h"
        !            18: #include "mainbus.h"
        !            19: 
        !            20: class InterruptDevice;
1.1       root       21: 
                     22: class MPU680x0Device : public MPUDevice
                     23: {
1.1.1.2   root       24:        using inherited = MPUDevice;
1.1.1.11! root       25:        friend class m68030MMU;
        !            26: 
        !            27:        // CPU の実行状態
        !            28:        static const uint32 CPU_STATE_NORMAL    = 0;
        !            29:        static const uint32 CPU_STATE_STOP              = 1;
        !            30:        static const uint32 CPU_STATE_HALT              = 2;
        !            31: 
1.1       root       32:  public:
1.1.1.7   root       33:        MPU680x0Device();
1.1.1.5   root       34:        virtual ~MPU680x0Device() override;
1.1       root       35: 
1.1.1.2   root       36:        bool Init() override;
1.1.1.10  root       37:        void ResetHard(bool poweron) override;
1.1       root       38: 
                     39:        // 現在の PPC を取得
1.1.1.11! root       40:        uint32 GetPPC() const override { return ppc; }
1.1       root       41: 
1.1.1.10  root       42:        // 現在の VBR を取得
1.1.1.11! root       43:        uint32 GetVBR() const override { return reg.vbr; }
        !            44: 
        !            45:        bool IsSuper() const    { return reg.s; }
        !            46:        bool IsMaster() const   { return reg.m; }
        !            47: 
        !            48:        // CPU の実行状態 (uint32) を返す。
        !            49:        uint32 GetState() const { return cpu_state; }
1.1.1.10  root       50: 
1.1       root       51:        // 現在アクセス中の論理アドレス、物理アドレスを取得。
1.1.1.11! root       52:        uint32 GetLaddr() const override { return bus.laddr; }
        !            53:        uint32 GetPaddr() const override { return bus.paddr; }
1.1       root       54: 
1.1.1.4   root       55:        // アクセスウェイトを加算
1.1.1.11! root       56:        void AddCycle(int32 cycle) override { used_cycle += cycle; }
1.1       root       57: 
1.1.1.5   root       58:        // 割り込みレベルが変わったことを MPU に通知
                     59:        void Interrupt(int level) override;
1.1       root       60: 
                     61:        // A-Line, F-Line 命令エミュレーションのコールバックを指定する。
                     62:        // (Human68k エミュレーションで使用)
1.1.1.11! root       63:        void SetALineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
        !            64:        void SetFLineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
1.1       root       65: 
                     66:        // FPU を持っているか
1.1.1.11! root       67:        bool HaveFPU() const { return has_fpu; }
1.1       root       68: 
1.1.1.9   root       69:        // MPU からのアクセスをエミュレートする。
1.1.1.11! root       70:        // アドレスは論理アドレスで、空間は現在のデータ空間。
        !            71:        // バスエラーなら (uint64)-1 を返す。
1.1.1.9   root       72:        uint64 Read8(uint32 addr) override;
                     73:        uint64 Read16(uint32 addr) override;
                     74:        uint64 Read32(uint32 addr) override;
                     75:        uint64 Write8(uint32 addr, uint32 data) override;
                     76:        uint64 Write16(uint32 addr, uint32 data) override;
                     77:        uint64 Write32(uint32 addr, uint32 data) override;
                     78: 
1.1.1.11! root       79:        // ホールト
1.1.1.10  root       80:        void Halt();
                     81: 
1.1.1.11! root       82:        // 基本アクセス。内部から使用する。
        !            83:        // アドレスは論理アドレスで、空間は現在の命令/データ空間。
        !            84:        // バスエラーなら C++ の例外をスローする。
        !            85:        uint32 fetch_8();
        !            86:        uint32 fetch_16();
        !            87:        uint32 fetch_32();
        !            88:        uint32 read_8(uint32 addr);
        !            89:        uint32 read_16(uint32 addr);
        !            90:        uint32 read_32(uint32 addr);
        !            91:        void write_8(uint32 addr, uint32 data);
        !            92:        void write_16(uint32 addr, uint32 data);
        !            93:        void write_32(uint32 addr, uint32 data);
        !            94: 
        !            95:        // MMU アクセス
        !            96:        uint64 TranslatePeek(uint32 laddr, uint fc, bool do_search);
        !            97: 
        !            98:        // レジスタ
        !            99:        uint16 GetIR() const    { return ir; }
        !           100:        uint16 GetIR2() const   { return ir2; }
        !           101:        // SR を変更する (Human68k から使う)
        !           102:        void SetSR(uint16);
        !           103:        uint16 GetSR() const    { return reg.GetSR(); }
        !           104: 
        !           105:        uint64 GetSRP()  const { return reg.srp.q; }
        !           106:        uint32 GetSRPh() const { return reg.srp.h; }
        !           107:        uint32 GetSRPl() const { return reg.srp.l; }
        !           108:        uint64 GetCRP()  const { return reg.crp.q; }
        !           109:        uint32 GetCRPh() const { return reg.crp.h; }
        !           110:        uint32 GetCRPl() const { return reg.crp.l; }
        !           111:        uint64 GetTT(int idx) const { return reg.tt[idx]; }
        !           112:        uint32 GetTC() const { return reg.tc; }
        !           113:        uint16 GetMMUSR() const { return reg.mmusr; }
        !           114: 
1.1       root      115:  private:
1.1.1.10  root      116:        // リセット例外コールバック
                    117:        void ResetCallback(Event& ev);
                    118: 
                    119:        // 命令実行系コールバック
                    120:        void ExecShort(Event& ev);
                    121:        void ExecFull(Event& ev);
                    122:        void ExecTrace(Event& ev);
1.1.1.5   root      123: 
1.1.1.10  root      124:        // トレース設定。デバッガから呼び出される。
                    125:        void SetTrace(bool trace_on) override;
1.1.1.9   root      126: 
1.1.1.10  root      127:        // 割り込みイベントコールバック
                    128:        void InterruptCallback(Event& ev);
                    129: 
1.1.1.11! root      130:        // 動作モード変更
        !           131:        void ChangeState(uint32 new_state);
1.1.1.8   root      132: 
1.1.1.11! root      133:        // 次の実行サイクルを Full にする。
        !           134:        void MakeNextFull();
1.1.1.8   root      135: 
1.1.1.11! root      136:        inline void CYCLE(int cc) {
        !           137:                used_cycle += cc;
        !           138:        }
        !           139:        inline void CYCLE2(int cc, int ncc) {
        !           140:                used_cycle += cc;
        !           141:                cycle_nocache += ncc - cc;
        !           142:        }
        !           143: 
        !           144:        // PC を addr に変更する。
        !           145:        // ベクタへのジャンプはここではなく JumpVector()。
        !           146:        inline void Jump(uint32 addr) {
        !           147:                // 先にブランチ履歴に記録
        !           148:                brhist.AddEntry(ppc | (IsSuper() ? 1 : 0), addr, ir << 16);
        !           149: 
        !           150:                if (__predict_false((addr & 1) != 0)) {
        !           151:                        Exception(M68K::EXCEP_ADDRERR);
        !           152:                        return;
        !           153:                }
        !           154:                reg.pc = addr;
        !           155:        }
        !           156: 
        !           157:        // -(An) 実行前にレジスタを保存する。
        !           158:        // バスエラーからの復帰用。
        !           159:        inline void save_reg_pd(int n) {
        !           160:                // 該当ビットのフラグを立てる
        !           161:                flag_pd |= (1 << n);
        !           162: 
        !           163:                // 保存
        !           164:                save_pd[n] = reg.A[n];
        !           165:        }
        !           166: 
        !           167:        // (An)+ 実行前にレジスタを保存する。
        !           168:        // バスエラーからの復帰用。
        !           169:        inline void save_reg_pi(int n) {
        !           170:                // 該当ビットのフラグを立てる
        !           171:                flag_pi |= (1 << n);
        !           172: 
        !           173:                // 保存
        !           174:                save_pi[n] = reg.A[n];
        !           175:        }
        !           176: 
        !           177:        void restore_reg_pi();
        !           178:        void restore_reg_pd();
        !           179:        void JumpVector(int vector);
        !           180: 
        !           181:  protected:
        !           182: #include "m68030ea.h"
        !           183: 
        !           184:  private:
        !           185: #include "m68030bus.h"
        !           186:        inline uint32 fetch_16_bus();
        !           187:        inline uint32 fetch_32_bus();
        !           188:        inline uint32 read_8_bus();
        !           189:        inline uint32 read_16_bus();
        !           190:        inline uint32 read_32_bus();
        !           191:        inline void write_8_bus();
        !           192:        inline void write_16_bus();
        !           193:        inline void write_32_bus();
        !           194:        // FC 指定
        !           195:        uint32 read_8_fc(uint32 addr);
        !           196:        uint32 read_16_fc(uint32 addr);
        !           197:        uint32 read_32_fc(uint32 addr);
        !           198:        void write_8_fc(uint32 addr, uint32 data);
        !           199:        void write_16_fc(uint32 addr, uint32 data);
        !           200:        void write_32_fc(uint32 addr, uint32 data);
        !           201: 
        !           202:        // 基本アクセスルーチンを使った便利サブルーチン
        !           203:        inline void push_16(uint32 data) {
        !           204:                reg.A[7] -= 2;
        !           205:                write_16(reg.A[7], data);
        !           206:        }
        !           207:        inline void push_32(uint32 data) {
        !           208:                reg.A[7] -= 4;
        !           209:                write_32(reg.A[7], data);
        !           210:        }
        !           211:        inline uint32 pop_16() {
        !           212:                uint32 data = read_16(reg.A[7]);
        !           213:                reg.A[7] += 2;
        !           214:                return data;
        !           215:        }
        !           216:        inline uint32 pop_32() {
        !           217:                uint32 data = read_32(reg.A[7]);
        !           218:                reg.A[7] += 4;
        !           219:                return data;
        !           220:        }
        !           221: 
        !           222: #define OP_PROTO(name) void __CONCAT(op_,name)()
        !           223: #include "m68030ops.h"
        !           224: #undef OP_PROTO
        !           225: 
        !           226:        void ops_divu_32_32(int r, int q);
        !           227:        void ops_divu_64_32(int r, int q);
        !           228:        void ops_divs_32_32(int r, int q);
        !           229:        void ops_divs_64_32(int r, int q);
        !           230:        void ops_movec_rc_rn();
        !           231:        void ops_movec_rn_rc();
        !           232:        void ops_movep();
        !           233:        // もともとソース内のテンプレートだった
        !           234:        void ops_movem_list_ea(int bytesize);
        !           235:        void ops_movem_ea_list(int bytesize);
        !           236:        void ops_trapcc(uint cond);
        !           237:        inline void ops_bra();
        !           238: 
        !           239:        // 68030core.cpp
        !           240:        void ops_rte();
        !           241:        void ops_stop();
        !           242:        // vm/mpu680x0.cpp
        !           243:        void ops_reset();
        !           244: 
        !           245: #include "m68030fpu.h"
        !           246:        void fpu_op_start();
        !           247: 
        !           248:        // MMU
        !           249:        bool SetSRP(uint32, uint32);
        !           250:        bool SetCRP(uint32, uint32);
        !           251:        void SetTT(int idx, uint32);
        !           252:        bool SetTC(uint32);
        !           253:        void SetMMUSR(uint16);
        !           254: 
        !           255:        bool TranslateFetch();
        !           256:        bool TranslateRead();
        !           257:        bool TranslateWrite();
        !           258: 
        !           259:        bool CheckTT() const;
        !           260:        uint32 get_fc();
        !           261:        void mmu_op_illg2();
        !           262:        void mmu_op_pflush();
        !           263:        void mmu_op_pflush_ea();
        !           264:        void mmu_op_pload();
        !           265:        void mmu_op_ptest();
        !           266:        // MMU 有効状態を更新。(TC と TT の変更で呼ばれる)
        !           267:        void mmu_enable_changed();
        !           268: 
        !           269:        // 例外
        !           270:        void GenerateExframe0(int vector, uint32 pc, uint16 sr);
        !           271:        void GenerateExframe2(int vector, uint16 sr);
        !           272:        void GenerateExframeB(int vector, uint16 sr);
        !           273:        int  ExceptionReset();
        !           274:        void ExceptionBuserr(int);
        !           275:        int  ExceptionInterrupt();
        !           276:        void Exception(int);
        !           277: 
        !           278:        // 二重バスフォールト
        !           279:        void DoubleBusFault(const char *where);
        !           280: 
        !           281:  public:
        !           282:        // レジスタ
        !           283:        m68kreg reg {};
        !           284: 
        !           285:        // MMU work
        !           286:        m68030TT mmu_tt[2] /*{}*/;
        !           287:        uint8 mmu_tt_quick[256] {};
        !           288:        m68030TC mmu_tc /*{}*/;
        !           289:        m68030ATC atc {this};
        !           290:        bool mmu_enable {};             // MMU が有効なら true
        !           291: 
        !           292:        // バス
        !           293:        m68kbus bus {};
        !           294: 
        !           295:  private:
        !           296:        uint16 ir {};
        !           297:        uint16 ir2 {};
        !           298:        // 現在実行中の命令の先頭アドレス
        !           299:        uint32 ppc {};
        !           300: 
        !           301:        // レジスタ(状態保存用)
        !           302:        uint32 save_pd[8] {};   // -(An) を保存
        !           303:        uint32 save_pi[8] {};   // (An)+ を保存
        !           304:        uint8  flag_pd {};              // -(An) のどのレジスタを保存したか
        !           305:        uint8  flag_pi {};              // (An)+ のどのレジスタを保存したか
        !           306: 
        !           307:        // FPU
        !           308:        int has_fpu {};                 // 0:FPUなし、1:68881、2:68882(?)
        !           309:        bool fpu_dirty {};
        !           310:        struct fpemu fe {};
        !           311: 
        !           312:        // CPU の実行状態
        !           313:        uint32 cpu_state {};
1.1.1.7   root      314: 
1.1.1.10  root      315:        // 割り込みペンディング
                    316:        bool intr_pending {};
                    317: 
1.1.1.11! root      318:        // 現在の外部割り込みレベル
        !           319:        int intr_level {};
        !           320: 
        !           321:        // 電源オンからの累積消費サイクル
        !           322:        uint64 used_cycle {};
        !           323: 
        !           324:        int32 cycle_nocache {};         // ノーキャッシュケースの時の追加分
        !           325: 
        !           326:        // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
        !           327:        // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
        !           328:        // コールバック側で処理完了したら true を返す。
        !           329:        // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
        !           330:        bool (*aline_callback)(MPU680x0Device *, void *) {};
        !           331:        void *aline_arg {};
        !           332:        bool (*fline_callback)(MPU680x0Device *, void *) {};
        !           333:        void *fline_arg {};
        !           334: 
        !           335:        // ブランチ履歴 (例外履歴を含む)
        !           336:        BranchHistory_m680x0 brhist { OBJ_MPU_BRHIST };
        !           337:        // 例外履歴のみ
        !           338:        BranchHistory_m680x0 exhist { OBJ_MPU_EXHIST };
        !           339: 
        !           340:        // 割り込みイベント
        !           341:        Event intr_event { this };
        !           342: 
1.1.1.10  root      343:        // トレースでコールバックを差し替えることができるように
                    344:        // イベントコールバックを変数に入れてある
                    345:        EventCallback_t exec_short {};
                    346:        EventCallback_t exec_full {};
1.1.1.4   root      347: 
1.1.1.11! root      348:        // レジスタモニター
        !           349:        DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
        !           350:        Monitor reg_monitor { this };
        !           351: 
        !           352:        // ATC モニター
        !           353:        DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
        !           354:        Monitor atc_monitor { this };
        !           355: 
        !           356:        InterruptDevice *interruptdev {};
        !           357:        VectorTable *vectortable {};
1.1       root      358: };
                    359: 
1.1.1.11! root      360: static inline MPU680x0Device *GetMPU680x0Device() {
        !           361:        return Object::GetObject<MPU680x0Device>(OBJ_MPU);
        !           362: }

unix.superglobalmegacorp.com

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