summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms7000
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tms7000')
-rw-r--r--src/devices/cpu/tms7000/7000dasm.cpp120
-rw-r--r--src/devices/cpu/tms7000/7000dasm.h42
-rw-r--r--src/devices/cpu/tms7000/tms7000.cpp34
-rw-r--r--src/devices/cpu/tms7000/tms7000.h57
4 files changed, 155 insertions, 98 deletions
diff --git a/src/devices/cpu/tms7000/7000dasm.cpp b/src/devices/cpu/tms7000/7000dasm.cpp
index 1f7f8549852..000c7ea2ea3 100644
--- a/src/devices/cpu/tms7000/7000dasm.cpp
+++ b/src/devices/cpu/tms7000/7000dasm.cpp
@@ -7,24 +7,9 @@
*/
#include "emu.h"
-#include "debugger.h"
-#include "tms7000.h"
+#include "7000dasm.h"
-enum operandtype { DONE, NONE, UI8, I8, UI16, I16, PCREL, PCABS, TRAP };
-
-struct oprandinfo {
- char opstr[4][12];
- operandtype decode[4];
-};
-
-struct tms7000_opcodeinfo {
- int opcode;
- char name[8];
- int operand;
- uint32_t s_flag;
-};
-
-static const oprandinfo of[] = {
+const tms7000_disassembler::oprandinfo tms7000_disassembler::of[] = {
/* 00 */ { {" B,A", "", "", ""}, {NONE, DONE, DONE, DONE} },
/* 01 */ { {" R%u", ",A", "", ""}, {UI8, NONE, DONE, DONE} },
/* 02 */ { {" R%u", ",B", "", ""}, {UI8, NONE, DONE, DONE} },
@@ -84,7 +69,7 @@ static const oprandinfo of[] = {
/* 45 */ { {" *R%u", "", "", ""}, {UI8, DONE, DONE, DONE} }
};
-static const tms7000_opcodeinfo opcodes[] = {
+const tms7000_disassembler::tms7000_opcodeinfo tms7000_disassembler::opcs[] = {
{0x69, "ADC", 0, 0 },
{0x19, "ADC", 1, 0 },
{0x39, "ADC", 2, 0 },
@@ -141,9 +126,9 @@ static const tms7000_opcodeinfo opcodes[] = {
{0x97, "BTJZP", 21, 0 },
{0xA7, "BTJZP", 22, 0 },
- {0x8E, "CALL", 43, DASMFLAG_STEP_OVER },
- {0x9E, "CALL", 45, DASMFLAG_STEP_OVER },
- {0xAE, "CALL", 12, DASMFLAG_STEP_OVER },
+ {0x8E, "CALL", 43, STEP_OVER },
+ {0x9E, "CALL", 45, STEP_OVER },
+ {0xAE, "CALL", 12, STEP_OVER },
{0xB5, "CLR A", 23, 0 },
{0xC5, "CLR B", 23, 0 },
@@ -273,8 +258,8 @@ static const tms7000_opcodeinfo opcodes[] = {
{0xD8, "PUSH", 24, 0 },
{0x0E, "PUSH ST", 23, 0 },
- {0x0B, "RETI", 23, DASMFLAG_STEP_OUT },
- {0x0A, "RETS", 23, DASMFLAG_STEP_OUT },
+ {0x0B, "RETI", 23, STEP_OUT },
+ {0x0A, "RETS", 23, STEP_OUT },
{0xBE, "RL A", 23, 0 },
{0xCE, "RL B", 23, 0 },
@@ -316,30 +301,30 @@ static const tms7000_opcodeinfo opcodes[] = {
{0x5A, "SUB", 5, 0 },
{0x7A, "SUB", 6, 0 },
- {0xFF, "TRAP 0", 44, DASMFLAG_STEP_OVER },
- {0xFE, "TRAP 1", 44, DASMFLAG_STEP_OVER },
- {0xFD, "TRAP 2", 44, DASMFLAG_STEP_OVER },
- {0xFC, "TRAP 3", 44, DASMFLAG_STEP_OVER },
- {0xFB, "TRAP 4", 44, DASMFLAG_STEP_OVER },
- {0xFA, "TRAP 5", 44, DASMFLAG_STEP_OVER },
- {0xF9, "TRAP 6", 44, DASMFLAG_STEP_OVER },
- {0xF8, "TRAP 7", 44, DASMFLAG_STEP_OVER },
- {0xF7, "TRAP 8", 44, DASMFLAG_STEP_OVER },
- {0xF6, "TRAP 9", 44, DASMFLAG_STEP_OVER },
- {0xF5, "TRAP 10", 44, DASMFLAG_STEP_OVER },
- {0xF4, "TRAP 11", 44, DASMFLAG_STEP_OVER },
- {0xF3, "TRAP 12", 44, DASMFLAG_STEP_OVER },
- {0xF2, "TRAP 13", 44, DASMFLAG_STEP_OVER },
- {0xF1, "TRAP 14", 44, DASMFLAG_STEP_OVER },
- {0xF0, "TRAP 15", 44, DASMFLAG_STEP_OVER },
- {0xEF, "TRAP 16", 44, DASMFLAG_STEP_OVER },
- {0xEE, "TRAP 17", 44, DASMFLAG_STEP_OVER },
- {0xED, "TRAP 18", 44, DASMFLAG_STEP_OVER },
- {0xEC, "TRAP 19", 44, DASMFLAG_STEP_OVER },
- {0xEB, "TRAP 20", 44, DASMFLAG_STEP_OVER },
- {0xEA, "TRAP 21", 44, DASMFLAG_STEP_OVER },
- {0xE9, "TRAP 22", 44, DASMFLAG_STEP_OVER },
- {0xE8, "TRAP 23", 44, DASMFLAG_STEP_OVER },
+ {0xFF, "TRAP 0", 44, STEP_OVER },
+ {0xFE, "TRAP 1", 44, STEP_OVER },
+ {0xFD, "TRAP 2", 44, STEP_OVER },
+ {0xFC, "TRAP 3", 44, STEP_OVER },
+ {0xFB, "TRAP 4", 44, STEP_OVER },
+ {0xFA, "TRAP 5", 44, STEP_OVER },
+ {0xF9, "TRAP 6", 44, STEP_OVER },
+ {0xF8, "TRAP 7", 44, STEP_OVER },
+ {0xF7, "TRAP 8", 44, STEP_OVER },
+ {0xF6, "TRAP 9", 44, STEP_OVER },
+ {0xF5, "TRAP 10", 44, STEP_OVER },
+ {0xF4, "TRAP 11", 44, STEP_OVER },
+ {0xF3, "TRAP 12", 44, STEP_OVER },
+ {0xF2, "TRAP 13", 44, STEP_OVER },
+ {0xF1, "TRAP 14", 44, STEP_OVER },
+ {0xF0, "TRAP 15", 44, STEP_OVER },
+ {0xEF, "TRAP 16", 44, STEP_OVER },
+ {0xEE, "TRAP 17", 44, STEP_OVER },
+ {0xED, "TRAP 18", 44, STEP_OVER },
+ {0xEC, "TRAP 19", 44, STEP_OVER },
+ {0xEB, "TRAP 20", 44, STEP_OVER },
+ {0xEA, "TRAP 21", 44, STEP_OVER },
+ {0xE9, "TRAP 22", 44, STEP_OVER },
+ {0xE8, "TRAP 23", 44, STEP_OVER },
{0xB7, "SWAP A", 23, 0 },
{0xC7, "SWAP B", 23, 0 },
@@ -367,17 +352,22 @@ static const tms7000_opcodeinfo opcodes[] = {
{0x00, "NOP", 23, 0 }
};
-CPU_DISASSEMBLE(tms7000)
+u32 tms7000_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+offs_t tms7000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
int opcode, i/*, size = 1*/;
- int pos = 0;
+ offs_t pos = pc;
char tmpbuf[32];
- opcode = oprom[pos++];
+ opcode = opcodes.r8(pos++);
- for( i=0; i<sizeof(opcodes) / sizeof(tms7000_opcodeinfo); i++ )
+ for( i=0; i<sizeof(opcs) / sizeof(tms7000_opcodeinfo); i++ )
{
- if( opcode == opcodes[i].opcode )
+ if( opcode == opcs[i].opcode )
{
/* We found a match */
@@ -387,9 +377,9 @@ CPU_DISASSEMBLE(tms7000)
uint16_t c;
int16_t d;
- util::stream_format(stream, "%s", opcodes[i].name);
+ util::stream_format(stream, "%s", opcs[i].name);
- j=opcodes[i].operand;
+ j=opcs[i].operand;
for( k=0; k<4; k++ )
{
@@ -401,34 +391,34 @@ CPU_DISASSEMBLE(tms7000)
util::stream_format(stream, "%s", of[j].opstr[k]);
break;
case UI8:
- a = (uint8_t)opram[pos++];
+ a = (uint8_t)params.r8(pos++);
util::stream_format(stream, of[j].opstr[k], (unsigned int)a);
break;
case I8:
- b = (int8_t)opram[pos++];
+ b = (int8_t)params.r8(pos++);
util::stream_format(stream, of[j].opstr[k], (int8_t)b);
break;
case UI16:
- c = (uint16_t)opram[pos++];
+ c = (uint16_t)params.r8(pos++);
c <<= 8;
- c += opram[pos++];
+ c += params.r8(pos++);
util::stream_format(stream, of[j].opstr[k], (unsigned int)c);
break;
case I16:
- d = (int16_t)opram[pos++];
+ d = (int16_t)params.r8(pos++);
d <<= 8;
- d += opram[pos++];
+ d += params.r8(pos++);
util::stream_format(stream, of[j].opstr[k], (signed int)d);
break;
case PCREL:
- b = (int8_t)opram[pos++];
+ b = (int8_t)params.r8(pos++);
sprintf(tmpbuf, "$%04X", pc+2+k+b);
util::stream_format(stream, of[j].opstr[k], tmpbuf);
break;
case PCABS:
- c = (uint16_t)opram[pos++];
+ c = (uint16_t)params.r8(pos++);
c <<= 8;
- c += opram[pos++];
+ c += params.r8(pos++);
sprintf(tmpbuf, "$%04X", c);
util::stream_format(stream, of[j].opstr[k], tmpbuf);
break;
@@ -438,11 +428,11 @@ CPU_DISASSEMBLE(tms7000)
break;
}
}
- return pos | opcodes[i].s_flag | DASMFLAG_SUPPORTED;
+ return (pos - pc) | opcs[i].s_flag | SUPPORTED;
}
}
/* No Match */
stream << "Illegal Opcode";
- return pos | DASMFLAG_SUPPORTED;
+ return (pos - pc) | SUPPORTED;
}
diff --git a/src/devices/cpu/tms7000/7000dasm.h b/src/devices/cpu/tms7000/7000dasm.h
new file mode 100644
index 00000000000..70c01e59fe6
--- /dev/null
+++ b/src/devices/cpu/tms7000/7000dasm.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Tim Lindner
+/*
+
+ TMS7000 disassembler
+
+*/
+
+#ifndef MAME_CPU_TMS7000_7000DASM_H
+#define MAME_CPU_TMS7000_7000DASM_H
+
+#pragma once
+
+class tms7000_disassembler : public util::disasm_interface
+{
+public:
+ tms7000_disassembler() = default;
+ virtual ~tms7000_disassembler() = default;
+
+ 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:
+ enum operandtype { DONE, NONE, UI8, I8, UI16, I16, PCREL, PCABS, TRAP };
+
+ struct oprandinfo {
+ char opstr[4][12];
+ operandtype decode[4];
+ };
+
+ struct tms7000_opcodeinfo {
+ int opcode;
+ char name[8];
+ int operand;
+ uint32_t s_flag;
+ };
+
+ static const oprandinfo of[];
+ static const tms7000_opcodeinfo opcs[];
+};
+
+#endif
diff --git a/src/devices/cpu/tms7000/tms7000.cpp b/src/devices/cpu/tms7000/tms7000.cpp
index a54bac9e20f..25265218735 100644
--- a/src/devices/cpu/tms7000/tms7000.cpp
+++ b/src/devices/cpu/tms7000/tms7000.cpp
@@ -19,6 +19,7 @@
#include "emu.h"
#include "tms7000.h"
+#include "7000dasm.h"
// TMS7000 is the most basic one, 128 bytes internal RAM and no internal ROM.
// TMS7020 and TMS7040 are same, but with 2KB and 4KB internal ROM respectively.
@@ -51,10 +52,6 @@ DEFINE_DEVICE_TYPE(TMS70C46, tms70c46_device, "tms70c46", "TMC70C46")
// internal memory maps
-static ADDRESS_MAP_START(tms7000_io, AS_IO, 8, tms7000_device)
- AM_RANGE(TMS7000_PORTB, TMS7000_PORTB) AM_READNOP
-ADDRESS_MAP_END
-
static ADDRESS_MAP_START(tms7000_mem, AS_PROGRAM, 8, tms7000_device )
AM_RANGE(0x0000, 0x007f) AM_RAM // 128 bytes internal RAM
AM_RANGE(0x0080, 0x00ff) AM_READWRITE(tms7000_unmapped_rf_r, tms7000_unmapped_rf_w)
@@ -114,7 +111,8 @@ tms7000_device::tms7000_device(const machine_config &mconfig, const char *tag, d
tms7000_device::tms7000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal, uint32_t info_flags)
: cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_BIG, 8, 16, 0, internal),
- m_io_config("io", ENDIANNESS_BIG, 8, 8, 0, ADDRESS_MAP_NAME(tms7000_io)),
+ m_port_in_cb{{*this}, {*this}, {*this}, {*this}, {*this}},
+ m_port_out_cb{{*this}, {*this}, {*this}, {*this}, {*this}},
m_info_flags(info_flags)
{
}
@@ -177,8 +175,7 @@ tms70c46_device::tms70c46_device(const machine_config &mconfig, const char *tag,
device_memory_interface::space_config_vector tms7000_device::memory_space_config() const
{
return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_IO, &m_io_config)
+ std::make_pair(AS_PROGRAM, &m_program_config)
};
}
@@ -191,14 +188,18 @@ void tms7000_device::device_start()
{
// init/zerofill
m_program = &space(AS_PROGRAM);
- m_direct = &m_program->direct();
- m_io = &space(AS_IO);
+ m_direct = m_program->direct<0>();
m_icountptr = &m_icount;
m_irq_state[TMS7000_INT1_LINE] = false;
m_irq_state[TMS7000_INT3_LINE] = false;
+ for (auto &cb : m_port_in_cb)
+ cb.resolve_safe(0xff);
+ for (auto &cb : m_port_out_cb)
+ cb.resolve_safe();
+
m_idle_state = false;
m_idle_halt = false;
m_pc = 0;
@@ -273,10 +274,9 @@ void tms7000_device::state_string_export(const device_state_entry &entry, std::s
}
}
-offs_t tms7000_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
+util::disasm_interface *tms7000_device::create_disassembler()
{
- extern CPU_DISASSEMBLE( tms7000 );
- return CPU_DISASSEMBLE_NAME(tms7000)(this, stream, pc, oprom, opram, options);
+ return new tms7000_disassembler;
}
@@ -512,7 +512,7 @@ READ8_MEMBER(tms7000_device::tms7000_pf_r)
// note: port B is write-only, reading it returns the output value as if ddr is 0xff
int port = offset / 2 - 2;
if (!machine().side_effect_disabled())
- return (m_io->read_byte(port) & ~m_port_ddr[port]) | (m_port_latch[port] & m_port_ddr[port]);
+ return (m_port_in_cb[port]() & ~m_port_ddr[port]) | (m_port_latch[port] & m_port_ddr[port]);
break;
}
@@ -594,7 +594,7 @@ WRITE8_MEMBER(tms7000_device::tms7000_pf_w)
// note: in memory expansion modes, some port output pins are used for memory strobes.
// this is currently ignored, since port writes will always be visible externally on peripheral expansion anyway.
int port = offset / 2 - 2;
- m_io->write_byte(port, data & m_port_ddr[port]);
+ m_port_out_cb[port](data & m_port_ddr[port]);
m_port_latch[port] = data;
break;
}
@@ -888,7 +888,9 @@ void tms70c46_device::device_start()
void tms70c46_device::device_reset()
{
m_control = 0;
- m_io->write_byte(TMS7000_PORTE, 0xff);
+
+ // reset port E
+ m_port_out_cb[4](0xff);
tms7000_device::device_reset();
}
@@ -902,7 +904,7 @@ WRITE8_MEMBER(tms70c46_device::control_w)
{
// d5: enable external databus
if (~m_control & data & 0x20)
- m_io->write_byte(TMS7000_PORTE, 0xff); // go into high impedance
+ m_port_out_cb[4](0xff); // put port E into high impedance
// d4: enable clock divider when accessing slow memory (not emulated)
// known fast memory areas: internal ROM/RAM, system RAM
diff --git a/src/devices/cpu/tms7000/tms7000.h b/src/devices/cpu/tms7000/tms7000.h
index ef69bdb881e..bd941fbf9ca 100644
--- a/src/devices/cpu/tms7000/tms7000.h
+++ b/src/devices/cpu/tms7000/tms7000.h
@@ -14,6 +14,33 @@
#include "debugger.h"
+// read-only on 70x0
+#define MCFG_TMS7000_IN_PORTA_CB(_devcb) \
+ devcb = &tms7000_device::set_port_read_cb(*device, 0, DEVCB_##_devcb);
+#define MCFG_TMS7000_OUT_PORTA_CB(_devcb) \
+ devcb = &tms7000_device::set_port_write_cb(*device, 0, DEVCB_##_devcb);
+
+// write-only
+#define MCFG_TMS7000_OUT_PORTB_CB(_devcb) \
+ devcb = &tms7000_device::set_port_write_cb(*device, 1, DEVCB_##_devcb);
+
+#define MCFG_TMS7000_IN_PORTC_CB(_devcb) \
+ devcb = &tms7000_device::set_port_read_cb(*device, 2, DEVCB_##_devcb);
+#define MCFG_TMS7000_OUT_PORTC_CB(_devcb) \
+ devcb = &tms7000_device::set_port_write_cb(*device, 2, DEVCB_##_devcb);
+
+#define MCFG_TMS7000_IN_PORTD_CB(_devcb) \
+ devcb = &tms7000_device::set_port_read_cb(*device, 3, DEVCB_##_devcb);
+#define MCFG_TMS7000_OUT_PORTD_CB(_devcb) \
+ devcb = &tms7000_device::set_port_write_cb(*device, 3, DEVCB_##_devcb);
+
+// TMS70C46 only
+#define MCFG_TMS7000_IN_PORTE_CB(_devcb) \
+ devcb = &tms7000_device::set_port_read_cb(*device, 4, DEVCB_##_devcb);
+#define MCFG_TMS7000_OUT_PORTE_CB(_devcb) \
+ devcb = &tms7000_device::set_port_write_cb(*device, 4, DEVCB_##_devcb);
+
+
enum { TMS7000_PC=1, TMS7000_SP, TMS7000_ST };
enum
@@ -23,15 +50,6 @@ enum
TMS7000_INT3_LINE
};
-enum
-{
- TMS7000_PORTA = 0, /* read-only on 70x0 */
- TMS7000_PORTB, /* write-only */
- TMS7000_PORTC,
- TMS7000_PORTD,
- TMS7000_PORTE /* TMS70C46 only */
-};
-
class tms7000_device : public cpu_device
{
@@ -39,6 +57,12 @@ public:
// construction/destruction
tms7000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // static configuration
+ template<class Object>
+ static devcb_base &set_port_read_cb(device_t &device, int p, Object &&object) { return downcast<tms7000_device &>(device).m_port_in_cb[p].set_callback(std::move(object)); }
+ template<class Object>
+ static devcb_base &set_port_write_cb(device_t &device, int p, Object &&object) { return downcast<tms7000_device &>(device).m_port_out_cb[p].set_callback(std::move(object)); }
+
DECLARE_READ8_MEMBER(tms7000_unmapped_rf_r) { if (!machine().side_effect_disabled()) logerror("'%s' (%04X): unmapped_rf_r @ $%04x\n", tag(), m_pc, offset + 0x80); return 0; };
DECLARE_WRITE8_MEMBER(tms7000_unmapped_rf_w) { logerror("'%s' (%04X): unmapped_rf_w @ $%04x = $%02x\n", tag(), m_pc, offset + 0x80, data); };
@@ -82,22 +106,21 @@ protected:
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
// device_disasm_interface overrides
- virtual uint32_t disasm_min_opcode_bytes() const override { return 1; }
- virtual uint32_t disasm_max_opcode_bytes() const override { return 4; }
- virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
+ virtual util::disasm_interface *create_disassembler() override;
uint32_t chip_get_family() const { return m_info_flags & CHIP_FAMILY_MASK; }
virtual void execute_one(uint8_t op);
address_space_config m_program_config;
- address_space_config m_io_config;
+
+ devcb_read8 m_port_in_cb[5];
+ devcb_write8 m_port_out_cb[5];
uint32_t m_info_flags;
address_space *m_program;
- direct_read_data *m_direct;
- address_space *m_io;
+ direct_read_data<0> *m_direct;
int m_icount;
bool m_irq_state[2];
@@ -319,8 +342,8 @@ public:
DECLARE_WRITE8_MEMBER(dockbus_data_w);
// access I/O port E if databus is disabled
- DECLARE_READ8_MEMBER(e_bus_data_r) { return machine().side_effect_disabled() ? 0xff : ((m_control & 0x20) ? 0xff : m_io->read_byte(TMS7000_PORTE)); }
- DECLARE_WRITE8_MEMBER(e_bus_data_w) { if (~m_control & 0x20) m_io->write_byte(TMS7000_PORTE, data); }
+ DECLARE_READ8_MEMBER(e_bus_data_r) { return machine().side_effect_disabled() ? 0xff : ((m_control & 0x20) ? 0xff : m_port_in_cb[4]()); }
+ DECLARE_WRITE8_MEMBER(e_bus_data_w) { if (~m_control & 0x20) m_port_out_cb[4](data); }
protected:
// device-level overrides