--- nono/vm/mpu680x0.h 2026/04/29 17:05:33 1.1.1.15 +++ nono/vm/mpu680x0.h 2026/04/29 17:06:00 1.1.1.19 @@ -5,15 +5,21 @@ // // -// MPU (MC68030) +// MPU (MC68030/MC68040) // +// ログレベル基準。 +// 1: 状態変化などの概要 +// 2: 命令などによる詳細 +// 3: メモリアクセスの概要 +// 4: メモリアクセスの詳細(MMU等) +// 5: デバッガアクセスのデバッグ用 + #pragma once #include "mpu.h" #include "branchhistory.h" #include "bus.h" -#include "event.h" #include "m680x0.h" #include "m68030mmu.h" #include @@ -30,12 +36,7 @@ class m68040ATCEntry; class MPU680x0Device : public MainMPUDevice { using inherited = MainMPUDevice; - friend class m68030MMU; - - // CPU の実行状態 - static const uint32 CPU_STATE_NORMAL = 0; - static const uint32 CPU_STATE_STOP = 1; - static const uint32 CPU_STATE_HALT = 2; + friend class m68030PageTableOp; public: MPU680x0Device(); @@ -63,13 +64,6 @@ class MPU680x0Device : public MainMPUDev bool IsSuper() const { return reg.s; } bool IsMaster() const { return reg.m; } - // CPU の実行状態 (uint32) を返す。 - uint32 GetState() const { return cpu_state; } - - // 現在アクセス中の論理アドレス、物理アドレスを取得。 - uint32 GetLaddr() const override { return bus.laddr.Addr(); } - uint32 GetPaddr() const override { return bus.paddr.Addr(); } - // 割り込みレベルが変わったことを MPU に通知 void Interrupt(int level) override; @@ -124,21 +118,18 @@ class MPU680x0Device : public MainMPUDev protected: // リセット例外コールバック - void ResetCallback(Event& ev); + void ResetCallback(Event *); // 命令実行系コールバック - void ExecShort(Event& ev); - void ExecFull(Event& ev); - void ExecTrace(Event& ev); + void ExecShort(Event *); + void ExecFull(Event *); + void ExecTrace(Event *); // トレース設定。デバッガから呼び出される。 - void SetTrace(bool trace_on) override; + void SetTrace(bool enable) override; // 割り込みイベントコールバック - void InterruptCallback(Event& ev); - - // 動作モード変更 - void ChangeState(uint32 new_state); + void InterruptCallback(Event *); // 次の実行サイクルを Full にする。 void MakeNextFull(); @@ -146,10 +137,8 @@ class MPU680x0Device : public MainMPUDev inline void CYCLE(int cc) { used_cycle += cc; } - inline void CYCLE2(int cc, int ncc) { - used_cycle += cc; - cycle_nocache += ncc - cc; - } + // 副作用前提のマクロなので do-while にしない。 +#define CYCLE3(name) used_cycle += cycle_table[__CONCAT(cycidx_,name)] // PC を addr に変更する。 // ベクタへのジャンプはここではなく JumpVector()。 @@ -168,7 +157,7 @@ class MPU680x0Device : public MainMPUDev // バスエラーからの復帰用。 inline void save_reg_pd(int n) { // 該当ビットのフラグを立てる - flag_pd |= (1 << n); + flag_pd |= (1U << n); // 保存 save_pd[n] = reg.A[n]; @@ -178,7 +167,7 @@ class MPU680x0Device : public MainMPUDev // バスエラーからの復帰用。 inline void save_reg_pi(int n) { // 該当ビットのフラグを立てる - flag_pi |= (1 << n); + flag_pi |= (1U << n); // 保存 save_pi[n] = reg.A[n]; @@ -187,14 +176,14 @@ class MPU680x0Device : public MainMPUDev // -(An) 実行前にレジスタを(まだ保存してなければ)保存する。 // 1命令で同じレジスタを2回 -(An) する可能性がある命令用。 inline void save_reg_pd_if(int n) { - if ((flag_pd & (1 << n)) == 0) { + if ((flag_pd & (1U << n)) == 0) { save_reg_pd(n); } } // (An)+ 実行前にレジスタを(まだ保存してなければ)保存する。 // 1命令で同じレジスタを2回 (An)+ する可能性がある命令用。 inline void save_reg_pi_if(int n) { - if ((flag_pi & (1 << n)) == 0) { + if ((flag_pi & (1U << n)) == 0) { save_reg_pi(n); } } @@ -232,9 +221,9 @@ class MPU680x0Device : public MainMPUDev virtual void write_data(busaddr addr, uint32 data) = 0; // 物理バスアクセス - busdata read_phys(); - busdata write_phys(uint32 data); - bool read_phys_burst(uint32 *dst); + busdata read_phys(const busaddr); + busdata write_phys(const busaddr, uint32 data); + bool read_phys_burst(busaddr, uint32 *dst); busdata read_phys_4(uint32 addr); busdata write_phys_4(uint32 addr, uint32 data); @@ -268,11 +257,11 @@ class MPU680x0Device : public MainMPUDev void ResetFPU(bool hard); void fpu_init(); uint32 cea_fpu(int bytes); + uint32 cea_fpulc(int bytes); void read_8(uint32 addr, uint32 *data); void read_12(uint32 addr, uint32 *data); void write_8(uint32 addr, const uint32 *data); void write_12(uint32 addr, const uint32 *data); - bool readSRC(int size_id, uint32 *data); void fpu_op_illg(); void fpu_op_illg2(); @@ -316,21 +305,22 @@ class MPU680x0Device : public MainMPUDev // キャッシュ virtual void SetCACR(uint32) = 0; - virtual bool TranslateRead() = 0; - virtual bool TranslateWrite() = 0; - // 例外 void GenerateExframe0(uint vector, uint16 sr, uint32 pc); void GenerateExframe2(uint vector, uint16 sr, uint32 pc, uint32 addr); + void GenerateExframe4(uint vector, uint16 sr, uint32 ea); void GenerateExframe7(uint vector, uint16 sr); void GenerateExframeB(uint vector, uint16 sr); int ExceptionReset(); void ExceptionBuserr(uint vector); uint64 ExceptionInterrupt(); + void ExceptionTrap0(); void ExceptionTrap15(); + void ExceptionFLine(); void ExceptionFP(uint vector); + void ExceptionFPLC(uint ea); void Exception(uint vector); - void ExceptionGeneric(uint ext_vector, uint32 inst); + void ExceptionGeneric(uint ext_vector, uint32 info); // リセット例外の CPU 固有部分。 virtual void ResetCache() = 0; @@ -356,6 +346,12 @@ class MPU680x0Device : public MainMPUDev // 現在実行中の命令の先頭アドレス uint32 ppc {}; + // サイクル数表 + const int8 *cycle_table {}; + static const int8 cycle_table_030cc[]; + static const int8 cycle_table_030ncc[]; + static const int8 cycle_table_040[]; + // レジスタ(状態保存用) uint32 save_pd[8] {}; // -(An) を保存 uint32 save_pi[8] {}; // (An)+ を保存 @@ -409,9 +405,6 @@ class MPU680x0Device : public MainMPUDev bool enable; } fpu40 {}; - // CPU の実行状態 - uint32 cpu_state {}; - // 割り込みペンディング bool intr_pending {}; @@ -427,10 +420,6 @@ class MPU680x0Device : public MainMPUDev // 外部バスがバースト転送に対応していれば true bool has_burst_access {}; - // 命令キャッシュ有効 (icache->enable のコピー) - bool icache_enable {}; - int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分 - // MPU/FPU 種別 m680x0MPUType mpu_type {}; m680x0FPUType fpu_type {}; @@ -450,8 +439,12 @@ class MPU680x0Device : public MainMPUDev // 例外履歴のみ BranchHistory_m680x0 exhist { OBJ_MPU_EXHIST }; + // NetBSD カーネルのエントリポイント。 + // TRAP#0 の履歴でシステムコールを判定するのに使う。 + uint32 netbsd_entrypoint {}; + // 割り込みイベント - Event intr_event { this }; + Event *intr_event {}; // トレースでコールバックを差し替えることができるように // イベントコールバックを変数に入れてある @@ -459,8 +452,8 @@ class MPU680x0Device : public MainMPUDev EventCallback_t exec_full {}; // モニター - void MonitorUpdateRegCommon(TextScreen&, m68kreg&, uint32, uint32); - int MonitorUpdateFPU(TextScreen&, int y, m68kreg&); + void MonitorScreenRegCommon(TextScreen&, m68kreg&, uint32, uint32); + int MonitorScreenFPU(TextScreen&, int y, m68kreg&); Monitor *reg_monitor {}; Monitor *atc_monitor {}; Monitor *cache_monitor {}; @@ -478,6 +471,7 @@ class MPU68030Device : public MPU680x0De ~MPU68030Device() override; void SetLogLevel(int loglevel_) override; + void ResetHard(bool poweron) override; uint64 GetSRP() const { return reg.srp.q; } uint32 GetSRPh() const { return reg.srp.h; } @@ -492,6 +486,11 @@ class MPU68030Device : public MPU680x0De busaddr TranslatePeek(busaddr laddr) override; void CalcStat() override; + // fc に対する文字列("UD"とか)を返す。 + static const char *FCstr(uint fc_) { + return &fcstr[fc_ * 4]; + } + private: // リセット void ResetCache() override; @@ -503,11 +502,14 @@ class MPU68030Device : public MPU680x0De void ops_mmu30() override; void ops_mmu40_pflush() override; uint32 get_fc(); - void mmu_op_illg2(); - void mmu_op_pflush(); - void mmu_op_pflush_ea(); - void mmu_op_pload(); - void mmu_op_ptest(); + void ops_mmu30_illg2(); + void ops_mmu30_pflusha(); + void ops_mmu30_pflush(); + void ops_mmu30_pflush_ea(); + void ops_mmu30_pload(); + void ops_mmu30_ptest(); + uint32 ptest_atc(const busaddr); + uint32 ptest_search(uint level, const busaddr, uint rn); // バスアクセス uint32 fetch_2() override; @@ -517,17 +519,18 @@ class MPU68030Device : public MPU680x0De void write_data(busaddr addr, uint32 data) override; busdata read_cache(m68030Cache *cache, busaddr addr); - busdata read_line(m68030CacheLine *, uint32 tag, uint32 opermask); - busdata read_single(busdata bd, uint32 readmask, uint32 opermask); + busdata read_single(busaddr); + busdata fill_single(busaddr, busdata); busdata write_bus(busaddr addr, uint32 data); // キャッシュ void SetCACR(uint32) override; // MMU - bool TranslateRead() override; - bool TranslateWrite() override; - bool CheckTT(); + busaddr TranslateRead(const busaddr laddr); + busaddr TranslateWrite(const busaddr laddr); + busaddr TTMatch(const busaddr laddr) const; + void PageTableSearch(const busaddr laddr, m68030ATCLine *); bool SetSRP(uint32, uint32); bool SetCRP(uint32, uint32); @@ -544,21 +547,24 @@ class MPU68030Device : public MPU680x0De m68030ATC atc {this}; private: - DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); - DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); - DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); - int MonitorUpdateMMU(TextScreen&, int, m68kreg&); - int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *, + DECLARE_MONITOR_SCREEN(MonitorScreenReg); + DECLARE_MONITOR_SCREEN(MonitorScreenATC); + DECLARE_MONITOR_SCREEN(MonitorScreenCache); + int MonitorScreenMMU(TextScreen&, int, m68kreg&); + int MonitorScreenCache1(TextScreen&, int y, m68030Cache *, char (*)(const m68030CacheLine&)); // キャッシュ std::unique_ptr icache /*{}*/; std::unique_ptr dcache /*{}*/; + + static const char fcstr[]; }; class MPU68040Device : public MPU680x0Device { using inherited = MPU680x0Device; + friend class WXPageTable68040Window; public: MPU68040Device(); @@ -574,6 +580,10 @@ class MPU68040Device : public MPU680x0De busaddr TranslatePeek(busaddr laddr) override; void CalcStat() override; + // デバッガ (pf コマンド) からも使う。 + static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd); + static std::string GetFPUTagName(int32); + private: // リセット void ResetCache() override; @@ -596,11 +606,12 @@ class MPU68040Device : public MPU680x0De void SetCACR(uint32) override; // MMU - bool TranslateRead() override; - bool TranslateWrite() override; - m68040TT *CheckTT(std::array, 2>&) const; - bool LookupATC(m68040ATC&); - bool Search(m68040ATCEntry *); + busaddr TranslateRead(const busaddr laddr); + busaddr TranslateWrite(const busaddr laddr); + m68040TT *TTMatch(std::array, 2>&, + const busaddr) const; + busaddr LookupATC(m68040ATC&, const busaddr); + void Search(m68040ATCEntry *, const busaddr); uint32 PeekDesc(uint32 base, uint32 idx); void SetTT(m68040TT *, uint32); @@ -610,16 +621,14 @@ class MPU68040Device : public MPU680x0De // MMU 有効状態を更新。(TC と *TTn の変更で呼ばれる) void mmu_enable_changed(); - DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); - DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); - int MonitorUpdateMMU(TextScreen&, int, m68kreg&); - void MonitorUpdateTT(TextScreen&, int x, int y, const char *, uint32); - void MonitorUpdateATC1(TextScreen&, int, const m68040ATC *); + DECLARE_MONITOR_SCREEN(MonitorScreenReg); + DECLARE_MONITOR_SCREEN(MonitorScreenATC); + int MonitorScreenMMU(TextScreen&, int, m68kreg&); + void MonitorScreenTT(TextScreen&, int x, int y, const char *, uint32); + void MonitorScreenATC1(TextScreen&, int, bool, const m68040ATC *); // FPU - void MonitorUpdateFPU40(TextScreen&, int y, const FPU40&); - static std::string GetReg1BName(uint32 opclass, uint32 sz, uint32 cmd); - static std::string GetFPUTagName(int32); + void MonitorScreenFPU40(TextScreen&, int y, const FPU40&); std::array, 2> mmu_itt /*{}*/; std::array, 2> mmu_dtt /*{}*/; @@ -633,6 +642,6 @@ class MPU68040Device : public MPU680x0De extern MPU680x0Device *NewMPU680x0Device(); // これを呼びたい人は mpu を持ってるはず。 -static inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) { +inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) { return dynamic_cast(mpu_); }