|
|
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.