|
|
nono 1.5.0
//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//
//
// XP プロセッサの物理バス
//
// IODevice
// +-- MainbusDevice (InitMainbus() と Read/Write に FC 版がある)
// | +-- Mainbus24Device
// | | +-- LunaMainbus
// | | | +-- Luna1Mainbus
// | | | +-- Luna88kMainbus
// | | +-- NewsMainbus
// | | +-- Virt68kMainbus
// | +-- X68kMainbus
// | +-- X68kIODevice
// |
// | +-------------+
// +-------| XPbusDevice | (これはただの IODevice)
// +-------------+
// 00000H +-------------------+
// | 3Port RAM (128KB) |
// 20000H +-------------------+
// | PROM (32KB) | ソケットが空のようだ
// 28000H +-------------------+
// | 3Port RAM (32KB) |
// 30000H +-------------------+
// | |
// : 無効
// | |
// FFE00H +-------------------+
// | 内蔵 RAM (512B) | (実際の位置は I/O で決まる)
// FFFFFH +-------------------+
//
// 3Port RAM (128KB) のほうは vm_luna で確保されている subram、
// 3Port RAM (32KB) のほうはこちらで確保する subram2。
// 内蔵 RAM は XPBusDevice の internal_ram[]。
#include "xpbus.h"
#include "nop.h"
#include "subram.h"
// コンストラクタ
XPbusDevice::XPbusDevice()
: inherited(OBJ_XPBUS)
{
pSubRAM2.reset(new SubRAM2Device(32));
pXPRAM.reset(new XPRAMDevice());
}
// デストラクタ
XPbusDevice::~XPbusDevice()
{
}
// 初期化
bool
XPbusDevice::Init()
{
nopio = GetNopIODevice();
subram = GetSubRAMDevice();
return true;
}
void
XPbusDevice::ResetHard(bool poweron)
{
// RMCR のリセットは XP 側からされるのでここでは何もしない
}
inline IODevice *
XPbusDevice::SearchDevice(uint32 addr) const
{
// まず内蔵 512 バイトRAM (位置は設定で可変)
if (__predict_true((addr & 0xffe00) == ram_addr)) {
return pXPRAM.get();
}
if (__predict_true(addr < 0x20000)) { // 00000H-20000H: 3Port RAM (128KB)
return subram;
}
if (__predict_false(addr < 0x28000)) { // 20000H-28000H: PROM 領域 (32KB)
return nopio;
}
if (__predict_true(addr < 0x30000)) { // 28000H-30000H: 非共有 RAM (32KB)
return pSubRAM2.get();
}
// 30000H 以降は空き。
// アクセス特性が NopIO かどうかは未調査。
return nopio;
}
busdata
XPbusDevice::Read1(uint32 addr)
{
addr &= 0x000fffff;
IODevice *d = SearchDevice(addr);
return d->Read1(addr);
}
busdata
XPbusDevice::Write1(uint32 addr, uint32 data)
{
addr &= 0x000fffff;
IODevice *d = SearchDevice(addr);
return d->Write1(addr, data);
}
busdata
XPbusDevice::Peek1(uint32 addr)
{
addr &= 0x000fffff;
IODevice *d = SearchDevice(addr);
return d->Peek1(addr);
}
bool
XPbusDevice::Poke1(uint32 addr, uint32 data)
{
addr &= 0x000fffff;
IODevice *d = SearchDevice(addr);
return d->Poke1(addr, data);
}
// RMCR レジスタを取得する
uint32
XPbusDevice::GetRMCR() const
{
return (ram_addr >> 12) & 0xff;
}
// RMCR レジスタを設定する
void
XPbusDevice::SetRMCR(uint32 data)
{
ram_addr = ((data & 0xf0) << 12) | 0xfe00;
}
//
// XP 内蔵 512 バイト RAM
//
// IODevice にしておかないといけない関係で独立して用意する。
// ここは RAM 実体を持っているだけで、配置場所は XPbusDevice が担当している。
//
// コンストラクタ
XPRAMDevice::XPRAMDevice()
: inherited(OBJ_XPRAM)
{
}
// デストラクタ
XPRAMDevice::~XPRAMDevice()
{
}
busdata
XPRAMDevice::Read1(uint32 addr)
{
uint32 offset = addr & 0x1ff;
busdata data = ram[offset];
return data;
}
busdata
XPRAMDevice::Write1(uint32 addr, uint32 data)
{
uint32 offset = addr & 0x1ff;
ram[offset] = data;
return 0;
}
busdata
XPRAMDevice::Peek1(uint32 addr)
{
addr &= 0x1ff;
return ram[addr];
}
bool
XPRAMDevice::Poke1(uint32 addr, uint32 data)
{
if ((int32)data >= 0) {
addr &= 0x1ff;
ram[addr] = data;
}
return true;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.