mame/src/emu/cpu/dsp16/dsp16dis.c
2015-04-29 08:18:54 +02:00

582 lines
15 KiB
C

#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;
}