Annotation of nono/m680x0/m68040bus.cpp, revision 1.1.1.2

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:                throw M68K::EXCEP_BUSERR;
                     37:        }
                     38:        return data.Data();
                     39: }
                     40: 
                     41: // キャッシュ無効時の読み込み。ミスアライン可。
                     42: // バスエラーも busdata を返す。
                     43: busdata
                     44: MPU68040Device::read_nocache(busaddr addr)
                     45: {
                     46:        // デバイスは、addr の下位ビットによらず、自身のデバイスのポートサイズ分
                     47:        // のデータと、その応答サイズ(自分のポートサイズ) を Size フィールドに
                     48:        // セットして返してくる。
                     49:        //
                     50:        // MPU(68040) は、A1-A0、残りバイト数、デバイスの応答サイズの情報から
                     51:        // 受け取ったデータバスのうち適切なところを切り出して使う。
                     52: 
                     53:        bool span_page = false;
                     54:        uint32 data = 0;
                     55:        for (;;) {
                     56:                bus.laddr = addr;
1.1.1.2 ! root       57:                busaddr paddr = TranslateRead(addr);
        !            58:                if (__predict_false(paddr.IsBusErr())) {
1.1       root       59:                        bus.atcfault = true;
                     60:                        // ATC フォールトが2ページ目で起きたか。
                     61:                        bus.atcfault2 = span_page;
                     62:                        return BusData::BusErr;
                     63:                }
1.1.1.2 ! root       64:                bus.ci = paddr.IsCInhibit();
        !            65:                busdata bd = read_phys(paddr);
1.1       root       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;
1.1.1.2 ! root      116:                busaddr paddr = TranslateWrite(addr);
        !           117:                if (__predict_false(paddr.IsBusErr())) {
1.1       root      118:                        bus.atcfault = true;
                    119:                        // ATC フォールトが2ページ目で起きたか。
                    120:                        bus.atcfault2 = span_page;
                    121:                        break;
                    122:                }
1.1.1.2 ! root      123:                bus.ci = paddr.IsCInhibit();
        !           124:                busdata bd = write_phys(paddr, data);
1.1       root      125:                if (__predict_false(bd.IsBusErr())) {
                    126:                        break;
                    127:                }
                    128:                uint32 reqsize = addr.GetSize();
                    129:                uint32 portsize = bd.GetSize();
                    130:                uint32 offset = addr.Addr() & (portsize - 1);
                    131:                uint32 datasize = portsize - offset;
                    132:                if (datasize >= reqsize) {
                    133:                        // ここが成功して終了。
                    134:                        return;
                    135:                }
                    136: 
                    137:                addr += datasize;
                    138:                reqsize -= datasize;
                    139:                addr.ChangeSize(reqsize);
                    140:                data &= (1U << (reqsize * 8)) - 1;
                    141: 
                    142:                if (((addr.Addr() ^ origaddr.Addr()) & ~mmu_tc->page_mask) != 0) {
                    143:                        span_page = true;
                    144:                }
                    145:        }
                    146: 
                    147:        // 報告するのは先頭のアドレス。
1.1.1.2 ! root      148:        bus.laddr = origaddr;
1.1       root      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.