i8089: converted to a proper cpu core, added debugger support and disassembler

This commit is contained in:
Dirk Best 2013-08-24 15:43:58 +00:00
parent 700b42c396
commit 8085624dc7
13 changed files with 1692 additions and 1300 deletions

8
.gitattributes vendored
View File

@ -512,6 +512,12 @@ src/emu/cpu/i8085/8085dasm.c svneol=native#text/plain
src/emu/cpu/i8085/i8085.c svneol=native#text/plain
src/emu/cpu/i8085/i8085.h svneol=native#text/plain
src/emu/cpu/i8085/i8085cpu.h svneol=native#text/plain
src/emu/cpu/i8089/i8089.c svneol=native#text/plain
src/emu/cpu/i8089/i8089.h svneol=native#text/plain
src/emu/cpu/i8089/i8089_channel.c svneol=native#text/plain
src/emu/cpu/i8089/i8089_channel.h svneol=native#text/plain
src/emu/cpu/i8089/i8089_dasm.c svneol=native#text/plain
src/emu/cpu/i8089/i8089_ops.c svneol=native#text/plain
src/emu/cpu/i86/i186.c svneol=native#text/plain
src/emu/cpu/i86/i186.h svneol=native#text/plain
src/emu/cpu/i86/i286.c svneol=native#text/plain
@ -1254,8 +1260,6 @@ src/emu/machine/generic.c svneol=native#text/plain
src/emu/machine/generic.h svneol=native#text/plain
src/emu/machine/i2cmem.c svneol=native#text/plain
src/emu/machine/i2cmem.h svneol=native#text/plain
src/emu/machine/i8089.c svneol=native#text/plain
src/emu/machine/i8089.h svneol=native#text/plain
src/emu/machine/i8155.c svneol=native#text/plain
src/emu/machine/i8155.h svneol=native#text/plain
src/emu/machine/i8212.c svneol=native#text/plain

View File

@ -718,6 +718,25 @@ $(CPUOBJ)/i8085/i8085.o: $(CPUSRC)/i8085/i8085.c \
$(CPUSRC)/i8085/i8085cpu.h
#-------------------------------------------------
# Intel 8089
#@src/emu/cpu/i8085/i8089.h,CPUS += I8089
#-------------------------------------------------
ifneq ($(filter I8089,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/i8089
CPUOBJS += $(CPUOBJ)/i8089/i8089.o \
$(CPUOBJ)/i8089/i8089_channel.o \
$(CPUOBJ)/i8089/i8089_ops.o
DASMOBJS += $(CPUOBJ)/i8089/i8089_dasm.o
endif
$(CPUOBJ)/i8089/i8089_ops.o: $(CPUSRC)/i8089/i8089_channel.h
$(CPUOBJ)/i8089/i8089_channel.o: $(CPUSRC)/i8089/i8089_channel.h
$(CPUOBJ)/i8089/i8089.o: $(CPUSRC)/i8089/i8089.c \
$(CPUSRC)/i8089/i8089.h
#-------------------------------------------------
# Intel MCS-48 (8039 and derivatives)

348
src/emu/cpu/i8089/i8089.c Normal file
View File

@ -0,0 +1,348 @@
/***************************************************************************
Intel 8089 I/O Processor
***************************************************************************/
#include "i8089.h"
#include "i8089_channel.h"
//**************************************************************************
// MACROS/CONSTANTS
//**************************************************************************
#define VERBOSE 1
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
const device_type I8089 = &device_creator<i8089_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// i8089_device - constructor
//-------------------------------------------------
i8089_device::i8089_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
cpu_device(mconfig, I8089, "Intel 8089", tag, owner, clock, "i8089", __FILE__),
m_icount(0),
m_ch1(*this, "1"),
m_ch2(*this, "2"),
m_write_sintr1(*this),
m_write_sintr2(*this),
m_16bit_system(false),
m_16bit_remote(false),
m_master(false),
m_request_grant(false),
m_current_tp(0),
m_ca(0),
m_sel(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void i8089_device::device_start()
{
// set our instruction counter
m_icountptr = &m_icount;
// resolve callbacks
m_write_sintr1.resolve_safe();
m_write_sintr2.resolve_safe();
// register debugger states
state_add(i8089_channel::GA, "CH1 GA", m_ch1->m_r[i8089_channel::GA].w).mask(0xfffff);
state_add(i8089_channel::GB, "CH1 GB", m_ch1->m_r[i8089_channel::GB].w).mask(0xfffff);
state_add(i8089_channel::GC, "CH1 GC", m_ch1->m_r[i8089_channel::GC].w).mask(0xfffff);
state_add(i8089_channel::TP, "CH1 TP", m_ch1->m_r[i8089_channel::TP].w).mask(0xfffff);
state_add(i8089_channel::BC, "CH1 BC", m_ch1->m_r[i8089_channel::BC].w).mask(0xffff);
state_add(i8089_channel::IX, "CH1 IX", m_ch1->m_r[i8089_channel::IX].w).mask(0xffff);
state_add(i8089_channel::CC, "CH1 CC", m_ch1->m_r[i8089_channel::CC].w).mask(0xffff);
state_add(i8089_channel::MC, "CH1 MC", m_ch1->m_r[i8089_channel::MC].w).mask(0xffff);
state_add(i8089_channel::CP, "CH1 CP", m_ch1->m_r[i8089_channel::CP].w).mask(0xfffff);
state_add(i8089_channel::PP, "CH1 PP", m_ch1->m_r[i8089_channel::PP].w).mask(0xfffff);
state_add(i8089_channel::PSW, "CH1 PSW", m_ch1->m_r[i8089_channel::PSW].w).callimport().callexport().formatstr("%12s");
state_add(i8089_channel::GA + i8089_channel::NUM_REGS, "CH2 GA", m_ch2->m_r[i8089_channel::GA].w).mask(0xfffff);
state_add(i8089_channel::GB + i8089_channel::NUM_REGS, "CH2 GB", m_ch2->m_r[i8089_channel::GB].w).mask(0xfffff);
state_add(i8089_channel::GC + i8089_channel::NUM_REGS, "CH2 GC", m_ch2->m_r[i8089_channel::GC].w).mask(0xfffff);
state_add(i8089_channel::TP + i8089_channel::NUM_REGS, "CH2 TP", m_ch2->m_r[i8089_channel::TP].w).mask(0xfffff);
state_add(i8089_channel::BC + i8089_channel::NUM_REGS, "CH2 BC", m_ch2->m_r[i8089_channel::BC].w).mask(0xffff);
state_add(i8089_channel::IX + i8089_channel::NUM_REGS, "CH2 IX", m_ch2->m_r[i8089_channel::IX].w).mask(0xffff);
state_add(i8089_channel::CC + i8089_channel::NUM_REGS, "CH2 CC", m_ch2->m_r[i8089_channel::CC].w).mask(0xffff);
state_add(i8089_channel::MC + i8089_channel::NUM_REGS, "CH2 MC", m_ch2->m_r[i8089_channel::MC].w).mask(0xffff);
state_add(i8089_channel::CP + i8089_channel::NUM_REGS, "CH2 CP", m_ch2->m_r[i8089_channel::CP].w).mask(0xfffff);
state_add(i8089_channel::PP + i8089_channel::NUM_REGS, "CH2 PP", m_ch2->m_r[i8089_channel::PP].w).mask(0xfffff);
state_add(i8089_channel::PSW + i8089_channel::NUM_REGS, "CH2 PSW", m_ch2->m_r[i8089_channel::PSW].w).callimport().callexport().formatstr("%12s");
state_add(STATE_GENPC, "GENPC", m_current_tp).mask(0xfffff).noshow();
// register for save states
save_item(NAME(m_16bit_system));
save_item(NAME(m_16bit_remote));
save_item(NAME(m_master));
save_item(NAME(m_request_grant));
save_item(NAME(m_ca));
save_item(NAME(m_sel));
// assign memory spaces
m_mem = &space(AS_PROGRAM);
m_io = &space(AS_IO);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void i8089_device::device_config_complete()
{
m_program_config = address_space_config("program", ENDIANNESS_LITTLE, m_databus_width, 20);
m_io_config = address_space_config("io", ENDIANNESS_LITTLE, m_databus_width, 16);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void i8089_device::device_reset()
{
m_initialized = false;
}
//-------------------------------------------------
// memory_space_config - device-specific address
// space configurations
//-------------------------------------------------
const address_space_config *i8089_device::memory_space_config(address_spacenum spacenum) const
{
switch (spacenum)
{
case AS_PROGRAM: return &m_program_config;
case AS_IO: return &m_io_config;
default: return NULL;
}
}
//-------------------------------------------------
// disasm_disassemble - disassembler
//-------------------------------------------------
offs_t i8089_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
extern CPU_DISASSEMBLE(i8089);
return CPU_DISASSEMBLE_NAME(i8089)(this, buffer, pc, oprom, opram, options);
}
//-------------------------------------------------
// state_string_export - export state as a string
// for the debugger
//-------------------------------------------------
void i8089_device::state_string_export(const device_state_entry &entry, astring &string)
{
switch (entry.index())
{
case i8089_channel::PSW:
string.printf("%c%s%c%s%s%s%c%c",
BIT(m_ch1->m_r[i8089_channel::PSW].w, 7) ? 'P':'.',
BIT(m_ch1->m_r[i8089_channel::PSW].w, 6) ? "XF":"..",
BIT(m_ch1->m_r[i8089_channel::PSW].w, 5) ? 'B':'.',
BIT(m_ch1->m_r[i8089_channel::PSW].w, 4) ? "IS":"..",
BIT(m_ch1->m_r[i8089_channel::PSW].w, 3) ? "IC":"..",
BIT(m_ch1->m_r[i8089_channel::PSW].w, 2) ? "TB":"..",
BIT(m_ch1->m_r[i8089_channel::PSW].w, 1) ? 'S':'.',
BIT(m_ch1->m_r[i8089_channel::PSW].w, 0) ? 'D':'.');
break;
case i8089_channel::PSW + i8089_channel::NUM_REGS:
string.printf("%c%s%c%s%s%s%c%c",
BIT(m_ch2->m_r[i8089_channel::PSW].w, 7) ? 'P':'.',
BIT(m_ch2->m_r[i8089_channel::PSW].w, 6) ? "XF":"..",
BIT(m_ch2->m_r[i8089_channel::PSW].w, 5) ? 'B':'.',
BIT(m_ch2->m_r[i8089_channel::PSW].w, 4) ? "IS":"..",
BIT(m_ch2->m_r[i8089_channel::PSW].w, 3) ? "IC":"..",
BIT(m_ch2->m_r[i8089_channel::PSW].w, 2) ? "TB":"..",
BIT(m_ch2->m_r[i8089_channel::PSW].w, 1) ? 'S':'.',
BIT(m_ch2->m_r[i8089_channel::PSW].w, 0) ? 'D':'.');
break;
}
}
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
static MACHINE_CONFIG_FRAGMENT( i8089 )
MCFG_I8089_CHANNEL_ADD("1")
MCFG_I8089_CHANNEL_SINTR(WRITELINE(i8089_device, ch1_sintr_w))
MCFG_I8089_CHANNEL_ADD("2")
MCFG_I8089_CHANNEL_SINTR(WRITELINE(i8089_device, ch2_sintr_w))
MACHINE_CONFIG_END
machine_config_constructor i8089_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( i8089 );
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
// the i8089 actually executes a program from internal rom here:
//
// MOVB SYSBUS from FFFF6
// LPD System Configuration Block from FFFF8
// MOVB SOC from (SCB)
// LPD Control Pointer (CP) from (SCB) + 2
// MOVBI "00" to CP + 1 (clear busy flag)
void i8089_device::initialize()
{
assert(!m_initialized);
// get system bus width
UINT8 sys_bus = m_mem->read_byte(0xffff6);
m_16bit_system = BIT(sys_bus, 0);
// get system configuration block address
UINT16 scb_offset = read_word(0xffff8);
UINT16 scb_segment = read_word(0xffffa);
offs_t scb_address = ((scb_segment << 4) + scb_offset) & 0x0fffff;
// get system operation command
UINT16 soc = read_word(scb_address);
m_16bit_remote = BIT(soc, 0);
m_request_grant = BIT(soc, 1);
m_master = !m_sel;
// get control block address
UINT16 cb_offset = read_word(scb_address + 2);
UINT16 cb_segment = read_word(scb_address + 4);
offs_t cb_address = ((cb_segment << 4) + cb_offset) & 0x0fffff;
// initialize channels
m_ch1->set_reg(i8089_channel::CP, cb_address);
m_ch2->set_reg(i8089_channel::CP, cb_address + 8);
// clear busy
UINT16 ccw = read_word(cb_address);
write_word(cb_address, ccw & 0x00ff);
// done
m_initialized = true;
// output some debug info
if (VERBOSE)
{
logerror("%s('%s'): ---- initializing ----\n", shortname(), basetag());
logerror("%s('%s'): %s system bus\n", shortname(), basetag(), m_16bit_system ? "16-bit" : "8-bit");
logerror("%s('%s'): system configuration block location: %06x\n", shortname(), basetag(), scb_address);
logerror("%s('%s'): %s remote bus\n", shortname(), basetag(), m_16bit_remote ? "16-bit" : "8-bit");
logerror("%s('%s'): request/grant: %d\n", shortname(), basetag(), m_request_grant);
logerror("%s('%s'): is %s\n", shortname(), basetag(), m_master ? "master" : "slave");
logerror("%s('%s'): channel control block location: %06x\n", shortname(), basetag(), cb_address);
}
}
UINT8 i8089_device::read_byte(offs_t address)
{
assert(m_initialized);
return m_mem->read_byte(address);
}
UINT16 i8089_device::read_word(offs_t address)
{
assert(m_initialized);
UINT16 data = 0xffff;
if (m_16bit_system && !(address & 1))
{
data = m_mem->read_word(address);
}
else
{
data = m_mem->read_byte(address);
data |= m_mem->read_byte(address + 1) << 8;
}
return data;
}
void i8089_device::write_byte(offs_t address, UINT8 data)
{
assert(m_initialized);
m_mem->write_byte(address, data);
}
void i8089_device::write_word(offs_t address, UINT16 data)
{
assert(m_initialized);
if (m_16bit_system && !(address & 1))
{
m_mem->write_word(address, data);
}
else
{
m_mem->write_byte(address, data & 0xff);
m_mem->write_byte(address + 1, (data >> 8) & 0xff);
}
}
void i8089_device::execute_run()
{
do
{
// allocate cycles to the two channels, very very incomplete
m_icount -= m_ch1->execute_run();
m_icount -= m_ch2->execute_run();
}
while (m_icount > 0);
}
//**************************************************************************
// EXTERNAL INPUTS
//**************************************************************************
WRITE_LINE_MEMBER( i8089_device::ca_w )
{
if (VERBOSE)
logerror("%s('%s'): ca_w: %u\n", shortname(), basetag(), state);
if (m_ca == 1 && state == 0)
{
if (!m_initialized)
initialize();
else
{
if (m_sel == 0)
m_ch1->attention();
else
m_ch2->attention();
}
}
m_ca = state;
}
WRITE_LINE_MEMBER( i8089_device::drq1_w ) { m_ch1->drq_w(state); }
WRITE_LINE_MEMBER( i8089_device::drq2_w ) { m_ch2->drq_w(state); }
WRITE_LINE_MEMBER( i8089_device::ext1_w ) { m_ch1->ext_w(state); }
WRITE_LINE_MEMBER( i8089_device::ext2_w ) { m_ch2->ext_w(state); }

View File

@ -16,9 +16,8 @@
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_I8089_ADD(_tag, _clock, _cputag) \
MCFG_DEVICE_ADD(_tag, I8089, _clock) \
i8089_device::static_set_cputag(*device, _cputag);
#define MCFG_I8089_DATABUS_WIDTH(_databus_width) \
i8089_device::set_databus_width(*device, _databus_width);
#define MCFG_I8089_SINTR1(_sintr1) \
downcast<i8089_device *>(device)->set_sintr1_callback(DEVCB2_##_sintr1);
@ -36,8 +35,7 @@ class i8089_channel;
// ======================> i8089_device
class i8089_device : public device_t,
public device_execute_interface
class i8089_device : public cpu_device
{
friend class i8089_channel;
@ -49,6 +47,9 @@ public:
template<class _sintr1> void set_sintr1_callback(_sintr1 sintr1) { m_write_sintr1.set_callback(sintr1); }
template<class _sintr2> void set_sintr2_callback(_sintr2 sintr2) { m_write_sintr2.set_callback(sintr2); }
// static configuration helpers
static void set_databus_width(device_t &device, UINT8 databus_width) { downcast<i8089_device &>(device).m_databus_width = databus_width; }
// input lines
DECLARE_WRITE_LINE_MEMBER( ca_w );
DECLARE_WRITE_LINE_MEMBER( sel_w ) { m_sel = state; }
@ -61,12 +62,10 @@ public:
DECLARE_WRITE_LINE_MEMBER( ch1_sintr_w ) { m_write_sintr1(state); }
DECLARE_WRITE_LINE_MEMBER( ch2_sintr_w ) { m_write_sintr2(state); }
// inline configuration
static void static_set_cputag(device_t &device, const char *tag);
protected:
// device-level overrides
virtual void device_start();
virtual void device_config_complete();
virtual void device_reset();
// device_execute_interface overrides
@ -74,6 +73,20 @@ protected:
int m_icount;
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
address_space_config m_program_config;
address_space_config m_io_config;
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
virtual UINT32 disasm_max_opcode_bytes() const { return 6; }
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, astring &string);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
@ -91,9 +104,7 @@ private:
void initialize();
// internal state
const char *m_cputag;
UINT8 m_databus_width;
address_space *m_mem;
address_space *m_io;
@ -104,6 +115,9 @@ private:
bool m_master;
bool m_request_grant;
// task pointer for the currently executing channel
offs_t m_current_tp;
// state of input pins
int m_ca;
int m_sel;

View File

@ -0,0 +1,641 @@
/***************************************************************************
Intel 8089 I/O Processor
I/O channel
***************************************************************************/
#include "emu.h"
#include "debugger.h"
#include "i8089_channel.h"
//**************************************************************************
// MACROS/CONSTANTS
//**************************************************************************
#define VERBOSE 1
#define VERBOSE_DMA 1
// channel control register fields
#define CC_TMC ((m_r[CC].w >> 0) & 0x07) // terminate on masked compare
#define CC_TBC ((m_r[CC].w >> 3) & 0x03) // terminate on byte count
#define CC_TX ((m_r[CC].w >> 5) & 0x03) // terminate on external signal
#define CC_TS ((m_r[CC].w >> 7) & 0x01) // terminate on single transfer
#define CC_CHAIN ((m_r[CC].w >> 8) & 0x01) // chaining
#define CC_LOCK ((m_r[CC].w >> 9) & 0x01) // actuate lock
#define CC_SOURCE ((m_r[CC].w >> 10) & 0x01) // source register
#define CC_SYNC ((m_r[CC].w >> 11) & 0x03) // synchronization
#define CC_TRANS ((m_r[CC].w >> 13) & 0x01) // translation
#define CC_FUNC ((m_r[CC].w >> 14) & 0x03) // function
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
const device_type I8089_CHANNEL = &device_creator<i8089_channel>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// i8089_channel - constructor
//-------------------------------------------------
i8089_channel::i8089_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, I8089_CHANNEL, "Intel 8089 I/O Channel", tag, owner, clock, "i8089_channel", __FILE__),
m_write_sintr(*this),
m_icount(0),
m_xfer_pending(false),
m_dma_value(0),
m_dma_state(DMA_IDLE)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void i8089_channel::device_start()
{
// get parent device
m_iop = downcast<i8089_device *>(owner());
// resolve callbacks
m_write_sintr.resolve_safe();
// register for save states
save_item(NAME(m_xfer_pending));
save_item(NAME(m_dma_value));
save_item(NAME(m_dma_state));
for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
{
save_item(NAME(m_r[i].w), i);
save_item(NAME(m_r[i].t), i);
}
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void i8089_channel::device_reset()
{
m_xfer_pending = false;
// initialize registers
for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
{
m_r[i].w = 0;
m_r[i].t = 0;
}
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
void i8089_channel::set_reg(int reg, int value, int tag)
{
m_r[reg].w = value;
if (tag != -1)
m_r[reg].t = tag;
if (reg == TP)
m_iop->m_current_tp = value;
}
// channel status
bool i8089_channel::executing() { return BIT(m_r[PSW].w, 2); }
bool i8089_channel::transferring() { return BIT(m_r[PSW].w, 6); }
bool i8089_channel::priority() { return BIT(m_r[PSW].w, 7); }
bool i8089_channel::chained() { return CC_CHAIN; }
bool i8089_channel::lock() { return CC_LOCK; }
UINT16 i8089_channel::displacement(int wb)
{
UINT16 displacement = 0;
if (wb == 1)
{
displacement = m_iop->read_byte(m_r[TP].w);
set_reg(TP, m_r[TP].w + 1);
}
else if (wb == 2)
{
displacement = m_iop->read_word(m_r[TP].w);
set_reg(TP, m_r[TP].w + 2);
}
return displacement;
}
UINT8 i8089_channel::offset(int aa)
{
UINT8 offset = 0;
if (aa == 1)
{
offset = m_iop->read_byte(m_r[TP].w);
set_reg(TP, m_r[TP].w + 1);
}
return offset;
}
UINT8 i8089_channel::imm8()
{
UINT8 imm8 = m_iop->read_byte(m_r[TP].w);
set_reg(TP, m_r[TP].w + 1);
return imm8;
}
UINT16 i8089_channel::imm16()
{
UINT16 imm16 = m_iop->read_word(m_r[TP].w);
set_reg(TP, m_r[TP].w + 2);
return imm16;
}
// adjust task pointer and continue execution
void i8089_channel::terminate_dma(int offset)
{
if (VERBOSE)
logerror("%s('%s'): terminating dma transfer\n", shortname(), tag());
set_reg(TP, m_r[TP].w + offset);
m_r[PSW].w |= 1 << 2;
m_r[PSW].w &= ~(1 << 6);
m_dma_state = DMA_IDLE;
}
int i8089_channel::execute_run()
{
m_icount = 0;
// active transfer?
if (transferring())
{
// new transfer?
if (executing())
{
// we are no longer executing task blocks
m_r[PSW].w &= ~(1 << 2);
m_xfer_pending = false;
if (VERBOSE)
{
logerror("%s('%s'): ---- starting dma transfer ----\n", shortname(), tag());
logerror("%s('%s'): ga = %06x, gb = %06x, gc = %06x\n", shortname(), tag(), m_r[GA].w, m_r[GB].w, m_r[GC].w);
logerror("%s('%s'): bc = %04x, cc = %04x, mc = %04x\n", shortname(), tag(), m_r[BC].w, m_r[CC].w, m_r[MC].w);
}
}
// todo: port transfers
if (CC_FUNC != 0x03)
fatalerror("%s('%s'): port transfer\n", shortname(), tag());
switch (m_dma_state)
{
case DMA_IDLE:
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_IDLE (bc = %04x)\n", shortname(), tag(), m_r[BC].w);
// synchronize on source?
if (CC_SYNC == 0x01)
m_dma_state = DMA_WAIT_FOR_SOURCE_DRQ;
else
m_dma_state = DMA_FETCH;
break;
case DMA_WAIT_FOR_SOURCE_DRQ:
fatalerror("%s('%s'): wait for source drq not supported\n", shortname(), tag());
break;
case DMA_FETCH:
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_FETCH", shortname(), tag());
// source is 16-bit?
if (BIT(m_r[PSW].w, 1))
{
m_dma_value = m_iop->read_word(m_r[GA + CC_SOURCE].w);
m_r[GA + CC_SOURCE].w += 2;
m_r[BC].w -= 2;
}
// destination is 16-bit, byte count is even
else if (BIT(m_r[PSW].w, 0) && !(m_r[BC].w & 1))
{
m_dma_value = m_iop->read_byte(m_r[GA + CC_SOURCE].w);
m_r[GA + CC_SOURCE].w++;
m_r[BC].w--;
}
// destination is 16-bit, byte count is odd
else if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
{
m_dma_value |= m_iop->read_byte(m_r[GA + CC_SOURCE].w) << 8;
m_r[GA + CC_SOURCE].w++;
m_r[BC].w--;
}
// 8-bit transfer
else
{
m_dma_value = m_iop->read_byte(m_r[GA + CC_SOURCE].w);
m_r[GA + CC_SOURCE].w++;
m_r[BC].w--;
}
if (VERBOSE_DMA)
logerror("[ %04x ]\n", m_dma_value);
if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
m_dma_state = DMA_FETCH;
else if (CC_TRANS)
m_dma_state = DMA_TRANSLATE;
else if (CC_SYNC == 0x02)
m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
else
m_dma_state = DMA_STORE;
break;
case DMA_TRANSLATE:
fatalerror("%s('%s'): dma translate requested\n", shortname(), tag());
break;
case DMA_WAIT_FOR_DEST_DRQ:
fatalerror("%s('%s'): wait for destination drq not supported\n", shortname(), tag());
break;
case DMA_STORE:
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_STORE", shortname(), tag());
// destination is 16-bit?
if (BIT(m_r[PSW].w, 0))
{
m_iop->write_word(m_r[GB - CC_SOURCE].w, m_dma_value);
m_r[GB - CC_SOURCE].w += 2;
if (VERBOSE_DMA)
logerror("[ %04x ]\n", m_dma_value);
}
// destination is 8-bit
else
{
m_iop->write_byte(m_r[GB - CC_SOURCE].w, m_dma_value & 0xff);
m_r[GB - CC_SOURCE].w++;
if (VERBOSE_DMA)
logerror("[ %02x ]\n", m_dma_value & 0xff);
}
if (CC_TMC & 0x03)
m_dma_state = DMA_COMPARE;
else
m_dma_state = DMA_TERMINATE;
break;
case DMA_COMPARE:
fatalerror("%s('%s'): dma compare requested\n", shortname(), tag());
break;
case DMA_TERMINATE:
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_TERMINATE\n", shortname(), tag());
// terminate on masked compare?
if (CC_TMC & 0x03)
fatalerror("%s('%s'): terminate on masked compare not supported\n", shortname(), tag());
// terminate on byte count?
else if (CC_TBC && m_r[BC].w == 0)
terminate_dma((CC_TBC - 1) * 4);
// terminate on external signal
else if (CC_TX)
fatalerror("%s('%s'): terminate on external signal not supported\n", shortname(), tag());
// terminate on single transfer
else if (CC_TS)
fatalerror("%s('%s'): terminate on single transfer not supported\n", shortname(), tag());
// not terminated, continue transfer
else
// do we need to read another byte?
if (BIT(m_r[PSW].w, 1) && !BIT(m_r[PSW].w, 0))
if (CC_SYNC == 0x02)
m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
else
m_dma_state = DMA_STORE_BYTE_HIGH;
// transfer done
else
m_dma_state = DMA_IDLE;
break;
case DMA_STORE_BYTE_HIGH:
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_STORE_BYTE_HIGH[ %02x ]\n", shortname(), tag(), (m_dma_value >> 8) & 0xff);
m_iop->write_byte(m_r[GB - CC_SOURCE].w, (m_dma_value >> 8) & 0xff);
m_r[GB - CC_SOURCE].w++;
m_dma_state = DMA_TERMINATE;
break;
}
m_icount++;
}
// executing task block instructions?
else if (executing())
{
// call debugger
debugger_instruction_hook(m_iop, m_iop->m_current_tp);
// dma transfer pending?
if (m_xfer_pending)
m_r[PSW].w |= 1 << 6;
// fetch first two instruction bytes
UINT16 op = m_iop->read_word(m_r[TP].w);
set_reg(TP, m_r[TP].w + 2);
// extract parameters
UINT8 params = op & 0xff;
UINT8 opcode = (op >> 8) & 0xff;
int brp = (params >> 5) & 0x07;
int wb = (params >> 3) & 0x03;
int aa = (params >> 1) & 0x03;
int w = (params >> 0) & 0x01;
int opc = (opcode >> 2) & 0x3f;
int mm = (opcode >> 0) & 0x03;
// fix-up so we can use our register array
if (mm == BC) mm = PP;
UINT8 o;
UINT16 off, seg;
switch (opc)
{
case 0x00: // control
switch (brp)
{
case 0: nop(); break;
case 1: invalid(opc); break;
case 2: sintr(); break;
case 3: xfer(); break;
default: wid(BIT(brp, 1), BIT(brp, 0));
}
break;
case 0x02: // lpdi
off = imm16();
seg = imm16();
lpdi(brp, seg, off);
break;
case 0x08: // add(b)i r, i
if (w) addi_ri(brp, imm16());
else addbi_ri(brp, imm8());
break;
case 0x0a: // and(b)i r, i
if (w) andi_ri(brp, imm16());
else andbi_ri(brp, imm8());
break;
case 0x0c: // mov(b)i r, i
if (w) movi_ri(brp, imm16());
else movbi_ri(brp, imm8());
break;
case 0x0f: // dec r
dec_r(brp);
break;
case 0x12: // hlt
if (BIT(brp, 0)) hlt();
else invalid(opc);
break;
case 0x22: // lpd
o = offset(aa);
lpd(brp, mm, o);
break;
case 0x28: // add(b) r, m
if (w) add_rm(brp, mm, offset(aa));
else addb_rm(brp, mm, offset(aa));
break;
case 0x2a: // and(b) r, m
if (w) and_rm(brp, mm, offset(aa));
else andb_rm(brp, mm, offset(aa));
break;
case 0x27: // call
o = offset(aa);
call(mm, displacement(wb), o);
break;
case 0x30: // add(b)i m, i
o = offset(aa);
if (w) addi_mi(mm, imm16(), o);
else addbi_mi(mm, imm8(), o);
break;
case 0x32: // and(b)i m, i
o = offset(aa);
if (w) andi_mi(mm, imm16(), o);
else andbi_mi(mm, imm8(), o);
break;
case 0x34: // add(b) m, r
if (w) add_mr(mm, brp, offset(aa));
else addb_mr(mm, brp, offset(aa));
break;
case 0x36: // and(b) m, r
if (w) and_mr(mm, brp, offset(aa));
else andb_mr(mm, brp, offset(aa));
break;
case 0x3b: // dec(b) m
if (w) dec_m(mm, offset(aa));
else decb(mm, offset(aa));
break;
case 0x3e: // clr
clr(mm, brp, offset(aa));
break;
default:
invalid(opc);
}
m_icount++;
}
// nothing to do
else
{
m_icount++;
}
return m_icount;
}
void i8089_channel::examine_ccw(UINT8 ccw)
{
// priority and bus load limit, bit 7 and 5
m_r[PSW].w = (m_r[PSW].w & 0x5f) | (ccw & 0xa0);
// acknowledge interrupt
if (BIT(ccw, 4))
{
m_write_sintr(0);
m_r[PSW].w &= ~(1 << 5);
}
// interrupt enable
if (BIT(ccw, 5))
{
if (BIT(ccw, 4))
m_r[PSW].w &= ~(1 << 4);
else
m_r[PSW].w |= 1 << 4;
}
}
void i8089_channel::attention()
{
// examine control byte
UINT8 ccw = m_iop->read_byte(m_r[CP].w);
switch (ccw & 0x07)
{
// no channel command
case 0:
if (VERBOSE)
logerror("%s('%s'): command received: update psw\n", shortname(), tag());
examine_ccw(ccw);
break;
// start channel, tb in local space
case 1:
if (VERBOSE)
logerror("%s('%s'): command received: start channel in local space\n", shortname(), tag());
examine_ccw(ccw);
lpd(PP, CP, 2);
movp_pm(TP, PP);
movbi_mi(CP, 0xff, 1);
m_r[PSW].w |= 1 << 2;
break;
// reserved
case 2:
if (VERBOSE)
logerror("%s('%s'): command received: invalid command 010\n", shortname(), tag());
break;
// start channel, tb in system space
case 3:
if (VERBOSE)
logerror("%s('%s'): command received: start channel in system space\n", shortname(), tag());
examine_ccw(ccw);
lpd(PP, CP, 2);
lpd(TP, PP);
movbi_mi(CP, 0xff, 1);
m_r[PSW].w |= 1 << 2;
if (VERBOSE)
{
logerror("%s('%s'): ---- starting channel ----\n", shortname(), tag());
logerror("%s('%s'): parameter block address: %06x\n", shortname(), tag(), m_r[PP].w);
logerror("%s('%s'): task pointer: %06x\n", shortname(), tag(), m_r[TP].w);
}
break;
case 4:
if (VERBOSE)
logerror("%s('%s'): command received: invalid command 100\n", shortname(), tag());
break;
// continue channel processing
case 5:
if (VERBOSE)
logerror("%s('%s'): command received: continue channel processing\n", shortname(), tag());
// restore task pointer and parameter block
movp_pm(TP, PP);
movb_rm(PSW, PP, 3);
movbi_mi(CP, 0xff, 1);
m_r[PSW].w |= 1 << 2;
if (VERBOSE)
{
logerror("%s('%s'): ---- continuing channel ----\n", shortname(), tag());
logerror("%s('%s'): task pointer: %06x\n", shortname(), tag(), m_r[TP].w);
}
break;
// halt channel, save tp
case 6:
if (VERBOSE)
logerror("%s('%s'): command received: halt channel and save tp\n", shortname(), tag());
// save task pointer and psw to parameter block
movp_mp(PP, TP);
movb_mr(PP, PSW, 3);
hlt();
break;
// halt channel, don't save tp
case 7:
if (VERBOSE)
logerror("%s('%s'): command received: halt channel\n", shortname(), tag());
hlt();
break;
}
}
WRITE_LINE_MEMBER( i8089_channel::ext_w )
{
if (VERBOSE)
logerror("%s('%s'): ext_w: %d\n", shortname(), tag(), state);
}
WRITE_LINE_MEMBER( i8089_channel::drq_w )
{
if (VERBOSE)
logerror("%s('%s'): ext_w: %d\n", shortname(), tag(), state);
}

View File

@ -0,0 +1,216 @@
/***************************************************************************
Intel 8089 I/O Processor
I/O channel
***************************************************************************/
#pragma once
#ifndef __I8089_CHANNEL_H__
#define __I8089_CHANNEL_H__
#include "emu.h"
#include "i8089.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_I8089_CHANNEL_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, I8089_CHANNEL, 0)
#define MCFG_I8089_CHANNEL_SINTR(_sintr) \
downcast<i8089_channel *>(device)->set_sintr_callback(DEVCB2_##_sintr);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class i8089_channel : public device_t
{
public:
// construction/destruction
i8089_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
template<class _sintr> void set_sintr_callback(_sintr sintr) { m_write_sintr.set_callback(sintr); }
// set register
void set_reg(int reg, int value, int tag = -1);
int execute_run();
void attention();
// channel status
bool executing();
bool transferring();
bool priority();
bool chained();
bool lock();
DECLARE_WRITE_LINE_MEMBER( ext_w );
DECLARE_WRITE_LINE_MEMBER( drq_w );
// register
enum
{
GA, // 20-bit general purpose address a
GB, // 20-bit general purpose address b
GC, // 20-bit general purpose address c
BC, // byte count
TP, // 20-bit task pointer
IX, // byte count
CC, // mask compare
MC, // channel control
// internal use register
CP, // 20-bit control block pointer
PP, // 20-bit parameter pointer
PSW, // program status word
NUM_REGS
};
struct
{
int w; // 20-bit address
int t; // tag-bit
}
m_r[11];
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
private:
// opcodes
void add_rm(int r, int m, int o = 0);
void add_mr(int m, int r, int o = 0);
void addb_rm(int r, int m, int o = 0);
void addb_mr(int m, int r, int o = 0);
void addbi_ri(int r, int i);
void addbi_mi(int m, int i, int o = 0);
void addi_ri(int r, int i);
void addi_mi(int m, int i, int o = 0);
void and_rm(int r, int m, int o = 0);
void and_mr(int m, int r, int o = 0);
void andb_rm(int r, int m, int o = 0);
void andb_mr(int m, int r, int o = 0);
void andbi_ri(int r, int i);
void andbi_mi(int m, int i, int o = 0);
void andi_ri(int r, int i);
void andi_mi(int m, int i, int o = 0);
void call(int m, int d, int o = 0);
void clr(int m, int b, int o = 0);
void dec_r(int r);
void dec_m(int m, int o = 0);
void decb(int m, int o = 0);
void hlt();
void inc_r(int r);
void inc_m(int m, int o = 0);
void incb(int m, int o = 0);
void jbt(int m, int b, int d, int o = 0);
void jmce(int m, int d, int o = 0);
void jmcne(int m, int d, int o = 0);
void jmp(int d);
void jnbt(int m, int b, int d, int o = 0);
void jnz_r(int r, int d);
void jnz_m(int m, int d, int o = 0);
void jnzb(int m, int d, int o = 0);
void jz_r(int r, int d);
void jz_m(int m, int d, int o = 0);
void jzb(int m, int d, int o = 0);
void lcall(int m, int d, int o = 0);
void ljbt(int m, int b, int d, int o = 0);
void ljmce(int m, int d, int o = 0);
void ljmcne(int m, int d, int o = 0);
void ljmp(int d);
void ljnbt(int m, int b, int d, int o = 0);
void ljnz_r(int r, int d);
void ljnz_m(int m, int d, int o = 0);
void ljnzb(int m, int d, int o = 0);
void ljz_r(int r, int d);
void ljz_m(int m, int d, int o = 0);
void ljzb(int m, int d, int o = 0);
void lpd(int p, int m, int o = 0);
void lpdi(int p, int i, int o = 0);
void mov_mr(int m, int r, int o = 0);
void mov_rm(int r, int m, int o = 0);
void mov_mm(int m1, int m2, int o1 = 0, int o2 = 0);
void movb_mr(int m, int r, int o = 0);
void movb_rm(int r, int m, int o = 0);
void movb_mm(int m1, int m2, int o1 = 0, int o2 = 0);
void movbi_ri(int r, int i);
void movbi_mi(int m, int i, int o = 0);
void movi_ri(int r, int i);
void movi_mi(int m, int i, int o = 0);
void movp_mp(int m, int p, int o = 0);
void movp_pm(int p, int m, int o = 0);
void nop();
void not_r(int r);
void not_m(int m, int o = 0);
void not_rm(int r, int m, int o = 0);
void notb_m(int m, int o = 0);
void notb_rm(int r, int m, int o = 0);
void or_rm(int r, int m, int o = 0);
void or_mr(int m, int r, int o = 0);
void orb_rm(int r, int m, int o = 0);
void orb_mr(int m, int r, int o = 0);
void orbi_ri(int r, int i);
void orbi_mi(int m, int i, int o = 0);
void ori_ri(int r, int i);
void ori_mi(int m, int i, int o = 0);
void setb(int m, int b, int o = 0);
void sintr();
void tsl(int m, int i, int d, int o = 0);
void wid(int s, int d);
void xfer();
void invalid(int opc);
// instruction fetch
UINT16 displacement(int wb);
UINT8 offset(int aa);
UINT8 imm8();
UINT16 imm16();
void examine_ccw(UINT8 ccw);
devcb2_write_line m_write_sintr;
i8089_device *m_iop;
int m_icount;
// dma
void terminate_dma(int offset);
bool m_xfer_pending;
UINT16 m_dma_value;
int m_dma_state;
// dma state
enum
{
DMA_IDLE,
DMA_WAIT_FOR_SOURCE_DRQ,
DMA_FETCH,
DMA_TRANSLATE,
DMA_WAIT_FOR_DEST_DRQ,
DMA_STORE,
DMA_STORE_BYTE_HIGH,
DMA_COMPARE,
DMA_TERMINATE
};
};
// device type definition
extern const device_type I8089_CHANNEL;
#endif /* __I8089_CHANNEL_H__ */

View File

@ -0,0 +1,174 @@
/***************************************************************************
Intel 8089 I/O Processor
Disassembler
Note: Incomplete
***************************************************************************/
#include "emu.h"
INT16 displacement(offs_t &pc, int wb, const UINT8 *oprom)
{
INT16 result = 0;
switch (wb)
{
case 1:
return oprom[2];
pc += 1;
break;
case 2:
return oprom[2] | (oprom[3] << 8);
pc += 2;
break;
}
return result;
}
void offset(char *buffer, offs_t &pc, int aa, int mm, const UINT8 *oprom)
{
const char *mm_name[] = { "ga", "gb", "gc", "pp" };
switch (aa)
{
case 0: sprintf(buffer, "[%s]", mm_name[mm]); break;
case 1: sprintf(buffer, "[%s].%x", mm_name[mm], oprom[2]); pc++; break;
case 2: sprintf(buffer, "[%s+ix]", mm_name[mm]); break;
case 3: sprintf(buffer, "[%s+ix+]", mm_name[mm]); break;
}
}
UINT8 imm8(offs_t &pc, const UINT8 *oprom)
{
pc += 1;
return oprom[2];
}
UINT16 imm16(offs_t &pc, const UINT8 *oprom)
{
pc += 2;
return oprom[2] | (oprom[3] << 8);
}
#define BRP brp_name[brp]
#define SDISP displacement(pc, wb, oprom)
#define OFFSET(x) offset(x, pc, aa, mm, oprom)
#define IMM8 imm8(pc, oprom)
#define IMM16 imm16(pc, oprom)
CPU_DISASSEMBLE( i8089 )
{
const char *brp_name[] = { "ga", "gb", "gc", "bc", "tp", "ix", "cc", "mc" };
UINT32 flags = 0;
offs_t ppc = pc;
// temporary storage
char o[10], o2[10];
memset(o, 0, sizeof(o));
memset(o2, 0, sizeof(o2));
UINT16 off, seg;
// decode instruction
int brp = (oprom[0] >> 5) & 0x07;
int wb = (oprom[0] >> 3) & 0x03;
int aa = (oprom[0] >> 1) & 0x03;
int w = (oprom[0] >> 0) & 0x01;
int opc = (oprom[1] >> 2) & 0x3f;
int mm = (oprom[1] >> 0) & 0x03;
pc += 2;
switch (opc)
{
case 0x00:
switch (brp)
{
case 0: sprintf(buffer, "nop"); break;
case 1: sprintf(buffer, "???"); break;
case 2: sprintf(buffer, "sintr"); break;
case 3: sprintf(buffer, "xfer"); break;
default: sprintf(buffer, "wid %d, %d", BIT(brp, 1) ? 16 : 8, BIT(brp, 0) ? 16 : 8); break;
}
break;
case 0x02:
off = IMM16;
seg = IMM16;
sprintf(buffer, "lpdi %s, %4x %4x", BRP, off, seg);
break;
case 0x08:
if (w) sprintf(buffer, "addi %s, %04x", BRP, IMM16);
else sprintf(buffer, "addbi %s, %02x", BRP, IMM8);
break;
case 0x0a:
if (w) sprintf(buffer, "andi %s, %04x", BRP, IMM16);
else sprintf(buffer, "andbi %s, %02x", BRP, IMM8);
break;
case 0x0c:
if (w) sprintf(buffer, "movi %s, %04x", BRP, IMM16);
else sprintf(buffer, "movbi %s, %02x", BRP, IMM8);
break;
case 0x0f:
sprintf(buffer, "dec %s", BRP);
break;
case 0x12:
sprintf(buffer, "hlt");
break;
case 0x22:
OFFSET(o);
sprintf(buffer, "lpd %s, %s", BRP, o);
break;
case 0x28:
OFFSET(o);
if (w) sprintf(buffer, "add %s, %s", BRP, o);
else sprintf(buffer, "addb %s, %s", BRP, o);
break;
case 0x2a:
OFFSET(o);
if (w) sprintf(buffer, "and %s, %s", BRP, o);
else sprintf(buffer, "andb %s, %s", BRP, o);
break;
case 0x27:
OFFSET(o);
sprintf(buffer, "call %s, %06x", o, ppc + SDISP);
flags = DASMFLAG_STEP_OVER;
break;
case 0x30:
OFFSET(o);
if (w) sprintf(buffer, "addi %s, %04x", o, IMM16);
else sprintf(buffer, "addbi %s, %02x", o, IMM8);
break;
case 0x32:
OFFSET(o);
if (w) sprintf(buffer, "andi %s, %04x", o, IMM16);
else sprintf(buffer, "andbi %s, %02x", o, IMM8);
break;
case 0x34:
OFFSET(o);
if (w) sprintf(buffer, "add %s, %s", o, BRP);
else sprintf(buffer, "addb %s, %s", o, BRP);
break;
case 0x36:
OFFSET(o);
if (w) sprintf(buffer, "and %s, %s", o, BRP);
else sprintf(buffer, "andb %s, %s", o, BRP);
break;
case 0x3b:
OFFSET(o);
if (w) sprintf(buffer, "dec %s", o);
else sprintf(buffer, "decb %s", o);
break;
case 0x3e:
OFFSET(o);
sprintf(buffer, "clr %s, %d", o, brp);
break;
default:
sprintf(buffer, "???");
}
return (pc - ppc) | flags | DASMFLAG_SUPPORTED;
}

View File

@ -0,0 +1,198 @@
/***************************************************************************
Intel 8089 I/O Processor
Opcode implementations
***************************************************************************/
#include "emu.h"
#include "i8089_channel.h"
#define UNIMPLEMENTED logerror("%s('%s'): unimplemented opcode: %s\n", shortname(), tag(), __FUNCTION__);
void i8089_channel::add_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::add_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::addb_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::addb_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::addbi_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::addbi_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::addi_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::addi_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::and_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::and_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::andb_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::andb_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::andbi_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::andbi_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::andi_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::andi_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::call(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::clr(int m, int b, int o) { UNIMPLEMENTED }
void i8089_channel::dec_r(int r) { UNIMPLEMENTED }
void i8089_channel::dec_m(int m, int o) { UNIMPLEMENTED }
void i8089_channel::decb(int m, int o) { UNIMPLEMENTED }
// halt
void i8089_channel::hlt()
{
movbi_mi(CP, 0x00, 1);
m_r[PSW].w &= ~(1 << 2);
}
void i8089_channel::inc_r(int r) { UNIMPLEMENTED }
void i8089_channel::inc_m(int m, int o) { UNIMPLEMENTED }
void i8089_channel::incb(int m, int o) { UNIMPLEMENTED }
void i8089_channel::jbt(int m, int b, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jmce(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jmcne(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jmp(int d) { UNIMPLEMENTED }
void i8089_channel::jnbt(int m, int b, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jnz_r(int r, int d) { UNIMPLEMENTED }
void i8089_channel::jnz_m(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jnzb(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jz_r(int r, int d) { UNIMPLEMENTED }
void i8089_channel::jz_m(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::jzb(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::lcall(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljbt(int m, int b, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljmce(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljmcne(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljmp(int d) { UNIMPLEMENTED }
void i8089_channel::ljnbt(int m, int b, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljnz_r(int r, int d) { UNIMPLEMENTED }
void i8089_channel::ljnz_m(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljnzb(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljz_r(int r, int d) { UNIMPLEMENTED }
void i8089_channel::ljz_m(int m, int d, int o) { UNIMPLEMENTED }
void i8089_channel::ljzb(int m, int d, int o) { UNIMPLEMENTED }
// load pointer from memory
void i8089_channel::lpd(int p, int m, int o)
{
UINT16 offset = m_iop->read_word(m_r[m].w + o);
UINT16 segment = m_iop->read_word(m_r[m].w + o + 2);
set_reg(p, ((segment << 4) + offset) & 0xfffff, 0);
}
// load pointer from immediate data
void i8089_channel::lpdi(int p, int i, int o)
{
set_reg(p, (o << 4) + (i & 0xffff), 0);
}
void i8089_channel::mov_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::mov_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::mov_mm(int m1, int m2, int o1, int o2) { UNIMPLEMENTED }
// move register to memory byte
void i8089_channel::movb_mr(int m, int r, int o)
{
m_iop->write_byte(m_r[m].w + o, m_r[r].w & 0xff);
}
// move memory byte to register
void i8089_channel::movb_rm(int r, int m, int o)
{
UINT8 byte = m_iop->read_byte(m_r[m].w + o);
set_reg(r, (BIT(byte, 7) ? 0xfff00 : 0x00000) | byte, 1);
}
// move memory byte to memory byte
void i8089_channel::movb_mm(int m1, int m2, int o1, int o2)
{
UINT8 byte = m_iop->read_byte(m_r[m2].w + o2);
m_iop->write_byte(m_r[m1].w + o1, byte);
}
// move immediate byte to register
void i8089_channel::movbi_ri(int r, int i)
{
set_reg(r, (BIT(i, 7) ? 0xfff00 : 0x00000) | (i & 0xff), 1);
}
// move immediate byte to memory byte
void i8089_channel::movbi_mi(int m, int i, int o)
{
m_iop->write_byte(m_r[m].w + o, i & 0xff);
}
// move immediate word to register
void i8089_channel::movi_ri(int r, int i)
{
set_reg(r, (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff), 1);
}
// move immediate word to memory word
void i8089_channel::movi_mi(int m, int i, int o)
{
m_iop->write_word(m_r[m].w + o, (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff));
}
// move pointer to memory (store)
void i8089_channel::movp_mp(int m, int p, int o)
{
m_iop->write_word(m_r[m].w + o, m_r[p].w & 0xffff);
m_iop->write_word(m_r[m].w + o + 2, (m_r[p].w >> 12 & 0xf0) | (m_r[p].t << 3 & 0x01));
}
// move memory to pointer (restore)
void i8089_channel::movp_pm(int p, int m, int o)
{
UINT16 offset = m_iop->read_word(m_r[m].w + o);
UINT16 segment = m_iop->read_word(m_r[m].w + o + 2);
set_reg(p, ((segment << 4) + offset) & 0xfffff, segment >> 3 & 0x01);
}
// no operation
void i8089_channel::nop()
{
}
void i8089_channel::not_r(int r) { UNIMPLEMENTED }
void i8089_channel::not_m(int m, int o) { UNIMPLEMENTED }
void i8089_channel::not_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::notb_m(int m, int o) { UNIMPLEMENTED }
void i8089_channel::notb_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::or_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::or_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::orb_rm(int r, int m, int o) { UNIMPLEMENTED }
void i8089_channel::orb_mr(int m, int r, int o) { UNIMPLEMENTED }
void i8089_channel::orbi_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::orbi_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::ori_ri(int r, int i) { UNIMPLEMENTED }
void i8089_channel::ori_mi(int m, int i, int o) { UNIMPLEMENTED }
void i8089_channel::setb(int m, int b, int o) { UNIMPLEMENTED }
// set interrupt service flip-flop
void i8089_channel::sintr()
{
if (BIT(m_r[PSW].w, 4))
{
m_r[PSW].w |= 1 << 5;
m_write_sintr(1);
}
}
void i8089_channel::tsl(int m, int i, int d, int o) { UNIMPLEMENTED }
// set source and destination logical widths
void i8089_channel::wid(int s, int d)
{
m_r[PSW].w &= 0x3f;
m_r[PSW].w |= d << 0;
m_r[PSW].w |= s << 1;
}
// enter dma transfer mode after next instruction
void i8089_channel::xfer()
{
m_xfer_pending = true;
}
void i8089_channel::invalid(int opc)
{
logerror("%s('%s'): invalid opcode: %02x\n", shortname(), tag(), opc);
}

File diff suppressed because it is too large Load Diff

View File

@ -465,15 +465,6 @@ ifneq ($(filter I2CMEM,$(MACHINES)),)
MACHINEOBJS += $(MACHINEOBJ)/i2cmem.o
endif
#-------------------------------------------------
#
#@src/emu/machine/i8089.h,MACHINES += I8089
#-------------------------------------------------
ifneq ($(filter I8089,$(MACHINES)),)
MACHINEOBJS += $(MACHINEOBJ)/i8089.o
endif
#-------------------------------------------------
#
#@src/emu/machine/i8155.h,MACHINES += I8155

View File

@ -2,15 +2,15 @@
ACT Apricot PC/Xi
- Needs Intel 8089 support (I/O processor)
- Error 29 (timer failed)
- Dump of the keyboard MCU ROM needed (can be dumped using test mode)
***************************************************************************/
#include "emu.h"
#include "cpu/i86/i86.h"
#include "cpu/i8089/i8089.h"
#include "machine/ram.h"
#include "machine/i8089.h"
#include "machine/pit8253.h"
#include "machine/i8255.h"
#include "machine/pic8259.h"
@ -24,16 +24,16 @@
#include "formats/apridisk.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class apricot_state : public driver_device
{
public:
apricot_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
apricot_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_cpu(*this, "ic91"),
m_ram(*this, RAM_TAG),
m_iop(*this, "ic71"),
m_sn(*this, "ic7"),
@ -55,7 +55,7 @@ public:
m_display_enabled(0)
{ }
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_cpu;
required_device<ram_device> m_ram;
required_device<i8089_device> m_iop;
required_device<sn76489_device> m_sn;
@ -101,9 +101,9 @@ public:
};
/***************************************************************************
I/O
***************************************************************************/
//**************************************************************************
// I/O
//**************************************************************************
WRITE8_MEMBER( apricot_state::i8089_ca1_w )
{
@ -136,7 +136,7 @@ WRITE8_MEMBER( apricot_state::apricot_sysctrl_w )
if (!BIT(data, 5))
m_fdc->set_floppy(BIT(data, 6) ? m_floppy1->get_device() : m_floppy0->get_device());
/* switch video modes */
// switch video modes
m_crtc->set_clock( m_video_mode ? XTAL_15MHz / 10 : XTAL_15MHz / 16);
m_crtc->set_hpixels_per_column( m_video_mode ? 10 : 16);
}
@ -229,9 +229,9 @@ static const centronics_interface apricot_centronics_intf =
};
/***************************************************************************
FLOPPY
***************************************************************************/
//**************************************************************************
// FLOPPY
//**************************************************************************
void apricot_state::wd2793_intrq_w(bool state)
{
@ -250,9 +250,9 @@ static SLOT_INTERFACE_START( apricot_floppies )
SLOT_INTERFACE_END
/***************************************************************************
VIDEO EMULATION
***************************************************************************/
//**************************************************************************
// VIDEO EMULATION
//**************************************************************************
UINT32 apricot_state::screen_update_apricot(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
@ -272,7 +272,7 @@ static MC6845_UPDATE_ROW( apricot_update_row )
if (state->m_video_mode)
{
/* text mode */
// text mode
for (i = 0; i < x_count; i++)
{
UINT16 code = state->m_screen_buffer[(ma + i) & 0x7ff];
@ -280,21 +280,21 @@ static MC6845_UPDATE_ROW( apricot_update_row )
UINT16 data = ram[offset + 1] << 8 | ram[offset];
int fill = 0;
if (BIT(code, 12) && BIT(data, 14)) fill = 1; /* strike-through? */
if (BIT(code, 13) && BIT(data, 15)) fill = 1; /* underline? */
if (BIT(code, 12) && BIT(data, 14)) fill = 1; // strike-through?
if (BIT(code, 13) && BIT(data, 15)) fill = 1; // underline?
/* draw 10 pixels of the character */
// draw 10 pixels of the character
for (x = 0; x <= 10; x++)
{
int color = fill ? 1 : BIT(data, x);
if (BIT(code, 15)) color = !color; /* reverse? */
if (BIT(code, 15)) color = !color; // reverse?
bitmap.pix32(y, x + i*10) = RGB_MONOCHROME_GREEN_HIGHLIGHT[color ? 1 + BIT(code, 14) : 0];
}
}
}
else
{
/* graphics mode */
// graphics mode
fatalerror("Graphics mode not implemented!\n");
}
}
@ -314,15 +314,20 @@ static MC6845_INTERFACE( apricot_mc6845_intf )
};
/***************************************************************************
MACHINE EMULATION
***************************************************************************/
//**************************************************************************
// MACHINE EMULATION
//**************************************************************************
void apricot_state::machine_start()
{
m_maincpu->space(AS_PROGRAM).install_ram(0x00000, m_ram->size() - 1, m_ram->pointer());
m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(apricot_state::irq_callback), this));
// install shared memory to the main cpu and the iop
m_cpu->space(AS_PROGRAM).install_ram(0x00000, m_ram->size() - 1, m_ram->pointer());
m_iop->space(AS_PROGRAM).install_ram(0x00000, m_ram->size() - 1, m_ram->pointer());
// setup interrupt acknowledge callback for the main cpu
m_cpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(apricot_state::irq_callback), this));
// setup floppy disk controller callbacks
m_fdc->setup_intrq_cb(wd2793_t::line_cb(FUNC(apricot_state::wd2793_intrq_w), this));
m_fdc->setup_drq_cb(wd2793_t::line_cb(FUNC(apricot_state::wd2793_drq_w), this));
@ -332,9 +337,9 @@ void apricot_state::machine_start()
}
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
//**************************************************************************
// ADDRESS MAPS
//**************************************************************************
static ADDRESS_MAP_START( apricot_mem, AS_PROGRAM, 16, apricot_state )
// AM_RANGE(0x00000, 0x3ffff) AM_RAMBANK("standard_ram")
@ -354,13 +359,13 @@ static ADDRESS_MAP_START( apricot_io, AS_IO, 16, apricot_state )
AM_RANGE(0x6a, 0x6b) AM_MIRROR(0x04) AM_DEVREADWRITE8("ic30", mc6845_device, register_r, register_w, 0x00ff)
AM_RANGE(0x70, 0x71) AM_MIRROR(0x04) AM_WRITE8(i8089_ca1_w, 0x00ff)
AM_RANGE(0x72, 0x73) AM_MIRROR(0x04) AM_WRITE8(i8089_ca2_w, 0x00ff)
AM_RANGE(0x78, 0x7f) AM_NOP /* unavailable */
AM_RANGE(0x78, 0x7f) AM_NOP // unavailable
ADDRESS_MAP_END
/***************************************************************************
MACHINE DRIVERS
***************************************************************************/
//**************************************************************************
// MACHINE DRIVERS
//**************************************************************************
static const sn76496_config psg_intf =
{
@ -368,11 +373,16 @@ static const sn76496_config psg_intf =
};
static MACHINE_CONFIG_START( apricot, apricot_state )
MCFG_CPU_ADD("maincpu", I8086, XTAL_15MHz / 3)
// main cpu
MCFG_CPU_ADD("ic91", I8086, XTAL_15MHz / 3)
MCFG_CPU_PROGRAM_MAP(apricot_mem)
MCFG_CPU_IO_MAP(apricot_io)
MCFG_I8089_ADD("ic71", XTAL_15MHz / 3, "maincpu")
// i/o cpu
MCFG_CPU_ADD("ic71", I8089, XTAL_15MHz / 3)
MCFG_CPU_PROGRAM_MAP(apricot_mem)
MCFG_CPU_IO_MAP(apricot_io)
MCFG_I8089_DATABUS_WIDTH(16)
MCFG_I8089_SINTR1(DEVWRITELINE("ic31", pic8259_device, ir0_w))
MCFG_I8089_SINTR2(DEVWRITELINE("ic31", pic8259_device, ir1_w))
@ -383,6 +393,8 @@ static MACHINE_CONFIG_START( apricot, apricot_state )
MCFG_SCREEN_REFRESH_RATE(72)
MCFG_SCREEN_UPDATE_DRIVER(apricot_state, screen_update_apricot)
MCFG_MC6845_ADD("ic30", MC6845, "screen", XTAL_15MHz / 10, apricot_mc6845_intf)
// sound hardware
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ic7", SN76489, XTAL_4MHz / 2)
@ -392,12 +404,11 @@ static MACHINE_CONFIG_START( apricot, apricot_state )
// internal ram
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("256k")
MCFG_RAM_EXTRA_OPTIONS("384k,512k") /* with 1 or 2 128k expansion boards */
MCFG_RAM_EXTRA_OPTIONS("384k,512k") // with 1 or 2 128k expansion boards
// devices
MCFG_MC6845_ADD("ic30", MC6845, "screen", XTAL_15MHz / 10, apricot_mc6845_intf)
MCFG_I8255A_ADD("ic17", apricot_i8255a_intf)
MCFG_PIC8259_ADD("ic31", INPUTLINE("maincpu", 0), VCC, NULL)
MCFG_PIC8259_ADD("ic31", INPUTLINE("ic91", 0), VCC, NULL)
MCFG_PIT8253_ADD("ic16", apricot_pit8253_intf)
MCFG_Z80SIO0_ADD("ic15", XTAL_15MHz / 6, apricot_z80sio_intf)
@ -417,9 +428,9 @@ static MACHINE_CONFIG_DERIVED( apricotxi, apricot )
MACHINE_CONFIG_END
/***************************************************************************
ROM DEFINITIONS
***************************************************************************/
//**************************************************************************
// ROM DEFINITIONS
//**************************************************************************
ROM_START( apricot )
ROM_REGION(0x4000, "bootstrap", 0)
@ -429,15 +440,15 @@ ROM_END
ROM_START( apricotxi )
ROM_REGION(0x4000, "bootstrap", 0)
ROM_LOAD16_BYTE("lo_ve007.u11", 0x0000, 0x2000, CRC(e74e14d1) SHA1(569133b0266ce3563b21ae36fa5727308797deee)) /* LO Ve007 03.04.84 */
ROM_LOAD16_BYTE("hi_ve007.u9", 0x0001, 0x2000, CRC(b04fb83e) SHA1(cc2b2392f1b4c04bb6ec8ee26f8122242c02e572)) /* HI Ve007 03.04.84 */
ROM_LOAD16_BYTE("lo_ve007.u11", 0x0000, 0x2000, CRC(e74e14d1) SHA1(569133b0266ce3563b21ae36fa5727308797deee)) // LO Ve007 03.04.84
ROM_LOAD16_BYTE("hi_ve007.u9", 0x0001, 0x2000, CRC(b04fb83e) SHA1(cc2b2392f1b4c04bb6ec8ee26f8122242c02e572)) // HI Ve007 03.04.84
ROM_END
/***************************************************************************
GAME DRIVERS
***************************************************************************/
//**************************************************************************
// GAME DRIVERS
//**************************************************************************
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1983, apricot, 0, 0, apricot, 0, driver_device, 0, "ACT", "Apricot PC", GAME_NOT_WORKING )
COMP( 1984, apricotxi, apricot, 0, apricotxi, 0, driver_device, 0, "ACT", "Apricot Xi", GAME_NOT_WORKING )

View File

@ -27,6 +27,7 @@ include $(SRC)/mess/messcore.mak
CPUS += Z80
CPUS += Z180
CPUS += I8085
CPUS += I8089
CPUS += M6502
CPUS += H6280
CPUS += I86

View File

@ -131,6 +131,7 @@ CPU_DISASSEMBLE( i8008 );
CPU_DISASSEMBLE( i8051 );
CPU_DISASSEMBLE( i8052 );
CPU_DISASSEMBLE( i8085 );
CPU_DISASSEMBLE( i8089 );
CPU_DISASSEMBLE( i80c51 );
CPU_DISASSEMBLE( i80c52 );
CPU_DISASSEMBLE( i860 );
@ -275,6 +276,7 @@ static const dasm_table_entry dasm_table[] =
{ "i8051", _8bit, 0, CPU_DISASSEMBLE_NAME(i8051) },
{ "i8052", _8bit, 0, CPU_DISASSEMBLE_NAME(i8052) },
{ "i8085", _8bit, 0, CPU_DISASSEMBLE_NAME(i8085) },
{ "i8089", _8bit, 0, CPU_DISASSEMBLE_NAME(i8089) },
{ "i80c51", _8bit, 0, CPU_DISASSEMBLE_NAME(i80c51) },
{ "i80c52", _8bit, 0, CPU_DISASSEMBLE_NAME(i80c52) },
{ "i860", _64le, 0, CPU_DISASSEMBLE_NAME(i860) },