--- nono/m88xx0/m88100disasm.cpp 2026/04/29 17:04:41 1.1.1.3 +++ nono/m88xx0/m88100disasm.cpp 2026/04/29 17:05:47 1.1.1.11 @@ -5,16 +5,18 @@ // #include "m88100disasm.h" +#include "debugger_memory.h" +#include "m88100.h" #include "m88100acc.h" -#include "bus.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(DebuggerMD *md_) - : inherited(md_) +m88100disasm::m88100disasm() { } @@ -25,26 +27,29 @@ m88100disasm::~m88100disasm() // 逆アセンブルを実行 bool -m88100disasm::Exec(saddr_t laddr) +m88100disasm::Exec(DebuggerMemoryStream *mem_) { - ExecInit(); + ExecInit(mem_); opX = 0; name.clear(); arg0.clear(); arg1.clear(); arg2.clear(); + altname.clear(); + altarg0.clear(); + altarg1.clear(); + altarg2.clear(); - xip = laddr.addr; + xip = mem->laddr.Addr(); - opX = peek(laddr); - uint32 op12 = ((opX >> 20) & 0x0fc0) | ((opX >> 10) & 0x003f); + opX = mem->Read(4); + uint32 op12 = M88100::op32_to_12(opX); switch (op12) { #include "m88100switch.inc" default: name = "illegal"; break; - //OP_FUNC(illegal); } // 出力文字列(ダンプ) @@ -63,21 +68,24 @@ m88100disasm::Exec(saddr_t laddr) // 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) + while (args.length() < argc * 4) args += " "; } args += arg1; + argc++; } if (!arg2.empty()) { - if (!args.empty()) { + if (argc != 0) { args += ","; - while (args.length() < 8) + while (args.length() < argc * 4) args += " "; } args += arg2; @@ -86,6 +94,60 @@ m88100disasm::Exec(saddr_t laddr) text += args; } + // 出力文字列(別名) + if (use_altname && !altname.empty()) { + if (altarg1.empty() && !altarg2.empty()) { + altarg1 = altarg2; + altarg2.clear(); + } + // {mov rn, rn} -> {nop} は無条件に置換できるのでここでやる + if (altname == "mov" && altarg0 == altarg1 && altarg2.empty()) { + altname = "nop"; + altarg0.clear(); + altarg1.clear(); + } + + alttext += "{" + altname; + + if (!altarg0.empty() || !altarg1.empty() || !altarg2.empty()) { + // オペランドがあればインデントする + int len = alttext.length(); + if (len < 8) { + alttext += std::string(8 - len, ' '); + } else { + alttext += ' '; + } + + // altarg0,1,2 の空でないやつを追加 + std::string altargs; + int altargc = 0; + if (!altarg0.empty()) { + altargs += altarg0; + altargc++; + } + if (!altarg1.empty()) { + if (altargc != 0) { + altargs += ','; + while (altargs.length() < altargc * 4) + altargs += ' '; + } + altargs += altarg1; + altargc++; + } + if (!altarg2.empty()) { + if (altargc != 0) { + altargs += ','; + while (altargs.length() < altargc * 4) + altargs += ' '; + } + altargs += altarg2; + } + + alttext += altargs; + } + alttext += '}'; + } + // 出力バイナリ列 // bin は vector。 bin.push_back( opX >> 24); @@ -96,18 +158,16 @@ m88100disasm::Exec(saddr_t laddr) return true; } -// ピーク (IP を進めずワードを取得する) -uint32 -m88100disasm::peek(const saddr_t& laddr) -{ - return md->PeekFetch(laddr); -} - // フィールド部品 +#define DD ((opX >> 21) & 0x1f) +#define S1 ((opX >> 16) & 0x1f) +#define S2 ( opX & 0x1f) #define B5 ((opX >> 21) & 0x1f) #define M5 ((opX >> 21) & 0x1f) #define W5 ((opX >> 5) & 0x1f) #define O5 ((opX ) & 0x1f) +#define CIO ((opX >> 8) & 0x03) +#define IMM16 (opX & 0x0000ffffU) #define VEC9 (opX & 0x000001ffU) #define D16 (((int32)(int16)opX) << 2) #define D26 (((int32)(opX << 6)) >> 4) @@ -115,19 +175,19 @@ m88100disasm::peek(const saddr_t& laddr) 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 @@ -142,6 +202,12 @@ m88100disasm::d16() return string_format("0x%08x", xip + D16); } +std::string +m88100disasm::d26() +{ + return string_format("0x%08x", xip + D26); +} + // 制御レジスタ名 std::string m88100disasm::crs() @@ -160,7 +226,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); // こうなのか? } } @@ -187,7 +253,7 @@ m88100disasm::fcrs() } else if (cr == 63) { return "fpcr"; } else { - return string_format("fcr%d", cr); + return string_format("fcr%u", cr); } } @@ -216,7 +282,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; } // キャリーサフィックス @@ -236,7 +314,7 @@ m88100disasm::cio() std::string m88100disasm::b5() { - return string_format("#%d", B5); + return string_format("#%u", B5); } std::string @@ -253,7 +331,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 @@ -269,148 +429,123 @@ m88100disasm::op_unimpl() name = "unimplemented"; } -// 000000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn -OP_DEF(xmem_bu_imm) +// ld_imm, st_imm, xmem_imm の共通部 +// namebase にはサイズプレフィックスを含む。 +void +m88100disasm::ops_ldst_imm(const std::string& namebase) { - name = "xmem.bu"; + name = namebase; arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + altname = namebase; + altarg0 = rd(); + if (IMM16 == 0) { + altarg1 = rs1(); + } else { + altarg1 = rs1() + "," + imm16(); + } + // 3文字目が 'a' になるのは lda しかない + if (namebase[2] != 'a') { + altarg1 = "(" + altarg1 + ")"; + } +} + +// 000000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn +OP_DEF(xmem_bu_imm) +{ + ops_ldst_imm("xmem.bu"); } // 000001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(xmem_w_imm) { - name = "xmem"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("xmem"); } // 000010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_hu_imm) { - name = "ld.hu"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld.hu"); } // 000011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_bu_imm) { - name = "ld.bu"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld.bu"); } // 000100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_d_imm) { - name = "ld.d"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld.d"); } // 000101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_w_imm) { - name = "ld"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld"); } // 000110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_h_imm) { - name = "ld.h"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld.h"); } // 000111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(ld_b_imm) { - name = "ld.b"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("ld.b"); } // 001000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(st_d_imm) { - name = "st.d"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("st.d"); } // 001001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(st_w_imm) { - name = "st"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("st"); } // 001010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(st_h_imm) { - name = "st.h"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("st.h"); } // 001011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(st_b_imm) { - name = "st.b"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("st.b"); } // 001100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(lda_d_imm) { - name = "lda.d"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("lda.d"); } // 001101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(lda_w_imm) { - name = "lda"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("lda"); } // 001110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(lda_h_imm) { - name = "lda.h"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("lda.h"); } // 001111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn OP_DEF(lda_b_imm) { - name = "lda.b"; - arg0 = rd(); - arg1 = rs1(); - arg2 = imm16(); + ops_ldst_imm("lda.b"); } // 010000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -420,6 +555,27 @@ OP_DEF(and_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm clr rd + // rd rd #imm and rd, #ffff'imm + // rd s1 #imm and rd, s1, #ffff'imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0xffff%04x", IMM16); + } } // 010001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -429,6 +585,27 @@ OP_DEF(and_u_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm clr rd + // rd rd #imm and rd, #imm'ffff + // rd s1 #imm and rd, s1, #imm'ffff + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16() + "ffff"; + } } // 010010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -438,6 +615,27 @@ OP_DEF(mask_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm clr rd + // rd rd #imm and rd, #0000'imm + // rd s1 #imm and rd, s1, #0000'imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); + } } // 010011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -447,6 +645,27 @@ OP_DEF(mask_u_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm clr rd + // rd rd #imm and rd, #imm'0000 + // rd s1 #imm and rd, s1, #imm'0000 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16() + "0000"; + } } // 010100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -456,6 +675,28 @@ OP_DEF(xor_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #imm + // rd rd #imm xor rd, #imm + // rd s1 #imm xor rd, s1, #imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = imm16(); + } else { + altname = "xor"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16(); + } } // 010101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -465,6 +706,28 @@ OP_DEF(xor_u_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #imm'0000 + // rd rd #imm xor rd, #imm'0000 + // rd s1 #imm xor rd, s1, #imm'0000 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = imm16() + "0000"; + } else { + altname = "xor"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16() + "0000"; + } } // 010110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -474,6 +737,28 @@ OP_DEF(or_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #imm + // rd rd #imm or rd, #imm + // rd s1 #imm or rd, s1, #imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = imm16(); + } else { + altname = "or"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16(); + } } // 010111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -483,6 +768,28 @@ OP_DEF(or_u_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #imm'0000 + // rd rd #imm or rd, #imm'0000 + // rd s1 #imm or rd, s1, #imm'0000 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = imm16() + "0000"; + } else { + altname = "or"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = imm16() + "0000"; + } } // 011000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -492,6 +799,28 @@ OP_DEF(addu_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #0000'imm + // rd rd #imm addu rd, #0000'imm + // rd s1 #imm addu rd, s1, #0000'imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = string_format("#0x0000%04x", IMM16); + } else { + altname = "addu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); + } } // 011001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -501,6 +830,28 @@ OP_DEF(subu_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 #imm mov rd, #-imm + // rd rd #imm subu rd, #0000'imm + // rd s1 #imm subu rd, s1, #0000'imm + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = string_format("#0x%08x", -(int32)(uint32)IMM16); + } else { + altname = "subu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); + } } // 011010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -510,6 +861,14 @@ OP_DEF(divu_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // 例外発生の可能性があるので r0 を含んでいたとしても別名にしない + altname = "divu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); } // 011011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -519,6 +878,14 @@ OP_DEF(mul_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // 例外発生の可能性があるので r0 を含んでいたとしても別名にしない + altname = "mul"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); } // 011100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -528,6 +895,14 @@ OP_DEF(add_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // 例外発生の可能性があるので r0 を含んでいたとしても別名にしない + altname = "adds"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); } // 011101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -537,6 +912,14 @@ OP_DEF(sub_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // 例外発生の可能性があるので r0 を含んでいたとしても別名にしない + altname = "subs"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); } // 011110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -546,6 +929,14 @@ OP_DEF(div_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + // 例外発生の可能性があるので r0 を含んでいたとしても別名にしない + altname = "div"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#0x0000%04x", IMM16); } // 011111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn @@ -555,6 +946,15 @@ OP_DEF(cmp_imm) arg0 = rd(); arg1 = rs1(); arg2 = imm16(); + + if (DD == 0) { + altname = "nop"; + } else { + altname = "cmp"; + altarg0 = rd(); + altarg1 = rs1(); + altarg2 = string_format("#0x0000%04x", IMM16); + } } // 100000_DDDDDzzzzz_01000n_nnnnnzzzzz @@ -716,28 +1116,28 @@ OP_DEF(fdiv) OP_DEF(br) { name = "br"; - arg0 = string_format("%08x", xip + D26); + arg0 = d26(); } // 110001_nnnnnnnnnn_nnnnnn_nnnnnnnnnn OP_DEF(br_n) { name = "br.n"; - arg0 = string_format("%08x", xip + D26); + arg0 = d26(); } // 110010_nnnnnnnnnn_nnnnnn_nnnnnnnnnn OP_DEF(bsr) { name = "bsr"; - arg0 = string_format("%08x", xip + D26); + arg0 = d26(); } // 110011_nnnnnnnnnn_nnnnnn_nnnnnnnnnn OP_DEF(bsr_n) { name = "bsr.n"; - arg0 = string_format("%08x", xip + D26); + arg0 = d26(); } // bb の共通部 @@ -775,24 +1175,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 @@ -802,6 +1217,15 @@ OP_DEF(clr_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + if (DD == 0) { + altname = "nop"; + } else { + altname = "and"; + altarg0 = rd(); + altarg1 = rs1(); + altarg2 = string_format("0x%08x", ~wo5mask()); + } } // 111100_DDDDDSSSSS_100010_wwwwwooooo @@ -811,6 +1235,15 @@ OP_DEF(set_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + if (DD == 0) { + altname = "nop"; + } else { + altname = "or"; + altarg0 = rd(); + altarg1 = rs1(); + altarg2 = string_format("0x%08x", wo5mask()); + } } // 111100_DDDDDSSSSS_100100_wwwwwooooo @@ -820,6 +1253,37 @@ OP_DEF(ext_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 w:o clr rd + // rd rd 32:o asr rd, #o + // rd s1 32:o asr rd, s1, #o + // rd rd w:o bfexts rd, w:o + // rd s1 w:o bfexts rd, s1, w:o + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (W5 == 0 || W5 + O5 >= 32) { + // W5 + O5 >= 32 なら単純なシフトに相当 + altname = "asr"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#%u", O5); + } else { + altname = "bfexts"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_100110_wwwwwooooo @@ -829,6 +1293,37 @@ OP_DEF(extu_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 w:o clr rd + // rd rd 32:o lsr rd, #o + // rd s1 32:o lsr rd, s1, #o + // rd rd w:o bfextu rd, w:o + // rd s1 w:o bfextu rd, s1, w:o + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (W5 == 0 || W5 + O5 >= 32) { + // W5 + O5 >= 32 なら単純なシフトに相当 + altname = "lsr"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#%u", O5); + } else { + altname = "bfextu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_101000_wwwwwooooo @@ -838,6 +1333,38 @@ OP_DEF(mak_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + // rd s1 imm + // ---------- + // r0 * * nop + // rd r0 w:o clr rd + // rd rd 32:o lsl rd, #o + // rd s1 32:o lsl rd, s1, #o + // rd rd w:o bfmak rd, w:o + // rd s1 w:o bfmak rd, s1, w:o + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (W5 == 0 || W5 + O5 >= 32) { + // W5 + O5 >= 32 なら単純なシフトに相当 + altname = "lsl"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#%u", O5); + } else { + // XXX 名前から動作が想像しづらいのがつらいのだが、とりあえず後回し + altname = "bfmak"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_101010_zzzzzooooo @@ -846,7 +1373,47 @@ OP_DEF(rot_1) name = "rot"; arg0 = rd(); arg1 = rs1(); - arg2 = string_format("<%d>", O5); + arg2 = string_format("<%u>", O5); + + // rd s1 offset + // ---------- + // r0 * * nop + // rd rd #0 nop + // rd r0 * clr rd + // rd rd 1-16 ror rd, #1-16 + // rd s1 1-16 ror rd, s1, #1-16 + // rd rd 17-31 rol rd, #1-15 + // rd s1 17-31 rol rd, s1, #1-15 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (O5 == 0) { + if (DD == S1) { + altname = "nop"; + } else { + altname = "clr"; + altarg0 = rd(); + } + } else { + // どう表記するのがいいかは状況によるかも知れないが + // 1-16ビット(右)ローテートなら ror #0-16、 + // 17-31ビット(右)ローテートなら rol #1-15 としてみる + auto offset = O5; + if (offset > 16) { + altname = "rol"; + offset = 32 - offset; + } else { + altname = "ror"; + } + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = string_format("#%u", offset); + } } void @@ -867,16 +1434,16 @@ OP_DEF(tb0) // 111100_bbbbbSSSSS_110110_0vvvvvvvvv OP_DEF(tb1) { - if (opt_alias && m88100opf_S1(opX) == 0) { + ops_tb("tb1"); + + if (S1 == 0) { // tb1 *,r0,* はパイプライン同期を目的として使われる。 // この形式はトラップは発生しない。 if (VEC9 < 128) { - name = "ssync"; + altname = "ssync"; } else { - name = "usync"; + altname = "usync"; } - } else { - ops_tb("tb1"); } } @@ -890,13 +1457,14 @@ OP_DEF(tcnd) } // ld_reg, st_reg, xmem_reg の共通部 +// size は ".bu" などドットを含むサイズプレフィックス。 void -m88100disasm::ops_ldst_reg(std::string namebase) +m88100disasm::ops_ldst_reg(const std::string& namebase, std::string size) { uint32 u = (opX >> 8) & 1; uint32 scaled = (opX >> 9) & 1; - name = namebase; + name = namebase + size; if (u) { name += ".usr"; } @@ -907,106 +1475,144 @@ m88100disasm::ops_ldst_reg(std::string n } else { arg1 += "[" + rs2() + "]"; } + + // 別名 + // ld.bu.usr はサフィックスの使い方が節操なさすぎるし + // ld と ld.usr はわりと違う命令なので、違う命令のように見せる。 + altname = namebase; + if (u) { + altname += "usr"; + } + altname += size; + altarg0 = rd(); + + // メモリアクセスはは括弧を付けて表す。 + // lda はメモリアクセスではないので括弧なしのまま。 + // + // rs1 rs2 scaled + // -------------- + // r* r0 * ld rd, (r*) + // r0 s2 no ld rd, (s2) + // s1 s2 no ld rd, (s1,s2) + // r0 s2 yes ld rd, (r0[s2]) + // s1 s2 yes ld rd, (s1[s2]) + if (S2 == 0) { + altarg1 = rs1(); + } else { + if (scaled == 0) { + if (S1 == 0) { + altarg1 = rs2(); + } else { + altarg1 = rs1() + "," + rs2(); + } + } else { + altarg1 = rs1() + "[" + rs2() + "]"; + } + } + // 3文字目が 'a' になるのは lda しかない + if (namebase[2] != 'a') { + altarg1 = "(" + altarg1 + ")"; + } } // 111101_DDDDDSSSSS_000000_xU000sssss OP_DEF(xmem_bu) { - ops_ldst_reg("xmem.bu"); + ops_ldst_reg("xmem", ".bu"); } // 111101_DDDDDSSSSS_000001_xU000sssss OP_DEF(xmem_w) { - ops_ldst_reg("xmem"); + ops_ldst_reg("xmem", ""); } // 111101_DDDDDSSSSS_000010_xU000sssss OP_DEF(ld_hu) { - ops_ldst_reg("ld.hu"); + ops_ldst_reg("ld", ".hu"); } // 111101_DDDDDSSSSS_000011_xU000sssss OP_DEF(ld_bu) { - ops_ldst_reg("ld.bu"); + ops_ldst_reg("ld", ".bu"); } // 111101_DDDDDSSSSS_000100_xU000sssss OP_DEF(ld_d) { - ops_ldst_reg("ld.d"); + ops_ldst_reg("ld", ".d"); } // 111101_DDDDDSSSSS_000101_xU000sssss OP_DEF(ld_w) { - ops_ldst_reg("ld"); + ops_ldst_reg("ld", ""); } // 111101_DDDDDSSSSS_000110_xU000sssss OP_DEF(ld_h) { - ops_ldst_reg("ld.h"); + ops_ldst_reg("ld", ".h"); } // 111101_DDDDDSSSSS_000111_xU000sssss OP_DEF(ld_b) { - ops_ldst_reg("ld.b"); + ops_ldst_reg("ld", ".b"); } // 111101_DDDDDSSSSS_001000_xU000sssss OP_DEF(st_d) { - ops_ldst_reg("st.d"); + ops_ldst_reg("st", ".d"); } // 111101_DDDDDSSSSS_001001_xU000sssss OP_DEF(st_w) { - ops_ldst_reg("st"); + ops_ldst_reg("st", ""); } // 111101_DDDDDSSSSS_001010_xU000sssss OP_DEF(st_h) { - ops_ldst_reg("st.h"); + ops_ldst_reg("st", ".h"); } // 111101_DDDDDSSSSS_001011_xU000sssss OP_DEF(st_b) { - ops_ldst_reg("st.b"); + ops_ldst_reg("st", ".b"); } // 111101_DDDDDSSSSS_001100_xU000sssss OP_DEF(lda_d) { // XXX bit8 が 1 だとどうなるのか - ops_ldst_reg("lda.d"); + ops_ldst_reg("lda", ".d"); } // 111101_DDDDDSSSSS_001101_xU000sssss OP_DEF(lda_w) { // XXX bit8 が 1 だとどうなるのか - ops_ldst_reg("lda"); + ops_ldst_reg("lda", ""); } // 111101_DDDDDSSSSS_001110_xU000sssss OP_DEF(lda_h) { // XXX bit8 が 1 だとどうなるのか - ops_ldst_reg("lda.h"); + ops_ldst_reg("lda", ".h"); } // 111101_DDDDDSSSSS_001111_xU000sssss OP_DEF(lda_b) { // XXX bit8 が 1 だとどうなるのか - ops_ldst_reg("lda.b"); + ops_ldst_reg("lda", ".b"); } // 111101_DDDDDSSSSS_010000_00000sssss @@ -1016,6 +1622,36 @@ OP_DEF(and) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 * clr rd + // rd * r0 clr rd + // rd rd rd nop + // rd s1 s1 mov rd, s1 + // rd rd s2 and rd, s2 + // rd s1 s2 and rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0 || S2 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S1 == S2) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + if (DD != S2) { + altarg2 = rs2(); + } + } } // 111101_DDDDDSSSSS_010001_00000sssss @@ -1025,6 +1661,36 @@ OP_DEF(and_c) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 * clr rd + // rd s1 r0 mov rd, s1 + // rd rd r0 nop + // rd s1 s1 clr rd + // rd s1 s2 and rd, s1, ~s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else if (S1 == S2) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "and"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = "~" + rs2(); + } } // 111101_DDDDDSSSSS_010100_00000sssss @@ -1034,6 +1700,38 @@ OP_DEF(xor) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 s1 clr rd + // rd r0 s2 mov rd, s2 + // rd s1 r0 mov rd, s1 + // rd s1 s2 xor rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == S2) { + altname = "clr"; + altarg0 = rd(); + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs2(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "xor"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + if (DD != S2) { + altarg2 = rs2(); + } + } } // 111101_DDDDDSSSSS_010101_00000sssss @@ -1043,21 +1741,82 @@ OP_DEF(xor_c) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 s1 mov rd, #0xffffffff + // rd r0 s2 not rd, s2 + // rd s1 r0 not rd, s1 + // rd s1 s2 xor rd, s1, ~s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == S2) { + altname = "mov"; + altarg0 = rd(); + altarg1 = "#0xffffffff"; + } else if (S1 == 0) { + altname = "not"; + altarg0 = rd(); + if (DD != S2) { + altarg1 = rs2(); + } + } else if (S2 == 0) { + altname = "not"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + } else { + altname = "xor"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = "~" + rs2(); + } } // 111101_DDDDDSSSSS_010110_00000sssss OP_DEF(or) { - if (opt_alias && m88100opf_D(opX) == 0) { - // or r0,*,* は nop とする - // and とかも nop だが motolora が サンプルコードで - // or r0,r0,r0 を nop として使っているため、or が一般的なようだ。 - name = "nop"; + name = "or"; + arg0 = rd(); + arg1 = rs1(); + arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 r0 clr rd + // rd s1 s1 mov rd, s1 + // rd s1 r0 mov rd, s1 + // rd r0 s2 mov rd, s2 + // rd s1 s2 or rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0 && S2 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S1 == S2 || S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else if (S1 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs2(); } else { - name = "or"; - arg0 = rd(); - arg1 = rs1(); - arg2 = rs2(); + altname = "or"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + if (DD != S2) { + altarg2 = rs2(); + } } } @@ -1068,6 +1827,35 @@ OP_DEF(or_c) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 r0 mov rd, #0xffffffff + // rd s1 s1 mov rd, #0xffffffff + // rd r0 s2 not rd, s2 + // rd s1 s2 or rd, s1, ~s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0 || S1 == S2) { + altname = "mov"; + altarg0 = rd(); + altarg1 = "#0xffffffff"; + } else if (S1 == 0) { + altname = "not"; + altarg0 = rd(); + if (DD != S2) { + altarg1 = rs2(); + } + } else { + altname = "or"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = "~" + rs2(); + } } // 111101_DDDDDSSSSS_011000_nn000sssss @@ -1077,6 +1865,57 @@ OP_DEF(addu) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + if (CIO == 0) { + // addu 無印の場合 + // + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 r0 clr rd + // rd s1 r0 mov rd, s1 + // rd r0 s2 mov rd, s2 + // rd s1 s2 add rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0 && S2 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S1 == 0 || S2 == 0) { + altname = "mov"; + altarg0 = rd(); + if (S1 == 0) { + altarg1 = rs2(); + } + if (S2 == 0) { + altarg1 = rs1(); + } + } else if (DD == S1 && DD == S2) { + altname = "addu"; + altarg0 = rd(); + altarg1 = rs2(); + } else { + altname = "addu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + if (DD != S2) { + altarg2 = rs2(); + } + } + } else { + // addu キャリー込み .ci/co/cio のほうは 2 オペランドへの省略のみ。 + // XXX addu の2項は交換可なので addu r1, r2, r1 は addu r1, r2 と + // 省略できていいがそれには未対応。 + altname = "addu" + cio(); + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_011001_nn000sssss @@ -1086,6 +1925,43 @@ OP_DEF(subu) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + if (CIO == 0) { + // subu 無印の場合 + // + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 s1 clr rd + // rd s1 r0 mov rd, s1 + // rd s1 s2 subu rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == S2) { + altname = "clr"; + altarg0 = rd(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "subu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } + } else { + // subu キャリー込み .ci/co/cio のほうは 2 オペランドへの省略のみ。 + altname = "subu" + cio(); + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_011010_zz000sssss @@ -1095,6 +1971,14 @@ OP_DEF(divu) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // 例外が起きる可能性があるので 2オペランドへの省略のみ + altname = "divu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); } // 111101_DDDDDSSSSS_011011_zz000sssss @@ -1104,6 +1988,14 @@ OP_DEF(mul) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // 例外が起きる可能性があるので 2オペランドへの省略のみ + altname = "mul"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); } // 111101_DDDDDSSSSS_011100_nn000sssss @@ -1113,6 +2005,63 @@ OP_DEF(add) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + if (CIO == 0) { + // add 無印は符号付きなので、より明示的な adds を使う。 + // 符号付き加算ではオーバーフローが起きる可能性があるため、 + // rD が r0 であってもただちに nop とはならない。 + // 一方 r0 を加算する場合は何も起きないので圧縮表記したい。 + + // rd s1 s2 + // ---------- + // rd r0 r0 clr rd + // r0 r0 rd nop + // rd r0 rd nop + // rd r0 s2 mov rd, s2 + // rd rd r0 nop + // rd s1 r0 mov rd, s1 + // rd s1 s2 adds rd, s1, s2 + + if (S1 == 0 && S2 == 0) { + if (DD == 0) { + altname = "nop"; + } else { + altname = "clr"; + altarg0 = rd(); + } + } else if (S1 == 0) { + if (DD == 0) { + altname = "nop"; + } else { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs2(); + } + } else if (S2 == 0) { + if (DD == 0) { + altname = "nop"; + } else { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } + } else { + altname = "adds"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } + } else { + // adds キャリー込み .ci/co/cio のほうは 2 オペランドへの省略のみ。 + altname = "adds" + cio(); + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_011101_nn000sssss @@ -1122,6 +2071,52 @@ OP_DEF(sub) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + if (CIO == 0) { + // sub 無印は符号付きなので、より明示的な subs を使う。 + // 符号付き減算ではオーバーフローが起きる可能性があるため、 + // rD が r0 であってもただちに nop とはならない。 + // 一方 r0 を減算する場合は何も起きないので圧縮表記したい。 + + // rd s1 s2 + // ---------- + // rd rd r0 nop + // rd r0 r0 clr rd + // rd s1 r0 mov rd, s1 + // rd s1 s2 subs rd, s1, s2 + + if (S1 == 0 && S2 == 0) { + if (DD == 0) { + altname = "nop"; + } else { + altname = "clr"; + altarg0 = rd(); + } + } else if (S2 == 0) { + if (DD == 0) { + altname = "nop"; + } else { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } + } else { + altname = "subs"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } + } else { + // subs キャリー込み .ci/co/cio のほうは 2 オペランドへの省略のみ。 + altname = "subs" + cio(); + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_011110_zz000sssss @@ -1131,6 +2126,14 @@ OP_DEF(div) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // 例外が起きる可能性があるので 2オペランドへの省略のみ + altname = "div"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); } // 111101_DDDDDSSSSS_011111_zz000sssss @@ -1140,6 +2143,11 @@ OP_DEF(cmp) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // cmp r0,*,* 以外は別表記を用意する必要ない + if (DD == 0) { + altname = "nop"; + } } // 111101_DDDDDSSSSS_100000_00000sssss @@ -1149,6 +2157,32 @@ OP_DEF(clr_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 s2 clr rd + // rd s1 r0 mov rd, s1 + // rd rd s2 bfclr rd, s2 + // rd s1 s2 bfclr rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "bfclr"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_100010_00000sssss @@ -1158,6 +2192,28 @@ OP_DEF(set_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 r0 mov rd, #0xffffffff + // rd rd s2 bfset rd, s2 + // rd s1 s2 bfset rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = "#0xffffffff"; + } else { + altname = "bfset"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_100100_00000sssss @@ -1167,6 +2223,28 @@ OP_DEF(ext_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 r0 mov rd, s1 + // rd rd s2 bfexts rd, s2 + // rd s1 s2 bfexts rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "bfexts"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_100110_00000sssss @@ -1176,6 +2254,28 @@ OP_DEF(extu_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd s1 r0 mov rd, s1 + // rd rd s2 bfextu rd, s2 + // rd s1 s2 bfextu rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "bfextu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_101000_00000sssss @@ -1185,6 +2285,31 @@ OP_DEF(mak_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 s2 clr rd + // rd s1 r0 mov rd, s1 + // rd s1 s2 bfmak rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "bfmak"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_DDDDDSSSSS_101010_00000sssss @@ -1194,6 +2319,31 @@ OP_DEF(rot_2) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // rd s1 s2 + // ---------- + // r0 * * nop + // rd r0 s2 clr rd + // rd s1 r0 mov rd, s1 + // rd s1 s2 ror rd, s1, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S1 == 0) { + altname = "clr"; + altarg0 = rd(); + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = rs1(); + } else { + altname = "ror"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = rs2(); + } } // 111101_zzzzzzzzzz_110000_00000sssss @@ -1230,6 +2380,24 @@ OP_DEF(ff1) name = "ff1"; arg0 = rd(); arg1 = rs2(); + + // rd s2 + // ------ + // r0 * nop + // rd r0 mov rd, #32 + // rd s2 ff1 rd, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0) { + altname = "mov"; + altarg0 = rd(); + altarg1 = "#32"; + } else { + altname = "ff1"; + altarg0 = rd(); + altarg1 = rs2(); + } } // 111101_DDDDDzzzzz_111011_00000sssss @@ -1238,6 +2406,23 @@ OP_DEF(ff0) name = "ff0"; arg0 = rd(); arg1 = rs2(); + + // rd s2 + // ------ + // r0 * nop + // rd r0 clr rd + // rd s2 ff0 rd, s2 + + if (DD == 0) { + altname = "nop"; + } else if (S2 == 0) { + altname = "clr"; + altarg0 = rd(); + } else { + altname = "ff0"; + altarg0 = rd(); + altarg1 = rs2(); + } } // 111101_zzzzzzzzzz_111111_0000000000 @@ -1262,14 +2447,11 @@ OP_DEF(tbnd_2) arg2 = imm16(); } -// 111111_zzzzzzzzzz_000011_zzzzzzzzzz -OP_DEF(getc) +// 111111_DDDDDSSSSS_000001_00nnnnnnnn +OP_DEF(doscall) { - name = "getc-emulator"; -} - -// 111111_zzzzzzzzzz_000100_zzzzzzzzzz -OP_DEF(putc) -{ - name = "putc-emulator"; + name = "doscall"; + arg0 = rd(); + arg1 = rs1(); + arg2 = string_format("#0x%02x", (opX & 0xff)); }