--- nono/m88xx0/m88100disasm.cpp 2026/04/29 17:04:52 1.1.1.6 +++ nono/m88xx0/m88100disasm.cpp 2026/04/29 17:04:57 1.1.1.7 @@ -7,6 +7,7 @@ #include "m88100disasm.h" #include "m88100acc.h" #include "bus.h" +#include "config.h" #define OP_DEF(name) void __CONCAT(m88100disasm::op_,name)() #define OP_FUNC(name) __CONCAT(op_,name)() @@ -15,6 +16,8 @@ m88100disasm::m88100disasm(DebuggerMemoryStream& mem_) : inherited(mem_) { + // XXX どこでやるか + use_altname = gConfig->Find(".m88k-altname").AsInt(); } // デストラクタ @@ -33,6 +36,10 @@ m88100disasm::Exec() arg0.clear(); arg1.clear(); arg2.clear(); + altname.clear(); + altarg0.clear(); + altarg1.clear(); + altarg2.clear(); xip = (uint32)mem.laddr; @@ -85,6 +92,57 @@ m88100disasm::Exec() 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; + if (!altarg0.empty()) { + altargs += altarg0; + } + if (!altarg1.empty()) { + if (!altargs.empty()) { + altargs += ','; + while (altargs.length() % 4 != 0) + altargs += ' '; + } + altargs += altarg1; + } + if (!altarg2.empty()) { + if (!altargs.empty()) { + altargs += ','; + while (altargs.length() % 4 != 0) + altargs += ' '; + } + altargs += altarg2; + } + + alttext += altargs; + } + alttext += '}'; + } + // 出力バイナリ列 // bin は vector。 bin.push_back( opX >> 24); @@ -96,10 +154,15 @@ m88100disasm::Exec() } // フィールド部品 +#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) @@ -276,6 +339,18 @@ m88100disasm::ops_ldst_imm(const std::st 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 @@ -381,6 +456,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 @@ -390,6 +486,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 @@ -399,6 +516,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 @@ -408,6 +546,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 @@ -417,6 +576,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 @@ -426,6 +607,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 @@ -435,6 +638,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 @@ -444,6 +669,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 @@ -453,6 +700,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 @@ -462,6 +731,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 @@ -471,6 +762,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 @@ -480,6 +779,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 @@ -489,6 +796,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 @@ -498,6 +813,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 @@ -507,6 +830,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 @@ -516,6 +847,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 @@ -763,6 +1103,22 @@ OP_DEF(clr_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + if (DD == 0) { + altname = "nop"; + } else { + altarg0 = rd(); + altarg1 = rs1(); + auto w5 = W5 ?: 32; + if (w5 == 1) { + altname = "bitclr"; + altarg2 = string_format("#%d", O5); + } else { + // XXX 表記はもうちょっと考える… + altname = "bfclr"; + altarg2 = wo5(); + } + } } // 111100_DDDDDSSSSS_100010_wwwwwooooo @@ -772,6 +1128,22 @@ OP_DEF(set_1) arg0 = rd(); arg1 = rs1(); arg2 = wo5(); + + if (DD == 0) { + altname = "nop"; + } else { + altarg0 = rd(); + altarg1 = rs1(); + auto w5 = W5 ?: 32; + if (w5 == 1) { + altname = "bitset"; + altarg2 = string_format("#%d", O5); + } else { + // XXX 表記はもうちょっと考える… + altname = "bfset"; + altarg2 = wo5(); + } + } } // 111100_DDDDDSSSSS_100100_wwwwwooooo @@ -781,6 +1153,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("#%d", O5); + } else { + altname = "bfexts"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_100110_wwwwwooooo @@ -790,6 +1193,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("#%d", O5); + } else { + altname = "bfextu"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_101000_wwwwwooooo @@ -799,6 +1233,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("#%d", O5); + } else { + // XXX 名前から動作が想像しづらいのがつらいのだが、とりあえず後回し + altname = "bfmak"; + altarg0 = rd(); + if (DD != S1) { + altarg1 = rs1(); + } + altarg2 = wo5(); + } } // 111100_DDDDDSSSSS_101010_zzzzzooooo @@ -808,6 +1274,46 @@ OP_DEF(rot_1) arg0 = rd(); arg1 = rs1(); arg2 = string_format("<%d>", 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("#%d", offset); + } } void @@ -828,16 +1334,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"); } } @@ -851,13 +1357,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"; } @@ -868,106 +1375,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 @@ -977,6 +1522,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 @@ -986,6 +1561,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 @@ -995,6 +1600,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 @@ -1004,21 +1641,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(); + } } } @@ -1029,6 +1727,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 @@ -1038,6 +1765,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 @@ -1047,6 +1825,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 @@ -1056,6 +1871,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 @@ -1065,6 +1888,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 @@ -1074,6 +1905,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 @@ -1083,6 +1971,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 @@ -1092,6 +2026,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 @@ -1101,6 +2043,11 @@ OP_DEF(cmp) arg0 = rd(); arg1 = rs1(); arg2 = rs2(); + + // cmp r0,*,* 以外は別表記を用意する必要ない + if (DD == 0) { + altname = "nop"; + } } // 111101_DDDDDSSSSS_100000_00000sssss @@ -1110,6 +2057,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 @@ -1119,6 +2092,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 @@ -1128,6 +2123,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 @@ -1137,6 +2154,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 @@ -1146,6 +2185,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 @@ -1155,6 +2219,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 @@ -1191,6 +2280,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 @@ -1199,6 +2306,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 @@ -1223,14 +2347,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)); }