--- nono/m680x0/m68030.h 2026/04/29 17:04:37 1.1.1.4 +++ nono/m680x0/m68030.h 2026/04/29 17:05:08 1.1.1.11 @@ -11,36 +11,30 @@ // #include "branchhistory.h" -#include -#include -#include __BEGIN_DECLS #include "fpu_emulate.h" __END_DECLS class m68kcpu; +class MPU680x0Device; // 外部ループフラグ // これらのフラグがいずれも立っていない間、CPU 実行は内側のディスパッチ // ループを周り、どれかでも立てばディスパッチループを抜けてフラグを処理 // してから再びディスパッチループに戻る。 // それぞれ独立しているためビットを立てる際は代入ではなく OR すること。 -#define CPU_REQ_STOP (0x00000001) // ストップ状態 -#define CPU_REQ_HALT (0x00000002) // ホールト状態 -#define CPU_REQ_TRACE (0x00000004) // デバッガ有効 -#define CPU_REQ_PROMPT (0x00000008) // デバッガプロンプト -#define CPU_REQ_RELEASE (0x00000010) // 命令後に CPU 実行中断 #define CPU_REQ_INTR (0x00000020) // 命令後に割り込みチェックが必要 -#define M68K_SR_T (0xc000) -#define M68K_SR_S (0x2000) -#define M68K_SR_M (0x1000) -#define M68K_CCR_X (0x0010) -#define M68K_CCR_N (0x0008) -#define M68K_CCR_Z (0x0004) -#define M68K_CCR_V (0x0002) -#define M68K_CCR_C (0x0001) +#define M68K_SR_T (0xc000) +#define M68K_SR_S (0x2000) +#define M68K_SR_M (0x1000) +#define M68K_SR_IMASK (0x0700) +#define M68K_CCR_X (0x0010) +#define M68K_CCR_N (0x0008) +#define M68K_CCR_Z (0x0004) +#define M68K_CCR_V (0x0002) +#define M68K_CCR_C (0x0001) // SSW #define SSW_SIZE(x) (((x) & 0x03) << 4) @@ -71,6 +65,18 @@ class m68kcpu; #define FC_SD (FC_SUPER | FC_DATA) #define FC_SP (FC_SUPER | FC_PROG) +#define M68K_CACR_EI (0x0001) +#define M68K_CACR_FI (0x0002) +#define M68K_CACR_CEI (0x0004) +#define M68K_CACR_CI (0x0008) +#define M68K_CACR_IBE (0x0010) +#define M68K_CACR_ED (0x0100) +#define M68K_CACR_FD (0x0200) +#define M68K_CACR_CED (0x0400) +#define M68K_CACR_CD (0x0800) +#define M68K_CACR_DBE (0x1000) +#define M68K_CACR_WA (0x2000) + #define M68K_FPCR_MASK (0x0000fff0) #define M68K_FPSR_MASK (0x0ffffff8) @@ -87,11 +93,16 @@ struct m68kreg { m68030ccr ccr; bool s; // SR の S ビット bool m; // SR の M ビット - int intr_level; // SR の割り込みレベル (0-7) + int intr_mask; // SR の割り込みマスク (0-7) - // 現在の SP は常に da[15]。現在有効でない残り2つの SP をここに保存。 - // 例えばユーザ状態なら da[15] が USP、isp/msp は ISP/MSP を示し、 - // usp の内容は無効。 + // 現在の SP は常に da[15]。da[15] が示しているときは対応する変数の + // ほうは更新されないため無効。 + // ユーザ状態なら da[15] が USP を示し usp は無効、 + // isp, msp は ISP, MSP を示して有効。 + // スーパバイザ状態で SR_M なら da[15] が MSP を示し msp は無効、 + // isp, usp は ISP, USP を示して有効。 + // スーパバイザ状態で !SR_M なら da[15] が ISP を示し isp は無効、 + // msp, usp は MSP, USP を示して有効。 uint32 usp; uint32 isp; uint32 msp; @@ -111,16 +122,10 @@ struct m68kreg { struct fpframe fpframe; - // CPU の実行状態 - // 0 .. 通常状態 - // CPU_REQ_STOP .. STOP 状態 - // CPU_REQ_HALT .. HALT 状態 - uint32 state; - public: // SR の上位8ビット部分のみを返す uint16 sr_h() { - return (s ? M68K_SR_S : 0) | (m ? M68K_SR_M : 0) | (intr_level << 8); + return (s ? M68K_SR_S : 0) | (m ? M68K_SR_M : 0) | (intr_mask << 8); } }; @@ -161,17 +166,23 @@ class m68kcpu final { public: m68kreg reg {}; - uint32 ppc = 0; // 現在実行中の命令の先頭アドレス - uint16 ir = 0; - uint16 ir2 = 0; + uint32 ppc {}; // 現在実行中の命令の先頭アドレス + uint16 ir {}; + uint16 ir2 {}; uint32 save_pd[8] {}; // -(An) を保存 uint32 save_pi[8] {}; // (An)+ を保存 - uint8 flag_pd = 0; // -(An) のどのレジスタを保存したか - uint8 flag_pi = 0; // (An)+ のどのレジスタを保存したか + uint8 flag_pd {}; // -(An) のどのレジスタを保存したか + uint8 flag_pi {}; // (An)+ のどのレジスタを保存したか + + // CPU の実行状態 + static const uint32 CPU_STATE_NORMAL = 0; + static const uint32 CPU_STATE_STOP = 1; + static const uint32 CPU_STATE_HALT = 2; + uint32 state {}; // MMU 状態 - bool mmu_enable = false; + bool mmu_enable {}; // SRP void SetSRP(uint32, uint32); uint64 GetSRP() const { return reg.srp.q; } @@ -192,85 +203,54 @@ class m68kcpu final { void SetMMUSR(uint16); uint16 GetMMUSR() const { return reg.mmusr; } // MMU work - m68030TT mmu_tt[2]; + m68030TT mmu_tt[2] {}; uint8 mmu_tt_quick[256] {}; - m68030TC mmu_tc; + m68030TC mmu_tc {}; m68030ATC atc {this}; private: void mmu_enable_changed(); public: - int has_fpu = 0; // 0:FPUなし、1:68881、2:68882(?) - bool fpu_dirty = false; + int has_fpu {}; // 0:FPUなし、1:68881、2:68882(?) + bool fpu_dirty {}; struct fpemu fe {}; - std::atomic atomic_reqflag {}; // 外部ループ & リクエストフラグ + // 現在の外部割り込みレベル + int intr_level {}; + + // 電源オンからの累積消費サイクル + uint64 used_cycle {}; - // 割り込みペンディング - // intr_vector[1] がレベル1割り込みのペンディング中ベクタ - // : - // intr_vector[7] がレベル7割り込みのペンディング中ベクタ - // - // [0] を intr_pending (割り込みペンディング) として使う。 - // ペンディングになっているレベルのビットを立てる。 - // - // bit 7 6 5 4 3 2 1 0 - // Level 0 1 2 3 4 5 6 7 - // - // intrmtx 取ってからアクセスすること。 - uint8 intr_vector[8] {}; -#define intr_pending intr_vector[0] - - // 割り込みマスク - // 現在の割り込みレベルで割り込みを受け付けるレベルのビットを立てる - // I=0 だと割り込みレベル 1..7 を受け付けるので %01111111 - // I=5 だと割り込みレベル 6,7 を受け付けるので %00000011 - // I=6 だと割り込みレベル 7 を受け付けるので %00000001 - // ただし I=7 はこれを使わず別処理する - // bit 7 6 5 4 3 2 1 0 - // Level 0 1 2 3 4 5 6 7 - // - // intrmtx 取ってからアクセスすること。 - uint8 intr_mask = 0; - - // 割り込み要求は別スレッドから呼ばれる場合もあるので - // (自スレッドから呼び出した関数の向こうから呼ばれる場合もあることに注意) - // それらの変数はこれで保護する。 - // 最終的には atomic_reqflag に CPU_REQ_INTR を立てることでメインループ - // に通知する (この通知そのものは atomic なので特に保護しなくてもよい)。 - std::mutex intrmtx {}; - - uint64 total_cycle = 0; // 積算実行サイクル数 - int32 cycle_cache = 0; // キャッシュケースの所用サイクル数 - int32 cycle_nocache = 0; // ノーキャッシュケースの時の *追加分* - uint64 inst_count = 0; // 命令実行数 + int32 cycle_nocache {}; // ノーキャッシュケースの時の追加分 // ブランチ履歴 (例外履歴を含む) - BranchHistory_m680x0 brhist {}; + BranchHistory_m680x0 brhist { BranchHistory::BrHist }; // 例外履歴のみ - BranchHistory_m680x0 exhist {}; + BranchHistory_m680x0 exhist { BranchHistory::ExHistOnly }; // バス m68kbus bus {}; - // 手抜きのためリセットベクタ取得アドレスを知っている。 - // リセット時のためだけにデバイス側に細工を入れるのは実行時の - // オーバーヘッドが大きそうなので。 - uint32 reset_vector = 0; - // A-Line, F-Line 命令エミュレーションのコールバックとユーザ引数。 // ユーザ引数には関与しないので呼び出し側が自由に指定してよい。 // コールバック側で処理完了したら true を返す。 // デフォルトの処理(すなわちm68k例外)にする場合は false を返す。 - bool (*aline_callback)(m68kcpu *, void *) = NULL; - void *aline_arg = NULL; - bool (*fline_callback)(m68kcpu *, void *) = NULL; - void *fline_arg = NULL; + bool (*aline_callback)(m68kcpu *, void *) {}; + void *aline_arg {}; + bool (*fline_callback)(m68kcpu *, void *) {}; + void *fline_arg {}; + + // RESET 命令のコールバックとユーザ引数 + void (*resetop_callback)(void *) {}; + void *resetop_arg {}; // ダブルバスフォールトのコールバックとユーザ引数。 - void (*halt_callback)(void *) = NULL; - void *halt_arg = NULL; + void (*halt_callback)(void *) {}; + void *halt_arg {}; + + // VM 側デバイス + MPU680x0Device *dev {}; }; #define RegD(n) (cpu->reg.da[(n)]) @@ -303,10 +283,14 @@ class m68kcpu final { #define RegAY RegA(RegIRY) // 外部公開ルーチン -extern m68kcpu *m68030_init(uint32 reset_vector); -extern uint32 m68030_run(m68kcpu *cpu, uint64 request); -extern void m68030_exception_reset(m68kcpu *cpu); -extern void m68030_interrupt(m68kcpu *cpu, int level, int vector); +extern m68kcpu *m68030_init(MPU680x0Device *dev_); +extern int m68030_exec(m68kcpu *cpu); +extern void m68030_power_on(m68kcpu *cpu); +extern bool m68030_interrupt(m68kcpu *cpu, int level); +extern bool m68030_check_interrupt(m68kcpu *cpu); +extern int m68030_exception_reset(m68kcpu *cpu); +extern int m68030_exception_interrupt(m68kcpu *cpu); // 外部で定義されるコールバック extern void m68030_reset_inst(m68kcpu *cpu); +extern int m68030_interrupt_acknowledge(int level);