--- nono/vm/mpu680x0.h 2026/04/29 17:05:24 1.1.1.13 +++ nono/vm/mpu680x0.h 2026/04/29 17:05:29 1.1.1.14 @@ -16,14 +16,14 @@ #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 の実行状態 @@ -69,6 +69,9 @@ class MPU680x0Device : public MPUDevice // FPU を持っているか bool HaveFPU() const { return has_fpu; } + // バーストアクセスをサポートするか + void EnableBurstAccess(bool enable) { has_burst_access = enable; } + void SetCI() override { bus.ci = true; } @@ -79,17 +82,29 @@ class MPU680x0Device : public MPUDevice // 基本アクセス。内部から使用する。 // アドレスは論理アドレスで、空間は現在の命令/データ空間。 // バスエラーなら C++ の例外をスローする。 - 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 アクセス busaddr TranslatePeek(busaddr laddr); + // 統計 + void CalcStat(); // レジスタ uint16 GetIR() const { return ir; } @@ -170,60 +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, bool from_buserr); + void JumpVector(uint vector, bool from_buserr); protected: #include "m68030ea.h" private: - // FC 指定アクセス - uint32 read_8_fc(busaddr addr); - uint32 read_16_fc(busaddr addr); - uint32 read_32_fc(busaddr addr); - void write_8_fc(busaddr addr, uint32 data); - void write_16_fc(busaddr addr, uint32 data); - void write_32_fc(busaddr 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 fetch_16_bus(uint32 addr); - uint32 fetch_32_bus(uint32 addr); - uint32 read_8_bus(busaddr addr); - uint32 read_16_bus(busaddr addr); - uint32 read_32_bus(busaddr addr); - void write_8_bus(busaddr addr, uint32 data); - void write_16_bus(busaddr addr, uint32 data); - void write_32_bus(busaddr addr, uint32 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(); @@ -244,17 +270,6 @@ class MPU680x0Device : public MPUDevice // キャッシュ void SetCACR(uint32); - uint32 fetch_16_cache(uint32 addr); - uint32 fetch_32_cache(uint32 addr); - uint32 fetch_32_cache_aligned(uint32 addr); -#if 0 - uint32 read_8_cache(busaddr addr); - uint32 read_16_cache(busaddr addr); - uint32 read_32_cache(busaddr addr); - void write_8_cache(busaddr addr, uint32 data); - void write_16_cache(busaddr addr, uint32 data); - void write_32_cache(busaddr addr, uint32 data); -#endif // MMU bool SetSRP(uint32, uint32); @@ -263,7 +278,6 @@ class MPU680x0Device : public MPUDevice bool SetTC(uint32); void SetMMUSR(uint16); - bool TranslateFetch(); bool TranslateRead(); bool TranslateWrite(); @@ -278,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); + 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); @@ -297,7 +311,6 @@ 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 @@ -321,9 +334,8 @@ class MPU680x0Device : public MPUDevice uint8 flag_pi {}; // (An)+ のどのレジスタを保存したか // キャッシュ - bool icache_enable {}; - bool icache_freeze {}; std::unique_ptr icache /*{}*/; + std::unique_ptr dcache /*{}*/; // FPU int has_fpu {}; // 0:FPUなし、1:68881、2:68882(?) @@ -345,6 +357,9 @@ class MPU680x0Device : public MPUDevice // 今回のバスウェイト [nsec] uint64 buswait {}; + // 外部バスがバースト転送に対応していれば true + bool has_burst_access {}; + int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分 // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。 @@ -371,6 +386,7 @@ class MPU680x0Device : public MPUDevice // レジスタモニター DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); + void MonitorUpdateFPU(TextScreen&, int y, m68kreg&); Monitor reg_monitor { this }; // ATC モニター @@ -379,6 +395,8 @@ class MPU680x0Device : public MPUDevice // キャッシュモニター DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); + int MonitorUpdateCache1(TextScreen&, int y, m68030Cache *, + char (*)(const m68030CacheLine&)); Monitor cache_monitor { this }; InterruptDevice *interruptdev {};