--- nono/debugger/branchhistory.cpp 2026/04/29 17:05:16 1.1.1.7 +++ nono/debugger/branchhistory.cpp 2026/04/29 17:05:20 1.1.1.8 @@ -9,6 +9,7 @@ // #include "branchhistory.h" +#include "m68030disasm.h" #include "m88100.h" #include "mpu64180.h" #include "vectortable.h" @@ -163,29 +164,49 @@ BranchHistory::FormatHeader() const // m680x0 ブランチ履歴 (どこに置くのがよいか) // -// m680x0 ブランチ履歴では、通常ブランチ、例外発生、例外ベクタによる -// ジャンプの3つを区別する。 +// m680x0 ブランチ履歴では、通常ブランチ、例外発生 (IOCS コールと +// それ以外)、例外ベクタによるジャンプの4つを区別する。 // -// 通常の分岐: -// from は上位31ビットが分岐元 PC、最下位ビットが S/U、 -// to は32ビット全体が分岐先 PC、 -// inst の上位16ビットに命令の1ワード目。 -// inst の $8000 が立っていないことで区別する。 -// -// 例外発生: -// from は上位31ビットが例外発生時の PC、最下位ビットが S/U、 -// to は不問(通常 0 をセットすること)、 -// inst は $00008LVV で $8000 が例外フラグ、VV がベクタ番号である。 -// ベクタ番号が $00 だと次項(ベクタによる分岐)と区別つかなくなってしまう -// ため、リセット例外 (ベクタ番号0) は V=$01 で記録する。 -// L は割り込みなら割り込みレベル。 -// inst に $8000 が立っていて、かつ $8000 と一致しないことで区別する。 +// 1. 通常の分岐: +// from は上位31ビットが分岐元 PC、最下位ビットが S/U。 +// to は32ビット全体が分岐先 PC。 +// inst は上位2ビットが %00 (Normal)、下位16ビットに分岐元命令の1ワード目。 // -// 例外ベクタによる分岐 (例外処理の最後に起きる): +// 31 30 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | 0 | 0 | .. | instruction word | +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// +// 2. 例外発生 (IOCS コール以外の場合): +// from は上位31ビットが例外発生時の PC、最下位ビットが S/U。 +// to は不問だが 0 にすること。 +// inst は上位2ビットが %11 (Exception)、Number はベクタ番号 (0-255)。 +// 例外が TRAP#15 で IOCS コールっぽくない場合もこちら。 +// +// 31 30 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | 1 | 1 | .. | 0 | Vector | +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// +// 3. 例外発生 (IOCS コールの場合): +// from, to は同じ。 +// inst は上位2ビットが %10 (IOCSCall)、Number は IOCS コール番号 (0-255)。 +// +// 31 30 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | 1 | 0 | .. | 0 | IOCS Call Number | +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// +// 4. 例外ベクタによる分岐 (例外処理の最後に起きる): // from はベクタアドレス、 // to は分岐先 (0 も起こりえる)、 -// inst は $00008000。 -// inst が $00008000 と一致することで区別する (ビットが立っているではない)。 +// inst は上位2ビットが %01 (VectorJump)。 +// +// 31 30 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | 0 | 1 | .. | 0 | +// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// // コンストラクタ BranchHistory_m680x0::BranchHistory_m680x0(int objid_) @@ -206,26 +227,11 @@ BranchHistory_m680x0::FormatEntry(const std::string desc = string_format("%c:%08x", (e.from & 1) ? 'S' : 'U', (e.from & ~1)); - if ((e.inst & 0x8000)) { - if ((e.inst & 0x7fff) != 0) { - // 例外発生記録 - // 発生アドレスとベクタ(と割り込みレベル)を表示 - uint32 vector = e.inst & 0xff; - if (vector == 1) { - vector = 0; - } - // とりあえず - const char *name = vectortable->GetExceptionName(vector); - desc += string_format("<%3d> %s", vector, name ?: ""); - // XXX TODO 割り込みレベル - } else { - // 例外ベクタフェッチしてジャンプ - desc += string_format("(vector fetch) -> $%08x", e.to); - } - } else { - // ブランチ + switch (e.inst >> 30) { + case 0: // 通常分岐 + { const char *mnemonic; - uint32 inst = e.inst >> 16; + uint32 inst = e.inst & 0xffff; if (inst == 0x4e73) { mnemonic = ":rte"; } else if (inst == 0x4e75) { @@ -254,6 +260,36 @@ BranchHistory_m680x0::FormatEntry(const mnemonic = ""; } desc += string_format("(%04x%-6s) -> $%08x", inst, mnemonic, e.to); + break; + } + + case 1: // 例外ベクタフェッチによるジャンプ + // 例外ベクタフェッチしてジャンプ + desc += string_format("(vector fetch) -> $%08x", e.to); + break; + + case 2: // 例外発生 (IOCS コール) + { + uint num = e.inst & 0xff; + const char *name = m680x0disasm::GetIOCSName(num); + if (name != NULL) { + desc += string_format("<%3d> IOCS %s", M68K::EXCEP_TRAP15, name); + } else { + desc += string_format("<%3d> IOCS $%02x", M68K::EXCEP_TRAP15, num); + } + break; + } + + case 3: // 例外発生 (IOCS コール以外) + { + uint32 vector = e.inst & 0xff; + const char *name = vectortable->GetExceptionName(vector); + desc += string_format("<%3d> %s", vector, name ?: ""); + break; + } + + default: + __unreachable(); } return desc; }