mirror of
https://github.com/holub/mame
synced 2025-07-03 17:08:39 +03:00
dspp: Add a real disassembler
This commit is contained in:
parent
812782cad5
commit
a27347890f
@ -449,7 +449,7 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
else
|
||||
{
|
||||
// Sign extend if right justified
|
||||
val = util::sext(operand, 13);
|
||||
val = uint16_t(util::sext(operand, 13));
|
||||
}
|
||||
m_core->m_operands[opidx++].value = val;
|
||||
}
|
||||
@ -1191,7 +1191,7 @@ inline void dspp_device::exec_arithmetic()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_core->m_acc = util::sext(alu_res, 20) << shift;
|
||||
m_core->m_acc = util::sext(alu_res << shift, 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Philip Bennett
|
||||
// copyright-holders:Philip Bennett, AJR
|
||||
/***************************************************************************
|
||||
|
||||
dsppdasm.c
|
||||
@ -21,104 +21,577 @@ uint32_t dspp_disassembler::opcode_alignment() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
offs_t dspp_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
{
|
||||
#if 0
|
||||
uint32_t op = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
|
||||
int opcode = op >> 27;
|
||||
int cond = (op >> 21) & 1;
|
||||
int rdst = (op >> 22) & 31;
|
||||
int rsrc1 = (op >> 16) & 31;
|
||||
int rsrc2 = op & 0xffff;
|
||||
int rsrc2_iszero = (!rsrc2 || rsrc2 == 0xffe0);
|
||||
uint32_t flags = 0;
|
||||
|
||||
switch (opcode)
|
||||
//-------------------------------------------------
|
||||
// format_operand - Format the value encoded by
|
||||
// an instruction operand
|
||||
//-------------------------------------------------
|
||||
|
||||
void dspp_disassembler::format_operand(std::ostream &stream, uint16_t operand)
|
||||
{
|
||||
uint32_t numregs = 0;
|
||||
|
||||
if (operand & 0x8000)
|
||||
{
|
||||
case 0x00: sprintf(buffer, "trap $00"); flags = DASMFLAG_STEP_OVER; break;
|
||||
case 0x01: sprintf(buffer, "b%s $%08x", condition[rdst & 15], pc + ((INT32)(op << 10) >> 8)); break;
|
||||
case 0x02: if ((op & 0x003fffff) == 3)
|
||||
{
|
||||
uint32_t nextop = oprom[4] | (oprom[5] << 8) | (oprom[6] << 16) | (oprom[7] << 24);
|
||||
if ((nextop >> 27) == 0x10 && ((nextop >> 22) & 31) == rdst && (nextop & 0xffff) == 0)
|
||||
{
|
||||
uint32_t nextnextop = oprom[8] | (oprom[9] << 8) | (oprom[10] << 16) | (oprom[11] << 24);
|
||||
sprintf(buffer, "llit%s $%08x,%s", setcond[cond], nextnextop, reg[rdst]);
|
||||
return 12 | DASMFLAG_STEP_OVER | DASMFLAG_SUPPORTED;
|
||||
}
|
||||
}
|
||||
if (rdst)
|
||||
{
|
||||
flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
|
||||
sprintf(buffer, "bsr %s,$%08x", reg[rdst], pc + ((INT32)(op << 10) >> 8));
|
||||
}
|
||||
else
|
||||
sprintf(buffer, "bra $%08x", pc + ((INT32)(op << 10) >> 8));
|
||||
break;
|
||||
case 0x03: sprintf(buffer, "lea%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
|
||||
case 0x04: sprintf(buffer, "leah%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
|
||||
case 0x05: sprintf(buffer, "subr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x06: sprintf(buffer, "xor%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x07: sprintf(buffer, "xorn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x08: if (!rsrc1 && !rdst && rsrc2_iszero)
|
||||
sprintf(buffer, "nop");
|
||||
else if (!rsrc1)
|
||||
sprintf(buffer, "mov%s %s,%s", setcond[cond], src2(op,0), reg[rdst]);
|
||||
else if (rsrc2_iszero)
|
||||
sprintf(buffer, "mov%s %s,%s", setcond[cond], reg[rsrc1], reg[rdst]);
|
||||
else
|
||||
sprintf(buffer, "add%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x09: sprintf(buffer, "sub%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0a: sprintf(buffer, "addc%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0b: sprintf(buffer, "subc%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0c: sprintf(buffer, "and%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0d: sprintf(buffer, "andn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0e: if (!rsrc1 && !rdst && rsrc2_iszero)
|
||||
sprintf(buffer, "nop");
|
||||
else if (!rsrc1)
|
||||
sprintf(buffer, "mov%s %s,%s", setcond[cond], src2(op,0), reg[rdst]);
|
||||
else if (rsrc2_iszero)
|
||||
sprintf(buffer, "mov%s %s,%s", setcond[cond], reg[rsrc1], reg[rdst]);
|
||||
else
|
||||
sprintf(buffer, "or%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x0f: sprintf(buffer, "orn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x10: sprintf(buffer, "ld%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
|
||||
case 0x11: sprintf(buffer, "ldh%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
|
||||
case 0x12: sprintf(buffer, "lduh%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
|
||||
case 0x13: sprintf(buffer, "sth%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
|
||||
case 0x14: sprintf(buffer, "st%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
|
||||
case 0x15: sprintf(buffer, "ldb%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x16: sprintf(buffer, "ldub%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x17: sprintf(buffer, "stb%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x18: sprintf(buffer, "ashr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x19: sprintf(buffer, "lshr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x1a: sprintf(buffer, "ashl%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x1b: sprintf(buffer, "rotl%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
|
||||
case 0x1c: sprintf(buffer, "getps %s", reg[rdst]); break;
|
||||
case 0x1d: sprintf(buffer, "putps %s", src2(op,0)); break;
|
||||
case 0x1e: if (rdst && rsrc2_iszero)
|
||||
{
|
||||
flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
|
||||
sprintf(buffer, "jsr%s %s,%s", setcond[cond], reg[rdst], reg[rsrc1]);
|
||||
}
|
||||
else if (rdst)
|
||||
{
|
||||
flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
|
||||
sprintf(buffer, "jsr%s %s,%s[%s]", setcond[cond], reg[rdst], reg[rsrc1], src2(op,2));
|
||||
}
|
||||
else if (rsrc2_iszero)
|
||||
{
|
||||
if (rsrc1 == 28)
|
||||
flags = DASMFLAG_STEP_OUT;
|
||||
sprintf(buffer, "jmp%s %s", setcond[cond], reg[rsrc1]);
|
||||
}
|
||||
else
|
||||
sprintf(buffer, "jmp%s %s[%s]", setcond[cond], reg[rsrc1], src2(op,2));
|
||||
break;
|
||||
case 0x1f: sprintf(buffer, "trap $1f"); flags = DASMFLAG_STEP_OVER; break;
|
||||
// Immediate value
|
||||
if ((operand & 0xc000) == 0xc000)
|
||||
{
|
||||
uint16_t val;
|
||||
|
||||
if (operand & 0x2000)
|
||||
{
|
||||
// Left justify
|
||||
val = (operand & 0x1fff) << 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sign extend if right justified
|
||||
val = util::sext(operand, 13);
|
||||
}
|
||||
util::stream_format(stream, "#0x%04X", val);
|
||||
}
|
||||
else if((operand & 0xe000) == 0x8000)
|
||||
{
|
||||
// Address operand
|
||||
uint16_t addr = operand & 0x03ff;
|
||||
|
||||
if (operand & 0x0400)
|
||||
{
|
||||
// Indirect
|
||||
stream << '@';
|
||||
}
|
||||
util::stream_format(stream, "[0x%03X]", addr);
|
||||
|
||||
if (operand & 0x0800)
|
||||
{
|
||||
// Write Back
|
||||
stream << '!';
|
||||
}
|
||||
}
|
||||
else if ((operand & 0xe000) == 0xa000)
|
||||
{
|
||||
// 1 or 2 register operand
|
||||
numregs = (operand & 0x0400) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numregs = 3;
|
||||
}
|
||||
|
||||
sprintf(buffer, "????");
|
||||
#endif
|
||||
return 1 | SUPPORTED;
|
||||
if (numregs > 0)
|
||||
{
|
||||
uint32_t shifter, regdi;
|
||||
|
||||
// Shift successive register operands from a single operand word
|
||||
for (uint32_t i = 0; i < numregs; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
stream << ", ";
|
||||
|
||||
shifter = ((numregs - i) - 1) * 5;
|
||||
regdi = (operand >> shifter) & 0x1f;
|
||||
|
||||
if (regdi & 0x0010)
|
||||
{
|
||||
// Indirect?
|
||||
stream << '@';
|
||||
}
|
||||
util::stream_format(stream, "[R%d]", regdi & 0xf);
|
||||
|
||||
if (numregs == 2)
|
||||
{
|
||||
if ((i == 0) && (operand & 0x1000))
|
||||
stream << '!';
|
||||
else if ((i == 1) && (operand & 0x0800))
|
||||
stream << '!';
|
||||
}
|
||||
else if (numregs == 1)
|
||||
{
|
||||
if (operand & 0x800)
|
||||
stream << '!';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// OPCODE DISASSEMBLY
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_super_special - Disassemble a super
|
||||
// special control op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_super_special(std::ostream &stream, uint16_t op)
|
||||
{
|
||||
uint32_t sel = (op >> 7) & 7;
|
||||
|
||||
switch (sel)
|
||||
{
|
||||
case 1: // BAC
|
||||
{
|
||||
stream << "BAC";
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
case 4: // RTS
|
||||
{
|
||||
stream << "RTS";
|
||||
return 1 | STEP_OUT | SUPPORTED;
|
||||
}
|
||||
|
||||
case 5: // OP_MASK
|
||||
{
|
||||
stream << "OP_MASK";
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
case 7: // SLEEP
|
||||
{
|
||||
stream << "SLEEP";
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
case 0: // NOP
|
||||
{
|
||||
stream << "NOP";
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
default: // Unused
|
||||
{
|
||||
util::stream_format(stream, "0x%04X", op);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_special - Disassemble a special control op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_special(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op)
|
||||
{
|
||||
switch ((op >> 10) & 7)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
return dasm_super_special(stream, op);
|
||||
}
|
||||
case 1: // JUMP
|
||||
{
|
||||
util::stream_format(stream, "JUMP 0x%03X", op & 0x3ff);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
case 2: // JSR
|
||||
{
|
||||
util::stream_format(stream, "JSR 0x%03X", op & 0x3ff);
|
||||
return 1 | STEP_OVER | SUPPORTED;
|
||||
}
|
||||
case 3: // BFM
|
||||
{
|
||||
util::stream_format(stream, "BFM 0x%03X", op & 0x3ff);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
case 4: // MOVEREG
|
||||
{
|
||||
uint32_t regdi = op & 0x3f;
|
||||
|
||||
util::stream_format(stream, "MOVEREG %sR%d, ", (regdi & 0x0010) ? "@" : "", regdi & 0xf);
|
||||
format_operand(stream, opcodes.r16(pc + 1));
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
case 5: // RBASE
|
||||
{
|
||||
util::stream_format(stream, "RBASE%d 0x%03X", (op & 3) << 2, op & 0x3fc);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
case 6: // MOVED
|
||||
{
|
||||
util::stream_format(stream, "MOVE [0x%03X], ", op & 0x3ff);
|
||||
format_operand(stream, opcodes.r16(pc + 1));
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
case 7: // MOVEI
|
||||
{
|
||||
util::stream_format(stream, "MOVE @[0x%03X], ", op & 0x3ff);
|
||||
format_operand(stream, opcodes.r16(pc + 1));
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
util::stream_format(stream, "0x%04X", op);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_branch - Disassemble a branch control op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_branch(std::ostream &stream, uint16_t op)
|
||||
{
|
||||
uint32_t mode = (op >> 13) & 3;
|
||||
uint32_t select = (op >> 12) & 1;
|
||||
uint32_t mask = (op >> 10) & 3;
|
||||
|
||||
char flag0, flag1;
|
||||
|
||||
if (select == 0)
|
||||
{
|
||||
flag0 = 'N';
|
||||
flag1 = 'V';
|
||||
}
|
||||
else
|
||||
{
|
||||
flag0 = 'C';
|
||||
flag1 = 'Z';
|
||||
}
|
||||
|
||||
bool mask0 = (mask & 2) != 0;
|
||||
bool mask1 = (mask & 1) != 0;
|
||||
|
||||
if (mode == 2)
|
||||
stream << "BFC ";
|
||||
else
|
||||
stream << "BTC ";
|
||||
|
||||
if (mask0 && mask1)
|
||||
{
|
||||
stream << flag1;
|
||||
stream << flag0;
|
||||
}
|
||||
else if (mask0)
|
||||
{
|
||||
stream << flag0;
|
||||
}
|
||||
else if (mask1)
|
||||
{
|
||||
stream << flag1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << '0';
|
||||
}
|
||||
|
||||
util::stream_format(stream, ", 0x%03X", op & 0x3ff);
|
||||
return 1 | (mask0 || mask1 ? STEP_COND : 0) | SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_complex_branch - Disassemble a complex
|
||||
// branch control op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_complex_branch(std::ostream &stream, uint16_t op)
|
||||
{
|
||||
uint32_t type = (op >> 10) & 7;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0: // BLT
|
||||
stream << "BLT";
|
||||
break;
|
||||
case 1: // BLE
|
||||
stream << "BLE";
|
||||
break;
|
||||
case 2: // BGE
|
||||
stream << "BGE";
|
||||
break;
|
||||
case 3: // BGT
|
||||
stream << "BGT";
|
||||
break;
|
||||
case 4: // BHI
|
||||
stream << "BHI";
|
||||
break;
|
||||
case 5: // BLS
|
||||
stream << "BLS";
|
||||
break;
|
||||
case 6: // BXS
|
||||
stream << "BXS";
|
||||
break;
|
||||
case 7: // BXC
|
||||
stream << "BXC";
|
||||
break;
|
||||
}
|
||||
|
||||
util::stream_format(stream, " 0x%03X", op & 0x3ff);
|
||||
return 1 | STEP_COND | SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_control - Disassemble a control op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_control(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op)
|
||||
{
|
||||
uint32_t mode = (op >> 13) & 3;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
// Special
|
||||
case 0:
|
||||
{
|
||||
return dasm_special(stream, pc, opcodes, op);
|
||||
}
|
||||
|
||||
// Branches
|
||||
case 1: case 2:
|
||||
{
|
||||
return dasm_branch(stream, op);
|
||||
}
|
||||
|
||||
// Complex branches
|
||||
case 3:
|
||||
{
|
||||
return dasm_complex_branch(stream, op);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
util::stream_format(stream, "0x%04X", op);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dasm_arithmetic - Disassemble an arithmetic op
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t dspp_disassembler::dasm_arithmetic(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op)
|
||||
{
|
||||
// Decode the various fields
|
||||
uint32_t numops = (op >> 13) & 3;
|
||||
uint32_t muxa = (op >> 10) & 3;
|
||||
uint32_t muxb = (op >> 8) & 3;
|
||||
uint32_t alu_op = (op >> 4) & 0xf;
|
||||
uint32_t barrel_code = op & 0xf;
|
||||
|
||||
uint32_t opidx = 0;
|
||||
|
||||
// Check for operand overflow
|
||||
if (numops == 0 && ((muxa == 1) || (muxa == 2) || (muxb == 1) || (muxb == 2)))
|
||||
numops = 4;
|
||||
|
||||
// Implicit barrel shift
|
||||
if (barrel_code == 8)
|
||||
++numops;
|
||||
|
||||
if (muxa == 3 || muxb == 3)
|
||||
{
|
||||
uint32_t mul_sel = (op >> 12) & 1;
|
||||
|
||||
++opidx;
|
||||
if (mul_sel)
|
||||
++opidx;
|
||||
}
|
||||
|
||||
stream << "LOAD ";
|
||||
|
||||
if (alu_op != 1)
|
||||
{
|
||||
if (alu_op == 9)
|
||||
stream << "NOT ";
|
||||
|
||||
switch (muxa)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
stream << "ACC";
|
||||
break;
|
||||
}
|
||||
case 1: case 2:
|
||||
{
|
||||
format_operand(stream, opcodes.r16(pc + 1 + opidx++));
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
uint32_t mul_sel = (op >> 12) & 1;
|
||||
|
||||
format_operand(stream, opcodes.r16(pc + 1));
|
||||
stream << " * ";
|
||||
if (mul_sel)
|
||||
format_operand(stream, opcodes.r16(pc + 2));
|
||||
else
|
||||
stream << "ACC";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (alu_op)
|
||||
{
|
||||
case 0: // _TRA
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 1: // _NEG
|
||||
{
|
||||
stream << "NEG ";
|
||||
break;
|
||||
}
|
||||
case 2: // _+
|
||||
{
|
||||
stream << " + ";
|
||||
break;
|
||||
}
|
||||
case 3: // _+C
|
||||
{
|
||||
stream << " + C";
|
||||
break;
|
||||
}
|
||||
case 4: // _-
|
||||
{
|
||||
stream << " - ";
|
||||
break;
|
||||
}
|
||||
case 5: // _-B
|
||||
{
|
||||
stream << " - B";
|
||||
break;
|
||||
}
|
||||
case 6: // _++
|
||||
{
|
||||
stream << "++";
|
||||
break;
|
||||
}
|
||||
case 7: // _--
|
||||
{
|
||||
stream << "--";
|
||||
break;
|
||||
}
|
||||
case 8: // _TRL
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 9: // _NOT
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 10: // _AND
|
||||
{
|
||||
stream << " AND ";
|
||||
break;
|
||||
}
|
||||
case 11: // _NAND
|
||||
{
|
||||
stream << " NAND ";
|
||||
break;
|
||||
}
|
||||
case 12: // _OR
|
||||
{
|
||||
stream << " OR ";
|
||||
break;
|
||||
}
|
||||
case 13: // _NOR
|
||||
{
|
||||
stream << " NOR ";
|
||||
break;
|
||||
}
|
||||
case 14: // _XOR
|
||||
{
|
||||
stream << " XOR ";
|
||||
break;
|
||||
}
|
||||
case 15: // _XNOR
|
||||
{
|
||||
stream << " XNOR ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alu_op == 1 || alu_op == 2 || alu_op == 4 || alu_op >= 10)
|
||||
{
|
||||
switch (muxb)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
stream << "ACC";
|
||||
break;
|
||||
}
|
||||
case 1: case 2:
|
||||
{
|
||||
format_operand(stream, opcodes.r16(pc + 1 + opidx++));
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
uint32_t mul_sel = (op >> 12) & 1;
|
||||
|
||||
format_operand(stream, opcodes.r16(pc + 1));
|
||||
stream << " * ";
|
||||
if (mul_sel)
|
||||
format_operand(stream, opcodes.r16(pc + 2));
|
||||
else
|
||||
stream << "ACC";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Barrel shift
|
||||
static const int32_t shifts[8] = { 0, 1, 2, 3, 4, 5, 8, 16 };
|
||||
|
||||
if (barrel_code == 8)
|
||||
{
|
||||
stream << " SHIFT ";
|
||||
format_operand(stream, opcodes.r16(pc + 1 + opidx++));
|
||||
}
|
||||
|
||||
else if (barrel_code & 8)
|
||||
{
|
||||
// Right shift
|
||||
uint32_t shift = shifts[(~barrel_code + 1) & 7];
|
||||
|
||||
if (shift != 0)
|
||||
{
|
||||
util::stream_format(stream, " >> %d", shift);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Left shift
|
||||
uint32_t shift = shifts[barrel_code];
|
||||
|
||||
if (shift == 16)
|
||||
{
|
||||
// Clip and saturate
|
||||
stream << " SAT";
|
||||
}
|
||||
else if (shift != 0)
|
||||
{
|
||||
util::stream_format(stream, " << %d", shift);
|
||||
}
|
||||
}
|
||||
|
||||
if (opidx < numops)
|
||||
{
|
||||
stream << ", ";
|
||||
format_operand(stream, opcodes.r16(pc + 1 + opidx));
|
||||
}
|
||||
|
||||
return (numops + 1) | SUPPORTED;
|
||||
}
|
||||
|
||||
offs_t dspp_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
{
|
||||
// Decode and disassemble
|
||||
uint16_t op = opcodes.r16(pc);
|
||||
if (op & 0x8000)
|
||||
return dasm_control(stream, pc, opcodes, op);
|
||||
else
|
||||
return dasm_arithmetic(stream, pc, opcodes, op);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Philip Bennett
|
||||
// copyright-holders:Philip Bennett, AJR
|
||||
/*
|
||||
DSPP disassembler shim
|
||||
*/
|
||||
@ -17,6 +17,16 @@ public:
|
||||
|
||||
virtual uint32_t opcode_alignment() const override;
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
|
||||
private:
|
||||
static void format_operand(std::ostream &stream, uint16_t operand);
|
||||
|
||||
static offs_t dasm_control(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op);
|
||||
static offs_t dasm_super_special(std::ostream &stream, uint16_t op);
|
||||
static offs_t dasm_special(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op);
|
||||
static offs_t dasm_branch(std::ostream &stream, uint16_t op);
|
||||
static offs_t dasm_complex_branch(std::ostream &stream, uint16_t op);
|
||||
static offs_t dasm_arithmetic(std::ostream &stream, offs_t pc, const data_buffer &opcodes, uint16_t op);
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_DSPP_DSPPDASM_H
|
||||
|
@ -48,6 +48,7 @@ using util::BIT;
|
||||
#include "cpu/dsp32/dsp32dis.h"
|
||||
#include "cpu/dsp56000/dsp56000d.h"
|
||||
#include "cpu/dsp56156/dsp56dsm.h"
|
||||
#include "cpu/dspp/dsppdasm.h"
|
||||
#include "cpu/e0c6200/e0c6200d.h"
|
||||
#include "cpu/e132xs/32xsdasm.h"
|
||||
#include "cpu/es5510/es5510d.h"
|
||||
@ -452,6 +453,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "dsp32c", le, 0, []() -> util::disasm_interface * { return new dsp32c_disassembler; } },
|
||||
{ "dsp56000", be, -2, []() -> util::disasm_interface * { return new dsp56000_disassembler; } },
|
||||
{ "dsp56156", le, -1, []() -> util::disasm_interface * { return new dsp56156_disassembler; } },
|
||||
{ "dspp", be, -1, []() -> util::disasm_interface * { return new dspp_disassembler; } },
|
||||
{ "e0c6200", be, -1, []() -> util::disasm_interface * { return new e0c6200_disassembler; } },
|
||||
{ "epg3231", le, -1, []() -> util::disasm_interface * { return new epg3231_disassembler; } },
|
||||
// { "es5510", be, 0, []() -> util::disasm_interface * { return new es5510_disassembler; } }, // Currently does nothing
|
||||
|
Loading…
Reference in New Issue
Block a user