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