|
|
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: // 読み込みのアドレス変換を行う。
13: bool
14: MPU68040Device::TranslateRead()
15: {
16: m68040TT *tt;
17: m68040ATC *atc;
18:
19: putlog(3, "TranslateRead %c.$%08x",
20: (bus.laddr.IsSuper() ? 'S' : 'U'), bus.laddr.Addr());
21:
22: // まず TT をチェック。
23: if (bus.laddr.IsData()) {
24: atc = atc_data.get();
25: tt = CheckTT(mmu_dtt);
26: } else {
27: atc = atc_inst.get();
28: tt = CheckTT(mmu_itt);
29: }
30: if (tt != NULL) {
31: putlog(3, "TranslateRead %s matched", tt->GetName());
32: return true;
33: }
34:
35: // TC がオフならここで終わり。
36: if (__predict_false(mmu_tc->e == false)) {
37: putlog(3, "TranslateRead TC:E OFF");
38: return true;
39: }
40:
41: return LookupATC(*atc);
42: }
43:
44: // 書き込みのアドレス変換を行う。
45: bool
46: MPU68040Device::TranslateWrite()
47: {
48: putlog(3, "TranslateWrite %c.$%08x",
49: (bus.laddr.IsSuper() ? 'S' : 'U'), bus.laddr.Addr());
50:
51: // まず TT をチェック。
52: m68040TT *tt = CheckTT(mmu_dtt);
53: if (tt) {
54: if (tt->w) {
55: putlog(3, "TranslateWrite %s matched (WriteProtected)",
56: tt->GetName());
57: return false;
58: } else {
59: putlog(3, "TranslateWrite %s matched", tt->GetName());
60: return true;
61: }
62: }
63:
64: // TC がオフならここで終わり。
65: if (__predict_false(mmu_tc->e == false)) {
66: putlog(3, "TranslateWrite TC:E OFF");
67: return true;
68: }
69:
70: m68040ATC *atc = atc_data.get();
71: return LookupATC(*atc);
72: }
73:
74: // *TTn にマッチすれば、マッチした方のポインタを返す。
75: // マッチしなければ NULL を返す。
76: m68040TT *
77: MPU68040Device::CheckTT(std::array<std::unique_ptr<m68040TT>, 2>& ttbase) const
78: {
79: for (int n = 0; n < 2; n++) {
80: m68040TT *tt = ttbase[n].get();
81: if (tt->Match(bus.laddr)) {
82: return tt;
83: }
84: }
85: return NULL;
86: }
87:
88: // ATC を検索する。
89: bool
90: MPU68040Device::LookupATC(m68040ATC& atc)
91: {
92: m68040ATCEntry *entry;
93: uint32 tag;
94: uint32 idx;
95: int n;
96:
97: // ATC のタグに使う論理アドレスはページサイズによって区切る位置が変わる。
98: // インデックスは本来タグの比較には使わないが、
99: // 表示の際にはインデックス部分がないとだいぶ意味が分からないのと、
100: // 4KB/page なら 16進数で下から 4桁目をインデックスで補完出来るからいいが
101: // 8KB/page の時にはつらいので、最初からタグに含めておく。
102: //
103: // 3 2 1 0
104: // 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
105: // +-+-------------------------------+-------+-----------------------+
106: // |S| Logical Address (16bit) | Index | Page Offset (4KB/page)|
107: // +-+-------------------------------+-------+-----------------------+
108: // :<-- FC2 + LAddress (+ Index) = 21bit --->:
109: //
110: // +-+-----------------------------+-------+-------------------------+
111: // |S| Logical Address (15bit) | Index | Page Offset (8KB/page)|
112: // +-+-----------------------------+-------+-------------------------+
113: // :<-- FC2 + LAddress (+ Index) = 20bit ->:
114: //
115: // タグはこの位置までシフト(とマスク)したもの。
116: // 3 2 1 0
117: // 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
118: // +-----+-+---------------------------------------+-------------+--+
119: // | 0 |S| Logical Address + Index (19/20bit) : | 0 |~V|
120: // +-----+-+---------------------------------------+-------------+--+
121:
122: idx = (bus.laddr.Addr() >> mmu_tc->tic_shift) & 0xf;
123: tag = (bus.laddr.Get() >> 4) & atc.tag_mask; // FC2+Addr(+Index)
124: m68040ATCSet& set = atc.sets[idx];
125:
126: // このセットから探す。
127: for (n = 0; n < set.entry.size(); n++) {
128: entry = &set.entry[n];
129: if (entry->tag == tag) {
130: if (entry->MatchStatus(bus.laddr)) {
131: // 見付かった。
132: goto found;
133: } else {
134: break;
135: }
136: }
137: }
138:
139: // 空きラインか、空いてなければ生贄を差し出す。
140: n = set.GetEntry();
141: entry = &set.entry[n];
142: entry->tag = tag;
143:
144: // テーブルサーチを行い、エントリを更新する。
1.1.1.3 ! root 145: Search(entry);
1.1 root 146:
147: // このエントリで再度ステータスが一致するか。(タグは一致している)
148: if (entry->MatchStatus(bus.laddr) == false) {
149: putlog(3, " LookupATC entry not matched");
150: return false;
151: }
152: found:
153: // 見付かったので bus.paddr を更新。
154: set.LRU = m88200CacheSet::TryUseLine(set.LRU, n);
155: uint32 offset = bus.laddr.Addr() & ~mmu_tc->page_mask;
156: bus.paddr.ChangeAddr(entry->paddr | offset);
157: putlog(3, " result $%08x", bus.paddr.Addr());
158: return true;
159: }
160:
161: // laddr がこのエントリの各種ステータスにマッチするか調べる。
162: // タグが一致している状態で呼ぶこと。
163: bool
164: m68040ATCEntry::MatchStatus(busaddr laddr) const
165: {
166: if (IsResident() == false) {
167: return false;
168: }
169: if (laddr.IsSuper() == false && IsSuperProtected()) {
170: return false;
171: }
172: if (laddr.IsWrite() && IsWriteProtected()) {
173: return false;
174: }
175: return true;
176: }
177:
178: // 更新用に空きエントリか、空きがなければどれかを差し出す。
179: int
180: m68040ATCSet::GetEntry() const
181: {
182: for (int i = 0; i < 4; i++) {
183: if (entry[i].IsValid() == false) {
184: return i;
185: }
186: }
187:
188: int oldest = m88200CacheSet::TryGetOldestLine(LRU);
189: return oldest;
190: }
191:
1.1.1.3 ! root 192: // テーブルサーチを行い、entry を埋める。
! 193: void
1.1 root 194: MPU68040Device::Search(m68040ATCEntry *entry)
195: {
196: uint32 base;
197: uint32 idx;
198: uint32 mask;
199: uint32 addr;
200: uint32 desc;
1.1.1.3 ! root 201: uint32 pdt;
! 202: busdata bd;
! 203: bool acc_wp = false;
1.1 root 204:
205: busaddr laddr = bus.laddr;
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()) {
376: tt = CheckTT(mmu_dtt);
377: } else {
378: tt = CheckTT(mmu_itt);
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
665: MPU68040Device::MonitorUpdateATC(Monitor *, TextScreen& screen)
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:
674: screen.Clear();
675: screen.Puts(0, 0, "<Data ATC>");
676: screen.Puts(x, 0, "<Instruction ATC>");
677: for (int i = 0; i < 4; i++) {
1.1.1.3 ! root 678: screen.Puts(i * 31 + (i & 2), 1, "IDX TagAddr PAddr Stat");
1.1 root 679: }
680: MonitorUpdateATC1(screen, 0, atc_data.get());
681: MonitorUpdateATC1(screen, x, atc_inst.get());
682: }
683:
684: void
685: MPU68040Device::MonitorUpdateATC1(TextScreen& screen, int x,
686: const m68040ATC *atc)
687: {
688: int y = 2;
689:
690: for (uint i = 0; i < atc->sets.size(); i++) {
691: const m68040ATCSet& set = atc->sets[i];
692: screen.Print(x, y, "[%x]", i);
693:
694: // 古い順に取り出して 3-0 の順序をつける。(新しい順に表示するため)
695: int order[4];
696: uint tmpL = set.LRU;
697: for (int j = 3; j >= 0; j--) {
698: int line = m88200CacheSet::TryGetOldestLine(tmpL);
699: order[j] = line;
700: tmpL = m88200CacheSet::TryUseLine(tmpL, line);
701: }
702:
703: for (int j = 0; j < set.entry.size(); j++) {
704: int line = order[j];
705: const m68040ATCEntry& entry = set.entry[line];
706: TA attr = entry.IsValid() ? TA::Normal : TA::Disable;
707: screen.Print(x + 4, y, attr,
1.1.1.3 ! root 708: "%c.%05x'000 %05x'000 %c%c%c%c",
1.1 root 709: (entry.IsSuper() ? 'S' : 'U'),
710: ((entry.tag >> 8) & 0xfffff),
711: entry.paddr >> 12,
712: ((entry.desc & m68040MMU::DESC_G) ? 'G' : '-'),
713: ((entry.desc & m68040MMU::DESC_S) ? 'S' : '-'),
1.1.1.3 ! root 714: ((entry.desc & m68040MMU::DESC_W) ? 'W' : '-'),
! 715: ((entry.desc & m68040MMU::DESC_R) ? 'R' : '-'));
1.1 root 716: y++;
717: }
718:
719: if (i == 7) {
1.1.1.3 ! root 720: x += 31;
1.1 root 721: y = 2;
722: }
723: }
724: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.