mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
Add disassembler for CDC 160(-A) architecture
This commit is contained in:
parent
f3d02b6425
commit
fb6b48711a
@ -3521,6 +3521,16 @@ if opt_tool(CPUS, "SIGMA2") then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/sigma2/sigma2d.h")
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
-- Control Data Corporation 160 (disassembler only)
|
||||
--@src/devices/cpu/cdc160/cdc160.h,CPUS["CDC160"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if opt_tool(CPUS, "CDC160") then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/cdc160/cdc160d.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/cdc160/cdc160d.h")
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
-- Control Data Corporation 1700 (disassembler only)
|
||||
--@src/devices/cpu/cdc1700/cdc1700.h,CPUS["CDC1700"] = true
|
||||
|
379
src/devices/cpu/cdc160/cdc160d.cpp
Normal file
379
src/devices/cpu/cdc160/cdc160d.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/***************************************************************************
|
||||
|
||||
CDC 160/160-A disassembler
|
||||
|
||||
Some departures from the syntax used by CDC's assemblers:
|
||||
— Two-word instructions are always written on one line each. This
|
||||
was not necessarily permitted, especially for INP and OUT.
|
||||
— For forward and backward addressing modes, the effective address is
|
||||
given rather than the 6-bit displacement to be added to P.
|
||||
— For 160-A only, a synthetic two-word instruction JPM (Jump Memory)
|
||||
represents the common pattern of using JFI with a 1-word displacement
|
||||
to jump to any address in the 4096-word bank.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cdc160d.h"
|
||||
|
||||
cdc160_disassembler::cdc160_disassembler()
|
||||
: util::disasm_interface()
|
||||
{
|
||||
}
|
||||
|
||||
u32 cdc160_disassembler::opcode_alignment() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
cdc160a_disassembler::cdc160a_disassembler()
|
||||
: cdc160_disassembler()
|
||||
{
|
||||
}
|
||||
|
||||
u32 cdc160a_disassembler::interface_flags() const
|
||||
{
|
||||
return PAGED;
|
||||
}
|
||||
|
||||
u32 cdc160a_disassembler::page_address_bits() const
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const char *const f_160a_bank_ops[7] =
|
||||
{
|
||||
"SRJ", "SIC", "IRJ", "SDC", "DRJ", "SID", "ACJ"
|
||||
};
|
||||
|
||||
const char *const f_160_alu_ops[10] =
|
||||
{
|
||||
"LP", "LS", "LD", "LC", "AD", "SB", "ST", "SR", "RA", "AO"
|
||||
};
|
||||
|
||||
const char *const f_160a_alu_ops[10] =
|
||||
{
|
||||
"LP", "SC", "LD", "LC", "AD", "SB", "ST", "SR", "RA", "AO"
|
||||
};
|
||||
|
||||
const char *const f_cond_jp_ops[6] =
|
||||
{
|
||||
"ZJ", "NZ", "PJ", "NJ"
|
||||
};
|
||||
|
||||
// 12-bit ones' complement addition
|
||||
inline u16 add_relative(uint_fast16_t a, uint_fast16_t b) noexcept
|
||||
{
|
||||
u16 c = (a & 07777) + (b & 07777);
|
||||
if (c >= 07777)
|
||||
c -= 07777;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
offs_t cdc160_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
{
|
||||
u16 inst = opcodes.r16(pc) & 07777;
|
||||
if (inst < 0200)
|
||||
{
|
||||
util::stream_format(stream, "%s %o", BIT(inst, 6) ? "SHA" : "ERR", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else if (inst < 01000)
|
||||
{
|
||||
// No address (6-bit immediate) mode
|
||||
util::stream_format(stream, "%sN %o", f_160_alu_ops[BIT(inst, 6, 3) - 2], inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else if (inst < 06000)
|
||||
{
|
||||
if (BIT(inst, 7))
|
||||
{
|
||||
// Relative forward or backward address mode
|
||||
util::stream_format(stream, "%s%c %04o", f_160_alu_ops[BIT(inst, 8, 4) - 2], BIT(inst, 6) ? 'B' : 'F',
|
||||
add_relative(pc, BIT(inst, 6) ? ~(inst & 0077) : inst & 0077));
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct or indirect address mode
|
||||
util::stream_format(stream, "%s%c %02o", f_160_alu_ops[BIT(inst, 8, 4) - 2], BIT(inst, 6) ? 'I' : 'D', inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
else if (inst < 07000)
|
||||
{
|
||||
// Relative conditional jumps
|
||||
util::stream_format(stream, "%s%c %04o", f_cond_jp_ops[BIT(inst, 6, 2)], BIT(inst, 8) ? 'B' : 'F',
|
||||
add_relative(pc, BIT(inst, 8) ? ~(inst & 0077) : inst & 0077));
|
||||
return 1 | STEP_COND | SUPPORTED;
|
||||
}
|
||||
else switch (BIT(inst, 6, 3))
|
||||
{
|
||||
case 0:
|
||||
util::stream_format(stream, "JPI %02o", inst & 0077);
|
||||
return 1 | STEP_OUT | SUPPORTED;
|
||||
|
||||
case 1:
|
||||
// Jump forward indirect
|
||||
util::stream_format(stream, "JFI %04o", add_relative(pc, inst & 0077));
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 2: case 3:
|
||||
util::stream_format(stream, "%s %04o %04o", BIT(inst, 6) ? "OUT" : "INP", add_relative(pc, inst & 0077), opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | SUPPORTED;
|
||||
|
||||
case 4:
|
||||
// Output direct
|
||||
util::stream_format(stream, "OTN %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 5:
|
||||
// External function
|
||||
util::stream_format(stream, "EXF %04o", (pc + (inst & 0077)) & 07777);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 6:
|
||||
util::stream_format(stream, "INA %o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 7: default:
|
||||
util::stream_format(stream, "HLT %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
offs_t cdc160a_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
{
|
||||
u16 inst = opcodes.r16(pc) & 07777;
|
||||
if (inst < 0200)
|
||||
{
|
||||
if (inst >= 0010 && inst < 0100)
|
||||
{
|
||||
util::stream_format(stream, "%s %d", f_160a_bank_ops[BIT(inst, 3, 3) - 1], inst & 0007);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else switch (inst)
|
||||
{
|
||||
case 0000:
|
||||
stream << "ERR";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0001:
|
||||
stream << "NOP";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0100:
|
||||
util::stream_format(stream, "BLS %04o", opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | STEP_COND | SUPPORTED;
|
||||
|
||||
case 0101:
|
||||
stream << "PTA";
|
||||
return 1 | (BIT(opcodes.r16(pc + 1), 6, 3) == 070 ? STEP_OVER | step_over_extra(1) : 0) | SUPPORTED;
|
||||
|
||||
case 0102:
|
||||
stream << "LS1";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0103:
|
||||
stream << "LS2";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0104:
|
||||
stream << "CBC";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0105:
|
||||
util::stream_format(stream, "ATE %04o", opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | STEP_COND | SUPPORTED;
|
||||
|
||||
case 0106:
|
||||
util::stream_format(stream, "ATX %04o", opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | STEP_COND | SUPPORTED;
|
||||
|
||||
case 0107:
|
||||
stream << "ETA";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0110:
|
||||
stream << "LS3";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0111:
|
||||
stream << "LS6";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0112:
|
||||
stream << "MUT";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0113:
|
||||
stream << "MUH";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0114:
|
||||
stream << "RS1";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0115:
|
||||
stream << "RS2";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0120:
|
||||
stream << "CIL";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0130:
|
||||
stream << "CTA";
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0140: case 0141: case 0142: case 0143: case 0144: case 0145: case 0146: case 0147:
|
||||
util::stream_format(stream, "SBU %d", inst & 0007);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0150: case 0151: case 0152: case 0153: case 0154: case 0155: case 0156: case 0157:
|
||||
util::stream_format(stream, "STP %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 0160: case 0161: case 0162: case 0163: case 0164: case 0165: case 0166: case 0167:
|
||||
util::stream_format(stream, "STE %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
default:
|
||||
util::stream_format(stream, "%04o", inst);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
else if (inst < 01000)
|
||||
{
|
||||
// No address (6-bit immediate) mode
|
||||
util::stream_format(stream, "%sN %o", f_160a_alu_ops[BIT(inst, 6, 3) - 2], inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else if (inst < 06000)
|
||||
{
|
||||
if (BIT(inst, 7))
|
||||
{
|
||||
if ((inst & 0077) != 0)
|
||||
{
|
||||
// Relative forward or backward address mode
|
||||
util::stream_format(stream, "%s%c %04o", f_160a_alu_ops[BIT(inst, 8, 4) - 2], BIT(inst, 6) ? 'B' : 'F',
|
||||
add_relative(pc, BIT(inst, 6) ? ~(inst & 0077) : inst & 0077));
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else if (BIT(inst, 6))
|
||||
{
|
||||
// Specific address mode
|
||||
util::stream_format(stream, "%sS", f_160a_alu_ops[BIT(inst, 8, 4) - 2]);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Constant address (12-bit immediate) mode
|
||||
util::stream_format(stream, "%sC %04o", f_160a_alu_ops[BIT(inst, 8, 4) - 2], opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
else if ((inst & 0177) == 0100)
|
||||
{
|
||||
// Memory address mode
|
||||
util::stream_format(stream, "%sM %04o", f_160a_alu_ops[BIT(inst, 8, 4) - 2], opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct or indirect address mode
|
||||
util::stream_format(stream, "%s%c %02o", f_160a_alu_ops[BIT(inst, 8, 4) - 2], BIT(inst, 6) ? 'I' : 'D', inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
}
|
||||
else if (inst < 07000)
|
||||
{
|
||||
// Relative conditional jumps
|
||||
util::stream_format(stream, "%s%c %04o", f_cond_jp_ops[BIT(inst, 6, 2)], BIT(inst, 8) ? 'B' : 'F',
|
||||
add_relative(pc, BIT(inst, 8) ? ~(inst & 0077) : inst & 0077));
|
||||
return 1 | STEP_COND | SUPPORTED;
|
||||
}
|
||||
else switch (BIT(inst, 6, 3))
|
||||
{
|
||||
case 0:
|
||||
util::stream_format(stream, "JPI %02o", inst & 0077);
|
||||
return 1 | STEP_OUT | SUPPORTED;
|
||||
|
||||
case 1:
|
||||
if ((inst & 0077) <= 1)
|
||||
{
|
||||
util::stream_format(stream, "JP%c %04o", BIT(inst, 0) ? 'M' : 'R', opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | (BIT(inst, 0) ? 0 : STEP_OVER) | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "JFI %04o", add_relative(pc, inst & 0077));
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
case 2: case 3:
|
||||
if ((inst & 0077) == 0)
|
||||
{
|
||||
// Buffer input/output
|
||||
util::stream_format(stream, "IB%c %04o", BIT(inst, 6) ? 'O' : 'I', opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | STEP_COND | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal input/output
|
||||
util::stream_format(stream, "%s %04o %04o", BIT(inst, 6) ? "OUT" : "INP", add_relative(pc, inst & 0077), opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 4:
|
||||
// Output direct
|
||||
util::stream_format(stream, "OTN %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 5:
|
||||
// External function
|
||||
if ((inst & 0077) == 0)
|
||||
{
|
||||
util::stream_format(stream, "EXC %04o", opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "EXF %04o", (pc + (inst & 0077)) & 07777);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
case 6:
|
||||
if ((inst & 0077) == 0)
|
||||
stream << "INA";
|
||||
else if ((inst & 0077) == 0077)
|
||||
stream << "OTA";
|
||||
else
|
||||
util::stream_format(stream, "HWI %02o", inst & 0077);
|
||||
return 1 | SUPPORTED;
|
||||
|
||||
case 7: default:
|
||||
if ((inst & 0077) == 0 || (inst & 0077) == 0077)
|
||||
{
|
||||
stream << "HLT";
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else if ((inst & 070) == 0)
|
||||
{
|
||||
util::stream_format(stream, "SLS %d", inst & 0007);
|
||||
return 1 | SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "%s %02o %04o", (inst & 0007) != 0 ? "SJS" : "SLJ", inst & 077, opcodes.r16(pc + 1) & 07777);
|
||||
return 2 | STEP_COND | SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
34
src/devices/cpu/cdc160/cdc160d.h
Normal file
34
src/devices/cpu/cdc160/cdc160d.h
Normal file
@ -0,0 +1,34 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
|
||||
#ifndef MAME_CPU_CDC160_CDC160D_H
|
||||
#define MAME_CPU_CDC160_CDC160D_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class cdc160_disassembler : public util::disasm_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cdc160_disassembler();
|
||||
|
||||
protected:
|
||||
// util::disasm_interface overrides
|
||||
virtual u32 opcode_alignment() const override;
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
};
|
||||
|
||||
class cdc160a_disassembler : public cdc160_disassembler
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cdc160a_disassembler();
|
||||
|
||||
protected:
|
||||
// util::disasm_interface overrides
|
||||
virtual u32 interface_flags() const override;
|
||||
virtual u32 page_address_bits() const override;
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_CDC160_CDC160D_H
|
@ -30,6 +30,7 @@ using util::BIT;
|
||||
#include "cpu/c33/c33dasm.h"
|
||||
#include "cpu/capricorn/capricorn_dasm.h"
|
||||
#include "cpu/ccpu/ccpudasm.h"
|
||||
#include "cpu/cdc160/cdc160d.h"
|
||||
#include "cpu/cdc1700/cdc1700d.h"
|
||||
#include "cpu/clipper/clipperd.h"
|
||||
#include "cpu/cop400/cop410ds.h"
|
||||
@ -423,6 +424,8 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "c33", le, 0, []() -> util::disasm_interface * { return new c33_disassembler; } },
|
||||
{ "capricorn", le, 0, []() -> util::disasm_interface * { return new capricorn_disassembler; } },
|
||||
{ "ccpu", le, 0, []() -> util::disasm_interface * { return new ccpu_disassembler; } },
|
||||
{ "cdc160", be, -1, []() -> util::disasm_interface * { return new cdc160_disassembler; } },
|
||||
{ "cdc160a", be, -1, []() -> util::disasm_interface * { return new cdc160a_disassembler; } },
|
||||
{ "cdc1700", be, -1, []() -> util::disasm_interface * { return new cdc1700_disassembler; } },
|
||||
{ "cdp1801", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1801); } },
|
||||
{ "cdp1802", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1802); } },
|
||||
|
Loading…
Reference in New Issue
Block a user