Annotation of nono/vm/busio.h, revision 1.1.1.9

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: // バスとデバイスとのインタフェース。
                      8: // バスに対し、デバイスがどのように接続されているかを記述する。
                      9: 
1.1.1.9 ! root       10: // Poke1() はここで定義しなければ基底クラスの Device::Poke1() が呼ばれて
        !            11: // 全域編集不可になる。BusIO を経由する必要があるデバイスはたいていは全域が
        !            12: // 編集不可なので、通常この基底の動作でよく、Poke1() を再定義する必要はない。
        !            13: // MK48T02Device のみ BusIO 経由で編集可能な領域を持っているため、これを
        !            14: // 受け取る BusIO_B と BusIO_BFFF だけ Poke1() を持っている。
        !            15: // 従って BusIO_B、BusIO_BFFF の親になるデバイスは全員 PokePort() も実装する
        !            16: // 必要がある。うーん。
        !            17: 
1.1.1.3   root       18: #pragma once
                     19: 
1.1       root       20: #if !defined(SELFTEST)
                     21: #include "device.h"
                     22: #endif
                     23: 
1.1.1.9 ! root       24: // テンプレート外のヘルパー関数。
        !            25: class BusIO
        !            26: {
        !            27:        static inline uint32 M4(uint32 a, uint32 b, uint32 c, uint32 d) {
        !            28:                return ((a << 24) | (b << 16) | (c << 8) | d);
        !            29:        }
        !            30: 
        !            31:  public:
        !            32:        // アドレス(とサイズ情報からなる) addr と書き込みデータ data から
        !            33:        // m68030 のバスに出るはずのデータを構成する。68030UM.pdf p7-11。
        !            34:        // m88200 ではこのうち7つ(reqsize==2 なら offset==0 か 2 のみ、等)
        !            35:        // しか使わないが、そのケースに限れば m68030 と同じ動作になる。
        !            36:        static inline uint32
        !            37:        DataMultiplexer_Write_L(const busaddr addr, uint32 data)
        !            38:        {
        !            39:                uint32 reqsize = addr.GetSize();
        !            40:                uint32 offset = addr.Addr() & 3U;
        !            41: 
        !            42:                uint32 op0 = (data >> 24) & 0xff;
        !            43:                uint32 op1 = (data >> 16) & 0xff;
        !            44:                uint32 op2 = (data >>  8) & 0xff;
        !            45:                uint32 op3 =  data        & 0xff;
        !            46:                if (reqsize == 4) {
        !            47:                        switch (offset) {
        !            48:                         case 0:        data = M4(op0, op1, op2, op3);  break;
        !            49:                         case 1:        data = M4(op0, op0, op1, op2);  break;
        !            50:                         case 2:        data = M4(op0, op1, op0, op1);  break;
        !            51:                         case 3:        data = M4(op0, op0, op1, op0);  break;
        !            52:                         default:
        !            53:                                __unreachable();
        !            54:                        }
        !            55:                } else if (reqsize == 3) {
        !            56:                        switch (offset) {
        !            57:                         case 0:        data = M4(op1, op2, op3, op0);  break;
        !            58:                         case 1:        data = M4(op1, op1, op2, op3);  break;
        !            59:                         case 2:        data = M4(op1, op2, op1, op2);  break;
        !            60:                         case 3:        data = M4(op1, op1, op2, op1);  break;
        !            61:                         default:
        !            62:                                __unreachable();
        !            63:                        }
        !            64:                } else if (reqsize == 2) {
        !            65:                        if ((offset & 1U) == 0) {
        !            66:                                data = M4(op2, op3, op2, op3);
        !            67:                        } else {
        !            68:                                data = M4(op2, op2, op3, op2);
        !            69:                        }
        !            70:                } else {
        !            71:                        data = M4(op3, op3, op3, op3);
        !            72:                }
        !            73:                return data;
        !            74:        }
        !            75: };
        !            76: 
1.1       root       77: // バイトデバイスをバイト、ワード、ロングワードポートにミラー配置する共通部
                     78: template <class T, int rshift>
1.1.1.4   root       79: class BusIO_B_Base : public T
1.1       root       80: {
1.1.1.9 ! root       81:  private:
        !            82:        inline uint32 Decoder(busaddr addr) const {
        !            83:                return Decoder(addr.Addr());
        !            84:        }
        !            85:        inline uint32 Decoder(uint32 addr) const {
1.1       root       86:                return (addr >> rshift) & (T::NPORT - 1);
                     87:        }
                     88: 
                     89:  public:
1.1.1.9 ! root       90:        busdata Read(busaddr addr) override {
        !            91:                return T::ReadPort(Decoder(addr));
1.1       root       92:        }
                     93: 
1.1.1.9 ! root       94:        busdata Write(busaddr addr, uint32 data) override {
        !            95:                data >>= (addr.GetSize() - 1) * 8;
        !            96:                return T::WritePort(Decoder(addr), data);
1.1       root       97:        }
                     98: 
1.1.1.9 ! root       99:        busdata Peek1(uint32 addr) override {
        !           100:                return T::PeekPort(Decoder(addr));
1.1       root      101:        }
1.1.1.7   root      102: 
1.1.1.9 ! root      103:        bool Poke1(uint32 addr, uint32 data) override {
        !           104:                return T::PokePort(Decoder(addr), data);
1.1.1.7   root      105:        }
1.1       root      106: };
                    107: 
                    108: // バイトデバイスをバイトのまま配置する。
                    109: // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。
                    110: template <class T>
1.1.1.4   root      111: class BusIO_B : public BusIO_B_Base<T, 0> { };
1.1       root      112: // バイトデバイスをワードにミラー配置する。
                    113: template <class T>
1.1.1.4   root      114: class BusIO_BB : public BusIO_B_Base<T, 1> { };
1.1       root      115: // バイトデバイスをロングワードにミラー配置する。
                    116: template <class T>
1.1.1.4   root      117: class BusIO_BBBB : public BusIO_B_Base<T, 2> { };
1.1       root      118: 
                    119: // ワードデバイスをワードのまま配置する。
                    120: // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。
                    121: template <class T>
1.1.1.4   root      122: class BusIO_W : public T
1.1       root      123: {
                    124:  private:
1.1.1.9 ! root      125:        inline uint32 Decoder(busaddr addr) const {
        !           126:                return Decoder(addr.Addr());
        !           127:        }
        !           128:        inline uint32 Decoder(uint32 addr) const {
1.1       root      129:                return (addr >> 1) & (T::NPORT - 1);
                    130:        }
1.1.1.9 ! root      131:        static inline uint32 M2(uint32 a, uint32 b) {
        !           132:                return ((a) << 8) | b;
        !           133:        }
1.1       root      134: 
                    135:  public:
1.1.1.9 ! root      136:        busdata Read(busaddr addr) override {
        !           137:                return T::ReadPort(Decoder(addr));
1.1       root      138:        }
                    139: 
1.1.1.9 ! root      140:        busdata Write(busaddr addr, uint32 data) override {
        !           141:                uint32 reqsize = addr.GetSize();
        !           142:                uint32 offset = addr.Addr() & 1;
        !           143: 
        !           144:                uint32 op0 = (data >> 24) & 0xff;
        !           145:                uint32 op1 = (data >> 16) & 0xff;
        !           146:                uint32 op2 = (data >>  8) & 0xff;
        !           147:                uint32 op3 =  data        & 0xff;
        !           148:                if (reqsize == 1) {
        !           149:                        data = M2(op3, op3);
        !           150:                } else if (reqsize == 2) {
        !           151:                        if (offset == 0) {
        !           152:                                data = M2(op2, op3);
        !           153:                        } else {
        !           154:                                data = M2(op2, op2);
        !           155:                        }
        !           156:                } else if (reqsize == 3) {
        !           157:                        if (offset == 0) {
        !           158:                                data = M2(op1, op2);
        !           159:                        } else {
        !           160:                                data = M2(op1, op1);
        !           161:                        }
        !           162:                } else {
        !           163:                        if (offset == 0) {
        !           164:                                data = M2(op0, op1);
        !           165:                        } else {
        !           166:                                data = M2(op0, op0);
        !           167:                        }
        !           168:                }
        !           169:                return T::WritePort(Decoder(addr), data);
1.1       root      170:        }
                    171: 
1.1.1.9 ! root      172:        busdata Peek1(uint32 addr) override {
1.1       root      173:                if ((addr & 1) == 0) {
1.1.1.9 ! root      174:                        return T::PeekPort(Decoder(addr)) >> 8;
1.1       root      175:                } else {
1.1.1.9 ! root      176:                        return T::PeekPort(Decoder(addr)) & 0xff;
1.1       root      177:                }
                    178:        }
                    179: };
                    180: 
1.1.1.9 ! root      181: // ロングワードデバイスをロングワードのまま m68k バスに配置する。
1.1       root      182: template <class T>
1.1.1.9 ! root      183: class BusIO_L : public T
1.1       root      184: {
                    185:  private:
1.1.1.9 ! root      186:        inline uint32 Decoder(busaddr addr) const {
        !           187:                return Decoder(addr.Addr());
        !           188:        }
        !           189:        inline uint32 Decoder(uint32 addr) const {
        !           190:                return (addr >> 2) & (T::NPORT - 1);
1.1       root      191:        }
                    192: 
                    193:  public:
1.1.1.9 ! root      194:        BusIO_L<T>()
        !           195:                : T()
        !           196:        {
1.1       root      197:        }
1.1.1.9 ! root      198:        BusIO_L<T>(uint arg1)
        !           199:                : T(arg1)
        !           200:        {
        !           201:        }
        !           202:        BusIO_L<T>(uint arg1, uint arg2)
        !           203:                : T(arg1, arg2)
        !           204:        {
1.1       root      205:        }
                    206: 
1.1.1.9 ! root      207:        busdata Read(busaddr addr) override {
        !           208:                return T::ReadPort(Decoder(addr));
1.1       root      209:        }
1.1.1.9 ! root      210: 
        !           211:        busdata Write(busaddr addr, uint32 data) override {
        !           212:                data = BusIO::DataMultiplexer_Write_L(addr, data);
        !           213:                return T::WritePort(Decoder(addr), data);
1.1       root      214:        }
                    215: 
1.1.1.9 ! root      216:        busdata Peek1(uint32 addr) override {
        !           217:                busdata data = T::PeekPort(Decoder(addr));
        !           218:                if (data.IsBusErr()) {
        !           219:                        return data;
1.1       root      220:                }
1.1.1.9 ! root      221:                data >>= (3 - (addr & 3U)) * 8;
        !           222:                data &= 0xff;
        !           223:                return data;
1.1       root      224:        }
                    225: };
                    226: 
1.1.1.9 ! root      227: // バイトデバイスを偶数アドレスに配置し、奇数アドレスはバスエラー。
        !           228: //class BusIO_BE
        !           229: 
1.1       root      230: // バイトデバイスを奇数アドレスに配置し、偶数アドレスはバスエラー。
                    231: template <class T>
1.1.1.4   root      232: class BusIO_EB : public T
1.1       root      233: {
                    234:  private:
1.1.1.9 ! root      235:        inline uint32 Decoder(busaddr addr) const {
        !           236:                return Decoder(addr.Addr());
        !           237:        }
        !           238:        inline uint32 Decoder(uint32 addr) const {
1.1       root      239:                return (addr >> 1) & (T::NPORT - 1);
                    240:        }
                    241: 
                    242:  public:
1.1.1.9 ! root      243:        busdata Read(busaddr addr) override {
        !           244:                if (addr.GetSize() == 1 && (addr.Addr() & 1) == 0) {
        !           245:                        return BusData::BusErr;
        !           246:                }
        !           247:                busdata bd = T::ReadPort(Decoder(addr));
        !           248:                bd |= 0xff00;
        !           249:                bd.ChangeSize(2);
        !           250:                return bd;
        !           251:        }
        !           252: 
        !           253:        busdata Write(busaddr addr, uint32 data) override {
        !           254:                busdata r;
        !           255:                uint32 reqsize = addr.GetSize();
        !           256:                uint32 offset = addr.Addr() & 1;
        !           257: 
        !           258:                uint32 op0 = (data >> 24) & 0xff;
        !           259:                uint32 op1 = (data >> 16) & 0xff;
        !           260:                uint32 op2 = (data >>  8) & 0xff;
        !           261:                uint32 op3 =  data        & 0xff;
        !           262:                if (reqsize == 1) {
        !           263:                        if (offset == 0) {
        !           264:                                return BusData::BusErr;
        !           265:                        } else {
        !           266:                                data = op3;
        !           267:                        }
        !           268:                } else if (reqsize == 2) {
        !           269:                        if (offset == 0) {
        !           270:                                data = op3;
        !           271:                        } else {
        !           272:                                data = op2;
        !           273:                        }
        !           274:                } else if (reqsize == 3) {
        !           275:                        if (offset == 0) {
        !           276:                                data = op2;
        !           277:                        } else {
        !           278:                                data = op1;
        !           279:                        }
1.1       root      280:                } else {
1.1.1.9 ! root      281:                        if (offset == 0) {
        !           282:                                data = op1;
        !           283:                        } else {
        !           284:                                data = op0;
        !           285:                        }
1.1       root      286:                }
1.1.1.9 ! root      287:                r = T::WritePort(Decoder(addr), data);
        !           288:                r.ChangeSize(2);
        !           289:                return r;
1.1       root      290:        }
                    291: 
1.1.1.9 ! root      292:        busdata Peek1(uint32 addr) override {
1.1       root      293:                if ((addr & 1) == 0) {
1.1.1.9 ! root      294:                        return BusData::BusErr;
1.1       root      295:                } else {
1.1.1.9 ! root      296:                        return T::PeekPort(Decoder(addr));
1.1       root      297:                }
                    298:        }
                    299: };
                    300: 
1.1.1.2   root      301: // バイトデバイスを奇数アドレスに配置し、偶数アドレスは非接続。
                    302: template <class T>
1.1.1.4   root      303: class BusIO_FB : public T
1.1.1.2   root      304: {
                    305:  private:
1.1.1.9 ! root      306:        inline uint32 Decoder(busaddr addr) const {
        !           307:                return Decoder(addr.Addr());
        !           308:        }
        !           309:        inline uint32 Decoder(uint32 addr) const {
1.1.1.2   root      310:                return (addr >> 1) & (T::NPORT - 1);
                    311:        }
                    312: 
                    313:  public:
1.1.1.9 ! root      314:        busdata Read(busaddr addr) override {
        !           315:                busdata bd;
        !           316:                if (addr.GetSize() == 1 && (addr.Addr() & 1) == 0) {
        !           317:                        bd = 0xff;
        !           318:                } else {
        !           319:                        bd = T::ReadPort(Decoder(addr));
        !           320:                }
        !           321:                bd |= 0xff00;
        !           322:                bd.ChangeSize(2);
        !           323:                return bd;
        !           324:        }
        !           325: 
        !           326:        busdata Write(busaddr addr, uint32 data) override {
        !           327:                busdata r;
        !           328:                uint32 reqsize = addr.GetSize();
        !           329:                uint32 offset = addr.Addr() & 1;
        !           330: 
        !           331:                uint32 op0 = (data >> 24) & 0xff;
        !           332:                uint32 op1 = (data >> 16) & 0xff;
        !           333:                uint32 op2 = (data >>  8) & 0xff;
        !           334:                uint32 op3 =  data        & 0xff;
        !           335:                if (reqsize == 1) {
        !           336:                        if (offset == 0) {
        !           337:                                r.ChangeSize(2);
        !           338:                                return r;
        !           339:                        } else {
        !           340:                                data = op3;
        !           341:                        }
        !           342:                } else if (reqsize == 2) {
        !           343:                        if (offset == 0) {
        !           344:                                data = op3;
        !           345:                        } else {
        !           346:                                data = op2;
        !           347:                        }
        !           348:                } else if (reqsize == 3) {
        !           349:                        if (offset == 0) {
        !           350:                                data = op2;
        !           351:                        } else {
        !           352:                                data = op1;
        !           353:                        }
1.1.1.2   root      354:                } else {
1.1.1.9 ! root      355:                        if (offset == 0) {
        !           356:                                data = op1;
        !           357:                        } else {
        !           358:                                data = op0;
        !           359:                        }
1.1.1.2   root      360:                }
1.1.1.9 ! root      361:                r = T::WritePort(Decoder(addr), data);
        !           362:                r.ChangeSize(2);
        !           363:                return r;
1.1.1.2   root      364:        }
                    365: 
1.1.1.9 ! root      366:        busdata Peek1(uint32 addr) override {
1.1.1.2   root      367:                if ((addr & 1) == 0) {
                    368:                        return 0xff;
                    369:                } else {
1.1.1.9 ! root      370:                        return T::PeekPort(Decoder(addr));
1.1.1.2   root      371:                }
                    372:        }
                    373: };
                    374: 
1.1       root      375: // バイトデバイスをロングワードの先頭に配置し、他は非接続。
                    376: template <class T>
1.1.1.4   root      377: class BusIO_BFFF : public T
1.1       root      378: {
1.1.1.9 ! root      379:  private:
        !           380:        inline uint32 Decoder(busaddr addr) const {
        !           381:                return Decoder(addr.Addr());
        !           382:        }
        !           383:        inline uint32 Decoder(uint32 addr) const {
1.1       root      384:                return (addr >> 2) & (T::NPORT - 1);
                    385:        }
                    386: 
                    387:  public:
1.1.1.9 ! root      388:        busdata Read(busaddr addr) override {
        !           389:                busdata bd = T::ReadPort(Decoder(addr));
        !           390:                bd <<= 24;
        !           391:                bd |= 0x00ffffff;
        !           392:                bd.ChangeSize(4);
        !           393:                return bd;
        !           394:        }
        !           395: 
        !           396:        busdata Write(busaddr addr, uint32 data) override {
        !           397:                data >>= (addr.GetSize() - 1) * 8;
        !           398:                busdata r = T::WritePort(Decoder(addr), data);
        !           399:                r.ChangeSize(4);
        !           400:                return r;
1.1       root      401:        }
                    402: 
1.1.1.9 ! root      403:        busdata Peek1(uint32 addr) override {
1.1       root      404:                if ((addr & 3) == 0) {
1.1.1.9 ! root      405:                        return T::PeekPort(Decoder(addr));
1.1       root      406:                } else {
                    407:                        return 0xff;
                    408:                }
                    409:        }
1.1.1.7   root      410: 
1.1.1.9 ! root      411:        bool Poke1(uint32 addr, uint32 data) override {
1.1.1.7   root      412:                if ((addr & 3) == 0) {
1.1.1.9 ! root      413:                        return T::PokePort(Decoder(addr), data);
1.1.1.7   root      414:                } else {
                    415:                        // 非接続なので、書き換えようとしてもエラーも起きず何も起きない。
1.1.1.8   root      416:                        return true;
1.1       root      417:                }
                    418:        }
                    419: };
                    420: 
                    421: // ワードデバイスをロングワード先頭に配置し、他は非接続。
                    422: template <class T>
1.1.1.4   root      423: class BusIO_WF : public T
1.1       root      424: {
                    425:  private:
1.1.1.9 ! root      426:        inline uint32 Decoder(busaddr addr) const {
        !           427:                return Decoder(addr.Addr());
        !           428:        }
        !           429:        inline uint32 Decoder(uint32 addr) const {
1.1       root      430:                return (addr >> 2) & (T::NPORT - 1);
                    431:        }
                    432:  public:
1.1.1.9 ! root      433:        busdata Read(busaddr addr) override {
        !           434:                busdata bd = T::ReadPort(Decoder(addr));
        !           435:                bd <<= 16;
        !           436:                bd |= 0xffff;
        !           437:                bd.ChangeSize(4);
        !           438:                return bd;
1.1       root      439:        }
                    440: 
1.1.1.9 ! root      441:        busdata Write(busaddr addr, uint32 data) override {
        !           442:                if (addr.GetSize() == 4) {
        !           443:                        data >>= 16;
        !           444:                } else if (addr.GetSize() == 2) {
        !           445:                        // ワード書き込みならデータバスは MSB LSB MSB LSB。(88200 p5-27)
1.1       root      446:                } else {
1.1.1.9 ! root      447:                        // バイト書き込みなら全バイトがコピー。
        !           448:                        data |= data << 8;
1.1       root      449:                }
1.1.1.9 ! root      450:                busdata r = T::WritePort(Decoder(addr), data);
        !           451:                r.ChangeSize(4);
        !           452:                return r;
1.1       root      453:        }
1.1.1.9 ! root      454: 
        !           455:        busdata Peek1(uint32 addr) override {
1.1       root      456:                switch (addr & 3) {
                    457:                 case 0:
1.1.1.9 ! root      458:                        return T::PeekPort(Decoder(addr)) >> 8;
1.1       root      459:                 case 1:
1.1.1.9 ! root      460:                        return T::PeekPort(Decoder(addr)) & 0xff;
1.1       root      461:                 case 2:
                    462:                 case 3:
                    463:                        return 0xff;
                    464:                }
                    465:                __unreachable();
                    466:        }
                    467: };
                    468: 
                    469: // X680x0 の SPC を収容するための専用バスアダプタ。
                    470: // ここは SASI 跡地 32バイト分と SCSI 用地 32バイト分を合わせた 64 バイト
                    471: // (0x40 バイト) でのミラーになっているため、BusIO_EB では表現できない。
                    472: // SASI 跡地は実際には読み出しパターンがあるようだが、本題ではないので
                    473: // とりあえず全部 0xff を返しておく。
                    474: template <class T>
                    475: class BusIO_X68kSPC : public T
                    476: {
                    477:  private:
1.1.1.9 ! root      478:        inline uint32 Decoder(busaddr addr) const {
        !           479:                return Decoder(addr.Addr());
        !           480:        }
        !           481:        inline uint32 Decoder(uint32 addr) const {
1.1       root      482:                // SASI 跡地と SCSI を合わせて 0x40 バイトでミラーしている
                    483:                return (addr >> 1) & (0x20 - 1);
                    484:        }
                    485: 
                    486:  public:
1.1.1.9 ! root      487:        busdata Read(busaddr addr) override {
        !           488:                if (addr.GetSize() == 1 && (addr.Addr() & 1) == 0) {
        !           489:                        return BusData::BusErr;
        !           490:                }
        !           491:                uint32 offset = Decoder(addr);
        !           492:                busdata bd;
        !           493:                if (offset < 0x10) {
        !           494:                        // 前半16ポートは SASI 跡地。
        !           495:                        bd = 0xff;
1.1       root      496:                } else {
1.1.1.9 ! root      497:                        // 後半16ポートは SCSI。
        !           498:                        bd = T::ReadPort(offset - 0x10);
        !           499:                }
        !           500:                bd |= 0xff00;
        !           501:                bd.ChangeSize(2);
        !           502:                return bd;
        !           503:        }
        !           504: 
        !           505:        busdata Write(busaddr addr, uint32 data) override {
        !           506:                busdata r;
        !           507:                uint32 reqsize = addr.GetSize();
        !           508:                uint32 offset = addr.Addr() & 1;
        !           509: 
        !           510:                uint32 op0 = (data >> 24) & 0xff;
        !           511:                uint32 op1 = (data >> 16) & 0xff;
        !           512:                uint32 op2 = (data >>  8) & 0xff;
        !           513:                uint32 op3 =  data        & 0xff;
        !           514:                if (reqsize == 1) {
        !           515:                        if (offset == 0) {
        !           516:                                return BusData::BusErr;
1.1       root      517:                        } else {
1.1.1.9 ! root      518:                                data = op3;
        !           519:                        }
        !           520:                } else if (reqsize == 2) {
        !           521:                        if (offset == 0) {
        !           522:                                data = op3;
        !           523:                        } else {
        !           524:                                data = op2;
        !           525:                        }
        !           526:                } else if (reqsize == 3) {
        !           527:                        if (offset == 0) {
        !           528:                                data = op2;
        !           529:                        } else {
        !           530:                                data = op1;
1.1       root      531:                        }
                    532:                } else {
1.1.1.9 ! root      533:                        if (offset == 0) {
        !           534:                                data = op1;
1.1       root      535:                        } else {
1.1.1.9 ! root      536:                                data = op0;
1.1       root      537:                        }
                    538:                }
1.1.1.9 ! root      539:                uint32 pa = Decoder(addr);
        !           540:                if (pa < 0x10) {
1.1       root      541:                        // 前半16ポートは SASI 跡地。
                    542:                        // XXX 書き込みはどうなる?
                    543:                } else {
1.1.1.9 ! root      544:                        r = T::WritePort(pa - 0x10, data);
1.1       root      545:                }
1.1.1.9 ! root      546:                r.ChangeSize(2);
        !           547:                return r;
1.1       root      548:        }
                    549: 
1.1.1.9 ! root      550:        busdata Peek1(uint32 addr) override {
1.1       root      551:                if ((addr & 1) == 0) {
1.1.1.9 ! root      552:                        return BusData::BusErr;
1.1       root      553:                } else {
                    554:                        addr = Decoder(addr);
                    555:                        if (addr < 0x10) {
                    556:                                // 前半16ポートは SASI 跡地。
                    557:                                return 0xff;
                    558:                        } else {
                    559:                                // 後半16ポートは SCSI。
1.1.1.9 ! root      560:                                return T::PeekPort(addr - 0x10);
1.1       root      561:                        }
                    562:                }
                    563:        }
                    564: };

unix.superglobalmegacorp.com

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