--- nono/vm/mpu.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/mpu.h 2026/04/29 17:05:59 1.1.1.18 @@ -1,90 +1,121 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// MPU 共通部 // #pragma once #include "device.h" -#include "m68030.h" +#include "message.h" +#include "event.h" +#include + +class Debugger; +class MainbusDevice; +class Syncer; +// 全 MPU の共通部 class MPUDevice : public Device { - typedef Device inherited; + using inherited = Device; public: - MPUDevice(uint32); - virtual ~MPUDevice(); + explicit MPUDevice(uint objid_); + ~MPUDevice() override; - virtual bool Init(); - virtual void ResetHard(); + bool Init() override; + void ResetHard(bool poweron) override; + void PowerOff() override; - virtual bool MonitorUpdate(); + // 現在実行中の命令の PC を取得 + virtual uint32 GetPPC() const = 0; - // MPU を request サイクル分実行する - uint32 Run(uint64 request); + // 最後に発生した例外ベクタを取得し、同時にクリアする + int32 GetAndResetLastVector(); - // 現在の PPC を取得 - uint32 GetPPC() const { return RegPPC; } + // exec イベントの回数 + uint64 GetExecCount() const { return exec_event->count; } - // 割り込み発生を MPU に通知 (オートベクタ) - void Interrupt(int level); + protected: + // 1命令実行イベント + Event *exec_event {}; - // 割り込み発生を MPU に通知 (ベクタ) - void Interrupt(int level, int vector); + Debugger *debugger {}; - // MPU の処理をこの命令で中断させる。 - // スケジューラのイベントリストに追加が発生した時に VM 側から - // MPU へ処理の中断を指示する。 - void Release() { cpu->atomic_reqflag |= CPU_REQ_RELEASE; } + // 最後に発生した例外ベクタ。起きてなければ -1。 + int32 last_vector {}; +}; - // 基準サイクル数を取得 - uint64 total_cycle() const { return cpu->total_cycle; } +// メイン MPU (680x0/88xxx0) 共通部 +class MainMPUDevice : public MPUDevice +{ + using inherited = MPUDevice; + protected: + // CPU の実行状態 + static const uint32 CPU_STATE_NORMAL = 0; + static const uint32 CPU_STATE_STOP = 1; + static const uint32 CPU_STATE_HALT = 2; - // A-Line, F-Line 命令エミュレーションのコールバックを指定する。 - // (Human68k エミュレーションで使用) - void SetALineCallback(bool (*callback)(m68kcpu*, void*), void *arg); - void SetFLineCallback(bool (*callback)(m68kcpu*, void*), void *arg); + public: + MainMPUDevice(); + ~MainMPUDevice() override; - // FPU を持っているか - bool HaveFPU() const { - return cpu->has_fpu; - } + bool Init() override; - // CPU コアを取得 (主にデバッグ用途) - m68kcpu *GetCPU() const { - return cpu; - } + // 現在の VBR を取得 + virtual uint32 GetVBR() const = 0; - private: - m68kcpu *cpu = NULL; -}; + // CPU の実行状態 (uint32) を返す。 + uint32 GetState() const noexcept { return cpu_state; } -// ATC モニタ -class MPUATC : public Object -{ - public: - MPUATC(m68kcpu *cpu); - virtual ~MPUATC() { } + // MPU 名を取得する。("MC68030" みたいなやつ、ログ名とは別) + virtual const char *GetMPUName() const = 0; - virtual bool MonitorUpdate(); + // MPU クロック [kHz] を取得する。 + uint GetClockSpeed() const { return clock_khz; } - private: - m68kcpu *cpu = NULL; -}; + // MPU クロック [tsec] を取得する。 + uint64 GetClock_tsec() const { return clock_tsec; } -// ブランチ履歴モニタ -class MPUBrHist : public Object -{ - public: - MPUBrHist(m68kcpu *cpu); - virtual ~MPUBrHist() { } + // 割り込み発生を MPU に通知 + virtual void Interrupt(int level) = 0; + + // デバイスが CI (キャッシュ禁止) をセットする。 + virtual void SetCI() = 0; + + // 例外カウンタ + std::vector excep_counter {}; + + protected: + void TraceMessage(MessageID, uint32); + virtual void SetTrace(bool enable) = 0; + + // CPU の状態 + void ChangeState(uint32 new_state); + + // CPU の実行状態 + uint32 cpu_state {}; + + uint clock_khz {}; // MPU クロック [kHz] + uint64 clock_tsec {}; // MPU クロック [tsec] + + bool resetting {}; // リセット処理中フラグ + + // キャッシュを強制的に無効にする。テスト用。 + bool force_disable_dcache {}; + bool force_disable_icache {}; - virtual bool MonitorUpdate(); + MainbusDevice *mainbus {}; + Syncer *syncer {}; - private: - m68kcpu *cpu = NULL; + // Round Mode (モニタ表示用) + static const char * const rmstr[4]; }; -extern MPUDevice *gMPU; -extern MPUATC *gMPUATC; -extern MPUBrHist *gMPUBrHist; +inline MainMPUDevice *GetMPUDevice() { + return Object::GetObject(OBJ_MPU); +}