summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/pdp1/pdp1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/pdp1/pdp1.cpp')
-rw-r--r--src/devices/cpu/pdp1/pdp1.cpp178
1 files changed, 58 insertions, 120 deletions
diff --git a/src/devices/cpu/pdp1/pdp1.cpp b/src/devices/cpu/pdp1/pdp1.cpp
index a8704ad29d3..efd93747fc7 100644
--- a/src/devices/cpu/pdp1/pdp1.cpp
+++ b/src/devices/cpu/pdp1/pdp1.cpp
@@ -6,7 +6,7 @@
* Barry Silverman mailto:barry@disus.com or mailto:bss@media.mit.edu
* Vadim Gerasimov mailto:vadim@media.mit.edu
*
- * MESS driver by Chris Salomon and Raphael Nabet.
+ * MAME driver by Chris Salomon and Raphael Nabet.
*
* Basically, it has been rewritten entirely in order to perform cycle-level simulation
* (with only a few flip-flops being set one cycle too early or too late). I don't know if
@@ -340,16 +340,16 @@
#include "emu.h"
-#include "debugger.h"
#include "pdp1.h"
#include "pdp1dasm.h"
-#define LOG 0
-#define LOG_EXTRA 0
-#define LOG_IOT_EXTRA 0
+#define LOG_EXTRA (1U << 1)
+#define LOG_IOT_EXTRA (1U << 2)
+#define VERBOSE (0)
+#include "logmacro.h"
-#define READ_PDP_18BIT(A) ((signed)m_program->read_dword((A)<<2))
-#define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A)<<2,(V)))
+#define READ_PDP_18BIT(A) ((signed)m_program->read_dword(A))
+#define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A),(V)))
#define PC m_pc
@@ -378,12 +378,16 @@
#define PREVIOUS_PC ((PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
-DEFINE_DEVICE_TYPE(PDP1, pdp1_device, "pdp1_cpu", "DEC PDP1")
+DEFINE_DEVICE_TYPE(PDP1, pdp1_device, "pdp1_cpu", "DEC PDP-1 Central Processor")
pdp1_device::pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, PDP1, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_BIG, 32, 18, 0)
+ , m_program_config("program", ENDIANNESS_BIG, 32, 18, -2) // data is actually 18 bits wide
+ , m_extern_iot(*this)
+ , m_io_sc_callback(*this)
+ , m_program(nullptr)
+ , m_reset_param(nullptr)
{
m_program_config.m_is_octal = true;
}
@@ -405,16 +409,9 @@ void pdp1_device::device_config_complete()
// or initialize to defaults if none provided
else
{
- memset(&read_binary_word, 0, sizeof(read_binary_word));
- memset(&io_sc_callback, 0, sizeof(io_sc_callback));
extend_support = 0;
hw_mul_div = 0;
type_20_sbs = 0;
-
- for (auto & elem : extern_iot)
- {
- memset(&elem, 0, sizeof(elem));
- }
}
}
@@ -495,34 +492,6 @@ void pdp1_device::execute_set_input(int irqline, int state)
}
-static void null_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
-{
- pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
-
- pdp1->pdp1_null_iot(op2, nac, mb, io, ac);
-}
-
-static void lem_eem_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
-{
- pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
-
- pdp1->pdp1_lem_eem_iot(op2, nac, mb, io, ac);
-}
-
-static void sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
-{
- pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
-
- pdp1->pdp1_sbs_iot(op2, nac, mb, io, ac);
-}
-
-static void type_20_sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
-{
- pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
-
- pdp1->pdp1_type_20_sbs_iot(op2, nac, mb, io, ac);
-}
-
void pdp1_device::device_start()
{
int i;
@@ -569,12 +538,11 @@ void pdp1_device::device_start()
/* set up params and callbacks */
for (i=0; i<64; i++)
{
- m_extern_iot[i] = (extern_iot[i])
- ? extern_iot[i]
- : null_iot;
+ m_extern_iot[i].resolve();
+ if (m_extern_iot[i].isnull())
+ m_extern_iot[i] = iot_delegate(*this, FUNC(pdp1_device::null_iot));
}
- m_read_binary_word = read_binary_word;
- m_io_sc_callback = io_sc_callback;
+ m_io_sc_callback.resolve();
m_extend_support = extend_support;
m_hw_mul_div = hw_mul_div;
m_type_20_sbs = type_20_sbs;
@@ -583,6 +551,7 @@ void pdp1_device::device_start()
{
default:
m_extend_support = 0;
+ [[fallthrough]];
case 0: /* no extension */
m_extended_address_mask = 07777;
m_address_extension_mask = 00000;
@@ -599,13 +568,13 @@ void pdp1_device::device_start()
if (m_extend_support)
{
- m_extern_iot[074] = lem_eem_iot;
+ m_extern_iot[074] = iot_delegate(*this, FUNC(pdp1_device::lem_eem_iot));
}
- m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = sbs_iot;
+ m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = iot_delegate(*this, FUNC(pdp1_device::sbs_iot));
if (m_type_20_sbs)
{
m_extern_iot[050] = m_extern_iot[051] = m_extern_iot[052] = m_extern_iot[053]
- = type_20_sbs_iot;
+ = iot_delegate(*this, FUNC(pdp1_device::type_20_sbs_iot));
}
state_add( PDP1_PC, "PC", m_pc).formatstr("%06O");
@@ -796,9 +765,6 @@ void pdp1_device::execute_run()
{
do
{
- debugger_instruction_hook(PC);
-
-
/* ioh should be cleared at the end of the instruction cycle, and ios at the
start of next instruction cycle, but who cares? */
if (m_ioh && m_ios)
@@ -808,15 +774,19 @@ void pdp1_device::execute_run()
if ((! m_run) && (! m_rim))
+ {
+ debugger_wait_hook();
m_icount = 0; /* if processor is stopped, just burn cycles */
+ }
else if (m_rim)
{
switch (m_rim_step)
{
case 0:
/* read first word as instruction */
- if (m_read_binary_word)
- (*m_read_binary_word)(this); /* data will be transferred to IO register */
+ MB = 0;
+ /* data will be transferred to IO register in response to RPB */
+ m_extern_iot[2](2, 1, MB, IO, AC);
m_rim_step = 1;
m_ios = 0;
break;
@@ -849,8 +819,7 @@ void pdp1_device::execute_run()
else
{
/* what the heck? */
- if (LOG)
- logerror("It seems this tape should not be operated in read-in mode\n");
+ LOG("It seems this tape should not be operated in read-in mode\n");
m_rim = 0; /* exit read-in mode (right???) */
m_rim_step = 0;
@@ -860,8 +829,8 @@ void pdp1_device::execute_run()
case 2:
/* read second word as data */
- if (m_read_binary_word)
- (*m_read_binary_word)(this); /* data will be transferred to IO register */
+ /* data will be transferred to IO register in response to RPB */
+ m_extern_iot[2](2, 1, MB, IO, AC);
m_rim_step = 3;
m_ios = 0;
break;
@@ -940,6 +909,7 @@ void pdp1_device::execute_run()
if (! m_cycle)
{ /* no instruction in progress: time to fetch a new instruction, I guess */
+ debugger_instruction_hook(PC);
MB = READ_PDP_18BIT(MA = PC);
INCREMENT_PC;
IR = MB >> 13; /* basic opcode */
@@ -1504,8 +1474,7 @@ void pdp1_device::execute_instruction()
}
break;
default:
- if (LOG)
- logerror("Undefined shift: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
+ LOG("Undefined shift: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
break;
}
break;
@@ -1564,7 +1533,7 @@ void pdp1_device::execute_instruction()
{ /* IOT with IO wait */
if (m_ioc)
{ /* the iot command line is pulsed only if ioc is asserted */
- (*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) == 0, MB, &IO, AC);
+ m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) == 0, MB, IO, AC);
m_ioh = 1; /* enable io wait */
@@ -1587,7 +1556,7 @@ void pdp1_device::execute_instruction()
}
else
{ /* IOT with no IO wait */
- (*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) != 0, MB, &IO, AC);
+ m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) != 0, MB, IO, AC);
}
break;
case OPR: /* Operate Instruction Group */
@@ -1614,16 +1583,14 @@ void pdp1_device::execute_instruction()
AC ^= 0777777;
if (MB & 00400) /* Halt */
{
- if (LOG_EXTRA)
- logerror("PDP1 Program executed HALT: at 0%06o\n", PREVIOUS_PC);
+ LOGMASKED(LOG_EXTRA, "PDP1 Program executed HALT: at 0%06o\n", PREVIOUS_PC);
m_run = 0;
}
break;
}
default:
- if (LOG)
- logerror("Illegal instruction: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
+ LOG("Illegal instruction: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
/* let us stop the CPU, like a real pdp-1 */
m_run = 0;
@@ -1639,20 +1606,14 @@ no_fetch:
/*
Handle unimplemented IOT
*/
-void pdp1_device::pdp1_null_iot(int op2, int nac, int mb, int *io, int ac)
+void pdp1_device::null_iot(int op2, int nac, int mb, int &io, int ac)
{
/* Note that the dummy IOT 0 is used to wait for the completion pulse
generated by the a pending IOT (IOT with completion pulse but no IO wait) */
- if (LOG_IOT_EXTRA)
- {
- if (op2 == 000)
- logerror("IOT sync instruction: mb=0%06o, pc=0%06o\n", (unsigned) mb, (unsigned) m_pc);
- }
- if (LOG)
- {
- if (op2 != 000)
- logerror("Not supported IOT command (no external IOT function given) 0%06o at 0%06o\n", mb, m_pc);
- }
+ if (op2 == 000)
+ LOGMASKED(LOG_IOT_EXTRA, "IOT sync instruction: mb=0%06o, pc=0%06o\n", (unsigned) mb, (unsigned) m_pc);
+ if (op2 != 000)
+ LOG("Not supported IOT command (no external IOT function given) 0%06o at 0%06o\n", mb, m_pc);
}
@@ -1661,18 +1622,14 @@ void pdp1_device::pdp1_null_iot(int op2, int nac, int mb, int *io, int ac)
IOT 74: LEM/EEM
*/
-void pdp1_device::pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac)
+void pdp1_device::lem_eem_iot(int op2, int nac, int mb, int &io, int ac)
{
if (! m_extend_support) /* extend mode supported? */
{
- if (LOG)
- logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+ LOG("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
return;
}
- if (LOG_EXTRA)
- {
- logerror("EEM/LEM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
- }
+ LOGMASKED(LOG_EXTRA, "EEM/LEM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
EXD = (mb & 0004000) ? 1 : 0;
}
@@ -1684,36 +1641,28 @@ void pdp1_device::pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac)
IOT 55: esm
IOT 56: cbs
*/
-void pdp1_device::pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac)
+void pdp1_device::sbs_iot(int op2, int nac, int mb, int &io, int ac)
{
switch (op2)
{
case 054: /* LSM */
- if (LOG_EXTRA)
- logerror("LSM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "LSM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_sbm = 0;
field_interrupt();
break;
case 055: /* ESM */
- if (LOG_EXTRA)
- logerror("ESM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "ESM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_sbm = 1;
field_interrupt();
break;
case 056: /* CBS */
- if (LOG_EXTRA)
- logerror("CBS instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "CBS instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
/*m_b3 = 0;*/
m_b4 = 0;
field_interrupt();
break;
default:
- if (LOG)
- logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
-
+ LOG("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
break;
}
}
@@ -1727,13 +1676,12 @@ void pdp1_device::pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac)
IOT 52: isb
IOT 53: cac
*/
-void pdp1_device::pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac)
+void pdp1_device::type_20_sbs_iot(int op2, int nac, int mb, int &io, int ac)
{
int channel, mask;
if (! m_type_20_sbs) /* type 20 sequence break system supported? */
{
- if (LOG)
- logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+ LOG("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
return;
}
channel = (mb >> 6) & 017;
@@ -1741,37 +1689,27 @@ void pdp1_device::pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac
switch (op2)
{
case 050: /* DSC */
- if (LOG_EXTRA)
- logerror("DSC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "DSC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_b1 &= ~mask;
field_interrupt();
break;
case 051: /* ASC */
- if (LOG_EXTRA)
- logerror("ASC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "ASC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_b1 |= mask;
field_interrupt();
break;
case 052: /* ISB */
- if (LOG_EXTRA)
- logerror("ISB instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "ISB instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_b2 |= mask;
field_interrupt();
break;
case 053: /* CAC */
- if (LOG_EXTRA)
- logerror("CAC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
-
+ LOGMASKED(LOG_EXTRA, "CAC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
m_b1 = 0;
field_interrupt();
break;
default:
- if (LOG)
- logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
-
+ LOG("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
break;
}
@@ -1820,6 +1758,6 @@ void pdp1_device::pulse_start_clear()
field_interrupt();
/* now, we kindly ask IO devices to reset, too */
- if (m_io_sc_callback)
- (*m_io_sc_callback)(this);
+ if (!m_io_sc_callback.isnull())
+ m_io_sc_callback();
}