diff options
Diffstat (limited to 'src/devices/cpu/dsp16/dsp16dis.c')
-rw-r--r-- | src/devices/cpu/dsp16/dsp16dis.c | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/src/devices/cpu/dsp16/dsp16dis.c b/src/devices/cpu/dsp16/dsp16dis.c new file mode 100644 index 00000000000..2e144df03af --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16dis.c @@ -0,0 +1,583 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include "dsp16.h" + +std::string disasmF1Field(const UINT8& F1, const UINT8& D, const UINT8& S) +{ + std::string ret = ""; + switch (F1) + { + case 0x00: strprintf(ret, "a%d = p, p = x*y", D); break; + case 0x01: strprintf(ret, "a%d = a%d + p, p = x*y", D, S); break; + case 0x02: strprintf(ret, "p = x*y"); break; + case 0x03: strprintf(ret, "a%d = a%d - p, p = x*y", D, S); break; + case 0x04: strprintf(ret, "a%d = p", D); break; + case 0x05: strprintf(ret, "a%d = a%d + p", D, S); break; + case 0x06: strprintf(ret, "NOP"); break; + case 0x07: strprintf(ret, "a%d = a%d - p", D, S); break; + case 0x08: strprintf(ret, "a%d = a%d | y", D, S); break; + case 0x09: strprintf(ret, "a%d = a%d ^ y", D, S); break; + case 0x0a: strprintf(ret, "a%d & y", S); break; + case 0x0b: strprintf(ret, "a%d - y", S); break; + case 0x0c: strprintf(ret, "a%d = y", D); break; + case 0x0d: strprintf(ret, "a%d = a%d + y", D, S); break; + case 0x0e: strprintf(ret, "a%d = a%d & y", D, S); break; + case 0x0f: strprintf(ret, "a%d = a%d - y", D, S); break; + + default: return "UNKNOWN"; + } + return ret; +} + +std::string disasmYField(const UINT8& Y) +{ + switch (Y) + { + case 0x00: return "*r0"; + case 0x01: return "*r0++"; + case 0x02: return "*r0--"; + case 0x03: return "*r0++j"; + + case 0x04: return "*r1"; + case 0x05: return "*r1++"; + case 0x06: return "*r1--"; + case 0x07: return "*r1++j"; + + case 0x08: return "*r2"; + case 0x09: return "*r2++"; + case 0x0a: return "*r2--"; + case 0x0b: return "*r2++j"; + + case 0x0c: return "*r3"; + case 0x0d: return "*r3++"; + case 0x0e: return "*r3--"; + case 0x0f: return "*r3++j"; + + default: return "UNKNOWN"; + } + // never executed + //return ""; +} + +std::string disasmZField(const UINT8& Z) +{ + switch (Z) + { + case 0x00: return "*r0zp"; + case 0x01: return "*r0pz"; + case 0x02: return "*r0m2"; + case 0x03: return "*r0jk"; + + case 0x04: return "*r1zp"; + case 0x05: return "*r1pz"; + case 0x06: return "*r1m2"; + case 0x07: return "*r1jk"; + + case 0x08: return "*r2zp"; + case 0x09: return "*r2pz"; + case 0x0a: return "*r2m2"; + case 0x0b: return "*r2jk"; + + case 0x0c: return "*r3zp"; + case 0x0d: return "*r3pz"; + case 0x0e: return "*r3m2"; + case 0x0f: return "*r3jk"; + + default: return "UNKNOWN"; + } + // never executed + //return ""; +} + +std::string disasmF2Field(const UINT8& F2, const UINT8& D, const UINT8& S) +{ + std::string ret = ""; + switch (F2) + { + case 0x00: strprintf(ret, "a%d = a%d >> 1", D, S); break; + case 0x01: strprintf(ret, "a%d = a%d << 1", D, S); break; + case 0x02: strprintf(ret, "a%d = a%d >> 4", D, S); break; + case 0x03: strprintf(ret, "a%d = a%d << 4", D, S); break; + case 0x04: strprintf(ret, "a%d = a%d >> 8", D, S); break; + case 0x05: strprintf(ret, "a%d = a%d << 8", D, S); break; + case 0x06: strprintf(ret, "a%d = a%d >> 16", D, S); break; + case 0x07: strprintf(ret, "a%d = a%d << 16", D, S); break; + + case 0x08: strprintf(ret, "a%d = p", D); break; + case 0x09: strprintf(ret, "a%dh = a%dh + 1", D, S); break; + case 0x0a: strprintf(ret, "RESERVED"); break; + case 0x0b: strprintf(ret, "a%d = rnd(a%d)", D, S); break; + case 0x0c: strprintf(ret, "a%d = y", D); break; + case 0x0d: strprintf(ret, "a%d = a%d + 1", D, S); break; + case 0x0e: strprintf(ret, "a%d = a%d", D, S); break; + case 0x0f: strprintf(ret, "a%d = -a%d", D, S); break; + + default: return "UNKNOWN"; + } + return ret; +} + +std::string disasmCONField(const UINT8& CON) +{ + switch (CON) + { + case 0x00: return "mi"; + case 0x01: return "pl"; + case 0x02: return "eq"; + case 0x03: return "ne"; + case 0x04: return "lvs"; + case 0x05: return "lvc"; + case 0x06: return "mvs"; + case 0x07: return "mvc"; + case 0x08: return "heads"; + case 0x09: return "tails"; + case 0x0a: return "c0ge"; + case 0x0b: return "c0lt"; + case 0x0c: return "c1ge"; + case 0x0d: return "c1lt"; + case 0x0e: return "true"; + case 0x0f: return "false"; + case 0x10: return "gt"; + case 0x11: return "le"; + + default: return "RESERVED"; + } + // never executed + //return ""; +} + +std::string disasmBField(const UINT8& B) +{ + switch (B) + { + case 0x00: return "return"; + case 0x01: return "ireturn"; + case 0x02: return "goto pt"; + case 0x03: return "call pt"; + case 0x04: + case 0x05: + case 0x06: + case 0x07: return "RESERVED"; + + default: return "UNKNOWN"; + } + // never executed + //return ""; +} + +std::string disasmRImmediateField(const UINT8& R) +{ + switch (R) + { + case 0x00: return "j"; + case 0x01: return "k"; + case 0x02: return "rb"; + case 0x03: return "re"; + case 0x04: return "r0"; + case 0x05: return "r1"; + case 0x06: return "r2"; + case 0x07: return "r3"; + + default: return "UNKNOWN"; + } + // never executed + //return ""; +} + +std::string disasmRField(const UINT8& R) +{ + switch (R) + { + case 0x00: return "r0"; + case 0x01: return "r1"; + case 0x02: return "r2"; + case 0x03: return "r3"; + case 0x04: return "j"; + case 0x05: return "k"; + case 0x06: return "rb"; + case 0x07: return "re"; + case 0x08: return "pt"; + case 0x09: return "pr"; + case 0x0a: return "pi"; + case 0x0b: return "i"; + + case 0x10: return "x"; + case 0x11: return "y"; + case 0x12: return "yl"; + case 0x13: return "auc"; + case 0x14: return "psw"; + case 0x15: return "c0"; + case 0x16: return "c1"; + case 0x17: return "c2"; + case 0x18: return "sioc"; + case 0x19: return "srta"; + case 0x1a: return "sdx"; + case 0x1b: return "tdms"; + case 0x1c: return "pioc"; + case 0x1d: return "pdx0"; + case 0x1e: return "pdx1"; + + default: return "RESERVED"; + } + // never executed + //return ""; +} + +std::string disasmIField(const UINT8& I) +{ + switch (I) + { + case 0x00: return "r0/j"; + case 0x01: return "r1/k"; + case 0x02: return "r2/rb"; + case 0x03: return "r3/re"; + + default: return "UNKNOWN"; + } + // never executed + //return ""; +} + +bool disasmSIField(const UINT8& SI) +{ + switch (SI) + { + case 0x00: return 0; // Not a software interrupt + case 0x01: return 1; // Software Interrupt + } + return false; +} + + +CPU_DISASSEMBLE( dsp16a ) +{ + UINT8 opSize = 1; + UINT32 dasmflags = 0; + UINT16 op = oprom[0] | (oprom[1] << 8); + UINT16 op2 = oprom[2] | (oprom[3] << 8); + + // TODO: Test for previous "if CON" instruction and tab the next instruction in? + + const UINT8 opcode = (op >> 11) & 0x1f; + switch(opcode) + { + // Format 1: Multiply/ALU Read/Write Group + case 0x06: + { + // F1, Y + const UINT8 Y = (op & 0x000f); + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string fString = disasmF1Field(F1, D, S); + sprintf(buffer, "%s, %s", fString.c_str(), yString.c_str()); + break; + } + case 0x04: case 0x1c: + { + // F1 Y=a0[1] | F1 Y=a1[1] + const UINT8 Y = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string fString = disasmF1Field(F1, D, S); + std::string aString = (opcode == 0x1c) ? "a0" : "a1"; + std::string xString = (X) ? "" : "l"; + sprintf(buffer, "%s = %s%s, %s", yString.c_str(), aString.c_str(), xString.c_str(), fString.c_str()); + break; + } + case 0x16: + { + // F1, x = Y + const UINT8 Y = (op & 0x000f); + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string fString = disasmF1Field(F1, D, S); + sprintf(buffer, "%s, x = %s", fString.c_str(), yString.c_str()); + break; + } + case 0x17: + { + // F1, y[l] = Y + const UINT8 Y = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string fString = disasmF1Field(F1, D, S); + std::string xString = (X ? "y" : "y1"); + sprintf(buffer, "%s, %s = %s", fString.c_str(), xString.c_str(), yString.c_str()); + break; + } + case 0x1f: + { + // F1, y = Y, x = *pt++[i] + const UINT8 Y = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string fString = disasmF1Field(F1, D, S); + std::string xString = (X ? "*pt++i" : "*pt++"); + sprintf(buffer, "%s, y = %s, x = %s", fString.c_str(), yString.c_str(), xString.c_str()); + break; + } + case 0x19: case 0x1b: + { + // F1, y = a0|1, x = *pt++[i] + const UINT8 Y = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string fString = disasmF1Field(F1, D, S); + std::string xString = (X ? "*pt++i" : "*pt++"); + std::string aString = (opcode == 0x19) ? "a0" : "a1"; + sprintf(buffer, "%s, y = %s, x = %s", fString.c_str(), aString.c_str(), xString.c_str()); + if (Y != 0x00) sprintf(buffer, "UNKNOWN"); + break; + } + case 0x14: + { + // F1, Y = y[1] + const UINT8 Y = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string xString = (X ? "y" : "y1"); + std::string fString = disasmF1Field(F1, D, S); + sprintf(buffer, "%s, %s = %s", fString.c_str(), yString.c_str(), xString.c_str()); + break; + } + + // Format 1a: Multiply/ALU Read/Write Group (major typo in docs on p3-51) + case 0x07: + { + // F1, At[1] = Y + const UINT8 Y = (op & 0x000f); + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 aT = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string yString = disasmYField(Y); + std::string atString = (aT ? "a0" : "a1"); + std::string fString = disasmF1Field(F1, aT, S); + sprintf(buffer, "%s, %s = %s", fString.c_str(), atString.c_str(), yString.c_str()); + break; + } + + // Format 2: Multiply/ALU Read/Write Group + case 0x15: + { + // F1, Z : y[1] + const UINT8 Z = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string zString = disasmZField(Z); + std::string xString = (X ? "y" : "y1"); + std::string fString = disasmF1Field(F1, D, S); + sprintf(buffer, "%s, %s <=> %s", fString.c_str(), xString.c_str(), zString.c_str()); + break; + } + case 0x1d: + { + // F1, Z : y, x=*pt++[i] + const UINT8 Z = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string zString = disasmZField(Z); + std::string xString = (X ? "*pt++i" : "*pt++"); + std::string fString = disasmF1Field(F1, D, S); + sprintf(buffer, "%s, %s <=> y, x = %s", fString.c_str(), zString.c_str(), xString.c_str()); + break; + } + + // Format 2a: Multiply/ALU Read/Write Group + case 0x05: + { + // F1, Z : aT[1] + const UINT8 Z = (op & 0x000f); + const UINT8 X = (op & 0x0010) >> 4; + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 aT = (op & 0x0400) >> 10; + const UINT8 F1 = (op & 0x01e0) >> 5; + std::string zString = disasmZField(Z); + std::string atString = (aT ? "a0" : "a1"); + atString += X ? "" : "1"; // TODO: Figure out unclear wording. + std::string fString = disasmF1Field(F1, aT, S); + sprintf(buffer, "%s, %s <=> %s", fString.c_str(), zString.c_str(), atString.c_str()); + break; + } + + // Format 3: Special Functions + case 0x12: + case 0x13: + { + // if|ifc CON F2 + const UINT8 CON = (op & 0x001f); + const UINT8 S = (op & 0x0200) >> 9; + const UINT8 D = (op & 0x0400) >> 10; + const UINT8 F2 = (op & 0x01e0) >> 5; + std::string fString = disasmF2Field(F2, D, S); + std::string conString = disasmCONField(CON); + if (op & 0x0800) sprintf(buffer, "if %s : %s", conString.c_str(), fString.c_str()); + else sprintf(buffer, "ifc %s : %s", conString.c_str(), fString.c_str()); + break; + } + + // Format 4: Branch Direct Group + case 0x00: case 0x01: + { + // goto JA + const UINT16 JA = (op & 0x0fff) | (pc & 0xf000); + sprintf(buffer, "goto 0x%04x", JA); + break; + } + case 0x10: case 0x11: + { + // call JA + const UINT16 JA = (op & 0x0fff) | (pc & 0xf000); + sprintf(buffer, "call 0x%04x", JA); + break; + } + + // Format 5: Branch Indirect Group + case 0x18: + { + // goto B + const UINT8 B = (op & 0x0700) >> 8; + std::string bString = disasmBField(B); + sprintf(buffer, "%s", bString.c_str()); + break; + } + + // Format 6: Contitional Branch Qualifier/Software Interrupt (icall) + case 0x1a: + { + // if CON [goto/call/return] + const UINT8 CON = (op & 0x001f); + std::string conString = disasmCONField(CON); + sprintf(buffer, "if %s:", conString.c_str()); + // TODO: Test for invalid ops + // icall + if (op == 0xd40e) sprintf(buffer, "icall"); + break; + } + + // Format 7: Data Move Group + case 0x09: case 0x0b: + { + // R = aS + const UINT8 R = (op & 0x03f0) >> 4; + const UINT8 S = (op & 0x1000) >> 12; + std::string rString = disasmRField(R); + sprintf(buffer, "%s = %s", rString.c_str(), (S ? "a1" : "a0")); + break; + } + case 0x08: + { + // aT = R + const UINT8 R = (op & 0x03f0) >> 4; + const UINT8 aT = (op & 0x0400) >> 10; + std::string rString = disasmRField(R); + sprintf(buffer, "%s = %s", (aT ? "a0" : "a1"), rString.c_str()); + break; + } + case 0x0f: + { + // R = Y + const UINT8 Y = (op & 0x000f); + const UINT8 R = (op & 0x03f0) >> 4; + std::string yString = disasmYField(Y); + std::string rString = disasmRField(R); + sprintf(buffer, "%s = %s", rString.c_str(), yString.c_str()); + // TODO: Special case the R == [y, y1, or x] case + break; + } + case 0x0c: + { + // Y = R + const UINT8 Y = (op & 0x000f); + const UINT8 R = (op & 0x03f0) >> 4; + std::string yString = disasmYField(Y); + std::string rString = disasmRField(R); + // TODO: page 3-31 "special function encoding" + sprintf(buffer, "%s = %s", yString.c_str(), rString.c_str()); + break; + } + case 0x0d: + { + // Z : R + const UINT8 Z = (op & 0x000f); + const UINT8 R = (op & 0x03f0) >> 4; + std::string zString = disasmZField(Z); + std::string rString = disasmRField(R); + sprintf(buffer, "%s <=> %s", zString.c_str(), rString.c_str()); + break; + } + + // Format 8: Data Move (immediate operand - 2 words) + case 0x0a: + { + // R = N + const UINT8 R = (op & 0x03f0) >> 4; + std::string rString = disasmRField(R); + sprintf(buffer, "%s = 0x%04x", rString.c_str(), op2); + opSize = 2; + break; + } + + // Format 9: Short Immediate Group + case 0x02: case 0x03: + { + // R = M + const UINT16 M = (op & 0x01ff); + const UINT8 R = (op & 0x0e00) >> 9; + std::string rString = disasmRImmediateField(R); + sprintf(buffer, "%s = 0x%04x", rString.c_str(), M); + break; + } + + // Format 10: do - redo + case 0x0e: + { + // do|redo K + const UINT8 K = (op & 0x007f); + const UINT8 NI = (op & 0x0780) >> 7; + sprintf(buffer, "do (next %d inst) %d times", NI, K); + // TODO: Limits on K & NI + if (NI == 0x00) + sprintf(buffer, "redo %d", K); + break; + } + + // RESERVED + case 0x1e: + { + sprintf(buffer, "RESERVED"); + break; + } + + // UNKNOWN + default: + { + sprintf(buffer, "UNKNOWN"); + break; + } + } + + return opSize | dasmflags | DASMFLAG_SUPPORTED; +} |