--- nono/m680x0/m680x0core.cpp 2026/04/29 17:05:31 1.1 +++ nono/m680x0/m680x0core.cpp 2026/04/29 17:05:35 1.1.1.2 @@ -240,6 +240,28 @@ MPU680x0Device::GenerateExframe2(uint ve push_2(sr); } +// 例外スタックフレーム $4 を生成する。(68LC040 only) +inline void +MPU680x0Device::GenerateExframe4(uint vector, uint16 sr, uint32 ea) +{ + // 公式の図 (のオフセット) が雑すぎる。 + // + // SP->| STATUS REGISTER + // +$02 | PROGRAM COUNTER (H) ; こっちは次の命令 + // +$04 | (L) + // +$06 | %0100 | VECTOR OFFSET + // +$08 | EFFECTIVE ADDRESS (H) + // +$0a | (L) + // +$0c | PC OF FAULTED INSTRUCTION (H) + // +$0e | (L) + + push_4(ppc); + push_4(ea); + push_2((4 << 12) | (vector << 2)); + push_4(reg.pc); + push_2(sr); +} + // 例外スタックフレーム $7 を生成する。(68040 only) inline void MPU680x0Device::GenerateExframe7(uint vector, uint16 sr) @@ -781,6 +803,40 @@ MPU680x0Device::ExceptionInterrupt() return (used_cycle - cycle_start) * clock_nsec + bd.GetWait(); } +// LC040 の未実装浮動小数点命令例外。 +void +MPU680x0Device::ExceptionFPLC(uint32 ea) +{ + const uint vector = M68K::EXCEP_FLINE; + const uint32 inst = BranchHistory_m680x0::Exception | vector; + + // 例外履歴に記録 (例外発生はブランチ履歴にも記録) + excep_counter[vector]++; + uint32 from = ppc | (IsSuper() ? 1 : 0); + exhist.AddEntry(from, 0, inst); + brhist.AddEntry(from, 0, inst); + // デバッガに通知 (例外ブレーク用) + debugger->NotifyExceptionMain(vector); + + // 状態を保存 + uint16 sr = GetSR(); + + // S を立てて T1,T0 を落とす + SetSR((GetSR() | M68K::SR_S) & ~M68K::SR_T); + + try { + GenerateExframe4(vector, sr, ea); + + // ベクタにジャンプ + JumpVector(vector, false); + } catch (uint vector2) { + assertmsg(vector2 == M68K::EXCEP_BUSERR, "vector=%u", vector); + + // バスエラー処理へ + ExceptionBuserr(vector2); + } +} + // RTE 命令。 // 例外処理の近くに置いておくほうが便利なので。 void @@ -811,6 +867,19 @@ MPU680x0Device::ops_rte() Jump(pc); break; + case 0x04: + { + // 68LC040 only + if (GetFPUType().Is4060LC() == false) { + Exception(M68K::EXCEP_FORMAT); + return; + } + reg.A[7] += 8; + SetSR(sr); + Jump(pc); + break; + } + case 0x07: { // 68040 only