diff options
author | 2012-12-17 23:19:50 +0000 | |
---|---|---|
committer | 2012-12-17 23:19:50 +0000 | |
commit | 73e4eb26ebb39f5636d233109e25298cfbe82dad (patch) | |
tree | 8a5c516da9e8a17dac66438bd5aae66d0bbf1fe1 /src/emu/cpu/mcs96 | |
parent | b6fe84c9275c4b1bfc69459803e7171b96aaf67e (diff) |
(mess) mcs96: First (incomplete) stab at a core [O. Galibert]
Diffstat (limited to 'src/emu/cpu/mcs96')
-rw-r--r-- | src/emu/cpu/mcs96/i8x9x.c | 396 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/i8x9x.h | 126 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/i8xc196.c | 101 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/i8xc196.h | 75 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/mcs96.c | 713 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/mcs96.h | 280 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/mcs96make.py | 192 | ||||
-rw-r--r-- | src/emu/cpu/mcs96/mcs96ops.lst | 1617 |
8 files changed, 3500 insertions, 0 deletions
diff --git a/src/emu/cpu/mcs96/i8x9x.c b/src/emu/cpu/mcs96/i8x9x.c index e69de29bb2d..cb58a072eee 100644 --- a/src/emu/cpu/mcs96/i8x9x.c +++ b/src/emu/cpu/mcs96/i8x9x.c @@ -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" diff --git a/src/emu/cpu/mcs96/i8x9x.h b/src/emu/cpu/mcs96/i8x9x.h index e69de29bb2d..0f2e1b4f47c 100644 --- a/src/emu/cpu/mcs96/i8x9x.h +++ b/src/emu/cpu/mcs96/i8x9x.h @@ -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 diff --git a/src/emu/cpu/mcs96/i8xc196.c b/src/emu/cpu/mcs96/i8xc196.c index e69de29bb2d..4eb8489a382 100644 --- a/src/emu/cpu/mcs96/i8xc196.c +++ b/src/emu/cpu/mcs96/i8xc196.c @@ -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" diff --git a/src/emu/cpu/mcs96/i8xc196.h b/src/emu/cpu/mcs96/i8xc196.h index e69de29bb2d..de509ba0b7e 100644 --- a/src/emu/cpu/mcs96/i8xc196.h +++ b/src/emu/cpu/mcs96/i8xc196.h @@ -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 diff --git a/src/emu/cpu/mcs96/mcs96.c b/src/emu/cpu/mcs96/mcs96.c index e69de29bb2d..849163fb2e3 100644 --- a/src/emu/cpu/mcs96/mcs96.c +++ b/src/emu/cpu/mcs96/mcs96.c @@ -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" diff --git a/src/emu/cpu/mcs96/mcs96.h b/src/emu/cpu/mcs96/mcs96.h index e69de29bb2d..a1a1b0aa175 100644 --- a/src/emu/cpu/mcs96/mcs96.h +++ b/src/emu/cpu/mcs96/mcs96.h @@ -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 diff --git a/src/emu/cpu/mcs96/mcs96make.py b/src/emu/cpu/mcs96/mcs96make.py index e69de29bb2d..4c6158a4914 100644 --- a/src/emu/cpu/mcs96/mcs96make.py +++ b/src/emu/cpu/mcs96/mcs96make.py @@ -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)) + diff --git a/src/emu/cpu/mcs96/mcs96ops.lst b/src/emu/cpu/mcs96/mcs96ops.lst index e69de29bb2d..0f41d2c777d 100644 --- a/src/emu/cpu/mcs96/mcs96ops.lst +++ b/src/emu/cpu/mcs96/mcs96ops.lst @@ -0,0 +1,1617 @@ +fetch + if(irq_requested) { + int level; + for(level = 7; level >= 0 && !(PSW & pending_irq & (1<<level)); level--); + pending_irq &= ~(1<<level); + OP1 = level; + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, PC); + PC = any_r16(0x2000+2*OP1); + standard_irq_callback(OP1); + check_irq(); + } + if(machine().debug_flags & DEBUG_FLAG_ENABLED) + debugger_instruction_hook(this, PC); + PPC = PC; + OP1 = read_pc(); + if(OP1 == 0xfe) { + OP1 = read_pc(); + inst_state = 0x100 | OP1; + } else + inst_state = OP1; + +fetch_noirq + if(machine().debug_flags & DEBUG_FLAG_ENABLED) + debugger_instruction_hook(this, PC); + PPC = PC; + OP1 = read_pc(); + if(OP1 == 0xfe) { + OP1 = read_pc(); + inst_state = 0x100 | OP1; + } else + inst_state = OP1; + +eadr rel8 + OP1 = INT8(read_pc()); + +eadr rel11 + OP1 = read_pc(); + OP1 = OP1 | ((inst_state & 7) << 8); + if(OP1 & 0x400) + OP1 |= 0xfc00; + +eadr rel16 + OP1 = read_pc(); + OP1 |= read_pc() << 8; + +eadr rrel8 + OP2 = read_pc(); + OP1 = INT8(read_pc()); + +eadr brrel8 + OP2 = read_pc(); + OP1 = INT8(read_pc()); + +eadr direct_1 + OP1 = read_pc(); + +eadr direct_2 + OP1 = read_pc(); + OP2 = read_pc(); + +eadr direct_3 + OP1 = read_pc(); + OP2 = read_pc(); + OP3 = read_pc(); + +eadr immed_1b + OP1 = read_pc(); + +eadr immed_2b + OP1 = read_pc(); + OP2 = read_pc(); + +eadr immed_3b + OP1 = read_pc(); + OP2 = read_pc(); + OP3 = read_pc(); + +eadr immed_1w + OP1 = read_pc(); + OP1 |= read_pc() << 8; + +eadr immed_2w + OP1 = read_pc(); + OP1 |= read_pc() << 8; + OP2 = read_pc(); + +eadr immed_3w + OP1 = read_pc(); + OP1 |= read_pc() << 8; + OP2 = read_pc(); + OP3 = read_pc(); + +eadr indirect_1n + OPI = read_pc() & 0xfe; + OP1 = reg_r16(OPI); + +eadr indirect_1 + OPI = read_pc(); + OP1 = reg_r16(OPI); + +eadr indirect_2 + OPI = read_pc(); + OP1 = reg_r16(OPI); + OP2 = read_pc(); + +eadr indirect_3 + OPI = read_pc(); + OP1 = reg_r16(OPI); + OP2 = read_pc(); + OP3 = read_pc(); + +macro post_indirect $size $cycles1 $cycles2 + if(OPI & 0x01) { + reg_w16(OPI, OP1 + $size); + next($cycles2); // +4 when external + } else { + next($cycles1); // +4 when external + } + +eadr indexed_1 + OPI = read_pc(); + OP1 = read_pc(); + if(OPI & 0x01) { + OPI &= 0xfe; + OP1 |= read_pc() << 8; + } else + OP1 = INT8(OP1); + if(OPI) { + OP1 += reg_r16(OPI); + } + +eadr indexed_2 + OPI = read_pc(); + OP1 = read_pc(); + if(OPI & 0x01) { + OPI &= 0xfe; + OP1 |= read_pc() << 8; + } else if(OP1 & 0x80) + OP1 |= 0xff00; + if(OPI) { + OP1 += reg_r16(OPI); + } + OP2 = read_pc(); + +eadr indexed_3 + OPI = read_pc(); + OP1 = read_pc(); + if(OPI & 0x01) { + OPI &= 0xfe; + OP1 |= read_pc() << 8; + } else if(OP1 & 0x80) + OP1 |= 0xff00; + if(OPI) { + OP1 += reg_r16(OPI); + } + OP2 = read_pc(); + OP3 = read_pc(); + +macro post_indexed $cycles1 $cycles2 + next(OPI & 0x01 ? $cycles2 : $cycles1); + +00 skip immed_1b + next(4); + +01 clr direct_1 + reg_w16(OP1, 0x0000); + next(4); + +02 not direct_1 + TMP = ~reg_r16(OP1); + set_nz16(TMP); + reg_w16(OP1, TMP); + next(4); + +03 neg direct_1 + TMP = reg_r16(OP1); + reg_w16(OP1, do_sub(0, TMP)); + next(4); + +04 xch direct_2 + +05 dec direct_1 + TMP = reg_r16(OP1); + reg_w16(OP1, do_sub(TMP, 1)); + next(4); + +06 ext direct_1 + OP1 &= 0xfc; + TMP = INT16(reg_r16(OP1)); + set_nz16(TMP); + reg_w16(OP1+2, TMP >> 16); + next(4); + +07 inc direct_1 + TMP = reg_r16(OP1); + reg_w16(OP1, do_add(TMP, 1)); + next(4); + +08 shr immed_2b + OP1 &= 0x1f; + TMP = reg_r16(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffff >> (OP1 <= 16 ? 17-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 16 && (TMP & (0x0001 << (OP1-1)))) + PSW |= F_C; + TMP = UINT16(TMP) >> OP1; + if(!TMP) + PSW |= F_Z; + else if(INT16(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +09 shl immed_2b + OP1 &= 0x1f; + TMP = reg_r16(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffff << (OP1 <= 16 ? 17-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 16 && (TMP & (0x8000 >> (OP1-1)))) + PSW |= F_C; + TMP = UINT16(TMP << OP1); + if(!TMP) + PSW |= F_Z; + else if(INT16(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +0a shra immed_2b + OP1 &= 0x1f; + TMP = reg_r16(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffff >> (OP1 <= 16 ? 17-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 16 && (TMP & (0x0001 << (OP1-1)))) + PSW |= F_C; + TMP = INT16(TMP) >> OP1; + if(!TMP) + PSW |= F_Z; + else if(INT16(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +0c shrl immed_2b + OP1 &= 0x1f; + OP2 &= 0xfc; + TMP = reg_r16(OP2); + TMP |= reg_r16(OP2+2) << 16; + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffffffff >> (33-OP1)))) + PSW |= F_ST; + if(OP1 >= 1 && (TMP & (0x00000001 << (OP1-1)))) + PSW |= F_C; + TMP = TMP >> OP1; + if(!TMP) + PSW |= F_Z; + else if(INT32(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(OP1 ? 7+OP1 : 8); + +0d shll immed_2b + OP1 &= 0x1f; + OP2 &= 0xfc; + TMP = reg_r16(OP2); + TMP |= reg_r16(OP2+2) << 16; + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffffffff << (33-OP1)))) + PSW |= F_ST; + if(OP1 >= 1 && (TMP & (0x80000000 >> (OP1-1)))) + PSW |= F_C; + TMP = TMP << OP1; + if(!TMP) + PSW |= F_Z; + else if(INT32(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(OP1 ? 7+OP1 : 8); + +0e shral immed_2b + OP1 &= 0x1f; + OP2 &= 0xfc; + TMP = reg_r16(OP2); + TMP |= reg_r16(OP2+2) << 16; + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xffffffff >> (33-OP1)))) + PSW |= F_ST; + if(OP1 >= 1 && (TMP & (0x00000001 << (OP1-1)))) + PSW |= F_C; + TMP = INT32(TMP) >> OP1; + if(!TMP) + PSW |= F_Z; + else if(INT32(TMP) < 0) + PSW |= F_N; + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(OP1 ? 7+OP1 : 8); + +0f norml direct_2 + +11 clrb direct_1 + reg_w8(OP1, 0x00); + next(4); + +12 notb direct_1 + TMP = ~reg_r8(OP1); + set_nz8(TMP); + reg_w8(OP1, TMP); + next(4); + +13 negb direct_1 + TMP = reg_r8(OP1); + reg_w8(OP1, do_subb(0, TMP)); + next(4); + +14 xchb direct_2 + +15 decb direct_1 + TMP = reg_r8(OP1); + reg_w8(OP1, do_subb(TMP, 1)); + next(4); + +16 extb direct_1 + OP1 &= 0xfe; + TMP = INT8(reg_r8(OP1)); + set_nz8(TMP); + reg_w16(OP1, TMP); + next(4); + +17 incb direct_1 + TMP = reg_r8(OP1); + reg_w8(OP1, do_addb(TMP, 1)); + next(4); + +18 shrb immed_2b + OP1 &= 0x1f; + TMP = reg_r8(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xff >> (OP1 <= 8 ? 9-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 8 && (TMP & (0x01 << (OP1-1)))) + PSW |= F_C; + TMP = UINT8(TMP) >> OP1; + if(!TMP) + PSW |= F_Z; + else if(INT8(TMP) < 0) + PSW |= F_N; + reg_w8(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +19 shlb immed_2b + OP1 &= 0x1f; + TMP = reg_r8(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xff << (OP1 <= 8 ? 9-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 8 && (TMP & (0x80 >> (OP1-1)))) + PSW |= F_C; + TMP = UINT8(TMP << OP1); + if(!TMP) + PSW |= F_Z; + else if(INT8(TMP) < 0) + PSW |= F_N; + reg_w8(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +1a shrab immed_2b + OP1 &= 0x1f; + TMP = reg_r8(OP2); + PSW &= ~(F_Z|F_N|F_C|F_V|F_ST); + if(OP1 >= 2 && (TMP & (0xff >> (OP1 <= 8 ? 9-OP1 : 0)))) + PSW |= F_ST; + if(OP1 >= 1 && OP1 <= 8 && (TMP & (0x01 << (OP1-1)))) + PSW |= F_C; + TMP = UINT8(INT8(TMP) >> OP1); + if(!TMP) + PSW |= F_Z; + else if(INT8(TMP) < 0) + PSW |= F_N; + reg_w8(OP2, TMP); + next(OP1 ? 7+OP1 : 8); + +20-27 sjmp rel11 + PC += OP1; + next(8); + +28-2f scall rel11 + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, PC); + PC += OP1; + next(13); // real is 13/16 depending on sp's position + +30-37 jbc brrel8 + TMP = reg_r8(OP2); + if(!((TMP >> (inst_state & 7)) & 1)) { + PC += OP1; + next(9); + } else { + next(5); + } + +38-3f jbs brrel8 + TMP = reg_r8(OP2); + if((TMP >> (inst_state & 7)) & 1) { + PC += OP1; + next(9); + } else { + next(5); + } + +40 and direct_3 + TMP = reg_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP3, TMP); + next(5); + +41 and immed_3w + TMP = OP1 & reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP3, TMP); + next(6); + +42 and indirect_3 + TMP = any_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP3, TMP); + post_indirect 2 7 8 // +5 when external + +43 and indexed_3 + TMP = any_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP3, TMP); + post_indexed 7 8 // +5 when external + +44 add direct_3 + TMP = reg_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + next(5); + +45 add immed_3w + TMP = do_add(reg_r16(OP2), OP1); + reg_w16(OP3, TMP); + next(6); + +46 add indirect_3 + TMP = any_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + post_indirect 2 7 8 // +5 when external + +47 add indexed_3 + TMP = any_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + post_indexed 7 8 // +5 when external + +48 sub direct_3 + TMP = reg_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + next(5); + +49 sub immed_3w + TMP = do_sub(reg_r16(OP2), OP1); + reg_w16(OP3, TMP); + next(6); + +4a sub indirect_3 + TMP = any_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + post_indexed 7 8 // +5 when external + +4b sub indexed_3 + TMP = any_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP3, TMP); + post_indexed 7 8 // +5 when external + +4c mulu direct_3 + TMP = reg_r16(OP1); + TMP *= reg_r16(OP2); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + next(26); + +4d mulu immed_3w + TMP = OP1 * reg_r16(OP2); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + next(27); + +4e mulu indirect_3 + TMP = any_r16(OP1); + TMP *= reg_r16(OP2); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + post_indirect 2 28 29 // +5 when external + +4f mulu indexed_3 + TMP = any_r16(OP1); + TMP *= reg_r16(OP2); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + post_indexed 28 29 // +5 when external + +fe4c mul direct_3 + TMP = reg_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + next(30); + +fe4d mul immed_3w + TMP = INT16(OP1) * INT16(reg_r16(OP2)); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + next(31); + +fe4e mul indirect_3 + TMP = any_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + post_indirect 2 32 33 // +5 when external + +fe4f mul indexed_3 + TMP = any_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + OP3 &= 0xfc; + reg_w16(OP3, TMP); + reg_w16(OP3+2, TMP >> 16); + post_indexed 32 33 // +5 when external + +50 andb direct_3 + TMP = reg_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP3, TMP); + next(5); + +51 andb immed_3b + TMP = OP1 & reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP3, TMP); + next(5); + +52 andb indirect_3 + TMP = any_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP3, TMP); + post_indirect 1 7 8 // +5 when external + +53 andb indexed_3 + TMP = any_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP3, TMP); + post_indexed 7 8 // +5 when external + +54 addb direct_3 + TMP = reg_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + next(5); + +55 addb immed_3b + TMP = do_addb(reg_r8(OP2), OP1); + reg_w8(OP3, TMP); + next(5); + +56 addb indirect_3 + TMP = any_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + post_indirect 1 7 8 // +5 when external + +57 addb indexed_3 + TMP = any_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + post_indexed 7 8 // +5 when external + +58 subb direct_3 + TMP = reg_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + next(5); + +59 subb immed_3b + TMP = do_subb(reg_r8(OP2), OP1); + reg_w8(OP3, TMP); + next(5); + +5a subb indirect_3 + TMP = any_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + post_indirect 1 7 8 // +5 when external + +5b subb indexed_3 + TMP = any_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP3, TMP); + post_indexed 7 8 // +5 when external + +5c mulub direct_3 + TMP = reg_r8(OP1); + TMP *= reg_r8(OP2); + reg_w16(OP3, TMP); + next(18); + +5d mulub immed_3b + TMP = OP1 * reg_r8(OP2); + reg_w16(OP3, TMP); + next(18); + +5e mulub indirect_3 + TMP = any_r8(OP1); + TMP *= reg_r8(OP2); + reg_w16(OP3, TMP); + post_indirect 1 20 21 // +5 when external + +5f mulub indexed_3 + TMP = any_r8(OP1); + TMP = reg_r8(OP2); + reg_w16(OP3, TMP); + post_indexed 20 21 // +5 when external + +fe5c mulb direct_3 + TMP = reg_r8(OP1); + TMP = INT8(reg_r8(OP2)) * INT8(TMP); + reg_w16(OP3, TMP); + next(22); + +fe5d mulb immed_3b + TMP = INT8(OP1) * INT8(reg_r8(OP2)); + reg_w16(OP3, TMP); + next(22); + +fe5e mulb indirect_3 + TMP = any_r8(OP1); + TMP = INT8(reg_r8(OP2)) * INT8(TMP); + reg_w16(OP3, TMP); + post_indirect 1 24 25 // +5 when external + +fe5f mulb indexed_3 + TMP = any_r8(OP1); + TMP = INT8(reg_r8(OP2)) * INT8(TMP); + reg_w16(OP3, TMP); + post_indexed 24 25 // +5 when external + +60 and direct_2 + TMP = reg_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(4); + +61 and immed_2w + TMP = OP1 & reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(5); + +62 and indirect_2 + TMP = any_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indirect 2 6 7 // +5 when external + +63 and indexed_2 + TMP = any_r16(OP1); + TMP &= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indexed 6 7 // +5 when external + +64 add direct_2 + TMP = reg_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + next(4); + +65 add immed_2w + TMP = do_add(reg_r16(OP2), OP1); + reg_w16(OP2, TMP); + next(5); + +66 add indirect_2 + TMP = any_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + post_indirect 2 6 7 // +5 when external + +67 add indexed_2 + TMP = any_r16(OP1); + TMP = do_add(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + post_indexed 6 7 // +5 when external + +68 sub direct_2 + TMP = reg_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + next(4); + +69 sub immed_2w + TMP = do_sub(reg_r16(OP2), OP1); + reg_w16(OP2, TMP); + next(5); + +6a sub indirect_2 + TMP = any_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + post_indirect 2 6 7 // +5 when external + +6b sub indexed_2 + TMP = any_r16(OP1); + TMP = do_sub(reg_r16(OP2), TMP); + reg_w16(OP2, TMP); + post_indexed 6 7 // +5 when external + +6c mulu direct_2 + OP2 &= 0xfc; + TMP = reg_r16(OP1); + TMP *= reg_r16(OP2); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(25); + +6d mulu immed_2w + OP2 &= 0xfc; + TMP = OP1 * reg_r16(OP2); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(26); + +6e mulu indirect_2 + OP2 &= 0xfc; + TMP = any_r16(OP1); + TMP *= reg_r16(OP2); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + post_indirect 2 27 28 // +5 when external + +6f mulu indexed_2 + OP2 &= 0xfc; + TMP = any_r16(OP1); + TMP *= reg_r16(OP2); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + post_indexed 27 28 // +5 when external + +fe6c mul direct_2 + OP2 &= 0xfc; + TMP = reg_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(29); + +fe6d mul immed_2w + OP2 &= 0xfc; + TMP = INT16(OP1) * INT16(reg_r16(OP2)); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + next(30); + +fe6e mul indirect_2 + OP2 &= 0xfc; + TMP = any_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + post_indirect 2 31 32 // +5 when external + +fe6f mul indexed_2 + OP2 &= 0xfc; + TMP = any_r16(OP1); + TMP = INT16(reg_r16(OP2)) * INT16(TMP); + reg_w16(OP2, TMP); + reg_w16(OP2+2, TMP >> 16); + post_indexed 31 32 // +5 when external + +70 andb direct_2 + TMP = reg_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +71 andb immed_2b + TMP = OP1 & reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +72 andb indirect_2 + TMP = any_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + post_indirect 1 6 7 // +5 when external + +73 andb indexed_2 + TMP = any_r8(OP1); + TMP &= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP3, TMP); + post_indexed 6 7 // +5 when external + +74 addb direct_2 + TMP = reg_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + next(4); + +75 addb immed_2b + TMP = do_addb(reg_r8(OP2), OP1); + reg_w8(OP2, TMP); + next(4); + +76 addb indirect_2 + TMP = any_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + post_indirect 1 6 7 // +5 when external + +77 addb indexed_2 + TMP = any_r8(OP1); + TMP = do_addb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + post_indexed 6 7 // +5 when external + +78 subb direct_2 + TMP = reg_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + next(4); + +79 subb immed_2b + TMP = do_subb(reg_r8(OP2), OP1); + reg_w8(OP2, TMP); + next(4); + +7a subb indirect_2 + TMP = any_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + post_indirect 1 6 7 // +5 when external + +7b subb indexed_2 + TMP = any_r8(OP1); + TMP = do_subb(reg_r8(OP2), TMP); + reg_w8(OP2, TMP); + post_indexed 6 7 // +5 when external + +7c mulub direct_2 + OP2 &= 0xfe; + TMP = reg_r8(OP1); + TMP *= reg_r8(OP2); + reg_w16(OP2, TMP); + next(17); + +7d mulub immed_2b + OP2 &= 0xfe; + TMP = OP1 * reg_r8(OP2); + reg_w16(OP2, TMP); + next(17); + +7e mulub indirect_2 + OP2 &= 0xfe; + TMP = any_r8(OP1); + TMP *= reg_r8(OP2); + reg_w16(OP2, TMP); + post_indirect 1 19 20 // +5 when external + +7f mulub indexed_2 + OP2 &= 0xfe; + TMP = any_r8(OP1); + TMP *= reg_r8(OP2); + reg_w16(OP2, TMP); + post_indexed 19 20 // +5 when external + +fe7c mulb direct_2 + OP2 &= 0xfe; + TMP = reg_r8(OP1); + TMP = INT8(reg_r16(OP2)) * INT8(TMP); + reg_w16(OP2, TMP); + next(21); + +fe7d mulb immed_2b + OP2 &= 0xfe; + TMP = INT8(OP1) * INT8(reg_r8(OP2)); + reg_w16(OP2, TMP); + next(21); + +fe7e mulb indirect_2 + OP2 &= 0xfe; + TMP = any_r8(OP1); + TMP = INT8(reg_r8(OP2)) * INT8(TMP); + reg_w16(OP2, TMP); + post_indirect 1 23 24 // +5 when external + +fe7f mulb indexed_2 + OP2 &= 0xfe; + TMP = any_r16(OP1); + TMP = INT8(reg_r16(OP2)) * INT8(TMP); + reg_w16(OP2, TMP); + post_indexed 23 24 // +5 when external + +80 or direct_2 + TMP = reg_r16(OP1); + TMP |= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(4); + +81 or immed_2w + TMP = OP1 | reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(5); + +82 or indirect_2 + TMP = any_r16(OP1); + TMP |= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indirect 2 6 7 // +5 when external + +83 or indexed_2 + TMP = any_r16(OP1); + TMP |= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indexed 6 7 // +5 when external + +84 xor direct_2 + TMP = reg_r16(OP1); + TMP ^= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(4); + +85 xor immed_2w + TMP = OP1 ^ reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + next(5); + +86 xor indirect_2 + TMP = any_r16(OP1); + TMP ^= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indirect 2 6 7 // +5 when external + +87 xor indexed_2 + TMP = any_r16(OP1); + TMP ^= reg_r16(OP2); + set_nz16(TMP); + reg_w16(OP2, TMP); + post_indexed 6 7 // +5 when external + +88 cmp direct_2 + TMP = reg_r16(OP1); + do_sub(reg_r16(OP2), TMP); + next(4); + +89 cmp immed_2w + do_sub(reg_r16(OP2), OP1); + next(5); + +8a cmp indirect_2 + TMP = any_r16(OP1); + do_sub(reg_r16(OP2), TMP); + post_indirect 2 6 7 // +5 when external + +8b cmp indexed_2 + TMP = any_r16(OP1); + do_sub(reg_r16(OP2), TMP); + post_indexed 6 7 // +5 when external + +8c divu direct_2 + +8d divu immed_2w + +8e divu indirect_2 + +8f divu indexed_2 + +fe8c div direct_2 + +fe8d div immed_2w + +fe8e div indirect_2 + +fe8f div indexed_2 + +90 orb direct_2 + TMP = reg_r8(OP1); + TMP |= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +91 orb immed_2b + TMP = OP1 | reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +92 orb indirect_2 + TMP = any_r8(OP1); + TMP |= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + post_indirect 1 6 7 // +5 when external + +93 orb indexed_2 + TMP = any_r8(OP1); + TMP |= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + post_indexed 6 7 // +5 when external + +94 xorb direct_2 + TMP = reg_r8(OP1); + TMP ^= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +95 xorb immed_2b + TMP = OP1 ^ reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + next(4); + +96 xorb indirect_2 + TMP = any_r8(OP1); + TMP ^= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + post_indirect 1 6 7 // +5 when external + +97 xorb indexed_2 + TMP = any_r8(OP1); + TMP ^= reg_r8(OP2); + set_nz8(TMP); + reg_w8(OP2, TMP); + post_indexed 6 7 // +5 when external + +98 cmpb direct_2 + TMP = reg_r8(OP1); + do_subb(reg_r8(OP2), TMP); + next(4); + +99 cmpb immed_2b + do_subb(reg_r8(OP2), OP1); + next(4); + +9a cmpb indirect_2 + TMP = any_r8(OP1); + do_subb(reg_r8(OP2), TMP); + post_indirect 2 6 7 // +5 when external + +9b cmpb indexed_2 + TMP = any_r8(OP1); + do_subb(reg_r8(OP2), TMP); + post_indexed 6 7 // +5 when external + +9c divub direct_2 + PSW &= ~F_V; + OP1 = reg_r8(OP1); + if(OP1) { + TMP = reg_r16(OP2); + UINT32 TMP2 = TMP / OP1; + if(TMP2 > 255) + PSW |= F_V|F_VT; + TMP = TMP % OP1; + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + next(17); + +9d divub immed_2b + PSW &= ~F_V; + if(OP1) { + TMP = reg_r16(OP2); + UINT32 TMP2 = TMP / OP1; + if(TMP2 > 255) + PSW |= F_V|F_VT; + TMP = TMP % OP1; + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + next(17); + +9e divub indirect_2 + PSW &= ~F_V; + UINT32 d = any_r8(OP1); + if(d) { + TMP = reg_r16(OP2); + UINT32 TMP2 = TMP / d; + if(TMP2 > 255) + PSW |= F_V|F_VT; + TMP = TMP % d; + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + post_indirect 1 20 21 // +4 when external + +9f divub indexed_2 + PSW &= ~F_V; + UINT32 d = any_r8(OP1); + if(d) { + TMP = reg_r16(OP2); + UINT32 TMP2 = TMP / d; + if(TMP2 > 255) + PSW |= F_V|F_VT; + TMP = TMP % d; + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + post_indexed 20 21 // +4 when external + +fe9c divb direct_2 + PSW &= ~F_V; + OP1 = reg_r8(OP1); + if(OP1) { + TMP = reg_r16(OP2); + UINT32 TMP2 = INT16(TMP) / INT8(OP1); + if(INT8(TMP2) > 127 || INT8(TMP2) < -128) + PSW |= F_V|F_VT; + TMP = INT16(TMP) % INT8(OP1); + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + next(21); + +fe9d divb immed_2b + PSW &= ~F_V; + OP1 = reg_r8(OP1); + if(OP1) { + TMP = reg_r16(OP2); + UINT32 TMP2 = INT16(TMP) / INT8(OP1); + if(INT8(TMP2) > 127 || INT8(TMP2) < -128) + PSW |= F_V|F_VT; + TMP = INT16(TMP) % INT8(OP1); + TMP = (TMP2 & 0xff) | ((TMP & 0xff) << 8); + reg_w16(OP2, TMP); + } + next(21); + +fe9e divb indirect_2 + +fe9f divb indexed_2 + +a0 ld direct_2 + reg_w16(OP2, reg_r16(OP1)); + next(4); + +a1 ld immed_2w + reg_w16(OP2, OP1); + next(5); + +a2 ld indirect_2 + reg_w16(OP2, any_r16(OP1)); + post_indirect 2 6 7 // +5 when external + +a3 ld indexed_2 + reg_w16(OP2, any_r16(OP1)); + post_indexed 6 7 // +5 when external + +a4 addc direct_2 + +a5 addc immed_2w + +a6 addc indirect_2 + +a7 addc indexed_2 + +a8 subc direct_2 + +a9 subc immed_2w + +aa subc indirect_2 + +ab subc indexed_2 + +ac ldbze direct_2 + reg_w16(OP2, UINT8(reg_r8(OP1))); + next(4); + +ad ldbze immed_2b + reg_w16(OP2, UINT8(OP1)); + next(4); + +ae ldbze indirect_2 + reg_w16(OP2, UINT8(any_r8(OP1))); + post_indirect 1 6 7 // +5 when external + +af ldbze indexed_2 + reg_w16(OP2, UINT8(any_r8(OP1))); + post_indexed 6 7 // +5 when external + +b0 ldb direct_2 + reg_w8(OP2, reg_r8(OP1)); + next(4); + +b1 ldb immed_2b + reg_w8(OP2, OP1); + next(4); + +b2 ldb indirect_2 + reg_w8(OP2, any_r8(OP1)); + post_indirect 1 6 7 // +5 when external + +b3 ldb indexed_2 + reg_w8(OP2, any_r8(OP1)); + post_indexed 6 7 // +5 when external + +b4 addcb direct_2 + +b5 addcb immed_2w + +b6 addcb indirect_2 + +b7 addcb indexed_2 + +b8 subcb direct_2 + +b9 subcb immed_2w + +ba subcb indirect_2 + +bb subcb indexed_2 + +bc ldbse direct_2 + reg_w16(OP2, INT8(reg_r8(OP1))); + next(4); + +bd ldbse immed_2b + reg_w16(OP2, INT8(OP1)); + next(4); + +be ldbse indirect_2 + reg_w16(OP2, INT8(any_r8(OP1))); + post_indirect 1 6 7 // +5 when external + +bf ldbse indexed_2 + reg_w16(OP2, INT8(any_r8(OP1))); + post_indexed 6 7 // +5 when external + +c0 st direct_2 + reg_w16(OP1, reg_r16(OP2)); + next(4); + +c1 bmov direct_2 196 + +c2 st indirect_2 + any_w16(OP1, reg_r16(OP2)); + post_indirect 2 7 8 // +4 when external + +c3 st indexed_2 + any_w16(OP1, reg_r16(OP2)); + post_indexed 7 8 // +4 when external + +c4 stb direct_2 + reg_w8(OP1, reg_r8(OP2)); + next(4); + +c5 cmpl direct_2 196 + +c6 stb indirect_2 + any_w8(OP1, reg_r8(OP2)); + post_indirect 1 7 8 // +4 when external + +c7 stb indexed_2 + any_w8(OP1, reg_r8(OP2)); + post_indexed 7 8 // +5 when external + +c8 push direct_1 + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + OP1 = reg_r16(OP1); + any_w16(TMP, OP1); + next(8); // +4 is external sp + +c9 push immed_1w + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, OP1); + next(8); // +4 is external sp + +ca push indirect_1 + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + OP1 = any_r16(OP1); + any_w16(TMP, OP1); + post_indirect 2 11 12 // +4 when external + +cb push indexed_1 + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + OP1 = any_r16(OP1); + any_w16(TMP, OP1); + post_indexed 11 12 // +4 when external + +cc pop direct_1 + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + TMP = any_r16(TMP); + reg_w16(OP1, TMP); + next(12); // +2 when external sp + +cd bmovi direct_2 196 + +ce pop indirect_1 + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + TMP = any_r16(TMP); + if((OPI & 0xfe) == 0x18) + OP1 += 2; + any_w16(OP1, TMP); + post_indirect 2 14 14 // +2 when external sp, +4 when external write + +ce pop indirect_1 196 + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + TMP = any_r16(TMP); + if((OPI & 0xfe) == 0x18) + OP1 += 2; + any_w16(OP1, TMP); + post_indirect 2 14 14 // +2 when external sp, +4 when external write + +cf pop indexed_1 + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + TMP = any_r16(TMP); + any_w16(OP1, TMP); + post_indexed 14 14 // +2 when external sp, +4 when external write + +cf pop indexed_1 196 + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + TMP = any_r16(TMP); + if((OPI & 0xfe) == 0x18) + OP1 += 2; + any_w16(OP1, TMP); + post_indexed 14 14 // +2 when external sp, +4 when external write + +d0 jnst rel8 + if(!(PSW & F_ST)) { + PC += OP1; + next(8); + } else { + PSW &= ~F_VT; + next(4); + } + +d1 jnh rel8 + if((PSW & (F_Z|F_N)) != F_C) { + PC += OP1; + next(8); + } else { + next(4); + } + +d2 jgt rel8 + if(!(PSW & (F_Z|F_N))) { + PC += OP1; + next(8); + } else { + next(4); + } + +d3 jnc rel8 + if(!(PSW & F_C)) { + PC += OP1; + next(8); + } else { + next(4); + } + +d4 jnvt rel8 + if(!(PSW & F_VT)) { + PC += OP1; + next(8); + } else { + PSW &= ~F_VT; + next(4); + } + +d5 jnv rel8 + if(!(PSW & F_V)) { + PC += OP1; + next(8); + } else { + next(4); + } + +d6 jge rel8 + if(!(PSW & F_N)) { + PC += OP1; + next(8); + } else { + next(4); + } + +d7 jne rel8 + if(!(PSW & F_Z)) { + PC += OP1; + next(8); + } else { + next(4); + } + +d8 jst rel8 + if(PSW & F_ST) { + PC += OP1; + next(8); + } else { + PSW &= ~F_VT; + next(4); + } + +d9 jh rel8 + if((PSW & (F_Z|F_N)) == F_C) { + PC += OP1; + next(8); + } else { + next(4); + } + +da jle rel8 + if(PSW & (F_Z|F_N)) { + PC += OP1; + next(8); + } else { + next(4); + } + +db jc rel8 + if(PSW & F_C) { + PC += OP1; + next(8); + } else { + next(4); + } + +dc jvt rel8 + if(PSW & F_VT) { + PSW &= ~F_VT; + PC += OP1; + next(8); + } else { + next(4); + } + +dd jv rel8 + if(PSW & F_V) { + PC += OP1; + next(8); + } else { + next(4); + } + +de jlt rel8 + if(PSW & F_N) { + PC += OP1; + next(8); + } else { + next(4); + } + +df je rel8 + if(PSW & F_Z) { + PC += OP1; + next(8); + } else { + next(4); + } + +e0 djnz rrel8 + TMP = reg_r8(OP2); + TMP = UINT8(TMP-1); + reg_w8(OP2, TMP); + if(TMP) { + PC += OP1; + next(9); + } else { + next(5); + } + +e1 djnzw rrel8 196 + TMP = reg_r16(OP2); + TMP = TMP-1; + reg_w16(OP2, TMP); + if(TMP) { + PC += OP1; + next(10); + } else { + next(6); + } + +e3 br indirect_1n + PC = OP1; + next(8); + +e7 ljmp rel16 + PC += OP1; + next(8); + +ef lcall rel16 + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, PC); + PC += OP1; + next(13); // +3 for external sp + +f0 ret none + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + PC = any_r16(TMP); + next(12); // +4 for external sp + +f2 pushf none + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, PSW); + PSW = 0x0000; + check_irq(); + next_noirq(8); // +4 for external sp + +f3 popf none + TMP = reg_r16(0x18); + reg_w16(0x18, TMP+2); + PSW = any_r16(TMP); + check_irq(); + next_noirq(9); // +4 for external sp + +f4 pusha none 196 + +f5 popa none + +f6 idlpd none 196 + +f7 trap none + TMP = reg_r16(0x18); + TMP -= 2; + reg_w16(0x18, TMP); + any_w16(TMP, PC); + PC = any_r16(0x2010); + next_noirq(21); // +3 for external sp + +f8 clrc none + PSW &= ~F_C; + next(4); + +f9 setc none + PSW |= F_C; + next(4); + +fa di none + PSW &= ~F_I; + check_irq(); + next_noirq(4); + +fb ei none + PSW |= F_I; + check_irq(); + next_noirq(4); + +fc clrvt none + PSW &= ~F_VT; + next(4); + +fd nop none + next(4); + +ff rst none + PC = 0x2080; + next(4); |