Annotation of nono/m680x0/m68040bus.cpp, revision 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 "m68040mmu.h"
        !             9: 
        !            10: uint32
        !            11: MPU68040Device::fetch_2()
        !            12: {
        !            13:        busaddr addr = busaddr(reg.pc) | fc_inst | BusAddr::Size2;
        !            14:        busdata bd = read_data(addr);
        !            15:        reg.pc += 2;
        !            16:        return bd.Data();
        !            17: }
        !            18: 
        !            19: uint32
        !            20: MPU68040Device::fetch_4()
        !            21: {
        !            22:        busaddr addr = busaddr(reg.pc) | fc_inst | BusAddr::Size4;
        !            23:        busdata bd = read_data(addr);
        !            24:        reg.pc += 4;
        !            25:        return bd.Data();
        !            26: }
        !            27: 
        !            28: // read_1,2,4() の共通部分。ミスアライン可。
        !            29: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
        !            30: uint32
        !            31: MPU68040Device::read_data(busaddr addr)
        !            32: {
        !            33:        busdata data = read_nocache(addr);
        !            34:        if (__predict_false(data.IsBusErr())) {
        !            35:                bus.laddr = addr;
        !            36:                bus.size = addr.GetSize();
        !            37:                throw M68K::EXCEP_BUSERR;
        !            38:        }
        !            39:        return data.Data();
        !            40: }
        !            41: 
        !            42: // キャッシュ無効時の読み込み。ミスアライン可。
        !            43: // バスエラーも busdata を返す。
        !            44: busdata
        !            45: MPU68040Device::read_nocache(busaddr addr)
        !            46: {
        !            47:        // デバイスは、addr の下位ビットによらず、自身のデバイスのポートサイズ分
        !            48:        // のデータと、その応答サイズ(自分のポートサイズ) を Size フィールドに
        !            49:        // セットして返してくる。
        !            50:        //
        !            51:        // MPU(68040) は、A1-A0、残りバイト数、デバイスの応答サイズの情報から
        !            52:        // 受け取ったデータバスのうち適切なところを切り出して使う。
        !            53: 
        !            54:        bool span_page = false;
        !            55:        uint32 data = 0;
        !            56:        for (;;) {
        !            57:                bus.laddr = addr;
        !            58:                bus.paddr = addr;
        !            59:                if (__predict_false(TranslateRead() == false)) {
        !            60:                        bus.atcfault = true;
        !            61:                        // ATC フォールトが2ページ目で起きたか。
        !            62:                        bus.atcfault2 = span_page;
        !            63:                        return BusData::BusErr;
        !            64:                }
        !            65:                busdata bd = read_phys();
        !            66:                if (__predict_false(bd.IsBusErr())) {
        !            67:                        return bd;
        !            68:                }
        !            69: 
        !            70:                uint32 reqsize = addr.GetSize();
        !            71:                // デバイスのポートサイズ(応答サイズ)
        !            72:                uint32 portsize = bd.GetSize();
        !            73:                // 今回のアドレスオフセット
        !            74:                uint32 offset = addr.Addr() & (portsize - 1);
        !            75:                uint32 datasize = portsize - offset;
        !            76:                uint32 tmp = bd.Data();
        !            77:                // 下詰めされたデータに対するマスク
        !            78:                uint32 mask = 0xffffffffU >> ((4 - datasize) * 8);
        !            79:                // 今回必要なところ
        !            80:                tmp &= mask;
        !            81:                if (datasize == reqsize) {
        !            82:                        data |= tmp;
        !            83:                        break;
        !            84:                } else if (datasize > reqsize) {
        !            85:                        tmp >>= (datasize - reqsize) * 8;
        !            86:                        data |= tmp;
        !            87:                        break;
        !            88:                } else {
        !            89:                        tmp <<= (reqsize - datasize) * 8;
        !            90:                        data |= tmp;
        !            91:                }
        !            92: 
        !            93:                uint32 oldaddr = addr.Addr();
        !            94:                addr += datasize;
        !            95:                reqsize -= datasize;
        !            96:                addr.ChangeSize(reqsize);
        !            97: 
        !            98:                if (__predict_false(((addr.Addr() ^ oldaddr) & ~mmu_tc->page_mask))) {
        !            99:                        span_page = true;
        !           100:                }
        !           101:        }
        !           102:        return data;
        !           103: }
        !           104: 
        !           105: // write_1,2,4() の共通部分。ミスアライン可。
        !           106: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
        !           107: void
        !           108: MPU68040Device::write_data(busaddr addr, uint32 data)
        !           109: {
        !           110:        busaddr origaddr = addr;
        !           111:        uint32  origdata = data;
        !           112: 
        !           113:        bool span_page = false;
        !           114:        for (;;) {
        !           115:                bus.laddr = addr;
        !           116:                bus.paddr = addr;
        !           117:                if (__predict_false(TranslateWrite() == false)) {
        !           118:                        bus.atcfault = true;
        !           119:                        // ATC フォールトが2ページ目で起きたか。
        !           120:                        bus.atcfault2 = span_page;
        !           121:                        break;
        !           122:                }
        !           123:                busdata bd = write_phys(data);
        !           124:                if (__predict_false(bd.IsBusErr())) {
        !           125:                        break;
        !           126:                }
        !           127:                uint32 reqsize = addr.GetSize();
        !           128:                uint32 portsize = bd.GetSize();
        !           129:                uint32 offset = addr.Addr() & (portsize - 1);
        !           130:                uint32 datasize = portsize - offset;
        !           131:                if (datasize >= reqsize) {
        !           132:                        // ここが成功して終了。
        !           133:                        return;
        !           134:                }
        !           135: 
        !           136:                addr += datasize;
        !           137:                reqsize -= datasize;
        !           138:                addr.ChangeSize(reqsize);
        !           139:                data &= (1U << (reqsize * 8)) - 1;
        !           140: 
        !           141:                if (((addr.Addr() ^ origaddr.Addr()) & ~mmu_tc->page_mask) != 0) {
        !           142:                        span_page = true;
        !           143:                }
        !           144:        }
        !           145: 
        !           146:        // 報告するのは先頭のアドレス。
        !           147:        bus.laddr.ChangeAddr(origaddr.Addr());
        !           148:        bus.size = origaddr.GetSize();
        !           149:        bus.data = origdata;
        !           150:        throw M68K::EXCEP_BUSERR;
        !           151: }
        !           152: 
        !           153: // CACR レジスタ書き込み。
        !           154: void
        !           155: MPU68040Device::SetCACR(uint32 data)
        !           156: {
        !           157:        // とりあえず
        !           158:        reg.cacr = data & M68040::CACR_MASK;
        !           159: }
        !           160: 
        !           161: // リセット例外の CPU 固有部分。
        !           162: void
        !           163: MPU68040Device::ResetCache()
        !           164: {
        !           165:        SetCACR(0);
        !           166: }

unix.superglobalmegacorp.com

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