--- nono/vm/busio.h 2026/04/29 17:04:31 1.1 +++ nono/vm/busio.h 2026/04/29 17:04:55 1.1.1.4 @@ -1,18 +1,21 @@ // // nono -// Copyright (C) 2020 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // // バスとデバイスとのインタフェース。 // バスに対し、デバイスがどのように接続されているかを記述する。 +#pragma once + #if !defined(SELFTEST) #include "device.h" #endif // バイトデバイスをバイト、ワード、ロングワードポートにミラー配置する共通部 template -class BusIO_B_Base: public T +class BusIO_B_Base : public T { private: inline uint32 Decoder(uint32 addr) { @@ -20,15 +23,15 @@ class BusIO_B_Base: public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { return T::Read(Decoder(addr)); } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { return T::Peek(Decoder(addr)); } }; @@ -36,18 +39,18 @@ class BusIO_B_Base: public T // バイトデバイスをバイトのまま配置する。 // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。 template -class BusIO_B: public BusIO_B_Base { }; +class BusIO_B : public BusIO_B_Base { }; // バイトデバイスをワードにミラー配置する。 template -class BusIO_BB: public BusIO_B_Base { }; +class BusIO_BB : public BusIO_B_Base { }; // バイトデバイスをロングワードにミラー配置する。 template -class BusIO_BBBB: public BusIO_B_Base { }; +class BusIO_BBBB : public BusIO_B_Base { }; // ワードデバイスをワードのまま配置する。 // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。 template -class BusIO_W: public T +class BusIO_W : public T { private: inline uint32 Decoder(uint32 addr) { @@ -55,27 +58,32 @@ class BusIO_W: public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 1) == 0) { return T::Read(Decoder(addr)) >> 8; } else { return T::Read(Decoder(addr)) & 0xff; } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { return T::Read(Decoder(addr)); } - virtual uint64 Write8(uint32 addr, uint32 data) { - PANIC("not implemented\n"); - return (int64)-1; // XXX 未確認 + uint64 Write8(uint32 addr, uint32 data) override { + uint32 offset = Decoder(addr); + uint32 old = T::Read(offset); + if ((addr & 1) == 0) { + return T::Write(offset, ((data << 8) & 0xff00) | (old & 0x00ff)); + } else { + return T::Write(offset, (old & 0xff00) | (data & 0x00ff)); + } } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 1) == 0) { return T::Peek(Decoder(addr)) >> 8; } else { @@ -85,12 +93,12 @@ class BusIO_W: public T }; /* XXX: stub -class BusIO_L: public T +class BusIO_L : public T */ // バイトデバイスを偶数アドレスに配置し、奇数アドレスはバスエラー。 template -class BusIO_BE: public T +class BusIO_BE : public T { private: inline uint32 Decoder(uint32 addr) { @@ -98,29 +106,29 @@ class BusIO_BE: public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 1) == 0) { return T::Read(Decoder(addr)); } else { return (int64)-1; } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { return (T::Read(Decoder(addr)) << 8) | 0xff; } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { return T::Write(Decoder(addr), data); } else { return (int64)-1; } } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data >> 8); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 1) == 0) { return T::Peek(Decoder(addr)); } else { @@ -131,7 +139,7 @@ class BusIO_BE: public T // バイトデバイスを奇数アドレスに配置し、偶数アドレスはバスエラー。 template -class BusIO_EB: public T +class BusIO_EB : public T { private: inline uint32 Decoder(uint32 addr) { @@ -139,29 +147,29 @@ class BusIO_EB: public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 1) == 0) { return (int64)-1; } else { return T::Read(Decoder(addr)); } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { return T::Read(Decoder(addr)) | 0xff00; } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { return (int64)-1; } else { return T::Write(Decoder(addr), data); } } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data & 0xff); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 1) == 0) { return (int64)-1; } else { @@ -170,9 +178,50 @@ class BusIO_EB: public T } }; +// バイトデバイスを奇数アドレスに配置し、偶数アドレスは非接続。 +template +class BusIO_FB : public T +{ + private: + inline uint32 Decoder(uint32 addr) { + return (addr >> 1) & (T::NPORT - 1); + } + + public: + uint64 Read8(uint32 addr) override { + if ((addr & 1) == 0) { + return 0xff; + } else { + return T::Read(Decoder(addr)); + } + } + uint64 Read16(uint32 addr) override { + return T::Read(Decoder(addr)) | 0xff00; + } + + uint64 Write8(uint32 addr, uint32 data) override { + if ((addr & 1) == 0) { + return 0; + } else { + return T::Write(Decoder(addr), data); + } + } + uint64 Write16(uint32 addr, uint32 data) override { + return T::Write(Decoder(addr), data & 0xff); + } + + uint64 Peek8(uint32 addr) override { + if ((addr & 1) == 0) { + return 0xff; + } else { + return T::Peek(Decoder(addr)); + } + } +}; + // バイトデバイスをロングワードの先頭に配置し、他は非接続。 template -class BusIO_BFFF: public T +class BusIO_BFFF : public T { private: inline uint32 Decoder(uint32 addr) { @@ -180,43 +229,43 @@ class BusIO_BFFF: public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 3) == 0) { return T::Read(Decoder(addr)); } else { return 0xff; } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { if ((addr & 2) == 0) { return (T::Read(Decoder(addr)) << 8) | 0xff; } else { return 0xffff; } } - virtual uint64 Read32(uint32 addr) { + uint64 Read32(uint32 addr) override { return (T::Read(Decoder(addr)) << 24) | 0x00ffffff; } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { if ((addr & 3) == 0) { return T::Write(Decoder(addr), data); } else { return 0; } } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { if ((addr & 2) == 0) { return T::Write(Decoder(addr), data >> 8); } else { return 0; } } - virtual uint64 Write32(uint32 addr, uint32 data) { + uint64 Write32(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data >> 24); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 3) == 0) { return T::Peek(Decoder(addr)); } else { @@ -227,33 +276,33 @@ class BusIO_BFFF: public T // ワードデバイスをロングワードにミラー配置する。 template -class BusIO_WW: public T +class BusIO_WW : public T { private: inline uint32 Decoder(uint32 addr) { return (addr >> 2) & (T::NPORT - 1); } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 1) == 0) { return T::Read(Decoder(addr)) >> 8; } else { return T::Read(Decoder(addr)) & 0xff; } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { return T::Read(Decoder(addr)); } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { PANIC("not implemented\n"); return (int64)-1; // XXX 未確認 } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data); } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 1) == 0) { return T::Peek(Decoder(addr)) >> 8; } else { @@ -264,14 +313,14 @@ class BusIO_WW: public T // ワードデバイスをロングワード先頭に配置し、他は非接続。 template -class BusIO_WF: public T +class BusIO_WF : public T { private: inline uint32 Decoder(uint32 addr) { return (addr >> 2) & (T::NPORT - 1); } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { switch (addr & 3) { case 0: return T::Read(Decoder(addr)) >> 8; @@ -283,7 +332,7 @@ class BusIO_WF: public T } __unreachable(); } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { if ((addr & 2) == 0) { return T::Read(Decoder(addr)); } else { @@ -291,18 +340,18 @@ class BusIO_WF: public T } } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { PANIC("not implemented\n"); return 0; // XXX 未確認 } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { if ((addr & 2) == 0) { return T::Write(Decoder(addr), data); } else { return 0; } } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { switch (addr & 3) { case 0: return T::Peek(Decoder(addr)) >> 8; @@ -331,7 +380,7 @@ class BusIO_X68kSPC : public T } public: - virtual uint64 Read8(uint32 addr) { + uint64 Read8(uint32 addr) override { if ((addr & 1) == 0) { return (uint64)-1; } else { @@ -345,7 +394,7 @@ class BusIO_X68kSPC : public T } } } - virtual uint64 Read16(uint32 addr) { + uint64 Read16(uint32 addr) override { addr = Decoder(addr); if (addr < 0x10) { // 前半16ポートは SASI 跡地 @@ -355,7 +404,7 @@ class BusIO_X68kSPC : public T } } - virtual uint64 Write8(uint32 addr, uint32 data) { + uint64 Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { return (uint64)-1; } else { @@ -370,7 +419,7 @@ class BusIO_X68kSPC : public T } } } - virtual uint64 Write16(uint32 addr, uint32 data) { + uint64 Write16(uint32 addr, uint32 data) override { addr = Decoder(addr); if (addr < 0x10) { // 前半16ポートは SASI 跡地。 @@ -382,7 +431,7 @@ class BusIO_X68kSPC : public T } } - virtual uint64 Peek8(uint32 addr) { + uint64 Peek8(uint32 addr) override { if ((addr & 1) == 0) { return (uint64)-1; } else {