(mess) mcs96: First (incomplete) stab at a core [O. Galibert]

This commit is contained in:
Olivier Galibert 2012-12-17 23:19:50 +00:00
parent b6fe84c927
commit 73e4eb26eb
10 changed files with 3539 additions and 1 deletions

View File

@ -701,6 +701,43 @@ $(CPUOBJ)/mcs51/mcs51.o: $(CPUSRC)/mcs51/mcs51.c \
$(CPUSRC)/mcs51/mcs51.h \
$(CPUSRC)/mcs51/mcs51ops.c
#-------------------------------------------------
# Intel MCS-96
#-------------------------------------------------
ifneq ($(filter MCS96,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/mcs96
CPUOBJS += $(CPUOBJ)/mcs96/mcs96.o \
$(CPUOBJ)/mcs96/i8x9x.o \
$(CPUOBJ)/mcs96/i8xc196.o
endif
$(CPUOBJ)/mcs96/mcs96.o: $(CPUOBJ)/mcs96/mcs96.inc \
$(CPUSRC)/mcs96/mcs96.c \
$(CPUSRC)/mcs96/mcs96.h
$(CPUOBJ)/mcs96/i8x9x.o: $(CPUOBJ)/mcs96/i8x9x.inc \
$(CPUSRC)/mcs96/i8x9x.c \
$(CPUSRC)/mcs96/i8x9x.h \
$(CPUSRC)/mcs96/mcs96.h
$(CPUOBJ)/mcs96/i8xc196.o: $(CPUOBJ)/mcs96/i8xc196.inc \
$(CPUSRC)/mcs96/i8xc196.c \
$(CPUSRC)/mcs96/i8xc196.c \
$(CPUSRC)/mcs96/mcs96.h
$(CPUOBJ)/mcs96/mcs96.inc: $(CPUSRC)/mcs96/mcs96make.py $(CPUSRC)/mcs96/mcs96ops.lst
@echo Generating i8x9x source file...
$(PYTHON) $(CPUSRC)/mcs96/mcs96make.py mcs96 $(CPUSRC)/mcs96/mcs96ops.lst $@
$(CPUOBJ)/mcs96/i8x9x.inc: $(CPUSRC)/mcs96/mcs96make.py $(CPUSRC)/mcs96/mcs96ops.lst
@echo Generating i8x9x source file...
$(PYTHON) $(CPUSRC)/mcs96/mcs96make.py i8x9x $(CPUSRC)/mcs96/mcs96ops.lst $@
$(CPUOBJ)/mcs96/i8xc196.inc: $(CPUSRC)/mcs96/mcs96make.py $(CPUSRC)/mcs96/mcs96ops.lst
@echo Generating i8x9x source file...
$(PYTHON) $(CPUSRC)/mcs96/mcs96make.py i8xc196 $(CPUSRC)/mcs96/mcs96ops.lst $@
#-------------------------------------------------
# Intel 80x86 series
#-------------------------------------------------

View File

@ -0,0 +1,396 @@
/***************************************************************************
i8x9x.h
MCS96, 8x9x branch, the original version
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OLIVIER GALIBERT BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#include "emu.h"
#include "i8x9x.h"
i8x9x_device::i8x9x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
mcs96_device(mconfig, type, name, tag, owner, clock, 8),
io_config("io", ENDIANNESS_LITTLE, 16, 16, -1)
{
}
offs_t i8x9x_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
return disasm_generic(buffer, pc, oprom, opram, options, disasm_entries);
}
const address_space_config *i8x9x_device::memory_space_config(address_spacenum spacenum) const
{
return spacenum == AS_PROGRAM ? &program_config : spacenum == AS_IO ? &io_config : NULL;
}
void i8x9x_device::device_start()
{
mcs96_device::device_start();
io = &space(AS_IO);
cycles_scaling = 3;
}
void i8x9x_device::device_reset()
{
mcs96_device::device_reset();
memset(hso_info, 0, sizeof(hso_info));
memset(&hso_cam_hold, 0, sizeof(hso_cam_hold));
hso_command = 0;
hso_time = 0;
base_timer2 = 0;
ios0 = ios1 = ioc0 = ioc1 = 0x00;
ad_result = 0;
ad_done = 0;
sp_stat = 0;
}
void i8x9x_device::commit_hso_cam()
{
for(int i=0; i<8; i++)
if(!hso_info[i].active) {
if(hso_command != 0x18)
logerror("%s: hso cam %02x %04x in slot %d (%04x)\n", tag(), hso_command, hso_time, i, PPC);
hso_info[i].active = true;
hso_info[i].command = hso_command;
hso_info[i].time = hso_time;
internal_update(get_cycle());
return;
}
hso_cam_hold.active = true;
hso_cam_hold.command = hso_command;
hso_cam_hold.time = hso_time;
}
void i8x9x_device::ad_start(UINT64 current_time)
{
ad_result = (io->read_word(2*((ad_command & 7) + A0)) << 6) | 8 | (ad_command & 7);
ad_done = current_time + 88;
internal_update(current_time);
}
void i8x9x_device::serial_send(UINT8 data)
{
serial_send_buf = data;
serial_send_timer = get_cycle() + 9600;
}
void i8x9x_device::serial_send_done()
{
serial_send_timer = 0;
io->write_word(SERIAL*2, serial_send_buf);
pending_irq |= IRQ_SERIAL;
sp_stat |= 0x20;
check_irq();
}
void i8x9x_device::io_w8(UINT8 adr, UINT8 data)
{
switch(adr) {
case 0x02:
ad_command = data;
if(ad_command & 8)
ad_start(get_cycle());
break;
case 0x03:
logerror("%s: hsi_mode %02x (%04x)\n", tag(), data, PPC);
break;
case 0x04:
hso_time = (hso_time & 0xff00) | data;
break;
case 0x05:
hso_time = (hso_time & 0x00ff) | (data << 8);
commit_hso_cam();
break;
case 0x06:
hso_command = data;
break;
case 0x07:
logerror("%s: sbuf %02x (%04x)\n", tag(), data, PPC);
serial_send(data);
break;
case 0x08:
PSW = (PSW & 0xff00) | data;
check_irq();
break;
case 0x09:
pending_irq = data;
logerror("%s: int_pending %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0a:
logerror("%s: watchdog %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0e:
logerror("%s: baud rate %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0f:
logerror("%s: io port 1 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x10:
logerror("%s: io port 2 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x11:
logerror("%s: sp con %02x (%04x)\n", tag(), data, PPC);
break;
case 0x15:
logerror("%s: ioc0 %02x (%04x)\n", tag(), data, PPC);
ioc0 = data;
break;
case 0x16:
logerror("%s: ioc1 %02x (%04x)\n", tag(), data, PPC);
ioc1 = data;
break;
case 0x17:
logerror("%s: pwm control %02x (%04x)\n", tag(), data, PPC);
break;
}
return;
}
void i8x9x_device::io_w16(UINT8 adr, UINT16 data)
{
switch(adr) {
case 0:
break;
case 4:
hso_time = data;
commit_hso_cam();
break;
default:
io_w8(adr, data);
io_w8(adr+1, data>>8);
break;
}
return;
}
UINT8 i8x9x_device::io_r8(UINT8 adr)
{
switch(adr) {
case 0x00:
return 0x00;
case 0x01:
return 0x00;
case 0x02:
return ad_result;
case 0x03:
return ad_result >> 8;
case 0x04:
logerror("%s: read hsi time l (%04x)\n", tag(), PPC);
return 0x00;
case 0x05:
logerror("%s: read hsi time h (%04x)\n", tag(), PPC);
return 0x00;
case 0x06:
logerror("%s: read hsi status (%04x)\n", tag(), PPC);
return 0x00;
case 0x07:
logerror("%s: read sbuf %02x (%04x)\n", tag(), sbuf, PPC);
return sbuf;
case 0x08:
return PSW;
case 0x09:
logerror("%s: read int pending (%04x)\n", tag(), PPC);
return pending_irq;
case 0x0a:
logerror("%s: read timer1 l (%04x)\n", tag(), PPC);
return timer_value(1, get_cycle());
case 0x0b:
logerror("%s: read timer1 h (%04x)\n", tag(), PPC);
return timer_value(1, get_cycle()) >> 8;
case 0x0c:
logerror("%s: read timer2 l (%04x)\n", tag(), PPC);
return timer_value(2, get_cycle());
case 0x0d:
logerror("%s: read timer2 h (%04x)\n", tag(), PPC);
return timer_value(2, get_cycle()) >> 8;
case 0x0e:
logerror("%s: read io port 0 (%04x)\n", tag(), PPC);
return 0x00;
case 0x0f:
logerror("%s: read io port 1 (%04x)\n", tag(), PPC);
return 0x00;
case 0x10:
logerror("%s: read io port 2 (%04x)\n", tag(), PPC);
return 0x00;
case 0x11: {
UINT8 res = sp_stat;
sp_stat &= 0x80;
logerror("%s: read sp stat %02x (%04x)\n", tag(), res, PPC);
return res;
}
case 0x15:
logerror("%s: read ios 0 %02x (%04x)\n", tag(), ios0, PPC);
return ios0;
case 0x16: {
UINT8 res = ios1;
ios1 = ios1 & 0xc0;
return res;
}
default:
logerror("%s: io_r8 %02x (%04x)\n", tag(), adr, PPC);
return 0x00;
}
}
UINT16 i8x9x_device::io_r16(UINT8 adr)
{
switch(adr) {
case 0x00:
return 0x0000;
case 0x02:
return ad_result;
case 0x04:
logerror("%s: read hsi time (%04x)\n", tag(), PPC);
return 0x0000;
case 0x0a:
return timer_value(1, get_cycle());
case 0x0c:
logerror("%s: read timer2 (%04x)\n", tag(), PPC);
return timer_value(2, get_cycle());
default:
return io_r8(adr) | (io_r8(adr+1) << 8);
}
}
void i8x9x_device::do_exec_partial()
{
}
void i8x9x_device::serial_w(UINT8 val)
{
sbuf = val;
sp_stat |= 0x40;
pending_irq |= IRQ_SERIAL;
check_irq();
}
UINT16 i8x9x_device::timer_value(int timer, UINT64 current_time) const
{
if(timer == 2)
current_time -= base_timer2;
return current_time >> 3;
}
UINT64 i8x9x_device::timer_time_until(int timer, UINT64 current_time, UINT16 timer_value) const
{
UINT64 timer_base = timer == 2 ? base_timer2 : 0;
UINT64 delta = (current_time - timer_base) >> 3;
UINT32 tdelta = UINT16(timer_value - delta);
if(!tdelta)
tdelta = 0x10000;
return timer_base + ((delta + tdelta) << 3);
}
void i8x9x_device::trigger_cam(int id, UINT64 current_time)
{
hso_cam_entry &cam = hso_info[id];
cam.active = false;
switch(cam.command & 0x0f) {
case 0x8: case 0x9: case 0xa: case 0xb:
ios1 |= 1 << (cam.command & 3);
pending_irq |= IRQ_SOFT;
check_irq();
break;
default:
logerror("%s: Action %x unimplemented\n", tag(), cam.command & 0x0f);
break;
}
}
void i8x9x_device::internal_update(UINT64 current_time)
{
UINT16 current_timer1 = timer_value(1, current_time);
UINT16 current_timer2 = timer_value(2, current_time);
for(int i=0; i<8; i++)
if(hso_info[i].active) {
UINT8 cmd = hso_info[i].command;
UINT16 t = hso_info[i].time;
if(((cmd & 0x40) && t == current_timer2) ||
(!(cmd & 0x40) && t == current_timer1)) {
if(cmd != 0x18)
logerror("%s: hso cam %02x %04x in slot %d triggered\n",
tag(), cmd, t, i);
trigger_cam(i, current_time);
}
}
if(current_time == ad_done) {
ad_done = 0;
ad_result &= ~8;
}
if(current_time == serial_send_timer)
serial_send_done();
UINT64 event_time = 0;
for(int i=0; i<8; i++) {
if(!hso_info[i].active && hso_cam_hold.active) {
hso_info[i] = hso_cam_hold;
hso_cam_hold.active = false;
logerror("%s: hso cam %02x %04x in slot %d from hold\n", tag(), hso_cam_hold.command, hso_cam_hold.time, i);
}
if(hso_info[i].active) {
UINT64 new_time = timer_time_until(hso_info[i].command & 0x40 ? 2 : 1, current_time, hso_info[i].time);
if(!event_time || new_time < event_time)
event_time = new_time;
}
}
if(ad_done && ad_done < event_time)
event_time = ad_done;
if(serial_send_timer && serial_send_timer < event_time)
event_time = serial_send_timer;
recompute_bcount(event_time);
}
c8095_device::c8095_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
i8x9x_device(mconfig, C8095, "C8095", tag, owner, clock)
{
}
p8098_device::p8098_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
i8x9x_device(mconfig, P8098, "P8098", tag, owner, clock)
{
}
const device_type C8095 = &device_creator<c8095_device>;
const device_type P8098 = &device_creator<p8098_device>;
#include "cpu/mcs96/i8x9x.inc"

View File

@ -0,0 +1,126 @@
/***************************************************************************
i8x9x.h
MCS96, 8x9x branch, the original version
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OLIVIER GALIBERT BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#ifndef __I8X9X_H__
#define __I8X9X_H__
#include "mcs96.h"
class i8x9x_device : public mcs96_device {
public:
enum {
A0, A1, A2, A3, A4, A5, A6, A7,
SERIAL
};
i8x9x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
void serial_w(UINT8 val);
protected:
virtual void device_start();
virtual void device_reset();
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
static const disasm_entry disasm_entries[0x100];
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
virtual void do_exec_full();
virtual void do_exec_partial();
virtual void internal_update(UINT64 current_time);
virtual void io_w8(UINT8 adr, UINT8 data);
virtual void io_w16(UINT8 adr, UINT16 data);
virtual UINT8 io_r8(UINT8 adr);
virtual UINT16 io_r16(UINT8 adr);
private:
enum {
IRQ_TIMER = 0x01,
IRQ_AD = 0x02,
IRQ_HSI = 0x04,
IRQ_HSO = 0x08,
IRQ_HSI0 = 0x10,
IRQ_SOFT = 0x20,
IRQ_SERIAL = 0x40,
IRQ_EXTINT = 0x80
};
struct hso_cam_entry {
bool active;
UINT8 command;
UINT16 time;
};
address_space_config io_config;
address_space *io;
hso_cam_entry hso_info[8];
hso_cam_entry hso_cam_hold;
UINT64 base_timer2, ad_done;
UINT8 hso_command, ad_command;
UINT16 hso_time, ad_result;
UINT8 ios0, ios1, ioc0, ioc1;
UINT8 sbuf, sp_stat;
UINT8 serial_send_buf;
UINT64 serial_send_timer;
UINT16 timer_value(int timer, UINT64 current_time) const;
UINT64 timer_time_until(int timer, UINT64 current_time, UINT16 timer_value) const;
void commit_hso_cam();
void trigger_cam(int id, UINT64 current_time);
void ad_start(UINT64 current_time);
void serial_send(UINT8 data);
void serial_send_done();
};
class c8095_device : public i8x9x_device {
public:
c8095_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
class p8098_device : public i8x9x_device {
public:
p8098_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
extern const device_type C8095;
extern const device_type P8098;
#endif

View File

@ -0,0 +1,101 @@
/***************************************************************************
i8xc196.h
MCS96, c196 branch, the enhanced 16 bits bus version
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OLIVIER GALIBERT BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#include "emu.h"
#include "i8xc196.h"
i8xc196_device::i8xc196_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
mcs96_device(mconfig, type, name, tag, owner, clock, 16)
{
}
offs_t i8xc196_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
return disasm_generic(buffer, pc, oprom, opram, options, disasm_entries);
}
void i8xc196_device::io_w8(UINT8 adr, UINT8 data)
{
switch(adr) {
case 0:
break;
case 1:
break;
default:
logerror("%s: io_w8 %02x, %02x (%04x)\n", tag(), adr, data, PPC);
}
return;
}
void i8xc196_device::io_w16(UINT8 adr, UINT16 data)
{
switch(adr) {
case 0:
break;
default:
io_w8(adr, data);
io_w8(adr+1, data>>8);
break;
}
return;
}
UINT8 i8xc196_device::io_r8(UINT8 adr)
{
switch(adr) {
case 0x00:
return 0x00;
case 0x01:
return 0x00;
}
UINT8 data = 0x00;
logerror("%s: io_r8 %02x, %02x (%04x)\n", tag(), adr, data, PPC);
return data;
}
UINT16 i8xc196_device::io_r16(UINT8 adr)
{
if(adr < 2)
return 0x0000;
UINT16 data = 0x0000;
logerror("%s: io_r16 %02x, %04x (%04x)\n", tag(), adr, data, PPC);
return data;
}
#include "cpu/mcs96/i8xc196.inc"

View File

@ -0,0 +1,75 @@
/***************************************************************************
i8xc196.h
MCS96, c196 branch, the enhanced 16 bits bus version
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OLIVIER GALIBERT BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#ifndef __I8XC196_H__
#define __I8XC196_H__
#include "mcs96.h"
class i8xc196_device : public mcs96_device {
public:
i8xc196_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
static const disasm_entry disasm_entries[0x100];
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
virtual void do_exec_full();
virtual void do_exec_partial();
virtual void next(int cycles);
virtual void io_w8(UINT8 adr, UINT8 data);
virtual void io_w16(UINT8 adr, UINT16 data);
virtual UINT8 io_r8(UINT8 adr);
virtual UINT16 io_r16(UINT8 adr);
#define O(o) void o ## _196_full(); void o ## _196_partial()
O(bmov_direct_2);
O(cmpl_direct_2);
O(bmovi_direct_2);
O(pop_indirect_1);
O(pop_indexed_1);
O(djnzw_rrel8);
O(pusha_none);
O(idlpd_none);
#undef O
};
#endif

View File

@ -0,0 +1,713 @@
/***************************************************************************
mcs96.h
MCS96, 8098/8398/8798 branch
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#include "emu.h"
#include "debugger.h"
#include "mcs96.h"
mcs96_device::mcs96_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int data_width) :
cpu_device(mconfig, type, name, tag, owner, clock),
program_config("program", ENDIANNESS_LITTLE, data_width, 16)
{
}
void mcs96_device::device_start()
{
program = &space(AS_PROGRAM);
direct = &program->direct();
m_icountptr = &icount;
state_add(STATE_GENPC, "GENPC", PC).noshow();
state_add(STATE_GENPCBASE, "GENPCBASE", PPC).noshow();
state_add(STATE_GENSP, "GENSP", R[0]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", PSW).formatstr("%16s").noshow();
state_add(MCS96_PC, "PC", PC);
state_add(MCS96_PSW, "PSW", PSW);
state_add(MCS96_R, "SP", R[0]);
for(int i=1; i<0x74; i++) {
char buf[10];
sprintf(buf, "R%02x", i*2+0x18);
state_add(MCS96_R+i, buf, R[i]);
}
memset(R, 0, sizeof(R));
}
void mcs96_device::device_reset()
{
PC = 0x2080;
PPC = PC;
PSW = 0;
pending_irq = 0x00;
irq_requested = false;
inst_state = STATE_FETCH;
}
UINT32 mcs96_device::execute_min_cycles() const
{
return 4;
}
UINT32 mcs96_device::execute_max_cycles() const
{
return 33;
}
UINT32 mcs96_device::execute_input_lines() const
{
return 1;
}
UINT64 mcs96_device::get_cycle()
{
return end_cycles == 0 || icount <= 0 ? machine().time().as_ticks(clock()) : end_cycles - icount;
}
void mcs96_device::recompute_bcount(UINT64 event_time)
{
if(!event_time || event_time >= end_cycles) {
bcount = 0;
return;
}
bcount = end_cycles - event_time;
}
void mcs96_device::check_irq()
{
irq_requested = (PSW & pending_irq) && (PSW & F_I);
}
void mcs96_device::execute_run()
{
UINT64 start_cycles = machine().time().as_ticks(clock());
end_cycles = start_cycles + icount;
internal_update(start_cycles);
if(/*inst_substate*/ 0)
do_exec_partial();
while(icount > 0) {
while(icount > bcount) {
int picount = inst_state >= 0x200 ? -1 : icount;
do_exec_full();
if(icount == picount) {
fprintf(stderr, "Unhandled %x (%04x)\n", inst_state, PPC);
exit(0);
}
}
while(bcount && icount <= bcount)
internal_update(end_cycles - bcount);
}
end_cycles = 0;
}
void mcs96_device::execute_set_input(int inputnum, int state)
{
switch(inputnum) {
}
}
const address_space_config *mcs96_device::memory_space_config(address_spacenum spacenum) const
{
return (spacenum == AS_PROGRAM) ? &program_config : NULL;
}
void mcs96_device::state_import(const device_state_entry &entry)
{
}
void mcs96_device::state_export(const device_state_entry &entry)
{
}
void mcs96_device::state_string_export(const device_state_entry &entry, astring &string)
{
switch(entry.index()) {
case STATE_GENFLAGS:
case MCS96_PSW:
string.printf("%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
PSW & F_Z ? 'Z' : '.',
PSW & F_N ? 'N' : '.',
PSW & F_V ? 'V' : '.',
PSW & F_VT ? 'v' : '.',
PSW & F_C ? 'C' : '.',
PSW & F_I ? 'I' : '.',
PSW & F_ST ? 'S' : '.',
PSW & 0x80 ? '7' : '.',
PSW & 0x40 ? '6' : '.',
PSW & 0x20 ? '5' : '.',
PSW & 0x10 ? '4' : '.',
PSW & 0x08 ? '3' : '.',
PSW & 0x04 ? '2' : '.',
PSW & 0x02 ? '1' : '.',
PSW & 0x01 ? '0' : '.');
break;
}
}
astring mcs96_device::regname(UINT8 reg)
{
char res[32];
switch(reg) {
case 0x18:
strcpy(res, "sp");
break;
case 0x19:
strcpy(res, "sph");
break;
default:
sprintf(res, "%02x", reg);
break;
}
return res;
}
offs_t mcs96_device::disasm_generic(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options, const disasm_entry *entries)
{
bool prefix_fe = false;
int off = 0;
if(oprom[0] == 0xfe && entries[oprom[1]].opcode_fe) {
prefix_fe = true;
pc++;
off++;
oprom++;
}
const disasm_entry &e = entries[oprom[0]];
UINT32 flags = e.flags | DASMFLAG_SUPPORTED;
buffer += sprintf(buffer, "%s", prefix_fe ? e.opcode_fe : e.opcode);
switch(e.mode) {
case DASM_none:
flags |= 1;
break;
case DASM_nop_2:
sprintf(buffer, " %02x", oprom[1]);
flags |= 2;
break;
case DASM_rel8: {
int delta = oprom[1];
if(delta & 0x80)
delta -= 0x100;
sprintf(buffer, " %04x", (pc+2+delta) & 0xffff);
flags |= 2;
break;
}
case DASM_rel11: {
int delta = ((oprom[0] << 8) | oprom[1]) & 0x7ff;
if(delta & 0x400)
delta -= 0x800;
sprintf(buffer, " %04x", (pc+2+delta) & 0xffff);
flags |= 2;
break;
}
case DASM_rel16: {
int delta = oprom[1] | (oprom[2] << 8);
sprintf(buffer, " %04x", (pc+3+delta) & 0xffff);
flags |= 3;
break;
}
case DASM_rrel8: {
int delta = oprom[2];
if(delta & 0x80)
delta -= 0x100;
sprintf(buffer, " %s, %04x", regname(oprom[1]).cstr(), (pc+3+delta) & 0xffff);
flags |= 3;
break;
}
case DASM_brrel8: {
int delta = oprom[2];
if(delta & 0x80)
delta -= 0x100;
sprintf(buffer, " %d, %s, %04x", oprom[0] & 7, regname(oprom[1]).cstr(), (pc+3+delta) & 0xffff);
flags |= 3;
break;
}
case DASM_direct_1:
sprintf(buffer, " %s", regname(oprom[1]).cstr());
flags |= 2;
break;
case DASM_direct_2:
sprintf(buffer, " %s, %s", regname(oprom[2]).cstr(), regname(oprom[1]).cstr());
flags |= 3;
break;
case DASM_direct_3:
sprintf(buffer, " %s, %s, %s", regname(oprom[3]).cstr(), regname(oprom[2]).cstr(), regname(oprom[1]).cstr());
flags |= 4;
break;
case DASM_immed_1b:
sprintf(buffer, " #%02x", oprom[1]);
flags |= 2;
break;
case DASM_immed_2b:
sprintf(buffer, " %s, #%02x", regname(oprom[2]).cstr(), oprom[1]);
flags |= 3;
break;
case DASM_immed_3b:
sprintf(buffer, " %s, %s, #%02x", regname(oprom[3]).cstr(), regname(oprom[2]).cstr(), oprom[1]);
flags |= 4;
break;
case DASM_immed_1w:
sprintf(buffer, " #%02x%02x", oprom[2], oprom[1]);
flags |= 3;
break;
case DASM_immed_2w:
sprintf(buffer, " %s, #%02x%02x", regname(oprom[3]).cstr(), oprom[2], oprom[1]);
flags |= 4;
break;
case DASM_immed_3w:
sprintf(buffer, " %s, %s, #%02x%02x", regname(oprom[4]).cstr(), regname(oprom[3]).cstr(), oprom[2], oprom[1]);
flags |= 5;
break;
case DASM_indirect_1n:
sprintf(buffer, " [%s]", regname(oprom[1]).cstr());
flags |= 2;
break;
case DASM_indirect_1:
if(oprom[1] & 0x01) {
sprintf(buffer, " [%s]+", regname(oprom[1]-1).cstr());
flags |= 2;
} else {
sprintf(buffer, " [%s]", regname(oprom[1]).cstr());
flags |= 2;
}
break;
case DASM_indirect_2:
if(oprom[1] & 0x01) {
sprintf(buffer, " %s, [%s]+", regname(oprom[2]).cstr(), regname(oprom[1]-1).cstr());
flags |= 3;
} else {
sprintf(buffer, " %s, [%s]", regname(oprom[2]).cstr(), regname(oprom[1]).cstr());
flags |= 3;
}
break;
case DASM_indirect_3:
if(oprom[1] & 0x01) {
sprintf(buffer, " %s, %s, [%s]+", regname(oprom[3]).cstr(), regname(oprom[2]).cstr(), regname(oprom[1]-1).cstr());
flags |= 4;
} else {
sprintf(buffer, " %s, %s, [%s]", regname(oprom[3]).cstr(), regname(oprom[2]).cstr(), regname(oprom[1]).cstr());
flags |= 4;
}
break;
case DASM_indexed_1:
if(oprom[1] & 0x01) {
if(oprom[1] == 0x01)
sprintf(buffer, " %02x%02x", oprom[3], oprom[2]);
else
sprintf(buffer, " %02x%02x[%s]", oprom[3], oprom[2], regname(oprom[1]-1).cstr());
flags |= 4;
} else {
int delta = oprom[2];
if(delta & 0x80)
delta -= 0x100;
if(oprom[1] == 0x00) {
if(delta < 0)
sprintf(buffer, " %04x", delta & 0xffff);
else
sprintf(buffer, " %02x", delta);
} else {
if(delta < 0)
sprintf(buffer, " -%02x[%s]", -delta, regname(oprom[1]-1).cstr());
else
sprintf(buffer, " %02x[%s]", delta, regname(oprom[1]-1).cstr());
}
flags |= 3;
}
break;
case DASM_indexed_2:
if(oprom[1] & 0x01) {
if(oprom[1] == 0x01)
sprintf(buffer, " %s, %02x%02x", regname(oprom[4]).cstr(), oprom[3], oprom[2]);
else
sprintf(buffer, " %s, %02x%02x[%s]", regname(oprom[4]).cstr(), oprom[3], oprom[2], regname(oprom[1]-1).cstr());
flags |= 5;
} else {
int delta = oprom[2];
if(delta & 0x80)
delta -= 0x100;
if(oprom[1] == 0x00) {
if(delta < 0)
sprintf(buffer, " %s, %04x", regname(oprom[3]).cstr(), delta & 0xffff);
else
sprintf(buffer, " %s, %02x", regname(oprom[3]).cstr(), delta);
} else {
if(delta < 0)
sprintf(buffer, " %s, -%02x[%s]", regname(oprom[3]).cstr(), -delta, regname(oprom[1]-1).cstr());
else
sprintf(buffer, " %s, %02x[%s]", regname(oprom[3]).cstr(), delta, regname(oprom[1]-1).cstr());
}
flags |= 4;
}
break;
case DASM_indexed_3:
if(oprom[1] & 0x01) {
if(oprom[1] == 0x01)
sprintf(buffer, " %s, %s, %02x%02x", regname(oprom[5]).cstr(), regname(oprom[4]).cstr(), oprom[3], oprom[2]);
else
sprintf(buffer, " %s, %s, %02x%02x[%s]", regname(oprom[5]).cstr(), regname(oprom[4]).cstr(), oprom[3], oprom[2], regname(oprom[1]-1).cstr());
flags |= 6;
} else {
int delta = oprom[2];
if(delta & 0x80)
delta -= 0x100;
if(oprom[1] == 0x00) {
if(delta < 0)
sprintf(buffer, " %s, %s, %04x", regname(oprom[4]).cstr(), regname(oprom[3]).cstr(), delta & 0xffff);
else
sprintf(buffer, " %s, %s, %02x", regname(oprom[4]).cstr(), regname(oprom[3]).cstr(), delta);
} else {
if(delta < 0)
sprintf(buffer, " %s, %s, -%02x[%s]", regname(oprom[4]).cstr(), regname(oprom[3]).cstr(), -delta, regname(oprom[1]-1).cstr());
else
sprintf(buffer, " %s, %s, %02x[%s]", regname(oprom[4]).cstr(), regname(oprom[3]).cstr(), delta, regname(oprom[1]-1).cstr());
}
flags |= 5;
}
break;
default:
fprintf(stderr, "Unhandled dasm mode %d\n", e.mode);
abort();
};
return flags+off;
}
UINT32 mcs96_device::disasm_min_opcode_bytes() const
{
return 1;
}
UINT32 mcs96_device::disasm_max_opcode_bytes() const
{
return 7;
}
void mcs96_device::io_w8(UINT8 adr, UINT8 data)
{
switch(adr) {
case 0x02:
logerror("%s: ad_command %02x (%04x)\n", tag(), data, PPC);
break;
case 0x03:
logerror("%s: hsi_mode %02x (%04x)\n", tag(), data, PPC);
break;
case 0x04:
logerror("%s: hso_time.l %02x (%04x)\n", tag(), data, PPC);
break;
case 0x05:
logerror("%s: hso_time.h %02x (%04x)\n", tag(), data, PPC);
break;
case 0x06:
logerror("%s: hso_command %02x (%04x)\n", tag(), data, PPC);
break;
case 0x07:
logerror("%s: sbuf %02x (%04x)\n", tag(), data, PPC);
break;
case 0x08:
PSW = (PSW & 0xff00) | data;
break;
case 0x09:
logerror("%s: int_pending %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0a:
logerror("%s: watchdog %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0e:
logerror("%s: baud rate %02x (%04x)\n", tag(), data, PPC);
break;
case 0x0f:
logerror("%s: io port 1 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x10:
logerror("%s: io port 2 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x11:
logerror("%s: sp con %02x (%04x)\n", tag(), data, PPC);
break;
case 0x15:
logerror("%s: ioc0 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x16:
logerror("%s: ioc1 %02x (%04x)\n", tag(), data, PPC);
break;
case 0x17:
logerror("%s: pwm control %02x (%04x)\n", tag(), data, PPC);
break;
}
return;
}
void mcs96_device::io_w16(UINT8 adr, UINT16 data)
{
switch(adr) {
case 0:
break;
case 4:
logerror("%s: hso_time %04x (%04x)\n", tag(), data, PPC);
break;
default:
io_w8(adr, data);
io_w8(adr+1, data>>8);
break;
}
return;
}
UINT8 mcs96_device::io_r8(UINT8 adr)
{
switch(adr) {
case 0x00:
return 0x00;
case 0x01:
return 0x00;
case 0x08:
return PSW;
}
UINT8 data = 0x00;
logerror("%s: io_r8 %02x, %02x (%04x)\n", tag(), adr, data, PPC);
return data;
}
UINT16 mcs96_device::io_r16(UINT8 adr)
{
if(adr < 2)
return 0x0000;
UINT16 data = 0x0000;
logerror("%s: io_r16 %02x, %04x (%04x)\n", tag(), adr, data, PPC);
return data;
}
void mcs96_device::reg_w8(UINT8 adr, UINT8 data)
{
if(adr < 0x18)
io_w8(adr, data);
else {
UINT16 &r = R[(adr - 0x18) >> 1];
if(adr & 0x01)
r = (r & 0x00ff) | (data << 8);
else
r = (r & 0xff00) | data;
}
}
void mcs96_device::reg_w16(UINT8 adr, UINT16 data)
{
adr &= 0xfe;
if(adr < 0x18)
io_w16(adr, data);
else
R[(adr-0x18) >> 1] = data;
}
UINT8 mcs96_device::reg_r8(UINT8 adr)
{
if(adr < 0x18)
return io_r8(adr);
UINT16 data = R[(adr - 0x18) >> 1];
if(adr & 0x01)
return data >> 8;
else
return data;
}
UINT16 mcs96_device::reg_r16(UINT8 adr)
{
adr &= 0xfe;
if(adr < 0x18)
return io_r16(adr);
return R[(adr-0x18) >> 1];
}
void mcs96_device::any_w8(UINT16 adr, UINT8 data)
{
if(adr < 0x18)
io_w8(adr, data);
else if(adr < 0x100) {
UINT16 &r = R[(adr - 0x18) >> 1];
if(adr & 0x01)
r = (r & 0x00ff) | (data << 8);
else
r = (r & 0xff00) | data;
} else
program->write_byte(adr, data);
}
void mcs96_device::any_w16(UINT16 adr, UINT16 data)
{
adr &= 0xfffe;
if(adr < 0x18)
io_w16(adr, data);
else if(adr < 0x100)
R[(adr-0x18) >> 1] = data;
else
program->write_word(adr, data);
}
UINT8 mcs96_device::any_r8(UINT16 adr)
{
if(adr < 0x18)
return io_r8(adr);
else if(adr < 0x100) {
UINT16 data = R[(adr - 0x18) >> 1];
if(adr & 0x01)
return data >> 8;
else
return data;
} else
return program->read_byte(adr);
}
UINT16 mcs96_device::any_r16(UINT16 adr)
{
adr &= 0xfffe;
if(adr < 0x18)
return io_r16(adr);
else if(adr < 0x100)
return R[(adr-0x18) >> 1];
else
return program->read_word(adr);
}
UINT8 mcs96_device::do_addb(UINT8 v1, UINT8 v2)
{
UINT16 sum = v1+v2;
PSW &= ~(F_Z|F_N|F_C|F_V);
if(!UINT8(sum))
PSW |= F_Z;
else if(INT8(sum) < 0)
PSW |= F_N;
if(~(v1^v2) & (v1^sum) & 0x80)
PSW |= F_V|F_VT;
if(sum & 0xff00)
PSW |= F_C;
return sum;
}
UINT16 mcs96_device::do_add(UINT16 v1, UINT16 v2)
{
UINT32 sum = v1+v2;
PSW &= ~(F_Z|F_N|F_C|F_V);
if(!UINT16(sum))
PSW |= F_Z;
else if(INT16(sum) < 0)
PSW |= F_N;
if(~(v1^v2) & (v1^sum) & 0x8000)
PSW |= F_V|F_VT;
if(sum & 0xffff0000)
PSW |= F_C;
return sum;
}
UINT8 mcs96_device::do_subb(UINT8 v1, UINT8 v2)
{
UINT16 diff = v1 - v2;
PSW &= ~(F_N|F_V|F_Z|F_C);
if(!UINT8(diff))
PSW |= F_Z;
else if(INT8(diff) < 0)
PSW |= F_N;
if((v1^v2) & (v1^diff) & 0x80)
PSW |= F_V;
if(!(diff & 0xff00))
PSW |= F_C;
return diff;
}
UINT16 mcs96_device::do_sub(UINT16 v1, UINT16 v2)
{
UINT32 diff = v1 - v2;
PSW &= ~(F_N|F_V|F_Z|F_C);
if(!UINT16(diff))
PSW |= F_Z;
else if(INT16(diff) < 0)
PSW |= F_N;
if((v1^v2) & (v1^diff) & 0x8000)
PSW |= F_V;
if(!(diff & 0xffff0000))
PSW |= F_C;
return diff;
}
void mcs96_device::set_nz8(UINT8 v)
{
PSW &= ~(F_N|F_V|F_Z|F_C);
if(!v)
PSW |= F_Z;
else if(INT8(v) < 0)
PSW |= F_N;
}
void mcs96_device::set_nz16(UINT16 v)
{
PSW &= ~(F_N|F_V|F_Z|F_C);
if(!v)
PSW |= F_Z;
else if(INT16(v) < 0)
PSW |= F_N;
}
#include "cpu/mcs96/mcs96.inc"

View File

@ -0,0 +1,280 @@
/***************************************************************************
mcs96.h
MCS96
****************************************************************************
Copyright Olivier Galibert
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY OLIVIER GALIBERT ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OLIVIER GALIBERT BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#ifndef __MCS96_H__
#define __MCS96_H__
class mcs96_device : public cpu_device {
public:
mcs96_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int data_width);
UINT64 get_cycle();
protected:
enum {
STATE_FETCH = 0x200,
STATE_FETCH_NOIRQ = 0x201,
};
enum {
F_ST = 0x0100,
F_I = 0x0200,
F_C = 0x0800,
F_VT = 0x1000,
F_V = 0x2000,
F_N = 0x4000,
F_Z = 0x8000,
};
struct disasm_entry {
const char *opcode, *opcode_fe;
int mode;
offs_t flags;
};
enum {
DASM_none, /* No parameters */
DASM_nop_2, /* One ignored parameter byte */
DASM_rel8, /* Relative, 8 bits */
DASM_rel11, /* Relative, 11 bits */
DASM_rel16, /* Relative, 16 bits */
DASM_rrel8, /* Register + relative, 8 bits */
DASM_brrel8, /* Bit test + register + relative, 8 bits */
DASM_direct_1, /* Register-direct references, 1 operator */
DASM_direct_2, /* Register-direct references, 2 operators */
DASM_direct_3, /* Register-direct references, 3 operators */
DASM_immed_1b, /* Immediate references to byte, 1 operator */
DASM_immed_2b, /* Immediate references to byte, 2 operators */
DASM_immed_3b, /* Immediate references to byte, 3 operators */
DASM_immed_1w, /* Immediate references to word, 1 operator */
DASM_immed_2w, /* Immediate references to word, 2 operators */
DASM_immed_3w, /* Immediate references to word, 3 operators */
DASM_indirect_1n, /* Indirect normal, 1 operator */
DASM_indirect_1, /* Indirect, normal or auto-incrementing, 1 operator */
DASM_indirect_2, /* Indirect, normal or auto-incrementing, 2 operators */
DASM_indirect_3, /* Indirect, normal or auto-incrementing, 3 operators */
DASM_indexed_1, /* Indexed, short or long, 1 operator */
DASM_indexed_2, /* Indexed, short or long, 2 operators */
DASM_indexed_3, /* Indexed, short or long, 3 operators */
};
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_execute_interface overrides
virtual UINT32 execute_min_cycles() const;
virtual UINT32 execute_max_cycles() const;
virtual UINT32 execute_input_lines() const;
virtual void execute_run();
virtual void execute_set_input(int inputnum, int state);
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
// device_state_interface overrides
virtual void state_import(const device_state_entry &entry);
virtual void state_export(const device_state_entry &entry);
virtual void state_string_export(const device_state_entry &entry, astring &string);
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const;
virtual UINT32 disasm_max_opcode_bytes() const;
virtual offs_t disasm_generic(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options, const disasm_entry *entries);
address_space_config program_config;
address_space *program;
direct_read_data *direct;
UINT64 end_cycles;
int icount, bcount, inst_state, cycles_scaling;
UINT8 pending_irq;
UINT16 PC, PPC, PSW;
UINT16 OP1;
UINT8 OP2, OP3, OPI;
UINT32 TMP;
UINT16 R[0x74];
bool irq_requested;
virtual void do_exec_full() = 0;
virtual void do_exec_partial() = 0;
virtual void internal_update(UINT64 current_time) = 0;
virtual void io_w8(UINT8 adr, UINT8 data) = 0;
virtual void io_w16(UINT8 adr, UINT16 data) = 0;
virtual UINT8 io_r8(UINT8 adr) = 0;
virtual UINT16 io_r16(UINT8 adr) = 0;
void recompute_bcount(UINT64 event_time);
static astring regname(UINT8 reg);
inline void next(int cycles) { icount -= cycles_scaling*cycles; inst_state = STATE_FETCH; }
inline void next_noirq(int cycles) { icount -= cycles_scaling*cycles; inst_state = STATE_FETCH_NOIRQ; }
void check_irq();
inline UINT8 read_pc() { return direct->read_decrypted_byte(PC++); }
void reg_w8(UINT8 adr, UINT8 data);
void reg_w16(UINT8 adr, UINT16 data);
void any_w8(UINT16 adr, UINT8 data);
void any_w16(UINT16 adr, UINT16 data);
UINT8 reg_r8(UINT8 adr);
UINT16 reg_r16(UINT8 adr);
UINT8 any_r8(UINT16 adr);
UINT16 any_r16(UINT16 adr);
UINT8 do_addb(UINT8 v1, UINT8 v2);
UINT16 do_add(UINT16 v1, UINT16 v2);
UINT8 do_subb(UINT8 v1, UINT8 v2);
UINT16 do_sub(UINT16 v1, UINT16 v2);
void set_nz8(UINT8 v);
void set_nz16(UINT16 v);
#define O(o) void o ## _full(); void o ## _partial()
O(add_direct_2); O(add_direct_3); O(add_immed_2w); O(add_immed_3w); O(add_indexed_2); O(add_indexed_3); O(add_indirect_2); O(add_indirect_3);
O(addb_direct_2); O(addb_direct_3); O(addb_immed_2b); O(addb_immed_3b); O(addb_indexed_2); O(addb_indexed_3); O(addb_indirect_2); O(addb_indirect_3);
O(addc_direct_2); O(addc_immed_2w); O(addc_indexed_2); O(addc_indirect_2);
O(addcb_direct_2); O(addcb_immed_2w); O(addcb_indexed_2); O(addcb_indirect_2);
O(and_direct_2); O(and_direct_3); O(and_immed_2w); O(and_immed_3w); O(and_indexed_2); O(and_indexed_3); O(and_indirect_2); O(and_indirect_3);
O(andb_direct_2); O(andb_direct_3); O(andb_immed_2b); O(andb_immed_3b); O(andb_indexed_2); O(andb_indexed_3); O(andb_indirect_2); O(andb_indirect_3);
O(br_indirect_1n);
O(clr_direct_1);
O(clrb_direct_1);
O(clrc_none);
O(clrvt_none);
O(cmp_direct_2); O(cmp_immed_2w); O(cmp_indexed_2); O(cmp_indirect_2);
O(cmpb_direct_2); O(cmpb_immed_2b); O(cmpb_indexed_2); O(cmpb_indirect_2);
O(dec_direct_1);
O(decb_direct_1);
O(di_none);
O(div_direct_2); O(div_immed_2w); O(div_indexed_2); O(div_indirect_2);
O(divb_direct_2); O(divb_immed_2b); O(divb_indexed_2); O(divb_indirect_2);
O(divu_direct_2); O(divu_immed_2w); O(divu_indexed_2); O(divu_indirect_2);
O(divub_direct_2); O(divub_immed_2b); O(divub_indexed_2); O(divub_indirect_2);
O(djnz_rrel8);
O(djnzw_rrel8);
O(ei_none);
O(ext_direct_1);
O(extb_direct_1);
O(idlpd_none);
O(inc_direct_1);
O(incb_direct_1);
O(jbc_brrel8);
O(jbs_brrel8);
O(jc_rel8);
O(je_rel8);
O(jge_rel8);
O(jgt_rel8);
O(jh_rel8);
O(jle_rel8);
O(jlt_rel8);
O(jnc_rel8);
O(jne_rel8);
O(jnh_rel8);
O(jnst_rel8);
O(jnv_rel8);
O(jnvt_rel8);
O(jst_rel8);
O(jv_rel8);
O(jvt_rel8);
O(lcall_rel16);
O(ld_direct_2); O(ld_immed_2w); O(ld_indexed_2); O(ld_indirect_2);
O(ldb_direct_2); O(ldb_immed_2b); O(ldb_indexed_2); O(ldb_indirect_2);
O(ldbse_direct_2); O(ldbse_immed_2b); O(ldbse_indexed_2); O(ldbse_indirect_2);
O(ldbze_direct_2); O(ldbze_immed_2b); O(ldbze_indexed_2); O(ldbze_indirect_2);
O(ljmp_rel16);
O(mul_direct_2); O(mul_direct_3); O(mul_immed_2w); O(mul_immed_3w); O(mul_indexed_2); O(mul_indexed_3); O(mul_indirect_2); O(mul_indirect_3);
O(mulb_direct_2); O(mulb_direct_3); O(mulb_immed_2b); O(mulb_immed_3b); O(mulb_indexed_2); O(mulb_indexed_3); O(mulb_indirect_2); O(mulb_indirect_3);
O(mulu_direct_2); O(mulu_direct_3); O(mulu_immed_2w); O(mulu_immed_3w); O(mulu_indexed_2); O(mulu_indexed_3); O(mulu_indirect_2); O(mulu_indirect_3);
O(mulub_direct_2); O(mulub_direct_3); O(mulub_immed_2b); O(mulub_immed_3b); O(mulub_indexed_2); O(mulub_indexed_3); O(mulub_indirect_2); O(mulub_indirect_3);
O(neg_direct_1);
O(negb_direct_1);
O(nop_none);
O(norml_direct_2);
O(not_direct_1);
O(notb_direct_1);
O(or_direct_2); O(or_immed_2w); O(or_indexed_2); O(or_indirect_2);
O(orb_direct_2); O(orb_immed_2b); O(orb_indexed_2); O(orb_indirect_2);
O(pop_direct_1); O(pop_indexed_1); O(pop_indirect_1);
O(popa_none);
O(popf_none);
O(push_direct_1); O(push_immed_1w); O(push_indexed_1); O(push_indirect_1);
O(pusha_none);
O(pushf_none);
O(ret_none);
O(rst_none);
O(scall_rel11);
O(setc_none);
O(shl_immed_2b);
O(shlb_immed_2b);
O(shll_immed_2b);
O(shr_immed_2b);
O(shra_immed_2b);
O(shrab_immed_2b);
O(shral_immed_2b);
O(shrb_immed_2b);
O(shrl_immed_2b);
O(sjmp_rel11);
O(skip_immed_1b);
O(st_direct_2); O(st_indexed_2); O(st_indirect_2);
O(stb_direct_2); O(stb_indexed_2); O(stb_indirect_2);
O(sub_direct_2); O(sub_direct_3); O(sub_immed_2w); O(sub_immed_3w); O(sub_indexed_2); O(sub_indexed_3); O(sub_indirect_2); O(sub_indirect_3);
O(subb_direct_2); O(subb_direct_3); O(subb_immed_2b); O(subb_immed_3b); O(subb_indexed_2); O(subb_indexed_3); O(subb_indirect_2); O(subb_indirect_3);
O(subc_direct_2); O(subc_immed_2w); O(subc_indexed_2); O(subc_indirect_2);
O(subcb_direct_2); O(subcb_immed_2w); O(subcb_indexed_2); O(subcb_indirect_2);
O(trap_none);
O(xch_direct_2);
O(xchb_direct_2);
O(xor_direct_2); O(xor_immed_2w); O(xor_indexed_2); O(xor_indirect_2);
O(xorb_direct_2); O(xorb_immed_2b); O(xorb_indexed_2); O(xorb_indirect_2);
O(fetch);
O(fetch_noirq);
#undef O
};
enum {
MCS96_PC = 1,
MCS96_PSW,
MCS96_R // 0x74 entries
};
#endif

View File

@ -0,0 +1,192 @@
#!/usr/bin/python
USAGE = """
Usage:
%s mcs96ops.lst mcs96.inc
"""
import sys
def save_full_one(f, t, name, source):
print >>f, "void %s_device::%s_full()" % (t, name)
print >>f, "{"
for line in source:
print >>f, line
print >>f, "}"
print >>f
class Opcode:
def __init__(self, rng, name, amode, is_196, ea):
rng1 = rng.split("-")
self.rng_start = int(rng1[0], 16)
if len(rng1) == 2:
self.rng_end = int(rng1[1], 16)
else:
self.rng_end = self.rng_start
self.name = name
self.amode = amode
self.source = []
self.is_196 = is_196
if amode in ea:
for line in ea[amode].source:
self.source.append(line)
def add_source_line(self, line):
self.source.append(line)
class Special:
def __init__(self, name):
self.name = name
self.source = []
def add_source_line(self, line):
self.source.append(line)
class Macro:
def __init__(self, tokens):
self.name = tokens[1]
self.params = []
for i in range(2, len(tokens)):
self.params.append(tokens[i])
self.source = []
def add_source_line(self, line):
self.source.append(line)
def apply(self, target, tokens):
values = []
for i in range(1, len(tokens)):
values.append(tokens[i])
for i in range(0, len(self.source)):
line = self.source[i]
for i in range(0, len(self.params)):
line = line.replace(self.params[i], values[i])
target.add_source_line(line)
class OpcodeList:
def __init__(self, fname, is_196):
self.opcode_info = []
self.opcode_per_id = {}
self.ea = {}
self.macros = {}
try:
f = open(fname, "r")
except Exception, err:
print "Cannot read opcodes file %s [%s]" % (fname, err)
sys.exit(1)
opc = None
for line in f:
if line.startswith("#"):
continue
line = line.rstrip()
if not line:
continue
if line.startswith(" ") or line.startswith("\t"):
# append instruction to last opcode, maybe expand a macro
tokens = line.split()
if tokens[0] in self.macros:
self.macros[tokens[0]].apply(inf, tokens)
else:
inf.add_source_line(line)
else:
# New something
tokens = line.split()
# Addressing mode header
if tokens[0] == "eadr":
inf = Special(tokens[1])
self.ea[inf.name] = inf
elif tokens[0] == "fetch":
inf = Special(tokens[0])
self.fetch = inf
elif tokens[0] == "fetch_noirq":
inf = Special(tokens[0])
self.fetch_noirq = inf
elif tokens[0] == "macro":
inf = Macro(tokens)
self.macros[inf.name] = inf
else:
inf = Opcode(tokens[0], tokens[1], tokens[2], len(tokens) >= 4 and tokens[3] == "196", self.ea)
self.opcode_info.append(inf)
if is_196 or not inf.is_196:
for i in range(inf.rng_start, inf.rng_end+1):
self.opcode_per_id[i] = inf
def save_dasm(self, f, t):
print >>f, "const %s_device::disasm_entry %s_device::disasm_entries[0x100] = {" % (t, t)
for i in range(0, 0x100):
if i in self.opcode_per_id:
opc = self.opcode_per_id[i]
alt = "NULL"
if i + 0xfe00 in self.opcode_per_id:
alt = "\"" + self.opcode_per_id[i+0xfe00].name + "\""
if opc.name == "scall" or opc.name == "lcall":
flags = "DASMFLAG_STEP_OVER"
elif opc.name == "rts":
flags = "DASMFLAG_STEP_OUT"
else:
flags = "0"
print >>f, "\t{ \"%s\", %s, DASM_%s, %s }," % (opc.name, alt, opc.amode, flags)
else:
print >>f, "\t{ \"???\", NULL, DASM_none, 0 },"
print >>f, "};"
print >>f
def save_opcodes(self, f, t):
pf = ""
is_196 = False
if t == "i8xc196":
pf = "_196"
is_196 = True
for opc in self.opcode_info:
if opc.is_196 == is_196:
save_full_one(f, t, opc.name + "_" + opc.amode + pf, opc.source)
if not is_196:
save_full_one(f, t, "fetch", self.fetch.source)
save_full_one(f, t, "fetch_noirq", self.fetch_noirq.source)
def save_exec(self, f, t):
print >>f, "void %s_device::do_exec_full()" % t
print >>f, "{"
print >>f, "\tswitch(inst_state) {"
for i in range(0x000, 0x200):
opc = None
if i >= 0x100 and i-0x100+0xfe00 in self.opcode_per_id:
opc = self.opcode_per_id[i-0x100+0xfe00]
if opc == None and (i & 0xff) in self.opcode_per_id:
opc = self.opcode_per_id[i & 0xff]
if opc != None:
nm = opc.name + "_" + opc.amode
if opc.is_196:
nm = nm + "_196"
print >>f, "\tcase 0x%03x: %s_full(); break;" % (i, nm)
print >>f, "\tcase 0x200: fetch_full(); break;"
print >>f, "\tcase 0x201: fetch_noirq_full(); break;"
print >>f, "\t}"
print >>f, "}"
def main(argv):
if len(argv) != 4:
print USAGE % argv[0]
return 1
t = argv[1]
opcodes = OpcodeList(argv[2], t == "i8xc196")
try:
f = open(argv[3], "w")
except Exception, err:
logging.error("cannot write file %s [%s]", fname, err)
sys.exit(1)
if t != "mcs96":
opcodes.save_dasm(f, t)
if t != "i8x9x":
opcodes.save_opcodes(f, t)
if t != "mcs96":
opcodes.save_exec(f, t)
f.close()
# ======================================================================
if __name__ == "__main__":
sys.exit(main(sys.argv))

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,7 @@ CPUS += V30MZ
CPUS += V60
CPUS += MCS48
CPUS += MCS51
CPUS += MCS96
CPUS += M6800
CPUS += M6805
CPUS += HD6309
@ -2120,7 +2121,7 @@ $(MESS_DRIVERS)/mac.o: $(MESSSRC)/drivers/mac.c \
$(MESSSRC)/includes/mac.h $(MESSSRC)/machine/egret.h $(MESSSRC)/machine/cuda.h
$(MESS_MACHINE)/egret.o: $(MESSSRC)/machine/egret.c\
$(MESSSRC)/machine/egret.h
$(MESSSRC)/machine/egret.h
$(MESS_DRIVERS)/apple2.o: $(MESSSRC)/includes/apple2.h
$(MESS_MACHINE)/apple2.o: $(MESSSRC)/includes/apple2.h