--- nono/m680x0/m68030core.cpp 2026/04/29 17:05:15 1.1.1.8 +++ nono/m680x0/m68030core.cpp 2026/04/29 17:05:26 1.1.1.11 @@ -5,8 +5,10 @@ // #include "mpu680x0.h" +#include "m68030cache.h" #include "debugger.h" #include "interrupt.h" +#include "mainbus.h" #include "scheduler.h" #include "vectortable.h" @@ -14,18 +16,19 @@ // 1命令実行する。 // 割り込みチェックなどを省いたショート版。 -// 戻り値は消費したサイクル数。 void MPU680x0Device::ExecShort(Event& ev) { uint64 cycle_start = used_cycle; + buswait = 0; + try { // 1命令版では switch-case を使うしかない。 ppc = reg.pc; flag_pi = 0; flag_pd = 0; - ir = fetch_16(); + ir = fetch_2(); // uint16 を 6ビット右シフトしたら 1024 以上になるはずは // ないのだが、デフォルトでは gcc/clang どちらも律儀に @@ -40,9 +43,11 @@ MPU680x0Device::ExecShort(Event& ev) #include "m68030switch.h" } - used_cycle += cycle_nocache; - cycle_nocache = 0; - } catch (int vector) { + if (__predict_false(icache->enable == false)) { + used_cycle += cycle_nocache; + cycle_nocache = 0; + } + } catch (uint vector) { // ここで(C++の)例外スローをキャッチするのは // - メモリ空間をアクセスした先でのバスエラー例外 // - EA パース中の不当命令例外 @@ -55,13 +60,17 @@ MPU680x0Device::ExecShort(Event& ev) putlogn("vector 0x%x", vector); } } - Exception(vector); + if (vector == M68K::EXCEP_BUSERR) { + ExceptionBuserr(vector); + } else { + Exception(vector); + } } // 外部割り込みの起動は VM 側で処理している。 int cycle = used_cycle - cycle_start; - ev.time = cycle * clock_nsec; + ev.time = cycle * clock_nsec + buswait; scheduler->StartEvent(ev); } @@ -116,12 +125,124 @@ MPU680x0Device::SetSR(uint16 data) reg.A[7] = reg.msp; } - // バスの FC2 を変更 - bus.SetFC2(reg.s); + // FC2-0 + fc_inst = BusAddr::Fetch | busaddr::SU(reg.s); + fc_data = BusAddr::D | busaddr::SU(reg.s); // XXX 他に何か状態変えないといけないことあったっけか。 } +// CACR レジスタ書き込み +void +MPU680x0Device::SetCACR(uint32 newval) +{ + newval &= M68K::CACR_MASK; + uint32 oldval = reg.cacr; + uint32 chgval = oldval ^ newval; + + // EI (命令キャッシュ有効) + if ((chgval & M68K::CACR_EI) != 0) { + if ((newval & M68K::CACR_EI) != 0) { + // 命令キャッシュ有効 + icache->enable = true; + icache->hist.Clear(); + putlog(1, "I-Cache enabled"); + } else { + // 命令キャッシュ無効 + icache->enable = false; + putlog(1, "I-Cache disabled"); + // 命令キャッシュが有効だった期間 nocache は使われずに + // 積算され続けているが、キャッシュ無効になるとこれを加算 + // しようとするのでここでリセット。 + cycle_nocache = 0; + } + } + + // FI (命令キャッシュ凍結) + if ((chgval & M68K::CACR_FI) != 0) { + putlog(0, "CACR:FI Not Implemented"); + icache->freeze = (newval & M68K::CACR_FI); + } + + // CEI (命令キャッシュの指定エントリをクリア) + if ((chgval & M68K::CACR_CEI) != 0) { + // CAAR の b7-2 で示されるロングワードを無効にする。 + uint32 idx = (reg.caar & 0x000000f0) >> 4; + uint32 sel = (reg.caar & 0x0000000c) >> 2; + auto& l = icache->line[idx]; + l.valid[sel] = 0; + + newval &= ~M68K::CACR_CEI; + } + + // CI (命令キャッシュクリア) + if ((chgval & M68K::CACR_CI) != 0) { + for (auto& l : icache->line) { + l.valid_all = 0; + } + + newval &= ~M68K::CACR_CI; + } + + // IBE (命令バースト有効) + if ((chgval & M68K::CACR_IBE) != 0) { + icache->burst_enable = (newval & M68K::CACR_IBE) && has_burst_access; + } + + // ED (データキャッシュ有効) + if ((chgval & M68K::CACR_ED) != 0) { + if ((newval & M68K::CACR_ED) != 0) { + // データキャッシュ有効。 + dcache->enable = true; + dcache->hist.Clear(); + putlog(1, "D-Cache enabled"); + } else { + // データキャッシュ無効。 + dcache->enable = false; + putlog(1, "D-Cache disabled"); + } + } + + // FD (データキャッシュ凍結) + if ((chgval & M68K::CACR_FD) != 0) { + dcache->freeze = (newval & M68K::CACR_FD); + putlog(1, "CACR:FD -> %u", dcache->freeze); + } + + // CED (データキャッシュの指定エントリをクリア) + if ((chgval & M68K::CACR_CED) != 0) { + // CAAR の b7-2 で示されるロングワードを無効にする。 + uint32 idx = (reg.caar & 0x000000f0) >> 4; + uint32 sel = (reg.caar & 0x0000000c) >> 2; + auto& l = dcache->line[idx]; + l.valid[sel] = 0; + + newval &= ~M68K::CACR_CED; + } + + // CD (データキャッシュクリア) + if ((chgval & M68K::CACR_CD) != 0) { + for (auto& l : dcache->line) { + l.valid_all = 0; + } + + newval &= ~M68K::CACR_CD; + } + + // DBE (データバースト有効) + if ((chgval & M68K::CACR_DBE) != 0) { + dcache->burst_enable = (newval & M68K::CACR_DBE) && has_burst_access; + } + + // WA (ライトアロケート) + if ((chgval & M68K::CACR_WA) != 0) { + dcache->wa = (newval & M68K::CACR_WA); + } + + // とりあえずレジスタイメージも保存。 + reg.cacr = newval; +} + // 命令中に (An)+ で変化したアドレスレジスタを命令実行前の状態に巻き戻す。 // flag_pi は bit7..0 が save_pi[7..0] の A7..A0 に対応している。 void @@ -150,22 +271,27 @@ MPU680x0Device::restore_reg_pd() // vector にジャンプする。vector はベクタ番号(アドレスではない)。 void -MPU680x0Device::JumpVector(int vector) +MPU680x0Device::JumpVector(uint vector, bool from_buserr) { uint32 vecaddr; uint32 newpc; vecaddr = reg.vbr + vector * 4; - reg.pc = vecaddr; - newpc = fetch_32(); + newpc = read_4(vecaddr); // VBR 込みのジャンプ先が確定したところで今度はブランチ履歴に記録。 // この時のブランチ元はベクタアドレス // (reg.pc は fetch によって進んでしまうので先に保存) - brhist.AddEntry(vecaddr | (IsSuper() ? 1 : 0), newpc, 0x8000); + uint32 inst = BranchHistory_m680x0::VectorJump; + brhist.AddEntry(vecaddr | (IsSuper() ? 1 : 0), newpc, inst); // 奇数番地ならアドレスエラー if (__predict_false((newpc & 1) != 0)) { - Exception(M68K::EXCEP_ADDRERR); + if (from_buserr) { + // バスエラー処理中ならダブルバスフォールト。 + throw M68K::EXCEP_ADDRERR; + } else { + ExceptionBuserr(M68K::EXCEP_ADDRERR); + } return; } reg.pc = newpc; @@ -175,7 +301,7 @@ MPU680x0Device::JumpVector(int vector) // なるケースはここでバスエラーが出なければいけないが、まだ // キャッシュを実装していないので、ここで1ワードフェッチしてみて // PC を戻すあほっぽい方法を取る。 - fetch_16(); + fetch_2(); reg.pc -= 2; } @@ -185,23 +311,23 @@ MPU680x0Device::JumpVector(int vector) // 次の命令位置かが異なる)。 // sr は例外発生時の SR。 inline void -MPU680x0Device::GenerateExframe0(int vector, uint32 pc, uint16 sr) +MPU680x0Device::GenerateExframe0(uint vector, uint32 pc, uint16 sr) { // 例外スタックフレーム $0 // SP+$00.W STATUS REGISTER // +$02.L PROGRAM COUNTER ; 例外ごとに異なる // +$06.W %0000 | VECTOR - push_16((0 << 12) | (vector * 4)); - push_32(pc); - push_16(sr); + push_2((0 << 12) | (vector << 2)); + push_4(pc); + push_2(sr); } // 例外スタックフレーム $2 を生成する。 // vector はベクタ番号。 // スタックに積む PC は常に次の命令。 inline void -MPU680x0Device::GenerateExframe2(int vector, uint16 sr) +MPU680x0Device::GenerateExframe2(uint vector, uint16 sr) { // 例外スタックフレーム $2 // SP+$00.W STATUS REGISTER @@ -209,15 +335,15 @@ MPU680x0Device::GenerateExframe2(int vec // +$06.W %0010 | VECTOR // +$08.L INSTRUCTION ADDRESS ; 例外を起こした命令のアドレス - push_32(ppc); // 例外を起こした命令のアドレス - push_16((2 << 12) | (vector * 4)); - push_32(reg.pc); // 次の命令位置 - push_16(sr); + push_4(ppc); // 例外を起こした命令のアドレス + push_2((2 << 12) | (vector << 2)); + push_4(reg.pc); // 次の命令位置 + push_2(sr); } // 例外スタックフレーム $B を生成する。 inline void -MPU680x0Device::GenerateExframeB(int vector, uint16 sr) +MPU680x0Device::GenerateExframeB(uint vector, uint16 sr) { uint16 ssw; uint32 fault_addr; @@ -225,9 +351,14 @@ MPU680x0Device::GenerateExframeB(int vec stageBaddr = reg.pc + 2; // この後のスタック操作で bus が変化する前に保存 - fault_addr = bus.laddr; - // DF ビットを立てておくと RTE した後この命令を再実行。 - ssw = bus.ssw | M68K::SSW_DF; + fault_addr = bus.laddr.Addr(); + + // DF は常に立てる必要がある?? + ssw = bus.GetSSW() | M68K::SSW_DF; + if (mmu_enable && (ssw & M68K::FC_DATA) != 0) { + // 命令アクセスなら RB をセット。 + ssw |= M68K::SSW_RB; + } // 例外スタックフレーム $B // SP+$00.W STATUS REGISTER @@ -262,28 +393,28 @@ MPU680x0Device::GenerateExframeB(int vec // 一方、ポストインクリメントのケースはこの少し下の // ExceptionBuserr() 内のコメント参照。 for (int i = 7; i >= 0; i--) { - push_32(save_pd[i]); + push_4(save_pd[i]); } - push_16(flag_pd); + push_2(flag_pd); reg.A[7] -= 2; reg.A[7] -= 2; // VERSION# reg.A[7] -= 6; - push_32(0); // DATA INPUT BUFFER + push_4(0); // DATA INPUT BUFFER reg.A[7] -= 4; - push_32(stageBaddr); // STAGE B ADDRESS + push_4(stageBaddr); // STAGE B ADDRESS reg.A[7] -= 8; - push_32(0); // DATA OUTPUT BUFFER + push_4(0); // DATA OUTPUT BUFFER reg.A[7] -= 4; - push_32(fault_addr); // DATA CYCLE FAULT ADDRESS - push_16(0); // INSTRUCTION PIPE STAGE B - push_16(0); // INSTRUCTION PIPE STAGE C - push_16(ssw); + push_4(fault_addr); // DATA CYCLE FAULT ADDRESS + push_2(0); // INSTRUCTION PIPE STAGE B + push_2(0); // INSTRUCTION PIPE STAGE C + push_2(ssw); reg.A[7] -= 2; - push_16(0xb000 | (vector << 2)); + push_2(0xb000 | (vector << 2)); // 本当は現在の PC だが、再実行のため PPC を積む。 - push_32(ppc); // PC - push_16(sr); // 例外入り口で保存した SR + push_4(ppc); // PC + push_2(sr); // 例外入り口で保存した SR } // 例外処理について。 @@ -294,14 +425,14 @@ MPU680x0Device::GenerateExframeB(int vec // 1. バスエラー例外 // MMU による論理アドレスでのバスエラーは (Translate*() が false を返した後) // m68030bus.cpp ルーチンが (C++の) 例外をスローする。 -// 物理アドレス空間アクセス後のバスエラーは (VM側の read*()/write*() が -// (int64)-1 を返した後) m68030bus.cpp ルーチンが (C++) の例外をスローする。 +// 物理アドレス空間アクセス後のバスエラーは (VM側の Read*()/Write*() が +// BusErr を返した後) m68030bus.cpp ルーチンが (C++) の例外をスローする。 // どちらのケースも m68030core.cpp のメインループで catch し、その catch -// ブロック内で Exception() を呼び出す。 +// ブロック内で ExceptionBuserr() を呼び出す。 // // 2. アドレスエラー例外 // アドレスエラーは Jump() 内でのみ発生するはずで、その場で -// Exception() を呼んで処理する。 +// ExceptionBuserr() を呼んで処理する。 // // 3. 命令中で起きる例外 // 命令途中で起きる(確定的な)例外は Exception() を呼び出す。 @@ -339,10 +470,10 @@ MPU680x0Device::ExceptionReset() // 例外履歴に記録 (例外発生はブランチ履歴にも記録) // m68k では今の所リセット例外発生時の PC にはあまり意味がないけど、 // m88k と動作を揃えておく。 - // 履歴のリセットベクタは 0 の代わりに 1 を使う仕様になっている。 const uint vector = 0; - exhist.AddEntry(reg.pc | 1, 0, 0x8000 | (vector + 1)); - brhist.AddEntry(reg.pc | 1, 0, 0x8000 | (vector + 1)); + excep_counter[0]++; + exhist.AddEntry(reg.pc | 1, 0, BranchHistory_m680x0::Exception | 0); + brhist.AddEntry(reg.pc | 1, 0, BranchHistory_m680x0::Exception | 0); // デバッガに通知 (例外ブレーク用)。こっちのベクタは 0 のままでよい。 debugger->NotifyExceptionMain(vector); @@ -360,15 +491,21 @@ MPU680x0Device::ExceptionReset() // ここは SetSR を使わずに設定する。 reg.s = true; reg.m = false; - bus.SetFC2(reg.s); + fc_inst = BusAddr::S | BusAddr::Fetch; + fc_data = BusAddr::S | BusAddr::D; // ここは割り込みレベル変化のチェックは不要でセットだけでいい。 reg.intr_mask = 7; // 4. VBR をクリア reg.vbr = 0; - // 5. キャッシュ - reg.cacr = 0; // XXX - // 6. キャッシュエントリクリア + + // 5. キャッシュの EI|ED, FI|FD, IBE|DBE, WA をクリア + // 6. キャッシュエントリをすべてクリア (CI|CD) + SetCACR(M68K::CACR_CD | M68K::CACR_CI); + cycle_nocache = 0; + icache->hist.Clear(); + dcache->hist.Clear(); + // 7. TC:E、TTn:E をクリア SetTC(GetTC() & ~m68030TC::TC_E); SetTT(0, GetTT(0) & ~m68030TT::E); @@ -379,13 +516,14 @@ MPU680x0Device::ExceptionReset() // 10. PC をロード try { reg.pc = 0; - reg.A[7] = fetch_32(); - uint32 pc = fetch_32(); - // 大丈夫のはずだけど fetch_32() が reg.pc を書き換えるので一応 + reg.A[7] = fetch_4(); + uint32 pc = fetch_4(); + // 大丈夫のはずだけど fetch_4() が reg.pc を書き換えるので一応 reg.pc = pc; // リセットベクタは常に 0, 4 番地から取得したことになっている - brhist.AddEntry(0x00000004 | 1, reg.pc, 0x8000); - } catch (int) { + uint32 inst = BranchHistory_m680x0::VectorJump; + brhist.AddEntry(0x00000004 | 1, reg.pc, inst); + } catch (uint) { DoubleBusFault("reset exception"); } @@ -399,21 +537,63 @@ MPU680x0Device::ExceptionReset() return used_cycle - cycle_start; } -// 例外処理 (リセット・割り込み以外) を行う。 -// vector はベクタ番号。 +// 汎用の例外処理を行う。vector はベクタ番号。 +// ただし以下の例外はここではなくそれぞれ固有のを呼ぶこと。 +// o リセット例外は ExceptionReset() +// o 割り込み例外は ExceptionInterrupt() +// o TRAP#15 例外は ExceptionTrap15() +// o バスエラー・アドレスエラーは ExceptionBuserr() void -MPU680x0Device::Exception(int vector) +MPU680x0Device::Exception(uint vector) { - // バスエラー・アドレスエラーは別で処理。 - if (vector <= M68K::EXCEP_ADDRERR) { - ExceptionBuserr(vector); - return; + uint32 inst = BranchHistory_m680x0::Exception | vector; + ExceptionGeneric(vector, inst); +} + +// TRAP #15 の例外処理を行う。 +// 処理自体は汎用の Exception() とまったく同じだが、 +// IOCS コールの時には分岐履歴の出力が変わるため入口を分けてある。 +void +MPU680x0Device::ExceptionTrap15() +{ + // 今発生した TRAP #15 が IOCS コールっぽいかどうか調べる。 + // + // Human68k 方面をやってる時は TRAP #15 は IOCS コールで表示してほしい。 + // 一方、NetBSD のカーネル内では TRAP #15 は IOCS コールではない別用途 + // なので IOCS コールかのように表示されるのは紛らわしい。さらに言えば + // NetBSD でもブートローダの時点はまだ IOCS コールを使うので、出来れば + // 今呼ばれたこれが IOCS コールなのか、そうでない TRAP #15 なのかは + // 区別したい。 + // + // IOCS コールかどうかは厳密には分からないが、これが呼ばれた時点で + // ワークエリアの $cbc == 0x03、$cbe == 0xff であれば IOCS コールと + // 判定することにする。 + // $cbc は MPU 種別で 3:68030。 + // $cbe は MMU 有無で 0xff:有り。 + // 今の所 68030/MMU有り しかサポートしていないので。 + // だめならまた考える。 + + const uint vector = M68K::EXCEP_TRAP15; + uint32 inst; + if (mainbus->Peek1(0xcbc) == 0x03 && mainbus->Peek1(0xcbe) == 0xff) { + // IOCS コールっぽい + inst = BranchHistory_m680x0::IOCSCall | (reg.D[0] & 0xff); + } else { + // TRAP#15 っぽい + inst = BranchHistory_m680x0::Exception | vector; } + ExceptionGeneric(vector, inst); +} +// 汎用の例外処理本体。 +void +MPU680x0Device::ExceptionGeneric(uint vector, uint32 inst) +{ // 例外履歴に記録 (例外発生はブランチ履歴にも記録) + excep_counter[vector]++; uint32 from = ppc | (IsSuper() ? 1 : 0); - exhist.AddEntry(from, 0, 0x8000 | vector); - brhist.AddEntry(from, 0, 0x8000 | vector); + exhist.AddEntry(from, 0, inst); + brhist.AddEntry(from, 0, inst); // デバッガに通知 (例外ブレーク用) debugger->NotifyExceptionMain(vector); @@ -447,14 +627,14 @@ MPU680x0Device::Exception(int vector) break; default: - PANIC("$%08x exception vector %d ?", ppc, vector); + PANIC("$%08x exception vector %u ?", ppc, vector); break; } // ベクタにジャンプ - JumpVector(vector); - } catch (int vector2) { - assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%d", vector); + JumpVector(vector, false); + } catch (uint vector2) { + assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%u", vector); // バスエラー処理へ ExceptionBuserr(vector2); @@ -464,15 +644,17 @@ MPU680x0Device::Exception(int vector) // バスエラー・アドレスエラー例外処理を行う。 // 他の例外とは違いが多いので分けた。 void -MPU680x0Device::ExceptionBuserr(int vector) +MPU680x0Device::ExceptionBuserr(uint vector) { assertmsg((vector == M68K::EXCEP_BUSERR || vector == M68K::EXCEP_ADDRERR), - "vector=%d", vector); + "vector=%u", vector); // 例外履歴に記録 (例外発生はブランチ履歴にも記録) + excep_counter[vector]++; uint32 from = ppc | (IsSuper() ? 1 : 0); - exhist.AddEntry(from, 0, 0x8000 | vector); - brhist.AddEntry(from, 0, 0x8000 | vector); + uint32 inst = BranchHistory_m680x0::Exception | vector; + exhist.AddEntry(from, 0, inst); + brhist.AddEntry(from, 0, inst); // デバッガに通知 (例外ブレーク用) debugger->NotifyExceptionMain(vector); @@ -497,10 +679,11 @@ MPU680x0Device::ExceptionBuserr(int vect // 使えればショートを使うのだが、ここでは全部ロングを使う。 GenerateExframeB(vector, sr); // ベクタにジャンプ - JumpVector(vector); - } catch (int vector2) { - // ここに来るのはバスエラーだけのはず - assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%d", vector); + JumpVector(vector, true); + } catch (uint vector2) { + // ここに来るのはバスエラーかアドレスエラーだけのはず + assertmsg(vector2 == M68K::EXCEP_BUSERR || + vector2 == M68K::EXCEP_ADDRERR, "vector=%u", vector); // バスエラー・アドレスエラー処理中のバスエラーは // ダブルバスフォールト。 @@ -510,11 +693,12 @@ MPU680x0Device::ExceptionBuserr(int vect // 割り込み例外処理を行う。 // 割り込みの受け付けとレベルのチェック等の後、次命令境界で呼ばれるやつ。 -int +// この処理にかかる時間 [nsec] を返す。 +uint64 MPU680x0Device::ExceptionInterrupt() { - int cycle_start = used_cycle; - int level = intr_level; + uint64 cycle_start = used_cycle; + uint level = intr_level; // ユーザーズマニュアル(日本語) p.399 図8-5 の中ほど // 「/IPEND をネゲート、割り込みアクノリッジサイクルを実行」 @@ -524,14 +708,24 @@ MPU680x0Device::ExceptionInterrupt() ChangeState(CPU_STATE_NORMAL); // 割り込みアクノリッジサイクルを実行 - int vector = interruptdev->InterruptAcknowledge(level); - if (vector == -1) { - vector = 24 + level; + uint32 vector; + busdata bd = interruptdev->InterruptAcknowledge(level); + if (__predict_false(bd.IsBusErr())) { + // 外部回路がバスエラーを返すと Spurious を発行する。(7.4.1.3) + vector = M68K::EXCEP_SPURIOUS; + } else { + vector = bd.Data(); + if ((int32)vector < 0) { + // オートベクタ要求 (7.4.1.2) + // (負数(-1)ならオートベクタということにしている) + vector = M68K::EXCEP_LEVEL_BASE + level; + } } // 例外履歴に記録 (例外発生はブランチ履歴にも記録) + excep_counter[vector]++; uint32 from = ppc | (IsSuper() ? 1 : 0); - uint32 inst = 0x8000 | (level << 8) | vector; + uint32 inst = BranchHistory_m680x0::Exception | vector; exhist.AddEntry(from, 0, inst); brhist.AddEntry(from, 0, inst); // デバッガに通知 (例外ブレーク用) @@ -553,15 +747,15 @@ MPU680x0Device::ExceptionInterrupt() GenerateExframe0(vector, reg.pc, oldsr); // ベクタにジャンプ - JumpVector(vector); - } catch (int vector2) { - assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%d", vector); + JumpVector(vector, false); + } catch (uint vector2) { + assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%u", vector); // バスエラー処理へ ExceptionBuserr(vector2); } - return used_cycle - cycle_start; + return (used_cycle - cycle_start) * clock_nsec + bd.GetWait(); } // RTE 命令。 @@ -574,9 +768,9 @@ MPU680x0Device::ops_rte() uint16 frame; try { - sr = pop_16(); - pc = pop_32(); - frame = pop_16(); + sr = pop_2(); + pc = pop_4(); + frame = pop_2(); switch (frame >> 12) { case 0: CYCLE2(18, 20); @@ -599,14 +793,14 @@ MPU680x0Device::ops_rte() CYCLE(76); reg.A[7] += 2; // $08.W - ssw = pop_16(); // $0a.W SSW + ssw = pop_2(); // $0a.W SSW reg.A[7] += 4 * 6; // $0c.L*6 - stage_b = pop_32(); // $24.L Stage B + stage_b = pop_4(); // $24.L Stage B reg.A[7] += 2 * 9; // $28.W*9 // $3a..$58 ここが save_pd の取り出し - flag_pd = pop_16(); + flag_pd = pop_2(); for (int i = 0; i < 8; i++) { - save_pd[i] = pop_32(); + save_pd[i] = pop_4(); } // A7 レジスタをリストアするかもしれない前に Super/User を // 復帰しておかないといけない @@ -629,8 +823,8 @@ MPU680x0Device::ops_rte() PANIC("RTE frame=$%x not supported", frame >> 12); break; } - } catch (int vector2) { - assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector2=%d", vector2); + } catch (uint vector2) { + assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector2=%u", vector2); // RTE 処理中のバスエラーはダブルバスフォールト。 DoubleBusFault("bus/address error handling"); @@ -641,7 +835,7 @@ MPU680x0Device::ops_rte() void MPU680x0Device::ops_stop() { - uint32 data = fetch_16(); + uint32 data = fetch_2(); SetSR(data); ChangeState(CPU_STATE_STOP);