|
|
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.7 ! root 58: bool e {}; // イネーブル
! 59: bool ci {}; // キャッシュ禁止
1.1.1.3 root 60: uint64 base {}; // ベース
61: uint64 mask {}; // マスク
1.1 root 62:
63: // アクセスがこの TT と一致するか調べる。
1.1.1.7 ! root 64: bool Match(busaddr addr) const;
1.1 root 65: };
66:
67: // TC レジスタの各フィールドを束ねた構造体のようなもの。
68: // m68kcpu::SetTC(), GetTC() で読み書きする。
69: class m68030TC
70: {
1.1.1.7 ! root 71: // 3 2 1 0
! 72: // 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
! 73: // +-+---------+-+-+-------+-------+-------+-------+-------+-------+
! 74: // |E| 0 |S|F| PS | IS | TIA | TIB | TIC | TID |
! 75: // +-+---------+-+-+-------+-------+-------+-------+-------+-------+
! 76: // | | +-- FCL (Function Code Lookup Enable)
! 77: // | +---- SRE (Supervisor Root Pointer Enable)
! 78: // +-- Enable
1.1 root 79: public:
80: static const uint32 MASK = 0x83ffffff;
81: static const uint32 TC_E = 0x80000000;
82: static const uint32 TC_SRE = 0x02000000;
83: static const uint32 TC_FCL = 0x01000000;
84:
85: // レジスタの各フィールド
1.1.1.3 root 86: uint32 e {}; // TC_E の位置
87: uint32 sre {}; // TC_SRE の位置
88: uint32 fcl {}; // TC_FCL の位置
89: uint ps {};
90: uint is {};
1.1 root 91: union {
92: uint tix[4] {};
93: struct {
94: uint tia;
95: uint tib;
96: uint tic;
97: uint tid;
98: } __packed;
99: };
100:
101: int shift[4] {}; // TIA-TID の各部分のシフト量
102: uint32 mask[4] {}; // TIA-TID の各部分のマスク
1.1.1.3 root 103: uint32 lmask {}; // TIA-TID 全体のマスク
104: uint32 pgmask {}; // PS 部分のマスク
1.1 root 105:
106: public:
107: void Set(uint32);
108: bool Check() const;
109: void MakeMask();
110: };
111:
112: class m68030MMUSR
113: {
114: public:
115: static const uint16 MASK = 0xee43;
116: static const uint16 B = 0x8000; // バスエラー
117: static const uint16 L = 0x4000; // リミット違反
118: static const uint16 S = 0x2000; // スーパバイザ専用
119: static const uint16 W = 0x0800; // 書き込み保護
120: static const uint16 I = 0x0400; // 無効
121: static const uint16 M = 0x0200; // 修正
122: static const uint16 T = 0x0040; // 透過アクセス
123: static const uint16 N = 0x0007; // レベル数
124: };
125:
126: // ATC の1エントリ
127: struct m68030ATCLine
128: {
1.1.1.7 ! root 129: // tag
1.1 root 130: // LLLLLLLL_LLLLLLLL_LLLLLLLL_0000000I : L は論理アドレス
131: // +-- invalid (%1で無効)
132: //
133: // FC はテーブル選択の時点で確定しているのでタグには不要。
134: //
1.1.1.7 ! root 135: // paddr
! 136: // PPPPPPPP_PPPPPPPP_PPPPPPPP_00000000 : P は物理アドレス
! 137: //
! 138: // data
! 139: // 00000000_00000000_00000000_0000BCPM
1.1 root 140: // |||+-- Modified
141: // ||+--- Write Protect
142: // |+---- Cache Inhibit
143: // +----- Bus Error
144:
145: static const uint32 LADDR_MASK = 0xffffff00;
146: static const uint32 INVALID = 0x00000001;
147: static const uint32 PADDR_MASK = 0xffffff00;
148: static const uint32 BUSERROR = 0x00000008;
149: static const uint32 CINHIBIT = 0x00000004;
150: static const uint32 WPROTECT = 0x00000002;
151: static const uint32 MODIFIED = 0x00000001;
152:
153: uint32 tag;
154: #if defined(ATC_SINGLE)
155: uint32 fc;
156: #endif
157: uint32 paddr;
158: uint32 data;
159:
160: uint32 GetTag() const { return tag; }
161:
162: void Invalidate() { tag |= INVALID; }
163: bool IsInvalid() const { return tag & INVALID; }
164: bool IsValid() const { return !IsInvalid(); }
165:
166: uint32 GetLAddr() const { return tag & LADDR_MASK; }
167: uint32 GetPAddr() const { return paddr; }
168: bool IsBusError() const { return data & BUSERROR; }
169: bool IsCInhibit() const { return data & CINHIBIT; }
170: bool IsWProtect() const { return data & WPROTECT; }
171: bool IsModified() const { return data & MODIFIED; }
172:
173: #if !defined(ATC_SINGLE)
174: // LRU 用カウンタ
175: uint32 age;
176: #else
177: m68030ATCLine *prev;
178: m68030ATCLine *next;
179: #endif
180:
181: // デバッグ表示
1.1.1.5 root 182: std::string fill_print(uint fc);
1.1 root 183: };
184:
185: // ATC のテーブル
1.1.1.2 root 186: class m68030ATCTable final
1.1 root 187: {
188: public:
189: static const int LINES = 22;
190:
191: m68030ATCTable();
1.1.1.6 root 192: ~m68030ATCTable();
1.1 root 193:
194: #if !defined(ATC_SINGLE)
195: // 空きエントリを取得。
196: m68030ATCLine *Lookup();
197: // a をエントリの先頭に
198: m68030ATCLine *MoveHead(m68030ATCLine *a);
199: #else
200: // 空きエントリを取得。
201: m68030ATCLine *lookup();
202: // LRU の先頭、2番目に追加
203: void insert_head(m68030ATCLine *);
204: void insert_second(m68030ATCLine *);
205: // LRU の先頭、2番目に移動
206: void move_head(m68030ATCLine *);
207: void move_second(m68030ATCLine *);
208: // LRU の末尾に追加
209: void insert_tail(m68030ATCLine *);
210: // LRU から削除
211: void remove(m68030ATCLine *);
212: #endif
213:
214: // フラッシュ
215: // flush() はこのテーブルのすべてのエントリが対象。
216: // flush(addr) はこのテーブルのアドレスが一致するエントリが対象。
217: // flush_fc(fc) はこのテーブルの FC が fc であるエントリが対象。
218: // flush(fc, addr) はこのテーブルの fc と addr が一致するエントリが対象。
219: // いずれも ATC クラスから呼ばれるが、ATC_SINGLE によって、一致する FC が
220: // 呼び出し前に決定されているかこちらで比較しないといけないかが変わる。
221: void flush();
222: #if !defined(ATC_SINGLE)
223: void flush(uint32 addr);
224: #else
225: void flush_fc(uint32 fc);
226: void flush(uint32 fc, uint32 addr);
227: #endif
228:
229: // ATC 実体
230: m68030ATCLine line[LINES] {};
231:
232: // 先頭から何エントリ目でヒットしたかの統計。最後の +1 はキャッシュミス。
233: uint64 hit[LINES + 1] {};
234:
235: // ATC_SINGLE ならリストの先頭。
236: // !ATC_SINGLE なら注目エントリ。
1.1.1.3 root 237: m68030ATCLine *head {};
1.1 root 238:
239: #if !defined(ATC_SINGLE)
240: // LRU 用の更新カウンタ
1.1.1.7 ! root 241: uint32 counter {};
1.1 root 242: // head のヒット回数。
1.1.1.7 ! root 243: uint64 hit_head {};
1.1 root 244: #endif
1.1.1.7 ! root 245:
! 246: int loglevel {};
! 247:
! 248: MPU680x0Device *cpu {};
1.1 root 249: };
250:
251: // ATC (Address Translation Cache)
1.1.1.2 root 252: class m68030ATC final
1.1 root 253: {
1.1.1.4 root 254: friend class MPU680x0Device;
1.1 root 255: public:
1.1.1.6 root 256: m68030ATC(MPU680x0Device *);
257: ~m68030ATC();
1.1 root 258:
1.1.1.7 ! root 259: // ログレベルを設定する。Object のとは同じ使い方だけど別物。
! 260: void SetLogLevel(int loglevel_);
! 261:
1.1 root 262: // エントリをサーチ&更新
1.1.1.7 ! root 263: const m68030ATCLine& fill_fetch(busaddr addr);
! 264: const m68030ATCLine& fill_read(busaddr addr);
! 265: const m68030ATCLine& fill_write(busaddr addr);
1.1 root 266: // デバッグ用にエントリを検索
1.1.1.6 root 267: const m68030ATCLine *fill_peek(uint32 laddr, uint fc);
1.1 root 268:
269: // フラッシュ (pflush* 命令から呼ばれる)
270: void flush();
271: void flush(uint32 fc, uint32 mask);
272: void flush(uint32 fc, uint32 mask, uint32 addr);
273:
274: private:
275: #if !defined(ATC_SINGLE)
276: // FC ごとのテーブル。
277: // 8個確保してあるが実際に使うのはこのうち4つだけ。
278: m68030ATCTable tables[8] {};
279: #else
280: // FC 混合のテーブル。
281: m68030ATCTable tables[1] {};
282: #endif
283:
1.1.1.7 ! root 284: int loglevel {};
! 285:
1.1.1.6 root 286: MPU680x0Device *cpu {};
1.1 root 287: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.