Annotation of nono/m680x0/m68040mmu.cpp, revision 1.1.1.1

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:        // テーブルサーチを行い、エントリを更新する。
                    145:        // (true なら entry を埋めて帰ってきてる)
                    146:        if (Search(entry) == false) {
                    147:                entry->Invalidate();
                    148:                putlog(3, " LookupATC invalid");
                    149:                return false;
                    150:        }
                    151: 
                    152:        // このエントリで再度ステータスが一致するか。(タグは一致している)
                    153:        if (entry->MatchStatus(bus.laddr) == false) {
                    154:                putlog(3, " LookupATC entry not matched");
                    155:                return false;
                    156:        }
                    157:  found:
                    158:        // 見付かったので bus.paddr を更新。
                    159:        set.LRU = m88200CacheSet::TryUseLine(set.LRU, n);
                    160:        uint32 offset = bus.laddr.Addr() & ~mmu_tc->page_mask;
                    161:        bus.paddr.ChangeAddr(entry->paddr | offset);
                    162:        putlog(3, " result $%08x", bus.paddr.Addr());
                    163:        return true;
                    164: }
                    165: 
                    166: // laddr がこのエントリの各種ステータスにマッチするか調べる。
                    167: // タグが一致している状態で呼ぶこと。
                    168: bool
                    169: m68040ATCEntry::MatchStatus(busaddr laddr) const
                    170: {
                    171:        if (IsResident() == false) {
                    172:                return false;
                    173:        }
                    174:        if (laddr.IsSuper() == false && IsSuperProtected()) {
                    175:                return false;
                    176:        }
                    177:        if (laddr.IsWrite() && IsWriteProtected()) {
                    178:                return false;
                    179:        }
                    180:        return true;
                    181: }
                    182: 
                    183: // 更新用に空きエントリか、空きがなければどれかを差し出す。
                    184: int
                    185: m68040ATCSet::GetEntry() const
                    186: {
                    187:        for (int i = 0; i < 4; i++) {
                    188:                if (entry[i].IsValid() == false) {
                    189:                        return i;
                    190:                }
                    191:        }
                    192: 
                    193:        int oldest = m88200CacheSet::TryGetOldestLine(LRU);
                    194:        return oldest;
                    195: }
                    196: 
                    197: // テーブルサーチを行う。
                    198: // 成功すると entry を埋めて true を返す。
                    199: // 失敗すると false を返す (呼び出し側で entry を無効にすること)。
                    200: bool
                    201: MPU68040Device::Search(m68040ATCEntry *entry)
                    202: {
                    203:        uint32 base;
                    204:        uint32 idx;
                    205:        uint32 mask;
                    206:        uint32 addr;
                    207:        uint32 desc;
                    208: 
                    209:        busaddr laddr = bus.laddr;
                    210:        bool is_write = laddr.IsWrite();
                    211: 
                    212:        putlog(3, " Search %c.$%08x", (laddr.IsSuper() ? 'S' : 'U'), laddr.Addr());
                    213: 
                    214:        // FC2 からルートポインタを決定。
                    215:        // XXX FC2 なのかこれからアクセスする空間の FC なのか。
                    216:        base = laddr.IsSuper() ? reg.srp40 : reg.urp40;
                    217: 
                    218:        // 第1、第2 レベルのディスクリプタを処理。
                    219:        idx = laddr.Addr() >> 25;
                    220:        mask = 0xfffffe00;
                    221:        for (int lv = 0; lv < 2; lv++) {
                    222:                addr = base + idx * 4;
                    223:                putlog(4, "  root=$%08x [$%02x] descaddr=$%08x", base, idx, addr);
                    224: 
                    225:                busdata bd = read_phys_4(addr);
                    226:                if (__predict_false(bd.IsBusErr())) {
                    227:                        putlog(4, "  BusErr (on read desc)");
                    228:                        return false;
                    229:                }
                    230:                desc = bd.Data();
                    231: 
                    232:                if (__predict_false(loglevel >= 4)) {
                    233:                        static const char *udtname[] = {
                    234:                                "Invalid", "Invalid", "Resident", "Resident",
                    235:                        };
                    236:                        uint32 dt = desc & m68040MMU::DESC_DT;
                    237:                        putlogn("  desc=$%08x %c%c DT%u(%s)", desc,
                    238:                                ((desc & m68040MMU::DESC_U) ? 'U' : '-'),
                    239:                                ((desc & m68040MMU::DESC_W) ? 'W' : '-'),
                    240:                                dt, udtname[dt]);
                    241:                }
                    242: 
                    243:                // UDT はビット1 が %0 なら無効。
                    244:                if ((desc & 2) == 0) {
                    245:                        putlog(4, "  invalid");
                    246:                        return false;
                    247:                }
                    248: 
                    249:                // U が立ってなければ U を立てて更新。
                    250:                if ((desc & m68040MMU::DESC_U) == 0) {
                    251:                        desc |= m68040MMU::DESC_U;
                    252:                        bd = write_phys_4(addr, desc);
                    253:                        if (__predict_false(bd.IsBusErr())) {
                    254:                                putlog(4, "  BusErr (on writeback U)");
                    255:                                return false;
                    256:                        }
                    257:                }
                    258: 
                    259:                if (__predict_false(is_write) && (desc & m68040MMU::DESC_W)) {
                    260:                        putlog(4, "  write protected");
                    261:                        return false;
                    262:                }
                    263: 
                    264:                // 次の段へ。
                    265:                base = desc & mask;
                    266:                idx = (laddr.Addr() >> 18) & 0x7f;
                    267:                mask = mmu_tc->table_mask;
                    268:        }
                    269: 
                    270:        // ページディスクリプタを処理。
                    271:        idx = (laddr.Addr() >> mmu_tc->tic_shift) & mmu_tc->tic_mask;
                    272:        addr = base + idx * 4;
                    273:        putlog(4, "  root=$%08x [$%02x] descaddr=$%08x", base, idx, addr);
                    274:        busdata bd = read_phys_4(addr);
                    275:        if (__predict_false(bd.IsBusErr())) {
                    276:                putlog(4, "  BusErr (on read desc)");
                    277:                return false;
                    278:        }
                    279:        desc = bd.Data();
                    280:        uint32 pdt = desc & m68040MMU::DESC_DT;
                    281: 
                    282:        if (__predict_false(loglevel >= 4)) {
                    283:                static const char *pdtname[] = {
                    284:                        "Invalid", "Resident", "Indirect", "Resident",
                    285:                };
                    286:                putlogn("  desc=$%08x %c%c%c%c%c CM%u DT%u(%s)", desc,
                    287:                        ((desc & m68040MMU::DESC_G) ? 'G' : '-'),
                    288:                        ((desc & m68040MMU::DESC_S) ? 'S' : '-'),
                    289:                        ((desc & m68040MMU::DESC_M) ? 'M' : '-'),
                    290:                        ((desc & m68040MMU::DESC_U) ? 'U' : '-'),
                    291:                        ((desc & m68040MMU::DESC_W) ? 'W' : '-'),
                    292:                        ((desc & m68040MMU::DESC_CM) >> 5),
                    293:                        pdt, pdtname[pdt]);
                    294:        }
                    295: 
                    296:        // PDT は %00 なら無効。
                    297:        if (__predict_false(pdt == m68040MMU::PDT_INVALID)) {
                    298:                putlog(4, "  invalid");
                    299:                return false;
                    300:        } else if (__predict_false(pdt == m68040MMU::PDT_INDIRECT)) {
                    301:                PANIC("indirect descriptor");
                    302:        }
                    303: 
                    304:        if (__predict_true(is_write == false)) {
                    305:                // 読み込みなら、U を立てるかどうか。
                    306:                if ((desc & m68040MMU::DESC_U) == 0) {
                    307:                        desc |= m68040MMU::DESC_U;
                    308:                        bd = write_phys_4(addr, desc);
                    309:                        if (__predict_false(bd.IsBusErr())) {
                    310:                                putlog(4, "  BusErr (on writeback U)");
                    311:                                return false;
                    312:                        }
                    313:                }
                    314:        } else {
                    315:                // 書き込みなら、U と M と WP。
                    316:                uint32 olddesc = desc;
                    317:                if ((desc & m68040MMU::DESC_U) == 0) {
                    318:                        desc |= m68040MMU::DESC_U;
                    319:                }
                    320:                if ((desc & (m68040MMU::DESC_M | m68040MMU::DESC_W)) == 0) {
                    321:                        desc |= m68040MMU::DESC_M;
                    322:                }
                    323:                if (olddesc != desc) {
                    324:                        bd = write_phys_4(addr, desc);
                    325:                        if (__predict_false(bd.IsBusErr())) {
                    326:                                putlog(4, "  BusErr (on writeback U)");
                    327:                                return false;
                    328:                        }
                    329:                }
                    330: 
                    331:                if ((desc & m68040MMU::DESC_W)) {
                    332:                        putlog(4, "  write protected");
                    333:                        return false;
                    334:                }
                    335:        }
                    336: 
                    337:        entry->paddr = desc & mmu_tc->page_mask;
                    338:        entry->desc  = desc;
                    339:        putlog(3, "  frame addr $%08x", entry->paddr);
                    340:        return true;
                    341: }
                    342: 
                    343: // ピーク用のアドレス変換を行う。
                    344: // 変換できれば対応する物理アドレスを、バスエラーなら BusErr を返す。
                    345: // テーブルサーチを行ったら TableSearched ビットを立てる。
                    346: busaddr
                    347: MPU68040Device::TranslatePeek(busaddr laddr)
                    348: {
                    349:        const m68040TT *tt;
                    350: 
                    351:        // TT を自前でサーチ。
                    352:        if (laddr.IsData()) {
                    353:                tt = CheckTT(mmu_dtt);
                    354:        } else {
                    355:                tt = CheckTT(mmu_itt);
                    356:        }
                    357:        if (__predict_false(tt != NULL)) {
                    358:                if (tt->Match(laddr)) {
                    359:                        return laddr;
                    360:                }
                    361:        }
                    362: 
                    363:        if (__predict_false(mmu_tc->e == false)) {
                    364:                return laddr;
                    365:        }
                    366: 
                    367:        // ATC を自前でサーチ。
                    368:        const m68040ATC *atc;
                    369:        if (laddr.IsData()) {
                    370:                atc = atc_data.get();
                    371:        } else {
                    372:                atc = atc_inst.get();
                    373:        }
                    374:        uint32 idx = (laddr.Addr() >> mmu_tc->tic_shift) & 0xf;
                    375:        uint32 tag = (laddr.Get() >> 4) & atc->tag_mask;        // FC2+Addr(+Index)
                    376:        const m68040ATCSet& set = atc->sets[idx];
                    377:        for (const auto& entry : set.entry) {
                    378:                if (entry.tag == tag) {
                    379:                        if (entry.MatchStatus(laddr)) {
                    380:                                // 見付かった。
                    381:                                uint32 offset = laddr.Addr() & ~mmu_tc->page_mask;
                    382:                                laddr.ChangeAddr(entry.paddr | offset);
                    383:                                return laddr;
                    384:                        } else {
                    385:                                break;
                    386:                        }
                    387:                }
                    388:        }
                    389: 
                    390:        // ATC になければ、テーブルサーチ相当を自前で行う。
                    391:        laddr |= BusAddr::TableSearched;
                    392:        bool is_write = laddr.IsWrite();
                    393:        uint32 desc;
                    394: 
                    395:        // FC2 からルートポインタを決定。
                    396:        uint32 base = laddr.IsSuper() ? reg.srp40 : reg.urp40;
                    397: 
                    398:        // 第1レベル。
                    399:        idx = laddr.Addr() >> 25;
                    400:        desc = PeekDesc(base, idx);
                    401:        // UDT はビット1 が %0 なら無効。
                    402:        if ((desc & 2) == 0) {
                    403:                return BusAddr::BusErr;
                    404:        }
                    405:        if (__predict_false(is_write) && (desc & 4)) {
                    406:                return BusAddr::BusErr;
                    407:        }
                    408:        base = desc & 0xfffffe00;
                    409: 
                    410:        // 第2レベル。
                    411:        idx = (laddr.Addr() >> 18) & 0x7f;
                    412:        desc = PeekDesc(base, idx);
                    413:        // UDT はビット1 が %0 なら無効。
                    414:        if ((desc & 2) == 0) {
                    415:                return BusAddr::BusErr;
                    416:        }
                    417:        if (__predict_false(is_write) && (desc & 4)) {
                    418:                return BusAddr::BusErr;
                    419:        }
                    420:        base = desc & mmu_tc->table_mask;
                    421: 
                    422:        // ページディスクリプタ。
                    423:        idx = (laddr.Addr() >> mmu_tc->tic_shift) & mmu_tc->tic_mask;
                    424:        desc = PeekDesc(base, idx);
                    425:        // PDT は %00 なら無効。
                    426:        uint32 pdt = desc & m68040MMU::DESC_DT;
                    427:        if (pdt == m68040MMU::PDT_INVALID) {
                    428:                return BusAddr::BusErr;
                    429:        } else if (__predict_false(pdt == m68040MMU::PDT_INDIRECT)) {
                    430:                PANIC("indirect descriptor");
                    431:        }
                    432:        if (__predict_false(is_write) && (desc & 4)) {
                    433:                return BusAddr::BusErr;
                    434:        }
                    435: 
                    436:        uint32 paddr = (desc & mmu_tc->page_mask)
                    437:                | (laddr.Addr() & ~mmu_tc->page_mask);
                    438:        laddr.ChangeAddr(paddr);
                    439:        return laddr;
                    440: }
                    441: 
                    442: // base[idx] からディスクリプタを副作用なく読み出す。(デバッガ用)
                    443: // U フラグは更新しない。
                    444: // バスエラーが起きれば 0 を返す (ディスクリプタの下位2ビットが %00 なら
                    445: // 無効を示すので)。
                    446: uint32
                    447: MPU68040Device::PeekDesc(uint32 base, uint32 idx)
                    448: {
                    449:        uint32 addr = base + idx * 4;
                    450:        uint64 data = mainbus->Peek4(addr);
                    451:        if ((int64)data < 0) {
                    452:                return 0;
                    453:        }
                    454:        return data;
                    455: }
                    456: 
                    457: // 現在の TC:E、TT:E の状態に応じてアドレス変換の有無を切り替える。
                    458: // mmu_enable ならアドレス変換ありのバスアクセスを使う。see m68030bus.cpp
                    459: void
                    460: MPU68040Device::mmu_enable_changed()
                    461: {
                    462:        bool enable;
                    463: 
                    464:        // TC、ITT*、DTT* のいずれかが有効ならアドレス変換あり。
                    465:        enable  = (reg.tc40 & m68040TC::E);
                    466:        enable |= mmu_itt[0]->e || mmu_itt[1]->e;
                    467:        enable |= mmu_dtt[0]->e || mmu_dtt[1]->e;
                    468: 
                    469:        // 変化した時だけ
                    470:        if (mmu_enable && !enable) {
                    471:                // 無効にする
                    472:                mmu_enable = false;
                    473:                putlog(1, "MMU Translation Disabled");
                    474:        } else if (!mmu_enable && enable) {
                    475:                // 有効にする
                    476:                mmu_enable = true;
                    477:                putlog(1, "MMU Translation Enabled");
                    478:        }
                    479: }
                    480: 
                    481: // *TTn レジスタへの書き込み。
                    482: void
                    483: MPU68040Device::SetTT(m68040TT *tt, uint32 data)
                    484: {
                    485:        *tt->reg  = (data & m68040TT::MASK);
                    486:        putlog(1, "%s <- $%08x", tt->GetName(), *tt->reg);
                    487: 
                    488:        tt->base  = (data & m68040TT::LBASE_MASK);
                    489:        tt->mask  = (~data & m68040TT::LMASK_MASK) << 8;
                    490:        tt->e     = (data & m68040TT::E);
                    491:        tt->s_ign = (data & m68040TT::S_IGN);
                    492:        tt->s_fc2 = (data & m68040TT::S_FC2);
                    493:        tt->u     = (data & m68040TT::U_MASK);
                    494:        tt->cm    = (data & m68040TT::CM) >> 5;
                    495:        tt->w     = (data & m68040TT::W);
                    496: 
                    497:        mmu_enable_changed();
                    498: }
                    499: 
                    500: void
                    501: MPU68040Device::SetSRP(uint32 data)
                    502: {
                    503:        // とりあえず
                    504:        reg.srp40 = data & m68040RP::ADDR_MASK;
                    505:        putlog(1, "SRP <- $%08x", reg.srp40);
                    506: }
                    507: 
                    508: void
                    509: MPU68040Device::SetURP(uint32 data)
                    510: {
                    511:        // とりあえず
                    512:        reg.urp40 = data & m68040RP::ADDR_MASK;
                    513:        putlog(1, "URP <- $%08x", reg.urp40);
                    514: }
                    515: 
                    516: void
                    517: MPU68040Device::SetTC(uint32 data)
                    518: {
                    519:        // とりあえず
                    520:        reg.tc40 = data & m68040TC::MASK;
                    521:        putlog(1, "TC <- $%04x", reg.tc40);
                    522: 
                    523:        mmu_tc->e = reg.tc40 & m68040TC::E;
                    524:        if ((reg.tc40 & m68040TC::P) == 0) {
                    525:                // 4KB/page
                    526:                mmu_tc->ps4k = true;
                    527:                mmu_tc->table_mask = 0xffffff00;
                    528:                mmu_tc->tic_shift  = 12;
                    529:                mmu_tc->tic_mask   = 0x0000003f;
                    530:                mmu_tc->page_mask  = 0xfffff000;
                    531:        } else {
                    532:                // 8KB/page
                    533:                mmu_tc->ps4k = false;
                    534:                mmu_tc->table_mask = 0xffffff80;
                    535:                mmu_tc->tic_shift  = 13;
                    536:                mmu_tc->tic_mask   = 0x0000001f;
                    537:                mmu_tc->page_mask  = 0xffffe000;
                    538:        }
                    539: 
                    540:        // ページサイズと連動している ATC の変数もセット。
                    541:        uint32 tag_mask = (mmu_tc->page_mask >> 4) | 0x1000'0000;
                    542:        atc_inst->tag_mask = tag_mask;
                    543:        atc_data->tag_mask = tag_mask;
                    544: 
                    545:        mmu_enable_changed();
                    546: }
                    547: 
                    548: // リセット例外の CPU 固有部分。
                    549: void
                    550: MPU68040Device::ResetMMU()
                    551: {
                    552:        mmu_tc->e = false;
                    553:        mmu_itt[0]->e = false;
                    554:        mmu_itt[1]->e = false;
                    555:        mmu_dtt[0]->e = false;
                    556:        mmu_dtt[1]->e = false;
                    557: 
                    558:        // ATC は影響を受けない。
                    559: }
                    560: 
                    561: // *TT
                    562: 
                    563: // コンストラクタ
                    564: m68040TT::m68040TT(const char *name_, uint32 *reg_)
                    565: {
                    566:        name = name_;
                    567:        reg  = reg_;
                    568: }
                    569: 
                    570: // デストラクタ
                    571: m68040TT::~m68040TT()
                    572: {
                    573: }
                    574: 
                    575: // addr がマッチすれば true を返す。
                    576: bool
                    577: m68040TT::Match(busaddr addr) const
                    578: {
                    579:        if (__predict_true(e == false)) {
                    580:                return false;
                    581:        }
                    582:        if (s_ign == false) {
                    583:                if (addr.IsSuper() != s_fc2) {
                    584:                        return false;
                    585:                }
                    586:        }
                    587:        if ((addr.Addr() & mask) != base) {
                    588:                return false;
                    589:        }
                    590: 
                    591:        // 一致した。
                    592:        return true;
                    593: }
                    594: 
                    595: // ATC
                    596: 
                    597: // ATC の指定の権限空間をすべて無効にする。
                    598: void
                    599: m68040ATC::Flush(bool s, bool only_non_global)
                    600: {
                    601:        uint32 target = s ? 0x1000'0000 : 0;
                    602: 
                    603:        //  G  only_non_global
                    604:        // --- ---
                    605:        //      0       0       invalidate
                    606:        //      0       1       invalidate
                    607:        //      1       0       invalidate
                    608:        //      1       1       nop
                    609: 
                    610:        for (auto& set : sets) {
                    611:                for (auto& entry : set.entry) {
                    612:                        // S/U と Valid ビットのみ比較。
                    613:                        if ((entry.tag & 0x1000'0001) == target) {
                    614:                                if (only_non_global == false || entry.IsGlobal() == false) {
                    615:                                        entry.Invalidate();
                    616:                                }
                    617:                        }
                    618:                }
                    619:        }
                    620: }
                    621: 
                    622: // ATC の指定の空間+アドレスを無効にする。
                    623: void
                    624: m68040ATC::Flush(busaddr addr, bool only_non_global)
                    625: {
                    626:        uint32 tag = (addr.Get() >> 4) & tag_mask;
                    627: 
                    628:        for (auto& set : sets) {
                    629:                for (auto& entry : set.entry) {
                    630:                        // S/U、アドレス、Valid ビットすべてを比較。
                    631:                        if (entry.tag == tag) {
                    632:                                if (only_non_global == false || entry.IsGlobal() == false) {
                    633:                                        entry.Invalidate();
                    634:                                }
                    635:                        }
                    636:                }
                    637:        }
                    638: }
                    639: 
                    640: // モニター更新 (68040 ATC)
                    641: void
                    642: MPU68040Device::MonitorUpdateATC(Monitor *, TextScreen& screen)
                    643: {
                    644:        int x = 62;
                    645: 
                    646:        // 0         1         2         3         4         5
                    647:        // 012345678901234567890123456789012345678901234567890123456789
                    648:        // IDX TagAddr     PAddr    Stat IDX TagAddr     PAddr    Stat
                    649:        // [0] S.12345'000 12345'000 --- [1] S.12345'000 12345'000 ---
                    650: 
                    651:        screen.Clear();
                    652:        screen.Puts(0, 0, "<Data ATC>");
                    653:        screen.Puts(x, 0, "<Instruction ATC>");
                    654:        for (int i = 0; i < 4; i++) {
                    655:                screen.Puts(i * 30 + (i & 2), 1, "IDX TagAddr     PAddr    Stat");
                    656:        }
                    657:        MonitorUpdateATC1(screen, 0, atc_data.get());
                    658:        MonitorUpdateATC1(screen, x, atc_inst.get());
                    659: }
                    660: 
                    661: void
                    662: MPU68040Device::MonitorUpdateATC1(TextScreen& screen, int x,
                    663:        const m68040ATC *atc)
                    664: {
                    665:        int y = 2;
                    666: 
                    667:        for (uint i = 0; i < atc->sets.size(); i++) {
                    668:                const m68040ATCSet& set = atc->sets[i];
                    669:                screen.Print(x, y, "[%x]", i);
                    670: 
                    671:                // 古い順に取り出して 3-0 の順序をつける。(新しい順に表示するため)
                    672:                int order[4];
                    673:                uint tmpL = set.LRU;
                    674:                for (int j = 3; j >= 0; j--) {
                    675:                        int line = m88200CacheSet::TryGetOldestLine(tmpL);
                    676:                        order[j] = line;
                    677:                        tmpL = m88200CacheSet::TryUseLine(tmpL, line);
                    678:                }
                    679: 
                    680:                for (int j = 0; j < set.entry.size(); j++) {
                    681:                        int line = order[j];
                    682:                        const m68040ATCEntry& entry = set.entry[line];
                    683:                        TA attr = entry.IsValid() ? TA::Normal : TA::Disable;
                    684:                        screen.Print(x + 4, y, attr,
                    685:                                "%c.%05x'000 %05x'000 %c%c%c",
                    686:                                (entry.IsSuper() ? 'S' : 'U'),
                    687:                                ((entry.tag >> 8) & 0xfffff),
                    688:                                entry.paddr >> 12,
                    689:                                ((entry.desc & m68040MMU::DESC_G) ? 'G' : '-'),
                    690:                                ((entry.desc & m68040MMU::DESC_S) ? 'S' : '-'),
                    691:                                ((entry.desc & m68040MMU::DESC_W) ? 'W' : '-'));
                    692:                        y++;
                    693:                }
                    694: 
                    695:                if (i == 7) {
                    696:                        x += 30;
                    697:                        y = 2;
                    698:                }
                    699:        }
                    700: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.