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