diff options
Diffstat (limited to 'src/devices/cpu/tms32082')
-rw-r--r-- | src/devices/cpu/tms32082/dis_mp.cpp | 16 | ||||
-rw-r--r-- | src/devices/cpu/tms32082/dis_pp.cpp | 1069 | ||||
-rw-r--r-- | src/devices/cpu/tms32082/dis_pp.h | 19 | ||||
-rw-r--r-- | src/devices/cpu/tms32082/mp_ops.cpp | 310 | ||||
-rw-r--r-- | src/devices/cpu/tms32082/tms32082.cpp | 199 | ||||
-rw-r--r-- | src/devices/cpu/tms32082/tms32082.h | 42 |
6 files changed, 947 insertions, 708 deletions
diff --git a/src/devices/cpu/tms32082/dis_mp.cpp b/src/devices/cpu/tms32082/dis_mp.cpp index be0f9d92074..b194dd0e4d4 100644 --- a/src/devices/cpu/tms32082/dis_mp.cpp +++ b/src/devices/cpu/tms32082/dis_mp.cpp @@ -325,14 +325,14 @@ offs_t tms32082_mp_disassembler::disassemble(std::ostream &stream, offs_t pc, co case 0x0c: util::stream_format(*output, "brcr R%d", src1); break; case 0x0d: util::stream_format(*output, "brcr %s", get_creg_name(imm32)); break; - case 0x10: util::stream_format(*output, "shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x12: util::stream_format(*output, "shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x14: util::stream_format(*output, "shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x16: util::stream_format(*output, "shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x18: util::stream_format(*output, "shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x1a: util::stream_format(*output, "shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x1c: util::stream_format(*output, "shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; - case 0x1e: util::stream_format(*output, "shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x10: util::stream_format(*output, "shift%s.dz R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x12: util::stream_format(*output, "shift%s.dm R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x14: util::stream_format(*output, "shift%s.ds R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x16: util::stream_format(*output, "shift%s.ez R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x18: util::stream_format(*output, "shift%s.em R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x1a: util::stream_format(*output, "shift%s.es R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x1c: util::stream_format(*output, "shift%s.iz R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; + case 0x1e: util::stream_format(*output, "shift%s.im R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break; case 0x22: util::stream_format(*output, "and R%d, R%d, R%d", src1, rs, rd); break; case 0x23: util::stream_format(*output, "and 0x%08X, R%d, R%d", imm32, rs, rd); break; diff --git a/src/devices/cpu/tms32082/dis_pp.cpp b/src/devices/cpu/tms32082/dis_pp.cpp index 8d15555b610..cfabab90359 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 transfer_text; + + switch (le) + { + 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; + } + + return transfer_text; +} + +std::string tms32082_pp_disassembler::make_condition(int cond, int ncvz) +{ + std::string condition; + + 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; +} + + +std::string tms32082_pp_disassembler::make_field_move(bool d, bool e, int size, int itm) { - std::string buffer; - int lmode = (op >> 35) & 0xf; - int gmode = (op >> 13) & 0xf; + 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; + } - bool is_nop = false; + if (!d) + { + field.append(util::string_format("%d", itm)); + } - switch (lmode) + return field; +} + + +void tms32082_pp_disassembler::parallel_transfer(uint64_t op) +{ + int lbits = (op >> 37) & 3; + int gbits = (op >> 15) & 3; + + if (lbits == 0 && gbits == 0) { - case 0x0: - case 0x1: - case 0x2: - case 0x3: + switch ((op >> 13) & 3) { - int cond = (op >> 32) & 0xf; + 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); - switch (gmode) + bool r = (op & (1 << 29)) ? true : false; + + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); + + m_parallel_transfer = util::string_format("%s = %s", get_reg_name(dst, false), get_reg_name(src, true)); + + break; + } + case 1: { - 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; + // 8. Conditional DU||Conditional Field Move + m_parallel_transfer = util::string_format("cond du||cond field move"); - int dreg = (dstbank << 3) | dst; - int sreg = (srcbank << 3) | src; + m_dstbank = (op >> 18) & 0xf; - 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; + 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 dreg = (adstbank << 3) | dst; - int sreg = (as1bank << 3) | src; + int cond = (op >> 32) & 0xf; + int ncvz = (op >> 25) & 0xf; - 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; + bool r = (op & (1 << 29)) ? true : false; - int greg = (bank << 3) | reg; + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); - buffer += util::string_format("%s", CONDITION_CODES[cond]); + m_alu_condition = make_condition(cond, ncvz); - 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; - } + 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; } - break; } - default: + } + else if (lbits == 0 && gbits != 0) + { + if (op & 0x4) { - int mode = gmode | ((op & (1 << 24)) ? 0x10 : 0); - - switch (mode) - { - case 0x00: // Format 2: Move || Local - { - buffer += util::string_format("move||local <TODO>"); - break; - } - case 0x01: // Format 3: Field Move || Local - { - buffer += util::string_format("field move||local <TODO>"); - 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; + // 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; - int reg = (4 << 3) | d; + m_alu_condition = make_condition(cond, ncvz); - 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; + bool r = (op & (1 << 29)) ? true : false; - int reg = (bank << 3) | d; + if (r) + m_parallel_condition = util::string_format("%s", make_condition(cond, ncvz)); - uint16_t offset; - if (s) - { - offset = op & 0x7fff; - if (offset & 0x4000) - offset |= 0xc000; - } - else - { - offset = op & 0x7fff; - } + 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; + } - 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; - } + case 1: + { + // 3. Field Move||Local + // TODO: not used by any program so far + m_parallel_transfer = util::string_format("field move || local"); + break; + } - util::stream_format(*output, ", "); + 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; + } - // 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; - } + 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; } } } - - if (!is_nop) - util::stream_format(*output, " || %s", buffer); + 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 <TODO>"); + 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, "<reserved>"); 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("<reserved>"); 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 diff --git a/src/devices/cpu/tms32082/mp_ops.cpp b/src/devices/cpu/tms32082/mp_ops.cpp index 0411e6996b6..5a81b500b13 100644 --- a/src/devices/cpu/tms32082/mp_ops.cpp +++ b/src/devices/cpu/tms32082/mp_ops.cpp @@ -21,21 +21,6 @@ #define OP_P2() ((m_ir >> 7) & 0x3) #define OP_ACC() ((m_ir >> 15) & 0x2) | ((m_ir >> 11) & 1) -#define ROTATE_L(x, r) ((x << r) | (x >> (32-r))) -#define ROTATE_R(x, r) ((x >> r) | (x << (32-r))) - -#define CMP_OVERFLOW32(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0) -#define CMP_OVERFLOW16(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0) -#define CMP_OVERFLOW8(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0) -#define CARRY32(x) (((x) & (((uint64_t)1) << 32)) ? 1 : 0) -#define CARRY16(x) (((x) & 0x10000) ? 1 : 0) -#define CARRY8(x) (((x) & 0x100) ? 1 : 0) -#define SIGN32(x) (((x) & 0x80000000) ? 1 : 0) -#define SIGN16(x) (((x) & 0x8000) ? 1 : 0) -#define SIGN8(x) (((x) & 0x80) ? 1 : 0) - -#define SIGN_EXTEND(x, r) ((x) | (((x) & (0x80000000 >> r)) ? ((int32_t)(0x80000000) >> r) : 0)) - bool tms32082_mp_device::test_condition(int condition, uint32_t value) @@ -72,63 +57,64 @@ bool tms32082_mp_device::test_condition(int condition, uint32_t value) uint32_t tms32082_mp_device::calculate_cmp(uint32_t src1, uint32_t src2) { - uint16_t src1_16 = (uint16_t)(src1); - uint8_t src1_8 = (uint8_t)(src1); - uint16_t src2_16 = (uint16_t)(src2); - uint8_t src2_8 = (uint8_t)(src2); - - uint64_t res32 = (uint64_t)src1 - (uint64_t)src2; - int z32 = (res32 == 0) ? 1 : 0; - int n32 = SIGN32(res32); - int v32 = CMP_OVERFLOW32(res32, src2, src1); - int c32 = CARRY32(res32); - - uint32_t res16 = (uint32_t)src1_16 - (uint32_t)src2_16; - int z16 = (res16 == 0) ? 1 : 0; - int n16 = SIGN16(res16); - int v16 = CMP_OVERFLOW16(res16, src2_16, src1_16); - int c16 = CARRY16(res16); - - uint16_t res8 = (uint16_t)src1_8 - (uint16_t)src2_8; - int z8 = (res8 == 0) ? 1 : 0; - int n8 = SIGN8(res8); - int v8 = CMP_OVERFLOW8(res8, src2_8, src1_8); - int c8 = CARRY8(res8); + int32_t a32 = (uint32_t)(src1); + int16_t a16 = (uint16_t)(src1); + int8_t a8 = (uint8_t)(src1); + int32_t b32 = (uint32_t)(src2); + int16_t b16 = (uint16_t)(src2); + int8_t b8 = (uint8_t)(src2); + + int32_t res32 = a32 - b32; + int16_t res16 = a16 - b16; + int8_t res8 = a8 - b8; + + int z32 = res32 == 0; + int n32 = ((res32) & 0x80000000) ? 1 : 0; + int v32 = ((((a32) ^ (b32)) & ((a32) ^ (res32))) & 0x80000000) ? 1 : 0; + int c32 = (!((uint32_t)a32 < (uint32_t)b32)) ? 1 : 0; + int z16 = res16 == 0; + int n16 = ((res16) & 0x8000) ? 1 : 0; + int v16 = ((((a16) ^ (b16)) & ((a16) ^ (res16))) & 0x8000) ? 1 : 0; + int c16 = (!((uint16_t)a16 < (uint16_t)b16)) ? 1 : 0; + int z8 = res8 == 0; + int n8 = ((res8) & 0x80) ? 1 : 0; + int v8 = ((((a8) ^ (b8)) & ((a8) ^ (res8))) & 0x80) ? 1 : 0; + int c8 = (!((uint8_t)a8 < (uint8_t)b8)) ? 1 : 0; uint32_t flags = 0; // 32-bits (bits 20-29) - flags |= ((~c32) & 1) << 29; // higher than or same (C) - flags |= ((c32) & 1) << 28; // lower than (~C) - flags |= ((c32|z32) & 1) << 27; // lower than or same (~C|Z) - flags |= ((~c32&~z32) & 1) << 26; // higher than (C&~Z) - flags |= (((n32&v32)|(~n32&~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V) - flags |= (((n32&~v32)|(~n32&v32)) & 1) << 24; // less than (N&~V)|(~N&V) - flags |= (((n32&~v32)|(~n32&v32)|(z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z - flags |= (((n32&v32&~z32)|(~n32&~v32&~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z) - flags |= ((~z32) & 1) << 21; // not equal (~Z) - flags |= ((z32) & 1) << 20; // equal (Z) + flags |= ((c32) & 1) << 29; // higher than or same (C) + flags |= ((~c32) & 1) << 28; // lower than (~C) + flags |= ((~c32 | z32) & 1) << 27; // lower than or same (~C|Z) + flags |= ((c32 & ~z32) & 1) << 26; // higher than (C&~Z) + flags |= (((n32 & v32) | (~n32 & ~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V) + flags |= (((n32 & ~v32) | (~n32 & v32)) & 1) << 24; // less than (N&~V)|(~N&V) + flags |= (((n32 & ~v32) | (~n32 & v32) | (z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z + flags |= (((n32 & v32 & ~z32) | (~n32 & ~v32 & ~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z) + flags |= ((~z32) & 1) << 21; // not equal (~Z) + flags |= ((z32) & 1) << 20; // equal (Z) // 16-bits (bits 10-19) - flags |= ((~c16) & 1) << 19; // higher than or same (C) - flags |= ((c16) & 1) << 18; // lower than (~C) - flags |= ((c16|z16) & 1) << 17; // lower than or same (~C|Z) - flags |= ((~c16&~z16) & 1) << 16; // higher than (C&~Z) - flags |= (((n16&v16)|(~n16&~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V) - flags |= (((n16&~v16)|(~n16&v16)) & 1) << 14; // less than (N&~V)|(~N&V) - flags |= (((n16&~v16)|(~n16&v16)|(z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z - flags |= (((n16&v16&~z16)|(~n16&~v16&~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z) - flags |= ((~z16) & 1) << 11; // not equal (~Z) - flags |= ((z16) & 1) << 10; // equal (Z) + flags |= ((c16) & 1) << 19; // higher than or same (C) + flags |= ((~c16) & 1) << 18; // lower than (~C) + flags |= ((~c16 | z16) & 1) << 17; // lower than or same (~C|Z) + flags |= ((c16 & ~z16) & 1) << 16; // higher than (C&~Z) + flags |= (((n16 & v16) | (~n16 & ~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V) + flags |= (((n16 & ~v16) | (~n16 & v16)) & 1) << 14; // less than (N&~V)|(~N&V) + flags |= (((n16 & ~v16) | (~n16 & v16) | (z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z + flags |= (((n16 & v16 & ~z16) | (~n16 & ~v16 & ~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z) + flags |= ((~z16) & 1) << 11; // not equal (~Z) + flags |= ((z16) & 1) << 10; // equal (Z) // 8-bits (bits 0-9) - flags |= ((~c8) & 1) << 9; // higher than or same (C) - flags |= ((c8) & 1) << 8; // lower than (~C) - flags |= ((c8|z8) & 1) << 7; // lower than or same (~C|Z) - flags |= ((~c8&~z8) & 1) << 6; // higher than (C&~Z) - flags |= (((n8&v8)|(~n8&~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V) - flags |= (((n8&~v8)|(~n8&v8)) & 1) << 4; // less than (N&~V)|(~N&V) - flags |= (((n8&~v8)|(~n8&v8)|(z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z - flags |= (((n8&v8&~z8)|(~n8&~v8&~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z) - flags |= ((~z8) & 1) << 1; // not equal (~Z) - flags |= ((z8) & 1) << 0; // equal (Z) + flags |= ((c8) & 1) << 9; // higher than or same (C) + flags |= ((~c8) & 1) << 8; // lower than (~C) + flags |= ((~c8 | z8) & 1) << 7; // lower than or same (~C|Z) + flags |= ((c8 & ~z8) & 1) << 6; // higher than (C&~Z) + flags |= (((n8 & v8) | (~n8 & ~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V) + flags |= (((n8 & ~v8) | (~n8 & v8)) & 1) << 4; // less than (N&~V)|(~N&V) + flags |= (((n8 & ~v8) | (~n8 & v8) | (z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z + flags |= (((n8 & v8 & ~z8) | (~n8 & ~v8 & ~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z) + flags |= ((~z8) & 1) << 1; // not equal (~Z) + flags |= ((z8) & 1) << 0; // equal (Z) return flags; } @@ -142,38 +128,38 @@ void tms32082_mp_device::vector_loadstore() { case 0x01: // vst.s { - m_program->write_dword(m_outp, m_reg[rd]); + m_program.write_dword(m_outp, m_reg[rd]); m_outp += 4; break; } case 0x03: // vst.d { uint64_t data = m_fpair[rd >> 1]; - m_program->write_qword(m_outp, data); + m_program.write_qword(m_outp, data); m_outp += 8; break; } case 0x04: // vld0.s { - m_reg[rd] = m_program->read_dword(m_in0p); + m_reg[rd] = m_program.read_dword(m_in0p); m_in0p += 4; break; } case 0x05: // vld1.s { - m_reg[rd] = m_program->read_dword(m_in1p); + m_reg[rd] = m_program.read_dword(m_in1p); m_in1p += 4; break; } case 0x06: // vld0.d { - m_fpair[rd >> 1] = m_program->read_qword(m_in0p); + m_fpair[rd >> 1] = m_program.read_qword(m_in0p); m_in0p += 8; break; } case 0x07: // vld1.d { - m_fpair[rd >> 1] = m_program->read_qword(m_in1p); + m_fpair[rd >> 1] = m_program.read_qword(m_in1p); m_in1p += 8; break; } @@ -257,11 +243,11 @@ void tms32082_mp_device::execute_short_imm() uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; + res = rotr_32(source, rot) & compmask; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -286,12 +272,14 @@ void tms32082_mp_device::execute_short_imm() uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; - res = SIGN_EXTEND(res, rot); + res = rotr_32(source, rot) & compmask; + // sign extend + if (res & (1 << (end - 1))) + res |= 0xffffffff << end; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; // sign extend makes no sense to left.. } @@ -312,18 +300,17 @@ void tms32082_mp_device::execute_short_imm() uint32_t endmask = SHIFT_MASK[end ? end : 32]; if (inv) endmask = ~endmask; - int shift = r ? 32-rot : rot; - uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32]; + uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot]; uint32_t compmask = endmask & shiftmask; uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; + res = rotr_32(source, rot) & compmask; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -349,11 +336,11 @@ void tms32082_mp_device::execute_short_imm() uint32_t res; if (r) // right { - res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask); + res = (rotr_32(source, rot) & compmask) | (m_reg[rd] & ~compmask); } else // left { - res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask); + res = (rotl_32(source, rot) & compmask) | (m_reg[rd] & ~compmask); } if (rd) @@ -373,19 +360,20 @@ void tms32082_mp_device::execute_short_imm() uint32_t endmask = SHIFT_MASK[end ? end : 32]; if (inv) endmask = ~endmask; - int shift = r ? 32-rot : rot; - uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32]; + uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot]; uint32_t compmask = endmask & shiftmask; uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; - res = SIGN_EXTEND(res, rot); + res = rotr_32(source, rot) & compmask; + // sign extend + if (res & (1 << (31 - rot))) + res |= 0xffffffff << (31 - rot); } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; // sign extend makes no sense to left.. } @@ -412,11 +400,11 @@ void tms32082_mp_device::execute_short_imm() uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; + res = rotr_32(source, rot) & compmask; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -442,11 +430,11 @@ void tms32082_mp_device::execute_short_imm() uint32_t res; if (r) // right { - res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask); + res = (rotr_32(source, rot) & compmask) | (m_reg[rd] & ~compmask); } else // left { - res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask); + res = (rotl_32(source, rot) & compmask) | (m_reg[rd] & ~compmask); } if (rd) @@ -518,7 +506,7 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data = (uint8_t)m_program->read_byte(address); + uint32_t data = (uint8_t)m_program.read_byte(address); if (data & 0x80) data |= 0xffffff00; if (rd) m_reg[rd] = data; @@ -537,7 +525,7 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data = (uint16_t)m_program->read_word(address); + uint32_t data = (uint16_t)m_program.read_word(address); if (data & 0x8000) data |= 0xffff0000; if (rd) m_reg[rd] = data; @@ -556,7 +544,7 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data = m_program->read_dword(address); + uint32_t data = m_program.read_dword(address); if (rd) m_reg[rd] = data; @@ -574,8 +562,8 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data1 = m_program->read_dword(address); - uint32_t data2 = m_program->read_dword(address+4); + uint32_t data1 = m_program.read_dword(address); + uint32_t data2 = m_program.read_dword(address+4); if (rd) { m_reg[(rd & ~1)+1] = data1; @@ -596,7 +584,7 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data = (uint8_t)(m_program->read_byte(address)); + uint32_t data = (uint8_t)(m_program.read_byte(address)); if (rd) m_reg[rd] = data; @@ -614,7 +602,7 @@ void tms32082_mp_device::execute_short_imm() int32_t offset = OP_SIMM15(); uint32_t address = m_reg[base] + offset; - uint32_t data = (uint16_t)(m_program->read_word(address)); + uint32_t data = (uint16_t)(m_program.read_word(address)); if (rd) m_reg[rd] = data; @@ -633,7 +621,7 @@ void tms32082_mp_device::execute_short_imm() uint32_t address = m_reg[base] + offset; - m_program->write_byte(address, (uint8_t)(m_reg[rd])); + m_program.write_byte(address, (uint8_t)(m_reg[rd])); if (m && base) m_reg[base] = address; @@ -650,7 +638,7 @@ void tms32082_mp_device::execute_short_imm() uint32_t address = m_reg[base] + offset; - m_program->write_word(address, (uint16_t)(m_reg[rd])); + m_program.write_word(address, (uint16_t)(m_reg[rd])); if (m && base) m_reg[base] = address; @@ -667,7 +655,7 @@ void tms32082_mp_device::execute_short_imm() uint32_t address = m_reg[base] + offset; - m_program->write_dword(address, m_reg[rd]); + m_program.write_dword(address, m_reg[rd]); if (m && base) m_reg[base] = address; @@ -684,8 +672,8 @@ void tms32082_mp_device::execute_short_imm() uint32_t address = m_reg[base] + offset; - m_program->write_dword(address+0, m_reg[(rd & ~1) + 1]); - m_program->write_dword(address+4, m_reg[rd & ~1]); + m_program.write_dword(address+0, m_reg[(rd & ~1) + 1]); + m_program.write_dword(address+4, m_reg[rd & ~1]); if (m && base) m_reg[base] = address; @@ -885,26 +873,25 @@ void tms32082_mp_device::execute_reg_long_imm() { int r = (m_ir & (1 << 10)); int inv = (m_ir & (1 << 11)); - int rot = m_reg[OP_ROTATE()]; + int rot = m_reg[OP_ROTATE()] & 0x1f; int end = OP_ENDMASK(); uint32_t source = m_reg[OP_RS()]; int rd = OP_RD(); - uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1]; + uint32_t endmask = end ? SHIFT_MASK[end] : 0xffffffff; if (inv) endmask = ~endmask; - int shift = r ? 32-rot : rot; - uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32]; + uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot]; uint32_t compmask = endmask & shiftmask; uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; + res = rotr_32(source, rot) & compmask; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -916,27 +903,28 @@ void tms32082_mp_device::execute_reg_long_imm() { int r = (m_ir & (1 << 10)); int inv = (m_ir & (1 << 11)); - int rot = m_reg[OP_ROTATE()]; + int rot = m_reg[OP_ROTATE()] & 0x1f; int end = OP_ENDMASK(); uint32_t source = m_reg[OP_RS()]; int rd = OP_RD(); - uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1]; + uint32_t endmask = SHIFT_MASK[end ? end : 32]; if (inv) endmask = ~endmask; - int shift = r ? 32-rot : rot; - uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32]; + uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot]; uint32_t compmask = endmask & shiftmask; uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; - res = SIGN_EXTEND(res, rot); + res = rotr_32(source, rot) & compmask; + // sign extend + if (res & (1 << (31 - rot))) + res |= 0xffffffff << (31 - rot); } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -948,26 +936,25 @@ void tms32082_mp_device::execute_reg_long_imm() { int r = (m_ir & (1 << 10)); int inv = (m_ir & (1 << 11)); - int rot = m_reg[OP_ROTATE()]; + int rot = m_reg[OP_ROTATE()] & 0x1f; int end = OP_ENDMASK(); uint32_t source = m_reg[OP_RS()]; int rd = OP_RD(); - uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1]; + uint32_t endmask = end ? SHIFT_MASK[end] : 0xffffffff; if (inv) endmask = ~endmask; - int shift = r ? 32-rot : rot; - uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32]; + uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot]; uint32_t compmask = endmask & ~shiftmask; uint32_t res; if (r) // right { - res = ROTATE_R(source, rot) & compmask; + res = rotr_32(source, rot) & compmask; } else // left { - res = ROTATE_L(source, rot) & compmask; + res = rotl_32(source, rot) & compmask; } if (rd) @@ -1043,7 +1030,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]); - uint32_t r = m_program->read_byte(address); + uint32_t r = m_program.read_byte(address); if (r & 0x80) r |= 0xffffff00; if (rd) @@ -1066,7 +1053,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - uint32_t r = m_program->read_word(address); + uint32_t r = m_program.read_word(address); if (r & 0x8000) r |= 0xffff0000; if (rd) @@ -1088,7 +1075,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - uint32_t r = m_program->read_dword(address); + uint32_t r = m_program.read_dword(address); if (rd) m_reg[rd] = r; @@ -1109,7 +1096,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - uint64_t r = m_program->read_qword(address); + uint64_t r = m_program.read_qword(address); if (rd) m_fpair[rd >> 1] = r; @@ -1129,7 +1116,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]); - uint32_t r = (uint8_t)(m_program->read_byte(address)); + uint32_t r = (uint8_t)(m_program.read_byte(address)); if (rd) m_reg[rd] = r; @@ -1150,7 +1137,7 @@ void tms32082_mp_device::execute_reg_long_imm() int rd = OP_RD(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - uint32_t r = (uint16_t)(m_program->read_word(address)); + uint32_t r = (uint16_t)(m_program.read_word(address)); if (rd) m_reg[rd] = r; @@ -1170,7 +1157,7 @@ void tms32082_mp_device::execute_reg_long_imm() int base = OP_BASE(); uint32_t address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]); - m_program->write_byte(address, (uint8_t)(m_reg[OP_RD()])); + m_program.write_byte(address, (uint8_t)(m_reg[OP_RD()])); if (m && base) m_reg[base] = address; @@ -1188,7 +1175,7 @@ void tms32082_mp_device::execute_reg_long_imm() int base = OP_BASE(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - m_program->write_word(address, (uint16_t)(m_reg[OP_RD()])); + m_program.write_word(address, (uint16_t)(m_reg[OP_RD()])); if (m && base) m_reg[base] = address; @@ -1206,7 +1193,7 @@ void tms32082_mp_device::execute_reg_long_imm() int base = OP_BASE(); uint32_t address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); - m_program->write_dword(address, m_reg[OP_RD()]); + m_program.write_dword(address, m_reg[OP_RD()]); if (m && base) m_reg[base] = address; @@ -1301,29 +1288,30 @@ void tms32082_mp_device::execute_reg_long_imm() int ls_bit1 = m_ir & (1 << 10); int ls_bit2 = m_ir & (1 << 6); int rd = OP_RS(); - int src1 OP_SRC1(); + int src1 = OP_SRC1(); double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[src1 >> 1]) : (double)u2f(m_reg[src1])); + double source2 = pd ? u2d(m_fpair[rd >> 1]) : (double)(u2f(m_reg[rd])); + + // parallel load/store op + if (!(ls_bit1 == 0 && ls_bit2 == 0)) + { + vector_loadstore(); + } if (rd) { if (pd) { - double res = source * u2d(m_fpair[rd >> 1]); + double res = source * source2; m_fpair[rd >> 1] = d2u(res); } else { - float res = (float)(source) * u2f(m_reg[rd]); + float res = (float)(source * source2); m_reg[rd] = f2u(res); } } - - // parallel load/store op - if (!(ls_bit1 == 0 && ls_bit2 == 0)) - { - vector_loadstore(); - } break; } @@ -1342,6 +1330,12 @@ void tms32082_mp_device::execute_reg_long_imm() double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1])); + // parallel load/store op + if (!(ls_bit1 == 0 && ls_bit2 == 0)) + { + vector_loadstore(); + } + if (rd) { // destination register @@ -1369,12 +1363,6 @@ void tms32082_mp_device::execute_reg_long_imm() m_facc[acc] = source; } - - // parallel load/store op - if (!(ls_bit1 == 0 && ls_bit2 == 0)) - { - vector_loadstore(); - } break; } @@ -1390,7 +1378,7 @@ void tms32082_mp_device::execute_reg_long_imm() int ls_bit2 = m_ir & (1 << 6); int rd = OP_RD(); - float src1 = u2f(m_reg[OP_SRC1()]); + float src1 = has_imm ? u2f(imm32) : u2f(m_reg[OP_SRC1()]); float src2 = u2f(m_reg[OP_RS()]); float res = (src1 * src2) + (z ? 0.0f : m_facc[acc]); @@ -1412,7 +1400,7 @@ void tms32082_mp_device::execute_reg_long_imm() else m_reg[rd] = f2u((float)res); } - else + else if (pd) { // write to accumulator m_facc[acc] = (double)res; @@ -1433,7 +1421,7 @@ void tms32082_mp_device::execute_reg_long_imm() int ls_bit2 = m_ir & (1 << 6); int rd = OP_RD(); - float src1 = u2f(m_reg[OP_SRC1()]); + float src1 = has_imm ? u2f(imm32) : u2f(m_reg[OP_SRC1()]); float src2 = u2f(m_reg[OP_RS()]); float res = (z ? 0.0f : m_facc[acc]) - (src1 * src2); @@ -1455,7 +1443,7 @@ void tms32082_mp_device::execute_reg_long_imm() else m_reg[rd] = f2u((float)res); } - else + else if (pd) { // write to accumulator m_facc[acc] = (double)res; @@ -1501,7 +1489,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x11: // DP - SP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); float s2 = u2f(m_reg[rs]); uint64_t res = d2u(s1 + (double) s2); m_fpair[rd >> 1] = res; @@ -1509,7 +1497,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x15: // DP - DP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); double s2 = u2d(m_fpair[rs >> 1]); uint64_t res = d2u((double)(s1 + s2)); m_fpair[rd >> 1] = res; @@ -1559,7 +1547,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x11: // DP - SP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); float s2 = u2f(m_reg[rs]); uint64_t res = d2u(s1 - (double) s2); m_fpair[rd >> 1] = res; @@ -1567,7 +1555,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x15: // DP - DP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); double s2 = u2d(m_fpair[rs >> 1]); uint64_t res = d2u((double)(s1 - s2)); m_fpair[rd >> 1] = res; @@ -1617,7 +1605,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x11: // DP x SP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); float s2 = u2f(m_reg[rs]); uint64_t res = d2u(s1 * (double) s2); m_fpair[rd >> 1] = res; @@ -1625,7 +1613,7 @@ void tms32082_mp_device::execute_reg_long_imm() } case 0x15: // DP x DP -> DP { - double s1 = u2d(m_fpair[src1 >> 1]); + double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]); double s2 = u2d(m_fpair[rs >> 1]); uint64_t res = d2u(s1 * s2); m_fpair[rd >> 1] = res; @@ -1694,7 +1682,7 @@ void tms32082_mp_device::execute_reg_long_imm() s = has_imm ? (double)(u2f(imm32)) : (double)u2f(m_reg[src1]); break; case 1: - s = u2d(m_fpair[src1 >> 1]); + s = has_imm ? (double)(u2f(imm32)) : u2d(m_fpair[src1 >> 1]); break; case 2: s = has_imm ? (double)((int32_t)(imm32)) : (double)(int32_t)(m_reg[src1]); @@ -1794,9 +1782,9 @@ void tms32082_mp_device::execute_reg_long_imm() for (int i=0; i < 32; i++) { - if (source & (1 << (31-i))) + if (source & (1 << i)) { - bit = i; + bit = 31 - i; break; } } diff --git a/src/devices/cpu/tms32082/tms32082.cpp b/src/devices/cpu/tms32082/tms32082.cpp index 3ccebccd923..7b1486470c0 100644 --- a/src/devices/cpu/tms32082/tms32082.cpp +++ b/src/devices/cpu/tms32082/tms32082.cpp @@ -11,7 +11,6 @@ #include "tms32082.h" #include "dis_pp.h" #include "dis_mp.h" -#include "debugger.h" DEFINE_DEVICE_TYPE(TMS32082_MP, tms32082_mp_device, "tms32082_mp", "Texas Instruments TMS32082 MP") DEFINE_DEVICE_TYPE(TMS32082_PP, tms32082_pp_device, "tms32082_pp", "Texas Instruments TMS32082 PP") @@ -47,6 +46,7 @@ const uint32_t tms32082_mp_device::SHIFT_MASK[] = tms32082_mp_device::tms32082_mp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, TMS32082_MP, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(tms32082_mp_device::mp_internal_map), this)) + , m_cmd_callback(*this) { } @@ -70,46 +70,38 @@ std::unique_ptr<util::disasm_interface> tms32082_mp_device::create_disassembler( return std::make_unique<tms32082_mp_disassembler>(); } -void tms32082_mp_device::set_command_callback(write32_delegate callback) -{ - m_cmd_callback = callback; -} - -READ32_MEMBER(tms32082_mp_device::mp_param_r) +void tms32082_mp_device::tc_command_execute(int channel, uint32_t entrypoint) { - //printf("mp_param_w: %08X, %08X\n", offset, mem_mask); - return m_param_ram[offset]; -} + [[maybe_unused]] static const char* CHANNEL_NAME[16] = { + "XPT15", "XPT14", "XPT13", "XPT12", "XPT11", "XPT10", "XPT9", "XPT8", + "XPT7", "XPT6", "XPT5", "XPT4", "XPT3", "XPT2", "XPT1", "MP" + }; -WRITE32_MEMBER(tms32082_mp_device::mp_param_w) -{ - //printf("mp_param_w: %08X, %08X, %08X\n", offset, data, mem_mask); + uint32_t address = entrypoint; - COMBINE_DATA(&m_param_ram[offset]); + uint32_t next_entry = m_program.read_dword(address + 0); + uint32_t pt_options = m_program.read_dword(address + 4); - if (offset == 0x3f) + if ((pt_options & 0x00100000) == 0) { - // initiate Transfer Controller operation - // TODO: move TC functionality to separate device - uint32_t address = data; - - uint32_t next_entry = m_program->read_dword(address + 0); - uint32_t pt_options = m_program->read_dword(address + 4); - uint32_t src_addr = m_program->read_dword(address + 8); - uint32_t dst_addr = m_program->read_dword(address + 12); - uint32_t src_b_count = m_program->read_word(address + 16); - uint32_t src_a_count = m_program->read_word(address + 18); - uint32_t dst_b_count = m_program->read_word(address + 20); - uint32_t dst_a_count = m_program->read_word(address + 22); - uint32_t src_c_count = m_program->read_dword(address + 24); - uint32_t dst_c_count = m_program->read_dword(address + 28); - uint32_t src_b_pitch = m_program->read_dword(address + 32); - uint32_t dst_b_pitch = m_program->read_dword(address + 36); - uint32_t src_c_pitch = m_program->read_dword(address + 40); - uint32_t dst_c_pitch = m_program->read_dword(address + 44); - - printf("TC operation:\n"); + // long-form transfer + + uint32_t src_addr = m_program.read_dword(address + 8); + uint32_t dst_addr = m_program.read_dword(address + 12); + uint32_t src_b_count = m_program.read_word(address + 16); + uint32_t src_a_count = m_program.read_word(address + 18); + // uint32_t dst_b_count = m_program.read_word(address + 20); + // uint32_t dst_a_count = m_program.read_word(address + 22); + uint32_t src_c_count = m_program.read_dword(address + 24); + // uint32_t dst_c_count = m_program.read_dword(address + 28); + uint32_t src_b_pitch = m_program.read_dword(address + 32); + uint32_t dst_b_pitch = m_program.read_dword(address + 36); + uint32_t src_c_pitch = m_program.read_dword(address + 40); + uint32_t dst_c_pitch = m_program.read_dword(address + 44); + + /* + printf("TC operation (long form) %s:\n", CHANNEL_NAME[channel]); printf(" Next entry: %08X\n", next_entry); printf(" PT options: %08X\n", pt_options); printf(" SRC addr: %08X\n", src_addr); @@ -122,6 +114,7 @@ WRITE32_MEMBER(tms32082_mp_device::mp_param_w) printf(" DST B pitch: %08X\n", dst_b_pitch); printf(" SRC C pitch: %08X\n", src_c_pitch); printf(" DST C pitch: %08X\n", dst_c_pitch); + */ if (pt_options != 0x80000000) fatalerror("TC transfer, options = %08X\n", pt_options); @@ -141,21 +134,73 @@ WRITE32_MEMBER(tms32082_mp_device::mp_param_w) uint32_t src = src_addr + c_src_offset + b_src_offset + ia; uint32_t dst = dst_addr + c_dst_offset + b_dst_offset + ia; - uint32_t data = m_program->read_byte(src); - m_program->write_byte(dst, data); + uint32_t data = m_program.read_byte(src); + m_program.write_byte(dst, data); //printf("%08X: %02X -> %08X\n", src, data, dst); } } } } + else + { + // short-form transfer + + bool stop = false; + + do + { + + // uint32_t src_addr = m_program.read_dword(address + 8); + // uint32_t dst_addr = m_program.read_dword(address + 12); + + // int count = pt_options & 0xffff; + stop = (pt_options & 0x80000000) ? true : false; + + /* + printf("TC operation (short form) %s [%08X]:\n", CHANNEL_NAME[channel], address); + printf(" Next entry: %08X\n", next_entry); + printf(" PT options: %08X\n", pt_options); + printf(" Byte count: %08X\n", count); + printf(" SRC addr: %08X\n", src_addr); + printf(" DST addr: %08X\n", dst_addr); + */ + + address = next_entry; + if (!stop) + { + next_entry = m_program.read_dword(address); + pt_options = m_program.read_dword(address + 4); + } + } while (!stop); + } +} + + +uint32_t tms32082_mp_device::mp_param_r(offs_t offset, uint32_t mem_mask) +{ + //printf("mp_param_w: %08X, %08X\n", offset, mem_mask); + return m_param_ram[offset]; +} + +void tms32082_mp_device::mp_param_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + //printf("mp_param_w: %08X, %08X, %08X\n", offset, data, mem_mask); + + COMBINE_DATA(&m_param_ram[offset]); + + if (offset >= 0x30 && offset <= 0x3f) + { + tc_command_execute(offset - 0x30, data); + } } void tms32082_mp_device::device_start() { - m_program = &space(AS_PROGRAM); + space(AS_PROGRAM).specific(m_program); + m_cmd_callback.resolve(); save_item(NAME(m_pc)); save_item(NAME(m_fetchpc)); @@ -221,8 +266,8 @@ void tms32082_mp_device::device_start() state_add(STATE_GENPC, "GENPC", m_pc).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); - m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); + space(AS_PROGRAM).cache(m_cache); + space(AS_PROGRAM).specific(m_program); set_icountptr(m_icount); } @@ -258,48 +303,32 @@ void tms32082_mp_device::device_reset() m_intpen = 0; m_ie = 0; + + m_pp_status = 0xf0000; // start with all PPs halted } void tms32082_mp_device::processor_command(uint32_t command) { - printf("MP CMND %08X: ", command); + // unhalt PPs + if (command & 0x20000000) + { + if (command & 0x00000001) + m_pp_status &= ~0x10000; + if (command & 0x00000002) + m_pp_status &= ~0x20000; + } - if (command & 0x80000000) - printf("Reset "); + // halt PPs if (command & 0x40000000) - printf("Halt "); - if (command & 0x20000000) - printf("Unhalt "); - if (command & 0x10000000) - printf("ICR "); - if (command & 0x08000000) - printf("DCR "); - if (command & 0x00004000) - printf("Task "); - if (command & 0x00002000) - printf("Msg "); - - printf("to: "); - - if (command & 0x00000400) - printf("VC "); - if (command & 0x00000200) - printf("TC "); - if (command & 0x00000100) - printf("MP "); - if (command & 0x00000008) - printf("PP3 "); - if (command & 0x00000004) - printf("PP2 "); - if (command & 0x00000002) - printf("PP1 "); - if (command & 0x00000001) - printf("PP0 "); + { + if (command & 0x00000001) + m_pp_status |= 0x10000; + if (command & 0x00000002) + m_pp_status |= 0x20000; + } if (!m_cmd_callback.isnull()) - m_cmd_callback(*m_program, 0, command, 0xffffffff); - - printf("\n"); + m_cmd_callback(space(AS_PROGRAM), command); } uint32_t tms32082_mp_device::read_creg(int reg) @@ -312,6 +341,11 @@ uint32_t tms32082_mp_device::read_creg(int reg) case 0x1: // EIP return m_eip; + case 0x2: // CONFIG + // Type = 0010: 2 Parallel Processors + // Release = 0011: Production release silicon + return (0x2 << 12) | (0x3 << 4); + case 0x4: // INTPEN return m_intpen; @@ -319,7 +353,7 @@ uint32_t tms32082_mp_device::read_creg(int reg) return m_ie; case 0xa: // PPERROR - return 0xe0000; + return m_pp_status; case 0xe: // TCOUNT return m_tcount; @@ -334,7 +368,7 @@ uint32_t tms32082_mp_device::read_creg(int reg) return m_outp; default: - printf("read_creg(): %08X\n", reg); + //printf("read_creg(): %08X\n", reg); break; } return 0; @@ -364,7 +398,6 @@ void tms32082_mp_device::write_creg(int reg, uint32_t data) case 0x6: // IE m_ie = data; - printf("IE = %08X\n", data); break; case 0xe: // TCOUNT @@ -384,7 +417,7 @@ void tms32082_mp_device::write_creg(int reg, uint32_t data) break; default: - printf("write_creg(): %08X, %08X\n", reg, data); + //printf("write_creg(): %08X, %08X\n", reg, data); break; } } @@ -406,7 +439,7 @@ void tms32082_mp_device::check_interrupts() m_ie &= ~1; // clear global interrupt mask // get new pc from vector table - m_fetchpc = m_pc = m_program->read_dword(0x01010180 + (i * 4)); + m_fetchpc = m_pc = m_program.read_dword(0x01010180 + (i * 4)); return; } } @@ -439,7 +472,7 @@ void tms32082_mp_device::execute_set_input(int inputnum, int state) uint32_t tms32082_mp_device::fetch() { - uint32_t w = m_cache->read_dword(m_fetchpc); + uint32_t w = m_cache.read_dword(m_fetchpc); m_fetchpc += 4; return w; } @@ -509,7 +542,7 @@ std::unique_ptr<util::disasm_interface> tms32082_pp_device::create_disassembler( void tms32082_pp_device::device_start() { - m_program = &space(AS_PROGRAM); + space(AS_PROGRAM).specific(m_program); save_item(NAME(m_pc)); save_item(NAME(m_fetchpc)); @@ -520,8 +553,8 @@ void tms32082_pp_device::device_start() state_add(STATE_GENPC, "GENPC", m_pc).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); - m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); + space(AS_PROGRAM).cache(m_cache); + space(AS_PROGRAM).specific(m_program); set_icountptr(m_icount); } diff --git a/src/devices/cpu/tms32082/tms32082.h b/src/devices/cpu/tms32082/tms32082.h index d281ac0eb78..7a66698d9d6 100644 --- a/src/devices/cpu/tms32082/tms32082.h +++ b/src/devices/cpu/tms32082/tms32082.h @@ -68,22 +68,20 @@ public: INPUT_X4 = 4 }; - DECLARE_READ32_MEMBER(mp_param_r); - DECLARE_WRITE32_MEMBER(mp_param_w); + uint32_t mp_param_r(offs_t offset, uint32_t mem_mask = ~0); + void mp_param_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - void set_command_callback(write32_delegate callback); + template <typename... T> void set_command_callback(T &&... args) { m_cmd_callback.set(std::forward<T>(args)...); } - - void mp_internal_map(address_map &map); + void mp_internal_map(address_map &map) ATTR_COLD; protected: // device level overrides - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 1; } - virtual uint32_t execute_input_lines() const override { return 0; } + virtual uint32_t execute_min_cycles() const noexcept override { return 1; } + virtual uint32_t execute_max_cycles() const noexcept override { return 1; } virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; @@ -130,10 +128,12 @@ protected: int m_icount; - address_space *m_program; - memory_access_cache<2, 0, ENDIANNESS_BIG> * m_cache; + memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cache; + memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_program; + + write32mo_delegate m_cmd_callback; - write32_delegate m_cmd_callback; + uint32_t m_pp_status; void check_interrupts(); void processor_command(uint32_t command); @@ -147,6 +147,7 @@ protected: bool test_condition(int condition, uint32_t value); uint32_t calculate_cmp(uint32_t src1, uint32_t src2); void vector_loadstore(); + void tc_command_execute(int channel, uint32_t entrypoint); }; @@ -162,16 +163,15 @@ public: PP_PC = 1 }; - void pp_internal_map(address_map &map); + void pp_internal_map(address_map &map) ATTR_COLD; protected: // device level overrides - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 1; } - virtual uint32_t execute_input_lines() const override { return 0; } + virtual uint32_t execute_min_cycles() const noexcept override { return 1; } + virtual uint32_t execute_max_cycles() const noexcept override { return 1; } virtual void execute_run() override; // device_memory_interface overrides @@ -190,8 +190,8 @@ protected: int m_icount; - address_space *m_program; - memory_access_cache<2, 0, ENDIANNESS_BIG> * m_cache; + memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cache; + memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_program; }; |