--- nono/m88xx0/m88100disasm.cpp 2026/04/29 17:04:57 1.1.1.7 +++ nono/m88xx0/m88100disasm.cpp 2026/04/29 17:05:56 1.1.1.12 @@ -5,19 +5,20 @@ // #include "m88100disasm.h" +#include "debugger_memory.h" +#include "m88100.h" #include "m88100acc.h" -#include "bus.h" -#include "config.h" +#include "mystring.h" #define OP_DEF(name) void __CONCAT(m88100disasm::op_,name)() #define OP_FUNC(name) __CONCAT(op_,name)() +// 別ニーモニックを使うなら true にする (外部から指定する) +/*static*/ bool m88100disasm::use_altname; + // コンストラクタ -m88100disasm::m88100disasm(DebuggerMemoryStream& mem_) - : inherited(mem_) +m88100disasm::m88100disasm() { - // XXX どこでやるか - use_altname = gConfig->Find(".m88k-altname").AsInt(); } // デストラクタ @@ -27,9 +28,9 @@ m88100disasm::~m88100disasm() // 逆アセンブルを実行 bool -m88100disasm::Exec() +m88100disasm::Exec(DebuggerMemoryStream *mem_) { - ExecInit(); + ExecInit(mem_); opX = 0; name.clear(); @@ -41,16 +42,15 @@ m88100disasm::Exec() altarg1.clear(); altarg2.clear(); - xip = (uint32)mem.laddr; + xip = mem->laddr.Addr(); - 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: name = "illegal"; break; - //OP_FUNC(illegal); } // 出力文字列(ダンプ) @@ -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; @@ -170,19 +176,19 @@ m88100disasm::Exec() std::string m88100disasm::rd() { - return string_format("r%d", (opX >> 21) & 0x1f); + return string_format("r%u", (opX >> 21) & 0x1f); } std::string m88100disasm::rs1() { - return string_format("r%d", (opX >> 16) & 0x1f); + return string_format("r%u", (opX >> 16) & 0x1f); } std::string m88100disasm::rs2() { - return string_format("r%d", (opX ) & 0x1f); + return string_format("r%u", (opX ) & 0x1f); } std::string @@ -221,7 +227,7 @@ m88100disasm::crs() if (cr < countof(crnames)) { return std::string(crnames[cr]); } else { - return string_format("cr%d", cr); // こうなのか? + return string_format("cr%u", cr); // こうなのか? } } @@ -248,7 +254,7 @@ m88100disasm::fcrs() } else if (cr == 63) { return "fpcr"; } else { - return string_format("fcr%d", cr); + return string_format("fcr%u", cr); } } @@ -277,7 +283,19 @@ m88100disasm::wo5() { uint32 w5 = W5 ?: 32; uint32 o5 = O5; - return string_format("%d<%d>", w5, o5); + return string_format("%u<%u>", w5, o5); +} + +// "Width" 形式をビットマスク形式(数値)にして返す +uint32 +m88100disasm::wo5mask() +{ + uint32 w5 = W5 ?: 32; + uint32 o5 = O5; + + uint64 mask = (1ULL << w5) - 1; + mask <<= o5; + return (uint32)mask; } // キャリーサフィックス @@ -297,7 +315,7 @@ m88100disasm::cio() std::string m88100disasm::b5() { - return string_format("#%d", B5); + return string_format("#%u", B5); } std::string @@ -314,7 +332,89 @@ m88100disasm::m5() default: break; } - return string_format("0x%02x", m); // ? + return string_format("#%u", 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()); } } @@ -1175,7 +1276,7 @@ OP_DEF(ext_1) if (DD != S1) { altarg1 = rs1(); } - altarg2 = string_format("#%d", O5); + altarg2 = string_format("#%u", O5); } else { altname = "bfexts"; altarg0 = rd(); @@ -1215,7 +1316,7 @@ OP_DEF(extu_1) if (DD != S1) { altarg1 = rs1(); } - altarg2 = string_format("#%d", O5); + altarg2 = string_format("#%u", O5); } else { altname = "bfextu"; altarg0 = rd(); @@ -1255,7 +1356,7 @@ OP_DEF(mak_1) if (DD != S1) { altarg1 = rs1(); } - altarg2 = string_format("#%d", O5); + altarg2 = string_format("#%u", O5); } else { // XXX 名前から動作が想像しづらいのがつらいのだが、とりあえず後回し altname = "bfmak"; @@ -1273,7 +1374,7 @@ OP_DEF(rot_1) name = "rot"; arg0 = rd(); arg1 = rs1(); - arg2 = string_format("<%d>", O5); + arg2 = string_format("<%u>", O5); // rd s1 offset // ---------- @@ -1312,7 +1413,7 @@ OP_DEF(rot_1) if (DD != S1) { altarg1 = rs1(); } - altarg2 = string_format("#%d", offset); + altarg2 = string_format("#%u", offset); } }