--- nono/vm/subram.cpp 2026/04/29 17:05:18 1.1.1.1 +++ nono/vm/subram.cpp 2026/04/29 17:05:43 1.1.1.4 @@ -18,13 +18,13 @@ // // コンストラクタ -SubRAMBaseDevice::SubRAMBaseDevice(int objid_, uint ramsize_kb) +SubRAMBaseDevice::SubRAMBaseDevice(uint objid_, uint ramsize_kb) : inherited(objid_) { - ramsize = ramsize_kb * 1024; + uint ramsize = ramsize_kb * 1024; + assert((ramsize & (ramsize - 1)) == 0); - ram.reset(new uint8[ramsize]); - memset(&ram[0], 0, ramsize); + mask = ramsize - 1; } // デストラクタ @@ -32,115 +32,158 @@ SubRAMBaseDevice::~SubRAMBaseDevice() { } +// 初期化 +bool +SubRAMBaseDevice::Init() +{ + uint ramsize = GetSize(); + ram.reset(new(std::nothrow) uint8[ramsize]); + if ((bool)ram == false) { + warnx("Cannot allocate %u bytes at %s", ramsize, __method__); + return false; + } + memset(&ram[0], 0, ramsize); + + return true; +} + // リセット void SubRAMBaseDevice::ResetHard(bool poweron) { if (poweron) { // 実際にはゼロ初期化ではなくゴミだと思うがとりあえず。 - memset(&ram[0], 0, ramsize); + memset(&ram[0], 0, GetSize()); } } // アドレスデコーダ -inline uint64 +inline uint32 SubRAMBaseDevice::Decoder(uint32 addr) const { - // たぶん 128KB というかサイズ分で折り返しイメージが見えるはず。要確認。 - return addr % ramsize; + // たぶんサイズ分で折り返しイメージが見えるはず。要確認。 + return addr & mask; } -uint64 -SubRAMBaseDevice::Read8(uint32 addr) +// MPU からのアクセス +busdata +SubRAMBaseDevice::Read(busaddr addr) { - uint32 offset = Decoder(addr); - uint32 data = ram[offset]; - putlog(4, "$%08x.B -> $%02x", addr, data); + uint32 offset = Decoder(addr.Addr()); + busdata data; + + // MPU からはおそらくロングワードデバイス。 + data = be32toh(*(uint32 *)&ram[offset & ~3U]); + data |= BusData::Size4; + putlog(4, "$%08x -> $%08x", addr.Addr(), data.Data()); return data; } -uint64 -SubRAMBaseDevice::Read16(uint32 addr) +// MPU からのアクセス +busdata +SubRAMBaseDevice::Write(busaddr addr, uint32 data) +{ + uint32 offset = Decoder(addr.Addr()); + uint32 reqsize = addr.GetSize(); + uint32 datasize = std::min(4 - (offset & 3U), reqsize); + + // MPU からはおそらくロングワードデバイス。 + if (datasize == 4) { + putlog(3, "$%08x <- $%08x", addr.Addr(), data); + *(uint32 *)&ram[offset] = htobe32(data); + } else if (datasize == 1) { + data >>= (reqsize - datasize) * 8; + putlog(3, "$%08x <- $%02x", addr.Addr(), data); + ram[offset] = data; + } else { + data >>= (reqsize - datasize) * 8; + putlog(3, "$%08x <- $%0*x", addr.Addr(), datasize * 2, data); + for (int i = datasize - 1; i >= 0; i--) { + ram[offset + i] = data; + data >>= 8; + } + } + + busdata r = BusData::Size4; + return r; +} + +busdata +SubRAMBaseDevice::Peek1(uint32 addr) { uint32 offset = Decoder(addr); - uint32 data; - data = (uint32)ram[offset + 0] << 8; - data |= (uint32)ram[offset + 1]; - putlog(4, "$%08x.W -> $%04x", addr, data); - return data; + return ram[offset]; +} + +bool +SubRAMBaseDevice::Poke1(uint32 addr, uint32 data) +{ + if ((int32)data >= 0) { + uint32 offset = Decoder(addr); + ram[offset] = data; + } + return true; } -uint64 -SubRAMBaseDevice::Read32(uint32 addr) +// XP からのバイト読み込み。 +// (サイズは自明なので返さない) +busdata +SubRAMBaseDevice::Read1(uint32 addr) { uint32 offset = Decoder(addr); - uint32 data; - data = (uint32)ram[offset + 0] << 24; - data |= (uint32)ram[offset + 1] << 16; - data |= (uint32)ram[offset + 2] << 8; - data |= (uint32)ram[offset + 3]; - putlog(4, "$%08x.L -> $%08x", addr, data); + busdata data = ram[offset]; + putlog(4, "XP $%05x -> $%02x", offset, data.Data()); return data; } -uint64 -SubRAMBaseDevice::Write8(uint32 addr, uint32 data) +// XP からのバイト書き込み。 +// (サイズは自明なので返さない) +busdata +SubRAMBaseDevice::Write1(uint32 addr, uint32 data) { - putlog(3, "$%08x.B <- $%02x", addr, data); - uint32 offset = Decoder(addr); + putlog(3, "XP $%05x <- $%02x", offset, data); ram[offset] = data; return 0; } -uint64 -SubRAMBaseDevice::Write16(uint32 addr, uint32 data) +// Lance からのワード読み込み。addr は偶数であること。 +// (サイズは自明なので返さない) +busdata +SubRAMBaseDevice::Read2(uint32 addr) { - putlog(3, "$%08x.W <- $%04x", addr, data); - - uint32 offset = Decoder(addr); - ram[offset + 0] = (data >> 8) & 0xff; - ram[offset + 1] = data & 0xff; - return 0; + busdata data = Peek2(addr); + putlog(4, "LE $%05x -> $%04x", Decoder(addr), data.Data()); + return data; } -uint64 -SubRAMBaseDevice::Write32(uint32 addr, uint32 data) +// Lance からのワード書き込み。addr は偶数であること。 +// (サイズは自明なので返さない) +busdata +SubRAMBaseDevice::Write2(uint32 addr, uint32 data) { - putlog(3, "$%08x.L <- $%08x", addr, data); - uint32 offset = Decoder(addr); - ram[offset + 0] = data >> 24; - ram[offset + 1] = (data >> 16) & 0xff; - ram[offset + 2] = (data >> 8) & 0xff; - ram[offset + 3] = data & 0xff; + putlog(3, "LE $%05x <- $%04x", offset, data); + *(uint16 *)&ram[offset] = htobe16(data); return 0; } -uint64 -SubRAMBaseDevice::Peek8(uint32 addr) +// Lance からのピーク。addr は偶数であること。 +busdata +SubRAMBaseDevice::Peek2(uint32 addr) const { uint32 offset = Decoder(addr); - return ram[offset]; -} - -uint64 -SubRAMBaseDevice::Poke8(uint32 addr, uint32 data) -{ - if ((int32)data >= 0) { - uint32 offset = Decoder(addr); - ram[offset] = data; - } - return 0; + busdata data = be16toh(*(uint16 *)&ram[offset]); + return data; } // -// サブメモリ 1 +// サブメモリ 1 (XP/Lance との共有 RAM) // // コンストラクタ -SubRAMDevice::SubRAMDevice(int ramsize_kb) +SubRAMDevice::SubRAMDevice(uint ramsize_kb) : inherited(OBJ_SUBRAM, ramsize_kb) { } @@ -164,11 +207,11 @@ SubRAMDevice::ResetHard(bool poweron) // -// サブメモリ 2 +// サブメモリ 2 (XP の非共有部) // // コンストラクタ -SubRAM2Device::SubRAM2Device(int ramsize_kb) +SubRAM2Device::SubRAM2Device(uint ramsize_kb) : inherited(OBJ_SUBRAM2, ramsize_kb) { }