--- nono/vm/mpu680x0.h 2026/04/29 17:05:20 1.1.1.12 +++ nono/vm/mpu680x0.h 2026/04/29 17:05:29 1.1.1.14 @@ -12,16 +12,18 @@ #include "mpu.h" #include "branchhistory.h" +#include "bus.h" #include "event.h" #include "m68030.h" #include "m68030mmu.h" -#include "mainbus.h" class InterruptDevice; +class m68030Cache; +struct m68030CacheLine; -class MPU680x0Device : public MPUDevice +class MPU680x0Device : public MainMPUDevice { - using inherited = MPUDevice; + using inherited = MainMPUDevice; friend class m68030MMU; // CPU の実行状態 @@ -31,8 +33,9 @@ class MPU680x0Device : public MPUDevice public: MPU680x0Device(); - virtual ~MPU680x0Device() override; + ~MPU680x0Device() override; + void SetLogLevel(int loglevel_) override; bool Init() override; void ResetHard(bool poweron) override; @@ -42,6 +45,9 @@ class MPU680x0Device : public MPUDevice // 現在の VBR を取得 uint32 GetVBR() const override { return reg.vbr; } + // MPU 名を取得 + const char *GetMPUName() const override { return "MC68030"; } + bool IsSuper() const { return reg.s; } bool IsMaster() const { return reg.m; } @@ -49,11 +55,8 @@ class MPU680x0Device : public MPUDevice uint32 GetState() const { return cpu_state; } // 現在アクセス中の論理アドレス、物理アドレスを取得。 - uint32 GetLaddr() const override { return bus.laddr; } - uint32 GetPaddr() const override { return bus.paddr; } - - // アクセスウェイトを加算 - void AddCycle(int32 cycle) override { used_cycle += cycle; } + uint32 GetLaddr() const override { return bus.laddr.Addr(); } + uint32 GetPaddr() const override { return bus.paddr.Addr(); } // 割り込みレベルが変わったことを MPU に通知 void Interrupt(int level) override; @@ -66,15 +69,12 @@ class MPU680x0Device : public MPUDevice // FPU を持っているか bool HaveFPU() const { return has_fpu; } - // MPU からのアクセスをエミュレートする。 - // アドレスは論理アドレスで、空間は現在のデータ空間。 - // バスエラーなら (uint64)-1 を返す。 - uint64 Read8(uint32 addr) override; - uint64 Read16(uint32 addr) override; - uint64 Read32(uint32 addr) override; - uint64 Write8(uint32 addr, uint32 data) override; - uint64 Write16(uint32 addr, uint32 data) override; - uint64 Write32(uint32 addr, uint32 data) override; + // バーストアクセスをサポートするか + void EnableBurstAccess(bool enable) { has_burst_access = enable; } + + void SetCI() override { + bus.ci = true; + } // ホールト void Halt(); @@ -82,18 +82,29 @@ class MPU680x0Device : public MPUDevice // 基本アクセス。内部から使用する。 // アドレスは論理アドレスで、空間は現在の命令/データ空間。 // バスエラーなら C++ の例外をスローする。 - uint32 fetch_8(); - uint32 fetch_16(); - uint32 fetch_32(); - uint32 read_8(uint32 addr); - uint32 read_16(uint32 addr); - uint32 read_32(uint32 addr); - void write_8(uint32 addr, uint32 data); - void write_16(uint32 addr, uint32 data); - void write_32(uint32 addr, uint32 data); + uint32 fetch_2(); + uint32 fetch_4(); + uint32 read_n(uint32 laddr, uint size) { + busaddr addr = + busaddr(laddr) | fc_data | BusAddr::R | busaddr::Size(size); + return read_data(addr); + } + void write_n(uint32 laddr, uint size, uint32 data) { + busaddr addr = + busaddr(laddr) | fc_data | BusAddr::W | busaddr::Size(size); + write_data(addr, data); + } + uint32 read_1(uint32 laddr) { return read_n(laddr, 1); } + uint32 read_2(uint32 laddr) { return read_n(laddr, 2); } + uint32 read_4(uint32 laddr) { return read_n(laddr, 4); } + void write_1(uint32 laddr, uint32 data) { write_n(laddr, 1, data); } + void write_2(uint32 laddr, uint32 data) { write_n(laddr, 2, data); } + void write_4(uint32 laddr, uint32 data) { write_n(laddr, 4, data); } // MMU アクセス - uint64 TranslatePeek(uint32 laddr, uint fc, bool do_search); + busaddr TranslatePeek(busaddr laddr); + // 統計 + void CalcStat(); // レジスタ uint16 GetIR() const { return ir; } @@ -174,59 +185,71 @@ class MPU680x0Device : public MPUDevice save_pi[n] = reg.A[n]; } + // -(An) 実行前にレジスタを(まだ保存してなければ)保存する。 + // 1命令で同じレジスタを2回 -(An) する可能性がある命令用。 + inline void save_reg_pd_if(int n) { + if ((flag_pd & (1 << n)) == 0) { + save_reg_pd(n); + } + } + // (An)+ 実行前にレジスタを(まだ保存してなければ)保存する。 + // 1命令で同じレジスタを2回 (An)+ する可能性がある命令用。 + inline void save_reg_pi_if(int n) { + if ((flag_pi & (1 << n)) == 0) { + save_reg_pi(n); + } + } + void restore_reg_pi(); void restore_reg_pd(); - void JumpVector(int vector); + void JumpVector(uint vector, bool from_buserr); protected: #include "m68030ea.h" private: -#include "m68030bus.h" - inline uint32 fetch_16_bus(); - inline uint32 fetch_32_bus(); - inline uint32 read_8_bus(); - inline uint32 read_16_bus(); - inline uint32 read_32_bus(); - inline void write_8_bus(); - inline void write_16_bus(); - inline void write_32_bus(); - // FC 指定 - uint32 read_8_fc(uint32 addr); - uint32 read_16_fc(uint32 addr); - uint32 read_32_fc(uint32 addr); - void write_8_fc(uint32 addr, uint32 data); - void write_16_fc(uint32 addr, uint32 data); - void write_32_fc(uint32 addr, uint32 data); - // 基本アクセスルーチンを使った便利サブルーチン - inline void push_16(uint32 data) { + inline void push_2(uint32 data) { reg.A[7] -= 2; - write_16(reg.A[7], data); + write_2(reg.A[7], data); } - inline void push_32(uint32 data) { + inline void push_4(uint32 data) { reg.A[7] -= 4; - write_32(reg.A[7], data); + write_4(reg.A[7], data); } - inline uint32 pop_16() { - uint32 data = read_16(reg.A[7]); + inline uint32 pop_2() { + uint32 data = read_2(reg.A[7]); reg.A[7] += 2; return data; } - inline uint32 pop_32() { - uint32 data = read_32(reg.A[7]); + inline uint32 pop_4() { + uint32 data = read_4(reg.A[7]); reg.A[7] += 4; return data; } + // バスアクセス + uint32 read_data(busaddr addr); + busdata read_nocache(busaddr addr); + busdata read_cache(m68030Cache *cache, busaddr addr); + busdata read_line(m68030CacheLine *, uint32 tag, uint32 opermask); + busdata read_single(busdata bd, uint32 readmask, uint32 opermask); + + void write_data(busaddr addr, uint32 data); + busdata write_bus(busaddr addr, uint32 data); + + busdata read_phys(); + busdata write_phys(uint32 data); + bool read_phys_burst(uint32 *dst); + #define OP_PROTO(name) void __CONCAT(op_,name)() #include "m68030ops.h" #undef OP_PROTO - void ops_divu_32_32(int r, int q); - void ops_divu_64_32(int r, int q); - void ops_divs_32_32(int r, int q); - void ops_divs_64_32(int r, int q); + void ops_divu_32_32(uint r, uint q); + void ops_divu_64_32(uint r, uint q); + void ops_divs_32_32(uint r, uint q); + void ops_divs_64_32(uint r, uint q); void ops_movec_rc_rn(); void ops_movec_rn_rc(); void ops_movep(); @@ -245,6 +268,9 @@ class MPU680x0Device : public MPUDevice #include "m68030fpu.h" void fpu_op_start(); + // キャッシュ + void SetCACR(uint32); + // MMU bool SetSRP(uint32, uint32); bool SetCRP(uint32, uint32); @@ -252,11 +278,10 @@ class MPU680x0Device : public MPUDevice bool SetTC(uint32); void SetMMUSR(uint16); - bool TranslateFetch(); bool TranslateRead(); bool TranslateWrite(); - bool CheckTT() const; + bool CheckTT(); uint32 get_fc(); void mmu_op_illg2(); void mmu_op_pflush(); @@ -267,15 +292,15 @@ class MPU680x0Device : public MPUDevice void mmu_enable_changed(); // 例外 - void GenerateExframe0(int vector, uint32 pc, uint16 sr); - void GenerateExframe2(int vector, uint16 sr); - void GenerateExframeB(int vector, uint16 sr); + void GenerateExframe0(uint vector, uint32 pc, uint16 sr); + void GenerateExframe2(uint vector, uint16 sr); + void GenerateExframeB(uint vector, uint16 sr); int ExceptionReset(); - void ExceptionBuserr(int); - int ExceptionInterrupt(); + void ExceptionBuserr(uint vector); + uint64 ExceptionInterrupt(); void ExceptionTrap15(); - void Exception(int); - void ExceptionGeneric(int vector, uint32 inst); + void Exception(uint vector); + void ExceptionGeneric(uint vector, uint32 inst); // 二重バスフォールト void DoubleBusFault(const char *where); @@ -286,13 +311,15 @@ class MPU680x0Device : public MPUDevice // MMU work m68030TT mmu_tt[2] /*{}*/; - uint8 mmu_tt_quick[256] {}; m68030TC mmu_tc /*{}*/; m68030ATC atc {this}; bool mmu_enable {}; // MMU が有効なら true // バス m68kbus bus {}; + // 現在の特権状態でのプログラム空間とデータ空間アクセス用。 + busaddr fc_inst {}; // こっちは R 含む + busaddr fc_data {}; // こっちは R/W 含まない private: uint16 ir {}; @@ -306,6 +333,10 @@ class MPU680x0Device : public MPUDevice uint8 flag_pd {}; // -(An) のどのレジスタを保存したか uint8 flag_pi {}; // (An)+ のどのレジスタを保存したか + // キャッシュ + std::unique_ptr icache /*{}*/; + std::unique_ptr dcache /*{}*/; + // FPU int has_fpu {}; // 0:FPUなし、1:68881、2:68882(?) bool fpu_dirty {}; @@ -323,6 +354,12 @@ class MPU680x0Device : public MPUDevice // 電源オンからの累積消費サイクル uint64 used_cycle {}; + // 今回のバスウェイト [nsec] + uint64 buswait {}; + + // 外部バスがバースト転送に対応していれば true + bool has_burst_access {}; + int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分 // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。 @@ -349,16 +386,24 @@ class MPU680x0Device : public MPUDevice // レジスタモニター DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); + void MonitorUpdateFPU(TextScreen&, int y, m68kreg&); Monitor reg_monitor { this }; // ATC モニター DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); Monitor atc_monitor { this }; + // キャッシュモニター + DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); + int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *, + char (*)(const m68030CacheLine&)); + Monitor cache_monitor { this }; + InterruptDevice *interruptdev {}; VectorTable *vectortable {}; }; -static inline MPU680x0Device *GetMPU680x0Device() { - return Object::GetObject(OBJ_MPU); +// これを呼びたい人は mpu を持ってるはず。 +static inline MPU680x0Device *GetMPU680x0Device(Device *mpu_) { + return dynamic_cast(mpu_); }