|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2024 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #include "mpu680x0.h"
8: #include "mainbus.h"
9: #include "m68040mmu.h"
10: #include "m88200.h"
11:
12: // 読み込みのアドレス変換を行う。
1.1.1.4 ! root 13: busaddr
! 14: MPU68040Device::TranslateRead(busaddr laddr)
1.1 root 15: {
1.1.1.4 ! root 16: const m68040TT *tt;
1.1 root 17: m68040ATC *atc;
18:
19: putlog(3, "TranslateRead %c.$%08x",
1.1.1.4 ! root 20: (laddr.IsSuper() ? 'S' : 'U'), laddr.Addr());
1.1 root 21:
22: // まず TT をチェック。
1.1.1.4 ! root 23: if (laddr.IsData()) {
1.1 root 24: atc = atc_data.get();
1.1.1.4 ! root 25: tt = TTMatch(mmu_dtt, laddr);
1.1 root 26: } else {
27: atc = atc_inst.get();
1.1.1.4 ! root 28: tt = TTMatch(mmu_itt, laddr);
1.1 root 29: }
30: if (tt != NULL) {
31: putlog(3, "TranslateRead %s matched", tt->GetName());
1.1.1.4 ! root 32: return laddr;
1.1 root 33: }
34:
35: // TC がオフならここで終わり。
36: if (__predict_false(mmu_tc->e == false)) {
37: putlog(3, "TranslateRead TC:E OFF");
1.1.1.4 ! root 38: return laddr;
1.1 root 39: }
40:
1.1.1.4 ! root 41: return LookupATC(*atc, laddr);
1.1 root 42: }
43:
44: // 書き込みのアドレス変換を行う。
1.1.1.4 ! root 45: busaddr
! 46: MPU68040Device::TranslateWrite(busaddr laddr)
1.1 root 47: {
48: putlog(3, "TranslateWrite %c.$%08x",
1.1.1.4 ! root 49: (laddr.IsSuper() ? 'S' : 'U'), laddr.Addr());
1.1 root 50:
51: // まず TT をチェック。
1.1.1.4 ! root 52: const m68040TT *tt = TTMatch(mmu_dtt, laddr);
1.1 root 53: if (tt) {
54: if (tt->w) {
55: putlog(3, "TranslateWrite %s matched (WriteProtected)",
56: tt->GetName());
1.1.1.4 ! root 57: return BusAddr::BusErr;
1.1 root 58: } else {
59: putlog(3, "TranslateWrite %s matched", tt->GetName());
1.1.1.4 ! root 60: return laddr;
1.1 root 61: }
62: }
63:
64: // TC がオフならここで終わり。
65: if (__predict_false(mmu_tc->e == false)) {
66: putlog(3, "TranslateWrite TC:E OFF");
1.1.1.4 ! root 67: return laddr;
1.1 root 68: }
69:
70: m68040ATC *atc = atc_data.get();
1.1.1.4 ! root 71: return LookupATC(*atc, laddr);
1.1 root 72: }
73:
74: // *TTn にマッチすれば、マッチした方のポインタを返す。
75: // マッチしなければ NULL を返す。
76: m68040TT *
1.1.1.4 ! root 77: MPU68040Device::TTMatch(std::array<std::unique_ptr<m68040TT>, 2>& ttbase,
! 78: const busaddr laddr) const
1.1 root 79: {
80: for (int n = 0; n < 2; n++) {
81: m68040TT *tt = ttbase[n].get();
1.1.1.4 ! root 82: if (tt->Match(laddr)) {
1.1 root 83: return tt;
84: }
85: }
86: return NULL;
87: }
88:
89: // ATC を検索する。
1.1.1.4 ! root 90: busaddr
! 91: MPU68040Device::LookupATC(m68040ATC& atc, const busaddr laddr)
1.1 root 92: {
93: m68040ATCEntry *entry;
94: uint32 tag;
95: uint32 idx;
96: int n;
97:
98: // ATC のタグに使う論理アドレスはページサイズによって区切る位置が変わる。
99: // インデックスは本来タグの比較には使わないが、
100: // 表示の際にはインデックス部分がないとだいぶ意味が分からないのと、
101: // 4KB/page なら 16進数で下から 4桁目をインデックスで補完出来るからいいが
102: // 8KB/page の時にはつらいので、最初からタグに含めておく。
103: //
104: // 3 2 1 0
105: // 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
106: // +-+-------------------------------+-------+-----------------------+
107: // |S| Logical Address (16bit) | Index | Page Offset (4KB/page)|
108: // +-+-------------------------------+-------+-----------------------+
109: // :<-- FC2 + LAddress (+ Index) = 21bit --->:
110: //
111: // +-+-----------------------------+-------+-------------------------+
112: // |S| Logical Address (15bit) | Index | Page Offset (8KB/page)|
113: // +-+-----------------------------+-------+-------------------------+
114: // :<-- FC2 + LAddress (+ Index) = 20bit ->:
115: //
116: // タグはこの位置までシフト(とマスク)したもの。
117: // 3 2 1 0
118: // 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
119: // +-----+-+---------------------------------------+-------------+--+
120: // | 0 |S| Logical Address + Index (19/20bit) : | 0 |~V|
121: // +-----+-+---------------------------------------+-------------+--+
122:
1.1.1.4 ! root 123: idx = (laddr.Addr() >> mmu_tc->tic_shift) & 0xf;
! 124: tag = (laddr.Get() >> 4) & atc.tag_mask; // FC2+Addr(+Index)
1.1 root 125: m68040ATCSet& set = atc.sets[idx];
126:
127: // このセットから探す。
128: for (n = 0; n < set.entry.size(); n++) {
129: entry = &set.entry[n];
130: if (entry->tag == tag) {
1.1.1.4 ! root 131: if (entry->MatchStatus(laddr)) {
1.1 root 132: // 見付かった。
133: goto found;
134: } else {
135: break;
136: }
137: }
138: }
139:
140: // 空きラインか、空いてなければ生贄を差し出す。
141: n = set.GetEntry();
142: entry = &set.entry[n];
143: entry->tag = tag;
144:
145: // テーブルサーチを行い、エントリを更新する。
1.1.1.4 ! root 146: Search(entry, laddr);
1.1 root 147:
148: // このエントリで再度ステータスが一致するか。(タグは一致している)
1.1.1.4 ! root 149: if (entry->MatchStatus(laddr) == false) {
1.1 root 150: putlog(3, " LookupATC entry not matched");
1.1.1.4 ! root 151: return BusAddr::BusErr;
1.1 root 152: }
153: found:
1.1.1.4 ! root 154: // 見付かったのでこれを返す。
1.1 root 155: set.LRU = m88200CacheSet::TryUseLine(set.LRU, n);
1.1.1.4 ! root 156: uint32 offset = laddr.Addr() & ~mmu_tc->page_mask;
! 157: busaddr paddr = laddr;
! 158: paddr.ChangeAddr(entry->paddr | offset);
! 159: putlog(3, " result $%08x", paddr.Addr());
! 160: return paddr;
1.1 root 161: }
162:
163: // laddr がこのエントリの各種ステータスにマッチするか調べる。
164: // タグが一致している状態で呼ぶこと。
165: bool
166: m68040ATCEntry::MatchStatus(busaddr laddr) const
167: {
168: if (IsResident() == false) {
169: return false;
170: }
171: if (laddr.IsSuper() == false && IsSuperProtected()) {
172: return false;
173: }
174: if (laddr.IsWrite() && IsWriteProtected()) {
175: return false;
176: }
177: return true;
178: }
179:
180: // 更新用に空きエントリか、空きがなければどれかを差し出す。
181: int
182: m68040ATCSet::GetEntry() const
183: {
184: for (int i = 0; i < 4; i++) {
185: if (entry[i].IsValid() == false) {
186: return i;
187: }
188: }
189:
190: int oldest = m88200CacheSet::TryGetOldestLine(LRU);
191: return oldest;
192: }
193:
1.1.1.3 root 194: // テーブルサーチを行い、entry を埋める。
195: void
1.1.1.4 ! root 196: MPU68040Device::Search(m68040ATCEntry *entry, const busaddr laddr)
1.1 root 197: {
198: uint32 base;
199: uint32 idx;
200: uint32 mask;
201: uint32 addr;
202: uint32 desc;
1.1.1.3 root 203: uint32 pdt;
204: busdata bd;
205: bool acc_wp = false;
1.1 root 206: bool is_write = laddr.IsWrite();
207:
208: putlog(3, " Search %c.$%08x", (laddr.IsSuper() ? 'S' : 'U'), laddr.Addr());
209:
210: // FC2 からルートポインタを決定。
211: // XXX FC2 なのかこれからアクセスする空間の FC なのか。
212: base = laddr.IsSuper() ? reg.srp40 : reg.urp40;
213:
214: // 第1、第2 レベルのディスクリプタを処理。
215: idx = laddr.Addr() >> 25;
216: mask = 0xfffffe00;
217: for (int lv = 0; lv < 2; lv++) {
218: addr = base + idx * 4;
1.1.1.3 root 219: putlog(4, " base=$%08x [$%02x] descaddr=$%08x", base, idx, addr);
1.1 root 220:
1.1.1.3 root 221: bd = read_phys_4(addr);
1.1 root 222: if (__predict_false(bd.IsBusErr())) {
223: putlog(4, " BusErr (on read desc)");
1.1.1.3 root 224: // エラーなので R を落としたエントリを作成。
225: desc = 0;
226: goto done;
1.1 root 227: }
228: desc = bd.Data();
229:
230: if (__predict_false(loglevel >= 4)) {
231: static const char *udtname[] = {
232: "Invalid", "Invalid", "Resident", "Resident",
233: };
234: uint32 dt = desc & m68040MMU::DESC_DT;
1.1.1.3 root 235: putlogn(" desc=$%08x %c%c UDT%u(%s)", desc,
1.1 root 236: ((desc & m68040MMU::DESC_U) ? 'U' : '-'),
237: ((desc & m68040MMU::DESC_W) ? 'W' : '-'),
238: dt, udtname[dt]);
239: }
240:
1.1.1.3 root 241: // ここから Fig. 3-10 左下あたり。
242:
1.1 root 243: // UDT はビット1 が %0 なら無効。
244: if ((desc & 2) == 0) {
245: putlog(4, " invalid");
1.1.1.3 root 246: // R を落としたエントリを作成。(Fig. 3-9)
247: // UDT の Resident はビット1だが、desc の Resident はビット0。
248: desc &= ~m68040MMU::DESC_R;
249: goto done;
250: }
251:
252: // WP を積算。
253: if ((desc & m68040MMU::DESC_W) != 0) {
254: acc_wp = true;
1.1 root 255: }
256:
257: // U が立ってなければ U を立てて更新。
1.1.1.3 root 258: // 実際には次のタイミングに遅延するらしいが。
1.1 root 259: if ((desc & m68040MMU::DESC_U) == 0) {
260: desc |= m68040MMU::DESC_U;
261: bd = write_phys_4(addr, desc);
262: if (__predict_false(bd.IsBusErr())) {
263: putlog(4, " BusErr (on writeback U)");
1.1.1.3 root 264: // エラーなので R を落としたエントリを作成。
265: desc &= ~m68040MMU::DESC_R;
266: goto done;
1.1 root 267: }
268: }
269:
270: // 次の段へ。
271: base = desc & mask;
272: idx = (laddr.Addr() >> 18) & 0x7f;
273: mask = mmu_tc->table_mask;
274: }
275:
276: // ページディスクリプタを処理。
277: idx = (laddr.Addr() >> mmu_tc->tic_shift) & mmu_tc->tic_mask;
278: addr = base + idx * 4;
1.1.1.3 root 279: putlog(4, " base=$%08x [$%02x] descaddr=$%08x", base, idx, addr);
280: bd = read_phys_4(addr);
1.1 root 281: if (__predict_false(bd.IsBusErr())) {
282: putlog(4, " BusErr (on read desc)");
1.1.1.3 root 283: // エラーなので R を落としたエントリを作成。
284: desc &= ~m68040MMU::DESC_R;
285: goto done;
1.1 root 286: }
287: desc = bd.Data();
1.1.1.3 root 288: pdt = desc & m68040MMU::DESC_DT;
1.1 root 289:
290: if (__predict_false(loglevel >= 4)) {
291: static const char *pdtname[] = {
1.1.1.3 root 292: "Invalid", "Resident", "INDIRECT", "Resident",
1.1 root 293: };
1.1.1.3 root 294: putlogn(" desc=$%08x %c%c%c%c%c CM%u PDT%u(%s)", desc,
1.1 root 295: ((desc & m68040MMU::DESC_G) ? 'G' : '-'),
296: ((desc & m68040MMU::DESC_S) ? 'S' : '-'),
297: ((desc & m68040MMU::DESC_M) ? 'M' : '-'),
298: ((desc & m68040MMU::DESC_U) ? 'U' : '-'),
299: ((desc & m68040MMU::DESC_W) ? 'W' : '-'),
300: ((desc & m68040MMU::DESC_CM) >> 5),
301: pdt, pdtname[pdt]);
302: }
303:
1.1.1.3 root 304: // ここから Fig. 3-10 右下あたり。
305:
306: // PDT は %00 なら無効。この場合エントリは作成しない。
1.1 root 307: if (__predict_false(pdt == m68040MMU::PDT_INVALID)) {
308: putlog(4, " invalid");
1.1.1.3 root 309: // R を落としたエントリを作成。(Fig. 3-9)
310: desc &= ~m68040MMU::DESC_R;
311: goto done;
1.1 root 312: } else if (__predict_false(pdt == m68040MMU::PDT_INDIRECT)) {
313: PANIC("indirect descriptor");
314: }
315:
1.1.1.3 root 316: // WP を積算。
317: if ((desc & m68040MMU::DESC_W) != 0) {
318: acc_wp = true;
319: }
320:
1.1 root 321: if (__predict_true(is_write == false)) {
1.1.1.3 root 322: // READ ACCESS
1.1 root 323: if ((desc & m68040MMU::DESC_U) == 0) {
324: desc |= m68040MMU::DESC_U;
1.1.1.3 root 325: // 本当は Read-Modify-Write。
1.1 root 326: bd = write_phys_4(addr, desc);
327: if (__predict_false(bd.IsBusErr())) {
328: putlog(4, " BusErr (on writeback U)");
1.1.1.3 root 329: // エラーなので R を落としたエントリを作成。
330: desc &= ~m68040MMU::DESC_R;
331: goto done;
1.1 root 332: }
333: }
334: } else {
1.1.1.3 root 335: // WRITE ACCESS
1.1 root 336: uint32 olddesc = desc;
1.1.1.3 root 337: if (acc_wp == false && (desc & m68040MMU::DESC_M) == 0) {
338: desc |= m68040MMU::DESC_U | m68040MMU::DESC_M;
339: } else if ((desc & m68040MMU::DESC_U) == 0) {
1.1 root 340: desc |= m68040MMU::DESC_U;
1.1.1.3 root 341: // こっちの場合は本当は Read-Modify-Write。
1.1 root 342: }
1.1.1.3 root 343: if (__predict_false(olddesc != desc)) {
1.1 root 344: bd = write_phys_4(addr, desc);
345: if (__predict_false(bd.IsBusErr())) {
346: putlog(4, " BusErr (on writeback U)");
1.1.1.3 root 347: // エラーなので R を落としたエントリを作成。
348: desc &= ~m68040MMU::DESC_R;
349: goto done;
1.1 root 350: }
351: }
352: }
353:
1.1.1.3 root 354: done:
1.1 root 355: entry->paddr = desc & mmu_tc->page_mask;
356: entry->desc = desc;
1.1.1.3 root 357: if (__predict_false(loglevel >= 3)) {
358: if ((entry->desc & m68040MMU::DESC_R)) {
359: putlogn(" frame addr $%08x", entry->paddr);
360: } else {
361: putlogn(" Not Resident");
362: }
363: }
1.1 root 364: }
365:
366: // ピーク用のアドレス変換を行う。
367: // 変換できれば対応する物理アドレスを、バスエラーなら BusErr を返す。
368: // テーブルサーチを行ったら TableSearched ビットを立てる。
369: busaddr
370: MPU68040Device::TranslatePeek(busaddr laddr)
371: {
372: const m68040TT *tt;
373:
374: // TT を自前でサーチ。
375: if (laddr.IsData()) {
1.1.1.4 ! root 376: tt = TTMatch(mmu_dtt, laddr);
1.1 root 377: } else {
1.1.1.4 ! root 378: tt = TTMatch(mmu_itt, laddr);
1.1 root 379: }
380: if (__predict_false(tt != NULL)) {
381: if (tt->Match(laddr)) {
382: return laddr;
383: }
384: }
385:
386: if (__predict_false(mmu_tc->e == false)) {
387: return laddr;
388: }
389:
390: // ATC を自前でサーチ。
391: const m68040ATC *atc;
392: if (laddr.IsData()) {
393: atc = atc_data.get();
394: } else {
395: atc = atc_inst.get();
396: }
397: uint32 idx = (laddr.Addr() >> mmu_tc->tic_shift) & 0xf;
398: uint32 tag = (laddr.Get() >> 4) & atc->tag_mask; // FC2+Addr(+Index)
399: const m68040ATCSet& set = atc->sets[idx];
400: for (const auto& entry : set.entry) {
401: if (entry.tag == tag) {
402: if (entry.MatchStatus(laddr)) {
403: // 見付かった。
404: uint32 offset = laddr.Addr() & ~mmu_tc->page_mask;
405: laddr.ChangeAddr(entry.paddr | offset);
406: return laddr;
407: } else {
408: break;
409: }
410: }
411: }
412:
413: // ATC になければ、テーブルサーチ相当を自前で行う。
414: laddr |= BusAddr::TableSearched;
415: bool is_write = laddr.IsWrite();
416: uint32 desc;
417:
418: // FC2 からルートポインタを決定。
419: uint32 base = laddr.IsSuper() ? reg.srp40 : reg.urp40;
420:
421: // 第1レベル。
422: idx = laddr.Addr() >> 25;
423: desc = PeekDesc(base, idx);
424: // UDT はビット1 が %0 なら無効。
425: if ((desc & 2) == 0) {
426: return BusAddr::BusErr;
427: }
428: if (__predict_false(is_write) && (desc & 4)) {
429: return BusAddr::BusErr;
430: }
431: base = desc & 0xfffffe00;
432:
433: // 第2レベル。
434: idx = (laddr.Addr() >> 18) & 0x7f;
435: desc = PeekDesc(base, idx);
436: // UDT はビット1 が %0 なら無効。
437: if ((desc & 2) == 0) {
438: return BusAddr::BusErr;
439: }
440: if (__predict_false(is_write) && (desc & 4)) {
441: return BusAddr::BusErr;
442: }
443: base = desc & mmu_tc->table_mask;
444:
445: // ページディスクリプタ。
446: idx = (laddr.Addr() >> mmu_tc->tic_shift) & mmu_tc->tic_mask;
447: desc = PeekDesc(base, idx);
448: // PDT は %00 なら無効。
449: uint32 pdt = desc & m68040MMU::DESC_DT;
450: if (pdt == m68040MMU::PDT_INVALID) {
451: return BusAddr::BusErr;
452: } else if (__predict_false(pdt == m68040MMU::PDT_INDIRECT)) {
453: PANIC("indirect descriptor");
454: }
455: if (__predict_false(is_write) && (desc & 4)) {
456: return BusAddr::BusErr;
457: }
458:
459: uint32 paddr = (desc & mmu_tc->page_mask)
460: | (laddr.Addr() & ~mmu_tc->page_mask);
461: laddr.ChangeAddr(paddr);
462: return laddr;
463: }
464:
465: // base[idx] からディスクリプタを副作用なく読み出す。(デバッガ用)
466: // U フラグは更新しない。
467: // バスエラーが起きれば 0 を返す (ディスクリプタの下位2ビットが %00 なら
468: // 無効を示すので)。
469: uint32
470: MPU68040Device::PeekDesc(uint32 base, uint32 idx)
471: {
472: uint32 addr = base + idx * 4;
473: uint64 data = mainbus->Peek4(addr);
474: if ((int64)data < 0) {
475: return 0;
476: }
477: return data;
478: }
479:
480: // 現在の TC:E、TT:E の状態に応じてアドレス変換の有無を切り替える。
481: // mmu_enable ならアドレス変換ありのバスアクセスを使う。see m68030bus.cpp
482: void
483: MPU68040Device::mmu_enable_changed()
484: {
485: bool enable;
486:
487: // TC、ITT*、DTT* のいずれかが有効ならアドレス変換あり。
488: enable = (reg.tc40 & m68040TC::E);
489: enable |= mmu_itt[0]->e || mmu_itt[1]->e;
490: enable |= mmu_dtt[0]->e || mmu_dtt[1]->e;
491:
492: // 変化した時だけ
493: if (mmu_enable && !enable) {
494: // 無効にする
495: mmu_enable = false;
496: putlog(1, "MMU Translation Disabled");
497: } else if (!mmu_enable && enable) {
498: // 有効にする
499: mmu_enable = true;
500: putlog(1, "MMU Translation Enabled");
501: }
502: }
503:
504: // *TTn レジスタへの書き込み。
505: void
506: MPU68040Device::SetTT(m68040TT *tt, uint32 data)
507: {
508: *tt->reg = (data & m68040TT::MASK);
509: putlog(1, "%s <- $%08x", tt->GetName(), *tt->reg);
510:
511: tt->base = (data & m68040TT::LBASE_MASK);
512: tt->mask = (~data & m68040TT::LMASK_MASK) << 8;
513: tt->e = (data & m68040TT::E);
514: tt->s_ign = (data & m68040TT::S_IGN);
515: tt->s_fc2 = (data & m68040TT::S_FC2);
516: tt->u = (data & m68040TT::U_MASK);
517: tt->cm = (data & m68040TT::CM) >> 5;
518: tt->w = (data & m68040TT::W);
519:
520: mmu_enable_changed();
521: }
522:
523: void
524: MPU68040Device::SetSRP(uint32 data)
525: {
526: // とりあえず
527: reg.srp40 = data & m68040RP::ADDR_MASK;
528: putlog(1, "SRP <- $%08x", reg.srp40);
529: }
530:
531: void
532: MPU68040Device::SetURP(uint32 data)
533: {
534: // とりあえず
535: reg.urp40 = data & m68040RP::ADDR_MASK;
1.1.1.2 root 536: putlog(2, "URP <- $%08x", reg.urp40);
1.1 root 537: }
538:
539: void
540: MPU68040Device::SetTC(uint32 data)
541: {
542: // とりあえず
543: reg.tc40 = data & m68040TC::MASK;
544: putlog(1, "TC <- $%04x", reg.tc40);
545:
546: mmu_tc->e = reg.tc40 & m68040TC::E;
547: if ((reg.tc40 & m68040TC::P) == 0) {
548: // 4KB/page
549: mmu_tc->ps4k = true;
550: mmu_tc->table_mask = 0xffffff00;
551: mmu_tc->tic_shift = 12;
552: mmu_tc->tic_mask = 0x0000003f;
553: mmu_tc->page_mask = 0xfffff000;
554: } else {
555: // 8KB/page
556: mmu_tc->ps4k = false;
557: mmu_tc->table_mask = 0xffffff80;
558: mmu_tc->tic_shift = 13;
559: mmu_tc->tic_mask = 0x0000001f;
560: mmu_tc->page_mask = 0xffffe000;
561: }
562:
563: // ページサイズと連動している ATC の変数もセット。
564: uint32 tag_mask = (mmu_tc->page_mask >> 4) | 0x1000'0000;
565: atc_inst->tag_mask = tag_mask;
566: atc_data->tag_mask = tag_mask;
567:
568: mmu_enable_changed();
569: }
570:
571: // リセット例外の CPU 固有部分。
572: void
573: MPU68040Device::ResetMMU()
574: {
575: mmu_tc->e = false;
576: mmu_itt[0]->e = false;
577: mmu_itt[1]->e = false;
578: mmu_dtt[0]->e = false;
579: mmu_dtt[1]->e = false;
580:
581: // ATC は影響を受けない。
582: }
583:
584: // *TT
585:
586: // コンストラクタ
587: m68040TT::m68040TT(const char *name_, uint32 *reg_)
588: {
589: name = name_;
590: reg = reg_;
591: }
592:
593: // デストラクタ
594: m68040TT::~m68040TT()
595: {
596: }
597:
598: // addr がマッチすれば true を返す。
599: bool
600: m68040TT::Match(busaddr addr) const
601: {
602: if (__predict_true(e == false)) {
603: return false;
604: }
605: if (s_ign == false) {
606: if (addr.IsSuper() != s_fc2) {
607: return false;
608: }
609: }
610: if ((addr.Addr() & mask) != base) {
611: return false;
612: }
613:
614: // 一致した。
615: return true;
616: }
617:
618: // ATC
619:
620: // ATC の指定の権限空間をすべて無効にする。
621: void
622: m68040ATC::Flush(bool s, bool only_non_global)
623: {
624: uint32 target = s ? 0x1000'0000 : 0;
625:
626: // G only_non_global
627: // --- ---
628: // 0 0 invalidate
629: // 0 1 invalidate
630: // 1 0 invalidate
631: // 1 1 nop
632:
633: for (auto& set : sets) {
634: for (auto& entry : set.entry) {
635: // S/U と Valid ビットのみ比較。
636: if ((entry.tag & 0x1000'0001) == target) {
637: if (only_non_global == false || entry.IsGlobal() == false) {
638: entry.Invalidate();
639: }
640: }
641: }
642: }
643: }
644:
645: // ATC の指定の空間+アドレスを無効にする。
646: void
647: m68040ATC::Flush(busaddr addr, bool only_non_global)
648: {
649: uint32 tag = (addr.Get() >> 4) & tag_mask;
650:
651: for (auto& set : sets) {
652: for (auto& entry : set.entry) {
653: // S/U、アドレス、Valid ビットすべてを比較。
654: if (entry.tag == tag) {
655: if (only_non_global == false || entry.IsGlobal() == false) {
656: entry.Invalidate();
657: }
658: }
659: }
660: }
661: }
662:
663: // モニター更新 (68040 ATC)
664: void
1.1.1.4 ! root 665: MPU68040Device::MonitorScreenATC(Monitor *, TextScreen& screen)
1.1 root 666: {
1.1.1.3 root 667: int x = 64;
1.1 root 668:
669: // 0 1 2 3 4 5
1.1.1.3 root 670: // 0123456789012345678901234567890123456789012345678901234567890
671: // IDX TagAddr PAddr Stat IDX TagAddr PAddr Stat
672: // [0] S.12345'000 12345'000 ---- [1] S.12345'000 12345'000 ----
1.1 root 673:
1.1.1.4 ! root 674: bool enable = mmu_tc->e;
! 675: TA attr_e = enable ? TA::Normal : TA::Disable;
! 676:
1.1 root 677: screen.Clear();
1.1.1.4 ! root 678: screen.Puts(0, 0, attr_e, "<Data ATC>");
! 679: screen.Puts(x, 0, attr_e, "<Instruction ATC>");
1.1 root 680: for (int i = 0; i < 4; i++) {
1.1.1.3 root 681: screen.Puts(i * 31 + (i & 2), 1, "IDX TagAddr PAddr Stat");
1.1 root 682: }
1.1.1.4 ! root 683: MonitorScreenATC1(screen, 0, enable, atc_data.get());
! 684: MonitorScreenATC1(screen, x, enable, atc_inst.get());
1.1 root 685: }
686:
687: void
1.1.1.4 ! root 688: MPU68040Device::MonitorScreenATC1(TextScreen& screen, int x, bool enable,
1.1 root 689: const m68040ATC *atc)
690: {
691: int y = 2;
1.1.1.4 ! root 692: TA attr_e = enable ? TA::Normal : TA::Disable;
1.1 root 693:
694: for (uint i = 0; i < atc->sets.size(); i++) {
695: const m68040ATCSet& set = atc->sets[i];
1.1.1.4 ! root 696: screen.Print(x, y, attr_e, "[%x]", i);
1.1 root 697:
698: // 古い順に取り出して 3-0 の順序をつける。(新しい順に表示するため)
699: int order[4];
700: uint tmpL = set.LRU;
701: for (int j = 3; j >= 0; j--) {
702: int line = m88200CacheSet::TryGetOldestLine(tmpL);
703: order[j] = line;
704: tmpL = m88200CacheSet::TryUseLine(tmpL, line);
705: }
706:
707: for (int j = 0; j < set.entry.size(); j++) {
708: int line = order[j];
709: const m68040ATCEntry& entry = set.entry[line];
710: TA attr = entry.IsValid() ? TA::Normal : TA::Disable;
711: screen.Print(x + 4, y, attr,
1.1.1.3 root 712: "%c.%05x'000 %05x'000 %c%c%c%c",
1.1 root 713: (entry.IsSuper() ? 'S' : 'U'),
714: ((entry.tag >> 8) & 0xfffff),
715: entry.paddr >> 12,
716: ((entry.desc & m68040MMU::DESC_G) ? 'G' : '-'),
717: ((entry.desc & m68040MMU::DESC_S) ? 'S' : '-'),
1.1.1.3 root 718: ((entry.desc & m68040MMU::DESC_W) ? 'W' : '-'),
719: ((entry.desc & m68040MMU::DESC_R) ? 'R' : '-'));
1.1 root 720: y++;
721: }
722:
723: if (i == 7) {
1.1.1.3 root 724: x += 31;
1.1 root 725: y = 2;
726: }
727: }
728: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.