--- nono/m88xx0/m88100disasm.cpp 2026/04/29 17:05:11 1.1.1.8 +++ nono/m88xx0/m88100disasm.cpp 2026/04/29 17:05:15 1.1.1.9 @@ -5,8 +5,9 @@ // #include "m88100disasm.h" +#include "debugger_memory.h" +#include "m88100.h" #include "m88100acc.h" -#include "bus.h" #define OP_DEF(name) void __CONCAT(m88100disasm::op_,name)() #define OP_FUNC(name) __CONCAT(op_,name)() @@ -15,8 +16,7 @@ /*static*/ bool m88100disasm::use_altname; // コンストラクタ -m88100disasm::m88100disasm(DebuggerMemoryStream& mem_) - : inherited(mem_) +m88100disasm::m88100disasm() { } @@ -27,9 +27,9 @@ m88100disasm::~m88100disasm() // 逆アセンブルを実行 bool -m88100disasm::Exec() +m88100disasm::Exec(DebuggerMemoryStream *mem_) { - ExecInit(); + ExecInit(mem_); opX = 0; name.clear(); @@ -41,10 +41,10 @@ m88100disasm::Exec() altarg1.clear(); altarg2.clear(); - xip = (uint32)mem.laddr; + xip = (uint32)mem->laddr; - opX = mem.FetchInst(); - uint32 op12 = m88kcpu::op32_to_12(opX); + opX = mem->Read(4); + uint32 op12 = M88100::op32_to_12(opX); switch (op12) { #include "m88100switch.inc" default: @@ -69,21 +69,24 @@ m88100disasm::Exec() // arg0,1,2 の空でないやつを追加 std::string args; + int argc = 0; if (!arg0.empty()) { args += arg0; + argc++; } if (!arg1.empty()) { - if (!args.empty()) { + if (argc != 0) { args += ","; - while (args.length() % 4 != 0) + while (args.length() < argc * 4) args += " "; } args += arg1; + argc++; } if (!arg2.empty()) { - if (!args.empty()) { + if (argc != 0) { args += ","; - while (args.length() % 4 != 0) + while (args.length() < argc * 4) args += " "; } args += arg2; @@ -118,21 +121,24 @@ m88100disasm::Exec() // altarg0,1,2 の空でないやつを追加 std::string altargs; + int altargc = 0; if (!altarg0.empty()) { altargs += altarg0; + altargc++; } if (!altarg1.empty()) { - if (!altargs.empty()) { + if (altargc != 0) { altargs += ','; - while (altargs.length() % 4 != 0) + while (altargs.length() < altargc * 4) altargs += ' '; } altargs += altarg1; + altargc++; } if (!altarg2.empty()) { - if (!altargs.empty()) { + if (altargc != 0) { altargs += ','; - while (altargs.length() % 4 != 0) + while (altargs.length() < altargc * 4) altargs += ' '; } altargs += altarg2; @@ -280,6 +286,18 @@ m88100disasm::wo5() return string_format("%d<%d>", w5, o5); } +// "Width" 形式をビットマスク形式(数値)にして返す +uint32 +m88100disasm::wo5mask() +{ + uint32 w5 = W5 ?: 32; + uint32 o5 = O5; + + uint64 mask = (1ULL << w5) - 1; + mask <<= o5; + return (uint32)mask; +} + // キャリーサフィックス std::string m88100disasm::cio() @@ -314,7 +332,89 @@ m88100disasm::m5() default: break; } - return string_format("0x%02x", m); // ? + return string_format("#%d", m); +} + +// M5(,rS1) に対する代替ニーモニックを返す。empty なら代替ニーモニックなし。 +// 条件が 0(always false) でも .n かどうかがあるので nop とかにはしない。 +// 15(always true) は無条件 br{,.n} だがこれは戻り値 "true" を呼び出し側が +// 比較して処理すること。 +// 6 と 9 は使いみちがないので empty を返す。 +// reserved なビットが立っていても動作には影響はないが、ニーモニックとしては +// 不正なものとして表示するためここでは empty を返す。 +std::string +m88100disasm::alt_m5() +{ + // 0000 false + // 0001 gt0 r > 0 (float)r > +0 + // 0010 eq0 r == 0 (float)r == +0 + // 0011 ge0 r >= 0 (float)r >= +0 + // 0100 (float)r < -0 + // 0101 (float)r != 0 + // 0110 #6 + // 0111 r != 0x80000000 (float)r != -0 + // 1000 r == 0x80000000 (float)r == -0 + // 1001 #9 + // 1010 (float)r == 0 + // 1011 (float)r >= -0 + // 1100 lt0 r < 0 (float)r < +0 + // 1101 ne0 r != 0 (float)r != +0 + // 1110 le0 r <= 0 (float)r <= +0 + // 1111 true + + uint32 m = M5; + if (S1 == 0) { + if (m < 0x10) { + // r0 相手なら、下から 2bit 目が立っていれば true、 + // そうでなければ false の二択。 + if ((m & 0x02)) { + return "true"; + } else { + return "false"; + } + } + } else { + char rs[8]; + strlcpy(rs, rs1().c_str(), sizeof(rs)); + switch (m) { + case 0: + return "false"; + case 1: + return string_format("(%s>0|(float)%s>+0)", rs, rs); + case 2: + return string_format("(%s==0|(float)%s==+0)", rs, rs); + case 3: + return string_format("(%s>=0|(float)%s>=+0)", rs, rs); + case 4: + return string_format("((float)%s<-0)", rs); + case 5: + return string_format("((float)%s!=0)", rs); + case 7: + return string_format("(%s!=0x80000000)", rs); + case 8: + return string_format("(%s==0x80000000)", rs); + case 0xa: + return string_format("((float)%s==0)", rs); + case 0xb: + return string_format("((float)%s>=-0)", rs); + case 0xc: + return string_format("(%s<0|(float)%s<+0)", rs, rs); + case 0xd: + return string_format("(%s!=0|(float)%s!=+0)", rs, rs); + case 0xe: + return string_format("(%s<=0|(float)%s<=+0)", rs, rs); + + case 0xf: // always true + return "true"; + + case 6: + case 9: + default: // reserved + break; + } + } + + return ""; } std::string @@ -1076,24 +1176,39 @@ OP_DEF(bb1_n) } void -m88100disasm::ops_bcnd(std::string namebase) +m88100disasm::ops_bcnd(std::string n) { - name = namebase; + name = "bcnd" + n; arg0 = m5(); arg1 = rs1(); arg2 = d16(); + + const std::string cond = alt_m5(); + if (cond.empty()) { + // 空なら表現できないやつなので代替表現もなし + return; + } else if (cond == "true") { + // 無条件分岐 + altname = "br" + n; + altarg0 = arg2; + } else { + // 条件分岐 + altname = "br" + n; + altarg0 = cond; + altarg1 = arg2; + } } // 111010_MMMMMSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(bcnd) { - ops_bcnd("bcnd"); + ops_bcnd(""); } // 111011_MMMMMSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(bcnd_n) { - ops_bcnd("bcnd.n"); + ops_bcnd(".n"); } // 111100_DDDDDSSSSS_100000_wwwwwooooo @@ -1107,17 +1222,10 @@ OP_DEF(clr_1) if (DD == 0) { altname = "nop"; } else { + altname = "and"; altarg0 = rd(); altarg1 = rs1(); - auto w5 = W5 ?: 32; - if (w5 == 1) { - altname = "bitclr"; - altarg2 = string_format("#%d", O5); - } else { - // XXX 表記はもうちょっと考える… - altname = "bfclr"; - altarg2 = wo5(); - } + altarg2 = string_format("0x%08x", ~wo5mask()); } } @@ -1132,17 +1240,10 @@ OP_DEF(set_1) if (DD == 0) { altname = "nop"; } else { + altname = "or"; altarg0 = rd(); altarg1 = rs1(); - auto w5 = W5 ?: 32; - if (w5 == 1) { - altname = "bitset"; - altarg2 = string_format("#%d", O5); - } else { - // XXX 表記はもうちょっと考える… - altname = "bfset"; - altarg2 = wo5(); - } + altarg2 = string_format("0x%08x", wo5mask()); } }