--- nono/vm/mfp.cpp 2026/04/29 17:04:29 1.1.1.2 +++ nono/vm/mfp.cpp 2026/04/29 17:04:32 1.1.1.3 @@ -8,7 +8,7 @@ #include "mystring.h" #include "scheduler.h" -MFPDevice *gMFP; +std::unique_ptr gMFP; // コンストラクタ MFPDevice::MFPDevice() @@ -46,23 +46,36 @@ MFPDevice::ResetSoft() // タイマーはすべてストップなのでイベントを削除 for (int ch = 0; ch < countof(event); ch++) { - gScheduler->DelEvent(&event[ch]); + event[ch].Stop(); } // ペンディング割り込みクリア } +// アドレスデコーダ +inline uint64 +MFPDevice::Decoder(uint32 addr) const +{ + // XXX 折り返しは? + addr -= baseaddr; + + // 偶数アドレスはバスエラー + if ((addr & 1) == 0) + return (uint64)-1; + + return addr >> 1; +} + uint64 MFPDevice::Read8(uint32 addr) { uint8 data; - if (addr % 2 == 0) + switch (Decoder(addr)) { + default: return (uint64)-1; - int n = (addr - baseaddr) / 2; - switch (n) { case MFP::GPIP: data = mfp.gpip; break; @@ -135,8 +148,6 @@ MFPDevice::Read8(uint32 addr) case MFP::UDR: data = mfp.udr; break; - default: - return (uint64)-1; } return data; } @@ -150,11 +161,10 @@ MFPDevice::Read16(uint32 addr) uint64 MFPDevice::Write8(uint32 addr, uint32 data) { - if (addr % 2 == 0) + switch (Decoder(addr)) { + default: return (uint64)-1; - int n = (addr - baseaddr) / 2; - switch (n) { case MFP::GPIP: putlog(0, "GPIP <- $%02x 未実装書き込み", data); mfp.gpip = data; @@ -254,8 +264,6 @@ MFPDevice::Write8(uint32 addr, uint32 da putlog(0, "UDR <- $%02x 未実装書き込み", data); mfp.udr = data; break; - default: - return (uint64)-1; } return 0; } @@ -271,11 +279,10 @@ MFPDevice::Peek8(uint32 addr) { uint8 data; - if (addr % 2 == 0) { + switch (Decoder(addr)) { + default: return (uint64)-1; - } - int n = (addr - baseaddr) / 2; - switch (n) { + case MFP::GPIP: data = mfp.gpip; break; @@ -348,9 +355,6 @@ MFPDevice::Peek8(uint32 addr) case MFP::UDR: data = mfp.udr; break; - default: - data = 0xff; - break; } return data; } @@ -484,7 +488,7 @@ MFPDevice::timer_vector[4] = { 13, 8, 5, bool MFPDevice::IsTimerIntrEnable(uint ch) const { - assert(ch < 4); + assertmsg(ch < 4, "ch=%u", ch); __assume(ch < 4); // 割り込みが無効なら false @@ -530,7 +534,7 @@ MFPDevice::SetTCR(int ch, uint32 data) putlog(1, "Timer-%c 停止", ch + 'A'); } mfp.timer_start[ch] = 0; - gScheduler->DelEvent(&event[ch]); + event[ch].Stop(); return; } else { @@ -577,7 +581,7 @@ MFPDevice::SetTCR(int ch, uint32 data) // 他には何もしなくてよい。Timer-B 対策。 if (IsTimerIntrEnable(ch)) { event[ch].time = mfp.initial_tdr[ch] * scale; - gScheduler->AddEvent(&event[ch]); + event[ch].Start(); } putlog(1, "Timer-%c ディレイモード開始(%d.%d x %d usec)", @@ -593,7 +597,7 @@ MFPDevice::SetTCR(int ch, uint32 data) // タイマー開始時刻と減算量が分かっているので読み出しのたびに求める。 // この操作に副作用はないので Peek/Monitor でも使用可能。 uint8 -MFPDevice::GetTDR(int ch) +MFPDevice::GetTDR(int ch) const { uint64 ellapsed; uint64 count; @@ -667,15 +671,20 @@ MFPDevice::SetTDR(int ch, uint32 data) ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch]; // プリスケールカウント時間 (上でいう1カウントの時間) scale = prescale_ns[mfp.tcr[ch]]; - // 1タイマー期間(上でいう50カウントに相当する時間) - period = scale * mfp.initial_tdr[ch]; - // タイマー開始時から次のタイムアップ時刻までの時間 - timer_end = ((ellapsed + period - 1) / period) * period; - // タイムアップ時刻 - timer_end = mfp.timer_start[ch] + timer_end; + if (__predict_true(scale > 0)) { + // 1タイマー期間(上でいう50カウントに相当する時間) + period = scale * mfp.initial_tdr[ch]; + // タイマー開始時から次のタイムアップ時刻までの時間 + timer_end = ((ellapsed + period - 1) / period) * period; + // タイムアップ時刻 + timer_end = mfp.timer_start[ch] + timer_end; + } else { + // タイムアップ時刻 + timer_end = mfp.timer_start[ch]; + } // 現在から次のタイムアップ時刻まで event[ch].time = timer_end - gScheduler->GetVirtTime(); - gScheduler->AddEvent(&event[ch]); + event[ch].Start(); putlog(3, "Timer-%c TDR 更新予約 %d.%09d", ch + 'A', (int)(event[ch].time / (1000 * 1000 * 1000)), @@ -718,10 +727,10 @@ MFPDevice::TimerCallback(int arg) period = prescale_ns[mfp.tcr[ch]] * mfp.initial_tdr[ch]; // イベント再設定 event[ch].time = period; - gScheduler->AddEvent(&event[ch]); + event[ch].Start(); // 割り込みを上げる - gMPU->Interrupt(6, mfp.vr + timer_vector[ch]); + gMPU680x0->Interrupt(6, mfp.vr + timer_vector[ch]); } if (mfp.initial_tdr[ch] != prevtdr) { @@ -775,7 +784,7 @@ MFPDevice::SetGPIP(int num, bool val) // 1 0 1 1 // 1 1 0 0 // 1 1 1 0 - if ((old != val) & (aer == val)) { + if ((old != val) && (aer == val)) { // XXX ここで割り込みを上げる }