|
|
nono 1.2.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// M88200 CMMU の I/O デバイス部分
//
// CMMU が確定しない場合はこのデバイスのログを使う。
// CMMU が確定したらそっちのデバイスログから出力する。
#include "cmmu.h"
#include "m88200.h"
#include "mainapp.h"
// コンストラクタ
CMMUDevice::CMMUDevice()
: inherited(OBJ_CMMUIO)
{
}
// デストラクタ
CMMUDevice::~CMMUDevice()
{
}
// 初期化
bool
CMMUDevice::Init()
{
// CMMU をポイントしておく
for (int i = 0; i < cmmus.size(); i++) {
cmmus[i] = gMainApp.FindObject<m88200>(OBJ_M88200(i));
}
return true;
}
// アドレスデコーダ
/*static*/ inline uint32
CMMUDevice::Decoder(uint32 addr)
{
uint32 offset = addr & 0xfff;
// BWP* の A5 はデコードされてない
if (0x420 <= offset && offset < 0x440) {
offset &= ~0x20;
}
// CDP*,CTP* の A4,A5 はデコードされていない
if (0x800 <= offset && offset < 0x880) {
offset &= ~0x30;
}
return offset;
}
busdata
CMMUDevice::Read(busaddr addr)
{
busdata data;
uint32 paddr = addr.Addr();
uint32 id = (paddr >> 12) & 0xff;
m88200 *cmmu = GetCMMU(id);
if (cmmu == NULL) {
putlog(3, "Read not-equipped CMMU[%u] $%08x", id, paddr);
return 0xffffffff;
}
uint32 offset = Decoder(paddr);
switch (offset) {
case IDR:
data = cmmu->GetIDR();
cmmu->putlogf(2, lstr("IDR -> $%08x", data.Data()));
break;
case SCR:
data = cmmu->GetSCR();
cmmu->putlogf(2, lstr("SCR -> $%08x", data.Data()));
break;
case SSR:
data = cmmu->GetSSR();
cmmu->putlogf(2, lstr("SSR -> $%08x", data.Data()));
break;
case SAR:
data = cmmu->GetSAR();
cmmu->putlogf(2, lstr("SAR -> $%08x", data.Data()));
break;
case SCTR:
data = cmmu->GetSCTR();
cmmu->putlogf(2, lstr("SCTR -> $%08x", data.Data()));
break;
case PFSR:
data = cmmu->GetPFSR();
cmmu->putlogf(2, lstr("PFSR -> $%08x", data.Data()));
break;
case PFAR:
data = cmmu->GetPFAR();
cmmu->putlogf(2, lstr("PFAR -> $%08x", data.Data()));
break;
case SAPR:
data = cmmu->GetSAPR();
cmmu->putlogf(2, lstr("SAPR -> $%08x", data.Data()));
break;
case UAPR:
data = cmmu->GetUAPR();
cmmu->putlogf(2, lstr("UAPR -> $%08x", data.Data()));
break;
case BWP0 ... BWP7:
// BWP は書き込み専用 (何が読めるだろうか)
data = 0xffffffff;
break;
case CSSP:
data = cmmu->GetCSSP();
cmmu->putlogf(2, lstr("CSSP -> $%08x", data.Data()));
break;
case CDP0 ... CDP3:
case CTP0 ... CTP3:
default:
putlog(0, "Read $%08x (NOT IMPLEMENTED)", paddr);
data = 0xffffffff;
}
// XXX wait?
data |= BusData::Size4;
return data;
}
busdata
CMMUDevice::Write(busaddr addr, uint32 data)
{
uint32 paddr = addr.Addr();
uint32 id = (paddr >> 12) & 0xff;
m88200 *cmmu = GetCMMU(id);
if (cmmu == NULL) {
putlog(3, "Write not-equipped CMMU[%u] $%08x <- $%08x",
id, paddr, data);
return 0;
}
// 普通はロングワードアクセスしかしないはず。
// m88k 専用なのでミスアラインアクセスは起きない。
// 88200 p5-27
uint32 size = addr.GetSize();
if (size == 4) {
// nop
} else {
if (size == 1) {
data |= data << 8;
}
data |= data << 16;
}
uint32 offset = Decoder(paddr);
uint n;
switch (offset) {
case IDR:
{
uint32 newid = data >> 24;
if (id != newid) {
// 後から ID を変更するのはサポートしない。というか実際無理では。
cmmu->putlogf(0, lstr(
"IDR <- $%08x (change ID $%02x to $%02x; NOT SUPPORTED)",
data, id, newid));
} else {
cmmu->putlogf(2, lstr("IDR <- $%08x", data));
}
break;
}
case SCR:
cmmu->SetSCR(data);
break;
case SSR:
cmmu->putlogf(1, lstr("SSR <- $%08x", data));
cmmu->SetSSR(data);
break;
case SAR:
cmmu->putlogf(2, lstr("SAR <- $%08x", data));
cmmu->SetSAR(data);
break;
case SCTR:
cmmu->SetSCTR(data);
break;
case PFSR:
cmmu->SetPFSR(data);
break;
case PFAR:
cmmu->SetPFAR(data);
break;
case SAPR:
cmmu->SetSAPR(data);
break;
case UAPR:
cmmu->SetUAPR(data);
break;
case BWP0 ... BWP7:
n = (offset - BWP0) / 4;
assert(n < 8);
cmmu->SetBWP(n, data);
break;
case CSSP:
cmmu->SetCSSP(data);
break;
case CDP0 ... CDP3:
case CTP0 ... CTP3:
default:
putlog(0, "Write $%08x <- $%08x (NOT IMPLEMENTED)", paddr, data);
VMPANIC("not impl");
break;
}
// wait?
busdata r = BusData::Size4;
return r;
}
// Peek1() の下請け。ロングワードで処理して後でバイトに分割するほうが楽。
uint32
CMMUDevice::Peek4(uint32 addr) const
{
uint32 id = (addr >> 12) & 0xff;
m88200 *cmmu = GetCMMU(id);
if (cmmu == NULL) {
return 0xffffffff;
}
uint32 offset = Decoder(addr);
switch (offset) {
case IDR:
return cmmu->GetIDR();
case SCR:
return cmmu->GetSCR();
case SSR:
return cmmu->GetSSR();
case SAR:
return cmmu->GetSAR();
case SCTR:
return cmmu->GetSCTR();
case PFSR:
return cmmu->GetPFSR();
case PFAR:
return cmmu->GetPFAR();
case SAPR:
return cmmu->GetSAPR();
case UAPR:
return cmmu->GetUAPR();
case BWP0 ... BWP7:
return 0xffffffff;
case CDP0 ... CDP3:
case CTP0 ... CTP3:
break;
case CSSP:
return cmmu->GetCSSP();
default:
break;
}
return 0xffffffff;
}
busdata
CMMUDevice::Peek1(uint32 addr)
{
uint32 data = Peek4(addr & ~3U);
switch (addr & 3) {
case 0:
return data >> 24;
case 1:
return (data >> 16) & 0xff;
case 2:
return (data >> 8) & 0xff;
case 3:
return data & 0xff;
default:
return 0xff;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.