summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua17
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/cpu/bcp/bcpdasm.cpp475
-rw-r--r--src/devices/cpu/bcp/bcpdasm.h36
-rw-r--r--src/devices/cpu/bcp/dp8344.cpp1290
-rw-r--r--src/devices/cpu/bcp/dp8344.h187
-rw-r--r--src/emu/xtal.cpp1
-rw-r--r--src/mame/drivers/is48x.cpp42
-rw-r--r--src/tools/unidasm.cpp2
10 files changed, 2049 insertions, 3 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 9a491f9f198..3a6b9792787 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -2897,3 +2897,20 @@ if (CPUS["RII"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/rii/riidasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/rii/riidasm.h")
end
+
+--------------------------------------------------
+-- National Semiconductor BCP
+--@src/devices/cpu/bcp/dp8344.h,CPUS["BCP"] = true
+--------------------------------------------------
+
+if (CPUS["BCP"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/cpu/bcp/dp8344.cpp",
+ MAME_DIR .. "src/devices/cpu/bcp/dp8344.h",
+ }
+end
+
+if (CPUS["BCP"]~=null or _OPTIONS["with-tools"]) then
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/bcp/bcpdasm.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/bcp/bcpdasm.h")
+end
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 2f675097397..02f3b0da184 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -135,6 +135,7 @@ CPUS["ST62XX"] = true
CPUS["DSPP"] = true
CPUS["HPC"] = true
--CPUS["RII"] = true
+--CPUS["BCP"] = true
--------------------------------------------------
-- specify available sound cores
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 4a4b969099a..4c20becd143 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -143,6 +143,7 @@ CPUS["HPC"] = true
CPUS["MEG"] = true
CPUS["DSPV"] = true
CPUS["RII"] = true
+CPUS["BCP"] = true
--------------------------------------------------
-- specify available sound cores; some of these are
diff --git a/src/devices/cpu/bcp/bcpdasm.cpp b/src/devices/cpu/bcp/bcpdasm.cpp
new file mode 100644
index 00000000000..fbecb015f70
--- /dev/null
+++ b/src/devices/cpu/bcp/bcpdasm.cpp
@@ -0,0 +1,475 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor DP8344 BCP disassembler
+
+***************************************************************************/
+
+#include "util/disasmintf.h"
+#include "bcpdasm.h"
+
+#include "util/strformat.h"
+
+using osd::u32;
+using util::BIT;
+using offs_t = u32;
+
+
+//**************************************************************************
+// BCP DISASSEMBLER
+//**************************************************************************
+
+dp8344_disassembler::dp8344_disassembler()
+ : util::disasm_interface()
+{
+}
+
+u32 dp8344_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+const char *dp8344_disassembler::cc_to_string(u8 f, bool s) const
+{
+ // f = 0, s = 1: Zero or EQual
+ // f = 0, s = 0: Not Zero or Not EQual
+ // f = 1, s = 1: Carry
+ // f = 1, s = 0: No Carry
+ // f = 2, s = 1: Overflow
+ // f = 2, s = 0: No Overflow
+ // f = 3, s = 1: Negative
+ // f = 3, s = 0: Positive
+ // f = 4, s = 1: Receiver Active
+ // f = 4, s = 0: Not Receiver Active
+ // f = 5, s = 1: Receiver Error
+ // f = 5, s = 0: No Receiver Error
+ // f = 6, s = 1: Data Available
+ // f = 6, s = 0: No Data Available
+ // f = 7, s = 1: Transmitter FIFO Full
+ // f = 7, s = 0: Transmitter FIFO Not Full
+
+ return std::array<const char *, 16> {
+ "nz", "nc", "nv", "p", "nra", "nre", "ndav", "ntss",
+ "z", "c", "v", "n", "ra", "re", "dav", "tss"
+ }[f | (s ? 8 : 0)];
+}
+
+const char *dp8344_disassembler::aop_to_string(u8 o) const
+{
+ return std::array<const char *, 8> {
+ "adda", "adca", "suba", "sbca", "anda", "ora", "xora", "move"
+ }[o];
+}
+
+void dp8344_disassembler::format_number(std::ostream &stream, u8 n) const
+{
+ if (n >= 0xa0)
+ stream << "0";
+ util::stream_format(stream, "%02Xh", n);
+}
+
+void dp8344_disassembler::format_address(std::ostream &stream, u16 nn) const
+{
+ if (nn >= 0xa000)
+ stream << "0";
+ util::stream_format(stream, "%04Xh", nn);
+}
+
+void dp8344_disassembler::format_register(std::ostream &stream, u8 r) const
+{
+ stream << std::array<const char *, 32> {
+ "CCR/DCR", "NCF/IBR", "ICR/ATR", "ACR/FBR",
+ "GP0/RTR", "GP1/TSR", "GP2/TCR", "GP3/TMR",
+ "GP4/GP4'", "GP5/GP5'", "GP6/GP6'", "GP7/GP7'",
+ "IWLO", "IWHI", "IXLO", "IXHI",
+ "IYLO", "IYHI", "IZLO", "IZHI",
+ "GP8", "GP9", "GP10", "GP11",
+ "GP12", "GP13", "GP14", "GP15",
+ "TRL", "TRH", "ISP", "DS"
+ }[r];
+}
+
+void dp8344_disassembler::format_modified_index_register(std::ostream &stream, u8 ir, u8 m) const
+{
+ if (m == 3)
+ stream << "+";
+ util::stream_format(stream, "I%c", 'W' + ir);
+ if (m == 0)
+ stream << "-";
+ else if (m == 2)
+ stream << "+";
+}
+
+void dp8344_disassembler::format_interrupt_vector(std::ostream &stream, u8 v) const
+{
+ switch (v)
+ {
+ case 0x1c:
+ stream << "NMI";
+ break;
+
+ case 0x04:
+ stream << "RFF/DA/RA";
+ break;
+
+ case 0x08:
+ stream << "TFE";
+ break;
+
+ case 0x0c:
+ stream << "LTE";
+ break;
+
+ case 0x10:
+ stream << "BIRQ";
+ break;
+
+ case 0x14:
+ stream << "TO";
+ break;
+
+ default:
+ format_number(stream, v);
+ break;
+ }
+}
+
+offs_t dp8344_disassembler::disassemble(std::ostream &stream, offs_t pc, const dp8344_disassembler::data_buffer &opcodes, const dp8344_disassembler::data_buffer &params)
+{
+ u16 inst = opcodes.r16(pc);
+ offs_t words = 1;
+
+ switch (inst & 0xf000)
+ {
+ case 0x0000:
+ // 0000-0FFF: ADD n,rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "add");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0x1000:
+ // 1000-1FFF: MOVE rs,[IZ+n] (3 T-states)
+ util::stream_format(stream, "%-8s", "move");
+ format_register(stream, inst & 0x000f);
+ stream << ",[IZ+";
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << "]";
+ break;
+
+ case 0x2000:
+ // 2000-2FFF: SUB n,rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "sub");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0x3000:
+ // 3000-3FFF: CMP rs,n (2 T-states)
+ util::stream_format(stream, "%-8s", "cmp");
+ format_register(stream, inst & 0x000f);
+ stream << ",";
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ break;
+
+ case 0x4000:
+ // 4000-4FFF: AND n,rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "and");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0x5000:
+ // 5000-5FFF: OR n,rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "or");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0x6000:
+ // 6000-6FFF: XOR n,rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "xor");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0x7000:
+ // 7000-7FFF: BIT rs,n (2 T-states)
+ util::stream_format(stream, "%-8s", "bit");
+ format_register(stream, inst & 0x000f);
+ stream << ",";
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ break;
+
+ case 0x8000:
+ if (!BIT(inst, 11))
+ {
+ // 8000-87FF: JRMK Rs,b,m (4 T-states)
+ util::stream_format(stream, "%-8s", "jrmk");
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",%d,%d", (inst & 0x00e0) >> 5, (inst & 0x0700) >> 8);
+ }
+ else if (!BIT(inst, 10))
+ {
+ // 8800-8BFF: MOVE n,[Ir] (3 T-states)
+ util::stream_format(stream, "%-8s", "move");
+ format_number(stream, (inst & 0x0380) >> 2 | (inst & 0x001f));
+ util::stream_format(stream, ",[I%c]", 'W' + ((inst & 0x0060) >> 5));
+ }
+ else
+ {
+ words = 2;
+ if (!BIT(inst, 9))
+ {
+ // 8C00-8DFF, 0000-FFFF: LJMP Rs,p,s,nn (2 + 2 T-states)
+ util::stream_format(stream, "%-8s", "ljmp");
+ }
+ else
+ {
+ // 8E00-8FFF, 0000-FFFF: LCALL Rs,p,s,nn (2 + 2 T-states)
+ util::stream_format(stream, "%-8s", "lcall");
+ words |= STEP_OVER;
+ }
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",%d,%d,", (inst & 0x00e0) >> 5, BIT(inst, 8));
+ format_address(stream, opcodes.r16(pc + 1));
+ }
+ break;
+
+ case 0x9000:
+ // 9000-9FFF: MOVE [IZ+n],rd (3 T-states)
+ util::stream_format(stream, "%-8s[IZ+", "move");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << "],";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0xa000:
+ {
+ if (inst < 0xae00)
+ {
+ // A000-A1FF: ADDA Rs,[mIr] (3 T-states)
+ // A200-A3FF: ADCA Rs,[mIr] (3 T-states)
+ // A400-A5FF: SUBA Rs,[mIr] (3 T-states)
+ // A600-A7FF: SBCA Rs,[mIr] (3 T-states)
+ // A800-A9FF: ANDA Rs,[mIr] (3 T-states)
+ // AA00-ABFF: ORA Rs,[mIr] (3 T-states)
+ // AC00-ADFF: XORA Rs,[mIr] (3 T-states)
+ util::stream_format(stream, "%-8s", aop_to_string((inst & 0x0e00) >> 9));
+ format_register(stream, inst & 0x001f);
+ stream << ",";
+ format_modified_index_register(stream, (inst & 0x0060) >> 5, (inst & 0x0180) >> 7);
+ }
+ else if (!BIT(inst, 8))
+ {
+ if (!BIT(inst, 7))
+ {
+ // AE00-AE1F: CPL Rsd (2 T-states)
+ util::stream_format(stream, "%-8s", "cpl");
+ format_register(stream, inst & 0x001f);
+ }
+ else
+ {
+ // AE80-AEF8: EXX ba,bb{,g} (2 T-states)
+ util::stream_format(stream, "%-8s%cA,%cB", "exx", BIT(inst, 4) ? 'A' : 'M', BIT(inst, 3) ? 'A' : 'M');
+ switch (inst & 0x0060)
+ {
+ case 0x0000: // NCHG
+ break;
+
+ case 0x0020:
+ stream << ",RI";
+ break;
+
+ case 0x0040:
+ stream << ",EI";
+ break;
+
+ case 0x0060:
+ stream << ",DI";
+ break;
+ }
+ }
+ }
+ else
+ {
+ // AF00-A7FF: RETF f,s{,{g}{,rf}} (2 or 3 T-states)
+ // AF80-AFF0: RET {g{,rf}} (2 T-states)
+ if (!BIT(inst, 7))
+ util::stream_format(stream, (inst & 0x0070) == 0 ? "r%s" : "r%-7s", cc_to_string(inst & 0x0007, BIT(inst, 3)));
+ else
+ util::stream_format(stream, (inst & 0x0070) == 0 ? "%s" : "%-8s", "ret");
+
+ switch (inst & 0x0060)
+ {
+ case 0x0000:
+ if (BIT(inst, 4))
+ stream << "NCHG";
+ break;
+
+ case 0x0020:
+ stream << "RI";
+ break;
+
+ case 0x0040:
+ stream << "EI";
+ break;
+
+ case 0x0060:
+ stream << "DI";
+ break;
+ }
+ if (BIT(inst, 4))
+ stream << ",RF";
+
+ words |= STEP_OUT;
+ }
+ break;
+ }
+
+ case 0xb000:
+ // B000-BFFF: MOVE n,rd (2 T-states)
+ util::stream_format(stream, "%-8s", "move");
+ format_number(stream, (inst & 0x0ff0) >> 4);
+ stream << ",";
+ format_register(stream, inst & 0x000f);
+ break;
+
+ case 0xc000:
+ switch (inst & 0xf80)
+ {
+ case 0x000: case 0x080: case 0x100: case 0x180:
+ // C000-C1FF: MOVE [mIr],Rd (3 T-states)
+ util::stream_format(stream, "%-8s[", "move");
+ format_modified_index_register(stream, (inst & 0x0060) >> 5, (inst & 0x0180) >> 7);
+ stream << "],";
+ format_register(stream, inst & 0x001f);
+ break;
+
+ case 0x200: case 0x280: case 0x300: case 0x380:
+ // C200-C3FF: MOVE Rs,[mIr] (3 T-states)
+ util::stream_format(stream, "%-8s", "move");
+ format_register(stream, inst & 0x001f);
+ stream << ",[";
+ format_modified_index_register(stream, (inst & 0x0060) >> 5, (inst & 0x0180) >> 7);
+ stream << "]";
+ break;
+
+ case 0x400:
+ // C400-C47F: MOVE [Ir+A],Rd (3 T-states)
+ util::stream_format(stream, "%-8s[I%c+A],", "move", 'W' + ((inst & 0x0060) >> 5));
+ format_register(stream, inst & 0x001f);
+ break;
+
+ case 0x480:
+ // C480-C4FF: MOVE Rs,[Ir+A] (3 T-states)
+ util::stream_format(stream, "%-8s", "move");
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",[I%c+A]", 'W' + ((inst & 0x0060) >> 5));
+ break;
+
+ case 0x800: case 0x880:
+ // C800-C8FF: SHR Rsd,b (2 T-states)
+ util::stream_format(stream, "%-8s", "shr");
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",%d", (inst & 0x00e0) >> 5);
+ break;
+
+ case 0x900: case 0x980:
+ // C900-C9FF: SHL Rsd,b (2 T-states)
+ util::stream_format(stream, "%-8s", "shl");
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",%d", (inst & 0x00e0) >> 5);
+ break;
+
+ case 0xa00: case 0xa80:
+ // CA00-CAFF: ROT Rsd,b (2 T-states)
+ util::stream_format(stream, "%-8s", "rot");
+ format_register(stream, inst & 0x001f);
+ util::stream_format(stream, ",%d", (inst & 0x00e0) >> 5);
+ break;
+
+ case 0xb00: case 0xb80:
+ // CB00-CBFF: JMP n (3 T-states)
+ util::stream_format(stream, "%-8s", "jmp");
+ format_address(stream, pc + 1 + s8(inst & 0x00ff));
+ break;
+
+ case 0xc00: case 0xc80:
+ // CC00-CCFF: CALL n (3 T-states)
+ util::stream_format(stream, "%-8s", "call");
+ format_address(stream, pc + 1 + s8(inst & 0x00ff));
+ words |= STEP_OVER;
+ break;
+
+ case 0xd00:
+ // CD00-DC60: LJMP [Ir] (2 T-states)
+ util::stream_format(stream, "%-8s[I%c]", "ljmp", 'W' + ((inst & 0x0060) >> 5));
+ break;
+
+ case 0xd80:
+ // CD80-CD9F: JMP Rs (4 T-states)
+ util::stream_format(stream, "%-8s", "jmp");
+ format_register(stream, inst & 0x001f);
+ break;
+
+ case 0xe00:
+ // CE00: LJMP nn (2 + 2 T-states)
+ util::stream_format(stream, "%-8s", "ljmp");
+ format_address(stream, opcodes.r16(pc + 1));
+ words = 2;
+ break;
+
+ case 0xe80:
+ // CE80: LCALL nn (2 + 2 T-states)
+ util::stream_format(stream, "%-8s", "lcall");
+ format_address(stream, opcodes.r16(pc + 1));
+ words = 2 | STEP_OVER;
+ break;
+
+ case 0xf80:
+ // CF80-CFFF: TRAP v{,g'} (2 T-states)
+ util::stream_format(stream, "%-8s", "trap");
+ format_interrupt_vector(stream, inst & 0x003f);
+ if (BIT(inst, 6))
+ stream << ",DI";
+ words |= STEP_OVER;
+ break;
+
+ default:
+ // invalid
+ stream << "???";
+ break;
+ }
+ break;
+
+ case 0xd000:
+ // D000-DFFF: JMP f,s,n (2 or 3 T-states)
+ util::stream_format(stream, "j%-7s", cc_to_string((inst & 0x0700) >> 8, BIT(inst, 11)));
+ format_address(stream, pc + 1 + s8(inst & 0x00ff));
+ break;
+
+ case 0xe000: case 0xf000:
+ // E000-E3FF: ADDA Rs,Rd (2 T-states)
+ // E400-E7FF: ADCA Rs,Rd (2 T-states)
+ // E800-EBFF: SUBA Rs,Rd (2 T-states)
+ // EC00-EFFF: SBCA Rs,Rd (2 T-states)
+ // F000-F3FF: ANDA Rs,Rd (2 T-states)
+ // F400-F7FF: ORA Rs,Rd (2 T-states)
+ // F800-FBFF: XORA Rs,Rd (2 T-states)
+ // FC00-FFFF: MOVE Rs,Rd (2 T-states)
+ util::stream_format(stream, "%-8s", aop_to_string((inst & 0x0e00) >> 9));
+ format_register(stream, inst & 0x001f);
+ stream << ",";
+ format_register(stream, (inst & 0x03e0) >> 5);
+ break;
+ }
+
+ return words | SUPPORTED;
+}
diff --git a/src/devices/cpu/bcp/bcpdasm.h b/src/devices/cpu/bcp/bcpdasm.h
new file mode 100644
index 00000000000..f544564221e
--- /dev/null
+++ b/src/devices/cpu/bcp/bcpdasm.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor DP8344 BCP disassembler
+
+***************************************************************************/
+
+#ifndef MAME_CPU_BCP_BCPDASM_H
+#define MAME_CPU_BCP_BCPDASM_H 1
+
+#pragma once
+
+class dp8344_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ dp8344_disassembler();
+
+protected:
+ // disassembler overrides
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+private:
+ // internal helpers
+ const char *cc_to_string(u8 f, bool s) const;
+ const char *aop_to_string(u8 o) const;
+ void format_number(std::ostream &stream, u8 n) const;
+ void format_address(std::ostream &stream, u16 nn) const;
+ void format_register(std::ostream &stream, u8 r) const;
+ void format_modified_index_register(std::ostream &stream, u8 ir, u8 m) const;
+ void format_interrupt_vector(std::ostream &stream, u8 v) const;
+};
+
+#endif // MAME_CPU_BCP_BCPDASM_H
diff --git a/src/devices/cpu/bcp/dp8344.cpp b/src/devices/cpu/bcp/dp8344.cpp
new file mode 100644
index 00000000000..6130b5d8a2b
--- /dev/null
+++ b/src/devices/cpu/bcp/dp8344.cpp
@@ -0,0 +1,1290 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ National Semiconductor DP8344 Biphase Communications Processor
+
+ The BCP employs a true Harvard architecture, with entirely
+ separate 64k address spaces for instruction words and data bytes
+ (the data bus is address-latched). Wait states can be internally
+ configured and/or externally requested. The sophisticated Remote
+ Interface and Arbitration System (RIAS) allows for remote access
+ to both data and instruction memory.
+
+ Though instruction words are 16 bits wide, the ALU is only 8-bit.
+ Since there are no instructions that perform 16-bit data transfers
+ (not even in immediate mode), the 16-bit index registers must be
+ loaded 8 bits at a time. The RIAS interface is also 8-bit.
+
+ Assuming no wait states are involved, all instructions accessing
+ data memory take 3 T-states. All other instructions use 2 T-states
+ per instruction word except for JRMK, which takes two additional
+ T-states to calculate the jump destination.
+
+ Data can be popped from and pushed to the internal 16-byte LIFO
+ data stack by reading and writing the special Data Stack register
+ (R31). The entries in the internal 12-word address stack are not
+ addressable by the BCP, though its pointer can be manipulated.
+
+ The 44 internal registers are mapped to 32 directly addressable
+ locations (some instructions are limited to the first 16). One
+ flag switches R0-R3 between Main Bank A (CCR, NCF, ICR, ACR) and
+ Alternate Bank A, and another flag switches R4-R11, including
+ accumulator R8, between Main Bank B (GP0-GP7) and Alternate Bank
+ B (RTR, TSR, TCR, TMR, GP4'-GP7'). These two flags must be set
+ together by the EXX function, and while they cannot be read back,
+ they are saved on the address stack along with the ALU flags and
+ Global Interrupt Enable bit.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "cpu/bcp/dp8344.h"
+#include "cpu/bcp/bcpdasm.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DP8344, dp8344_device, "dp8344", "DP8344 BCP")
+
+
+//**************************************************************************
+// DEVICE CONSTRUCTION AND INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// dp8344_device - constructor
+//-------------------------------------------------
+
+dp8344_device::dp8344_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig, DP8344, tag, owner, clock)
+ , m_inst_config("instruction", ENDIANNESS_LITTLE, 16, 16, -1)
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_inst_space(nullptr)
+ , m_data_space(nullptr)
+ , m_inst_cache(nullptr)
+ , m_birq_out_cb(*this)
+ , m_data_out_cb(*this)
+ , m_data_dly_cb(*this)
+ , m_tx_act_cb(*this)
+ , m_pc(0)
+ , m_icount(0)
+ , m_nmi_pending(false)
+ , m_ccr(0)
+ , m_ncf(0)
+ , m_icr(0)
+ , m_acr(0)
+ , m_dcr(0)
+ , m_ibr(0)
+ , m_atr(0)
+ , m_fbr(0)
+ , m_ecr(0)
+ , m_tsr(0)
+ , m_tcr(0)
+ , m_tmr(0)
+ , m_gp_main{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ , m_gp_alt{0, 0, 0, 0}
+ , m_ir{{0}, {0}, {0}, {0}}
+ , m_tr(0)
+ , m_as{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ , m_ds{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ , m_asp(0)
+ , m_dsp(0)
+ , m_ba(false)
+ , m_bb(false)
+ , m_ric(0)
+ , m_hib(false)
+ , m_auto_start(true)
+ , m_nmi_state(false)
+ , m_rfifo{0, 0, 0}
+ , m_tfifo{0, 0, 0}
+ , m_rfifo_head(0)
+ , m_tfifo_head(0)
+{
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a vector of
+// configuration structures for memory spaces
+//-------------------------------------------------
+
+device_memory_interface::space_config_vector dp8344_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_inst_config),
+ std::make_pair(AS_DATA, &m_data_config)
+ };
+}
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void dp8344_device::device_resolve_objects()
+{
+ // resolve output callbacks
+ m_birq_out_cb.resolve_safe();
+ m_data_out_cb.resolve_safe();
+ m_data_dly_cb.resolve_safe();
+ m_tx_act_cb.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dp8344_device::device_start()
+{
+ // get memory spaces
+ m_inst_space = &space(AS_PROGRAM);
+ m_data_space = &space(AS_DATA);
+ m_inst_cache = m_inst_space->cache<1, -1, ENDIANNESS_LITTLE>();
+
+ set_icountptr(m_icount);
+
+ // debug state registration
+ state_add(BCP_PC, "PC", m_pc);
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_pc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_ccr).noshow();
+ state_add(BCP_CCR, "CCR", m_ccr);
+ state_add(BCP_NCF, "NCF", m_ncf);
+ state_add(BCP_ICR, "ICR", m_icr);
+ state_add(BCP_ACR, "ACR", m_acr);
+ state_add(BCP_DCR, "DCR", m_dcr);
+ state_add(BCP_IBR, "IBR", m_ibr);
+ state_add(BCP_ATR, "ATR", m_atr);
+ state_add(BCP_FBR, "FBR", m_fbr);
+ for (int i = 0; i < 8; i++)
+ state_add(BCP_GP0 + i, string_format("GP%d", i).c_str(), m_gp_main[i]);
+ state_add(BCP_ECR, "ECR", m_ecr).mask(0x1f);
+ state_add(BCP_TSR, "TSR", m_tsr);
+ state_add(BCP_TCR, "TCR", m_tcr);
+ state_add(BCP_TMR, "TMR", m_tmr);
+ for (int i = 0; i < 4; i++)
+ state_add(BCP_GP4_ALT + i, string_format("GP%da", 4 + i).c_str(), m_gp_alt[i]);
+ for (int i = 0; i < 4; i++)
+ {
+ state_add(BCP_IW + i, string_format("I%c", 'W' + i).c_str(), m_ir[i].w);
+ state_add(BCP_IWLO + i, string_format("I%cLO", 'W' + i).c_str(), m_ir[i].b.l).noshow();
+ state_add(BCP_IWHI + i, string_format("I%cHI", 'W' + i).c_str(), m_ir[i].b.h).noshow();
+ }
+ for (int i = 8; i < 16; i++)
+ state_add(BCP_GP8 + i - 8, string_format("GP%d", i).c_str(), m_gp_main[i]);
+ state_add(BCP_TR, "TR", m_tr);
+ state_add(BCP_ASP, "ASP", m_asp).mask(0xf);
+ state_add(BCP_DSP, "DSP", m_dsp).mask(0xf);
+
+ state_add(BCP_BA, "BA", m_ba);
+ state_add(BCP_BB, "BB", m_bb);
+
+ // save states
+ save_item(NAME(m_pc));
+ save_item(NAME(m_nmi_state));
+ save_item(NAME(m_ccr));
+ save_item(NAME(m_ncf));
+ save_item(NAME(m_icr));
+ save_item(NAME(m_acr));
+ save_item(NAME(m_dcr));
+ save_item(NAME(m_ibr));
+ save_item(NAME(m_atr));
+ save_item(NAME(m_fbr));
+ save_item(NAME(m_ecr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_tmr));
+ save_item(NAME(m_gp_main));
+ save_item(NAME(m_gp_alt));
+ for (int i = 0; i < 4; i++)
+ save_item(NAME(m_ir[i].w), i);
+ save_item(NAME(m_tr));
+ save_item(NAME(m_asp));
+ save_item(NAME(m_dsp));
+ save_item(NAME(m_as)); // 12-word Address Stack
+ save_item(NAME(m_ds)); // 16-byte Data Stack
+ save_item(NAME(m_ba));
+ save_item(NAME(m_bb));
+ save_item(NAME(m_ric));
+ save_item(NAME(m_hib));
+ save_item(NAME(m_nmi_pending));
+ save_item(NAME(m_rfifo)); // 3-frame Receive FIFO
+ save_item(NAME(m_tfifo)); // 3-frame Transmit FIFO
+ save_item(NAME(m_rfifo_head));
+ save_item(NAME(m_tfifo_head));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dp8344_device::device_reset()
+{
+ // Reset Program Counter
+ m_pc = 0x0000;
+
+ // Reset Condition Code Register
+ m_ccr &= 0x10;
+
+ // Reset Interrupt Control Register
+ m_icr = 0xff;
+
+ // Reset Auxiliary Control Register and timer interrupt
+ m_acr = 0x00;
+ set_timer_interrupt(false);
+
+ // Reset Device Control Register (maximum number of wait states)
+ m_dcr = 0xdf;
+
+ // Reset Interrupt Base Register
+ m_ibr = 0x00;
+
+ // Reset Transceiver Command Register (3 line quiesce pulses)
+ m_tcr = 0x80;
+
+ // Reset Transceiver Mode Register (default to 3270 protocol)
+ m_tmr = 0x00;
+
+ // Reset Address and Data Stack Pointers
+ m_asp = 0x0;
+ m_dsp = 0x0;
+
+ // Select Alternate Bank A and Alternate Bank B
+ m_ba = true;
+ m_bb = true;
+
+ // Reset Remote Interface Configuration Register
+ m_ric = m_auto_start ? 0x03 : 0x01;
+ m_hib = false;
+
+ m_nmi_pending = false;
+
+ transceiver_reset();
+
+ // Undefined on reset: ATR, FBR, TRH, TRL, data in transceiver FIFOs and stacks
+ // Also likely undefined on reset: all general-purpose registers
+}
+
+
+//**************************************************************************
+// CONTROL REGISTERS AND CONDITION CODES
+//**************************************************************************
+
+//-------------------------------------------------
+// get_flag - retrieve condition from CCR or TSR
+//-------------------------------------------------
+
+bool dp8344_device::get_flag(unsigned f) const
+{
+ switch (f)
+ {
+ case 0: // Zero/Equal
+ return BIT(m_ccr, 0);
+
+ case 1: // Carry
+ return BIT(m_ccr, 1);
+
+ case 2: // Overflow
+ return BIT(m_ccr, 2);
+
+ case 3: // Negative (or else Positive)
+ return BIT(m_ccr, 3);
+
+ case 4: // Receiver Active
+ return BIT(m_tsr, 4);
+
+ case 5: // Receiver Error
+ return BIT(m_tsr, 5);
+
+ case 6: // Data Available
+ return BIT(m_tsr, 3); // FIXME: differs from numeric value!
+
+ case 7: // Transmitter FIFO Full (or else Not Full)
+ return BIT(m_tsr, 7);
+
+ default:
+ logerror("Unknown flag %d\n", f);
+ return false;
+ }
+}
+
+
+//-------------------------------------------------
+// set_receiver_interrupt - update receiver
+// interrupt request status
+//-------------------------------------------------
+
+void dp8344_device::set_receiver_interrupt(bool state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// set_transmitter_interrupt - update transmitter
+// interrupt request status
+//-------------------------------------------------
+
+void dp8344_device::set_transmitter_interrupt(bool state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// set_line_turn_around_interrupt - update line
+// turn around interrupt request status
+//-------------------------------------------------
+
+void dp8344_device::set_line_turn_around_interrupt(bool state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// set_birq_interrupt - update internal
+// bi-directional interrupt request status
+//-------------------------------------------------
+
+void dp8344_device::set_birq_interrupt(bool state)
+{
+ if (state)
+ m_ccr |= 0x10;
+ else
+ m_ccr &= 0xef;
+}
+
+
+//-------------------------------------------------
+// set_timer_interrupt - update TO flag and timer
+// interrupt request status
+//-------------------------------------------------
+
+void dp8344_device::set_timer_interrupt(bool state)
+{
+ if (state)
+ m_ccr |= 0x80;
+ else
+ m_ccr &= 0x7f;
+}
+
+
+//-------------------------------------------------
+// set_gie - set the global interrupt enable bit
+//-------------------------------------------------
+
+void dp8344_device::set_gie(bool state)
+{
+ if (state)
+ m_acr |= 0x01;
+ else
+ m_acr &= 0xfe;
+}
+
+
+//-------------------------------------------------
+// set_condition_code - write to CCR
+//-------------------------------------------------
+
+void dp8344_device::set_condition_code(u8 data)
+{
+ // ALU flags normally writeable; TO, RR, RW cleared by writing 1s; BIRQ is read-only
+ m_ccr = (m_ccr & (~data & 0xe0)) | (m_ccr & 0x10) | (data & 0x0f);
+
+ if (BIT(data, 7))
+ set_timer_interrupt(false);
+}
+
+
+void dp8344_device::set_interrupt_control(u8 data)
+{
+ // IM0: Receiver
+ // IM1: Transmitter
+ // IM2: Line Turn-Around
+ // IM3: BIRQ
+ // IM4: Timer
+
+ if ((m_icr & 0xc0) != (data & 0xc0))
+ {
+ switch (data & 0xc0)
+ {
+ case 0x00:
+ // Interrupt on RFF + RE
+ set_receiver_interrupt(BIT(m_ncf, 6) || BIT(m_tsr, 5));
+ break;
+
+ case 0x40:
+ // Interrupt on DAV + RE
+ set_receiver_interrupt((m_tsr & 0x28) != 0);
+ break;
+
+ case 0xc0:
+ // Interrupt on RA
+ set_receiver_interrupt(BIT(m_tsr, 4));
+ break;
+
+ default:
+ set_receiver_interrupt(false);
+ break;
+ }
+ }
+
+ // Update BIRQ output
+ if (BIT(m_acr, 4) && BIT(data ^ m_icr, 3))
+ m_birq_out_cb(BIT(data, 3));
+
+ // Bit 5 is reserved
+ m_icr = data | 0x20;
+}
+
+
+//-------------------------------------------------
+// set_auxiliary_control - write to ACR
+//-------------------------------------------------
+
+void dp8344_device::set_auxiliary_control(u8 data)
+{
+ // Configure BIRQ for output when BIC is set
+ if (BIT(data, 4) && !BIT(m_acr, 4))
+ {
+ set_birq_interrupt(false);
+ m_birq_out_cb(BIT(m_icr, 3));
+ }
+
+ // Clearing Timer StarT disables the timer and its interrupt
+ if (!BIT(data, 7) && BIT(m_acr, 7))
+ set_timer_interrupt(false);
+
+ // Bit 3 is reserved
+ m_acr = data & 0xf7;
+}
+
+
+//**************************************************************************
+// 16-BIT TIMER
+//**************************************************************************
+
+//-------------------------------------------------
+// get_timer_count - return current count status
+// of the timer
+//-------------------------------------------------
+
+u16 dp8344_device::get_timer_count()
+{
+ // TODO
+ return 0;
+}
+
+
+//**************************************************************************
+// INTERNAL STACKS
+//**************************************************************************
+
+//-------------------------------------------------
+// address_stack_push - push address frame upon
+// performing a call
+//-------------------------------------------------
+
+void dp8344_device::address_stack_push()
+{
+ m_as[m_asp++] = u32(m_pc)
+ | (u32(m_ccr & 0x0f) << 16)
+ | (m_ba << 20)
+ | (m_bb << 21)
+ | (u32(m_acr & 0x01) << 22);
+ if (m_asp >= 12)
+ m_asp = 0;
+}
+
+
+//-------------------------------------------------
+// address_stack_pop - pop address frame upon
+// executing a RET or RETF instruction
+//-------------------------------------------------
+
+void dp8344_device::address_stack_pop(u8 grf)
+{
+ m_asp = (m_asp == 0) ? 11 : m_asp - 1;
+ m_pc = m_as[m_asp] & 0xffff;
+
+ // Optionally restore, set or clear GIE
+ if (BIT(grf, 6))
+ set_gie(BIT(grf, 5));
+ else if (BIT(grf, 5))
+ set_gie(BIT(m_as[m_asp], 22));
+
+ // Optionally restore ALU flags and register banks
+ if (BIT(grf, 4))
+ {
+ m_ccr = (m_ccr & 0xf0) | (m_as[m_asp] & 0xf0000) >> 20;
+ m_ba = BIT(m_as[m_asp], 20);
+ m_bb = BIT(m_as[m_asp], 21);
+ }
+}
+
+
+//-------------------------------------------------
+// set_stack_pointer - write to ISP register
+//-------------------------------------------------
+
+void dp8344_device::set_stack_pointer(u8 data)
+{
+ // TODO: one-instruction latency
+ m_asp = data >> 4;
+ m_dsp = data & 0xf;
+}
+
+
+//-------------------------------------------------
+// data_stack_push - write to DS register
+//-------------------------------------------------
+
+void dp8344_device::data_stack_push(u8 data)
+{
+ m_ds[m_dsp] = data;
+ m_dsp = (m_dsp + 1) & 0xf;
+}
+
+
+//-------------------------------------------------
+// data_stack_pop - read from DS register
+//-------------------------------------------------
+
+u8 dp8344_device::data_stack_pop()
+{
+ m_dsp = (m_dsp - 1) & 0xf;
+ return m_ds[m_dsp];
+}
+
+
+
+
+//**************************************************************************
+// TRANSCEIVER OPERATION
+//**************************************************************************
+
+//-------------------------------------------------
+// transceiver_reset - reset the receiver and
+// transmitter
+//-------------------------------------------------
+
+void dp8344_device::transceiver_reset()
+{
+ // Clear transmitter and receiver FIFOs
+ m_rfifo_head = 3;
+ m_tfifo_head = 3;
+
+ // Clear all transmitter and receiver status flags except for Transmit FIFO Empty
+ m_ncf = 0x80;
+ m_tsr &= 0x07;
+
+ // Clear Error Code Register
+ m_ecr = 0x00;
+
+ // Clear receiver and line turn around interrupts
+ set_receiver_interrupt(false);
+ set_line_turn_around_interrupt(false);
+
+ // Set transmitter interrupt (due to TFE)
+ set_transmitter_interrupt(true);
+
+ // Reset transmitter outputs
+ m_tx_act_cb(0);
+ m_data_out_cb(1);
+ m_data_dly_cb(!BIT(m_tmr, 3));
+}
+
+
+//-------------------------------------------------
+// transmit_fifo_push - write to RTR
+//-------------------------------------------------
+
+void dp8344_device::transmit_fifo_push(u8 data)
+{
+ // Push OWP, TF10-8 and RTF7-0 onto transmit FIFO
+ m_tfifo[0] = data | u16(m_tcr & 0x0f) << 8;
+
+ if (m_tfifo_head != 0)
+ {
+ // Asynchronously propagate data through FIFO (actually takes 40 ns)
+ m_tfifo_head--;
+ for (int i = 0; i < m_tfifo_head; i++)
+ m_tfifo[i + 1] = m_tfifo[i];
+
+ // Set flag when FIFO is full
+ if (m_tfifo_head == 0)
+ m_tsr |= 0x80;
+ }
+
+ // Clear Transmit FIFO Empty and Line Turn Around bits in NCF and associated interrupts
+ m_ncf &= 0x6f;
+ set_transmitter_interrupt(false);
+ set_line_turn_around_interrupt(false);
+
+ // Make sure to disable receiver before transmitting in half-duplex mode
+ if (BIT(m_tsr, 4) && !BIT(m_tmr, 5))
+ {
+ // Receiver Disabled While Active error
+ set_receiver_error(0x01);
+ }
+}
+
+
+//-------------------------------------------------
+// transmit_fifo_pop -
+//-------------------------------------------------
+
+u16 dp8344_device::transmit_fifo_pop()
+{
+ assert(m_tfifo_head < 3);
+ u16 data = m_tfifo[m_tfifo_head++];
+
+ if (m_tfifo_head == 3)
+ {
+ // Set Transmit FIFO Empty bit
+ m_ncf |= 0x80;
+ set_transmitter_interrupt(true);
+ }
+
+ // Clear FIFO full flag
+ m_tsr &= 0x7f;
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// transmitter_idle -
+//-------------------------------------------------
+
+void dp8344_device::transmitter_idle()
+{
+ // Deassert TX-ACT
+ m_tx_act_cb(0);
+
+ // Clear Transmitter Active flag
+ m_tsr &= 0xbf;
+}
+
+
+//-------------------------------------------------
+// receiver_active - update status and interrupt
+// flags after receiving a valid sync sequence
+//-------------------------------------------------
+
+void dp8344_device::receiver_active()
+{
+ m_tsr |= 0x10;
+ if ((m_icr & 0xc0) == 0xc0)
+ set_receiver_interrupt(true);
+}
+
+
+//-------------------------------------------------
+// receive_fifo_push -
+//-------------------------------------------------
+
+void dp8344_device::receive_fifo_push(u8 data)
+{
+ // Overflow error if the receive FIFO is already full
+ if (BIT(m_ncf, 6))
+ set_receiver_error(0x10);
+}
+
+
+//-------------------------------------------------
+// receive_fifo_pop - read from RTR
+//-------------------------------------------------
+
+u8 dp8344_device::receive_fifo_pop()
+{
+ // Clear Receive FIFO Full, DEME, Auto-Response and Poll/Acknowledge bits in NCF
+ m_ncf &= 0xb0;
+
+ // Clear Data Available flag in TSR
+ m_tsr &= 0xf7;
+ if ((m_icr & 0xc0) == 0xc0)
+ set_receiver_interrupt(false);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// set_receiver_error - raise error code and
+// disable receiver
+//-------------------------------------------------
+
+void dp8344_device::set_receiver_error(u8 code)
+{
+ assert(code != 0 && (code & 0xe0) == 0);
+
+ // Set one of five flags in ECR
+ m_ecr |= code;
+
+ // Clear Data Available and Receiver Active flags in TSR
+ m_tsr &= 0xe7;
+
+ // Set Receiver Error flag in TSR
+ m_tsr |= 0x20;
+
+ // Interrupt on RE if enabled; no interrupt on RA
+ set_receiver_interrupt(!BIT(m_icr, 7));
+}
+
+
+//-------------------------------------------------
+// get_error_code - read from ECR
+//-------------------------------------------------
+
+u8 dp8344_device::get_error_code()
+{
+ u8 code = m_ecr;
+
+ // Clear Error Code Register and Receiver Error flag in NCF
+ m_ecr = 0x00;
+ m_ncf &= 0xdf;
+
+ // Update interrupt status if RE interrupt selected
+ switch (m_icr & 0xc0)
+ {
+ case 0x00:
+ // Interrupt on RFF
+ set_receiver_interrupt(BIT(m_ncf, 6));
+ break;
+
+ case 0x40:
+ // Interrupt on DAV
+ set_receiver_interrupt(BIT(m_tsr, 3));
+ break;
+
+ default:
+ break;
+ }
+
+ return code;
+}
+
+
+//-------------------------------------------------
+// set_transceiver_mode - write to TMR
+//-------------------------------------------------
+
+void dp8344_device::set_transceiver_mode(u8 data)
+{
+ // Programmed transceiver reset
+ if (!BIT(m_tmr, 7) && BIT(data, 7))
+ transceiver_reset();
+
+ // TX-ACT is disabled when internal loopback mode is selected
+ if (!BIT(m_tmr, 6) && BIT(data, 6))
+ m_tx_act_cb(0);
+
+ switch (data & 0x07)
+ {
+ case 0:
+ logerror("Protocol Select: IBM 3270\n");
+ break;
+
+ case 1:
+ logerror("Protocol Select: IBM 3299 Multiplexer\n");
+ break;
+
+ case 2:
+ logerror("Protocol Select: IBM 3299 Controller\n");
+ break;
+
+ case 3:
+ logerror("Protocol Select: IBM 3299 Repeater\n");
+ break;
+
+ case 4:
+ logerror("Protocol Select: IBM 5250\n");
+ break;
+
+ case 5:
+ logerror("Protocol Select: IBM 5250 Promiscuous\n");
+ break;
+
+ case 6:
+ logerror("Protocol Select: 8-bit\n");
+ break;
+
+ case 7:
+ logerror("Protocol Select: 8-bit Promiscuous\n");
+ break;
+ }
+
+ m_tmr = data;
+}
+
+
+//-------------------------------------------------
+// clear_network_command_flag - write to NCF
+//-------------------------------------------------
+
+void dp8344_device::clear_network_command_flag(u8 data)
+{
+ // Clear Line Turn Around flag by writing a 1
+ if (BIT(data, 4))
+ {
+ m_ncf &= 0xef;
+ set_line_turn_around_interrupt(false);
+ }
+}
+
+
+//**************************************************************************
+// REGISTER ARRAY
+//**************************************************************************
+
+//-------------------------------------------------
+// read_register - read from source register
+//-------------------------------------------------
+
+u8 dp8344_device::read_register(unsigned reg)
+{
+ switch (reg)
+ {
+ case 0: // Condition Code Register (main) or Device Control Register (alternate)
+ if (m_ba)
+ return m_dcr;
+ else
+ return m_ccr;
+
+ case 1: // Network Command Flag Register (main) or Interrupt Base Register (alternate)
+ if (m_ba)
+ return m_ibr;
+ else
+ return m_ncf;
+
+ case 2: // Interrupt Control Register (main) or Auxiliary Transceiver Register (alternate)
+ if (m_ba)
+ return m_atr;
+ else
+ return m_icr;
+
+ case 3: // Auxiliary Control Register (main) or Fill-Bit Register (alternate)
+ if (m_ba)
+ return m_fbr;
+ else
+ return m_acr;
+
+ case 4: // GP0 (main) or Receive/Transmit Register and/or Error Code Register (alternate)
+ if (m_bb)
+ return BIT(m_tcr, 6) ? get_error_code() : receive_fifo_pop();
+ else
+ return m_gp_main[0];
+
+ case 5: // GP1 (main) or Transceiver Status Register (alternate)
+ if (m_bb)
+ return m_tsr;
+ else
+ return m_gp_main[1];
+
+ case 6: // GP2 (main) or Transceiver Command Register (alternate)
+ if (m_bb)
+ return m_tcr;
+ else
+ return m_gp_main[2];
+
+ case 7: // GP3 (main) or Transceiver Mode Register (alternate)
+ if (m_bb)
+ return m_tmr;
+ else
+ return m_gp_main[3];
+
+ case 8: // GP4/accumulator (main) or GP4' (alternate)
+ if (m_bb)
+ return m_gp_alt[0];
+ else
+ return m_gp_main[4];
+
+ case 9: // GP5 (main) or GP5' (alternate)
+ if (m_bb)
+ return m_gp_alt[1];
+ else
+ return m_gp_main[5];
+
+ case 10: // GP6 (main) or GP6' (alternate)
+ if (m_bb)
+ return m_gp_alt[2];
+ else
+ return m_gp_main[6];
+
+ case 11: // GP7 (main) or GP7' (alternate)
+ if (m_bb)
+ return m_gp_alt[3];
+ else
+ return m_gp_main[7];
+
+ case 12: // IW (low byte)
+ return m_ir[0].b.l;
+
+ case 13: // IW (high byte)
+ return m_ir[0].b.h;
+
+ case 14: // IX (low byte)
+ return m_ir[1].b.l;
+
+ case 15: // IX (high byte)
+ return m_ir[1].b.h;
+
+ case 16: // IY (low byte)
+ return m_ir[2].b.l;
+
+ case 17: // IY (high byte)
+ return m_ir[2].b.h;
+
+ case 18: // IZ (low byte)
+ return m_ir[3].b.l;
+
+ case 19: // IZ (high byte)
+ return m_ir[3].b.h;
+
+ case 20: // GP8
+ return m_gp_main[8];
+
+ case 21: // GP9
+ return m_gp_main[9];
+
+ case 22: // GP10
+ return m_gp_main[10];
+
+ case 23: // GP11
+ return m_gp_main[11];
+
+ case 24: // GP12
+ return m_gp_main[12];
+
+ case 25: // GP13
+ return m_gp_main[13];
+
+ case 26: // GP14
+ return m_gp_main[14];
+
+ case 27: // GP15
+ return m_gp_main[15];
+
+ case 28: // TRL count status
+ return get_timer_count() & 0x00ff;
+
+ case 29: // TRH count status
+ return get_timer_count() >> 8;
+
+ case 30: // Internal Stack Pointer
+ return (m_asp << 4) | m_dsp;
+
+ case 31: // Data Stack
+ return data_stack_pop();
+
+ default: // should never happen
+ logerror("Invalid source register R%d\n", reg);
+ return 0;
+ }
+}
+
+
+//-------------------------------------------------
+// read_accumulator - source ALU data from
+// accumulator register (GP4)
+//-------------------------------------------------
+
+u8 dp8344_device::read_accumulator() const
+{
+ return m_bb ? m_gp_alt[0] : m_gp_main[4];
+}
+
+
+//-------------------------------------------------
+// write_register - write to destination register
+//-------------------------------------------------
+
+void dp8344_device::write_register(unsigned reg, u8 data)
+{
+ switch (reg)
+ {
+ case 0: // Condition Code Register (main) or Device Control Register (alternate)
+ if (m_ba)
+ m_dcr = data;
+ else
+ set_condition_code(data);
+ break;
+
+ case 1: // Network Command Flag Register (main) or Interrupt Base Register (alternate)
+ if (m_ba)
+ m_ibr = data;
+ else
+ clear_network_command_flag(data);
+ break;
+
+ case 2: // Interrupt Control Register (main) or Auxiliary Transceiver Register (alternate)
+ if (m_ba)
+ m_atr = data;
+ else
+ set_interrupt_control(data);
+ break;
+
+ case 3: // Auxiliary Control Register (main) or Fill-Bit Register (alternate)
+ if (m_ba)
+ m_fbr = data;
+ else
+ set_auxiliary_control(data);
+ break;
+
+ case 4: // GP0 (main) or Receive/Transmit Register (alternate)
+ if (m_bb)
+ transmit_fifo_push(data);
+ else
+ m_gp_main[0] = data;
+ break;
+
+ case 5: // GP1 (main) or Transceiver Status Register (alternate)
+ if (m_bb)
+ logerror("Transceiver Status Register is read-only\n");
+ else
+ m_gp_main[1] = data;
+
+ case 6: // GP2 (main) or Transceiver Command Register (alternate)
+ if (m_bb)
+ m_tcr = data;
+ else
+ m_gp_main[2] = data;
+ break;
+
+ case 7: // GP3 (main) or Transceiver Mode Register (alternate)
+ if (m_bb)
+ set_transceiver_mode(data);
+ else
+ m_gp_main[3] = data;
+ break;
+
+ case 8: // GP4/accumulator (main) or GP4' (alternate)
+ if (m_bb)
+ m_gp_alt[0] = data;
+ else
+ m_gp_main[4] = data;
+ break;
+
+ case 9: // GP5 (main) or GP5' (alternate)
+ if (m_bb)
+ m_gp_alt[1] = data;
+ else
+ m_gp_main[5] = data;
+ break;
+
+ case 10: // GP6 (main) or GP6' (alternate)
+ if (m_bb)
+ m_gp_alt[2] = data;
+ else
+ m_gp_main[6] = data;
+ break;
+
+ case 11: // GP7 (main) or GP7' (alternate)
+ if (m_bb)
+ m_gp_alt[3] = data;
+ else
+ m_gp_main[7] = data;
+ break;
+
+ case 12: // IW (low byte)
+ m_ir[0].b.l = data;
+ break;
+
+ case 13: // IW (high byte)
+ m_ir[0].b.h = data;
+ break;
+
+ case 14: // IX (low byte)
+ m_ir[1].b.l = data;
+ break;
+
+ case 15: // IX (high byte)
+ m_ir[1].b.h = data;
+ break;
+
+ case 16: // IY (low byte)
+ m_ir[2].b.l = data;
+ break;
+
+ case 17: // IY (high byte)
+ m_ir[2].b.h = data;
+ break;
+
+ case 18: // IZ (low byte)
+ m_ir[3].b.l = data;
+ break;
+
+ case 19: // IZ (high byte)
+ m_ir[3].b.h = data;
+ break;
+
+ case 20: // GP8
+ m_gp_main[8] = data;
+ break;
+
+ case 21: // GP9
+ m_gp_main[9] = data;
+ break;
+
+ case 22: // GP10
+ m_gp_main[10] = data;
+ break;
+
+ case 23: // GP11
+ m_gp_main[11] = data;
+ break;
+
+ case 24: // GP12
+ m_gp_main[12] = data;
+ break;
+
+ case 25: // GP13
+ m_gp_main[13] = data;
+ break;
+
+ case 26: // GP14
+ m_gp_main[14] = data;
+ break;
+
+ case 27: // GP15
+ m_gp_main[15] = data;
+ break;
+
+ case 28: // TRL holding register
+ m_tr = (m_tr & 0xff00) | data;
+ break;
+
+ case 29: // TRH holding register
+ m_tr = (m_tr & 0x00ff) | u16(data) << 8;
+ break;
+
+ case 30: // Internal Stack Pointer
+ set_stack_pointer(data);
+ break;
+
+ case 31: // Data Stack
+ data_stack_push(data);
+ break;
+
+ default: // should never happen
+ logerror("Invalid destination register R%d = %02X\n", reg, data);
+ break;
+ }
+}
+
+
+//**************************************************************************
+// INPUT LINE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// execute_set_input -
+//-------------------------------------------------
+
+void dp8344_device::execute_set_input(int irqline, int state)
+{
+ switch (irqline)
+ {
+ case BIRQ_LINE:
+ if (!BIT(m_acr, 4))
+ set_birq_interrupt(state == ASSERT_LINE);
+ break;
+
+ case NMI_LINE:
+ if ((state == ASSERT_LINE) && !m_nmi_state)
+ m_nmi_pending = true;
+ m_nmi_state = state == ASSERT_LINE;
+ break;
+
+ case DATA_IN_LINE:
+ break;
+
+ case X_TCLK_LINE:
+ break;
+ }
+}
+
+
+//**************************************************************************
+// PROGRAM EXECUTION
+//**************************************************************************
+
+//-------------------------------------------------
+// create_disassembler -
+//-------------------------------------------------
+
+std::unique_ptr<util::disasm_interface> dp8344_device::create_disassembler()
+{
+ return std::make_unique<dp8344_disassembler>();
+}
+
+
+//-------------------------------------------------
+// execute_run -
+//-------------------------------------------------
+
+void dp8344_device::execute_run()
+{
+ debugger_instruction_hook(m_pc);
+
+ // TODO: everything
+ m_icount = 0;
+}
+
+
+//**************************************************************************
+// REMOTE INTERFACE AND ARBITRATION SYSTEM
+//**************************************************************************
+
+//-------------------------------------------------
+// ric_w - write to Remote Interface Control
+// Register from off-chip
+//-------------------------------------------------
+
+void dp8344_device::ric_w(u8 data)
+{
+ // Bit 7 = Bidirectional Interrupt Status
+ // Bit 6 = Single-Step
+ // Bit 5 = Fast Write
+ // Bit 4 = Latched Read
+ // Bit 3 = Latched Write
+ // Bit 2 = STaRT
+ // Bits 1-0 = Memory Select
+
+ m_ric = data;
+}
+
+
+//-------------------------------------------------
+// remote_read -
+//-------------------------------------------------
+
+void dp8344_device::remote_read()
+{
+ // TODO: stop CPU if not accessing DMEM or RIC
+
+ // set Remote Read bit in CCR
+ m_ccr |= 0x40;
+}
+
+
+//-------------------------------------------------
+// remote_write -
+//-------------------------------------------------
+
+void dp8344_device::remote_write()
+{
+ // TODO: stop CPU if not accessing DMEM or RIC
+
+ // set Remote Write bit in CCR
+ m_ccr |= 0x20;
+}
diff --git a/src/devices/cpu/bcp/dp8344.h b/src/devices/cpu/bcp/dp8344.h
new file mode 100644
index 00000000000..e0ab2e0869e
--- /dev/null
+++ b/src/devices/cpu/bcp/dp8344.h
@@ -0,0 +1,187 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ National Semiconductor DP8344 Biphase Communications Processor
+
+**********************************************************************/
+
+#ifndef MAME_CPU_BCP_DP8344_H
+#define MAME_CPU_BCP_DP8344_H 1
+
+#pragma once
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dp8344_device
+
+class dp8344_device : public cpu_device
+{
+public:
+ // input line enumeration
+ enum {
+ BIRQ_LINE = INPUT_LINE_IRQ0,
+ NMI_LINE = INPUT_LINE_NMI,
+ DATA_IN_LINE = BIRQ_LINE + 1,
+ X_TCLK_LINE
+ };
+
+ // register enumeration
+ enum {
+ BCP_PC,
+ BCP_CCR, BCP_NCF, BCP_ICR, BCP_ACR,
+ BCP_DCR, BCP_IBR, BCP_ATR, BCP_FBR,
+ BCP_GP0, BCP_GP1, BCP_GP2, BCP_GP3, BCP_GP4, BCP_GP5, BCP_GP6, BCP_GP7,
+ BCP_GP8, BCP_GP9, BCP_GP10, BCP_GP11, BCP_GP12, BCP_GP13, BCP_GP14, BCP_GP15,
+ BCP_ECR, BCP_TSR, BCP_TCR, BCP_TMR,
+ BCP_GP4_ALT, BCP_GP5_ALT, BCP_GP6_ALT, BCP_GP7_ALT,
+ BCP_IW, BCP_IX, BCP_IY, BCP_IZ,
+ BCP_IWLO, BCP_IXLO, BCP_IYLO, BCP_IZLO,
+ BCP_IWHI, BCP_IXHI, BCP_IYHI, BCP_IZHI,
+ BCP_TR,
+ BCP_ASP, BCP_DSP,
+ BCP_BA, BCP_BB
+ };
+
+ // construction/destruction
+ dp8344_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // callback configuration
+ auto birq_out_cb() { return m_birq_out_cb.bind(); }
+ auto data_out_cb() { return m_data_out_cb.bind(); }
+ auto data_dly_cb() { return m_data_dly_cb.bind(); }
+ auto tx_act_cb() { return m_tx_act_cb.bind(); }
+
+ // misc. configuration
+ void set_auto_start(bool auto_start) { m_auto_start = auto_start; }
+
+ // remote interface
+ void ric_w(u8 data);
+
+protected:
+ // device-specific overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual u32 execute_min_cycles() const override { return 2; }
+ virtual u32 execute_max_cycles() const override { return 4; }
+ virtual u32 execute_input_lines() const override { return 3; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int irqline, int state) 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;
+
+private:
+ // internal functions
+ bool get_flag(unsigned f) const;
+ void set_receiver_interrupt(bool state);
+ void set_transmitter_interrupt(bool state);
+ void set_line_turn_around_interrupt(bool state);
+ void set_birq_interrupt(bool state);
+ void set_timer_interrupt(bool state);
+ void set_gie(bool state);
+ void set_condition_code(u8 data);
+ void set_interrupt_control(u8 data);
+ void set_auxiliary_control(u8 data);
+ u16 get_timer_count();
+ void address_stack_push();
+ void address_stack_pop(u8 grf);
+ void set_stack_pointer(u8 data);
+ void data_stack_push(u8 data);
+ u8 data_stack_pop();
+ void transceiver_reset();
+ void transmit_fifo_push(u8 data);
+ u16 transmit_fifo_pop();
+ void transmitter_idle();
+ void receiver_active();
+ void receive_fifo_push(u8 data);
+ u8 receive_fifo_pop();
+ void set_receiver_error(u8 code);
+ u8 get_error_code();
+ void set_transceiver_mode(u8 data);
+ void clear_network_command_flag(u8 data);
+ u8 read_register(unsigned reg);
+ u8 read_accumulator() const;
+ void write_register(unsigned reg, u8 data);
+ void remote_read();
+ void remote_write();
+
+ // address spaces
+ const address_space_config m_inst_config;
+ const address_space_config m_data_config;
+ address_space *m_inst_space;
+ address_space *m_data_space;
+ memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_inst_cache;
+
+ // output callbacks
+ devcb_write_line m_birq_out_cb;
+ devcb_write_line m_data_out_cb;
+ devcb_write_line m_data_dly_cb;
+ devcb_write_line m_tx_act_cb;
+
+ // execution state
+ u16 m_pc;
+ s32 m_icount;
+ bool m_nmi_pending;
+
+ // control registers
+ u8 m_ccr;
+ u8 m_ncf;
+ u8 m_icr;
+ u8 m_acr;
+ u8 m_dcr;
+ u8 m_ibr;
+ u8 m_atr;
+ u8 m_fbr;
+ u8 m_ecr;
+ u8 m_tsr;
+ u8 m_tcr;
+ u8 m_tmr;
+
+ // general purpose registers
+ u8 m_gp_main[16];
+ u8 m_gp_alt[4];
+
+ // index registers
+ PAIR16 m_ir[4];
+
+ // timer registers
+ u16 m_tr;
+
+ // internal stacks
+ u32 m_as[12];
+ u8 m_ds[16];
+ u8 m_asp;
+ u8 m_dsp;
+
+ // bank selects
+ bool m_ba;
+ bool m_bb;
+
+ // remote interface registers
+ u8 m_ric;
+ bool m_hib;
+ bool m_auto_start;
+
+ // input lines
+ bool m_nmi_state;
+
+ // transceiver FIFOs
+ u16 m_rfifo[3];
+ u16 m_tfifo[3];
+ u8 m_rfifo_head;
+ u8 m_tfifo_head;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(DP8344, dp8344_device)
+
+#endif // MAME_CPU_BCP_DP8344_H
diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp
index 9a889777a6c..01e7222ff6e 100644
--- a/src/emu/xtal.cpp
+++ b/src/emu/xtal.cpp
@@ -255,6 +255,7 @@ const double XTAL::known_xtals[] = {
18'480'000, /* 18.48_MHz_XTAL Wyse WY-100 video */
18'575'000, /* 18.575_MHz_XTAL Visual 102, Visual 220 */
18'720'000, /* 18.72_MHz_XTAL Nokia MikroMikko 1 */
+ 18'867'000, /* 18.867_MHz_XTAL Decision Data IS-482 */
18'869'600, /* 18.8696_MHz_XTAL Memorex 2178 */
19'339'600, /* 19.3396_MHz_XTAL TeleVideo TVI-955 80-column display clock */
19'584'000, /* 19.584_MHz_XTAL ADM-42 */
diff --git a/src/mame/drivers/is48x.cpp b/src/mame/drivers/is48x.cpp
index 8c06be7ac97..7c06edb6ee0 100644
--- a/src/mame/drivers/is48x.cpp
+++ b/src/mame/drivers/is48x.cpp
@@ -8,7 +8,7 @@
#include "emu.h"
#include "cpu/i86/i186.h"
-//#include "cpu/bcp/bcp.h"
+#include "cpu/bcp/dp8344.h"
//#include "machine/eeprompar.h"
//#include "video/mc6845.h"
//#include "screen.h"
@@ -19,21 +19,46 @@ public:
is48x_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
+ , m_bcp(*this, "bcp")
+ , m_bcpram(*this, "bcpram")
{ }
void is482(machine_config &config);
private:
+ u8 bcpram_r(offs_t offset);
+ void bcpram_w(offs_t offset, u8 data);
+
void mem_map(address_map &map);
void io_map(address_map &map);
+ void bcp_inst_map(address_map &map);
+ void bcp_data_map(address_map &map);
required_device<cpu_device> m_maincpu;
+ required_device<dp8344_device> m_bcp;
+ required_shared_ptr<u16> m_bcpram;
};
+u8 is48x_state::bcpram_r(offs_t offset)
+{
+ if (BIT(offset, 0))
+ return m_bcpram[offset >> 1] >> 8;
+ else
+ return m_bcpram[offset >> 1] & 0x00ff;
+}
+
+void is48x_state::bcpram_w(offs_t offset, u8 data)
+{
+ if (BIT(offset, 0))
+ m_bcpram[offset >> 1] = (m_bcpram[offset >> 1] & 0x00ff) | data << 8;
+ else
+ m_bcpram[offset >> 1] = (m_bcpram[offset >> 1] & 0xff00) | data;
+}
+
void is48x_state::mem_map(address_map &map)
{
map(0x00000, 0x07fff).ram();
- map(0x40000, 0x47fff).ram();
+ map(0x40000, 0x47fff).rw(FUNC(is48x_state::bcpram_r), FUNC(is48x_state::bcpram_w));
map(0x50000, 0x51fff).ram();
map(0x54000, 0x55fff).ram();
map(0x60022, 0x60022).nopr();
@@ -50,6 +75,15 @@ void is48x_state::io_map(address_map &map)
map(0x8180, 0x8180).ram();
}
+void is48x_state::bcp_inst_map(address_map &map)
+{
+ map(0x0000, 0x3fff).ram().share("bcpram");
+}
+
+void is48x_state::bcp_data_map(address_map &map)
+{
+}
+
static INPUT_PORTS_START(is482)
INPUT_PORTS_END
@@ -59,7 +93,9 @@ void is48x_state::is482(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &is48x_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &is48x_state::io_map);
- //DP8344(config, "bcp", 18.867_MHz_XTAL);
+ DP8344(config, m_bcp, 18.867_MHz_XTAL);
+ m_bcp->set_addrmap(AS_PROGRAM, &is48x_state::bcp_inst_map);
+ m_bcp->set_addrmap(AS_DATA, &is48x_state::bcp_data_map);
}
ROM_START(is482) // "IS-488-A" on case
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 1467f13b278..027fa909d7b 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -28,6 +28,7 @@ using util::BIT;
#include "cpu/arm7/arm7dasm.h"
#include "cpu/asap/asapdasm.h"
#include "cpu/avr8/avr8dasm.h"
+#include "cpu/bcp/bcpdasm.h"
#include "cpu/capricorn/capricorn_dasm.h"
#include "cpu/ccpu/ccpudasm.h"
#include "cpu/clipper/clipperd.h"
@@ -339,6 +340,7 @@ static const dasm_table_entry dasm_table[] =
{ "cquestlin", be, -3, []() -> util::disasm_interface * { return new cquestlin_disassembler; } },
{ "cquestrot", be, -3, []() -> util::disasm_interface * { return new cquestrot_disassembler; } },
{ "cquestsnd", be, -3, []() -> util::disasm_interface * { return new cquestsnd_disassembler; } },
+ { "dp8344", le, -1, []() -> util::disasm_interface * { return new dp8344_disassembler; } },
{ "ds5002fp", le, 0, []() -> util::disasm_interface * { return new ds5002fp_disassembler; } },
{ "dsp16", le, -1, []() -> util::disasm_interface * { return new dsp16_disassembler; } },
{ "dsp32c", le, 0, []() -> util::disasm_interface * { return new dsp32c_disassembler; } },