mirror of
https://github.com/holub/mame
synced 2025-05-04 21:43:05 +03:00
(mess) mcs96: First (incomplete) stab at a core [O. Galibert]
This commit is contained in:
parent
b6fe84c927
commit
73e4eb26eb
@ -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
|
||||
#-------------------------------------------------
|
||||
|
@ -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"
|
@ -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
|
@ -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"
|
@ -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
|
@ -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"
|
@ -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
|
@ -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
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user