|
|
nono 1.7.0
//
// nono
// Copyright (C) 2024 nono project
// Licensed under nono-license.txt
//
//
// メインバス (virt-m68k)
//
// IODevice
// +-- MainbusBaseDevice (InitMainbus() と FC アクセスを持つ)
// | +-- MainbusDevice (これがメインバス、システムに1つ)
// | | +-- Mainbus24Device (上位8ビットがテーブルで表せるメインバス)
// | | | +-- LunaMainbus
// | | | | +-- Luna1Mainbus
// | | | | +-- Luna88kMainbus
// | | | +-- NewsMainbus
// | | |
// | | | +----------------+
// | | +--| Virt68kMainbus |
// | | | +----------------+
// | | |
// | | +-- X68kMainbus
// | +-- X68kIODevice
// +-- XPbusDevice
#include "mainbus_virt68k.h"
#include "buserr.h"
#include "interrupt.h"
#include "mainapp.h"
#include "mainram.h"
#include "monitor.h"
#include "v68kio.h"
// コンストラクタ
Virt68kMainbus::Virt68kMainbus()
: inherited(OBJ_MAINBUS)
{
NEWDV(BusErr, new BusErrDevice());
NEWDV(Interrupt, new Virt68kInterrupt());
NEWDV(MainRAM, new MainRAMDevice());
NEWDV(V68kIO, new V68kIODevice());
// メインメモリは Init() で設定する。
accstat_monitor->SetSize(80, 2 + 32);
}
// デストラクタ
Virt68kMainbus::~Virt68kMainbus()
{
}
// メインバスの初期化
bool
Virt68kMainbus::InitMainbus()
{
// RAM は容量が確定した後のここで配置。
// 16MB 単位になっている。
auto mainram = dynamic_cast<MainRAMDevice *>(pMainRAM.get());
ramsize = mainram->GetSize();
// アクセス状況用のマップを作成。
for (uint32 i = 0; i < 4096 / 16; i++) {
if (Decoder(i * 0x0100'0000) != pBusErr.get()) {
accstat_avail[i / 8] |= 0x80U >> (i % 8);
}
}
return true;
}
inline IODevice *
Virt68kMainbus::Decoder(uint32 addr) const
{
if (__predict_true(addr < ramsize)) {
return pMainRAM.get();
} else if (__predict_true(addr >= 0xff000000)) {
return pV68kIO.get();
} else {
return pBusErr.get();
}
}
busdata
Virt68kMainbus::Read(busaddr addr)
{
uint32 pa = addr.Addr();
lastaddr = pa;
accstat_read[pa >> AccStat::SHIFT] = AccStat::READ;
IODevice *dev = Decoder(pa);
return dev->Read(addr);
}
busdata
Virt68kMainbus::Write(busaddr addr, uint32 data)
{
uint32 pa = addr.Addr();
lastaddr = pa;
accstat_read[pa >> AccStat::SHIFT] = AccStat::WRITE;
IODevice *dev = Decoder(pa);
return dev->Write(addr, data);
}
busdata
Virt68kMainbus::ReadBurst16(busaddr addr, uint32 *dst)
{
uint32 pa = addr.Addr();
lastaddr = pa; // 開始アドレスしか残らない…
IODevice *dev = Decoder(pa);
busdata r = dev->ReadBurst16(addr, dst);
if (__predict_true(r.IsBusErr() == false)) {
accstat_read[pa >> AccStat::SHIFT] = AccStat::READ;
}
return r;
}
busdata
Virt68kMainbus::WriteBurst16(busaddr addr, const uint32 *src)
{
uint32 pa = addr.Addr();
lastaddr = pa; // 開始アドレスしか残らない…
IODevice *dev = Decoder(pa);
busdata r = dev->WriteBurst16(addr, src);
if (__predict_true(r.IsBusErr() == false)) {
accstat_read[pa >> AccStat::SHIFT] = AccStat::WRITE;
}
return r;
}
busdata
Virt68kMainbus::Peek1(uint32 addr)
{
IODevice *dev = Decoder(addr);
return dev->Peek1(addr);
}
bool
Virt68kMainbus::Poke1(uint32 addr, uint32 data)
{
IODevice *dev = Decoder(addr);
return dev->Poke1(addr, data);
}
// ブートページを切り替える。
void
Virt68kMainbus::SwitchBootPage(bool isram)
{
// まだサポートしていない。
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.