summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms32082
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tms32082')
-rw-r--r--src/devices/cpu/tms32082/dis_mp.cpp16
-rw-r--r--src/devices/cpu/tms32082/dis_pp.cpp1069
-rw-r--r--src/devices/cpu/tms32082/dis_pp.h19
-rw-r--r--src/devices/cpu/tms32082/mp_ops.cpp310
-rw-r--r--src/devices/cpu/tms32082/tms32082.cpp199
-rw-r--r--src/devices/cpu/tms32082/tms32082.h42
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 &params)
{
- 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 &params) 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;
};