|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2017 [email protected] ! 4: // ! 5: ! 6: #pragma once ! 7: ! 8: // ATC_SINGLE は過去との比較のために残してある、双方向リストによる ! 9: // FC 混合 22 エントリ実装。 ! 10: // 定義しない場合(デフォルト)は、FC 別の世代付き配列みたいなもの。 ! 11: //#define ATC_SINGLE 1 ! 12: ! 13: // SRP, CRP ! 14: class m68030RP ! 15: { ! 16: // 6 5 4 3 ! 17: // 3 2 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 ! 18: // +-+-----------------------------+---------------------------+---+ ! 19: // |U| LIMIT | unused |DT | ! 20: // +-+-----------------------------+---------------------------+---+ ! 21: // ! 22: // 3 2 1 0 ! 23: // 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 ! 24: // +-------------------------------------------------------+-------+ ! 25: // | TABLE ADDRESS (PA31-PA4) |unused | ! 26: // +-------------------------------------------------------+-------+ ! 27: public: ! 28: static const uint32 H_MASK = 0xffff0003; ! 29: static const uint32 L_MASK = 0xfffffff0; ! 30: }; ! 31: ! 32: // TT レジスタの各フィールドを束ねた構造体のようなもの。 ! 33: // m68kcpu::SetTT(), GetTT() で読み書きする。 ! 34: class m68030TT ! 35: { ! 36: // 3 2 1 0 ! 37: // 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 ! 38: // +---------------+---------------+-+-+-+-+-+-+-+-+-+-----+-+-----+ ! 39: // |LogicalAddrBase|LogicalAddrMask|E| |C|R|M| | FCB | | FCM | ! 40: // +---------------+---------------+-+-+-+-+-+-+-+-+-+-----+-+-----+ ! 41: ! 42: public: ! 43: static const uint32 MASK = 0xffff8777; ! 44: ! 45: static const uint32 LBASE_MASK = 0xff000000; ! 46: static const uint32 LMASK_MASK = 0x00ff0000; ! 47: static const uint32 E = 0x00008000; ! 48: static const uint32 CI = 0x00000400; ! 49: static const uint32 RW = 0x00000200; ! 50: static const uint32 RWM = 0x00000100; ! 51: static const uint32 FCBASE_MASK = 0x00000070; ! 52: static const uint32 FCMASK_MASK = 0x00000007; ! 53: ! 54: uint32 e = 0; // 00008000 イネーブル ! 55: uint32 ci = 0; // 00000400 キャッシュ禁止 ! 56: uint64 base = 0; // ベース ! 57: uint64 mask = 0; // マスク ! 58: ! 59: // アクセスがこの TT と一致するか調べる。 ! 60: bool Match(uint64 ssw_laddr); ! 61: }; ! 62: ! 63: // TC レジスタの各フィールドを束ねた構造体のようなもの。 ! 64: // m68kcpu::SetTC(), GetTC() で読み書きする。 ! 65: class m68030TC ! 66: { ! 67: public: ! 68: static const uint32 MASK = 0x83ffffff; ! 69: static const uint32 TC_E = 0x80000000; ! 70: static const uint32 TC_SRE = 0x02000000; ! 71: static const uint32 TC_FCL = 0x01000000; ! 72: ! 73: // レジスタの各フィールド ! 74: uint32 e = 0; // TC_E の位置 ! 75: uint32 sre = 0; // TC_SRE の位置 ! 76: uint32 fcl = 0; // TC_FCL の位置 ! 77: uint ps = 0; ! 78: uint is = 0; ! 79: union { ! 80: uint tix[4] {}; ! 81: struct { ! 82: uint tia; ! 83: uint tib; ! 84: uint tic; ! 85: uint tid; ! 86: } __packed; ! 87: }; ! 88: ! 89: int shift[4] {}; // TIA-TID の各部分のシフト量 ! 90: uint32 mask[4] {}; // TIA-TID の各部分のマスク ! 91: uint32 lmask = 0; // TIA-TID 全体のマスク ! 92: uint32 pgmask = 0; // PS 部分のマスク ! 93: ! 94: public: ! 95: void Set(uint32); ! 96: bool Check() const; ! 97: void MakeMask(); ! 98: }; ! 99: ! 100: class m68030MMUSR ! 101: { ! 102: public: ! 103: static const uint16 MASK = 0xee43; ! 104: static const uint16 B = 0x8000; // バスエラー ! 105: static const uint16 L = 0x4000; // リミット違反 ! 106: static const uint16 S = 0x2000; // スーパバイザ専用 ! 107: static const uint16 W = 0x0800; // 書き込み保護 ! 108: static const uint16 I = 0x0400; // 無効 ! 109: static const uint16 M = 0x0200; // 修正 ! 110: static const uint16 T = 0x0040; // 透過アクセス ! 111: static const uint16 N = 0x0007; // レベル数 ! 112: }; ! 113: ! 114: // ATC の1エントリ ! 115: struct m68030ATCLine ! 116: { ! 117: // 1エントリはタグとデータの計64ビット。 ! 118: // ! 119: // タグ ! 120: // LLLLLLLL_LLLLLLLL_LLLLLLLL_0000000I : L は論理アドレス ! 121: // +-- invalid (%1で無効) ! 122: // ! 123: // FC はテーブル選択の時点で確定しているのでタグには不要。 ! 124: // ! 125: // データ ! 126: // PPPPPPPP_PPPPPPPP_PPPPPPPP_0000BCPM : P は物理アドレス ! 127: // |||+-- Modified ! 128: // ||+--- Write Protect ! 129: // |+---- Cache Inhibit ! 130: // +----- Bus Error ! 131: ! 132: static const uint32 LADDR_MASK = 0xffffff00; ! 133: static const uint32 INVALID = 0x00000001; ! 134: static const uint32 PADDR_MASK = 0xffffff00; ! 135: static const uint32 BUSERROR = 0x00000008; ! 136: static const uint32 CINHIBIT = 0x00000004; ! 137: static const uint32 WPROTECT = 0x00000002; ! 138: static const uint32 MODIFIED = 0x00000001; ! 139: ! 140: uint32 tag; ! 141: #if defined(ATC_SINGLE) ! 142: uint32 fc; ! 143: #endif ! 144: uint32 paddr; ! 145: uint32 data; ! 146: ! 147: uint32 GetTag() const { return tag; } ! 148: ! 149: void Invalidate() { tag |= INVALID; } ! 150: bool IsInvalid() const { return tag & INVALID; } ! 151: bool IsValid() const { return !IsInvalid(); } ! 152: ! 153: uint32 GetLAddr() const { return tag & LADDR_MASK; } ! 154: uint32 GetPAddr() const { return paddr; } ! 155: bool IsBusError() const { return data & BUSERROR; } ! 156: bool IsCInhibit() const { return data & CINHIBIT; } ! 157: bool IsWProtect() const { return data & WPROTECT; } ! 158: bool IsModified() const { return data & MODIFIED; } ! 159: ! 160: #if !defined(ATC_SINGLE) ! 161: // LRU 用カウンタ ! 162: uint32 age; ! 163: #else ! 164: m68030ATCLine *prev; ! 165: m68030ATCLine *next; ! 166: #endif ! 167: ! 168: // デバッグ表示 ! 169: void fill_print(uint fc); ! 170: }; ! 171: ! 172: // ATC のテーブル ! 173: class m68030ATCTable ! 174: { ! 175: public: ! 176: static const int LINES = 22; ! 177: ! 178: m68030ATCTable(); ! 179: virtual ~m68030ATCTable() { } ! 180: ! 181: #if !defined(ATC_SINGLE) ! 182: // 空きエントリを取得。 ! 183: m68030ATCLine *Lookup(); ! 184: // a をエントリの先頭に ! 185: m68030ATCLine *MoveHead(m68030ATCLine *a); ! 186: #else ! 187: // 空きエントリを取得。 ! 188: m68030ATCLine *lookup(); ! 189: // LRU の先頭、2番目に追加 ! 190: void insert_head(m68030ATCLine *); ! 191: void insert_second(m68030ATCLine *); ! 192: // LRU の先頭、2番目に移動 ! 193: void move_head(m68030ATCLine *); ! 194: void move_second(m68030ATCLine *); ! 195: // LRU の末尾に追加 ! 196: void insert_tail(m68030ATCLine *); ! 197: // LRU から削除 ! 198: void remove(m68030ATCLine *); ! 199: #endif ! 200: ! 201: // フラッシュ ! 202: // flush() はこのテーブルのすべてのエントリが対象。 ! 203: // flush(addr) はこのテーブルのアドレスが一致するエントリが対象。 ! 204: // flush_fc(fc) はこのテーブルの FC が fc であるエントリが対象。 ! 205: // flush(fc, addr) はこのテーブルの fc と addr が一致するエントリが対象。 ! 206: // いずれも ATC クラスから呼ばれるが、ATC_SINGLE によって、一致する FC が ! 207: // 呼び出し前に決定されているかこちらで比較しないといけないかが変わる。 ! 208: void flush(); ! 209: #if !defined(ATC_SINGLE) ! 210: void flush(uint32 addr); ! 211: #else ! 212: void flush_fc(uint32 fc); ! 213: void flush(uint32 fc, uint32 addr); ! 214: #endif ! 215: ! 216: // ATC 実体 ! 217: m68030ATCLine line[LINES] {}; ! 218: ! 219: // 先頭から何エントリ目でヒットしたかの統計。最後の +1 はキャッシュミス。 ! 220: uint64 hit[LINES + 1] {}; ! 221: ! 222: // ATC_SINGLE ならリストの先頭。 ! 223: // !ATC_SINGLE なら注目エントリ。 ! 224: m68030ATCLine *head = NULL; ! 225: ! 226: #if !defined(ATC_SINGLE) ! 227: // LRU 用の更新カウンタ ! 228: uint32 counter = 0; ! 229: // head のヒット回数。 ! 230: uint64 hit_head = 0; ! 231: #endif ! 232: }; ! 233: ! 234: // ATC (Address Translation Cache) ! 235: class m68030ATC ! 236: { ! 237: friend class MPUATC; ! 238: public: ! 239: m68030ATC(m68kcpu *); ! 240: virtual ~m68030ATC() { } ! 241: ! 242: // エントリをサーチ&更新 ! 243: const m68030ATCLine& fill_fetch(); ! 244: const m68030ATCLine& fill_read(); ! 245: const m68030ATCLine& fill_write(); ! 246: // デバッグ用にエントリを検索 ! 247: uint64 fill_peek(uint32 laddr, uint fc); ! 248: ! 249: // フラッシュ (pflush* 命令から呼ばれる) ! 250: void flush(); ! 251: void flush(uint32 fc, uint32 mask); ! 252: void flush(uint32 fc, uint32 mask, uint32 addr); ! 253: ! 254: private: ! 255: #if !defined(ATC_SINGLE) ! 256: // FC ごとのテーブル。 ! 257: // 8個確保してあるが実際に使うのはこのうち4つだけ。 ! 258: m68030ATCTable tables[8] {}; ! 259: #else ! 260: // FC 混合のテーブル。 ! 261: m68030ATCTable tables[1] {}; ! 262: #endif ! 263: ! 264: m68kcpu *cpu = NULL; ! 265: }; ! 266: ! 267: extern bool m68030_mmu_translate_fetch(m68kcpu *cpu); ! 268: extern bool m68030_mmu_translate_read(m68kcpu *cpu); ! 269: extern bool m68030_mmu_translate_write(m68kcpu *cpu); ! 270: extern uint64 m68030_mmu_translate_peek(m68kcpu *cpu, uint32 laddr, uint fc, ! 271: bool do_search); ! 272: extern void mmu_op_pflush(m68kcpu *cpu); ! 273: extern void mmu_op_pflush_ea(m68kcpu *cpu); ! 274: extern void mmu_op_pload(m68kcpu *cpu); ! 275: extern void mmu_op_ptest(m68kcpu *cpu);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.