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

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: //
1.1.1.17  root        8: // MPU (MC68030/MC68040)
1.1.1.10  root        9: //
1.1       root       10: 
1.1.1.19! root       11: // ログレベル基準。
        !            12: // 1: 状態変化などの概要
        !            13: // 2: 命令などによる詳細
        !            14: // 3: メモリアクセスの概要
        !            15: // 4: メモリアクセスの詳細(MMU等)
        !            16: // 5: デバッガアクセスのデバッグ用
        !            17: 
1.1       root       18: #pragma once
                     19: 
                     20: #include "mpu.h"
1.1.1.11  root       21: #include "branchhistory.h"
1.1.1.13  root       22: #include "bus.h"
1.1.1.15  root       23: #include "m680x0.h"
1.1.1.11  root       24: #include "m68030mmu.h"
1.1.1.15  root       25: #include <array>
1.1.1.11  root       26: 
                     27: class InterruptDevice;
1.1.1.13  root       28: class m68030Cache;
1.1.1.14  root       29: struct m68030CacheLine;
1.1.1.15  root       30: enum class m68030MPUType;
                     31: class m68040TT;
                     32: class m68040TC;
                     33: class m68040ATC;
                     34: class m68040ATCEntry;
1.1       root       35: 
1.1.1.14  root       36: class MPU680x0Device : public MainMPUDevice
1.1       root       37: {
1.1.1.14  root       38:        using inherited = MainMPUDevice;
1.1.1.19! root       39:        friend class m68030PageTableOp;
1.1.1.11  root       40: 
1.1       root       41:  public:
1.1.1.7   root       42:        MPU680x0Device();
1.1.1.13  root       43:        ~MPU680x0Device() override;
1.1       root       44: 
1.1.1.2   root       45:        bool Init() override;
1.1.1.10  root       46:        void ResetHard(bool poweron) override;
1.1       root       47: 
                     48:        // 現在の PPC を取得
1.1.1.11  root       49:        uint32 GetPPC() const override { return ppc; }
1.1       root       50: 
1.1.1.10  root       51:        // 現在の VBR を取得
1.1.1.11  root       52:        uint32 GetVBR() const override { return reg.vbr; }
                     53: 
1.1.1.15  root       54:        // MPU 種別を取得
                     55:        m680x0MPUType GetMPUType() const { return mpu_type; }
                     56: 
                     57:        // FPU
                     58:        m680x0FPUType GetFPUType() const { return fpu_type; }
                     59:        bool HasFPU() const     { return fpu_type.Is4060FPU() || fpu_type.Is6888x(); }
                     60: 
1.1.1.13  root       61:        // MPU 名を取得
1.1.1.15  root       62:        const char *GetMPUName() const override { return mpu_name; }
1.1.1.13  root       63: 
1.1.1.11  root       64:        bool IsSuper() const    { return reg.s; }
                     65:        bool IsMaster() const   { return reg.m; }
                     66: 
1.1.1.5   root       67:        // 割り込みレベルが変わったことを MPU に通知
                     68:        void Interrupt(int level) override;
1.1       root       69: 
                     70:        // A-Line, F-Line 命令エミュレーションのコールバックを指定する。
                     71:        // (Human68k エミュレーションで使用)
1.1.1.11  root       72:        void SetALineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
                     73:        void SetFLineCallback(bool (*callback)(MPU680x0Device*, void*), void *arg);
1.1       root       74: 
1.1.1.14  root       75:        // バーストアクセスをサポートするか
                     76:        void EnableBurstAccess(bool enable) { has_burst_access = enable; }
                     77: 
1.1.1.13  root       78:        void SetCI() override {
                     79:                bus.ci = true;
                     80:        }
1.1.1.9   root       81: 
1.1.1.11  root       82:        // ホールト
1.1.1.10  root       83:        void Halt();
                     84: 
1.1.1.11  root       85:        // 基本アクセス。内部から使用する。
                     86:        // アドレスは論理アドレスで、空間は現在の命令/データ空間。
                     87:        // バスエラーなら C++ の例外をスローする。
1.1.1.15  root       88:        virtual uint32 fetch_2() = 0;
                     89:        virtual uint32 fetch_4() = 0;
1.1.1.14  root       90:        uint32 read_n(uint32 laddr, uint size) {
                     91:                busaddr addr =
                     92:                        busaddr(laddr) | fc_data | BusAddr::R | busaddr::Size(size);
                     93:                return read_data(addr);
                     94:        }
                     95:        void write_n(uint32 laddr, uint size, uint32 data) {
                     96:                busaddr addr =
                     97:                        busaddr(laddr) | fc_data | BusAddr::W | busaddr::Size(size);
                     98:                write_data(addr, data);
                     99:        }
                    100:        uint32 read_1(uint32 laddr) { return read_n(laddr, 1); }
                    101:        uint32 read_2(uint32 laddr) { return read_n(laddr, 2); }
                    102:        uint32 read_4(uint32 laddr) { return read_n(laddr, 4); }
                    103:        void write_1(uint32 laddr, uint32 data) { write_n(laddr, 1, data); }
                    104:        void write_2(uint32 laddr, uint32 data) { write_n(laddr, 2, data); }
                    105:        void write_4(uint32 laddr, uint32 data) { write_n(laddr, 4, data); }
1.1.1.11  root      106: 
                    107:        // MMU アクセス
1.1.1.15  root      108:        virtual busaddr TranslatePeek(busaddr laddr) = 0;
1.1.1.14  root      109:        // 統計
1.1.1.15  root      110:        virtual void CalcStat() = 0;
1.1.1.11  root      111: 
                    112:        // レジスタ
                    113:        uint16 GetIR() const    { return ir; }
                    114:        uint16 GetIR2() const   { return ir2; }
                    115:        // SR を変更する (Human68k から使う)
                    116:        void SetSR(uint16);
                    117:        uint16 GetSR() const    { return reg.GetSR(); }
                    118: 
1.1.1.15  root      119:  protected:
1.1.1.10  root      120:        // リセット例外コールバック
1.1.1.18  root      121:        void ResetCallback(Event *);
1.1.1.10  root      122: 
                    123:        // 命令実行系コールバック
1.1.1.18  root      124:        void ExecShort(Event *);
                    125:        void ExecFull(Event *);
                    126:        void ExecTrace(Event *);
1.1.1.5   root      127: 
1.1.1.10  root      128:        // トレース設定。デバッガから呼び出される。
1.1.1.17  root      129:        void SetTrace(bool enable) override;
1.1.1.9   root      130: 
1.1.1.10  root      131:        // 割り込みイベントコールバック
1.1.1.18  root      132:        void InterruptCallback(Event *);
1.1.1.10  root      133: 
1.1.1.11  root      134:        // 次の実行サイクルを Full にする。
                    135:        void MakeNextFull();
1.1.1.8   root      136: 
1.1.1.11  root      137:        inline void CYCLE(int cc) {
                    138:                used_cycle += cc;
                    139:        }
1.1.1.17  root      140:        // 副作用前提のマクロなので do-while にしない。
                    141: #define CYCLE3(name)   used_cycle += cycle_table[__CONCAT(cycidx_,name)]
1.1.1.11  root      142: 
                    143:        // PC を addr に変更する。
                    144:        // ベクタへのジャンプはここではなく JumpVector()。
                    145:        inline void Jump(uint32 addr) {
                    146:                // 先にブランチ履歴に記録
1.1.1.12  root      147:                brhist.AddEntry(ppc | (IsSuper() ? 1 : 0), addr, ir);
1.1.1.11  root      148: 
                    149:                if (__predict_false((addr & 1) != 0)) {
1.1.1.12  root      150:                        ExceptionBuserr(M68K::EXCEP_ADDRERR);
1.1.1.11  root      151:                        return;
                    152:                }
                    153:                reg.pc = addr;
                    154:        }
                    155: 
                    156:        // -(An) 実行前にレジスタを保存する。
                    157:        // バスエラーからの復帰用。
                    158:        inline void save_reg_pd(int n) {
                    159:                // 該当ビットのフラグを立てる
1.1.1.18  root      160:                flag_pd |= (1U << n);
1.1.1.11  root      161: 
                    162:                // 保存
                    163:                save_pd[n] = reg.A[n];
                    164:        }
                    165: 
                    166:        // (An)+ 実行前にレジスタを保存する。
                    167:        // バスエラーからの復帰用。
                    168:        inline void save_reg_pi(int n) {
                    169:                // 該当ビットのフラグを立てる
1.1.1.18  root      170:                flag_pi |= (1U << n);
1.1.1.11  root      171: 
                    172:                // 保存
                    173:                save_pi[n] = reg.A[n];
                    174:        }
                    175: 
1.1.1.14  root      176:        // -(An) 実行前にレジスタを(まだ保存してなければ)保存する。
                    177:        // 1命令で同じレジスタを2回 -(An) する可能性がある命令用。
                    178:        inline void save_reg_pd_if(int n) {
1.1.1.18  root      179:                if ((flag_pd & (1U << n)) == 0) {
1.1.1.14  root      180:                        save_reg_pd(n);
                    181:                }
                    182:        }
                    183:        // (An)+ 実行前にレジスタを(まだ保存してなければ)保存する。
                    184:        // 1命令で同じレジスタを2回 (An)+ する可能性がある命令用。
                    185:        inline void save_reg_pi_if(int n) {
1.1.1.18  root      186:                if ((flag_pi & (1U << n)) == 0) {
1.1.1.14  root      187:                        save_reg_pi(n);
                    188:                }
                    189:        }
                    190: 
1.1.1.11  root      191:        void restore_reg_pi();
                    192:        void restore_reg_pd();
1.1.1.14  root      193:        void JumpVector(uint vector, bool from_buserr);
1.1.1.11  root      194: 
                    195:  protected:
1.1.1.15  root      196: #include "m680x0ea.h"
1.1.1.11  root      197: 
1.1.1.15  root      198:  protected:
1.1.1.11  root      199:        // 基本アクセスルーチンを使った便利サブルーチン
1.1.1.14  root      200:        inline void push_2(uint32 data) {
1.1.1.11  root      201:                reg.A[7] -= 2;
1.1.1.14  root      202:                write_2(reg.A[7], data);
1.1.1.11  root      203:        }
1.1.1.14  root      204:        inline void push_4(uint32 data) {
1.1.1.11  root      205:                reg.A[7] -= 4;
1.1.1.14  root      206:                write_4(reg.A[7], data);
1.1.1.11  root      207:        }
1.1.1.14  root      208:        inline uint32 pop_2() {
                    209:                uint32 data = read_2(reg.A[7]);
1.1.1.11  root      210:                reg.A[7] += 2;
                    211:                return data;
                    212:        }
1.1.1.14  root      213:        inline uint32 pop_4() {
                    214:                uint32 data = read_4(reg.A[7]);
1.1.1.11  root      215:                reg.A[7] += 4;
                    216:                return data;
                    217:        }
                    218: 
1.1.1.13  root      219:        // バスアクセス
1.1.1.15  root      220:        virtual uint32 read_data(busaddr addr) = 0;
                    221:        virtual void write_data(busaddr addr, uint32 data) = 0;
1.1.1.14  root      222: 
1.1.1.15  root      223:        // 物理バスアクセス
1.1.1.19! root      224:        busdata read_phys(const busaddr);
        !           225:        busdata write_phys(const busaddr, uint32 data);
        !           226:        bool read_phys_burst(busaddr, uint32 *dst);
1.1.1.15  root      227:        busdata read_phys_4(uint32 addr);
                    228:        busdata write_phys_4(uint32 addr, uint32 data);
1.1.1.13  root      229: 
1.1.1.11  root      230: #define OP_PROTO(name) void __CONCAT(op_,name)()
1.1.1.15  root      231: #include "m680x0ops.h"
1.1.1.11  root      232: #undef OP_PROTO
                    233: 
1.1.1.14  root      234:        void ops_divu_32_32(uint r, uint q);
                    235:        void ops_divu_64_32(uint r, uint q);
                    236:        void ops_divs_32_32(uint r, uint q);
                    237:        void ops_divs_64_32(uint r, uint q);
1.1.1.15  root      238:        void ops_link(int32 imm);
1.1.1.11  root      239:        void ops_movec_rc_rn();
                    240:        void ops_movec_rn_rc();
1.1.1.15  root      241:        virtual bool ops_movec_rc_rn_cpu(uint c, uint n) = 0;
                    242:        virtual bool ops_movec_rn_rc_cpu(uint c, uint n) = 0;
1.1.1.11  root      243:        void ops_movep();
                    244:        // もともとソース内のテンプレートだった
                    245:        void ops_movem_list_ea(int bytesize);
                    246:        void ops_movem_ea_list(int bytesize);
                    247:        void ops_trapcc(uint cond);
                    248:        inline void ops_bra();
1.1.1.15  root      249:        busaddr translate_fc40(busaddr);
1.1.1.11  root      250: 
                    251:        void ops_rte();
                    252:        void ops_stop();
                    253:        void ops_reset();
1.1.1.15  root      254:        virtual void ops_mmu30() = 0;
                    255:        virtual void ops_mmu40_pflush() = 0;
1.1.1.11  root      256: 
1.1.1.15  root      257:        void ResetFPU(bool hard);
                    258:        void fpu_init();
                    259:        uint32 cea_fpu(int bytes);
1.1.1.16  root      260:        uint32 cea_fpulc(int bytes);
1.1.1.15  root      261:        void read_8(uint32 addr, uint32 *data);
                    262:        void read_12(uint32 addr, uint32 *data);
                    263:        void write_8(uint32 addr, const uint32 *data);
                    264:        void write_12(uint32 addr, const uint32 *data);
                    265: 
                    266:        void fpu_op_illg();
                    267:        void fpu_op_illg2();
                    268: 
                    269:        void fpu_op_fgen_reg();
                    270:        void fpu_op_fgen_mem();
                    271:        void fgen(const uint32 *srcdata, uint srcsize_id);
                    272:        void fgen881pre(uint dstnum, const uint32 *srcdata, uint srcsize_id);
                    273:        bool fgen040pre(uint opmode, uint dst, const uint32 *src, uint srcsize);
                    274:        void fpu_op_fmovecr();
                    275:        void fpu_op_fmove_to_mem();
                    276:        void fpu_op_fmove_b_mem();
                    277:        void fpu_op_fmove_w_mem();
                    278:        void fpu_op_fmove_l_mem();
                    279:        void fpu_op_fmove_s_mem();
                    280:        void fpu_op_fmove_d_mem();
                    281:        void fpu_op_fmove_x_mem();
                    282:        void fpu_op_fmove_p_mem();
                    283:        void fpu_op_fmove_ea2ctl();
                    284:        void fpu_op_fmovem_ea2ctl();
                    285:        void fpu_op_fmove_ctl2ea();
                    286:        void fpu_op_fmovem_ctl2ea();
                    287:        void fpu_op_fmovem_ea2reg();
                    288:        void fpu_op_fmovem_reg2ea();
                    289:        void fpu_op_fscc();
                    290:        void fpu_op_fdbcc();
                    291:        void fpu_op_ftrapcc_w();
                    292:        void fpu_op_ftrapcc_l();
                    293:        void fpu_op_ftrapcc();
                    294:        void fpu_op_fbcc_w();
                    295:        void fpu_op_fbcc_l();
                    296:        void fpu_op_fsave();
                    297:        void fpu_op_frestore();
                    298:        void fpu_op_fsave_frame_noimpl(std::array<uint32, 13>&);
                    299: 
                    300:        static struct fpframe initial_fpframe;
                    301:        static const uint32 fsave_frame_null[1];
                    302:        static const uint32 fsave_frame_idle_68881[7];
                    303:        static const uint32 fsave_frame_idle_68040[1];
1.1.1.11  root      304: 
1.1.1.13  root      305:        // キャッシュ
1.1.1.15  root      306:        virtual void SetCACR(uint32) = 0;
1.1.1.11  root      307: 
                    308:        // 例外
1.1.1.15  root      309:        void GenerateExframe0(uint vector, uint16 sr, uint32 pc);
                    310:        void GenerateExframe2(uint vector, uint16 sr, uint32 pc, uint32 addr);
1.1.1.16  root      311:        void GenerateExframe4(uint vector, uint16 sr, uint32 ea);
1.1.1.15  root      312:        void GenerateExframe7(uint vector, uint16 sr);
1.1.1.14  root      313:        void GenerateExframeB(uint vector, uint16 sr);
1.1.1.11  root      314:        int  ExceptionReset();
1.1.1.14  root      315:        void ExceptionBuserr(uint vector);
1.1.1.13  root      316:        uint64 ExceptionInterrupt();
1.1.1.19! root      317:        void ExceptionTrap0();
1.1.1.12  root      318:        void ExceptionTrap15();
1.1.1.17  root      319:        void ExceptionFLine();
1.1.1.15  root      320:        void ExceptionFP(uint vector);
1.1.1.16  root      321:        void ExceptionFPLC(uint ea);
1.1.1.14  root      322:        void Exception(uint vector);
1.1.1.17  root      323:        void ExceptionGeneric(uint ext_vector, uint32 info);
1.1.1.15  root      324: 
                    325:        // リセット例外の CPU 固有部分。
                    326:        virtual void ResetCache() = 0;
                    327:        virtual void ResetMMU() = 0;
1.1.1.11  root      328: 
                    329:        // 二重バスフォールト
                    330:        void DoubleBusFault(const char *where);
                    331: 
                    332:  public:
                    333:        // レジスタ
                    334:        m68kreg reg {};
                    335:        bool mmu_enable {};             // MMU が有効なら true
                    336: 
                    337:        // バス
                    338:        m68kbus bus {};
1.1.1.13  root      339:        // 現在の特権状態でのプログラム空間とデータ空間アクセス用。
                    340:        busaddr fc_inst {};             // こっちは R 含む
                    341:        busaddr fc_data {};             // こっちは R/W 含まない
1.1.1.11  root      342: 
1.1.1.15  root      343:  protected:
1.1.1.11  root      344:        uint16 ir {};
                    345:        uint16 ir2 {};
                    346:        // 現在実行中の命令の先頭アドレス
                    347:        uint32 ppc {};
                    348: 
1.1.1.17  root      349:        // サイクル数表
                    350:        const int8 *cycle_table {};
                    351:        static const int8 cycle_table_030cc[];
                    352:        static const int8 cycle_table_030ncc[];
                    353:        static const int8 cycle_table_040[];
                    354: 
1.1.1.11  root      355:        // レジスタ(状態保存用)
                    356:        uint32 save_pd[8] {};   // -(An) を保存
                    357:        uint32 save_pi[8] {};   // (An)+ を保存
                    358:        uint8  flag_pd {};              // -(An) のどのレジスタを保存したか
                    359:        uint8  flag_pi {};              // (An)+ のどのレジスタを保存したか
                    360: 
                    361:        // FPU
1.1.1.15  root      362:        enum {
                    363:                FPU_STATE_NULL,         // 内部状態なし
                    364:                FPU_STATE_IDLE,         // FRESTORE 以降に FPU 命令を実行した
                    365:                FPU_STATE_BUSY,         // ビジー状態 (実装していない)
                    366:                FPU_STATE_NOIMPL,       // 浮動小数点未実装命令
                    367:        } fpu_state {};
1.1.1.11  root      368:        struct fpemu fe {};
                    369: 
1.1.1.15  root      370:        // 68040 FPU 用の内部状態
                    371:        struct FPU40 {
                    372:                uint32 reg1b;           // CMDREG1B
                    373:                uint32 ea;                      // 計算した EA
                    374:                enum {
                    375:                        // NONE は未決定だが Unnormal/Denormal ではないいずれかなので
                    376:                        // UNNORMAL より小さい値にしておく。(大小比較する)
                    377:                        TAG_NONE                = -1,
                    378:                        TAG_NORMAL              = 0,
                    379:                        TAG_ZERO                = 1,
                    380:                        TAG_INF                 = 2,
                    381:                        TAG_NAN                 = 3,
                    382:                        TAG_UNNORMAL    = 4,    // .X denormal or unnormal
                    383:                        TAG_DENORMAL    = 5,    // .S/.D denormal
                    384: 
                    385:                        // 内部表現 (下位3ビットは維持したまま上位で詳細を区別する)
                    386:                        TAG_DENORMAL_S  = (0x10 | TAG_DENORMAL),
                    387:                        TAG_DENORMAL_D  = (0x20 | TAG_DENORMAL),
                    388:                        TAG_DENORMAL_X  = (0x30 | TAG_UNNORMAL),
                    389:                        TAG_UNNORMAL_X  = (0x40 | TAG_UNNORMAL),
                    390:                        // PACKED のときタグは undefined となっている。仕方ないので 7。
                    391:                        TAG_PACKED              = 0x07 ,
                    392:                };
                    393:                int32 stag;
                    394:                int32 dtag;
                    395:                uint32 etemp[3];
                    396:                uint32 fptemp[3];
                    397:                enum {
                    398:                        E1 = 0x04000000,
                    399:                        E3 = 0x02000000,
                    400:                };
                    401:                uint32 eflag;
                    402:                bool post;                      // T bit, post-op exception
                    403: 
                    404:                // 表示用のフラグ。例外発生から FSAVE の間までが有効。
                    405:                bool enable;
                    406:        } fpu40 {};
                    407: 
1.1.1.10  root      408:        // 割り込みペンディング
                    409:        bool intr_pending {};
                    410: 
1.1.1.11  root      411:        // 現在の外部割り込みレベル
                    412:        int intr_level {};
                    413: 
                    414:        // 電源オンからの累積消費サイクル
                    415:        uint64 used_cycle {};
                    416: 
1.1.1.13  root      417:        // 今回のバスウェイト [nsec]
                    418:        uint64 buswait {};
                    419: 
1.1.1.14  root      420:        // 外部バスがバースト転送に対応していれば true
                    421:        bool has_burst_access {};
                    422: 
1.1.1.15  root      423:        // MPU/FPU 種別
                    424:        m680x0MPUType mpu_type {};
                    425:        m680x0FPUType fpu_type {};
                    426:        const char *mpu_name {};
                    427: 
1.1.1.11  root      428:        // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。
                    429:        // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。
                    430:        // コールバック側で処理完了したら true を返す。
                    431:        // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。
                    432:        bool (*aline_callback)(MPU680x0Device *, void *) {};
                    433:        void *aline_arg {};
                    434:        bool (*fline_callback)(MPU680x0Device *, void *) {};
                    435:        void *fline_arg {};
                    436: 
                    437:        // ブランチ履歴 (例外履歴を含む)
                    438:        BranchHistory_m680x0 brhist { OBJ_MPU_BRHIST };
                    439:        // 例外履歴のみ
                    440:        BranchHistory_m680x0 exhist { OBJ_MPU_EXHIST };
                    441: 
1.1.1.19! root      442:        // NetBSD カーネルのエントリポイント。
        !           443:        // TRAP#0 の履歴でシステムコールを判定するのに使う。
        !           444:        uint32 netbsd_entrypoint {};
        !           445: 
1.1.1.11  root      446:        // 割り込みイベント
1.1.1.18  root      447:        Event *intr_event {};
1.1.1.11  root      448: 
1.1.1.10  root      449:        // トレースでコールバックを差し替えることができるように
                    450:        // イベントコールバックを変数に入れてある
                    451:        EventCallback_t exec_short {};
                    452:        EventCallback_t exec_full {};
1.1.1.4   root      453: 
1.1.1.15  root      454:        // モニター
1.1.1.19! root      455:        void MonitorScreenRegCommon(TextScreen&, m68kreg&, uint32, uint32);
        !           456:        int  MonitorScreenFPU(TextScreen&, int y, m68kreg&);
1.1.1.15  root      457:        Monitor *reg_monitor {};
                    458:        Monitor *atc_monitor {};
                    459:        Monitor *cache_monitor {};
1.1.1.11  root      460: 
1.1.1.15  root      461:        InterruptDevice *interruptdev {};
                    462:        VectorTable *vectortable {};
                    463: };
                    464: 
                    465: class MPU68030Device : public MPU680x0Device
                    466: {
                    467:        using inherited = MPU680x0Device;
                    468: 
                    469:  public:
                    470:        MPU68030Device();
                    471:        ~MPU68030Device() override;
                    472: 
                    473:        void SetLogLevel(int loglevel_) override;
1.1.1.19! root      474:        void ResetHard(bool poweron) override;
1.1.1.11  root      475: 
1.1.1.15  root      476:        uint64 GetSRP()  const { return reg.srp.q; }
                    477:        uint32 GetSRPh() const { return reg.srp.h; }
                    478:        uint32 GetSRPl() const { return reg.srp.l; }
                    479:        uint64 GetCRP()  const { return reg.crp.q; }
                    480:        uint32 GetCRPh() const { return reg.crp.h; }
                    481:        uint32 GetCRPl() const { return reg.crp.l; }
                    482:        uint64 GetTT(int idx) const { return reg.tt[idx]; }
                    483:        uint32 GetTC() const { return reg.tc; }
                    484:        uint16 GetMMUSR() const { return reg.mmusr; }
                    485: 
                    486:        busaddr TranslatePeek(busaddr laddr) override;
                    487:        void CalcStat() override;
                    488: 
1.1.1.19! root      489:        // fc に対する文字列("UD"とか)を返す。
        !           490:        static const char *FCstr(uint fc_) {
        !           491:                return &fcstr[fc_ * 4];
        !           492:        }
        !           493: 
1.1.1.15  root      494:  private:
                    495:        // リセット
                    496:        void ResetCache() override;
                    497:        void ResetMMU() override;
                    498: 
                    499:        // 命令
                    500:        bool ops_movec_rc_rn_cpu(uint c, uint n) override;
                    501:        bool ops_movec_rn_rc_cpu(uint c, uint n) override;
                    502:        void ops_mmu30() override;
                    503:        void ops_mmu40_pflush() override;
                    504:        uint32 get_fc();
1.1.1.19! root      505:        void ops_mmu30_illg2();
        !           506:        void ops_mmu30_pflusha();
        !           507:        void ops_mmu30_pflush();
        !           508:        void ops_mmu30_pflush_ea();
        !           509:        void ops_mmu30_pload();
        !           510:        void ops_mmu30_ptest();
        !           511:        uint32 ptest_atc(const busaddr);
        !           512:        uint32 ptest_search(uint level, const busaddr, uint rn);
1.1.1.15  root      513: 
                    514:        // バスアクセス
                    515:        uint32 fetch_2() override;
                    516:        uint32 fetch_4() override;
                    517:        uint32 read_data(busaddr addr) override;
                    518:        busdata read_nocache(busaddr addr);
                    519:        void write_data(busaddr addr, uint32 data) override;
                    520: 
                    521:        busdata read_cache(m68030Cache *cache, busaddr addr);
1.1.1.19! root      522:        busdata read_single(busaddr);
        !           523:        busdata fill_single(busaddr, busdata);
1.1.1.15  root      524:        busdata write_bus(busaddr addr, uint32 data);
                    525: 
                    526:        // キャッシュ
                    527:        void SetCACR(uint32) override;
                    528: 
                    529:        // MMU
1.1.1.19! root      530:        busaddr TranslateRead(const busaddr laddr);
        !           531:        busaddr TranslateWrite(const busaddr laddr);
        !           532:        busaddr TTMatch(const busaddr laddr) const;
        !           533:        void PageTableSearch(const busaddr laddr, m68030ATCLine *);
1.1.1.15  root      534: 
                    535:        bool SetSRP(uint32, uint32);
                    536:        bool SetCRP(uint32, uint32);
                    537:        void SetTT(int idx, uint32);
                    538:        bool SetTC(uint32);
                    539:        void SetMMUSR(uint16);
                    540:        // MMU 有効状態を更新。(TC と TT の変更で呼ばれる)
                    541:        void mmu_enable_changed();
                    542: 
                    543:  public:
                    544:        // MMU work
                    545:        m68030TT mmu_tt[2] /*{}*/;
                    546:        m68030TC mmu_tc /*{}*/;
                    547:        m68030ATC atc {this};
                    548: 
                    549:  private:
1.1.1.19! root      550:        DECLARE_MONITOR_SCREEN(MonitorScreenReg);
        !           551:        DECLARE_MONITOR_SCREEN(MonitorScreenATC);
        !           552:        DECLARE_MONITOR_SCREEN(MonitorScreenCache);
        !           553:        int MonitorScreenMMU(TextScreen&, int, m68kreg&);
        !           554:        int MonitorScreenCache1(TextScreen&, int y, m68030Cache *,
1.1.1.14  root      555:                char (*)(const m68030CacheLine&));
1.1.1.13  root      556: 
1.1.1.15  root      557:        // キャッシュ
                    558:        std::unique_ptr<m68030Cache> icache /*{}*/;
                    559:        std::unique_ptr<m68030Cache> dcache /*{}*/;
1.1.1.19! root      560: 
        !           561:        static const char fcstr[];
1.1.1.15  root      562: };
                    563: 
                    564: class MPU68040Device : public MPU680x0Device
                    565: {
                    566:        using inherited = MPU680x0Device;
1.1.1.19! root      567:        friend class WXPageTable68040Window;
1.1.1.15  root      568: 
                    569:  public:
                    570:        MPU68040Device();
                    571:        ~MPU68040Device() override;
                    572: 
                    573:        uint32 GetITT(int n) const      { return reg.itt[n]; }
                    574:        uint32 GetDTT(int n) const      { return reg.dtt[n]; }
                    575:        uint32 GetSRP()         const   { return reg.srp40; }
                    576:        uint32 GetURP()         const   { return reg.urp40; }
                    577:        uint32 GetTC()          const   { return reg.tc40; }
                    578:        uint32 GetMMUSR()       const   { return reg.mmusr40; }
                    579: 
                    580:        busaddr TranslatePeek(busaddr laddr) override;
                    581:        void CalcStat() override;
                    582: 
1.1.1.19! root      583:        // デバッガ (pf コマンド) からも使う。
        !           584:        static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd);
        !           585:        static std::string GetFPUTagName(int32);
        !           586: 
1.1.1.15  root      587:  private:
                    588:        // リセット
                    589:        void ResetCache() override;
                    590:        void ResetMMU() override;
                    591: 
                    592:        // 命令
                    593:        bool ops_movec_rc_rn_cpu(uint c, uint n) override;
                    594:        bool ops_movec_rn_rc_cpu(uint c, uint n) override;
                    595:        void ops_mmu30() override;
                    596:        void ops_mmu40_pflush() override;
                    597: 
                    598:        // バスアクセス
                    599:        uint32 fetch_2() override;
                    600:        uint32 fetch_4() override;
                    601:        uint32 read_data(busaddr addr) override;
                    602:        busdata read_nocache(busaddr addr);
                    603:        void write_data(busaddr addr, uint32 data) override;
                    604: 
                    605:        // キャッシュ
                    606:        void SetCACR(uint32) override;
                    607: 
                    608:        // MMU
1.1.1.19! root      609:        busaddr TranslateRead(const busaddr laddr);
        !           610:        busaddr TranslateWrite(const busaddr laddr);
        !           611:        m68040TT *TTMatch(std::array<std::unique_ptr<m68040TT>, 2>&,
        !           612:                const busaddr) const;
        !           613:        busaddr LookupATC(m68040ATC&, const busaddr);
        !           614:        void Search(m68040ATCEntry *, const busaddr);
1.1.1.15  root      615:        uint32 PeekDesc(uint32 base, uint32 idx);
                    616: 
                    617:        void SetTT(m68040TT *, uint32);
                    618:        void SetSRP(uint32);
                    619:        void SetURP(uint32);
                    620:        void SetTC(uint32);
                    621:        // MMU 有効状態を更新。(TC と *TTn の変更で呼ばれる)
                    622:        void mmu_enable_changed();
                    623: 
1.1.1.19! root      624:        DECLARE_MONITOR_SCREEN(MonitorScreenReg);
        !           625:        DECLARE_MONITOR_SCREEN(MonitorScreenATC);
        !           626:        int MonitorScreenMMU(TextScreen&, int, m68kreg&);
        !           627:        void MonitorScreenTT(TextScreen&, int x, int y, const char *, uint32);
        !           628:        void MonitorScreenATC1(TextScreen&, int, bool, const m68040ATC *);
1.1.1.15  root      629: 
                    630:        // FPU
1.1.1.19! root      631:        void MonitorScreenFPU40(TextScreen&, int y, const FPU40&);
1.1.1.15  root      632: 
                    633:        std::array<std::unique_ptr<m68040TT>, 2> mmu_itt /*{}*/;
                    634:        std::array<std::unique_ptr<m68040TT>, 2> mmu_dtt /*{}*/;
                    635:        std::unique_ptr<m68040TC> mmu_tc /*{}*/;
                    636: 
                    637:        std::unique_ptr<m68040ATC> atc_inst /*{}*/;
                    638:        std::unique_ptr<m68040ATC> atc_data /*{}*/;
1.1       root      639: };
                    640: 
1.1.1.15  root      641: // ブートストラップ
                    642: extern MPU680x0Device *NewMPU680x0Device();
                    643: 
1.1.1.13  root      644: // これを呼びたい人は mpu を持ってるはず。
1.1.1.19! root      645: inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) {
1.1.1.13  root      646:        return dynamic_cast<MPU680x0Device*>(mpu_);
1.1.1.11  root      647: }

unix.superglobalmegacorp.com

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