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

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

unix.superglobalmegacorp.com

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