--- nono/m88xx0/m88100core.cpp 2026/04/29 17:05:07 1.1.1.11 +++ nono/m88xx0/m88100core.cpp 2026/04/29 17:05:11 1.1.1.12 @@ -88,55 +88,71 @@ m88kcpu::Reset() fetch(); + // リセット例外はここまで。 + // ここからは最初の命令のプリフェッチ + Prefetch(); + return used_cycle - cycle_start; } +// プリフェッチステージ(?)。 +// 命令サイクルは、自然に書けば、 +// (1) パイプラインをシフトし、FIP の指すところをフェッチ。 +// (2) デバッガはここに入れたい。 +// (3) XIP(opX) を解釈、実行。 +// の繰り返しになるが、デバッガは Exec() から戻ったところでスケジューラから +// 呼び出される構造のため、順序をずらして 1回の Exec() では (3)->(1) を実行 +// してからスケジューラに戻って (2) を実行する、の順にする。 +// そのため、リセット例外では1回プリフェッチを実行しておく必要がある。 +inline void +m88kcpu::Prefetch() +{ + // shift pipeline + opX = opF; + xip = nip; + + // prefetch next inst + fetch(); +} + // 1命令実行する。 // 戻り値は消費したサイクル数。 int m88kcpu::Exec() { uint64 cycle_start = used_cycle; + uint32 op12; - { - // shift pipeline - opX = opF; - xip = nip; - - // prefetch next inst - fetch(); + // この時点で実行しようとする命令が opX に入っている - // この時点で実行しようとする命令が opX に入っている - - if (OpIsBusErr(opX)) { - // プリフェッチしていた命令がバスエラー - Exception(M88K_EXCEP_INST); - goto exit; - } - - uint32 op12 = op32_to_12(opX); + if (OpIsBusErr(opX)) { + // プリフェッチしていた命令がバスエラー + Exception(M88K_EXCEP_INST); + goto exit; + } - switch (op12) { + op12 = op32_to_12(opX); + switch (op12) { #include "m88100switch.inc" - default: - OP_FUNC(illegal); - break; - } - - if (intr_pending && IsIntrEnable()) { - // 割り込み処理要求が来ていて、 - // 直前の命令が割り込みを禁止していなければ割り込み - // XXX 実際は違う気がする - cpulog(4, "INTR take"); - ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR); - goto exit; - } - - used_cycle++; + default: + OP_FUNC(illegal); + break; + } + if (intr_pending && IsIntrEnable()) { + // 割り込み処理要求が来ていて、 + // 直前の命令が割り込みを禁止していなければ割り込み + // XXX 実際は違う気がする + cpulog(4, "INTR take"); + ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR); + goto exit; } + used_cycle++; + exit: + Prefetch(); + return used_cycle - cycle_start; }