Add tentative VT61/VT62 disassembler and skeleton CPU device

This commit is contained in:
AJR 2020-01-13 21:18:27 -05:00
parent 1329d54013
commit 96ec01a614
8 changed files with 521 additions and 17 deletions

View File

@ -3015,6 +3015,23 @@ if (CPUS["VT50"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/vt50/vt50dasm.h")
end
--------------------------------------------------
-- DEC VT61
--@src/devices/cpu/vt61/vt61.h,CPUS["VT61"] = true
--------------------------------------------------
if (CPUS["VT61"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/vt61/vt61.cpp",
MAME_DIR .. "src/devices/cpu/vt61/vt61.h",
}
end
if (CPUS["VT61"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/vt61/vt61dasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/vt61/vt61dasm.h")
end
--------------------------------------------------
-- National Semiconductor PACE/INS8900
--@src/devices/cpu/pace/pace.h,CPUS["PACE"] = true

View File

@ -149,6 +149,7 @@ CPUS["CR16B"] = true
CPUS["FR"] = true
CPUS["DSP56000"] = true
CPUS["VT50"] = true
CPUS["VT61"] = true
CPUS["PACE"] = true
CPUS["WE32000"] = true
CPUS["RX01"] = true

View File

@ -0,0 +1,107 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
DEC VT61 CPU
Currently this device is just a stub with no actual execution core.
***************************************************************************/
#include "emu.h"
#include "vt61.h"
#include "vt61dasm.h"
// device type definition
DEFINE_DEVICE_TYPE(VT61_CPU, vt61_cpu_device, "vt61_cpu", "DEC VT61 CPU")
vt61_cpu_device::vt61_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: cpu_device(mconfig, VT61_CPU, tag, owner, clock)
, m_program_config("microprogram", ENDIANNESS_LITTLE, 16, 10, -1)
, m_memory_config("memory", ENDIANNESS_LITTLE, 8, 16, 0)
, m_idr_config("IDR", ENDIANNESS_LITTLE, 8, 6, 0)
, m_program_cache(nullptr)
, m_memory_cache(nullptr)
, m_idr_cache(nullptr)
, m_pc(0)
, m_ac(0)
, m_mar(0)
, m_mdr(0)
, m_ir(0)
, m_sp{0}
, m_icount(0)
{
m_program_config.m_is_octal = true;
m_memory_config.m_is_octal = true;
m_idr_config.m_is_octal = true;
}
std::unique_ptr<util::disasm_interface> vt61_cpu_device::create_disassembler()
{
return std::make_unique<vt61_disassembler>();
}
device_memory_interface::space_config_vector vt61_cpu_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_DATA, &m_memory_config),
std::make_pair(AS_IDR, &m_idr_config)
};
}
void vt61_cpu_device::device_start()
{
m_program_cache = space(AS_PROGRAM).cache<1, -1, ENDIANNESS_LITTLE>();
m_memory_cache = space(AS_DATA).cache<0, 0, ENDIANNESS_LITTLE>();
m_idr_cache = space(AS_IDR).cache<0, 0, ENDIANNESS_LITTLE>();
set_icountptr(m_icount);
state_add(VT61_PC, "PC", m_pc).mask(01777).formatstr("%5s");
state_add(STATE_GENPC, "GENPC", m_pc).mask(01777).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_pc).mask(01777).noshow();
state_add(VT61_AC, "AC", m_ac).formatstr("%03O");
state_add(VT61_MAR, "MAR", m_mar).formatstr("%06O");
state_add<u8>(VT61_MALO, "MALO",
[this]() { return m_mar & 000377; },
[this](u8 data) { m_mar = (m_mar & 0177400) | data; }
).noshow();
state_add<u8>(VT61_MAHI, "MAHI",
[this]() { return (m_mar & 0177400) >> 8; },
[this](u8 data) { m_mar = (m_mar & 000377) | (data << 8); }
).noshow();
state_add(VT61_MDR, "MDR", m_mdr).formatstr("%03O");
state_add(VT61_IR, "IR", m_ir).mask(6);
for (int i = 0; i < 16; i++)
state_add(VT61_R0 + i, string_format("R%d", i).c_str(), m_sp[i]).formatstr("%03O");
save_item(NAME(m_pc));
save_item(NAME(m_ac));
save_item(NAME(m_mar));
save_item(NAME(m_mdr));
save_item(NAME(m_ir));
save_item(NAME(m_sp));
}
void vt61_cpu_device::device_reset()
{
m_pc = 0;
}
void vt61_cpu_device::execute_run()
{
debugger_instruction_hook(m_pc);
m_icount = 0;
}
void vt61_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case VT61_PC:
str = string_format("%o:%03o", m_pc >> 8, m_pc & 0377);
break;
}
}

View File

@ -0,0 +1,69 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_CPU_VT61_VT61_H
#define MAME_CPU_VT61_VT61_H
#pragma once
class vt61_cpu_device : public cpu_device
{
public:
enum {
VT61_PC,
VT61_AC,
VT61_MAR, VT61_MALO, VT61_MAHI,
VT61_MDR,
VT61_IR,
VT61_R0, VT61_R1, VT61_R2, VT61_R3,
VT61_R4, VT61_R5, VT61_R6, VT61_R7,
VT61_R8, VT61_R9, VT61_R10, VT61_R11,
VT61_R12, VT61_R13, VT61_R14, VT61_R15
};
enum {
AS_IDR = 2
};
// construction/destruction
vt61_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
virtual void execute_run() override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
// device_state_interface overrides
void state_string_export(const device_state_entry &entry, std::string &str) const override;
private:
// address spaces
address_space_config m_program_config;
address_space_config m_memory_config;
address_space_config m_idr_config;
memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_program_cache;
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_memory_cache;
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_idr_cache;
// internal state
u16 m_pc;
u8 m_ac;
u16 m_mar;
u8 m_mdr;
u8 m_ir;
u8 m_sp[16]; // scratchpad memory
s32 m_icount;
};
DECLARE_DEVICE_TYPE(VT61_CPU, vt61_cpu_device)
#endif // MAME_CPU_VT61_VT61_H

View File

@ -0,0 +1,275 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
DEC VT61 microcode disassembler
No microprogram source listing appears to have been published by DEC,
nor any instruction reference other than the decode signal references
in the schematics. The instruction format should not be regarded as
official, though it draws on some of DEC's PDP assembly languages.
***************************************************************************/
#include "emu.h"
#include "vt61dasm.h"
vt61_disassembler::vt61_disassembler()
: util::disasm_interface()
{
}
const char *const vt61_disassembler::s_opr_a[8] = {
"NOP", // NO OP A
"IAC", // INC AC
"LIR", // LD IR
"IMA", // INC MA
"SMD", // SHIFT MDR
"JMP0", // CLR PC
"CMPC8", // COMP PC 8
"LDR" // LD RAM
};
const char *const vt61_disassembler::s_opr_b[16] = {
"OPR", // NO OP B
"SPARE",
"RC", // RESET C FLAG
"SPARE",
"SPARE",
"LMISC", // LD MISC FLAG
"LLED", // LD LED FLAG
"LMOD", // LD MODEM FLAG
"SKCLK", // SET KEYCLICK
"LINTRC", // LD INTRPT CONTROL
"SPARE",
"CNBR", // CLR NBR
"LSYNC", // LD SYNC + CLR NBX
"PLD", // PLD
"CVSR", // CLR VID SERV REQ
"ENVID" // ENABLE VID LOAD
};
const char *const vt61_disassembler::s_sources[12] = {
"AC", // SEL AC
"STAT1", // SEL STATUS 1
"SW", // SEL SWITCHES
"CAS1", // SEL CAS 1
"CAS2", // SEL CAS 2
"RAM", // SEL RAM
"IDR", // SEL IDR
"UART", // SEL UART
"SPARE",
"TBSW", // TEST BOX SWITCH
"invalid", // SEL SPM LO
"invalid" // SEL SPM HI
};
const char *const vt61_disassembler::s_conditions[32][2] = {
{ "NINTR1", "INTR1" }, // INTR 1 L
{ "NBXF", "NBXT" }, // NBX L
{ "NBRF", "NBRT" }, // NBR L
{ "NF1", "F1" }, // F1 L
{ "NF2", "F2" }, // F2 L
{ "NCF", "CF" }, // C L
{ "NURF", "URF" }, // UART R FLAG L
{ "NUTB", "UTB" }, // UART T BUFF L
{ "NXOFF", "XOFF" }, // DO X OFF L
{ "NGOSR", "GOSR" }, // GOUT SER RQ L
{ "NF3", "F3" }, // F3 L
{ "NINTR2", "INTR2" }, // INTR 2 L
{ "KEYUP", "KEYDN" }, // KEY DOWN L
{ "NPWRUP", "PWRUP" }, // PWR UP L
{ "NSYNC", "SYNC" }, // SYNC ENA L
{ "PE", "NPE" }, // PARITY ERROR H
{ "BZY", "NBZY" }, // MEM BZY H
{ "EQ", "NE" }, // EQUAL H
{ "CC", "CS" }, // CARRY OUT L
{ "MDOFO", "MDOFZ" }, // MDR O.F. OUT H
{ "NCSR", "CSR" }, // COPIER SER REQ L
{ "NCPCF", "CPCF" }, // C-PCF L
{ "T", "F" }, // TRUE H
{ "NVSR", "VSR" }, // VID SERV REQ L
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" },
{ "?H", "?L" }
};
u32 vt61_disassembler::opcode_alignment() const
{
return 1;
}
u32 vt61_disassembler::interface_flags() const
{
return PAGED;
}
u32 vt61_disassembler::page_address_bits() const
{
return 8;
}
void vt61_disassembler::dasm_spr(std::ostream &stream, u8 r)
{
if (BIT(r, 4))
util::stream_format(stream, "IR%d", r & 9);
else
util::stream_format(stream, "R%d", r);
}
void vt61_disassembler::dasm_source(std::ostream &stream, u16 inst)
{
if ((inst & 003000) == 003000)
util::stream_format(stream, "#%03o", inst & 000377);
else
{
if ((inst & 003400) == 002400 && (inst & 070000) != 070000)
dasm_spr(stream, (inst & 000170) >> 2 | (inst & 000200) >> 7);
else
stream << s_sources[(inst & 003600) >> 7];
if ((inst & 000007) != 0 && (inst & 0170000) != 0100000)
stream << "," << s_opr_a[inst & 000007];
}
}
offs_t vt61_disassembler::disassemble(std::ostream &stream, offs_t pc, const vt61_disassembler::data_buffer &opcodes, const vt61_disassembler::data_buffer &params)
{
u16 inst = opcodes.r16(pc);
offs_t flags = SUPPORTED;
if (!BIT(inst, 15))
{
if ((inst & 074000) == 054000)
{
stream << "LDU";
if ((inst & 000007) != 0 && (inst & 003000) != 003000)
{
stream << " " << s_opr_a[inst & 000007];
if ((inst & 000007) == 5)
flags |= STEP_OUT;
}
}
else
{
switch (inst & 070000)
{
case 000000:
stream << "LAC ";
break;
case 040000:
stream << "LMA " << (BIT(inst, 11) ? "HI," : "LO,");
break;
case 050000:
stream << "JMP ";
break;
case 060000:
if (BIT(inst, 11))
stream << "LMD ";
else
stream << "CAS3 ";
break;
case 070000:
stream << "LSP ";
dasm_spr(stream, (inst & 000170) >> 2 | (inst & 004000) >> 11);
stream << ",";
break;
default:
stream << "LD? ";
break;
}
dasm_source(stream, inst);
if ((inst & 000007) == 5 && (inst & 003000) != 003000)
flags |= STEP_OUT;
}
}
else if (BIT(inst, 14))
{
util::stream_format(stream, "BR %s,%03o", s_conditions[(inst & 017400) >> 8][BIT(inst, 13)], inst & 000377);
}
else if (BIT(inst, 13))
{
if ((inst & 007407) == 0)
stream << "NOP";
else
{
stream << s_opr_b[(inst & 007400) >> 8];
if ((inst & 000007) != 0)
{
stream << " " << s_opr_a[inst & 000007];
if ((inst & 000207) == 000204)
stream << "A"; // ENABLE MDR A (CAS DATA)
if ((inst & 000107) == 000104)
stream << "B"; // ENABLE MDR B (SYNC DATA IN)
if ((inst & 000007) == 5)
flags |= STEP_OUT;
}
}
}
else if (BIT(inst, 12))
{
stream << "CMP ";
dasm_source(stream, inst);
if ((inst & 000007) == 5 && (inst & 003000) != 003000)
flags |= STEP_OUT;
}
else switch (inst & 000007)
{
case 0:
stream << "CMA";
break;
case 1:
stream << "ORA ";
dasm_source(stream, inst);
break;
case 2:
stream << "XOR ";
dasm_source(stream, inst);
break;
case 3:
stream << "AND ";
dasm_source(stream, inst);
break;
case 4:
stream << "DCA";
if (BIT(inst, 11))
stream << " C";
break;
case 5:
stream << "ADD ";
if (BIT(inst, 11))
stream << "C,";
dasm_source(stream, inst);
break;
case 6:
stream << "SUB ";
if (BIT(inst, 11))
stream << "C,";
dasm_source(stream, inst);
break;
case 7:
stream << "SLA";
if (BIT(inst, 11))
stream << " C";
break;
}
return 1 | flags;
}

View File

@ -0,0 +1,34 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_CPU_VT61_VT61DASM_H
#define MAME_CPU_VT61_VT61DASM_H
#pragma once
class vt61_disassembler : public util::disasm_interface
{
public:
// construction/destruction
vt61_disassembler();
protected:
// disassembler overrides
virtual u32 opcode_alignment() const override;
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 &params) override;
private:
// tables
static const char *const s_opr_a[8];
static const char *const s_opr_b[16];
static const char *const s_sources[12];
static const char *const s_conditions[32][2];
// disassembly helpers
void dasm_spr(std::ostream &stream, u8 r);
void dasm_source(std::ostream &stream, u16 inst);
};
#endif // MAME_CPU_VT61_VT61DASM_H

View File

@ -8,7 +8,7 @@
#include "emu.h"
//#include "bus/rs232/rs232.h"
//#include "cpu/vt61/vt61.h"
#include "cpu/vt61/vt61.h"
#include "machine/ay31015.h"
//#include "sound/spkrdev.h"
#include "screen.h"
@ -19,6 +19,7 @@ class vt62_state : public driver_device
public:
vt62_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_uart(*this, "uart")
{
}
@ -31,11 +32,11 @@ protected:
private:
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
//void micro_map(address_map &map);
//void memory_map(address_map &map);
//void decode_map(address_map &map);
void micro_map(address_map &map);
void memory_map(address_map &map);
void decode_map(address_map &map);
//required_device<vt61_cpu_device> m_maincpu;
required_device<vt61_cpu_device> m_maincpu;
required_device<ay31015_device> m_uart;
//required_ioport_array<8> m_keys;
//required_ioport m_baud_sw;
@ -50,35 +51,33 @@ u32 vt62_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const
return 0;
}
#ifdef UNUSED_DEFINITION
void vt62_state::micro_map(address_map &map)
{
map(0x000, 0x3ff).rom().region("crom", 0);
map(00000, 01777).rom().region("crom", 0);
}
void vt62_state::memory_map(address_map &map)
{
map(0x0000, 0x00ff).mirror(0x4f00).ram(); // static RAM A
map(0x1000, 0x1fff).mirror(0x4000).ram(); // dynamic RAM B
map(0x2000, 0x2fff).mirror(0x4000).ram(); // dynamic RAM C
map(0x8000, 0x9fff).mirror(0x6000).rom().region("mrom", 0);
map(0000000, 0000377).mirror(0047400).ram(); // static RAM A
map(0010000, 0013777).mirror(0040000).ram(); // dynamic RAM B
map(0020000, 0023777).mirror(0040000).ram(); // dynamic RAM C
map(0100000, 0117777).mirror(0060000).rom().region("mrom", 0);
}
void vt62_state::decode_map(address_map &map)
{
map(0x00, 0x3f).rom().region("idr", 0);
map(000, 077).rom().region("idr", 0);
}
#endif
static INPUT_PORTS_START(vt62)
INPUT_PORTS_END
void vt62_state::vt62(machine_config &mconfig)
{
//VT61_CPU(mconfig, m_maincpu, 15.36_MHz_XTAL);
//m_maincpu->set_addrmap(AS_PROGRAM, &vt62_state::micro_map);
//m_maincpu->set_addrmap(AS_DATA, &vt62_state::memory_map);
//m_maincpu->set_addrmap(vt61_cpu_device::AS_IDR, &vt62_state::decode_map);
VT61_CPU(mconfig, m_maincpu, 15.36_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &vt62_state::micro_map);
m_maincpu->set_addrmap(AS_DATA, &vt62_state::memory_map);
m_maincpu->set_addrmap(vt61_cpu_device::AS_IDR, &vt62_state::decode_map);
AY51013(mconfig, m_uart);

View File

@ -161,6 +161,7 @@ using util::BIT;
#include "cpu/v60/v60d.h"
#include "cpu/v810/v810dasm.h"
#include "cpu/vt50/vt50dasm.h"
#include "cpu/vt61/vt61dasm.h"
#include "cpu/we32000/we32100d.h"
#include "cpu/z180/z180dasm.h"
#include "cpu/z8/z8dasm.h"
@ -531,6 +532,7 @@ static const dasm_table_entry dasm_table[] =
{ "v810", le, 0, []() -> util::disasm_interface * { return new v810_disassembler; } },
{ "vt50", le, 0, []() -> util::disasm_interface * { return new vt50_disassembler; } },
{ "vt52", le, 0, []() -> util::disasm_interface * { return new vt52_disassembler; } },
{ "vt61", le, -1, []() -> util::disasm_interface * { return new vt61_disassembler; } },
{ "we32100", be, 0, []() -> util::disasm_interface * { return new we32100_disassembler; } },
{ "x86_16", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 16; return new i386_disassembler(&i386_unidasm); } },
{ "x86_32", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 32; return new i386_disassembler(&i386_unidasm); } },