From 234a196120aa89052cf8f1b76a4c886d44b9b654 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Mon, 11 Oct 2021 20:31:02 +0300 Subject: tms32082: rewrote the PP disassembler --- src/devices/cpu/tms32082/dis_pp.cpp | 1073 +++++++++++++++++++++-------------- src/devices/cpu/tms32082/dis_pp.h | 19 +- 2 files changed, 655 insertions(+), 437 deletions(-) diff --git a/src/devices/cpu/tms32082/dis_pp.cpp b/src/devices/cpu/tms32082/dis_pp.cpp index 8d15555b610..9da3562731f 100644 --- a/src/devices/cpu/tms32082/dis_pp.cpp +++ b/src/devices/cpu/tms32082/dis_pp.cpp @@ -5,40 +5,92 @@ #include "emu.h" #include "dis_pp.h" -char const *const tms32082_pp_disassembler::REG_NAMES[128] = +#define ROTATE_L(x, r) ((x << r) | (x >> (32-r))) + +std::string tms32082_pp_disassembler::get_reg_name(int reg, bool read) { - // 0 - 15 - "a0", "a1", "a2", "a3", "a4", "???", "a6", "a7", - "a8", "a9", "a10", "a11", "a12", "???", "a14", "a15", - // 16 - 31 - "x0", "x1", "x2", "???", "???", "???", "???", "???", - "x8", "x9", "x10", "???", "???", "???", "???", "???", - // 32 - 47 - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "???", "sr", "mf", "???", "???", "???", "???", "???", - // 48 - 63 - "???", "???", "???", "???", "???", "???", "???", "???", - "pc/call", "ipa/br", "ipe", "iprs", "inten", "intflg", "comm", "lctl", - // 64 - 79 - "???", "???", "???", "???", "???", "???", "???", "???", - "???", "???", "???", "???", "???", "???", "???", "???", - // 80 - 95 - "???", "???", "???", "???", "???", "???", "???", "???", - "???", "???", "???", "???", "???", "???", "???", "???", - // 96 - 111 - "lc0", "lc1", "lc2", "???", "lr0", "lr1", "lr2", "???", - "lrse0", "lrse1", "lrse2", "???", "lrs0", "lrs1", "lrs2", "???", - // 112 - 127 - "ls0", "ls1", "ls2", "???", "le0", "le1", "le2", "???", - "???", "???", "???", "???", "tag0", "tag1", "tag2", "tag3" -}; + switch (reg) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + return util::string_format("a%d", reg & 0xf); + + case 0x07: + case 0x0f: + return util::string_format("0"); // a7 and a15 read as zero + + case 0x06: + case 0x0e: + return util::string_format("sp"); + + case 0x10: + case 0x11: + case 0x12: + case 0x18: + case 0x19: + case 0x1a: + return util::string_format("x%d", reg & 0xf); + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + return util::string_format("d%d", reg & 0x7); + + case 0x29: return util::string_format("sr"); + case 0x2a: return util::string_format("mf"); + case 0x38: return read ? util::string_format("pc") : util::string_format("call"); + case 0x39: return read ? util::string_format("ipa") : util::string_format("br"); + case 0x3a: return util::string_format("ipe"); + case 0x3b: return util::string_format("iprs"); + case 0x3c: return util::string_format("inten"); + case 0x3d: return util::string_format("intflg"); + case 0x3e: return util::string_format("comm"); + case 0x3f: return util::string_format("lctl"); + case 0x60: return util::string_format("lc0"); + case 0x61: return util::string_format("lc1"); + case 0x62: return util::string_format("lc2"); + case 0x64: return util::string_format("lr0"); + case 0x65: return util::string_format("lr1"); + case 0x66: return util::string_format("lr2"); + case 0x68: return util::string_format("lrse0"); + case 0x69: return util::string_format("lrse1"); + case 0x6a: return util::string_format("lrse2"); + case 0x6c: return util::string_format("lrs0"); + case 0x6d: return util::string_format("lrs1"); + case 0x6e: return util::string_format("lrs2"); + case 0x70: return util::string_format("ls0"); + case 0x71: return util::string_format("ls1"); + case 0x72: return util::string_format("ls2"); + case 0x74: return util::string_format("le0"); + case 0x75: return util::string_format("le1"); + case 0x76: return util::string_format("le2"); + case 0x7c: return util::string_format("tag0"); + case 0x7d: return util::string_format("tag1"); + case 0x7e: return util::string_format("tag2"); + case 0x7f: return util::string_format("tag3"); + default: return util::string_format("???"); + } +} char const *const tms32082_pp_disassembler::CONDITION_CODES[16] = { - "", "[p] ", "[ls] ", "[hi] ", - "[lt] ", "[le] ", "[ge] ", "[gt] ", - "[hs] ", "[lo] ", "[eq] ", "[ne] ", - "[v] ", "[nv] ", "[n] ", "[nn] " + "u", "p", "ls", "hi", + "lt", "le", "ge", "gt", + "hs", "lo", "eq", "ne", + "v", "nv", "n", "nn" }; char const *const tms32082_pp_disassembler::TRANSFER_SIZE[4] = @@ -46,292 +98,396 @@ char const *const tms32082_pp_disassembler::TRANSFER_SIZE[4] = "b:", "h:", "w:", "" }; -std::string tms32082_pp_disassembler::format_address_mode(int mode, int areg, int s, int limx) +std::string tms32082_pp_disassembler::make_ea(int mode, int areg, bool scale, int size, int offset, int xreg) { + std::string offset_text; + if (scale) + { + if (size == 1) + offset *= 2; + else if (size == 2) + offset *= 4; + } + + offset_text = util::string_format("0x%X", offset); + switch (mode) { - case 0x4: return util::string_format("*(a%d++=x%d)", areg, limx); - case 0x5: return util::string_format("*(a%d--=x%d)", areg, limx); - case 0x6: return util::string_format("*(a%d++0x%04X)", areg, limx); - case 0x7: return util::string_format("*(a%d--0x%04X)", areg, limx); - case 0x8: return util::string_format("*(a%d+x%d)", areg, limx); - case 0x9: return util::string_format("*(a%d-x%d)", areg, limx); - case 0xa: return util::string_format("*(a%d+0x%04X)", areg, limx); - case 0xb: return util::string_format("*(a%d-0x%04X)", areg, limx); - case 0xc: return util::string_format("*(a%d+=x%d)", areg, limx); - case 0xd: return util::string_format("*(a%d-=x%d)", areg, limx); - case 0xe: return util::string_format("*(a%d+=0x%04X)", areg, limx); - case 0xf: return util::string_format("*(a%d-=0x%04X)", areg, limx); + case 0x4: return util::string_format("%s++=x%d", get_reg_name(areg, true), xreg); + case 0x5: return util::string_format("%s--=x%d", get_reg_name(areg, true), xreg); + case 0x6: return util::string_format("%s++%s", get_reg_name(areg, true), offset_text); + case 0x7: return util::string_format("%s--%s", get_reg_name(areg, true), offset_text); + case 0x8: return util::string_format("%s+x%d", get_reg_name(areg, true), xreg); + case 0x9: return util::string_format("%s-x%d", get_reg_name(areg, true), xreg); + case 0xa: return util::string_format("%s+%s", get_reg_name(areg, true), offset_text); + case 0xb: return util::string_format("%s-%s", get_reg_name(areg, true), offset_text); + case 0xc: return util::string_format("%s+=x%d", get_reg_name(areg, true), xreg); + case 0xd: return util::string_format("%s-=x%d", get_reg_name(areg, true), xreg); + case 0xe: return util::string_format("%s+=%s", get_reg_name(areg, true), offset_text); + case 0xf: return util::string_format("%s-=%s", get_reg_name(areg, true), offset_text); } return ""; } -void tms32082_pp_disassembler::format_transfer(uint64_t op) +std::string tms32082_pp_disassembler::make_mem_transfer(int mode, int dst, int a, bool scale, int size, int le, int imm, int x) { - std::string buffer; - int lmode = (op >> 35) & 0xf; - int gmode = (op >> 13) & 0xf; - - bool is_nop = false; + std::string transfer_text; - switch (lmode) + switch (le) { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - { - int cond = (op >> 32) & 0xf; + case 0: // store + transfer_text = util::string_format("&%s*(%s) = %s", TRANSFER_SIZE[size], make_ea(mode, a, scale, size, imm, x), get_reg_name(dst, true)); + break; + case 1: // address unit arithmetic + transfer_text = util::string_format("%s = %s", get_reg_name(dst, false), make_ea(mode, a, scale, size, imm, x)); + break; + case 2: // zero-extended load + transfer_text = util::string_format("%s = &%s*(%s)", get_reg_name(dst, false), TRANSFER_SIZE[size], make_ea(mode, a, scale, size, imm, x)); + break; + case 3: // sign-extended load + transfer_text = util::string_format("%s = &s%s*(%s)", get_reg_name(dst, false), TRANSFER_SIZE[size], make_ea(mode, a, scale, size, imm, x)); + break; + } - switch (gmode) - { - case 0x00: // Format 7: Conditional DU || Conditional Move - { - int dstbank = (op >> 18) & 0xf; - int srcbank = (op >> 6) & 0xf; - int src = (op >> 10) & 0x7; - int dst = (op >> 3) & 0x7; + return transfer_text; +} - int dreg = (dstbank << 3) | dst; - int sreg = (srcbank << 3) | src; +std::string tms32082_pp_disassembler::make_condition(int cond, int ncvz) +{ + std::string condition; - buffer += util::string_format("%s", CONDITION_CODES[cond]); - buffer += util::string_format("%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); - break; - } - case 0x01: // Format 8: Conditional DU ||Conditional Field Move - { - int dstbank = (op >> 18) & 0xf; - int src = (op >> 10) & 0x7; - int dst = (op >> 3) & 0x7; - int itm = (op >> 22) & 0x3; - int size = (op >> 7) & 0x3; - // int e = (op & (1 << 9)); - - int dreg = (dstbank << 3) | dst; - int sreg = (4 << 3) | src; - - buffer += util::string_format("%s", CONDITION_CODES[cond]); - buffer += util::string_format("%s = [%s%d]%s", REG_NAMES[dreg], TRANSFER_SIZE[size], itm, REG_NAMES[sreg]); - break; - } - case 0x02: case 0x03: // Format 10: Conditional Non-D Data Unit - { - int as1bank = (op >> 6) & 0xf; - int adstbank = (op >> 18) & 0xf; - int src = (op >> 45) & 0x7; - int dst = (op >> 48) & 0x7; + if (cond || ncvz) + { + condition.append("["); + } + if (cond) + { + condition.append(util::string_format("%s", CONDITION_CODES[cond])); + } + if (ncvz) + { + condition.append("."); + if (ncvz & 8) + condition.append("n"); + if (ncvz & 4) + condition.append("c"); + if (ncvz & 2) + condition.append("v"); + if (ncvz & 1) + condition.append("z"); + } + if (cond || ncvz) + { + condition.append("]"); + } + return condition; +} - int dreg = (adstbank << 3) | dst; - int sreg = (as1bank << 3) | src; - if (dreg == sreg) - { - is_nop = true; - } - else - { - buffer += util::string_format("%s", CONDITION_CODES[cond]); - buffer += util::string_format("%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); - } - break; - } - default: - { - if (op & 0x4) // Format 9: Conditional DU || Conditional Global - { - int bank = (op >> 18) & 0xf; - int le = ((op >> 16) & 2) | ((op >> 9) & 1); - int size = (op >> 7) & 0x3; - int s = (op & (1 << 6)); - int reg = (op >> 10) & 0x7; - int ga = (op >> 3) & 0x7; - int gimx = (op >> 22) & 0x7; +std::string tms32082_pp_disassembler::make_field_move(bool d, bool e, int size, int itm) +{ + std::string field; + if (d) + { + field.append("r"); + } + else + { + field.append(util::string_format("%s", e ? "s" : "")); + } + + switch (size) + { + case 0: field.append("b"); break; + case 1: field.append("w"); break; + } - int greg = (bank << 3) | reg; + if (!d) + { + field.append(util::string_format("%d", itm)); + } - buffer += util::string_format("%s", CONDITION_CODES[cond]); + return field; +} - switch (le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx), REG_NAMES[greg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, gimx)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break; - } - } - else // Format 5: Global (Long Offset) - { - int bank = (op >> 18) & 0xf; - int le = ((op >> 16) & 2) | ((op >> 9) & 1); - int size = (op >> 7) & 0x3; - int s = (op & (1 << 6)); - int offset = (op >> 22) & 0x7fff; - int reg = (op >> 10) & 0x7; - //int grm = op & 0x3; - int ga = (op >> 3) & 0x7; - - int greg = (bank << 3) | reg; - - // sign extend offset - if (s && (offset & 0x4000)) - offset |= 0xffffc000; - - switch (le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset), REG_NAMES[greg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, offset)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; - } - } - break; - } - } - break; - } - default: +void tms32082_pp_disassembler::parallel_transfer(uint64_t op) +{ + int lbits = (op >> 37) & 3; + int gbits = (op >> 15) & 3; + + if (lbits == 0 && gbits == 0) + { + switch ((op >> 13) & 3) { - int mode = gmode | ((op & (1 << 24)) ? 0x10 : 0); + case 0: + { + // 7. Conditional DU||Conditional Move + int cond = (op >> 32) & 0xf; + int ncvz = (op >> 25) & 0xf; + + m_alu_condition = make_condition(cond, ncvz); + + m_src1bank = (op >> 6) & 0xf; + m_dstbank = (op >> 18) & 0xf; + + int dst = ((op >> 3) & 7) | (m_dstbank << 3); + int src = ((op >> 10) & 7) | (m_src1bank << 3); + + bool r = (op & (1 << 29)) ? true : false; + + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); - switch (mode) + m_parallel_transfer = util::string_format("%s = %s", get_reg_name(dst, false), get_reg_name(src, true)); + + break; + } + case 1: { - case 0x00: // Format 2: Move || Local - { - buffer += util::string_format("move||local "); - break; - } - case 0x01: // Format 3: Field Move || Local - { - buffer += util::string_format("field move||local "); - break; - } - case 0x02: case 0x03: // Format 6: Non-D DU || Local - { - int d = (op >> 32) & 0x7; - int s = (op & (1 << 28)); - int size = (op >> 29) & 0x3; - int le = ((op >> 16) & 2) | ((op >> 31) & 1); - int la = (op >> 25) & 0x7; - int limx = op & 0x7; + // 8. Conditional DU||Conditional Field Move + m_parallel_transfer = util::string_format("cond du||cond field move"); - int reg = (4 << 3) | d; + m_dstbank = (op >> 18) & 0xf; - switch (le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx), REG_NAMES[reg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, limx)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break; - } - break; - } - case 0x10: case 0x11: case 0x12: case 0x13: // Format 4: Local (Long Offset) - { - int d = (op >> 32) & 0x7; - int bank = (op >> 18) & 0xf; - int s = (op & (1 << 28)); - int size = (op >> 29) & 0x3; - int le = ((op >> 16) & 2) | ((op >> 31) & 1); - int la = (op >> 25) & 0x7; + int itm = (op >> 22) & 3; + bool e = (op & (1 << 9)) ? true : false; + bool d = (op & (1 << 6)) ? true : false; + int size = (op >> 7) & 3; + int dst = ((op >> 3) & 7) | (m_dstbank << 3); + int src = ((op >> 10) & 7) | (4 << 3); - int reg = (bank << 3) | d; + int cond = (op >> 32) & 0xf; + int ncvz = (op >> 25) & 0xf; - uint16_t offset; - if (s) - { - offset = op & 0x7fff; - if (offset & 0x4000) - offset |= 0xc000; - } - else - { - offset = op & 0x7fff; - } + bool r = (op & (1 << 29)) ? true : false; - switch (le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset), REG_NAMES[reg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, offset)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; - } - break; - } - case 0x14: case 0x15: case 0x16: case 0x17: // Format 1: Double Parallel - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - { - int la = (op >> 25) & 0x7; - int ga = (op >> 3) & 0x7; - int local_imx = op & 0x7; - int global_imx = (op >> 22) & 0x7; - int local_s = (op & (1 << 28)); - int global_s = (op & (1 << 6)); - int local_size = (op >> 29) & 0x3; - int global_size = (op >> 7) & 0x3; - int local_le = ((op >> 20) & 2) | ((op >> 31) & 1); - int global_le = ((op >> 16) & 2) | ((op >> 9) & 1); - int gbank = (op >> 18) & 0x7; - int reg = (op >> 10) & 0x7; - int d = (op >> 32) & 0x7; - - int greg = (gbank << 3) | reg; - int lreg = (4 << 3) | d; - - // local transfer - switch (local_le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx), REG_NAMES[lreg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[lreg], format_address_mode(lmode, la, local_s, local_imx)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; - } + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); - util::stream_format(*output, ", "); + m_alu_condition = make_condition(cond, ncvz); - // global transfer - switch (global_le) - { - case 0: buffer += util::string_format("&%s%s = %s", TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx), REG_NAMES[greg]); break; - case 1: buffer += util::string_format("%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, global_s, global_imx)); break; - case 2: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; - case 3: buffer += util::string_format("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; - } - break; - } + m_parallel_transfer = util::string_format("%s = %s %s", get_reg_name(dst, false), make_field_move(d, e, size, itm), get_reg_name(src, true)); + break; + } + case 2: + case 3: + { + // 10. Conditional Non-D Data Unit + + // no transfer, only modifies ALU operation + m_src1bank = (op >> 6) & 0xf; + m_dstbank = (op >> 18) & 0xf; + + int cond = (op >> 32) & 0xf; + // bool c = (op & (1 << 31)) ? true : false; + // bool r = (op & (1 << 30)) ? true : false; + int ncvz = (op >> 25) & 0xf; + + m_alu_condition = make_condition(cond, ncvz); + break; } } + } + else if (lbits == 0 && gbits != 0) + { + if (op & 0x4) + { + // 9. Conditional DU||Conditional Global + int global_im = (op >> 22) & 7; + int global_x = ((op >> 22) & 7) | 8; // global x-registers: x8-x10 + int bank = (op >> 18) & 7; + int global_le = ((op >> 9) & 1) | ((op >> 16) & 2); + int gmode = (op >> 13) & 0xf; + int reg = (op >> 10) & 7; + int global_size = (op >> 7) & 3; + bool global_s = (op & (1 << 6)) ? true : false; + int global_a = ((op >> 3) & 7) | 8; // global a-registers: a8-a12 + int cond = (op >> 32) & 0xf; + int ncvz = (op >> 25) & 0xf; + + m_alu_condition = make_condition(cond, ncvz); + + bool r = (op & (1 << 29)) ? true : false; + + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); + + m_parallel_transfer = make_mem_transfer(gmode, (bank << 3) | reg, global_a, global_s, global_size, global_le, global_im, global_x); + } + else + { + // 5. Global(Long Offset) + int bank = (op >> 18) & 0xf; + int global_le = ((op >> 9) & 1) | ((op >> 16) & 2); + int gmode = (op >> 13) & 0xf; + int reg = (op >> 10) & 7; + int global_size = (op >> 7) & 3; + bool global_s = (op & (1 << 6)) ? true : false; + int global_a = ((op >> 3) & 7) | 8; // global a-registers: a8-a12 + + int offset = (op >> 22) & 0x7fff; + int x = (offset & 7) | 8; // global x-registers: x8-x10 + + // s-bit is MSB for immediate value when transfer size is 8 bits + if (global_size == 0) + offset |= global_s ? 0x8000 : 0; + + m_parallel_transfer.append(make_mem_transfer(gmode, (bank << 3) | reg, global_a, global_s, global_size, global_le, offset, x)); + } + } + else if (lbits != 0 && gbits == 0) + { + switch (((op >> 22) & 4) | ((op >> 13) & 3)) + { + case 0: + { + // 2. Move||Local + int lmode = (op >> 35) & 0xf; + int d = ((op >> 32) & 7) | (0x4 << 3); // d-registers are in bank 4 + int local_le = ((op >> 31) & 1) | ((op >> 16) & 2); + int local_size = (op >> 29) & 3; + bool local_s = (op & (1 << 28)) ? true : false; + int local_a = (op >> 25) & 7; + int local_im = op & 7; + int local_x = op & 7; + + if (local_size == 0) + local_im |= local_s ? 0x8 : 0; + + int srcbank = (op >> 6) & 0xf; + int dstbank = (op >> 18) & 0xf; + int src = ((op >> 10) & 7) | (srcbank << 3); + int dst = ((op >> 3) & 7) | (dstbank << 3); + + m_parallel_transfer = make_mem_transfer(lmode, d, local_a, local_s, local_size, local_le, local_im, local_x); + m_parallel_transfer.append(" || "); + m_parallel_transfer.append(util::string_format("%s = %s", get_reg_name(dst, false), get_reg_name(src, true))); + break; + } + + case 1: + { + // 3. Field Move||Local + // TODO: not used by any program so far + m_parallel_transfer = util::string_format("field move || local"); + break; + } + + case 2: + case 3: + { + // 6. Non-D DU||Local + int lmode = (op >> 35) & 0xf; + int d = ((op >> 32) & 7) | (0x4 << 3); // d-registers are in bank 4 + int le = ((op >> 31) & 1) | ((op >> 16) & 2); + int size = (op >> 29) & 3; + bool s = (op & (1 << 28)) ? true : false; + int a = (op >> 25) & 7; + int im = (op >> 22) & 7; + int x = ((op >> 22) & 7); + + m_dstbank = (op >> 18) & 0xf; + m_src1bank = (op >> 6) & 0xf; + + m_parallel_transfer = make_mem_transfer(lmode, d, a, s, size, le, im, x); + break; + } - if (!is_nop) - util::stream_format(*output, " || %s", buffer); + case 4: + case 5: + case 6: + case 7: + { + // 4. Local (Long Offset) + int lmode = (op >> 35) & 0xf; + int d = (op >> 32) & 7; + int local_le = ((op >> 31) & 1) | ((op >> 16) & 2); + int local_size = (op >> 29) & 3; + bool local_s = (op & (1 << 28)) ? true : false; + int local_a = (op >> 25) & 7; + int bank = (op >> 18) & 0xf; + int offset = op & 0x7fff; + + // s-bit is MSB for immediate value when transfer size is 8 bits + if (local_size == 0) + offset |= local_s ? 0x8000 : 0; + + m_parallel_transfer.append(make_mem_transfer(lmode, (bank << 3) | d, local_a, local_s, local_size, local_le, offset, offset & 7)); + break; + } + } + } + else + { + // (gbits != 0 && lbits != 0) + // 1. Double Parallel + int lmode = (op >> 35) & 0xf; + int d = ((op >> 32) & 7) | (0x4 << 3); // d-registers are in bank 4 + int local_le = ((op >> 31) & 1) | ((op >> 20) & 2); + int local_size = (op >> 29) & 3; + bool local_s = (op & (1 << 28)) ? true : false; + int local_a = (op >> 25) & 7; + int global_im = (op >> 22) & 7; + int global_x = ((op >> 22) & 7) | 8; // global x-registers: x8-x10 + int bank = (op >> 18) & 7; + int global_le = ((op >> 9) & 1) | ((op >> 16) & 2); + int gmode = (op >> 13) & 0xf; + int reg = (op >> 10) & 7; + int global_size = (op >> 7) & 3; + bool global_s = (op & (1 << 6)) ? true : false; + int global_a = ((op >> 3) & 7) | 8; // global a-registers: a8-a12 + int local_im = op & 7; + int local_x = op & 7; + + // s-bit is MSB for immediate value when transfer size is 8 bits + if (global_size == 0) + global_im |= local_s ? 0x8 : 0; + if (local_size == 0) + local_im |= local_s ? 0x8 : 0; + + m_parallel_transfer.append(make_mem_transfer(lmode, d, local_a, local_s, local_size, local_le, local_im, local_x)); + m_parallel_transfer.append(" || "); + m_parallel_transfer.append(make_mem_transfer(gmode, (bank << 3) | reg, global_a, global_s, global_size, global_le, global_im, global_x)); + } } -void tms32082_pp_disassembler::format_alu_op(int aluop, int a, const char *dst_text, const char *a_text, const char *b_text, const char *c_text) +std::string tms32082_pp_disassembler::format_alu_op(int aluop, int a, const std::string& dst_text, std::string& a_text, std::string& b_text, std::string& c_text) { if (a) // arithmetic { + int modifier = ((aluop >> 1) & 1) | ((aluop >> 2) & 2) | ((aluop >> 3) & 4) | ((aluop >> 4) & 8); + + switch (modifier) + { + case 0: break; // normal operation + case 1: break; // cin (TODO) + case 4: a_text = util::string_format("0"); break; // A port = 0 + case 5: a_text = util::string_format("0"); break; // A port = 0, cin (TODO) + case 6: a_text = util::string_format("0"); break; // A port = 0 and %! if maskgen instruction. lmbc if not maskgen instruction. (TODO) + case 7: a_text = util::string_format("0"); break; // A port = 0, %!, and cin if maskgen instruction. rmbc if not maskgen instruction. (TODO) + } + int bits = (aluop & 1) | ((aluop >> 1) & 2) | ((aluop >> 2) & 4) | ((aluop >> 3) & 8); switch (bits) { - case 1: util::stream_format(*output, "%s = %s - %s<1<", dst_text, a_text, b_text); break; - case 2: util::stream_format(*output, "%s = %s + %s<0<", dst_text, a_text, b_text); break; - case 3: util::stream_format(*output, "%s = %s - %s", dst_text, a_text, c_text); break; - case 4: util::stream_format(*output, "%s = %s - %s>1>", dst_text, a_text, b_text); break; - case 5: util::stream_format(*output, "%s = %s - %s", dst_text, a_text, b_text); break; - case 6: util::stream_format(*output, "?"); break; - case 7: util::stream_format(*output, "%s = %s - %s>0>", dst_text, a_text, b_text); break; - case 8: util::stream_format(*output, "%s = %s + %s>0>", dst_text, a_text, b_text); break; - case 9: util::stream_format(*output, "?"); break; - case 10: util::stream_format(*output, "%s = %s + %s", dst_text, a_text, b_text); break; - case 11: util::stream_format(*output, "%s = %s + %s>1>", dst_text, a_text, b_text); break; - case 12: util::stream_format(*output, "%s = %s + %s", dst_text, a_text, c_text); break; - case 13: util::stream_format(*output, "%s = %s - %s<0<", dst_text, a_text, b_text); break; - case 14: util::stream_format(*output, "%s = %s + %s<1<", dst_text, a_text, b_text); break; - case 15: util::stream_format(*output, "%s = field %s + %s", dst_text, a_text, b_text); break; + case 1: return util::string_format("%s = %s - %s<1<", dst_text, a_text, b_text); break; + case 2: return util::string_format("%s = %s + %s<0<", dst_text, a_text, b_text); break; + case 3: return util::string_format("%s = %s - %s", dst_text, a_text, c_text); break; + case 4: return util::string_format("%s = %s - %s>1>", dst_text, a_text, b_text); break; + case 5: return util::string_format("%s = %s - %s", dst_text, a_text, b_text); break; + case 6: return util::string_format("?"); break; + case 7: return util::string_format("%s = %s - %s>0>", dst_text, a_text, b_text); break; + case 8: return util::string_format("%s = %s + %s>0>", dst_text, a_text, b_text); break; + case 9: return util::string_format("?"); break; + case 10: return util::string_format("%s = %s + %s", dst_text, a_text, b_text); break; + case 11: return util::string_format("%s = %s + %s>1>", dst_text, a_text, b_text); break; + case 12: return util::string_format("%s = %s + %s", dst_text, a_text, c_text); break; + case 13: return util::string_format("%s = %s - %s<0<", dst_text, a_text, b_text); break; + case 14: return util::string_format("%s = %s + %s<1<", dst_text, a_text, b_text); break; + case 15: return util::string_format("%s = field %s + %s", dst_text, a_text, b_text); break; } } else // boolean @@ -339,64 +495,63 @@ void tms32082_pp_disassembler::format_alu_op(int aluop, int a, const char *dst_t switch (aluop) { case 0xaa: // A & B & C | A & ~B & C | A & B & ~C | A & ~B & ~C = A - util::stream_format(*output, "%s = %s", dst_text, a_text); - break; + return util::string_format("%s = %s", dst_text, a_text); case 0x55: // ~A & B & C | ~A & ~B & C | ~A & B & ~C | ~A & ~B & ~C = ~A - util::stream_format(*output, "%s = ~%s", dst_text, a_text); - break; + return util::string_format("%s = ~%s", dst_text, a_text); case 0xcc: // A & B & C | ~A & B & C | A & B & ~C | ~A & B & ~C = B - util::stream_format(*output, "%s = %s", dst_text, b_text); - break; + return util::string_format("%s = %s", dst_text, b_text); case 0x33: // A & ~B & C | ~A & ~B & C | A & ~B & ~C | ~A & ~B & ~C = ~B - util::stream_format(*output, "%s = %s", dst_text, b_text); - break; + return util::string_format("%s = %s", dst_text, b_text); case 0xf0: // A & B & C | ~A & B & C | A & ~B & C | ~A & ~B & C = C - util::stream_format(*output, "%s = %s", dst_text, c_text); - break; + return util::string_format("%s = %s", dst_text, c_text);; case 0x0f: // A & B & ~C | ~A & B & ~C | A & ~B & ~C | ~A & ~B & ~C = ~C - util::stream_format(*output, "%s = ~%s", dst_text, c_text); - break; + return util::string_format("%s = ~%s", dst_text, c_text); case 0x80: // A & B & C - util::stream_format(*output, "%s = %s & %s & %s", dst_text, a_text, b_text, c_text); - break; + return util::string_format("%s = %s & %s & %s", dst_text, a_text, b_text, c_text); case 0x88: // A & B & C | A & B & ~C = A & B - util::stream_format(*output, "%s = %s & %s", dst_text, a_text, b_text); - break; + return util::string_format("%s = %s & %s", dst_text, a_text, b_text); case 0xa0: // A & B & C | A & ~B & C = A & C - util::stream_format(*output, "%s = %s & %s", dst_text, a_text, c_text); - break; + return util::string_format("%s = %s & %s", dst_text, a_text, c_text); case 0xc0: // A & B & C | ~A & B & C = B & C - util::stream_format(*output, "%s = %s & %s", dst_text, b_text, c_text); - break; + return util::string_format("%s = %s & %s", dst_text, b_text, c_text); case 0xea: // A & B & C | ~A & B & C | A & ~B & C | // A & B & ~C | A & ~B & ~C = A | C - util::stream_format(*output, "%s = %s | %s", dst_text, a_text, c_text); - break; + return util::string_format("%s = %s | %s", dst_text, a_text, c_text); case 0xee: // A & B & C | ~A & B & C | A & ~B & C | // A & B & ~C | ~A & B & ~C | A & ~B & ~C = A | B - util::stream_format(*output, "%s = %s | %s", dst_text, a_text, b_text); - break; + return util::string_format("%s = %s | %s", dst_text, a_text, b_text); case 0x44: // ~A & B & C | ~A & B & ~C = ~A & B - util::stream_format(*output, "%s = ~%s & %s", dst_text, a_text, b_text); - break; + return util::string_format("%s = ~%s & %s", dst_text, a_text, b_text); + + case 0x22: // A & ~B & ~C | A & ~B & C = A & ~B + return util::string_format("%s = %s & ~%s", dst_text, a_text, b_text); + + case 0xaf: // A & B & C | A & ~B & C | A & B & ~C | + // ~A & B & ~C | A & ~B & ~C | ~A & ~B & ~C = A | ~C + return util::string_format("%s = %s | ~%s", dst_text, a_text, c_text); + + case 0xfa: // A & B & C | ~A & B & C | A & ~B & C | + // ~A & ~B & C | A & B & ~C | A & ~B & ~C = A | C + return util::string_format("%s = %s | %s", dst_text, a_text, c_text); + default: - util::stream_format(*output, "%s = b%02X(%s, %s, %s)", dst_text, aluop, a_text, b_text, c_text); - break; + return util::string_format("%s = b%02X(%s, %s, %s)", dst_text, aluop, a_text, b_text, c_text); } } + return std::string(""); } u32 tms32082_pp_disassembler::opcode_alignment() const @@ -406,17 +561,76 @@ u32 tms32082_pp_disassembler::opcode_alignment() const offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { - output = &stream; uint32_t flags = 0; - uint64_t op = opcodes.r64(pc); + m_alu_condition.clear(); + m_alu_operation.clear(); + m_parallel_condition.clear(); + m_parallel_transfer.clear(); + + // by default src/dst bank is 4, but can be overridden by parallel transfer types 6 & 10 + m_src1bank = 4; + m_dstbank = 4; + uint64_t op = opcodes.r64(pc); switch (op >> 60) { case 0x6: case 0x7: // Six-operand { - util::stream_format(*output, "A: six operand "); + int sixop = (op >> 57) & 0xf; + + int src3 = ((op >> 54) & 7) | (4 << 3); + int dst2 = ((op >> 51) & 7) | (4 << 3); + int dst1 = ((op >> 48) & 7) | (m_dstbank << 3); + int src1 = ((op >> 45) & 7) | (m_src1bank << 3); + int src4 = ((op >> 42) & 7) | (4 << 3); + int src2 = ((op >> 39) & 7) | (4 << 3); + + parallel_transfer(op); + + switch (sixop) + { + case 0x0: + case 0x1: + case 0x4: + case 0x5: + // MPY||ADD + m_alu_operation = util::string_format("%s = %c(%s * %s), %s = %s %c %s", + get_reg_name(dst2, false), + (sixop & 4) ? 'u' : 's', + get_reg_name(src3, true), + get_reg_name(src4, true), + get_reg_name(dst1, false), + get_reg_name(src2, true), + (sixop & 1) ? '-' : '+', + get_reg_name(src1, true)); + break; + + case 0x2: + case 0x3: + case 0x6: + case 0x7: + m_alu_operation = util::string_format("MPY||EALU"); + break; + + case 0x8: + case 0x9: + case 0xb: + m_alu_operation = util::string_format("EALU||ROTATE"); + break; + + case 0xa: + m_alu_operation = util::string_format("divi"); + break; + + case 0xc: + case 0xd: + case 0xe: + case 0xf: + m_alu_operation = util::string_format("MPY||SADD"); + break; + } break; } @@ -432,31 +646,30 @@ offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, co if ((op & 0xfaa8100000000000U) == 0x8800000000000000U) { int operation = (op >> 39) & 0x1f; - uint64_t parallel_xfer = (op & 0x0000007fffffffffU); + + parallel_transfer(op); switch (operation) { - case 0x00: util::stream_format(*output, "nop"); break; - case 0x02: util::stream_format(*output, "eint"); break; - case 0x03: util::stream_format(*output, "dint"); break; - default: util::stream_format(*output, ""); break; + case 0x00: break; + case 0x02: m_alu_operation = util::string_format("eint"); break; + case 0x03: m_alu_operation = util::string_format("dint"); break; + default: m_alu_operation = util::string_format(""); break; } - - format_transfer(parallel_xfer); } else { - char dst_text[32]; - char a_text[32]; - char b_text[32]; - char c_text[32]; + std::string dst_text; + std::string a_text; + std::string b_text; + std::string c_text; switch ((op >> 43) & 3) { case 0: case 1: // Base set ALU (5-bit immediate) { - uint64_t parallel_xfer = (op & 0x0000007fffffffffU); + parallel_transfer(op); int dst = (op >> 48) & 7; int src1 = (op >> 45) & 7; @@ -465,77 +678,63 @@ offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, co int aluop = (op >> 51) & 0xff; int a = (op >> 59) & 1; - int adstbank; - int as1bank; - - if ((op & 0x0101c000) == 0x00004000) - { - adstbank = (op >> 18) & 0xf; - as1bank = (op >> 6) & 0xf; - } - else - { - adstbank = 4; - as1bank = 4; - } - - int s1reg = src1 | (as1bank << 3); - int dreg = dst | (adstbank << 3); + int s1reg = src1 | (m_src1bank << 3); + int dreg = dst | (m_dstbank << 3); int dstcreg = dst | (0x4 << 3); - sprintf(dst_text, "%s", REG_NAMES[dreg]); + dst_text = util::string_format("%s", get_reg_name(dreg, false)); switch (cl) { case 0: - sprintf(a_text, "0x%02X", src2imm); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("0x%02X", src2imm); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 1: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "0x%02X", src2imm); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("0x%02X", src2imm); break; case 2: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "%%0x%02X", src2imm); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("%%0x%02X", src2imm); break; case 3: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\0x%02X", REG_NAMES[s1reg], src2imm); - sprintf(c_text, "%%0x%02X", src2imm); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\0x%02X", get_reg_name(s1reg, true), src2imm); + c_text = util::string_format("%%0x%02X", src2imm); break; case 4: - sprintf(a_text, "0x%02X", src2imm); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "%%d0"); + a_text = util::string_format("0x%02X", src2imm); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("%%d0"); break; case 5: - sprintf(a_text, "0x%02X", src2imm); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("0x%02X", src2imm); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 6: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "0x%02X", src2imm); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("0x%02X", src2imm); break; case 7: - sprintf(a_text, "%s", REG_NAMES[s1reg]); - sprintf(b_text, "1\\\\0x%02X", src2imm); - sprintf(c_text, "0x%02X", src2imm); + a_text = util::string_format("%s", get_reg_name(s1reg, true)); + //b_text = util::string_format("1\\\\0x%02X", src2imm); + b_text = util::string_format("0x%08X", ROTATE_L(1, src2imm)); + c_text = util::string_format("0x%02X", src2imm); break; } - format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); - format_transfer(parallel_xfer); + m_alu_operation = format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); break; } case 2: // Base set ALU (reg src2) { - uint64_t parallel_xfer = (op & 0x0000007fffffffffU); + parallel_transfer(op); int dst = (op >> 48) & 7; int src1 = (op >> 45) & 7; @@ -544,72 +743,57 @@ offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, co int aluop = (op >> 51) & 0xff; int a = (op >> 59) & 1; - int adstbank; - int as1bank; - - if ((op & 0x0101c000) == 0x00004000) - { - adstbank = (op >> 18) & 0xf; - as1bank = (op >> 6) & 0xf; - } - else - { - adstbank = 4; - as1bank = 4; - } - - int s1reg = src1 | (as1bank << 3); + int s1reg = src1 | (m_src1bank << 3); int s2reg = src2 | (0x4 << 3); int dstcreg = dst | (0x4 << 3); - int dreg = dst | (adstbank << 3); + int dreg = dst | (m_dstbank << 3); - sprintf(dst_text, "%s", REG_NAMES[dreg]); + dst_text = util::string_format("%s", get_reg_name(dreg, false)); switch (cl) { case 0: - sprintf(a_text, "%s", REG_NAMES[s2reg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("%s", get_reg_name(s2reg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 1: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "%s", REG_NAMES[s2reg]); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("%s", get_reg_name(s2reg, true)); break; case 2: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "%%%s", REG_NAMES[s2reg]); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("%%%s", get_reg_name(s2reg, true)); break; case 3: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\%s", REG_NAMES[s1reg], REG_NAMES[s2reg]); - sprintf(c_text, "%%%s", REG_NAMES[s2reg]); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\%s", get_reg_name(s1reg, true), get_reg_name(s2reg, true)); + c_text = util::string_format("%%%s", get_reg_name(s2reg, true)); break; case 4: - sprintf(a_text, "%s", REG_NAMES[s2reg]); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "%%d0"); + a_text = util::string_format("%s", get_reg_name(s2reg, true)); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("%%d0"); break; case 5: - sprintf(a_text, "%s", REG_NAMES[s2reg]); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("%s", get_reg_name(s2reg, true)); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 6: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "%s", REG_NAMES[s2reg]); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("%s", get_reg_name(s2reg, true)); break; case 7: - sprintf(a_text, "%s", REG_NAMES[s1reg]); - sprintf(b_text, "1\\\\%s", REG_NAMES[s2reg]); - sprintf(c_text, "%s", REG_NAMES[s2reg]); + a_text = util::string_format("%s", get_reg_name(s1reg, true)); + b_text = util::string_format("1\\\\%s", get_reg_name(s2reg, true)); + c_text = util::string_format("%s", get_reg_name(s2reg, true)); break; } - format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); - format_transfer(parallel_xfer); + m_alu_operation = format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); break; } @@ -629,54 +813,55 @@ offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, co int s1reg = src1 | (s1bank << 3); int dstcreg = dst | (0x4 << 3); - sprintf(dst_text, "%s", REG_NAMES[dreg]); + dst_text = util::string_format("%s", get_reg_name(dreg, false)); switch (cl) { case 0: - sprintf(a_text, "0x%08X", imm32); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("0x%08X", imm32); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 1: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "0x%08X", imm32); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("0x%08X", imm32); break; case 2: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "%%0x%08X", imm32); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("%%0x%08X", imm32); break; case 3: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s\\\\0x%08X", REG_NAMES[s1reg], imm32); - sprintf(c_text, "%%0x%08X", imm32); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s\\\\0x%08X", get_reg_name(s1reg, true), imm32); + c_text = util::string_format("%%0x%08X", imm32); break; case 4: - sprintf(a_text, "0x%08X", imm32); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "%%d0"); + a_text = util::string_format("0x%08X", imm32); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("%%d0"); break; case 5: - sprintf(a_text, "0x%08X", imm32); - sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]); - sprintf(c_text, "@mf"); + a_text = util::string_format("0x%08X", imm32); + b_text = util::string_format("%s\\\\d0", get_reg_name(s1reg, true)); + c_text = util::string_format("@mf"); break; case 6: - sprintf(a_text, "%s", REG_NAMES[dstcreg]); - sprintf(b_text, "%s", REG_NAMES[s1reg]); - sprintf(c_text, "0x%08X", imm32); + a_text = util::string_format("%s", get_reg_name(dstcreg, true)); + b_text = util::string_format("%s", get_reg_name(s1reg, true)); + c_text = util::string_format("0x%08X", imm32); break; case 7: - sprintf(a_text, "%s", REG_NAMES[s1reg]); - sprintf(b_text, "1\\\\0x%08X", imm32); - sprintf(c_text, "0x%08X", imm32); + a_text = util::string_format("%s", get_reg_name(s1reg, true)); + //b_text = util::string_format("1\\\\0x%08X", imm32); + b_text = util::string_format("%08X", ROTATE_L(1, imm32)); + c_text = util::string_format("0x%08X", imm32); break; } - util::stream_format(*output, "%s", CONDITION_CODES[cond]); + m_alu_condition = make_condition(cond, 0); - format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); + m_alu_operation = format_alu_op(aluop, a, dst_text, a_text, b_text, c_text); break; } } @@ -685,9 +870,33 @@ offs_t tms32082_pp_disassembler::disassemble(std::ostream &stream, offs_t pc, co } default: - util::stream_format(*output, "??? (%02X)", (uint32_t)(op >> 60)); + m_alu_operation = util::string_format("??? (%02X)", (uint32_t)(op >> 60)); break; } + + if (m_alu_operation.length() == 0 && m_parallel_transfer.length() == 0) + { + stream << "nop"; + } + else + { + if (m_alu_operation.length() > 0) + { + stream << m_alu_condition; + stream << m_alu_operation; + + if (m_parallel_transfer.length() > 0) + { + stream << " || "; + } + } + if (m_parallel_transfer.length() > 0) + { + stream << m_parallel_condition; + stream << m_parallel_transfer; + } + } + return 8 | flags | SUPPORTED; } diff --git a/src/devices/cpu/tms32082/dis_pp.h b/src/devices/cpu/tms32082/dis_pp.h index a2f37ea26c8..fd71e7e1e25 100644 --- a/src/devices/cpu/tms32082/dis_pp.h +++ b/src/devices/cpu/tms32082/dis_pp.h @@ -17,17 +17,26 @@ public: virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; private: - static char const *const REG_NAMES[128]; static char const *const CONDITION_CODES[16]; static char const *const TRANSFER_SIZE[4]; + std::string m_alu_condition; + std::string m_alu_operation; + std::string m_parallel_condition; + std::string m_parallel_transfer; - std::ostream *output; + int m_src1bank; + int m_dstbank; + std::string format_alu_op(int aluop, int a, const std::string& dst_text, std::string& a_text, std::string& b_text, std::string& c_text); - std::string format_address_mode(int mode, int areg, int s, int limx); - void format_transfer(uint64_t op); - void format_alu_op(int aluop, int a, const char *dst_text, const char *a_text, const char *b_text, const char *c_text); + void parallel_transfer(uint64_t op); + std::string make_mem_transfer(int mode, int dst, int a, bool scale, int size, int le, int imm, int x); + std::string make_ea(int mode, int areg, bool scale, int size, int offset, int xreg); + std::string make_condition(int cond, int ncvz); + + std::string get_reg_name(int reg, bool read); + std::string make_field_move(bool d, bool e, int size, int itm); }; #endif -- cgit v1.2.3