--- nono/m88xx0/m88200.h 2026/04/29 17:05:15 1.1.1.8 +++ nono/m88xx0/m88200.h 2026/04/29 17:05:22 1.1.1.9 @@ -9,6 +9,7 @@ #pragma once #include "device.h" +#include "bus.h" #include "mainbus.h" #include "monitor.h" #include @@ -34,6 +35,7 @@ struct m88200BATC // +-------------------------+-------------------------+-+-------+--+ // | LBA | 0 |S| 0 |~V| // +-------------------------+-------------------------+-+-------+--+ + static const uint32 LBAMASK = 0xfff80000; static const uint32 S = 0x00000020; static const uint32 INVALID = 0x00000001; uint32 lba; // LBA,S,~V @@ -47,6 +49,8 @@ struct m88200BATC bool IsValid() const { return (lba & INVALID) == 0; } // S ビットが立っていれば true を返す bool IsS() const { return (lba & S); } + // 論理アドレス(32ビット)を返す + uint32 Laddr() const { return (lba & LBAMASK); } }; // PATC @@ -59,6 +63,7 @@ struct m88200PATC // +---------------------------------------+-----------+-+-------+--+ // | LPA | 0 |S| 0 |~V| // +---------------------------------------+-----------+-+-------+--+ + static const uint32 LPAMASK = 0xfffff000; static const uint32 S = 0x00000020; static const uint32 INVALID = 0x00000001; uint32 lpa; // LPA,S,~V @@ -71,6 +76,8 @@ struct m88200PATC bool IsValid() const { return (lpa & INVALID) == 0; } // S ビットが立っていれば true を返す bool IsS() const { return (lpa & S); } + // 論理アドレス(32ビット)を返す + uint32 Laddr() const { return (lpa & LPAMASK); } }; // キャッシュの1セット @@ -316,6 +323,11 @@ class m88200 : public Device uint32 GetPFAR() const { return fault_addr; } void SetPFAR(uint32 val) { fault_addr = val; } + void SetFault(uint32 code_, uint32 addr_) { + fault_code = code_; + fault_addr = addr_; + } + // BWP0-7 (BATC Write Ports 0..7) +$400..+$41c // 3 2 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 @@ -325,6 +337,7 @@ class m88200 : public Device // +---------------------------------------------------------------+ static const uint32 BWP_LBA_MASK = 0xfff80000; static const uint32 BWP_PBA_MASK = 0x0007ffc0; + static const uint32 BWP_FLAG_MASK = 0x0000003f; static const uint32 BWP_S = 0x00000020; // Address Space static const uint32 BWP_WT = 0x00000010; // WriteThrough static const uint32 BWP_G = 0x00000008; // Global @@ -332,6 +345,7 @@ class m88200 : public Device static const uint32 BWP_WP = 0x00000002; // Write Protect static const uint32 BWP_V = 0x00000001; // Valid void SetBWP(uint n, uint32 val); + void SetBATC(uint n, uint32 laddr, uint32 paddr, uint32 flags); // CDP0-3 (Cache Data Ports 0..3) +$800..+$80c // 3 2 1 @@ -379,9 +393,9 @@ class m88200 : public Device // 物理バスアクセス // // XXX size をどうするか - uint64 MBusRead(uint32 paddr, int size); - uint64 MBusWrite(uint32 paddr, uint32 data, int size); - uint64 MBusXmem(uint32 paddr, uint32 data, int size); + busdata MBusRead(uint32 paddr, int size); + busdata MBusWrite(uint32 paddr, uint32 data, int size); + busdata MBusXmem(uint32 paddr, uint32 data, int size); // // アクセス関数 @@ -474,9 +488,11 @@ class m88200 : public Device // S/U 信号線 // 実際には P Bus の Address フェーズで毎回送られてくるが // そうそう変わらないので状態変化を通知してもらう方式。 - // true なら super, false なら user。 - bool acc_super {}; + // acc_super は S か U のみ。 + busaddr acc_super {}; void SetSuper(bool super); + bool IsSuper() const { return acc_super.IsSuper(); } + bool IsUser() const { return !IsSuper(); } m88200PATC *acc_patc {}; // ヒットした PATC エントリ uint32 tmp_desc {}; // TEMP_DESCR @@ -485,7 +501,7 @@ class m88200 : public Device // アドレス変換 // bool Translate(); - uint64 TranslatePeek(uint32 laddr, bool issuper, bool do_search) const; + busaddr TranslatePeek(busaddr laddr) const; private: static std::string stat2str(uint32 stat); bool SelectAreaDesc(); @@ -498,58 +514,47 @@ class m88200 : public Device static const uint32 BATC_LBA_MASK = BWP_LBA_MASK; static const uint32 BATC_S = m88200BATC::S; static const uint32 BATC_INVALID = m88200BATC::INVALID; - void MakeBATCHash(); std::array batc {}; - // 検索用のハッシュ。値のビットN (0..9) が立っていれば batc[N] がこの - // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。 - // [0x00] => 0b00'0000'0000; - std::array batc_hash_s {}; - std::array batc_hash_u {}; - // 現在の特権状態によって batc_hash_{s,u} のいずれかを指す - uint16 *batc_hash {}; - static int batc_hash_func(uint32 a) { - return (a >> 19) & 0x0f; - } // PATC static const uint32 PATC_S = m88200PATC::S; static const uint32 PATC_INVALID = m88200PATC::INVALID; void CreatePATCEntry(); - void InvalidatePATCHash(int); + void InvalidatePATCEntry(m88200PATC&); std::array patc {}; - // 検索用のハッシュ。値のビット N (0..55) が立っていれば patc[N] がこの - // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。 - std::array patc_hash_s {}; - std::array patc_hash_u {}; - // 現在の特権状態によって patc_hash_{s,u} のいずれかを指す - uint64 *patc_hash {}; - static int patc_hash_func(uint32 a) { - return (a >> 12) & 0xff; - } - // patc[] のうち空きエントリはビットを立てて示す - uint64 patc_free_map {}; // 次回追加する位置 int patc_next {}; + // BATC/PATC 混合のハッシュ。 + // 1エントリが 4KB の1ページを示し、4GB のメモリ空間全体あるので + // 1M 個 (x User/Supervisor で2倍)。 + // 各エントリは1バイトで、内容は以下の通り。 + // 0: BATC/PATC なし + // 0xff-0xf6: BATC #(~n) + // 1-56: PATC #(n-1) + // BATC は重複して設定することも可能だが、してはいけないとマニュアルに + // 書いてあるので、ここでも動作不定でよいことにする。 + // 前半 (0x00'0000..0x0f'ffff) が User モード用、 + // 後半 (0x10'0000..0x1f'ffff) が Supervisor モード用。 + inline uint32 addr2hash(bool issuper, uint32 addr) const; + void DumpATC(); + std::array atc_hash_all {}; + // 現在の特権状態によって atc_hash_all の [0] か [0x10'0000] を指す。 + uint8 *atc_hash {}; + // 統計 uint64 translate_total {}; std::array batc_hit {}; uint64 patc_hit {}; uint64 atc_miss {}; -#define M88200_STAT 1 +#define M88200_STAT #if defined(M88200_STAT) // 開発用の統計 - uint64 stat_patc_search {}; // ハッシュを引いた回数 - uint64 stat_patc_hit {}; // ヒットした回数 - uint64 stat_patc_miss1 {}; // ハッシュだけでミスした回数 - uint64 stat_patc_miss2 {}; // ビットを調べてミスした回数 uint64 stat_patc_create {}; // エントリ作成回数 uint64 stat_patc_invcmd_all {}; // Invalidate ALL 発行回数 uint64 stat_patc_invcmd_seg {}; // Invalidate Segment 発行回数 uint64 stat_patc_invcmd_page {}; // Invalidate Page 発行回数 uint64 stat_patc_invalidate {}; // 無効にした PATC の総数 - std::array stat_batc_hash_s {}; // BATC.S の衝突状況 - std::array stat_batc_hash_u {}; // BATC.U の衝突状況 #endif //