File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / mainbus_virt68k.cpp
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:01 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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)
{
	// まだサポートしていない。
}

unix.superglobalmegacorp.com

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