--- nono/vm/mpu88xx0.cpp 2026/04/29 17:04:32 1.1 +++ nono/vm/mpu88xx0.cpp 2026/04/29 17:04:42 1.1.1.4 @@ -1,22 +1,49 @@ // // nono -// Copyright (C) 2020 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // // MPU (m88xx0) #include "mpu88xx0.h" #include "config.h" +#include "sysctlr.h" + +std::unique_ptr gMPU88200ATC[2]; // コンストラクタ MPU88xx0Device::MPU88xx0Device(uint32 addr) { - monitor.Init(79, 15); + monitor_size = nnSize(79, 18); // リセットベクタアドレスは Reset() で指定するので保持しておく reset_vector = addr; cpu.reset(new m88kcpu()); + + // リセット例外イベントコールバック設定 + reset_event.func = (DeviceCallback_t)&MPU88xx0Device::ResetCallback; + + // LUNA88K では CMMU の ID は次のように割り振ってあるようだ。 + // OpenBSD の sys/arch/luna68k/include/board.h より。 + // + // Inst Data + // CPU#0 ID=7 ID=6 + // CPU#1 ID=5 ID=4 + // CPU#2 ID=3 ID=2 + // CPU#3 ID=1 ID=0 + // + // 厳密にはこれは LUNA88K のハードウェアがどういうコンフィグレーションで + // m88200 を使うかなので、ここではなくて vm_luna あたりのほうがいいかも + // しれんけど、あまり遠いのも面倒なので、とりあえずこの辺に。 + // あとマルチプロセッサになったらまたその時考える。 + cpu->cmmu[0].SetID(7); + cpu->cmmu[1].SetID(6); + + // モニタ用の別オブジェクト + gMPU88200ATC[0].reset(new MPU88200ATC(&cpu->cmmu[0])); + gMPU88200ATC[1].reset(new MPU88200ATC(&cpu->cmmu[1])); } // デストラクタ @@ -24,17 +51,39 @@ MPU88xx0Device::~MPU88xx0Device() { } -// リセット -// (MPU が動くのはこの後 Scheduler::Run() を発行した後) +// リセット例外イベントコールバック void -MPU88xx0Device::ResetHard() +MPU88xx0Device::ResetCallback(Event& ev) { cpu->Reset(reset_vector); } +// アクセスウェイトを加算 +void +MPU88xx0Device::AddCycle(uint64 cycle) +{ + // 今アクセスしてきている(= バスマスターの) CMMU に対して加算する + m88200 *cmmu = m88200::GetBusMaster(); + assert(cmmu); + cmmu->AddCycle(cycle); +} + +// Interrupt +void +MPU88xx0Device::Interrupt(Object *src, int level) +{ + // XXX: なぜか 1 レベルずれている? + level++; + if (gSysCtlr->GetIntMask(0) & (1 << level)) { + putlog(1, "Interrupt from %s", src->devname.c_str()); + gSysCtlr->TellIntLevel(0, 1 << level); + cpu->Interrupt(); + } +} + // モニター更新 -bool -MPU88xx0Device::MonitorUpdate() +void +MPU88xx0Device::MonitorUpdate(TextScreen& monitor) { m88100reg reg; int x; @@ -53,33 +102,36 @@ MPU88xx0Device::MonitorUpdate() // 制御レジスタ x = 0; y = 9; - monitor.Print(x, y++, "pid (cr0):%08x(arch=$%02x ver=$%02x %c)", + monitor.Print(x, y++, "pid (cr0):%08x(Arch=$%02x Ver=$%02x MC=%s)", reg.pid, (reg.pid >> 8) & 0xff, - (reg.pid & 0xfe), - (reg.pid & 1) ? 'M' : '-'); - monitor.Print(x, y++, "psr (cr1):%08x(%c,%s,%s,%s %s,%s,%s,%s)", - reg.psr, - (reg.psr & m88100reg::PSR_SUPER) ? 'S' : '-', - (reg.psr & m88100reg::PSR_BO_LE) ? "LE" : "BE", - (reg.psr & m88100reg::PSR_SER) ? "CON" : "SER", - (reg.psr & m88100reg::PSR_C) ? "Cy" : "--", - (reg.psr & m88100reg::PSR_SFD1) ? "SFD1" : "----", - (reg.psr & m88100reg::PSR_MXM) ? "MXM" : "---", - (reg.psr & m88100reg::PSR_IND) ? "IND" : "---", - (reg.psr & m88100reg::PSR_SFRZ) ? "SFRZ" : "----"); - monitor.Print(x, y++, "epsr(cr2):%08x(%c,%s,%s,%s %s,%s,%s,%s)", - reg.epsr, - (reg.epsr & m88100reg::PSR_SUPER) ? 'S' : '-', - (reg.epsr & m88100reg::PSR_BO_LE) ? "LE" : "BE", - (reg.epsr & m88100reg::PSR_SER) ? "CON" : "SER", - (reg.epsr & m88100reg::PSR_C) ? "Cy" : "--", - (reg.epsr & m88100reg::PSR_SFD1) ? "SFD1" : "----", - (reg.epsr & m88100reg::PSR_MXM) ? "MXM" : "---", - (reg.epsr & m88100reg::PSR_IND) ? "IND" : "---", - (reg.epsr & m88100reg::PSR_SFRZ) ? "SFRZ" : "----"); + (reg.pid >> 1) & 0x7f, + (reg.pid & 1) ? "Master" : "Checker"); + monitor.Print(x, y, "psr (cr1):%08x(", reg.psr); + monitor.Puts(x + 19, y, TA::OnOff(reg.psr & m88100reg::PSR_SUPER), "S"); + monitor.Puts(x + 21, y, + ((reg.psr & m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE")); + monitor.Puts(x + 27, y, TA::OnOff(reg.psr & m88100reg::PSR_SER), "SER"); + monitor.Puts(x + 31, y, TA::OnOff(reg.psr & m88100reg::PSR_C), "Cy"); + monitor.Puts(x + 34, y, TA::OnOff(reg.psr & m88100reg::PSR_SFD1), "SFD1"); + monitor.Puts(x + 39, y, TA::OnOff(reg.psr & m88100reg::PSR_MXM), "MXM"); + monitor.Puts(x + 43, y, TA::OnOff(reg.psr & m88100reg::PSR_IND), "IND"); + monitor.Puts(x + 47, y, TA::OnOff(reg.psr & m88100reg::PSR_SFRZ), "SFRZ"); + monitor.Puts(x + 51, y, ")"); + y++; + monitor.Print(x, y, "epsr(cr2):%08x(", reg.epsr); + monitor.Puts(x + 19, y, TA::OnOff(reg.epsr & m88100reg::PSR_SUPER), "S"); + monitor.Puts(x + 21, y, + ((reg.epsr& m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE")); + monitor.Puts(x + 27, y, TA::OnOff(reg.epsr & m88100reg::PSR_SER), "SER"); + monitor.Puts(x + 31, y, TA::OnOff(reg.epsr & m88100reg::PSR_C), "Cy"); + monitor.Puts(x + 34, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFD1), "SFD1"); + monitor.Puts(x + 39, y, TA::OnOff(reg.epsr & m88100reg::PSR_MXM), "MXM"); + monitor.Puts(x + 43, y, TA::OnOff(reg.epsr & m88100reg::PSR_IND), "IND"); + monitor.Puts(x + 47, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFRZ), "SFRZ"); + monitor.Puts(x + 51, y, ")"); - // 制御レジスタ(左下; *IP) + // 制御レジスタ(左中; *IP) x = 0; y = 12; monitor.Print(x, y + 0, "xip:%08x opX:%08x(%c%c)", @@ -102,15 +154,135 @@ MPU88xx0Device::MonitorUpdate() (reg.cr[4 + i] & m88100reg::SIP_E) ? 'E' : '-'); } - // 制御レジスタ(右列) + // 制御レジスタ(右中) x = 55; y = 9; - monitor.Print(x, y++, "ssbr(cr3):%08x", reg.ssbr); - monitor.Print(x, y++, "vbr (cr7):%08x", reg.vbr); for (int i = 0; i < 4; i++) { int rn = 17 + i; - monitor.Print(x, y + i, "sr%d(cr%d):%08x", i, rn, reg.cr[rn]); + monitor.Print(x, y++, "sr%d(cr%d):%08x", i, rn, reg.cr[rn]); } + monitor.Print(x, y++, "ssbr(cr3):%08x", reg.ssbr); + monitor.Print(x, y++, "vbr (cr7):%08x", reg.vbr); + + // MMU レジスタ(下段) + x = 0; + y = 15; + for (int i = 0; i <= 2; i++) { + int dt = 8 + i * 3; + int dd = 9 + i * 3; + int da = 10 + i * 3; + + monitor.Print(0, y, "dmt%d(cr%-2d):%04x", + i, dt, (reg.cr[dt] & 0xffff)); + monitor.Puts(15, y, "(b,s,d,l,rx, s,en ,w,v)"); + monitor.Puts(16, y, (reg.cr[dt] & m88100reg::DM_BO) ? "B" : "-"); + monitor.Puts(18, y, (reg.cr[dt] & m88100reg::DM_DAS) ? "S" : "U"); + monitor.Puts(20, y, (reg.cr[dt] & m88100reg::DM_DOUB1) ? "D" : "-"); + monitor.Puts(22, y, (reg.cr[dt] & m88100reg::DM_LOCK) ? "L" : "-"); + // カンマが自然に見えるようにここだけカンマも含めて前詰めで出力 + monitor.Print(25, y, "%d,", + (reg.cr[dt] & m88100reg::DM_DREG_MASK) >> 7); + monitor.Puts(28, y, (reg.cr[dt] & m88100reg::DM_SIGNED) ? "S" : "-"); + uint32 en = (reg.cr[dt] & m88100reg::DM_EN_MASK) >> 2; + monitor.Puts(30, y, m88100reg::dmt_en_str[en]); + monitor.Puts(35, y, (reg.cr[dt] & m88100reg::DM_WRITE) ? "W" : "-"); + monitor.Puts(37, y, (reg.cr[dt] & m88100reg::DM_VALID) ? "V" : "-"); + + monitor.Print(40, y, "dmd%d(cr%-2d):%08x", i, dd, reg.cr[dd]); + monitor.Print(60, y, "dma%d(cr%2d):%08x", i, da, reg.cr[da]); + y++; + } +} - return true; +// +// {B,P}ATC モニタ +// + +// コンストラクタ +MPU88200ATC::MPU88200ATC(m88200 *cmmu_) +{ + cmmu = cmmu_; + + monitor_size = nnSize(65, 38); +} + +void +MPU88200ATC::MonitorUpdate(TextScreen& monitor) +{ + int x; + int y; + + monitor.Clear(); + + monitor.Print(0, 0, "SAPR %05x'000 TE=%d %c%c%c", + (cmmu->sapr.addr >> 12) & 0xfffff, + cmmu->sapr.enable ? 1 : 0, + (cmmu->sapr.stat & m88200::APR_WT) ? 'T' : '-', + (cmmu->sapr.stat & m88200::APR_G) ? 'G' : '-', + (cmmu->sapr.stat & m88200::APR_CI) ? 'C' : '-'); + + monitor.Print(34, 0, "UAPR %05x'000 TE=%d %c%c%c", + (cmmu->uapr.addr >> 12) & 0xfffff, + cmmu->uapr.enable ? 1 : 0, + (cmmu->uapr.stat & m88200::APR_WT) ? 'T' : '-', + (cmmu->uapr.stat & m88200::APR_G) ? 'G' : '-', + (cmmu->uapr.stat & m88200::APR_CI) ? 'C' : '-'); + + monitor.Puts(0, 1, ""); + monitor.Puts(0, 2, "No. LBA PBA Stat"); + monitor.Puts(34, 2, "No. LBA PBA Stat"); + x = 0; + y = 3; + for (int i = 0; i < 10; i++) { + m88200BATC& b = cmmu->batc[i]; + + if (i == cmmu->batc.size() / 2) { + x = 34; + y = 3; + } + if (i < 8) { + monitor.Print(x, y, " %d:", i); + } else { + monitor.Print(x, y, "(%d)", i); + } + if ((b.lba & 1) == 0) { + monitor.Print(x + 4, y, "%c:%04x'0000 %04x'0000 %c%c%c%c", + (b.lba & m88200::BATC_S) ? 'S' : 'U', + b.lba >> 16, b.pba >> 16, + (b.stat & m88200::DESC_WT) ? 'T' : '-', + (b.stat & m88200::DESC_G) ? 'G' : '-', + (b.stat & m88200::DESC_CI) ? 'C' : '-', + (b.stat & m88200::DESC_WP) ? 'P' : '-'); + } + y++; + } + + monitor.Puts(0, 8, ""); + monitor.Puts(0, 9, "No. LPA PFA Stat"); + monitor.Puts(34, 9, "No. LPA PFA Stat"); + + x = 0; + y = 10; + for (int i = 0; i < cmmu->patc.size(); i++) { + m88200PATC& p = cmmu->patc[i]; + + if (i == cmmu->patc.size() / 2) { + x = 34; + y = 10; + } + + monitor.Print(x, y, "%2d:", i); + if ((p.lpa & 1) == 0) { + monitor.Print(x + 4, y, "%c:%05x'000 %05x'000 %c%c%c%c%c", + (p.lpa & m88200::PATC_S) ? 'S' : 'U', + p.lpa >> 12, p.pfa >> 12, + (p.stat & m88200::DESC_WT) ? 'T' : '-', + (p.stat & m88200::DESC_G) ? 'G' : '-', + (p.stat & m88200::DESC_CI) ? 'C' : '-', + (p.stat & m88200::DESC_WP) ? 'P' : '-', + p.m ? 'M' : '-'); + } + + y++; + } }