--- nono/vm/busio.h 2026/04/29 17:04:35 1.1.1.2 +++ nono/vm/busio.h 2026/04/29 17:05:25 1.1.1.8 @@ -7,48 +7,54 @@ // バスとデバイスとのインタフェース。 // バスに対し、デバイスがどのように接続されているかを記述する。 +#pragma once + #if !defined(SELFTEST) #include "device.h" #endif // バイトデバイスをバイト、ワード、ロングワードポートにミラー配置する共通部 template -class BusIO_B_Base: public T +class BusIO_B_Base : public T { - private: + protected: inline uint32 Decoder(uint32 addr) { return (addr >> rshift) & (T::NPORT - 1); } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { return T::Read(Decoder(addr)); } - uint64 Write8(uint32 addr, uint32 data) override { + busdata Write8(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data); } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { return T::Peek(Decoder(addr)); } + + bool Poke8(uint32 addr, uint32 data) override { + return T::Poke(Decoder(addr), data); + } }; // バイトデバイスをバイトのまま配置する。 // 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) { @@ -56,32 +62,32 @@ class BusIO_W: public T } public: - uint64 Read8(uint32 addr) override { + // ワードポートからのバイト読み込みはワードで読んだ後必要な方を取る。 + busdata Read8(uint32 addr) override { if ((addr & 1) == 0) { - return T::Read(Decoder(addr)) >> 8; + busdata data = T::Read(Decoder(addr)); + data >>= 8; + return data; } else { - return T::Read(Decoder(addr)) & 0xff; + busdata data = T::Read(Decoder(addr)); + data &= 0xff; + return data; } } - uint64 Read16(uint32 addr) override { + busdata Read16(uint32 addr) override { return T::Read(Decoder(addr)); } - 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)); - } + // ワードポートにバイト書き込みするとデータバスは OP3 OP3 OP3 OP3。 + busdata Write8(uint32 addr, uint32 data) override { + data |= data << 8; + return T::Write(Decoder(addr), data); } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data); } - - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 1) == 0) { return T::Peek(Decoder(addr)) >> 8; } else { @@ -91,12 +97,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) { @@ -104,40 +110,43 @@ class BusIO_BE: public T } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { if ((addr & 1) == 0) { return T::Read(Decoder(addr)); } else { - return (int64)-1; + return busdata::BusErr; } } - uint64 Read16(uint32 addr) override { - return (T::Read(Decoder(addr)) << 8) | 0xff; + busdata Read16(uint32 addr) override { + busdata data = T::Read(Decoder(addr)); + data <<= 8; + data |= 0xff; + return data; } - uint64 Write8(uint32 addr, uint32 data) override { + busdata Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { return T::Write(Decoder(addr), data); } else { - return (int64)-1; + return busdata::BusErr; } } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data >> 8); } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 1) == 0) { return T::Peek(Decoder(addr)); } else { - return (int64)-1; + return busdata::BusErr; } } }; // バイトデバイスを奇数アドレスに配置し、偶数アドレスはバスエラー。 template -class BusIO_EB: public T +class BusIO_EB : public T { private: inline uint32 Decoder(uint32 addr) { @@ -145,31 +154,33 @@ class BusIO_EB: public T } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { if ((addr & 1) == 0) { - return (int64)-1; + return busdata::BusErr; } else { return T::Read(Decoder(addr)); } } - uint64 Read16(uint32 addr) override { - return T::Read(Decoder(addr)) | 0xff00; + busdata Read16(uint32 addr) override { + busdata data = T::Read(Decoder(addr)); + data |= 0xff00; + return data; } - uint64 Write8(uint32 addr, uint32 data) override { + busdata Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { - return (int64)-1; + return busdata::BusErr; } else { return T::Write(Decoder(addr), data); } } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data & 0xff); } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 1) == 0) { - return (int64)-1; + return busdata::BusErr; } else { return T::Peek(Decoder(addr)); } @@ -178,7 +189,7 @@ class BusIO_EB: public T // バイトデバイスを奇数アドレスに配置し、偶数アドレスは非接続。 template -class BusIO_FB: public T +class BusIO_FB : public T { private: inline uint32 Decoder(uint32 addr) { @@ -186,29 +197,31 @@ class BusIO_FB: public T } public: - uint64 Read8(uint32 addr) override { + busdata 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; + busdata Read16(uint32 addr) override { + busdata data = T::Read(Decoder(addr)); + data |= 0xff00; + return data; } - uint64 Write8(uint32 addr, uint32 data) override { + busdata 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 { + busdata Write16(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data & 0xff); } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 1) == 0) { return 0xff; } else { @@ -219,118 +232,101 @@ class BusIO_FB: public T // バイトデバイスをロングワードの先頭に配置し、他は非接続。 template -class BusIO_BFFF: public T +class BusIO_BFFF : public T { - private: + protected: inline uint32 Decoder(uint32 addr) { return (addr >> 2) & (T::NPORT - 1); } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { if ((addr & 3) == 0) { return T::Read(Decoder(addr)); } else { return 0xff; } } - uint64 Read16(uint32 addr) override { + busdata Read16(uint32 addr) override { if ((addr & 2) == 0) { - return (T::Read(Decoder(addr)) << 8) | 0xff; + busdata data = T::Read(Decoder(addr)); + data <<= 8; + data |= 0xff; + return data; } else { return 0xffff; } } - uint64 Read32(uint32 addr) override { - return (T::Read(Decoder(addr)) << 24) | 0x00ffffff; + busdata Read32(uint32 addr) override { + busdata data = T::Read(Decoder(addr)); + data <<= 24; + data |= 0x00ffffff; + return data; } - uint64 Write8(uint32 addr, uint32 data) override { + busdata Write8(uint32 addr, uint32 data) override { if ((addr & 3) == 0) { return T::Write(Decoder(addr), data); } else { return 0; } } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { if ((addr & 2) == 0) { return T::Write(Decoder(addr), data >> 8); } else { return 0; } } - uint64 Write32(uint32 addr, uint32 data) override { + busdata Write32(uint32 addr, uint32 data) override { return T::Write(Decoder(addr), data >> 24); } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 3) == 0) { return T::Peek(Decoder(addr)); } else { return 0xff; } } -}; -// ワードデバイスをロングワードにミラー配置する。 -template -class BusIO_WW: public T -{ - private: - inline uint32 Decoder(uint32 addr) { - return (addr >> 2) & (T::NPORT - 1); - } - public: - uint64 Read8(uint32 addr) override { - if ((addr & 1) == 0) { - return T::Read(Decoder(addr)) >> 8; - } else { - return T::Read(Decoder(addr)) & 0xff; - } - } - uint64 Read16(uint32 addr) override { - return T::Read(Decoder(addr)); - } - - uint64 Write8(uint32 addr, uint32 data) override { - PANIC("not implemented\n"); - return (int64)-1; // XXX 未確認 - } - uint64 Write16(uint32 addr, uint32 data) override { - return T::Write(Decoder(addr), data); - } - - uint64 Peek8(uint32 addr) override { - if ((addr & 1) == 0) { - return T::Peek(Decoder(addr)) >> 8; + bool Poke8(uint32 addr, uint32 data) override { + if ((addr & 3) == 0) { + return T::Poke(Decoder(addr), data); } else { - return T::Peek(Decoder(addr)) & 0xff; + // 非接続なので、書き換えようとしてもエラーも起きず何も起きない。 + return true; } } }; // ワードデバイスをロングワード先頭に配置し、他は非接続。 template -class BusIO_WF: public T +class BusIO_WF : public T { private: inline uint32 Decoder(uint32 addr) { return (addr >> 2) & (T::NPORT - 1); } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { + busdata data; switch (addr & 3) { case 0: - return T::Read(Decoder(addr)) >> 8; + data = T::Read(Decoder(addr)); + data >>= 8; + return data; case 1: - return T::Read(Decoder(addr)) & 0xff; + data = T::Read(Decoder(addr)); + data &= 0xff; + return data; case 2: case 3: return 0xff; } __unreachable(); } - uint64 Read16(uint32 addr) override { + busdata Read16(uint32 addr) override { if ((addr & 2) == 0) { return T::Read(Decoder(addr)); } else { @@ -338,18 +334,23 @@ class BusIO_WF: public T } } - uint64 Write8(uint32 addr, uint32 data) override { - PANIC("not implemented\n"); - return 0; // XXX 未確認 + // バイト書き込みならデータバスは OP3 OP3 OP3 OP3。 + busdata Write8(uint32 addr, uint32 data) override { + if ((addr & 2) == 0) { + data |= data << 8; + return T::Write(Decoder(addr), data); + } else { + return 0; + } } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { if ((addr & 2) == 0) { return T::Write(Decoder(addr), data); } else { return 0; } } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { switch (addr & 3) { case 0: return T::Peek(Decoder(addr)) >> 8; @@ -372,15 +373,15 @@ template class BusIO_X68kSPC : public T { private: - inline uint64 Decoder(uint32 addr) { + inline uint32 Decoder(uint32 addr) { // SASI 跡地と SCSI を合わせて 0x40 バイトでミラーしている return (addr >> 1) & (0x20 - 1); } public: - uint64 Read8(uint32 addr) override { + busdata Read8(uint32 addr) override { if ((addr & 1) == 0) { - return (uint64)-1; + return busdata::BusErr; } else { addr = Decoder(addr); if (addr < 0x10) { @@ -392,19 +393,21 @@ class BusIO_X68kSPC : public T } } } - uint64 Read16(uint32 addr) override { + busdata Read16(uint32 addr) override { addr = Decoder(addr); if (addr < 0x10) { // 前半16ポートは SASI 跡地 return 0xffff; } else { - return T::Read(addr - 0x10) | 0xff00; + busdata data = T::Read(addr - 0x10); + data |= 0xff00; + return data; } } - uint64 Write8(uint32 addr, uint32 data) override { + busdata Write8(uint32 addr, uint32 data) override { if ((addr & 1) == 0) { - return (uint64)-1; + return busdata::BusErr; } else { addr = Decoder(addr); if (addr < 0x10) { @@ -417,7 +420,7 @@ class BusIO_X68kSPC : public T } } } - uint64 Write16(uint32 addr, uint32 data) override { + busdata Write16(uint32 addr, uint32 data) override { addr = Decoder(addr); if (addr < 0x10) { // 前半16ポートは SASI 跡地。 @@ -429,9 +432,9 @@ class BusIO_X68kSPC : public T } } - uint64 Peek8(uint32 addr) override { + busdata Peek8(uint32 addr) override { if ((addr & 1) == 0) { - return (uint64)-1; + return busdata::BusErr; } else { addr = Decoder(addr); if (addr < 0x10) {