--- nono/debugger/branchhistory.cpp 2026/04/29 17:05:32 1.1.1.10 +++ nono/debugger/branchhistory.cpp 2026/04/29 17:05:49 1.1.1.12 @@ -71,7 +71,7 @@ BranchHistory::Clear() e.count = 0; e.from = 0xffffffff; e.to = 0xffffffff; - e.inst = 0; + e.info = 0; } } @@ -162,7 +162,7 @@ BranchHistory::FormatHeader() const // -// m680x0 ブランチ履歴 (どこに置くのがよいか) +// m680x0 ブランチ履歴 // // m680x0 ブランチ履歴では、通常ブランチ、例外発生 (IOCS コールと @@ -171,43 +171,46 @@ BranchHistory::FormatHeader() const // 1. 通常の分岐: // from は上位31ビットが分岐元 PC、最下位ビットが S/U。 // to は32ビット全体が分岐先 PC。 -// inst は上位2ビットが %00 (Normal)、下位16ビットに分岐元命令の1ワード目。 +// info は上位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 | -// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// 3 2 1 0 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-+-+-----------+---------------+---------------+---------------+ +// |0 0| 0 | Instruction Word | +// +-+-+-----------+---------------+---------------+---------------+ // -// 2. 例外発生 (IOCS コール以外の場合): +// 2. 例外発生 (IOCS/DOS コール以外の場合): // from は上位31ビットが例外発生時の PC、最下位ビットが S/U。 // to は不問だが 0 にすること。 -// inst は上位2ビットが %11 (Exception)、Number はベクタ番号 (0-255)。 -// 例外が TRAP#15 で IOCS コールっぽくない場合もこちら。 +// info は上位2ビットが %11 (Exception)、最下位バイトがベクタ番号 (0-255)。 +// 例外が TRAP#15 だが IOCS コールっぽくない場合と、 +// 例外が F ライン例外だが DOS コールっぽくない場合もこちら。 +// +// +-+-+-----------+---------------+---------------+---------------+ +// |1 1| 0 | 0 | Vector No. | +// +-+-+-----------+---------------+---------------+---------------+ // -// 31 30 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | 1 | 1 | .. | 0 | Vector | -// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// -// 3. 例外発生 (IOCS コールの場合): +// 3. 例外発生 (IOCS/DOS コールの場合): // 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 | -// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// info は上位2ビットが %10 (ServiceCall)。 +// IOCS コールなら、b8 が %0 で b7-b0 に IOCS コール番号。 +// DOS コールなら、b8 が %1 で b7-b0 に DOS コール番号。 +// +// +-+-+-----------+---------------+---------------+---------------+ +// |1 0| 0 | 0 |0| IOCS Call No. | +// +-+-+-----------+---------------+---------------+---------------+ +// +-+-+-----------+---------------+---------------+---------------+ +// |1 0| 0 | - |1| DOS Call No. | +// +-+-+-----------+---------------+---------------+---------------+ // // 4. 例外ベクタによる分岐 (例外処理の最後に起きる): // from はベクタアドレス、 // to は分岐先 (0 も起こりえる)、 -// 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 | -// +---+---+-- --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// info は上位2ビットが %01 (VectorJump)。 // +// +-+-+-----------+---------------+---------------+---------------+ +// |0 1| 0 | +// +-+-+-----------+---------------+---------------+---------------+ // コンストラクタ BranchHistory_m680x0::BranchHistory_m680x0(uint objid_) @@ -228,11 +231,11 @@ BranchHistory_m680x0::FormatEntry(const std::string desc = string_format("%c:%08x", (e.from & 1) ? 'S' : 'U', (e.from & ~1)); - switch (e.inst >> 30) { + switch (e.info >> 30) { case 0: // 通常分岐 { const char *mnemonic; - uint32 inst = e.inst & 0xffff; + uint32 inst = e.info & 0xffff; if (inst == 0x4e73) { mnemonic = ":rte"; } else if (inst == 0x4e75) { @@ -269,21 +272,32 @@ BranchHistory_m680x0::FormatEntry(const desc += string_format("(vector fetch) -> $%08x", e.to); break; - case 2: // 例外発生 (IOCS コール) + case 2: // 例外発生 (IOCS/DOS コール) { - uint num = e.inst & 0xff; - const char *name = m680x0disasm::GetIOCSName(num); + const char *call; + const char *name; + uint vector; + uint num = e.info & 0xff; + if ((e.info & 0x0100) == 0) { + call = "IOCS"; + name = m680x0disasm::GetIOCSName(num); + vector = M68K::EXCEP_TRAP15; + } else { + call = "DOS"; + name = m680x0disasm::GetDOSName(num); + vector = M68K::EXCEP_FLINE; + } if (name != NULL) { - desc += string_format("<%3u> IOCS %s", M68K::EXCEP_TRAP15, name); + desc += string_format("<%3u> %s %s", vector, call, name); } else { - desc += string_format("<%3u> IOCS $%02x", M68K::EXCEP_TRAP15, num); + desc += string_format("<%3u> %s $%02x", vector, call, num); } break; } - case 3: // 例外発生 (IOCS コール以外) + case 3: // 例外発生 (IOCS/DOS コール以外) { - uint32 vector = e.inst & 0xff; + uint32 vector = e.info & 0xff; const char *name = vectortable->GetExceptionName(vector); desc += string_format("<%3u> %s", vector, name ?: ""); break; @@ -297,7 +311,7 @@ BranchHistory_m680x0::FormatEntry(const // -// m88xx0 ブランチ履歴 (どこに置くのがよいか) +// m88xx0 ブランチ履歴 // // m88xx0 ブランチ履歴では、通常ブランチ、例外発生の2つを区別する。 @@ -307,12 +321,18 @@ BranchHistory_m680x0::FormatEntry(const // 通常の分岐: // from は上位30ビットが分岐元 XIP、最下位ビットが S/U、 // to は32ビット全体が分岐先アドレス、 -// inst は命令ワード。 +// info は命令ワード。 // // 例外発生: // from は上位30ビットが例外発生時の XIP、最下位ビットが S/U、 -// to は 0。 -// inst は $fc000VVV で VVV (9ビット)がベクタ番号。 +// to は不問。 +// info は、9 ビットのベクタ番号と、ベクタが OpenBSD/m88k システムコール +// の場合はシステムコール番号を含む。 +// 3 2 1 0 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---------------+---------------+-------+-----+-+---------------+ +// |1 1 0 0 0 0 0 0| System Call No. |0 0 0| Vector Number | +// +---------------+---------------+-------+-----+-+---------------+ // 命令ワードとは衝突しない (instruction.txt 参照)。 // コンストラクタ @@ -334,21 +354,21 @@ BranchHistory_m88xx0::FormatEntry(const std::string desc = string_format("%c:%08x", (e.from & 1) ? 'S' : 'U', (e.from & ~1)); - if (e.inst >= 0xfc000000 && e.to == 0) { + if (e.info >= 0xfc000000) { // 例外発生記録 // 発生アドレスとベクタを表示 - uint32 vector = e.inst & 0x1ff; + uint32 vector = e.info & 0x1ff; const char *name = vectortable->GetExceptionName(vector); desc += string_format("<%3u> %s", vector, name ?: ""); if (vector == 128 || vector == 450) { // 450 なら OpenBSD のシステムコール番号を追加。 // 非公式 NetBSD/luna88k は(今の所?) 128 を使ってるようだ。 - desc += string_format("(%u)", (e.inst >> 12) & 0xfff); + desc += string_format("(%u)", (e.info >> 12) & 0xfff); } - } else if (e.inst >= 0xc0000000) { + } else if (e.info >= 0xc0000000) { // ブランチ const char *mnemonic = ""; - uint32 up4 = (e.inst >> 26) & 0xf; + uint32 up4 = (e.info >> 26) & 0xf; switch (up4) { case 0: mnemonic = ":br"; break; case 1: mnemonic = ":br.n"; break; @@ -362,7 +382,7 @@ BranchHistory_m88xx0::FormatEntry(const case 0xa: mnemonic = ":bcnd"; break; case 0xb: mnemonic = ":bcnd.n"; break; case 0xc: { - uint32 lo6 = (e.inst >> 10) & 0x3f; + uint32 lo6 = (e.info >> 10) & 0x3f; if (lo6 == 0x34) { mnemonic = ":tb0"; } else if (lo6 == 0x36) { @@ -373,9 +393,9 @@ BranchHistory_m88xx0::FormatEntry(const break; } case 0xd: { - uint32 lo6 = (e.inst >> 10) & 0x3f; + uint32 lo6 = (e.info >> 10) & 0x3f; if (lo6 == 0x30) { - if ((e.inst & 0x1f) == 1) { + if ((e.info & 0x1f) == 1) { mnemonic = ":jmp r1"; } else { mnemonic = ":jmp"; @@ -395,7 +415,7 @@ BranchHistory_m88xx0::FormatEntry(const default: break; } - desc += string_format("(%08x%-7s) -> $%08x", e.inst, mnemonic, e.to); + desc += string_format("(%08x%-7s) -> $%08x", e.info, mnemonic, e.to); } return desc; } @@ -411,8 +431,8 @@ BranchHistory_m88xx0::FormatEntry(const // 通常の分岐 // from は下位 16 ビットが分岐元 PC // to は下位 16 ビットが分岐先 PC -// inst の最上位ビットが %0 で区別する。 -// inst の下位 16 ビットに命令を上詰めで。例えば +// info の最上位ビットが %0 で区別する。 +// info の下位 16 ビットに命令を上詰めで。例えば // CALL (1バイト命令 CD nn nn) なら $0000'cd00、 // RETI (2バイト命令 ED 4D) なら $0000'ed4d。 // @@ -420,13 +440,13 @@ BranchHistory_m88xx0::FormatEntry(const // from は下位 16 ビットが例外発生時の PC // to は $ffffffff ならこのエントリはベクタ方式の例外発生時側を示す、 // そうでなければダイレクト方式で下位 16 ビットが分岐先 PC -// inst の最上位ビットが %1 で inst が $ffffffff でなければ +// info の最上位ビットが %1 で info が $ffffffff でなければ // 下位に優先度(0-15)。 // // 例外ベクタジャンプの場合 // from はベクタアドレス // to は分岐先 PC、 -// inst が $ffffffff で区別する。 +// info が $ffffffff で区別する。 // コンストラクタ BranchHistory_hd64180::BranchHistory_hd64180(uint objid_) @@ -468,12 +488,12 @@ BranchHistory_hd64180::FormatEntry(const std::string desc = strhex(e.from, 4); - if (e.inst == 0xffffffff) { + if (e.info == 0xffffffff) { // 例外ベクタフェッチしてジャンプ desc += string_format("(vector fetch) -> $%04x", e.to); - } else if ((int32)e.inst < 0) { + } else if ((int32)e.info < 0) { // 例外発生 - uint32 vector = e.inst & 0xff; + uint32 vector = e.info & 0xff; desc += string_format("<%2u>%-15s", vector, MPU64180Device::InterruptName[vector]); // 例外履歴には宛先は出さないほうに統一。 @@ -484,7 +504,7 @@ BranchHistory_hd64180::FormatEntry(const } else { // ブランチ std::string mnemonic; - uint32 inst = e.inst & 0xffff; + uint32 inst = e.info & 0xffff; if (inst == 0x1000) { mnemonic = ":DJNZ"; } else if (inst == 0x1800) {