--- nono/m88xx0/m88100core.cpp 2026/04/29 17:04:44 1.1.1.5 +++ nono/m88xx0/m88100core.cpp 2026/04/29 17:04:49 1.1.1.7 @@ -9,23 +9,26 @@ #include "debugger.h" #include "cvprompt.h" #include "mpu.h" +#include "scheduler.h" #define OP_DEF(name) void __CONCAT(m88kcpu::op_,name)() #define OP_FUNC(name) __CONCAT(op_,name)() #include "m88100ops.cpp" +// 文字列を作る前にレベルを評価するためマクロ +#define cpulog(lv, fmt...) do { \ + if (__predict_false(gMPU->loglevel >= (lv))) { \ + gMPU->putlogn(fmt); \ + } \ +} while (0) + // リセット例外のようなもの? void m88kcpu::Reset() { - const uint32 Undefined = 0xcccccccc; - // 内部の割り込み状態をクリア intr_pending = 0; - - // 履歴を初期化。リセット前の履歴いらんよな? - exhist.Clear(); - brhist.Clear(); + atomic_reqflag &= ~(CPU_REQ_RESET | CPU_REQ_INTR | CPU_REQ_STOP); // Table 6-8 (p6-47) psr = 0x800003ff; @@ -39,42 +42,25 @@ m88kcpu::Reset() SetPSR(); - epsr = Undefined; - // scoreboard: cleared - ssbr = Undefined; - // 実際には m88k MPU はリセット直後は 0 番地から実行を開始するので、 // 大抵の場合システムでリセット直後は 0 番地付近に ROM を見せるように // してあるのだと思うが、ここではその代わりに ROM のアドレスを指定して、 // 直接そこから実行を開始することにする。 fip = reset_vector; + + // レジスタのうち明記されてるものをクリア。 + // 不定と明記されてるものはリセットでは触らないでおく。 + // scoreboard: cleared nip = 0; xip = 0; - sfip = Undefined; - snip = Undefined; - sxip = Undefined; - vbr = 0; - // DMTx は bit0(Valid) をクリア。他は不定。 - dmt0 &= ~DM_VALID; - dmt1 &= ~DM_VALID; - dmt2 &= ~DM_VALID; - dma0 = Undefined; - dma1 = Undefined; - dma2 = Undefined; - dmd0 = Undefined; - dmd1 = Undefined; - dmd2 = Undefined; - for (int i = 1; i < 32; i++) { - r[i] = Undefined; - } - fpecr = 0; - for (int i = 1; i < 9; i++) { - fcr[i] = Undefined; - } fpcr = 0; fpsr = 0; + // DMTx は bit0(Valid) をクリア。他は不定 + dmt0 &= ~DM_VALID; + dmt1 &= ~DM_VALID; + dmt2 &= ~DM_VALID; cmmu[0].Reset(); cmmu[1].Reset(); @@ -94,10 +80,7 @@ m88kcpu::Reset() } // 仮想時間 delta [nsec] だけ CPU を実行する。実際には大抵行き過ぎる。 -// 戻り値はフラグ。 -// -// 戻る時に仮想時刻を確定させなくても構わない。スケジューラはこれを呼び出した -// 後に必然的に仮想時刻を取得することになるため、そこで確定させられる。 +// 戻り値は CPU 状態 (Scheduler::SCHED_CPU_*)。 uint32 m88kcpu::Run(uint32 delta) { @@ -118,7 +101,7 @@ m88kcpu::Run(uint32 delta) } else { // STOP 継続として戻る。 used_cycle = goal_cycle; - return atomic_reqflag; + goto exit; } } @@ -137,7 +120,6 @@ m88kcpu::Run(uint32 delta) if ((atomic_reqflag & CPU_REQ_RESET)) { // リセット例外。 - atomic_reqflag &= ~CPU_REQ_RESET; Reset(); // XIP がリセットベクタを指すためにはもう一回フェッチが必要 // なので、ここは continue が必要。 @@ -210,7 +192,7 @@ m88kcpu::Run(uint32 delta) // 割り込み処理要求が来ていて、直前の命令が割り込みを禁止していなければ割り込み // XXX 実際は違う気がする is_intr = false; - gMPU->putlog(4, "INTR take"); + cpulog(4, "INTR take"); ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR); continue; } @@ -219,35 +201,24 @@ m88kcpu::Run(uint32 delta) if ((atomic_reqflag & CPU_REQ_STOP)) { // STOP 状態は、残りサイクルを消費したことにして戻る - gMPU->putlog(2, "STOP 状態検出"); - used_cycle = goal_cycle; - is_release = true; + cpulog(2, "STOP 状態検出"); + if (used_cycle < goal_cycle) { + used_cycle = goal_cycle; + } } if (used_cycle >= goal_cycle) break; } - return atomic_reqflag; -} - -// 仕掛中のサイクルを仮想時刻に反映させる -void -m88kcpu::UpdateVTime() -{ - goal_cycle -= used_cycle; + exit: total_vtime += Cycle2Vtime(used_cycle); used_cycle = 0; -} -// 仮想時刻 [nsec] を取得する -uint64 -m88kcpu::GetVTime() -{ - if (used_cycle != 0) { - UpdateVTime(); - } - return total_vtime; + // HALT 状態がないので NORMAL か STOP かだけでいい + return (atomic_reqflag & CPU_REQ_STOP) + ? Scheduler::SCHED_CPU_STOP + : Scheduler::SCHED_CPU_NORMAL; } // この命令後に実行を中断して VM に戻る @@ -308,18 +279,18 @@ m88kcpu::ExceptionCore(int vec, Exceptio if (psr & PSR_SFRZ) { if (cause != ExceptionKind::TRAP) { - gMPU->putlog(2, "SFRZ Error Exception"); + cpulog(2, "SFRZ Error Exception"); vec = M88K_EXCEP_ERROR; cause = ExceptionKind::ERROR; } } else { - gMPU->putlog(2, "Exception %x", vec); + cpulog(2, "Exception %x", vec); if (vec != 1) { - gMPU->putlog(1, "Exception %x x=%x n=%x f=%x", vec, xip, nip, fip); + cpulog(1, "Exception %x x=%x n=%x f=%x", vec, xip, nip, fip); } sxip = xip; snip = nip; - sfip = fip; + sfip = fip; sxip |= SIP_V; snip |= SIP_V; @@ -424,7 +395,7 @@ m88kcpu::ReadDataException32(uint32 addr ; dmt1 &= ~DM_VALID; dmt2 &= ~DM_VALID; - gMPU->putlog(1, "ReadDAE xip=%x addr=%x", xip, addr); + cpulog(1, "ReadDAE xip=%x addr=%x", xip, addr); ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA); } @@ -455,7 +426,7 @@ m88kcpu::ReadDataException64(uint32 addr dmt0 &= ~DM_VALID; } - gMPU->putlog(1, "ReadDAE64 xip=%x addr=%x", xip, addr); + cpulog(1, "ReadDAE64 xip=%x addr=%x", xip, addr); ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA); } @@ -476,7 +447,7 @@ m88kcpu::WriteDataException32(uint32 add dmt1 &= ~DM_VALID; dmt2 &= ~DM_VALID; - gMPU->putlog(1, "WriteDAE xip=%x addr=%x", xip, addr); + cpulog(1, "WriteDAE xip=%x addr=%x", xip, addr); ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA); } @@ -511,7 +482,7 @@ m88kcpu::WriteDataException64(uint32 add dmt0 &= ~DM_VALID; } - gMPU->putlog(1, "WriteDAE64 xip=%x addr=%x", xip, addr); + cpulog(1, "WriteDAE64 xip=%x addr=%x", xip, addr); ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA); } @@ -551,7 +522,7 @@ m88kcpu::XmemDataException(uint32 addr, dmt0 &= ~DM_VALID; } - gMPU->putlog(1, "xmemDAE xip=%x addr=%x", xip, addr); + cpulog(1, "xmemDAE xip=%x addr=%x", xip, addr); ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA); } @@ -586,5 +557,5 @@ m88kcpu::fpu_unimpl() OP_DEF(illegal) { // 本来は不当命令例外? - gMPU->putlog(0, "Illegal instruction %08x", (uint32)opX); + cpulog(0, "Illegal instruction %08x", (uint32)opX); }