--- nono/vm/mpu680x0.cpp 2026/04/29 17:04:32 1.1 +++ nono/vm/mpu680x0.cpp 2026/04/29 17:04:42 1.1.1.4 @@ -1,19 +1,19 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // // MPU (m680x0) #include "mpu680x0.h" -#include "m68030excep.h" #include "config.h" +#include "m68030excep.h" #include "mainapp.h" #include "vm.h" #include std::unique_ptr gMPUATC; -std::unique_ptr gMPUBrHist; // コンストラクタ // @@ -27,13 +27,15 @@ std::unique_ptr gMPUBrHist; // できる。すごい楽。 MPU680x0Device::MPU680x0Device(uint32 reset_vector) { - monitor.Init(79, 16); + monitor_size = nnSize(79, 16); cpu = m68030_init(reset_vector); + // リセット例外イベントコールバック設定 + reset_event.func = (DeviceCallback_t)&MPU680x0Device::ResetCallback; + // モニタ用の別オブジェクト gMPUATC.reset(new MPUATC(cpu)); - gMPUBrHist.reset(new MPUBrHist(cpu)); } // デストラクタ @@ -45,12 +47,12 @@ bool MPU680x0Device::Init() { // FPU (6888x) - if (gMainApp.GetVMType() == VMTYPE_LUNA) { + if (gMainApp.GetVMType() == VMTYPE_LUNA1) { // LUNA は 68881 固定 (設定は見ない) cpu->has_fpu = 1; } else { // X68k は設定による - const ConfigItem& item = gConfig->Get("mpu-has-fpu"); + const ConfigItem& item = gConfig->Find("mpu-has-fpu"); cpu->has_fpu = item.AsInt(); if (cpu->has_fpu < 0 || cpu->has_fpu > 2) { item.Err(); @@ -61,10 +63,9 @@ MPU680x0Device::Init() return true; } -// リセット -// (MPU が動くのはこの後 Scheduler::Run() を発行した後) +// リセット例外イベントコールバック void -MPU680x0Device::ResetHard() +MPU680x0Device::ResetCallback(Event& ev) { m68030_exception_reset(cpu); } @@ -83,7 +84,7 @@ MPU680x0Device::Run(uint64 request) // 割り込み発生を MPU に通知 (オートベクタ) void -MPU680x0Device::Interrupt(int level) +MPU680x0Device::Interrupt(Object *src, int level) { int vector = M68K_EXCEP_LEVEL_BASE + level; m68030_interrupt(cpu, level, vector); @@ -91,7 +92,7 @@ MPU680x0Device::Interrupt(int level) // 割り込み発生を MPU に通知 (ベクタ) void -MPU680x0Device::Interrupt(int level, int vector) +MPU680x0Device::Interrupt(Object *src, int level, int vector) { m68030_interrupt(cpu, level, vector); } @@ -112,9 +113,17 @@ MPU680x0Device::SetFLineCallback(bool (* cpu->fline_arg = arg; } +// ダブルバスフォールトのコールバックを指定。 +void +MPU680x0Device::SetHaltCallback(void (*callback)(void *), void *arg) +{ + cpu->halt_callback = callback; + cpu->halt_arg = arg; +} + // モニター更新 (レジスタウィンドウ) -bool -MPU680x0Device::MonitorUpdate() +void +MPU680x0Device::MonitorUpdate(TextScreen& monitor) { m68kreg reg; uint32 ppc; @@ -180,17 +189,17 @@ MPU680x0Device::MonitorUpdate() // XXX どこに置くのがいいか if (reg.state == 0) { - monitor.Print(25, 4, "State: Running"); + monitor.Puts(25, 4, "State: Running"); } else if (reg.state == CPU_REQ_STOP) { - monitor.Print(25, 4, "State: STOP instruction"); + monitor.Puts(25, 4, "State: STOP instruction"); } else if (reg.state == CPU_REQ_HALT) { - monitor.Print(25, 4, "State: Double Bus Fault"); + monitor.Puts(25, 4, TA::On, "State: Double Bus Fault"); } // MMU x = 0; y = 4; - monitor.Print(x, y++, ""); + monitor.Puts(x, y++, ""); monitor.Print(x, y, "SRP:%08x_%08x", reg.srp.h, reg.srp.l); monitor.Print(x, y + 1, "CRP:%08x_%08x", reg.crp.h, reg.crp.l); x += 23; @@ -222,7 +231,7 @@ MPU680x0Device::MonitorUpdate() // FPU x = 0; y = 7; - monitor.Print(x, y++, ""); + monitor.Puts(x, y++, ""); for (int i = 0; i < 8; i++) { monitor.Print(x, y + i, "FP%d:%04x_%08x_%08x (%-20s)", i, @@ -290,8 +299,6 @@ MPU680x0Device::MonitorUpdate() // FPIAR monitor.Print(x, y++, "FPIAR:%08x", reg.fpframe.fpf_fpiar); - - return true; } // CPU 側からのコールバック。RESET 命令ハンドラ @@ -304,18 +311,18 @@ m68030_reset_inst(m68kcpu *cpu) // // ATC モニタ // -MPUATC::MPUATC(m68kcpu *arg) +MPUATC::MPUATC(m68kcpu *cpu_) { - cpu = arg; + cpu = cpu_; #if !defined(ATC_SINGLE) - monitor.Init(131, m68030ATCTable::LINES + 3); + monitor_size = nnSize(131, m68030ATCTable::LINES + 3); #else - monitor.Init(31, 24); + monitor_size = nnSize(31, 24); #endif } -bool -MPUATC::MonitorUpdate() +void +MPUATC::MonitorUpdate(TextScreen& monitor) { m68030ATCTable *table; #if !defined(ATC_SINGLE) @@ -345,7 +352,7 @@ MPUATC::MonitorUpdate() table = &cpu->atc.tables[fc]; monitor.Print(x, 0, "FC=%d %s", fc, name); - monitor.Print(x, 1, "LAddr PAddr Flag Hit%% Age"); + monitor.Puts(x, 1, "LAddr PAddr Flag Hit% Age"); // 先に統計用の母数を計算 uint64 total = 0; for (i = 0; i < countof(table->hit); i++) { @@ -356,7 +363,7 @@ MPUATC::MonitorUpdate() // エントリ表示 for (i = 0; i < countof(table->line); i++) { m68030ATCLine& a = table->line[i]; - int attr; + TA attr; if (a.IsInvalid()) { attr = TA::Disable; } else if (table->head == &a) { @@ -373,13 +380,13 @@ MPUATC::MonitorUpdate() a.IsModified() ? 'M' : '-'); } // ヘッドのヒット率 - monitor.Print(x + 0, i + 2, "head"); + monitor.Puts(x + 0, i + 2, "head"); r = (double)table->hit_head * 100 / total; if (!isnan(r)) { monitor.Print(x + 5, i + 2, "%4.1f%%", r); } // 配列のヒット率とミス率 - monitor.Print(x + 17, i + 2, "miss"); + monitor.Puts(x + 17, i + 2, "miss"); for (i = 0; i < countof(table->hit); i++) { r = (double)(table->hit[i] * 100) / total; if (!isnan(r)) { @@ -402,7 +409,7 @@ MPUATC::MonitorUpdate() table = &cpu->atc.tables[0]; monitor.Clear(); - monitor.Print(0, 0, "No. FC LAddr PAddr Flag"); + monitor.Puts(0, 0, "No. FC LAddr PAddr Flag"); for (a = table->head, i = 0; a; a = a->next, i++) { monitor.Print(0, i + 1, "%02d:", i); if (!a->IsInvalid()) { @@ -423,47 +430,4 @@ MPUATC::MonitorUpdate() } } #endif - return true; -} - -// -// ブランチ履歴モニタ -// -MPUBrHist::MPUBrHist(m68kcpu *arg) -{ - cpu = arg; - monitor.Init(70, 16); -} - -bool -MPUBrHist::MonitorUpdate() -{ - int i; - uint8 t; - - // 0 1 2 3 4 5 6 - // 0123456789012345678901234567890123456789012345678901234567890123456789 - // 01 $01234567->$01234567 x123456789 16 $01234567->$01234567 x123456789 - - monitor.Clear(); - - // top は現在の位置。 - // brhist[] は古い順に書き込まれるが、表示は新しい順にしたい。 - // ブランチ履歴は書き込み最適化のため256エントリあるが、そんなに - // 奥のほうが気になることはないだろう。 - t = cpu->brhist_top; - for (i = 0; i < 32; i++) { - m68kbrhist& h = cpu->brhist[t--]; - int x = (i / 16) * 36; - int y = i % 16; - if (h.count == 0) { - continue; - } - monitor.Print(x, y, "%02d:$%08x->$%08x", i, - h.from, h.to); - if (h.count > 1) { - monitor.Print(x + 24, y, "x%9u", h.count); - } - } - return true; }