Annotation of nono/m680x0/m68040bus.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 "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.