--- nono/vm/mpu680x0.cpp 2026/04/29 17:05:32 1.1.1.18 +++ nono/vm/mpu680x0.cpp 2026/04/29 17:05:41 1.1.1.20 @@ -8,6 +8,18 @@ // MPU (MC68030/MC68040) // +// MPU/FPU 種別について: +// +// 構造上やむをえないが MPU が 68030 なら FPU は fpu-type で指定し、 +// MPU が 68040/68LC040 なら mpu-type で MPU/FPU を指定する。 +// +// mpu-type fpu-type +// -------- -------- +// 68030 none : 68030、FPU なし +// 68030 68881 : 68030 + 68881 +// 68LC040 - : 68040 (FPU なし) +// 68040 - : 68040 (FPU あり) + #include "mpu680x0.h" #include "config.h" #include "debugger.h" @@ -18,12 +30,9 @@ #include "mainapp.h" #include "mainbus.h" #include "scheduler.h" -#include "syncer.h" #include "uimessage.h" #include "vectortable.h" -static Syncer *gSyncer; - // ブートストラップ。設定に応じてインスタンスを生成して返す。 // ここではとりあえず 68040 かそれ以外なら 68030 を生成しておき、 // Init() でもう一度 (機種情報も含めて) チェックする。 @@ -36,8 +45,8 @@ NewMPU680x0Device() std::string mpu_type = item.AsString(); // 設定に応じて継承側のクラスを作成する。 - // この段階では 68040 かそれ以外だけ判断する。 - if (mpu_type == "68040") { + // この段階では知らないものは一旦 68030 にしておく。 + if (mpu_type == "68040" || strcasecmp(mpu_type.c_str(), "68LC040") == 0) { return new MPU68040Device(); } else { return new MPU68030Device(); @@ -79,19 +88,28 @@ MPU680x0Device::Init() } // なる早で、もう一度 MPU 設定を読んで判定。そのついでに FPU も判定。 - const ConfigItem& mputype_item = gConfig->Find("mpu-type"); - std::string mputype = mputype_item.AsString(); - // mpu-type の設定値が不正な場合でも (コンストラクト時点ではまだエラーを + // "mpu-type" の設定値が不正な場合でも (コンストラクト時点ではまだエラーを // 報告できない構造なので) 一旦 MPU68030Device インスタンスとしてここに // 来る。なのでここで改めてチェックしてエラー報告する必要がある。 // mpu_type (メンバ変数) 自体はすでにセットされている。 - if (mputype != "68030" && mputype != "68040") { + const ConfigItem& mputype_item = gConfig->Find("mpu-type"); + std::string mputype = mputype_item.AsString(); + if (mputype == "68030") { + // FPU はこのすぐ次で機種ごとに選ぶ。 + } else if (mputype == "68040") { + fpu_type = m680x0FPUType::M68040; + } else if (strcasecmp(mputype.c_str(), "68LC040") == 0) { + fpu_type = m680x0FPUType::M68LC040; + // 名前も再設定? + mpu_name = "MC68LC040"; + SetName("MPU(68LC040)"); + } else { mputype_item.Err(); return false; } // 機種ごとに MPU/FPU のサポート状況が違う。 - // fpu_type はここでセットする。 + // 68030 なら fpu_type はここでセットする。 switch (gMainApp.GetVMType()) { case VMType::LUNA1: case VMType::NEWS: @@ -122,8 +140,7 @@ MPU680x0Device::Init() return false; } } else { - // 68040 なら FPU は現状 !LC040 固定。 - fpu_type = m680x0FPUType::M68040; + // 68040 なら FPU はすぐ上で設定済み。 } break; @@ -132,11 +149,8 @@ MPU680x0Device::Init() break; } - debugger = GetDebugger(); interruptdev = GetInterruptDevice(); vectortable = GetVectorTable(); - // static 関数から参照するため。うーん…。 - gSyncer = syncer; // 割り込みイベントコールバック設定。 // @@ -367,23 +381,6 @@ MPU680x0Device::MakeNextFull() exec_event.func = exec_full; } -void -MPU680x0Device::ChangeState(uint32 new_state) -{ - // new_mode (CPU_STATE_*) と - // RequestCPUMode() の引数 Syncer::SCHED_CPU_* は - // 実は同じ値なのでそのまま渡してよいことにする。 - static_assert(CPU_STATE_NORMAL == Syncer::SCHED_CPU_NORMAL, ""); - static_assert(CPU_STATE_STOP == Syncer::SCHED_CPU_STOP, ""); - static_assert(CPU_STATE_HALT == Syncer::SCHED_CPU_HALT, ""); - - if (cpu_state != new_state) { - cpu_state = new_state; - // スケジューラに通知 - syncer->RequestCPUMode(cpu_state); - } -} - // A-Line 命令エミュレーションのコールバックを指定。 void MPU680x0Device::SetALineCallback(bool (*callback)(MPU680x0Device *, void*), @@ -958,6 +955,8 @@ MPU68040Device::MPU68040Device() mpu_name = "MC68040"; SetName("MPU(68040)"); + cycle_table = cycle_table_040; + mmu_itt[0].reset(new m68040TT("ITT0", ®.itt[0])); mmu_itt[1].reset(new m68040TT("ITT1", ®.itt[1])); mmu_dtt[0].reset(new m68040TT("DTT0", ®.dtt[0])); @@ -973,7 +972,7 @@ MPU68040Device::MPU68040Device() // ATC モニター (Inst/Data) atc_monitor = gMonitorManager->Regist(ID_MONITOR_MPUATC, this); atc_monitor->func = ToMonitorCallback(&MPU68040Device::MonitorUpdateATC); - atc_monitor->SetSize(121, 34); + atc_monitor->SetSize(125, 34); } // デストラクタ