summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms32082
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/cpu/tms32082
parente92ac9e0fa8e99869894bea00589bbb526be30aa (diff)
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/cpu/tms32082')
-rw-r--r--src/devices/cpu/tms32082/dis_mp.c513
-rw-r--r--src/devices/cpu/tms32082/dis_pp.c714
-rw-r--r--src/devices/cpu/tms32082/mp_ops.c1821
-rw-r--r--src/devices/cpu/tms32082/tms32082.c597
-rw-r--r--src/devices/cpu/tms32082/tms32082.h214
5 files changed, 3859 insertions, 0 deletions
diff --git a/src/devices/cpu/tms32082/dis_mp.c b/src/devices/cpu/tms32082/dis_mp.c
new file mode 100644
index 00000000000..1b89eb88129
--- /dev/null
+++ b/src/devices/cpu/tms32082/dis_mp.c
@@ -0,0 +1,513 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+// TMS32082 MP Disassembler
+
+#include "emu.h"
+
+
+#define SIMM15(v) (INT32)((v & 0x4000) ? (v | 0xffffe000) : (v))
+#define UIMM15(v) (v)
+
+static const char *BCND_CONDITION[32] =
+{
+ "nev.b", "gt0.b", "eq0.b", "ge0.b", "lt0.b", "ne0.b", "le0.b", "alw.b",
+ "nev.h", "gt0.h", "eq0.h", "ge0.h", "lt0.h", "ne0.h", "le0.h", "alw.h",
+ "nev.w", "gt0.w", "eq0.w", "ge0.w", "lt0.w", "ne0.w", "le0.w", "alw.w",
+ "nev.d", "gt0.d", "eq0.d", "ge0.d", "lt0.d", "ne0.d", "le0.d", "alw.d",
+};
+
+static const char *BITNUM_CONDITION[32] =
+{
+ "eq.b", "ne.b", "gt.b", "le.b", "lt.b", "ge.b", "hi.b", "ls.b",
+ "lo.b", "hs.b", "eq.h", "ne.h", "gt.h", "le.h", "lt.h", "ge.h",
+ "hi.h", "ls.h", "lo.h", "hs.h", "eq.w", "ne.w", "gt.w", "le.w",
+ "lt.w", "ge.w", "hi.w", "ls.w", "lo.w", "hs.w", "?", "?",
+};
+
+static const char *MEMOP_S[2] =
+{
+ ":s", ""
+};
+
+static const char *MEMOP_M[2] =
+{
+ ":m", ""
+};
+
+static const char *FLOATOP_PRECISION[4] =
+{
+ "s", "d", "i", "u"
+};
+
+static const char *ACC_SEL[4] =
+{
+ "A0", "A1", "A2", "A3"
+};
+
+static const char *FLOATOP_ROUND[4] =
+{
+ "n", "z", "p", "m"
+};
+
+static char *output;
+static const UINT8 *opdata;
+static int opbytes;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ output += vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+static UINT32 fetch(void)
+{
+ UINT32 d = ((UINT32)(opdata[0]) << 24) | ((UINT32)(opdata[1]) << 16) | ((UINT32)(opdata[2]) << 8) | opdata[3];
+ opdata += 4;
+ opbytes += 4;
+ return d;
+}
+
+static char* get_creg_name(UINT32 reg)
+{
+ static char buffer[64];
+
+ switch (reg)
+ {
+ case 0x0000: sprintf(buffer, "EPC"); break;
+ case 0x0001: sprintf(buffer, "EIP"); break;
+ case 0x0002: sprintf(buffer, "CONFIG"); break;
+ case 0x0004: sprintf(buffer, "INTPEN"); break;
+ case 0x0006: sprintf(buffer, "IE"); break;
+ case 0x0008: sprintf(buffer, "FPST"); break;
+ case 0x000a: sprintf(buffer, "PPERROR"); break;
+ case 0x000d: sprintf(buffer, "PKTREQ"); break;
+ case 0x000e: sprintf(buffer, "TCOUNT"); break;
+ case 0x000f: sprintf(buffer, "TSCALE"); break;
+ case 0x0010: sprintf(buffer, "FLTOP"); break;
+ case 0x0011: sprintf(buffer, "FLTADR"); break;
+ case 0x0012: sprintf(buffer, "FLTTAG"); break;
+ case 0x0013: sprintf(buffer, "FLTDTL"); break;
+ case 0x0014: sprintf(buffer, "FLTDTH"); break;
+ case 0x0020: sprintf(buffer, "SYSSTK"); break;
+ case 0x0021: sprintf(buffer, "SYSTMP"); break;
+ case 0x0030: sprintf(buffer, "MPC"); break;
+ case 0x0031: sprintf(buffer, "MIP"); break;
+ case 0x0033: sprintf(buffer, "ECOMCNTL"); break;
+ case 0x0034: sprintf(buffer, "ANASTAT"); break;
+ case 0x0039: sprintf(buffer, "BRK1"); break;
+ case 0x003a: sprintf(buffer, "BRK2"); break;
+ case 0x4000: sprintf(buffer, "IN0P"); break;
+ case 0x4001: sprintf(buffer, "IN1P"); break;
+ case 0x4002: sprintf(buffer, "OUTP"); break;
+ default: sprintf(buffer, "CR %04X", reg);
+ }
+
+ return buffer;
+}
+
+static char* format_vector_op(UINT32 op, UINT32 imm32)
+{
+ static char buffer[256];
+ static char dest[64];
+ char *b = buffer;
+
+ int rd = (op >> 27) & 0x1f;
+ int rs = (op >> 22) & 0x1f;
+ int src1 = (op & 0x1f);
+ int subop = (op >> 12) & 0xff;
+ int vector_ls_bits = (((op >> 9) & 0x3) << 1) | ((op >> 6) & 1);
+
+ int p1 = (op >> 5) & 1;
+ int pd2 = (op >> 7) & 1;
+ int pd4 = (op >> 7) & 3;
+
+ int z = op & (1 << 8);
+
+ int acc = (((op >> 16) << 1) & 2) | ((op >> 11) & 1);
+ bool regdest = (op & (1 << 10)) == 0 && (op & (1 << 6)) == 0;
+
+ // accumulator or register destination
+ if (regdest)
+ sprintf(dest, "R%d", rd);
+ else
+ sprintf(dest, "A%d", acc);
+
+ // base op
+ switch (subop)
+ {
+ case 0xc0: b += sprintf(b, "vadd.%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], src1, rs, rs); break;
+ case 0xc1: b += sprintf(b, "vadd.%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], imm32, rs, rs); break;
+ case 0xc2: b += sprintf(b, "vsub.%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], rs, src1, rs); break;
+ case 0xc3: b += sprintf(b, "vsub.%s%s R%d, 0x%08X, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], rs, imm32, rs); break;
+ case 0xc4: b += sprintf(b, "vmpy.%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], src1, rs, rs); break;
+ case 0xc5: b += sprintf(b, "vmpy.%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd2], imm32, rs, rs); break;
+
+ case 0xd6: case 0xc6:
+ b += sprintf(b, "vmsub.s%s R%d, %s, R%d", FLOATOP_PRECISION[pd2], src1, z ? "0" : ACC_SEL[acc], rs);
+ break;
+ case 0xd7: case 0xc7:
+ b += sprintf(b, "vmsub.s%s 0x%08X, %s, R%d", FLOATOP_PRECISION[pd2], imm32, z ? "0" : ACC_SEL[acc], rs);
+ break;
+ case 0xd8: case 0xc8:
+ b += sprintf(b, "vrnd.%s%s R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd4], src1, rs);
+ break;
+ case 0xd9: case 0xc9:
+ b += sprintf(b, "vrnd.%s%s 0x%08X, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd4], imm32, rs);
+ break;
+
+ case 0xca: b += sprintf(b, "vrnd.%s%s R%d, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2],src1, rs); break;
+ case 0xcb: b += sprintf(b, "vrnd.%s%s 0x%08X, R%d", FLOATOP_PRECISION[2 + p1], FLOATOP_PRECISION[pd2], imm32, rs); break;
+
+ case 0xcc: case 0xdc:
+ b += sprintf(b, "vmac.ss%s R%d, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], src1, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest);
+ break;
+ case 0xcd: case 0xdd:
+ b += sprintf(b, "vmac.ss%s 0x%08X, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], imm32, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest);
+ break;
+ case 0xce: case 0xde:
+ b += sprintf(b, "vmsc.ss%s R%d, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], src1, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest);
+ break;
+ case 0xcf: case 0xdf:
+ b += sprintf(b, "vmsc.ss%s 0x%08X, R%d, %s, %s", FLOATOP_PRECISION[(op >> 9) & 1], imm32, rs, z ? "0" : ACC_SEL[acc], (regdest && rd == 0) ? ACC_SEL[acc] : dest);
+ break;
+
+ default: b += sprintf(b, "?"); break;
+ }
+
+ // align the line end
+ int len = strlen(buffer);
+ if (len < 30)
+ {
+ for (int i=0; i < (30-len); i++)
+ {
+ b += sprintf(b, " ");
+ }
+ }
+
+ // optional load/store op
+ switch (vector_ls_bits)
+ {
+ case 0x01: b += sprintf(b, "|| vst.s R%d", rd); break;
+ case 0x03: b += sprintf(b, "|| vst.d R%d", rd); break;
+ case 0x04: b += sprintf(b, "|| vld0.s R%d", rd); break;
+ case 0x05: b += sprintf(b, "|| vld1.s R%d", rd); break;
+ case 0x06: b += sprintf(b, "|| vld0.d R%d", rd); break;
+ case 0x07: b += sprintf(b, "|| vld1.d R%d", rd); break;
+ }
+
+ return buffer;
+}
+
+static offs_t tms32082_disasm_mp(char *buffer, offs_t pc, const UINT8 *oprom)
+{
+ output = buffer;
+ opdata = oprom;
+ opbytes = 0;
+ UINT32 flags = 0;
+
+ UINT32 op = fetch();
+
+ int rd = (op >> 27) & 0x1f;
+ int link = rd;
+ int bitnum = rd ^ 0x1f;
+ int rs = (op >> 22) & 0x1f;
+ int endmask = (op >> 5) & 0x1f;
+ int rotate = (op & 0x1f);
+ int src1 = rotate;
+ UINT32 uimm15 = op & 0x7fff;
+
+ switch ((op >> 20) & 3)
+ {
+ case 0: case 1: case 2: // Short immediate
+ {
+ int subop = (op >> 15) & 0x7f;
+ int m = op & (1 << 17) ? 0 : 1;
+
+ switch (subop)
+ {
+ case 0x00: print("illop0 "); break;
+ case 0x01: print("trap %d", UIMM15(uimm15)); break;
+ case 0x02: print("cmnd 0x%04X", UIMM15(uimm15)); break;
+ case 0x04: print("rdcr %s, R%d", get_creg_name(UIMM15(uimm15)), rd); break;
+ case 0x05: print("swcr R%d, %s, R%d", rd, get_creg_name(UIMM15(uimm15)), rs); break;
+ case 0x06: print("brcr %s", get_creg_name(UIMM15(uimm15))); break;
+ case 0x08: print("shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x09: print("shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0a: print("shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0b: print("shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0c: print("shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0d: print("shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0e: print("shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x0f: print("shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x11: print("and 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x12: print("and.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x14: print("and.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x16: print("xor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x17: print("or 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x18: print("and.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x19: print("xnor 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x1b: print("or.tf 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x1d: print("or.ft 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+ case 0x1e: print("or.ff 0x%04X, R%d, R%d", UIMM15(uimm15), rs, rd); break;
+
+ case 0x24: case 0x20:
+ print("ld.b 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+ case 0x25: case 0x21:
+ print("ld.h 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+ case 0x26: case 0x22:
+ print("ld 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+ case 0x27: case 0x23:
+ print("ld.d 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+ case 0x2c: case 0x28:
+ print("ld.ub 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+ case 0x2d: case 0x29:
+ print("ld.uh 0x%04X(R%d%s), R%d", UIMM15(uimm15), rs, MEMOP_M[m], rd);
+ break;
+
+ case 0x34: case 0x30:
+ print("st.b R%d, 0x%04X(R%d%s)", rd, UIMM15(uimm15), rs, MEMOP_M[m]);
+ break;
+ case 0x35: case 0x31:
+ print("st.h R%d, 0x%04X(R%d%s)", rd, UIMM15(uimm15), rs, MEMOP_M[m]);
+ break;
+ case 0x36: case 0x32:
+ print("st R%d, 0x%04X(R%d%s)", rd, UIMM15(uimm15), rs, MEMOP_M[m]);
+ break;
+ case 0x37: case 0x33:
+ print("st.d R%d, 0x%04X(R%d%s)", rd, UIMM15(uimm15), rs, MEMOP_M[m]);
+ break;
+
+ case 0x40: print("bsr 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break;
+ case 0x41: print("bsr.a 0x%08X, R%d", pc + (SIMM15(uimm15) * 4), link); break;
+ case 0x44: print("jsr 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break;
+ case 0x45: print("jsr.a 0x%04X(R%d), R%d", SIMM15(uimm15), rs, link); break;
+ case 0x48: print("bbz 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x49: print("bbz.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x4a: print("bbo 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x4b: print("bbo.a 0x%08X, R%d, %s (%d)", pc + (SIMM15(uimm15) * 4), rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x4c: print("bcnd 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break;
+ case 0x4d: print("bcnd.a 0x%08X, R%d, %s", pc + (SIMM15(uimm15) * 4), rs, BCND_CONDITION[rd]); break;
+ case 0x50: print("cmp 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break;
+ case 0x58: print("add 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break;
+ case 0x59: print("addu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break;
+ case 0x5a: print("sub 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break;
+ case 0x5b: print("subu 0x%08X, R%d, R%d", SIMM15(uimm15), rs, rd); break;
+
+ default: print("?"); break;
+ }
+ break;
+ }
+
+ case 3: // Register / Long immediate
+ {
+ int subop = (op >> 12) & 0xff;
+
+ UINT32 imm32 = 0;
+ if (op & (1 << 12)) // fetch 32-bit immediate if needed
+ imm32 = fetch();
+
+ int m = op & (1 << 15) ? 0 : 1;
+ int s = op & (1 << 11) ? 0 : 1;
+
+ int p1 = (op >> 5) & 3;
+ int p2 = (op >> 7) & 3;
+ int pd = (op >> 9) & 3;
+
+ int rndmode = (op >> 7) & 3;
+
+
+ switch (subop)
+ {
+ case 0x02: print("trap %d", src1); break;
+ case 0x03: print("trap %d", imm32); break;
+ case 0x04: print("cmnd R%d", src1); break;
+ case 0x05: print("cmnd 0x%08X", imm32); break;
+ case 0x08: print("rdcr R%d, R%d,", src1, rd); break;
+ case 0x09: print("rdcr %s, R%d", get_creg_name(imm32), rd); break;
+ case 0x0a: print("swcr R%d, R%d, R%d", rd, src1, rs); break;
+ case 0x0b: print("swcr R%d, %s, R%d", rd, get_creg_name(imm32), rs); break;
+ case 0x0c: print("brcr R%d", src1); break;
+ case 0x0d: print("brcr %s", get_creg_name(imm32)); break;
+
+ case 0x10: print("shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x12: print("shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x14: print("shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x16: print("shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x18: print("shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1a: print("shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1c: print("shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1e: print("shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+
+ case 0x22: print("and R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x23: print("and 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x24: print("and.tf R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x25: print("and.tf 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x28: print("and.ft R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x29: print("and.ft 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x2c: print("xor R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x2d: print("xor 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x2e: print("or R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x2f: print("or 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x30: print("and.ff R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x31: print("and.ff 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x32: print("xnor R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x33: print("xnor 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x36: print("or.tf R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x37: print("or.tf 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x3a: print("or.ft R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x3b: print("or.ft 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0x3c: print("or.ff R%d, R%d, R%d", src1, rs, rd); break;
+ case 0x3d: print("or.ff 0x%08X, R%d, R%d", imm32, rs, rd); break;
+
+ case 0x48: case 0x40:
+ print("ld.b R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x49: case 0x41:
+ print("ld.b 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x4a: case 0x42:
+ print("ld.h R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x4b: case 0x43:
+ print("ld.h 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x4c: case 0x44:
+ print("ld R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x4d: case 0x45:
+ print("ld 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs,MEMOP_M[m], rd);
+ break;
+ case 0x4e: case 0x46:
+ print("ld.d R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x4f: case 0x47:
+ print("ld.d 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x58: case 0x50:
+ print("ld.ub R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x59: case 0x51:
+ print("ld.ub 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x5a: case 0x52:
+ print("ld.uh R%d%s(R%d%s), R%d", src1, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+ case 0x5b: case 0x53:
+ print("ld.uh 0x%08X%s(R%d%s), R%d", imm32, MEMOP_S[s], rs, MEMOP_M[m], rd);
+ break;
+
+ case 0x68: case 0x60:
+ print("st.b R%d, R%d%s(R%d%s)", rd, src1, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x69: case 0x61:
+ print("st.b R%d, 0x%08X%s(R%d%s)", rd, imm32, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6a: case 0x62:
+ print("st.h R%d, R%d%s(R%d%s)", rd, src1, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6b: case 0x63:
+ print("st.h R%d, 0x%08X%s(R%d%s)", rd, imm32, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6c: case 0x64:
+ print("st R%d, R%d%s(R%d%s)", rd, src1, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6d: case 0x65:
+ print("st R%d, 0x%08X%s(R%d%s)", rd, imm32, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6e: case 0x66:
+ print("st.d R%d, R%d%s(R%d%s)", rd, src1, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+ case 0x6f: case 0x67:
+ print("st.d R%d, 0x%08X%s(R%d%s)", rd, imm32, MEMOP_S[s], rs, MEMOP_M[m]);
+ break;
+
+ case 0x78: case 0x70:
+ print("dcache R%d(R%d)", src1, rs);
+ break;
+ case 0x79: case 0x71:
+ print("dcache 0x%08X(R%d)", imm32, rs);
+ break;
+
+ case 0x80: print("bsr R%d, R%d", src1, link); break;
+ case 0x81: print("bsr 0x%08X, R%d", imm32, link); break;
+ case 0x82: print("bsr.a R%d, R%d", src1, rd); break;
+ case 0x83: print("bsr.a 0x%08X, R%d", imm32, link); break;
+ case 0x88: print("jsr R%d, R%d", src1, link); break;
+ case 0x89: print("jsr 0x%08X, R%d", imm32, link); break;
+ case 0x8a: print("jsr.a R%d, R%d", src1, link); break;
+ case 0x8b: print("jsr.a 0x%08X, R%d", imm32, link); break;
+ case 0x90: print("bbz R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x91: print("bbz 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x92: print("bbz.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x93: print("bbz.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x94: print("bbo R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x95: print("bbo 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x96: print("bbo.a R%d, R%d, %s (%d)", src1, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x97: print("bbo.a 0x%08X, R%d, %s (%d)", imm32, rs, BITNUM_CONDITION[bitnum], bitnum); break;
+ case 0x98: print("bcnd R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break;
+ case 0x99: print("bcnd 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break;
+ case 0x9a: print("bcnd.a R%d, R%d, %s", src1, rs, BCND_CONDITION[rd]); break;
+ case 0x9b: print("bcnd.a 0x%08X, R%d, %s", imm32, rs, BCND_CONDITION[rd]); break;
+ case 0xa0: print("cmp R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xa1: print("cmp 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0xb0: print("add R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xb1: print("add 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0xb2: print("addu R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xb3: print("addu 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0xb4: print("sub R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xb5: print("sub 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0xb6: print("subu R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xb7: print("subu 0x%08X, R%d, R%d", imm32, rs, rd); break;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5:
+ case 0xc6: case 0xd6: case 0xc7: case 0xd7: case 0xc8: case 0xd8: case 0xc9: case 0xd9:
+ case 0xca: case 0xcb: case 0xcc: case 0xdc: case 0xcd: case 0xdd: case 0xce: case 0xde:
+ case 0xcf: case 0xdf:
+ {
+ print("%s", format_vector_op(op, imm32));
+ break;
+ }
+
+ case 0xe0: print("fadd.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break;
+ case 0xe1: print("fadd.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break;
+ case 0xe2: print("fsub.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break;
+ case 0xe3: print("fsub.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break;
+ case 0xe4: print("fmpy.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break;
+ case 0xe5: print("fmpy.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break;
+ case 0xe6: print("fdiv.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break;
+ case 0xe7: print("fdiv.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break;
+ case 0xe8: print("frnd%s.%s%s R%d, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], src1, rd); break;
+ case 0xe9: print("frnd%s.%s%s 0x%08X, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], imm32, rd); break;
+ case 0xea: print("fcmp R%d, R%d, R%d", src1, rs, rd); break;
+ case 0xeb: print("fcmp 0x%08X, R%d, R%d", imm32, rs, rd); break;
+ case 0xee: print("fsqrt R%d, R%d", src1, rd); break;
+ case 0xef: print("fsqrt 0x%08X, R%d", imm32, rd); break;
+ case 0xf0: print("lmo R%d, R%d", rs, rd); break;
+ case 0xf2: print("rmo R%d, R%d", rs, rd); break;
+ case 0xfc: print("estop "); break;
+
+ case 0xfe: case 0xff:
+ print("illopF ");
+ break;
+
+ default: print("?"); break;
+ }
+ break;
+ }
+ }
+
+ return opbytes | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE(tms32082_mp)
+{
+ return tms32082_disasm_mp(buffer, pc, oprom);
+}
diff --git a/src/devices/cpu/tms32082/dis_pp.c b/src/devices/cpu/tms32082/dis_pp.c
new file mode 100644
index 00000000000..54f8a6d7004
--- /dev/null
+++ b/src/devices/cpu/tms32082/dis_pp.c
@@ -0,0 +1,714 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+// TMS32082 PP Disassembler
+
+#include "emu.h"
+
+
+static const char *REG_NAMES[128] =
+{
+ // 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"
+};
+
+static const char *CONDITION_CODES[16] =
+{
+ "", "[p] ", "[ls] ", "[hi] ",
+ "[lt] ", "[le] ", "[ge] ", "[gt] ",
+ "[hs] ", "[lo] ", "[eq] ", "[ne] ",
+ "[v] ", "[nv] ", "[n] ", "[nn] "
+};
+
+static const char *TRANSFER_SIZE[4] =
+{
+ "b:", "h:", "w:", ""
+};
+
+
+static char *output;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ output += vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+static char *format_address_mode(int mode, int areg, int s, int limx)
+{
+ static char buffer[64];
+
+ memset(buffer, 0, sizeof(char)*64);
+
+ switch (mode)
+ {
+ case 0x4: sprintf(buffer, "*(a%d++=x%d)", areg, limx); break;
+ case 0x5: sprintf(buffer, "*(a%d--=x%d)", areg, limx); break;
+ case 0x6: sprintf(buffer, "*(a%d++0x%04X)", areg, limx); break;
+ case 0x7: sprintf(buffer, "*(a%d--0x%04X)", areg, limx); break;
+ case 0x8: sprintf(buffer, "*(a%d+x%d)", areg, limx); break;
+ case 0x9: sprintf(buffer, "*(a%d-x%d)", areg, limx); break;
+ case 0xa: sprintf(buffer, "*(a%d+0x%04X)", areg, limx); break;
+ case 0xb: sprintf(buffer, "*(a%d-0x%04X)", areg, limx); break;
+ case 0xc: sprintf(buffer, "*(a%d+=x%d)", areg, limx); break;
+ case 0xd: sprintf(buffer, "*(a%d-=x%d)", areg, limx); break;
+ case 0xe: sprintf(buffer, "*(a%d+=0x%04X)", areg, limx); break;
+ case 0xf: sprintf(buffer, "*(a%d-=0x%04X)", areg, limx); break;
+ }
+
+ return buffer;
+}
+
+static void format_transfer(UINT64 op)
+{
+ char buffer[128];
+ char *b = buffer;
+ int lmode = (op >> 35) & 0xf;
+ int gmode = (op >> 13) & 0xf;
+
+ bool is_nop = false;
+
+ memset(buffer, 0, sizeof(char)*128);
+
+ switch (lmode)
+ {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ {
+ int cond = (op >> 32) & 0xf;
+
+ switch (gmode)
+ {
+ case 0x00: // Format 7: Conditional DU || Conditional Move
+ {
+ int dstbank = (op >> 18) & 0xf;
+ int srcbank = (op >> 6) & 0xf;
+ int src = (op >> 10) & 0x7;
+ int dst = (op >> 3) & 0x7;
+
+ int dreg = (dstbank << 3) | dst;
+ int sreg = (srcbank << 3) | src;
+
+ b += sprintf(b, "%s", CONDITION_CODES[cond]);
+ b += sprintf(b, "%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;
+
+ b += sprintf(b, "%s", CONDITION_CODES[cond]);
+ b += sprintf(b, "%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 dreg = (adstbank << 3) | dst;
+ int sreg = (as1bank << 3) | src;
+
+ if (dreg == sreg)
+ {
+ is_nop = true;
+ }
+ else
+ {
+ b += sprintf(b, "%s", CONDITION_CODES[cond]);
+ b += sprintf(b, "%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;
+
+ int greg = (bank << 3) | reg;
+
+ b += sprintf(b, "%s", CONDITION_CODES[cond]);
+
+ switch (le)
+ {
+ case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx), REG_NAMES[greg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, gimx)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break;
+ case 3: b += sprintf(b, "%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: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset), REG_NAMES[greg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, offset)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break;
+ case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ int mode = gmode | ((op & (1 << 24)) ? 0x10 : 0);
+
+ switch (mode)
+ {
+ case 0x00: // Format 2: Move || Local
+ {
+ b += sprintf(b, "move||local <TODO>");
+ break;
+ }
+ case 0x01: // Format 3: Field Move || Local
+ {
+ b += sprintf(b, "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;
+
+ int reg = (4 << 3) | d;
+
+ switch (le)
+ {
+ case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx), REG_NAMES[reg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, limx)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break;
+ case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break;
+ }
+ break;
+ }
+ case 0x10: case 0x11: case 0x12: case 0x13: // Format 4: Local (Long Offset)
+ {
+ int d = (op >> 32) & 0x7;
+ int bank = (op >> 18) & 0xf;
+ int s = (op & (1 << 28));
+ int size = (op >> 29) & 0x3;
+ int le = ((op >> 16) & 2) | ((op >> 31) & 1);
+ int la = (op >> 25) & 0x7;
+
+ int reg = (bank << 3) | d;
+
+ UINT16 offset = 0;
+ if (s)
+ {
+ offset = op & 0x7fff;
+ if (offset & 0x4000)
+ offset |= 0xc000;
+ }
+ else
+ {
+ offset = op & 0x7fff;
+ }
+
+ switch (le)
+ {
+ case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset), REG_NAMES[reg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, offset)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break;
+ case 3: b += sprintf(b, "%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: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx), REG_NAMES[lreg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[lreg], format_address_mode(lmode, la, local_s, local_imx)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break;
+ case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break;
+ }
+
+ print(", ");
+
+ // global transfer
+ switch (global_le)
+ {
+ case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx), REG_NAMES[greg]); break;
+ case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, global_s, global_imx)); break;
+ case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break;
+ case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (!is_nop)
+ print(" || %s", buffer);
+}
+
+static void format_alu_op(int aluop, int a, const char *dst_text, const char *a_text, const char *b_text, const char *c_text)
+{
+ if (a) // arithmetic
+ {
+ int bits = (aluop & 1) | ((aluop >> 1) & 2) | ((aluop >> 2) & 4) | ((aluop >> 3) & 8);
+ switch (bits)
+ {
+ case 1: print("%s = %s - %s<1<", dst_text, a_text, b_text); break;
+ case 2: print("%s = %s + %s<0<", dst_text, a_text, b_text); break;
+ case 3: print("%s = %s - %s", dst_text, a_text, c_text); break;
+ case 4: print("%s = %s - %s>1>", dst_text, a_text, b_text); break;
+ case 5: print("%s = %s - %s", dst_text, a_text, b_text); break;
+ case 6: print("?"); break;
+ case 7: print("%s = %s - %s>0>", dst_text, a_text, b_text); break;
+ case 8: print("%s = %s + %s>0>", dst_text, a_text, b_text); break;
+ case 9: print("?"); break;
+ case 10: print("%s = %s + %s", dst_text, a_text, b_text); break;
+ case 11: print("%s = %s + %s>1>", dst_text, a_text, b_text); break;
+ case 12: print("%s = %s + %s", dst_text, a_text, c_text); break;
+ case 13: print("%s = %s - %s<0<", dst_text, a_text, b_text); break;
+ case 14: print("%s = %s + %s<1<", dst_text, a_text, b_text); break;
+ case 15: print("%s = field %s + %s", dst_text, a_text, b_text); break;
+ }
+ }
+ else // boolean
+ {
+ switch (aluop)
+ {
+ case 0xaa: // A & B & C | A & ~B & C | A & B & ~C | A & ~B & ~C = A
+ print("%s = %s", dst_text, a_text);
+ break;
+
+ case 0x55: // ~A & B & C | ~A & ~B & C | ~A & B & ~C | ~A & ~B & ~C = ~A
+ print("%s = ~%s", dst_text, a_text);
+ break;
+
+ case 0xcc: // A & B & C | ~A & B & C | A & B & ~C | ~A & B & ~C = B
+ print("%s = %s", dst_text, b_text);
+ break;
+
+ case 0x33: // A & ~B & C | ~A & ~B & C | A & ~B & ~C | ~A & ~B & ~C = ~B
+ print("%s = %s", dst_text, b_text);
+ break;
+
+ case 0xf0: // A & B & C | ~A & B & C | A & ~B & C | ~A & ~B & C = C
+ print("%s = %s", dst_text, c_text);
+ break;
+
+ case 0x0f: // A & B & ~C | ~A & B & ~C | A & ~B & ~C | ~A & ~B & ~C = ~C
+ print("%s = ~%s", dst_text, c_text);
+ break;
+
+ case 0x80: // A & B & C
+ print("%s = %s & %s & %s", dst_text, a_text, b_text, c_text);
+ break;
+
+ case 0x88: // A & B & C | A & B & ~C = A & B
+ print("%s = %s & %s", dst_text, a_text, b_text);
+ break;
+
+ case 0xa0: // A & B & C | A & ~B & C = A & C
+ print("%s = %s & %s", dst_text, a_text, c_text);
+ break;
+
+ case 0xc0: // A & B & C | ~A & B & C = B & C
+ print("%s = %s & %s", dst_text, b_text, c_text);
+ break;
+
+ case 0xea: // A & B & C | ~A & B & C | A & ~B & C |
+ // A & B & ~C | A & ~B & ~C = A | C
+ print("%s = %s | %s", dst_text, a_text, c_text);
+ break;
+
+ case 0xee: // A & B & C | ~A & B & C | A & ~B & C |
+ // A & B & ~C | ~A & B & ~C | A & ~B & ~C = A | B
+ print("%s = %s | %s", dst_text, a_text, b_text);
+ break;
+
+ case 0x44: // ~A & B & C | ~A & B & ~C = ~A & B
+ print("%s = ~%s & %s", dst_text, a_text, b_text);
+ break;
+
+ default:
+ print("%s = b%02X(%s, %s, %s)", dst_text, aluop, a_text, b_text, c_text);
+ break;
+ }
+ }
+}
+
+static offs_t tms32082_disasm_pp(char *buffer, offs_t pc, const UINT8 *oprom)
+{
+ output = buffer;
+ UINT32 flags = 0;
+
+ UINT64 op = ((UINT64)(oprom[0]) << 56) | ((UINT64)(oprom[1]) << 48) | ((UINT64)(oprom[2]) << 40) | ((UINT64)(oprom[3]) << 32) |
+ ((UINT64)(oprom[4]) << 24) | ((UINT64)(oprom[5]) << 16) | ((UINT64)(oprom[6]) << 8) | ((UINT64)(oprom[7]));
+
+ switch (op >> 60)
+ {
+ case 0x6:
+ case 0x7: // Six-operand
+ {
+ print("A: six operand <TODO>");
+ break;
+ }
+
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ {
+ if ((op & U64(0xfaa8100000000000)) == U64(0x8800000000000000))
+ {
+ int operation = (op >> 39) & 0x1f;
+ UINT64 parallel_xfer = (op & U64(0x0000007fffffffff));
+
+ switch (operation)
+ {
+ case 0x00: print("nop"); break;
+ case 0x02: print("eint"); break;
+ case 0x03: print("dint"); break;
+ default: print("<reserved>"); break;
+ }
+
+ format_transfer(parallel_xfer);
+ }
+ else
+ {
+ char dst_text[32];
+ char a_text[32];
+ char b_text[32];
+ char c_text[32];
+
+ switch ((op >> 43) & 3)
+ {
+ case 0:
+ case 1: // Base set ALU (5-bit immediate)
+ {
+ UINT64 parallel_xfer = (op & U64(0x0000007fffffffff));
+
+ int dst = (op >> 48) & 7;
+ int src1 = (op >> 45) & 7;
+ int src2imm = (op >> 39) & 0x1f;
+ int cl = (op >> 60) & 7;
+ 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 dstcreg = dst | (0x4 << 3);
+
+ sprintf(dst_text, "%s", REG_NAMES[dreg]);
+ switch (cl)
+ {
+ case 0:
+ sprintf(a_text, "0x%02X", src2imm);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "@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);
+ break;
+ case 2:
+ sprintf(a_text, "%s", REG_NAMES[dstcreg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%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);
+ break;
+ case 4:
+ sprintf(a_text, "0x%02X", src2imm);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%d0");
+ break;
+ case 5:
+ sprintf(a_text, "0x%02X", src2imm);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "@mf");
+ break;
+ case 6:
+ sprintf(a_text, "%s", REG_NAMES[dstcreg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "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);
+ break;
+ }
+
+ format_alu_op(aluop, a, dst_text, a_text, b_text, c_text);
+ format_transfer(parallel_xfer);
+ break;
+ }
+
+ case 2: // Base set ALU (reg src2)
+ {
+ UINT64 parallel_xfer = (op & U64(0x0000007fffffffff));
+
+ int dst = (op >> 48) & 7;
+ int src1 = (op >> 45) & 7;
+ int src2 = (op >> 39) & 7;
+ int cl = (op >> 60) & 7;
+ 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 s2reg = src2 | (0x4 << 3);
+ int dstcreg = dst | (0x4 << 3);
+ int dreg = dst | (adstbank << 3);
+
+ sprintf(dst_text, "%s", REG_NAMES[dreg]);
+ switch (cl)
+ {
+ case 0:
+ sprintf(a_text, "%s", REG_NAMES[s2reg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "@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]);
+ break;
+ case 2:
+ sprintf(a_text, "%s", REG_NAMES[dstcreg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%%s", REG_NAMES[s2reg]);
+ 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]);
+ break;
+ case 4:
+ sprintf(a_text, "%s", REG_NAMES[s2reg]);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%d0");
+ break;
+ case 5:
+ sprintf(a_text, "%s", REG_NAMES[s2reg]);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "@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]);
+ 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]);
+ break;
+ }
+
+ format_alu_op(aluop, a, dst_text, a_text, b_text, c_text);
+ format_transfer(parallel_xfer);
+ break;
+ }
+
+ case 3: // Base set ALU (32-bit immediate)
+ {
+ int dst = (op >> 48) & 7;
+ int src1 = (op >> 45) & 7;
+ int dstbank = (op >> 39) & 0xf;
+ int s1bank = (op >> 36) & 7;
+ int cond = (op >> 32) & 0xf;
+ int cl = (op >> 60) & 7;
+ int aluop = (op >> 51) & 0xff;
+ int a = (op >> 59) & 1;
+ UINT32 imm32 = (UINT32)(op);
+
+ int dreg = dst | (dstbank << 3);
+ int s1reg = src1 | (s1bank << 3);
+ int dstcreg = dst | (0x4 << 3);
+
+ sprintf(dst_text, "%s", REG_NAMES[dreg]);
+ switch (cl)
+ {
+ case 0:
+ sprintf(a_text, "0x%08X", imm32);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "@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);
+ break;
+ case 2:
+ sprintf(a_text, "%s", REG_NAMES[dstcreg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%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);
+ break;
+ case 4:
+ sprintf(a_text, "0x%08X", imm32);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "%%d0");
+ break;
+ case 5:
+ sprintf(a_text, "0x%08X", imm32);
+ sprintf(b_text, "%s\\\\d0", REG_NAMES[s1reg]);
+ sprintf(c_text, "@mf");
+ break;
+ case 6:
+ sprintf(a_text, "%s", REG_NAMES[dstcreg]);
+ sprintf(b_text, "%s", REG_NAMES[s1reg]);
+ sprintf(c_text, "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);
+ break;
+ }
+
+ print("%s", CONDITION_CODES[cond]);
+
+ format_alu_op(aluop, a, dst_text, a_text, b_text, c_text);
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ print("??? (%02X)", (UINT32)(op >> 60));
+ break;
+ }
+
+ return 8 | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE(tms32082_pp)
+{
+ return tms32082_disasm_pp(buffer, pc, oprom);
+}
diff --git a/src/devices/cpu/tms32082/mp_ops.c b/src/devices/cpu/tms32082/mp_ops.c
new file mode 100644
index 00000000000..79c0b401392
--- /dev/null
+++ b/src/devices/cpu/tms32082/mp_ops.c
@@ -0,0 +1,1821 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+// TMS320C82 Master Processor core execution
+
+#include "emu.h"
+#include "tms32082.h"
+
+
+#define OP_LINK() ((m_ir >> 27) & 0x1f)
+#define OP_RD() ((m_ir >> 27) & 0x1f)
+#define OP_RS() ((m_ir >> 22) & 0x1f)
+#define OP_BASE() ((m_ir >> 22) & 0x1f)
+#define OP_SIMM15() ((m_ir & 0x4000) ? (0xffffe000 | (m_ir & 0x7fff)) : (m_ir & 0x7fff))
+#define OP_UIMM15() (m_ir & 0x7fff)
+#define OP_BITNUM() ((m_ir >> 27) & 0x1f)
+#define OP_ROTATE() (m_ir & 0x1f)
+#define OP_ENDMASK() ((m_ir >> 5) & 0x1f)
+#define OP_SRC1() (m_ir & 0x1f)
+#define OP_PD() ((m_ir >> 9) & 0x3)
+#define OP_P1() ((m_ir >> 5) & 0x3)
+#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)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)(0x80000000) >> r) : 0))
+
+
+
+bool tms32082_mp_device::test_condition(int condition, UINT32 value)
+{
+ switch (condition)
+ {
+ case 0x00: return false; // never, byte
+ case 0x01: return (INT8)(value) > 0; // greater than zero, byte
+ case 0x02: return (INT8)(value) == 0; // equals zero, byte
+ case 0x03: return (INT8)(value) >= 0; // greater than or equal to zero, byte
+ case 0x04: return (INT8)(value) < 0; // less than zero, byte
+ case 0x05: return (INT8)(value) != 0; // not equal to zero, byte
+ case 0x06: return (INT8)(value) <= 0; // less than or equal to zero, byte
+ case 0x07: return true; // always, byte
+ case 0x08: return false; // never, word
+ case 0x09: return (INT16)(value) > 0; // greater than zero, word
+ case 0x0a: return (INT16)(value) == 0; // equals zero, word
+ case 0x0b: return (INT16)(value) >= 0; // greater than or equal to zero, word
+ case 0x0c: return (INT16)(value) < 0; // less than zero, word
+ case 0x0d: return (INT16)(value) != 0; // not equal to zero, word
+ case 0x0e: return (INT16)(value) <= 0; // less than or equal to zero, word
+ case 0x0f: return true; // always, word
+ case 0x10: return false; // never, dword
+ case 0x11: return (INT32)(value) > 0; // greater than zero, dword
+ case 0x12: return (INT32)(value) == 0; // equals zero, dword
+ case 0x13: return (INT32)(value) >= 0; // greater than or equal to zero, dword
+ case 0x14: return (INT32)(value) < 0; // less than zero, dword
+ case 0x15: return (INT32)(value) != 0; // not equal to zero, dword
+ case 0x16: return (INT32)(value) <= 0; // less than or equal to zero, dword
+ case 0x17: return true; // always, dword
+ default: return false; // reserved
+ }
+}
+
+UINT32 tms32082_mp_device::calculate_cmp(UINT32 src1, UINT32 src2)
+{
+ UINT16 src1_16 = (UINT16)(src1);
+ UINT8 src1_8 = (UINT8)(src1);
+ UINT16 src2_16 = (UINT16)(src2);
+ UINT8 src2_8 = (UINT8)(src2);
+
+ UINT64 res32 = (UINT64)src1 - (UINT64)src2;
+ int z32 = (res32 == 0) ? 1 : 0;
+ int n32 = SIGN32(res32);
+ int v32 = CMP_OVERFLOW32(res32, src2, src1);
+ int c32 = CARRY32(res32);
+
+ UINT32 res16 = (UINT32)src1_16 - (UINT32)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 res8 = (UINT16)src1_8 - (UINT16)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);
+
+ UINT32 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)
+ // 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)
+ // 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)
+
+ return flags;
+}
+
+void tms32082_mp_device::vector_loadstore()
+{
+ int rd = OP_RD();
+ int vector_ls_bits = (((m_ir >> 9) & 0x3) << 1) | ((m_ir >> 6) & 1);
+
+ switch (vector_ls_bits)
+ {
+ case 0x01: // vst.s
+ {
+ m_program->write_dword(m_outp, m_reg[rd]);
+ m_outp += 4;
+ break;
+ }
+ case 0x03: // vst.d
+ {
+ UINT64 data = m_fpair[rd >> 1];
+ 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_in0p += 4;
+ break;
+ }
+ case 0x05: // vld1.s
+ {
+ 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_in0p += 8;
+ break;
+ }
+ case 0x07: // vld1.d
+ {
+ m_fpair[rd >> 1] = m_program->read_qword(m_in1p);
+ m_in1p += 8;
+ break;
+ }
+
+ default:
+ fatalerror("vector_loadstore(): ls bits = %02X\n", vector_ls_bits);
+ }
+}
+
+void tms32082_mp_device::execute_short_imm()
+{
+ switch ((m_ir >> 15) & 0x7f)
+ {
+ case 0x02: // cmnd
+ {
+ UINT32 data = OP_UIMM15();
+
+ processor_command(data);
+ break;
+ }
+
+ case 0x04: // rdcr
+ {
+ int rd = OP_RD();
+ UINT32 imm = OP_UIMM15();
+
+ UINT32 r = read_creg(imm);
+
+ if (rd)
+ m_reg[rd] = r;
+ break;
+ }
+
+ case 0x05: // swcr
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ UINT32 r = read_creg(imm);
+ if (rd)
+ m_reg[rd] = r;
+
+ write_creg(imm, m_reg[rs]);
+ break;
+ }
+
+ case 0x06: // brcr
+ {
+ int cr = OP_UIMM15();
+
+ if (cr == 0x0001)
+ {
+ // ignore jump to EIP because of how we emulate the pipeline
+ }
+ else
+ {
+ UINT32 data = read_creg(cr);
+
+ m_fetchpc = data & ~3;
+ m_ie = (m_ie & ~1) | (data & 1); // global interrupt mask from creg
+ // TODO: user/supervisor latch from creg
+ }
+ break;
+ }
+
+ case 0x08: // shift.dz
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ UINT32 compmask = endmask; // shiftmask == 0xffffffff
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0a: // shift.ds
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ UINT32 compmask = endmask; // shiftmask == 0xffffffff
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ res = SIGN_EXTEND(res, rot);
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ // sign extend makes no sense to left..
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0b: // shift.ez
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ int shift = r ? 32-rot : rot;
+ UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32];
+ UINT32 compmask = endmask & shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0c: // shift.em
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ UINT32 shiftmask = SHIFT_MASK[r ? 32-rot : rot];
+ UINT32 compmask = endmask & shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask);
+ }
+ else // left
+ {
+ res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask);
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0d: // shift.es
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ int shift = r ? 32-rot : rot;
+ UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32];
+ UINT32 compmask = endmask & shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ res = SIGN_EXTEND(res, rot);
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ // sign extend makes no sense to left..
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0e: // shift.iz
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ UINT32 shiftmask = SHIFT_MASK[r ? 32-rot : rot];
+ UINT32 compmask = endmask & ~shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x0f: // shift.im
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = OP_ROTATE();
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = SHIFT_MASK[end ? end : 32];
+ if (inv) endmask = ~endmask;
+
+ UINT32 shiftmask = SHIFT_MASK[r ? 32-rot : rot];
+ UINT32 compmask = endmask & ~shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = (ROTATE_R(source, rot) & compmask) | (m_reg[rd] & ~compmask);
+ }
+ else // left
+ {
+ res = (ROTATE_L(source, rot) & compmask) | (m_reg[rd] & ~compmask);
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x11: // and
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] & imm;
+ break;
+ }
+
+ case 0x12: // and.tf
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ if (rd)
+ m_reg[rd] = ~m_reg[rs] & imm;
+ break;
+ }
+
+ case 0x14: // and.ft
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] & ~imm;
+ break;
+ }
+
+ case 0x17: // or
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] | imm;
+ break;
+ }
+
+ case 0x1d: // or.ft
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 imm = OP_UIMM15();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] | ~imm;
+ break;
+ }
+
+ case 0x24:
+ case 0x20: // ld.b
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data = (UINT8)m_program->read_byte(address);
+ if (data & 0x80) data |= 0xffffff00;
+ if (rd)
+ m_reg[rd] = data;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x25:
+ case 0x21: // ld.h
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data = (UINT16)m_program->read_word(address);
+ if (data & 0x8000) data |= 0xffff0000;
+ if (rd)
+ m_reg[rd] = data;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x26:
+ case 0x22: // ld
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data = m_program->read_dword(address);
+ if (rd)
+ m_reg[rd] = data;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x27:
+ case 0x23: // ld.d
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data1 = m_program->read_dword(address);
+ UINT32 data2 = m_program->read_dword(address+4);
+ if (rd)
+ {
+ m_reg[(rd & ~1)+1] = data1;
+ m_reg[(rd & ~1)] = data2;
+ }
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x28:
+ case 0x2c: // ld.ub
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data = (UINT8)(m_program->read_byte(address));
+ if (rd)
+ m_reg[rd] = data;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x2d:
+ case 0x29: // ld.uh
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+ UINT32 data = (UINT16)(m_program->read_word(address));
+ if (rd)
+ m_reg[rd] = data;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x34:
+ case 0x30: // st.b
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+
+ m_program->write_byte(address, (UINT8)(m_reg[rd]));
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x35:
+ case 0x31: // st.h
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+
+ m_program->write_word(address, (UINT16)(m_reg[rd]));
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x36:
+ case 0x32: // st
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 address = m_reg[base] + offset;
+
+ m_program->write_dword(address, m_reg[rd]);
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x37:
+ case 0x33: // st.d
+ {
+ int rd = OP_RD();
+ int base = OP_BASE();
+ int m = m_ir & (1 << 17);
+ INT32 offset = OP_SIMM15();
+
+ UINT32 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]);
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x45: // jsr.a
+ {
+ int link = OP_LINK();
+ int base = OP_BASE();
+ INT32 offset = OP_SIMM15();
+
+ if (link)
+ m_reg[link] = m_fetchpc;
+
+ m_fetchpc = m_reg[base] + offset;
+ break;
+ }
+
+ case 0x48: // bbz
+ {
+ int bitnum = OP_BITNUM() ^ 0x1f;
+ INT32 offset = OP_SIMM15();
+ int rs = OP_RS();
+
+ if ((m_reg[rs] & (1 << bitnum)) == 0)
+ {
+ UINT32 address = m_pc + (offset * 4);
+
+ m_pc = m_fetchpc;
+ delay_slot();
+
+ m_fetchpc = address;
+ }
+ break;
+ }
+
+ case 0x49: // bbz.a
+ {
+ int bitnum = OP_BITNUM() ^ 0x1f;
+ INT32 offset = OP_SIMM15();
+ int rs = OP_RS();
+
+ if ((m_reg[rs] & (1 << bitnum)) == 0)
+ {
+ m_fetchpc = m_pc + (offset * 4);
+ }
+ break;
+ }
+
+ case 0x4a: // bbo
+ {
+ int bitnum = OP_BITNUM() ^ 0x1f;
+ INT32 offset = OP_SIMM15();
+ int rs = OP_RS();
+
+ if ((m_reg[rs] & (1 << bitnum)) != 0)
+ {
+ UINT32 address = m_pc + (offset * 4);
+
+ m_pc = m_fetchpc;
+ delay_slot();
+
+ m_fetchpc = address;
+ }
+ break;
+ }
+
+ case 0x4b: // bbo.a
+ {
+ int bitnum = OP_BITNUM() ^ 0x1f;
+ INT32 offset = OP_SIMM15();
+ int rs = OP_RS();
+
+ if ((m_reg[rs] & (1 << bitnum)) != 0)
+ {
+ m_fetchpc = m_pc + (offset * 4);
+ }
+ break;
+ }
+
+ case 0x4c: // bcnd
+ {
+ INT32 offset = OP_SIMM15();
+ int code = OP_RD();
+ int rs = OP_RS();
+
+ if (test_condition(code, m_reg[rs]))
+ {
+ UINT32 address = m_pc + (offset * 4);
+
+ m_pc = m_fetchpc;
+ delay_slot();
+
+ m_fetchpc = address;
+ }
+ break;
+ }
+
+ case 0x4d: // bcnd.a
+ {
+ INT32 offset = OP_SIMM15();
+ int code = OP_RD();
+ int rs = OP_RS();
+
+ if (test_condition(code, m_reg[rs]))
+ {
+ m_fetchpc = m_pc + (offset * 4);
+ }
+ break;
+ }
+
+ case 0x50: // cmp
+ {
+ UINT32 src1 = OP_SIMM15();
+ UINT32 src2 = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ if (rd)
+ m_reg[rd] = calculate_cmp(src1, src2);
+ break;
+ }
+
+ case 0x58: // add
+ {
+ INT32 imm = OP_SIMM15();
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] + imm;
+
+ // TODO: integer overflow exception
+ break;
+ }
+
+ case 0x59: // addu
+ {
+ INT32 imm = OP_SIMM15();
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] + imm;
+ break;
+ }
+
+ case 0x5a: // sub
+ {
+ INT32 imm = OP_SIMM15();
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = imm - m_reg[rs];
+
+ // TODO: integer overflow exception
+ break;
+ }
+
+ case 0x5b: // subu
+ {
+ INT32 imm = OP_SIMM15();
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = imm - m_reg[rs];
+ break;
+ }
+
+ default:
+ fatalerror("execute_short_imm(): %08X: opcode %08X (%02X)", m_pc, m_ir, (m_ir >> 15) & 0x7f);
+ }
+}
+
+void tms32082_mp_device::execute_reg_long_imm()
+{
+ UINT32 imm32 = 0;
+
+ int has_imm = (m_ir & (1 << 12));
+
+ if (has_imm)
+ imm32 = fetch();
+
+ switch ((m_ir >> 12) & 0xff)
+ {
+ case 0x04: // cmnd
+ {
+ UINT32 data = has_imm ? imm32 : m_reg[OP_SRC1()];
+
+ processor_command(data);
+ break;
+ }
+
+ case 0x16: // shift.ez
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = m_reg[OP_ROTATE()];
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ if (inv) endmask = ~endmask;
+
+ int shift = r ? 32-rot : rot;
+ UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32];
+ UINT32 compmask = endmask & shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x1a: // shift.es
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = m_reg[OP_ROTATE()];
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ if (inv) endmask = ~endmask;
+
+ int shift = r ? 32-rot : rot;
+ UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32];
+ UINT32 compmask = endmask & shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ res = SIGN_EXTEND(res, rot);
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x1c: // shift.iz
+ {
+ int r = (m_ir & (1 << 10));
+ int inv = (m_ir & (1 << 11));
+ int rot = m_reg[OP_ROTATE()];
+ int end = OP_ENDMASK();
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ UINT32 endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ if (inv) endmask = ~endmask;
+
+ int shift = r ? 32-rot : rot;
+ UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32];
+ UINT32 compmask = endmask & ~shiftmask;
+
+ UINT32 res = 0;
+ if (r) // right
+ {
+ res = ROTATE_R(source, rot) & compmask;
+ }
+ else // left
+ {
+ res = ROTATE_L(source, rot) & compmask;
+ }
+
+ if (rd)
+ m_reg[rd] = res;
+ break;
+ }
+
+ case 0x22:
+ case 0x23: // and
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 src1 = has_imm ? imm32 : m_reg[OP_SRC1()];
+
+ if (rd)
+ m_reg[rd] = src1 & m_reg[rs];
+ break;
+ }
+
+ case 0x24:
+ case 0x25: // and.tf
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ UINT32 src1 = has_imm ? imm32 : m_reg[OP_SRC1()];
+
+ if (rd)
+ m_reg[rd] = src1 & ~(m_reg[rs]);
+ break;
+ }
+
+ case 0x2c:
+ case 0x2d: // xor
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] ^ (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+
+ case 0x2e:
+ case 0x2f: // or
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] | (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+
+ case 0x3a:
+ case 0x3b: // or.ft
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] | ~(has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+
+ case 0x40:
+ case 0x41:
+ case 0x48:
+ case 0x49: // ld.b
+ {
+ int m = m_ir & (1 << 15);
+
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ UINT32 r = m_program->read_byte(address);
+ if (r & 0x80) r |= 0xffffff00;
+
+ if (rd)
+ m_reg[rd] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x42:
+ case 0x4a:
+ case 0x43:
+ case 0x4b: // ld.h
+ {
+ int shift = (m_ir & (1 << 11)) ? 1 : 0;
+ int m = m_ir & (1 << 15);
+
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ UINT32 r = m_program->read_word(address);
+ if (r & 0x8000) r |= 0xffff0000;
+
+ if (rd)
+ m_reg[rd] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x4c:
+ case 0x44:
+ case 0x4d:
+ case 0x45: // ld
+ {
+ int shift = (m_ir & (1 << 11)) ? 2 : 0;
+ int m = m_ir & (1 << 15);
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ UINT32 r = m_program->read_dword(address);
+
+ if (rd)
+ m_reg[rd] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x4e:
+ case 0x4f:
+ case 0x46:
+ case 0x47: // ld.d
+ {
+ int shift = (m_ir & (1 << 11)) ? 3 : 0;
+ int m = m_ir & (1 << 15);
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ UINT64 r = m_program->read_qword(address);
+
+ if (rd)
+ m_fpair[rd >> 1] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x58:
+ case 0x59:
+ case 0x50:
+ case 0x51: // ld.ub
+ {
+ int m = m_ir & (1 << 15);
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ UINT32 r = (UINT8)(m_program->read_byte(address));
+
+ if (rd)
+ m_reg[rd] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x5a:
+ case 0x5b:
+ case 0x52:
+ case 0x53: // ld.uh
+ {
+ int shift = (m_ir & (1 << 11)) ? 1 : 0;
+ int m = m_ir & (1 << 15);
+ int base = OP_BASE();
+ int rd = OP_RD();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ UINT32 r = (UINT16)(m_program->read_word(address));
+
+ if (rd)
+ m_reg[rd] = r;
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x60:
+ case 0x61:
+ case 0x68:
+ case 0x69: // st.b
+ {
+ int m = m_ir & (1 << 15);
+
+ int base = OP_BASE();
+
+ UINT32 address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ m_program->write_byte(address, (UINT8)(m_reg[OP_RD()]));
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x62:
+ case 0x63:
+ case 0x6a:
+ case 0x6b: // st.h
+ {
+ int shift = (m_ir & (1 << 11)) ? 1 : 0;
+ int m = m_ir & (1 << 15);
+
+ int base = OP_BASE();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ m_program->write_word(address, (UINT16)(m_reg[OP_RD()]));
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x6c:
+ case 0x6d:
+ case 0x64:
+ case 0x65: // st
+ {
+ int shift = (m_ir & (1 << 11)) ? 2 : 0;
+ int m = m_ir & (1 << 15);
+
+ int base = OP_BASE();
+
+ UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift);
+ m_program->write_dword(address, m_reg[OP_RD()]);
+
+ if (m && base)
+ m_reg[base] = address;
+ break;
+ }
+
+ case 0x88:
+ case 0x89: // jsr
+ {
+ int link = OP_LINK();
+ int base = OP_BASE();
+
+ if (link)
+ m_reg[link] = m_fetchpc + 4;
+
+ UINT32 address = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+
+ m_pc = m_fetchpc;
+ delay_slot();
+
+ m_fetchpc = address;
+ break;
+ }
+
+ case 0x8a:
+ case 0x8b: // jsr.a
+ {
+ int link = OP_LINK();
+ int base = OP_BASE();
+
+ if (link)
+ m_reg[link] = m_fetchpc;
+
+ m_fetchpc = m_reg[base] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+
+ case 0xa0:
+ case 0xa1: // cmp
+ {
+ int rd = OP_RD();
+ UINT32 src1 = has_imm ? imm32 : m_reg[OP_SRC1()];
+ UINT32 src2 = m_reg[OP_RS()];
+
+ if (rd)
+ m_reg[rd] = calculate_cmp(src1, src2);
+ break;
+ }
+
+ case 0xb2:
+ case 0xb3: // addu
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = m_reg[rs] + (has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+
+ case 0xb4:
+ case 0xb5: // sub
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = (has_imm ? imm32 : m_reg[OP_SRC1()]) - m_reg[rs];
+
+ // TODO: overflow interrupt
+ break;
+ }
+
+ case 0xb6:
+ case 0xb7: // subu
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+
+ if (rd)
+ m_reg[rd] = (has_imm ? imm32 : m_reg[OP_SRC1()]) - m_reg[rs];
+ break;
+ }
+
+ case 0xc4:
+ case 0xd4:
+ case 0xc5:
+ case 0xd5: // vmpy
+ {
+ int p1 = m_ir & (1 << 5);
+ int pd = m_ir & (1 << 7);
+ int ls_bit1 = m_ir & (1 << 10);
+ int ls_bit2 = m_ir & (1 << 6);
+ int rd = OP_RS();
+ int src1 OP_SRC1();
+
+ double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[src1 >> 1]) : (double)u2f(m_reg[src1]));
+
+ if (rd)
+ {
+ if (pd)
+ {
+ double res = source * u2d(m_fpair[rd >> 1]);
+ m_fpair[rd >> 1] = d2u(res);
+ }
+ else
+ {
+ float res = (float)(source) * u2f(m_reg[rd]);
+ m_reg[rd] = f2u(res);
+ }
+ }
+
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+ }
+ break;
+ }
+
+ case 0xc8:
+ case 0xd8:
+ case 0xc9:
+ case 0xd9: // vrnd
+ {
+ int acc = OP_ACC();
+ int p1 = m_ir & (1 << 5);
+ int pd = (m_ir >> 7) & 3;
+ int ls_bit1 = m_ir & (1 << 10);
+ int ls_bit2 = m_ir & (1 << 6);
+ int rd = OP_RS();
+ int rs1 = OP_SRC1();
+
+ double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1]));
+
+ if (rd)
+ {
+ // destination register
+ switch (pd)
+ {
+ case 0:
+ m_reg[rd] = f2u((float)source);
+ break;
+ case 1:
+ m_fpair[rd >> 1] = d2u(source);
+ break;
+ case 2:
+ m_reg[rd] = (INT32)(source);
+ break;
+ case 3:
+ m_reg[rd] = (UINT32)(source);
+ break;
+ }
+ }
+ else
+ {
+ // destination accumulator
+ if (pd != 1)
+ fatalerror("vrnd pd = %d at %08X\n", pd, m_pc);
+
+ m_facc[acc] = source;
+ }
+
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+ }
+ break;
+ }
+
+ case 0xcc:
+ case 0xdc:
+ case 0xcd:
+ case 0xdd: // vmac
+ {
+ int acc = OP_ACC();
+ int z = m_ir & (1 << 8);
+ int pd = m_ir & (1 << 9);
+ int ls_bit1 = m_ir & (1 << 10);
+ int ls_bit2 = m_ir & (1 << 6);
+ int rd = OP_RD();
+
+ float src1 = u2f(m_reg[OP_SRC1()]);
+ float src2 = u2f(m_reg[OP_RS()]);
+
+ float res = (src1 * src2) + (z ? 0.0f : m_acc[acc]);
+
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+
+ // if the opcode has load/store, dest is always accumulator
+ m_facc[acc] = (double)res;
+ }
+ else
+ {
+ if (rd)
+ {
+ if (pd)
+ m_fpair[rd >> 1] = d2u(res);
+ else
+ m_reg[rd] = f2u((float)res);
+ }
+ else
+ {
+ // write to accumulator
+ m_facc[acc] = (double)res;
+ }
+ }
+ break;
+ }
+
+ case 0xce:
+ case 0xde:
+ case 0xcf:
+ case 0xdf: // vmsc
+ {
+ int acc = OP_ACC();
+ int z = m_ir & (1 << 8);
+ int pd = m_ir & (1 << 9);
+ int ls_bit1 = m_ir & (1 << 10);
+ int ls_bit2 = m_ir & (1 << 6);
+ int rd = OP_RD();
+
+ float src1 = u2f(m_reg[OP_SRC1()]);
+ float src2 = u2f(m_reg[OP_RS()]);
+
+ float res = (z ? 0.0f : m_acc[acc]) - (src1 * src2);
+
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+
+ // if the opcode has load/store, dest is always accumulator
+ m_facc[acc] = (double)res;
+ }
+ else
+ {
+ if (rd)
+ {
+ if (pd)
+ m_fpair[rd >> 1] = d2u(res);
+ else
+ m_reg[rd] = f2u((float)res);
+ }
+ else
+ {
+ // write to accumulator
+ m_facc[acc] = (double)res;
+ }
+ }
+ break;
+ }
+
+ case 0xe0:
+ case 0xe1: // fadd
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ int src1 = OP_SRC1();
+ int precision = (m_ir >> 5) & 0x3f;
+
+ if (rd) // only calculate if destination register is valid
+ {
+ switch (precision)
+ {
+ case 0x00: // SP - SP -> SP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ m_reg[rd] = f2u(s1 + s2);
+ break;
+ }
+ case 0x10: // SP - SP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u((double)(s1 + s2));
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x14: // SP - DP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u((double) s1 + s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x11: // DP - SP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u(s1 + (double) s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x15: // DP - DP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u((double)(s1 + s2));
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ default:
+ fatalerror("fadd: invalid precision combination %02X\n", precision);
+ }
+ }
+ break;
+ }
+
+ case 0xe2:
+ case 0xe3: // fsub
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ int src1 = OP_SRC1();
+ int precision = (m_ir >> 5) & 0x3f;
+
+ if (rd) // only calculate if destination register is valid
+ {
+ switch (precision)
+ {
+ case 0x00: // SP - SP -> SP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ m_reg[rd] = f2u(s1 - s2);
+ break;
+ }
+ case 0x10: // SP - SP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u((double)(s1 - s2));
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x14: // SP - DP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u((double) s1 - s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x11: // DP - SP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u(s1 - (double) s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x15: // DP - DP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u((double)(s1 - s2));
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ default:
+ fatalerror("fsub: invalid precision combination %02X\n", precision);
+ }
+ }
+ break;
+ }
+
+ case 0xe4:
+ case 0xe5: // fmpy
+ {
+ int rd = OP_RD();
+ int rs = OP_RS();
+ int src1 = OP_SRC1();
+ int precision = (m_ir >> 5) & 0x3f;
+
+ if (rd) // only calculate if destination register is valid
+ {
+ switch (precision)
+ {
+ case 0x00: // SP x SP -> SP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ m_reg[rd] = f2u(s1 * s2);
+ break;
+ }
+ case 0x10: // SP x SP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u((double)(s1 * s2));
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x14: // SP x DP -> DP
+ {
+ float s1 = u2f(has_imm ? imm32 : m_reg[src1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u((double)s1 * s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x11: // DP x SP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ float s2 = u2f(m_reg[rs]);
+ UINT64 res = d2u(s1 * (double) s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x15: // DP x DP -> DP
+ {
+ double s1 = u2d(m_fpair[src1 >> 1]);
+ double s2 = u2d(m_fpair[rs >> 1]);
+ UINT64 res = d2u(s1 * s2);
+ m_fpair[rd >> 1] = res;
+ break;
+ }
+ case 0x2a: // I x I -> I
+ {
+ m_reg[rd] = (INT32)(m_reg[rs]) * (INT32)(has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+ case 0x3f: // U x U -> U
+ {
+ m_reg[rd] = (UINT32)(m_reg[rs]) * (UINT32)(has_imm ? imm32 : m_reg[OP_SRC1()]);
+ break;
+ }
+ default:
+ fatalerror("fmpy: invalid precision combination %02X\n", precision);
+ }
+ }
+ break;
+ }
+
+ case 0xe6:
+ case 0xe7: // fdiv
+ {
+ int rd = OP_RD();
+ int p1 = m_ir & (1 << 5);
+ int p2 = m_ir & (1 << 7);
+ int pd = m_ir & (1 << 9);
+ int rs1 = OP_SRC1();
+ int rs2 = OP_RS();
+
+ if (rd)
+ {
+ double src1 = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1]));
+ double src2 = p2 ? u2d(m_fpair[rs2 >> 1]) : (double)u2f(m_reg[rs2]);
+
+ double res = src1 / src2;
+
+ if (pd)
+ m_fpair[rd >> 1] = d2u(res);
+ else
+ m_reg[rd] = f2u((float)res);
+ }
+ break;
+ }
+
+ case 0xe8:
+ case 0xe9: // frnd
+ {
+ //int mode = (m_ir >> 7) & 3;
+ int p1 = (m_ir >> 5) & 3;
+ int pd = (m_ir >> 9) & 3;
+ int src1 = OP_SRC1();
+ int rd = OP_RD();
+
+ double s = 0.0;
+
+ switch (p1)
+ {
+ case 0:
+ s = has_imm ? (double)(u2f(imm32)) : (double)u2f(m_reg[src1]);
+ break;
+ case 1:
+ s = u2d(m_fpair[src1 >> 1]);
+ break;
+ case 2:
+ s = has_imm ? (double)((INT32)(imm32)) : (double)(INT32)(m_reg[src1]);
+ break;
+ case 3:
+ s = has_imm ? (double)((UINT32)(imm32)) : (double)(UINT32)(m_reg[src1]);
+ break;
+ }
+
+ // TODO: round
+
+ if (rd)
+ {
+ switch (pd)
+ {
+ case 0:
+ m_reg[rd] = f2u((float)(s));
+ break;
+ case 1:
+ m_fpair[rd] = d2u(s);
+ break;
+ case 2:
+ m_reg[rd] = (INT32)(s);
+ break;
+ case 3:
+ m_reg[rd] = (UINT32)(s);
+ break;
+ }
+ }
+ break;
+ }
+
+ case 0xea:
+ case 0xeb: // fcmp
+ {
+ int rd = OP_RD();
+ int p1 = m_ir & (1 << 5);
+ int p2 = m_ir & (1 << 7);
+ int rs1 = OP_SRC1();
+ int rs2 = OP_RS();
+
+ double src1 = has_imm ? (double)(u2f(imm32)) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1]));
+ double src2 = p2 ? u2d(m_fpair[rs2 >> 1]) : (double)u2f(m_reg[rs2]);
+
+ if (rd)
+ {
+ UINT32 flags = 0;
+ flags |= (src1 == src2) ? (1 << 20) : 0;
+ flags |= (src1 != src2) ? (1 << 21) : 0;
+ flags |= (src1 > src2) ? (1 << 22) : 0;
+ flags |= (src1 <= src2) ? (1 << 23) : 0;
+ flags |= (src1 < src2) ? (1 << 24) : 0;
+ flags |= (src1 >= src2) ? (1 << 25) : 0;
+ flags |= (src1 < 0 || src1 > src2) ? (1 << 26) : 0;
+ flags |= (src1 > 0 && src1 < src2) ? (1 << 27) : 0;
+ flags |= (src1 >= 0 && src1 <= src2) ? (1 << 28) : 0;
+ flags |= (src1 <= 0 || src1 >= src2) ? (1 << 29) : 0;
+ // TODO: src1 or src2 unordered
+ // TODO: src1 and src2 ordered
+
+ m_reg[rd] = flags;
+ }
+ break;
+ }
+
+ case 0xee:
+ case 0xef: // fsqrt
+ {
+ int rd = OP_RD();
+ int src1 = OP_SRC1();
+ int p1 = m_ir & (1 << 5);
+ int pd = m_ir & (1 << 9);
+ double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[src1 >> 1]) : (double)u2f(m_reg[src1]));
+
+ if (rd)
+ {
+ double res = sqrt(source);
+
+ if (pd)
+ m_fpair[rd >> 1] = d2u(res);
+ else
+ m_reg[rd] = f2u((float)res);
+ }
+ break;
+ }
+
+ case 0xf2: // rmo
+ {
+ UINT32 source = m_reg[OP_RS()];
+ int rd = OP_RD();
+
+ int bit = 32;
+
+ for (int i=0; i < 32; i++)
+ {
+ if (source & (1 << (31-i)))
+ {
+ bit = i;
+ break;
+ }
+ }
+
+ if (rd)
+ m_reg[rd] = bit;
+ break;
+ }
+
+ default:
+ fatalerror("execute_reg_long_imm(): %08X: opcode %08X (%02X)", m_pc, m_ir, (m_ir >> 12) & 0xff);
+ }
+}
+
+
+void tms32082_mp_device::execute()
+{
+ switch ((m_ir >> 20) & 3)
+ {
+ case 0:
+ case 1:
+ case 2:
+ execute_short_imm();
+ break;
+
+ case 3:
+ execute_reg_long_imm();
+ break;
+ }
+}
diff --git a/src/devices/cpu/tms32082/tms32082.c b/src/devices/cpu/tms32082/tms32082.c
new file mode 100644
index 00000000000..6ce5a2e2c80
--- /dev/null
+++ b/src/devices/cpu/tms32082/tms32082.c
@@ -0,0 +1,597 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+/*
+ Texas Instruments TMS320C82 DSP Emulator
+
+ Written by Ville Linde
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32082.h"
+
+extern CPU_DISASSEMBLE(tms32082_mp);
+extern CPU_DISASSEMBLE(tms32082_pp);
+
+const device_type TMS32082_MP = &device_creator<tms32082_mp_device>;
+const device_type TMS32082_PP = &device_creator<tms32082_pp_device>;
+
+
+
+
+// Master Processor
+
+// internal memory map
+static ADDRESS_MAP_START(mp_internal_map, AS_PROGRAM, 32, tms32082_mp_device)
+ AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("pp0_data0")
+ AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("pp1_data0")
+ AM_RANGE(0x00008000, 0x00008fff) AM_RAM AM_SHARE("pp0_data1")
+ AM_RANGE(0x00009000, 0x00009fff) AM_RAM AM_SHARE("pp1_data1")
+ AM_RANGE(0x01000000, 0x01000fff) AM_RAM AM_SHARE("pp0_param")
+ AM_RANGE(0x01001000, 0x01001fff) AM_RAM AM_SHARE("pp1_param")
+ AM_RANGE(0x01010000, 0x010107ff) AM_READWRITE(mp_param_r, mp_param_w)
+ADDRESS_MAP_END
+
+const UINT32 tms32082_mp_device::SHIFT_MASK[] =
+{
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
+};
+
+
+
+tms32082_mp_device::tms32082_mp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, TMS32082_MP, "TMS32082 MP", tag, owner, clock, "tms32082_mp", __FILE__)
+ , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(mp_internal_map))
+{
+}
+
+
+offs_t tms32082_mp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ return CPU_DISASSEMBLE_NAME(tms32082_mp)(this, buffer, pc, oprom, opram, options);
+}
+
+
+
+READ32_MEMBER(tms32082_mp_device::mp_param_r)
+{
+ //printf("mp_param_w: %08X, %08X\n", offset, mem_mask);
+ return m_param_ram[offset];
+}
+
+WRITE32_MEMBER(tms32082_mp_device::mp_param_w)
+{
+ //printf("mp_param_w: %08X, %08X, %08X\n", offset, data, mem_mask);
+
+ COMBINE_DATA(&m_param_ram[offset]);
+
+ if (offset == 0x3f)
+ {
+ // initiate Transfer Controller operation
+ // TODO: move TC functionality to separate device
+ UINT32 address = data;
+
+ UINT32 next_entry = m_program->read_dword(address + 0);
+ UINT32 pt_options = m_program->read_dword(address + 4);
+ UINT32 src_addr = m_program->read_dword(address + 8);
+ UINT32 dst_addr = m_program->read_dword(address + 12);
+ UINT32 src_b_count = m_program->read_word(address + 16);
+ UINT32 src_a_count = m_program->read_word(address + 18);
+ UINT32 dst_b_count = m_program->read_word(address + 20);
+ UINT32 dst_a_count = m_program->read_word(address + 22);
+ UINT32 src_c_count = m_program->read_dword(address + 24);
+ UINT32 dst_c_count = m_program->read_dword(address + 28);
+ UINT32 src_b_pitch = m_program->read_dword(address + 32);
+ UINT32 dst_b_pitch = m_program->read_dword(address + 36);
+ UINT32 src_c_pitch = m_program->read_dword(address + 40);
+ UINT32 dst_c_pitch = m_program->read_dword(address + 44);
+
+ printf("TC operation:\n");
+ printf(" Next entry: %08X\n", next_entry);
+ printf(" PT options: %08X\n", pt_options);
+ printf(" SRC addr: %08X\n", src_addr);
+ printf(" DST addr: %08X\n", dst_addr);
+ printf(" SRC count A: %04X, B: %04X\n", src_a_count, src_b_count);
+ printf(" DST count A: %04X, B: %04X\n", dst_a_count, dst_b_count);
+ printf(" SRC count C: %08X\n", src_c_count);
+ printf(" DST count C: %08X\n", dst_c_count);
+ printf(" SRC B pitch: %08X\n", src_b_pitch);
+ 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);
+
+ for (int ic = 0; ic <= src_c_count; ic++)
+ {
+ UINT32 c_src_offset = ic * src_c_pitch;
+ UINT32 c_dst_offset = ic * dst_c_pitch;
+
+ for (int ib = 0; ib <= src_b_count; ib++)
+ {
+ UINT32 b_src_offset = ib * src_b_pitch;
+ UINT32 b_dst_offset = ib * dst_b_pitch;
+
+ for (int ia = 0; ia < src_a_count; ia++)
+ {
+ UINT32 src = src_addr + c_src_offset + b_src_offset + ia;
+ UINT32 dst = dst_addr + c_dst_offset + b_dst_offset + ia;
+
+ UINT32 data = m_program->read_byte(src);
+ m_program->write_byte(dst, data);
+
+ //printf("%08X: %02X -> %08X\n", src, data, dst);
+ }
+ }
+ }
+ }
+}
+
+
+
+void tms32082_mp_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_fetchpc));
+ save_item(NAME(m_reg));
+ save_item(NAME(m_acc));
+
+ save_item(NAME(m_in0p));
+ save_item(NAME(m_in1p));
+ save_item(NAME(m_outp));
+ save_item(NAME(m_ie));
+ save_item(NAME(m_intpen));
+
+ // Register state for debugger
+ state_add(MP_PC, "pc", m_pc).formatstr("%08X");
+
+ state_add(MP_R0, "r0", m_reg[0]).formatstr("%08X");
+ state_add(MP_R1, "r1", m_reg[1]).formatstr("%08X");
+ state_add(MP_R2, "r2", m_reg[2]).formatstr("%08X");
+ state_add(MP_R3, "r3", m_reg[3]).formatstr("%08X");
+ state_add(MP_R4, "r4", m_reg[4]).formatstr("%08X");
+ state_add(MP_R5, "r5", m_reg[5]).formatstr("%08X");
+ state_add(MP_R6, "r6", m_reg[6]).formatstr("%08X");
+ state_add(MP_R7, "r7", m_reg[7]).formatstr("%08X");
+ state_add(MP_R8, "r8", m_reg[8]).formatstr("%08X");
+ state_add(MP_R9, "r9", m_reg[9]).formatstr("%08X");
+ state_add(MP_R10, "r10", m_reg[10]).formatstr("%08X");
+ state_add(MP_R11, "r11", m_reg[11]).formatstr("%08X");
+ state_add(MP_R12, "r12", m_reg[12]).formatstr("%08X");
+ state_add(MP_R13, "r13", m_reg[13]).formatstr("%08X");
+ state_add(MP_R14, "r14", m_reg[14]).formatstr("%08X");
+ state_add(MP_R15, "r15", m_reg[15]).formatstr("%08X");
+ state_add(MP_R16, "r16", m_reg[16]).formatstr("%08X");
+ state_add(MP_R17, "r17", m_reg[17]).formatstr("%08X");
+ state_add(MP_R18, "r18", m_reg[18]).formatstr("%08X");
+ state_add(MP_R19, "r19", m_reg[19]).formatstr("%08X");
+ state_add(MP_R20, "r20", m_reg[20]).formatstr("%08X");
+ state_add(MP_R21, "r21", m_reg[21]).formatstr("%08X");
+ state_add(MP_R22, "r22", m_reg[22]).formatstr("%08X");
+ state_add(MP_R23, "r23", m_reg[23]).formatstr("%08X");
+ state_add(MP_R24, "r24", m_reg[24]).formatstr("%08X");
+ state_add(MP_R25, "r25", m_reg[25]).formatstr("%08X");
+ state_add(MP_R26, "r26", m_reg[26]).formatstr("%08X");
+ state_add(MP_R27, "r27", m_reg[27]).formatstr("%08X");
+ state_add(MP_R28, "r28", m_reg[28]).formatstr("%08X");
+ state_add(MP_R29, "r29", m_reg[29]).formatstr("%08X");
+ state_add(MP_R30, "r30", m_reg[30]).formatstr("%08X");
+ state_add(MP_R31, "r31", m_reg[31]).formatstr("%08X");
+
+ state_add(MP_ACC0, "acc0", m_acc[0]).formatstr("%016X");
+ state_add(MP_ACC1, "acc1", m_acc[1]).formatstr("%016X");
+ state_add(MP_ACC2, "acc2", m_acc[2]).formatstr("%016X");
+ state_add(MP_ACC3, "acc3", m_acc[3]).formatstr("%016X");
+
+ state_add(MP_IN0P, "in0p", m_in0p).formatstr("%08X");
+ state_add(MP_IN1P, "in1p", m_in1p).formatstr("%08X");
+ state_add(MP_OUTP, "outp", m_outp).formatstr("%08X");
+ state_add(MP_IE, "ie", m_ie).formatstr("%08X");
+ state_add(MP_INTPEN, "intpen", m_intpen).formatstr("%08X");
+
+ state_add(MP_TCOUNT, "tcount", m_tcount).formatstr("%08X");
+ state_add(MP_TSCALE, "tscale", m_tscale).formatstr("%08X");
+
+ state_add(STATE_GENPC, "curpc", m_pc).noshow();
+
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ m_icountptr = &m_icount;
+}
+
+void tms32082_mp_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "?");
+ break;
+ }
+}
+
+void tms32082_mp_device::device_reset()
+{
+ m_pc = 0;
+ m_fetchpc = 0xfffffff8;
+
+ for (int i=0; i < 32; i++)
+ {
+ m_reg[i] = 0;
+ }
+
+ m_acc[0] = 0;
+ m_acc[1] = 0;
+ m_acc[2] = 0;
+ m_acc[3] = 0;
+
+ m_in0p = 0;
+ m_in1p = 0;
+ m_outp = 0;
+
+ m_intpen = 0;
+ m_ie = 0;
+}
+
+void tms32082_mp_device::processor_command(UINT32 command)
+{
+ printf("MP CMND %08X: ", command);
+
+ if (command & 0x80000000)
+ printf("Reset ");
+ 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 ");
+
+ printf("\n");
+
+ // PP0
+ if (command & 1)
+ {
+ if (command & 0x00004000)
+ {
+ // simulate PP behavior for now...
+ m_program->write_dword(0x00000084, 3);
+
+ UINT32 num = m_program->read_dword(0x90);
+
+ printf("PP num %d\n", num);
+
+ /*
+ UINT32 ra = 0x1000280;
+
+ printf("FIFO push:\n");
+
+ for (int i=0; i < num; i++)
+ {
+ printf("Entry %d:\n", i);
+ for (int k=0; k < 6; k++)
+ {
+ for (int l=0; l < 4; l++)
+ {
+ UINT32 dd = m_program->read_dword(ra);
+ ra += 4;
+
+ printf("%08X(%f) ", dd, u2f(dd));
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+ */
+
+ UINT32 ra = 0x1000280;
+
+ int oldnum = m_program->read_dword(0x600ffffc);
+ UINT32 rb = 0x60000000 + (oldnum * 0x60);
+
+ for (int i=0; i < num; i++)
+ {
+ for (int k=0; k < 24; k++)
+ {
+ UINT32 dd = m_program->read_dword(ra);
+ ra += 4;
+
+ m_program->write_dword(rb, dd);
+ rb += 4;
+ }
+ }
+ m_program->write_dword(0x600ffffc, oldnum+num);
+
+ m_program->write_dword(0x00000090, 0);
+ m_program->write_dword(0x00000094, num);
+
+ }
+ }
+ // PP1
+ if (command & 2)
+ {
+ if (command & 0x00004000)
+ {
+ // simulate PP behavior for now...
+ m_program->write_dword(0x00001014, 3);
+ }
+ }
+}
+
+UINT32 tms32082_mp_device::read_creg(int reg)
+{
+ switch (reg)
+ {
+ case 0x0: // EPC
+ return m_epc;
+
+ case 0x1: // EIP
+ return m_eip;
+
+ case 0x4: // INTPEN
+ return m_intpen;
+
+ case 0x6: // IE
+ return m_ie;
+
+ case 0xa: // PPERROR
+ return 0xe0000;
+
+ case 0xe: // TCOUNT
+ return m_tcount;
+
+ case 0x4000: // IN0P
+ return m_in0p;
+
+ case 0x4001: // IN1P
+ return m_in1p;
+
+ case 0x4002: // OUTP
+ return m_outp;
+
+ default:
+ printf("read_creg(): %08X\n", reg);
+ break;
+ }
+ return 0;
+}
+
+void tms32082_mp_device::write_creg(int reg, UINT32 data)
+{
+ switch (reg)
+ {
+ case 0x0: // EPC
+ m_epc = data;
+ break;
+
+ case 0x1: // EIP
+ m_eip = data;
+ break;
+
+ case 0x4: // INTPEN
+ {
+ for (int i=0; i < 32; i++)
+ {
+ if (data & (1 << i))
+ m_intpen &= ~(1 << i);
+ }
+ break;
+ }
+
+ case 0x6: // IE
+ m_ie = data;
+ printf("IE = %08X\n", data);
+ break;
+
+ case 0xe: // TCOUNT
+ m_tcount = data;
+ break;
+
+ case 0x4000: // IN0P
+ m_in0p = data;
+ break;
+
+ case 0x4001: // IN1P
+ m_in1p = data;
+ break;
+
+ case 0x4002: // OUTP
+ m_outp = data;
+ break;
+
+ default:
+ printf("write_creg(): %08X, %08X\n", reg, data);
+ break;
+ }
+}
+
+void tms32082_mp_device::check_interrupts()
+{
+ if (m_ie & 1) // global interrupt mask
+ {
+ for (int i=1; i < 32; i++)
+ {
+ if (m_ie & m_intpen & (1 << i))
+ {
+ m_epc = (m_fetchpc & ~3);
+ m_epc |= (m_ie & 1); // save global interrupt mask
+ // TODO: user mode bit to EPC
+
+ m_eip = m_pc;
+
+ m_ie &= ~1; // clear global interrupt mask
+
+ // get new pc from vector table
+ m_fetchpc = m_pc = m_program->read_dword(0x01010180 + (i * 4));
+ return;
+ }
+ }
+ }
+}
+
+void tms32082_mp_device::execute_set_input(int inputnum, int state)
+{
+ if (state == ASSERT_LINE)
+ {
+ switch (inputnum)
+ {
+ case INPUT_X1:
+ m_intpen |= (1 << 11);
+ break;
+ case INPUT_X2:
+ m_intpen |= (1 << 12);
+ break;
+ case INPUT_X3:
+ m_intpen |= (1 << 29);
+ break;
+ case INPUT_X4:
+ m_intpen |= (1 << 30);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+UINT32 tms32082_mp_device::fetch()
+{
+ UINT32 w = m_direct->read_dword(m_fetchpc);
+ m_fetchpc += 4;
+ return w;
+}
+
+void tms32082_mp_device::delay_slot()
+{
+ debugger_instruction_hook(this, m_pc);
+ m_ir = fetch();
+ execute();
+
+ m_icount--;
+}
+
+void tms32082_mp_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ m_pc = m_fetchpc;
+
+ check_interrupts();
+
+ debugger_instruction_hook(this, m_pc);
+
+ m_ir = fetch();
+ execute();
+
+ m_tcount--;
+ if (m_tcount < 0)
+ {
+ // TODO: timer interrupt
+ m_tcount = m_tscale;
+ }
+
+ m_icount--;
+ };
+
+ return;
+}
+
+
+
+
+// Parallel Processor
+
+// internal memory map
+static ADDRESS_MAP_START(pp_internal_map, AS_PROGRAM, 32, tms32082_pp_device)
+ AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("pp0_data0")
+ AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("pp1_data0")
+ AM_RANGE(0x00008000, 0x00008fff) AM_RAM AM_SHARE("pp0_data1")
+ AM_RANGE(0x00009000, 0x00009fff) AM_RAM AM_SHARE("pp1_data1")
+ AM_RANGE(0x01000000, 0x01000fff) AM_RAM AM_SHARE("pp0_param")
+ AM_RANGE(0x01001000, 0x01001fff) AM_RAM AM_SHARE("pp1_param")
+ADDRESS_MAP_END
+
+tms32082_pp_device::tms32082_pp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, TMS32082_PP, "TMS32082 PP", tag, owner, clock, "tms32082_pp", __FILE__)
+ , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(pp_internal_map))
+{
+}
+
+
+offs_t tms32082_pp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ return CPU_DISASSEMBLE_NAME(tms32082_pp)(this, buffer, pc, oprom, opram, options);
+}
+
+void tms32082_pp_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_fetchpc));
+
+ // Register state for debugger
+ state_add(PP_PC, "pc", m_pc).formatstr("%08X");
+
+ state_add(STATE_GENPC, "curpc", m_pc).noshow();
+
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ m_icountptr = &m_icount;
+}
+
+void tms32082_pp_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "?");
+ break;
+ }
+}
+
+void tms32082_pp_device::device_reset()
+{
+ m_pc = 0;
+ m_fetchpc = 0x400010a0;
+}
+
+void tms32082_pp_device::execute_run()
+{
+ m_pc = m_fetchpc;
+ debugger_instruction_hook(this, m_pc);
+
+ m_icount = 0;
+
+ return;
+}
diff --git a/src/devices/cpu/tms32082/tms32082.h b/src/devices/cpu/tms32082/tms32082.h
new file mode 100644
index 00000000000..494f1580504
--- /dev/null
+++ b/src/devices/cpu/tms32082/tms32082.h
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+#pragma once
+
+#ifndef __TMS32082_H__
+#define __TMS32082_H__
+
+// Master Processor class
+class tms32082_mp_device : public cpu_device
+{
+public:
+ // construction/destruction
+ tms32082_mp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ enum
+ {
+ MP_PC=1,
+ MP_R0,
+ MP_R1,
+ MP_R2,
+ MP_R3,
+ MP_R4,
+ MP_R5,
+ MP_R6,
+ MP_R7,
+ MP_R8,
+ MP_R9,
+ MP_R10,
+ MP_R11,
+ MP_R12,
+ MP_R13,
+ MP_R14,
+ MP_R15,
+ MP_R16,
+ MP_R17,
+ MP_R18,
+ MP_R19,
+ MP_R20,
+ MP_R21,
+ MP_R22,
+ MP_R23,
+ MP_R24,
+ MP_R25,
+ MP_R26,
+ MP_R27,
+ MP_R28,
+ MP_R29,
+ MP_R30,
+ MP_R31,
+ MP_ACC0,
+ MP_ACC1,
+ MP_ACC2,
+ MP_ACC3,
+ MP_IN0P,
+ MP_IN1P,
+ MP_OUTP,
+ MP_IE,
+ MP_INTPEN,
+ MP_TCOUNT,
+ MP_TSCALE
+ };
+
+ enum
+ {
+ INPUT_X1 = 1,
+ INPUT_X2 = 2,
+ INPUT_X3 = 3,
+ INPUT_X4 = 4
+ };
+
+ DECLARE_READ32_MEMBER(mp_param_r);
+ DECLARE_WRITE32_MEMBER(mp_param_w);
+
+
+protected:
+ // device level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const { return 1; }
+ virtual UINT32 execute_max_cycles() const { return 1; }
+ virtual UINT32 execute_input_lines() const { return 0; }
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const
+ {
+ switch (spacenum)
+ {
+ case AS_PROGRAM: return &m_program_config;
+ default: return NULL;
+ }
+ }
+
+ // device_state_interface overrides
+ void state_string_export(const device_state_entry &entry, std::string &str);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
+ virtual UINT32 disasm_max_opcode_bytes() const { return 8; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ address_space_config m_program_config;
+
+ static const UINT32 SHIFT_MASK[33];
+
+
+ UINT32 m_pc;
+ UINT32 m_fetchpc;
+ union
+ {
+ UINT32 m_reg[32];
+ UINT64 m_fpair[16];
+ };
+ union
+ {
+ UINT64 m_acc[4];
+ double m_facc[4];
+ };
+ UINT32 m_ir;
+
+ UINT32 m_in0p;
+ UINT32 m_in1p;
+ UINT32 m_outp;
+ UINT32 m_ie;
+ UINT32 m_intpen;
+ UINT32 m_epc;
+ UINT32 m_eip;
+
+ UINT32 m_tcount;
+ UINT32 m_tscale;
+
+ UINT32 m_param_ram[0x800];
+
+ int m_icount;
+
+ address_space *m_program;
+ direct_read_data* m_direct;
+
+ void check_interrupts();
+ void processor_command(UINT32 command);
+ UINT32 fetch();
+ void delay_slot();
+ void execute();
+ void execute_short_imm();
+ void execute_reg_long_imm();
+ UINT32 read_creg(int reg);
+ void write_creg(int reg, UINT32 data);
+ bool test_condition(int condition, UINT32 value);
+ UINT32 calculate_cmp(UINT32 src1, UINT32 src2);
+ void vector_loadstore();
+};
+
+
+// Parallel Processor class
+class tms32082_pp_device : public cpu_device
+{
+public:
+ // construction/destruction
+ tms32082_pp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ enum
+ {
+ PP_PC = 1
+ };
+
+protected:
+ // device level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const { return 1; }
+ virtual UINT32 execute_max_cycles() const { return 1; }
+ virtual UINT32 execute_input_lines() const { return 0; }
+ virtual void execute_run();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const
+ {
+ switch (spacenum)
+ {
+ case AS_PROGRAM: return &m_program_config;
+ default: return NULL;
+ }
+ }
+
+ // device_state_interface overrides
+ void state_string_export(const device_state_entry &entry, std::string &str);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const { return 8; }
+ virtual UINT32 disasm_max_opcode_bytes() const { return 8; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ address_space_config m_program_config;
+
+ UINT32 m_pc;
+ UINT32 m_fetchpc;
+
+ int m_icount;
+
+ address_space *m_program;
+ direct_read_data* m_direct;
+};
+
+
+extern const device_type TMS32082_MP;
+extern const device_type TMS32082_PP;
+
+
+#endif /* __TMS32082_H__ */