summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu
diff options
context:
space:
mode:
author therealmogminer@gmail.com <therealmogminer@gmail.com>2015-08-13 14:37:07 +0200
committer therealmogminer@gmail.com <therealmogminer@gmail.com>2015-08-13 14:38:30 +0200
commit5d7c5fc62becc90d7b0eb9d04548cc2f587b0e19 (patch)
tree96eacc6bdd131accdb48776debfaa421c57a7e4a /src/emu/cpu
parent21b7eb47cd7568cd8f74315458004992fe27540d (diff)
nw, add skeleton and disassembler for DEC PDP-8 CPU
Diffstat (limited to 'src/emu/cpu')
-rw-r--r--src/emu/cpu/pdp8/pdp8.c249
-rw-r--r--src/emu/cpu/pdp8/pdp8.h113
-rw-r--r--src/emu/cpu/pdp8/pdp8dasm.c183
3 files changed, 545 insertions, 0 deletions
diff --git a/src/emu/cpu/pdp8/pdp8.c b/src/emu/cpu/pdp8/pdp8.c
new file mode 100644
index 00000000000..dd2fd6fc6b3
--- /dev/null
+++ b/src/emu/cpu/pdp8/pdp8.c
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ First-gen DEC PDP-8 emulator skeleton
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "pdp8.h"
+
+CPU_DISASSEMBLE( pdp8 );
+
+#define OP ((op >> 011) & 07)
+
+#define MR_IND ((op >> 010) & 01)
+#define MR_PAGE ((op >> 07) & 01)
+#define MR_ADDR (op & 0177)
+
+#define IOT_DEVICE ((op >> 03) & 077)
+#define IOT_IOP1 (op & 01)
+#define IOT_IOP2 ((op >> 01) & 01)
+#define IOT_IOP4 ((op >> 02) & 01)
+
+#define OPR_GROUP ((op >> 010) & 01)
+#define OPR_CLA ((op >> 07) & 01)
+#define OPR_CLL ((op >> 06) & 01)
+#define OPR_CMA ((op >> 05) & 01)
+#define OPR_CML ((op >> 04) & 01)
+#define OPR_ROR ((op >> 03) & 01)
+#define OPR_ROL ((op >> 02) & 01)
+#define OPR_ROT2 ((op >> 01) & 01)
+#define OPR_IAC (op & 01)
+
+#define OPR_SMA OPR_CLL
+#define OPR_SZA OPR_CMA
+#define OPR_SNL OPR_CML
+#define OPR_REVSKIP OPR_ROR
+#define OPR_OSR OPR_ROL
+#define OPR_HLT OPR_ROT2
+
+#define OPR_GROUP_MASK 0401
+#define OPR_GROUP1_VAL 0000
+#define OPR_GROUP2_VAL 0400
+
+const device_type PDP8CPU = &device_creator<pdp8_device>;
+
+//-------------------------------------------------
+// pdp8_device - constructor
+//-------------------------------------------------
+
+pdp8_device::pdp8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, PDP8CPU, "PDP8CPU", tag, owner, clock, "pdp8_cpu", __FILE__),
+ m_program_config("program", ENDIANNESS_BIG, 12, 12),
+ m_pc(0),
+ m_ac(0),
+ m_mb(0),
+ m_ma(0),
+ m_sr(0),
+ m_l(0),
+ m_ir(0),
+ m_halt(true),
+ m_icount(0)
+{
+ // Allocate & setup
+}
+
+
+void pdp8_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ // register our state for the debugger
+ std::string tempstr;
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_l).callimport().callexport().formatstr("%1s").noshow();
+ state_add(PDP8_PC, "PC", m_pc).mask(0xfff);
+ state_add(PDP8_AC, "AC", m_ac).mask(0xfff);
+ state_add(PDP8_MB, "MB", m_mb).mask(0xfff);
+ state_add(PDP8_MA, "MA", m_ma).mask(0xfff);
+ state_add(PDP8_SR, "SR", m_sr).mask(0xfff);
+ state_add(PDP8_L, "L", m_l).mask(0xf);
+ state_add(PDP8_IR, "IR", m_ir).mask(0xff);
+ state_add(PDP8_HALT, "HLT", m_halt).mask(0xf);
+
+ // setup regtable
+ save_item(NAME(m_pc));
+ save_item(NAME(m_ac));
+ save_item(NAME(m_mb));
+ save_item(NAME(m_ma));
+ save_item(NAME(m_sr));
+ save_item(NAME(m_l));
+ save_item(NAME(m_ir));
+ save_item(NAME(m_halt));
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+void pdp8_device::device_stop()
+{
+}
+
+void pdp8_device::device_reset()
+{
+ m_pc = 0;
+ m_ac = 0;
+ m_mb = 0;
+ m_ma = 0;
+ m_sr = 0;
+ m_l = 0;
+ m_ir = 0;
+ m_halt = true;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *pdp8_device::memory_space_config(address_spacenum spacenum) const
+{
+ if (spacenum == AS_PROGRAM)
+ {
+ return &m_program_config;
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void pdp8_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "%c", m_halt ? 'H' : '.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 pdp8_device::disasm_min_opcode_bytes() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 pdp8_device::disasm_max_opcode_bytes() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t pdp8_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( pdp8 );
+ return CPU_DISASSEMBLE_NAME(pdp8)(this, buffer, pc, oprom, opram, options);
+}
+
+
+//**************************************************************************
+// CORE EXECUTION LOOP
+//**************************************************************************
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 pdp8_device::execute_min_cycles() const
+{
+ return 1; // TODO
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 pdp8_device::execute_max_cycles() const
+{
+ return 3; // TODO
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 pdp8_device::execute_input_lines() const
+{
+ return 0; // TODO
+}
+
+
+//-------------------------------------------------
+// execute_set_input - set the state of an input
+// line during execution
+//-------------------------------------------------
+
+void pdp8_device::execute_set_input(int inputnum, int state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// execute_run - execute a timeslice's worth of
+// opcodes
+//-------------------------------------------------
+
+void pdp8_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ m_pc &= 07777;
+
+ debugger_instruction_hook(this, m_pc);
+
+ UINT16 op = m_program->read_word(m_pc);
+
+ --m_icount;
+ }
+}
diff --git a/src/emu/cpu/pdp8/pdp8.h b/src/emu/cpu/pdp8/pdp8.h
new file mode 100644
index 00000000000..58332770dad
--- /dev/null
+++ b/src/emu/cpu/pdp8/pdp8.h
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ First-gen DEC PDP-8 CPU emulator
+
+ Written by MooglyGuy
+*/
+
+#pragma once
+
+#ifndef __PDP8_H__
+#define __PDP8_H__
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pdp8_device
+
+// Used by core CPU interface
+class pdp8_device : public cpu_device
+{
+public:
+ // construction/destruction
+ pdp8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_stop();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str);
+
+ // address spaces
+ const address_space_config m_program_config;
+
+ enum state
+ {
+ FETCH,
+ DEFER,
+ EXECUTE,
+ WORD_COUNT,
+ CURRENT_ADDR,
+ BREAK
+ }
+
+ enum opcode
+ {
+ AND = 0,
+ TAD,
+ ISZ,
+ DCA,
+ JMS,
+ JMP,
+ IOT,
+ OPR
+ }
+private:
+ // CPU registers
+ UINT16 m_pc;
+ UINT16 m_ac;
+ UINT16 m_mb;
+ UINT16 m_ma;
+ UINT16 m_sr;
+ UINT8 m_l;
+ UINT8 m_ir;
+ bool m_halt;
+
+ // other internal states
+ int m_icount;
+
+ // address spaces
+ address_space *m_program;
+};
+
+// device type definition
+extern const device_type PDP8CPU;
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ PDP8_PC = 1,
+ PDP8_AC,
+ PDP8_MB,
+ PDP8_MA,
+ PDP8_SR,
+ PDP8_L,
+ PDP8_IR,
+ PDP8_HALT
+};
+
+CPU_DISASSEMBLE( pdp8 );
+
+#endif /* __PDP8_H__ */
diff --git a/src/emu/cpu/pdp8/pdp8dasm.c b/src/emu/cpu/pdp8/pdp8dasm.c
new file mode 100644
index 00000000000..5ed4e73ebbb
--- /dev/null
+++ b/src/emu/cpu/pdp8/pdp8dasm.c
@@ -0,0 +1,183 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ First-gen DEC PDP-8 disassembler
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+
+static char *output;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ output += vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+offs_t pdp8_dasm_one(char *buffer, offs_t pc, UINT16 op)
+{
+ UINT8 opcode = (op >> 011) & 07;
+ UINT16 current_page = pc & 07600;
+ UINT16 zero_addr = op & 0177;
+ UINT16 current_addr = current_page | zero_addr;
+ bool indirect = (op & 0400) ? true : false;
+ bool zero_page = (op & 0200) ? false : true;
+
+ output = buffer;
+
+ switch (opcode)
+ {
+ case 0:
+ output += sprintf(buffer, "AND %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 1:
+ output += sprintf(buffer, "TAD %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 2:
+ output += sprintf(buffer, "ISZ %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 3:
+ output += sprintf(buffer, "DCA %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 4:
+ output += sprintf(buffer, "JMS %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 5:
+ output += sprintf(buffer, "JMP %c %05o", indirect ? 'I' : ' ', zero_page ? zero_addr : current_addr);
+ break;
+ case 6:
+ output += sprintf(buffer, "IOT %03o %01o", (op >> 03) & 077, op & 07);
+ break;
+ case 7:
+ {
+ bool group2 = ((op & 0401) == 0400);
+ if (!group2)
+ {
+ if (!(op & 0377))
+ {
+ output += sprintf(buffer, "NOP ");
+ }
+ else
+ {
+ if (op & 0200)
+ {
+ output += sprintf(buffer, "CLA ");
+ }
+ if (op & 0100)
+ {
+ output += sprintf(buffer, "CLL ");
+ }
+ if (op & 040)
+ {
+ output += sprintf(buffer, "CMA ");
+ }
+ if (op & 020)
+ {
+ output += sprintf(buffer, "CML ");
+ }
+ if (op & 01)
+ {
+ output += sprintf(buffer, "IAC ");
+ }
+ if (op & 010)
+ {
+ if (op & 02)
+ {
+ output += sprintf(buffer, "RTR ");
+ }
+ else
+ {
+ output += sprintf(buffer, "RAR ");
+ }
+ }
+ if (op & 04)
+ {
+ if (op & 02)
+ {
+ output += sprintf(buffer, "RTL ");
+ }
+ else
+ {
+ output += sprintf(buffer, "RAL ");
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!(op & 0377))
+ {
+ output += sprintf(buffer, "NOP ");
+ }
+ else
+ {
+ if (op & 010)
+ {
+ if (!(op & 0160))
+ {
+ output += sprintf(buffer, "SKP ");
+ }
+ else
+ {
+ if (op & 0100)
+ {
+ output += sprintf(buffer, "SPA ");
+ }
+ if (op & 040)
+ {
+ output += sprintf(buffer, "SNA ");
+ }
+ if (op & 020)
+ {
+ output += sprintf(buffer, "SZL ");
+ }
+ }
+ }
+ else
+ {
+ if (op & 0100)
+ {
+ output += sprintf(buffer, "SMA ");
+ }
+ if (op & 040)
+ {
+ output += sprintf(buffer, "SZA ");
+ }
+ if (op & 020)
+ {
+ output += sprintf(buffer, "SNL ");
+ }
+ }
+ if (op & 0200)
+ {
+ output += sprintf(buffer, "CLA ");
+ }
+ if (op & 04)
+ {
+ output += sprintf(buffer, "OSR ");
+ }
+ if (op & 02)
+ {
+ output += sprintf(buffer, "HLT ");
+ }
+ }
+ }
+ }
+ }
+
+ return 2 | DASMFLAG_SUPPORTED;
+}
+
+/*****************************************************************************/
+
+CPU_DISASSEMBLE( pdp8 )
+{
+ UINT16 op = (*(UINT8 *)(opram + 0) << 8) |
+ (*(UINT8 *)(opram + 1) << 0);
+ return pdp8_dasm_one(buffer, pc, op);
+}