From 0cc1b379e5f64aa60d96bfed7950c4aa7310a39f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 6 Jan 2011 22:00:43 +0000 Subject: [PATCH] Added HD61700 CPU core used for emulate Casio PB-1000/PB-2000c in MESS [Sandro Ronco] --- .gitattributes | 3 + src/emu/cpu/cpu.mak | 13 + src/emu/cpu/hd61700/hd61700.c | 3062 ++++++++++++++++++++++++++++++++ src/emu/cpu/hd61700/hd61700.h | 192 ++ src/emu/cpu/hd61700/hd61700d.c | 437 +++++ 5 files changed, 3707 insertions(+) create mode 100644 src/emu/cpu/hd61700/hd61700.c create mode 100644 src/emu/cpu/hd61700/hd61700.h create mode 100644 src/emu/cpu/hd61700/hd61700d.c diff --git a/.gitattributes b/.gitattributes index c184778e47f..9d423159c26 100644 --- a/.gitattributes +++ b/.gitattributes @@ -142,6 +142,9 @@ src/emu/cpu/hcd62121/hcd62121.c svneol=native#text/plain src/emu/cpu/hcd62121/hcd62121.h svneol=native#text/plain src/emu/cpu/hcd62121/hcd62121_ops.h svneol=native#text/plain src/emu/cpu/hcd62121/hcd62121d.c svneol=native#text/plain +src/emu/cpu/hd61700/hd61700.c svneol=native#text/plain +src/emu/cpu/hd61700/hd61700.h svneol=native#text/plain +src/emu/cpu/hd61700/hd61700d.c svneol=native#text/plain src/emu/cpu/hd6309/6309dasm.c svneol=native#text/plain src/emu/cpu/hd6309/6309ops.c svneol=native#text/plain src/emu/cpu/hd6309/6309tbl.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index e69c65bf7a0..065618e7ea5 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -1784,3 +1784,16 @@ endif $(CPUOBJ)/pps4/pps4.o: $(CPUSRC)/pps4/pps4.c \ $(CPUSRC)/pps4/pps4.h + +#------------------------------------------------- +# Hitachi HD61700 +#------------------------------------------------- + +ifneq ($(filter HD61700,$(CPUS)),) +OBJDIRS += $(CPUOBJ)/hd61700 +CPUOBJS += $(CPUOBJ)/hd61700/hd61700.o +DASMOBJS += $(CPUOBJ)/hd61700/hd61700d.o +endif + +$(CPUOBJ)/hd61700/hd61700.o: $(CPUSRC)/hd61700/hd61700.c \ + $(CPUSRC)/hd61700/hd61700.h diff --git a/src/emu/cpu/hd61700/hd61700.c b/src/emu/cpu/hd61700/hd61700.c new file mode 100644 index 00000000000..626a432a8b4 --- /dev/null +++ b/src/emu/cpu/hd61700/hd61700.c @@ -0,0 +1,3062 @@ +/****************************************************************************** + + Hitachi HD61700 cpu core emulation. + by Sandro Ronco + + This CPU core is based on documentations works done by: + - Piotr Piatek ( http://www.pisi.com.pl/piotr433/pb1000he.htm ) + - BLUE ( http://www.geocities.jp/hd61700lab/ ) + + The HD61700 has 0x1800 bytes of internal ROM accessed as 16bit with address + shift by -1 (mapped from 0x0000 to 0x0c00), the external memory is accessed + with a 8bit data bus, this core emulate all memory as 16bit access with + address shifted by -1 and in the memory above 0x0c00 only the lower 8bit + are used. + + TODO: + - dasm don't decode some mnemonics + - CPU fast/slow mode + - probably other minor things + +******************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "hd61700.h" + +// internal ROM +#define INT_ROM 0x0c00 + +// 5 bit registers +#define REG_SX m_regsir[0] +#define REG_SY m_regsir[1] +#define REG_SZ m_regsir[2] +#define READ_SREG(a) (m_regsir[((a)>>5) & 0x03] & 0x1f) +#define WRITE_SREG(a,d) (m_regsir[((a)>>5) & 0x03] = (d) & 0x1f) + +// 8 bit registers +#define REG_PE m_reg8bit[0] +#define REG_PD m_reg8bit[1] +#define REG_IB m_reg8bit[2] +#define REG_UA m_reg8bit[3] +#define REG_IA m_reg8bit[4] +#define REG_IE m_reg8bit[5] +#define REG_TM m_reg8bit[7] +#define READ_REG8(a) (m_reg8bit[(a) & 0x07]) +#define WRITE_REG8(a,d) (m_reg8bit[(a) & 0x07] = d) + +// 16 bit registers +#define REG_IX m_reg16bit[0] +#define REG_IY m_reg16bit[1] +#define REG_IZ m_reg16bit[2] +#define REG_US m_reg16bit[3] +#define REG_SS m_reg16bit[4] +#define REG_KY m_reg16bit[5] + +// main registers +#define READ_REG(a) (m_regmain[(a) & 0x1f]) +#define WRITE_REG(a,d) (m_regmain[(a) & 0x1f] = d) +#define COPY_REG(d,s) (m_regmain[(d) & 0x1f] = m_regmain[(s) & 0x1f]) +#define REG_GET16(r) (((m_regmain[((r)) & 0x1f]<<0)) | (m_regmain[((r) + 1) & 0x1f]<<8)) +#define REG_PUT16(r,d) do{(m_regmain[(r) & 0x1f] = (((d)>>0) & 0xff)); (m_regmain[((r)+1)&0x1f]=(((d)>>8)&0xff));}while(0) + +// opcode +#define GET_REG_IDX(a,b) (((a<<2) & 0x04) | ((b>>5) & 0x03)) +#define RESTORE_REG(o,r,pr) r = (o&0x02) ? r : pr +#define COND_WRITE_REG(o,a,d) if (o&0x08) WRITE_REG(a,d) +#define GET_IM3(d) (((d>>5)&0x07) + 1) + +// flags +#define SET_FLAG_C m_flags |= FLAG_C +#define CLEAR_FLAG_Z m_flags |= FLAG_Z +#define CLEAR_FLAG_LZ m_flags |= FLAG_LZ +#define CLEAR_FLAG_UZ m_flags |= FLAG_UZ +#define CLEAR_FLAGS m_flags &= ~(FLAG_Z | FLAG_C | FLAG_LZ | FLAG_UZ) + +#define CHECK_FLAG_Z(d) if((d) != 0) CLEAR_FLAG_Z +#define CHECK_FLAG_C(d,l) if (d > l) SET_FLAG_C +#define CHECK_FLAGB_LZ(d) if(((d) & 0x0f) != 0) CLEAR_FLAG_LZ +#define CHECK_FLAGB_UZ(d) if(((d) & 0xf0) != 0) CLEAR_FLAG_UZ +#define CHECK_FLAGW_LZ(d) if(((d) & 0x0f00) != 0) CLEAR_FLAG_LZ +#define CHECK_FLAGW_UZ(d) if(((d) & 0xf000) != 0) CLEAR_FLAG_UZ +#define CHECK_FLAGB_UZ_LZ(d) do{CHECK_FLAGB_LZ(d); CHECK_FLAGB_UZ(d);}while(0) +#define CHECK_FLAGW_UZ_LZ(d) do{CHECK_FLAGW_LZ(d); CHECK_FLAGW_UZ(d);}while(0) + +//CPU state +#define CPU_FAST 0x01 +#define CPU_SLP 0x02 + +/* HD61700 IRQ vector */ +static const UINT16 irq_vector[] = {0x0032, 0x0042, 0x0052, 0x0062, 0x0072}; + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type HD61700 = hd61700_cpu_device_config::static_alloc_device_config; + + +//************************************************************************** +// HD61700 DEVICE CONFIG +//************************************************************************** + +//------------------------------------------------- +// hd61700_cpu_device_config - constructor +//------------------------------------------------- + +hd61700_cpu_device_config::hd61700_cpu_device_config(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock) + : cpu_device_config(mconfig, type, "HD61700", tag, owner, clock), + m_program_config("program", ENDIANNESS_BIG, 16, 18, -1) +{ +} + + +//------------------------------------------------- +// static_alloc_device_config - allocate a new +// configuration object +//------------------------------------------------- + +device_config *hd61700_cpu_device_config::static_alloc_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock ) +{ + return global_alloc(hd61700_cpu_device_config(mconfig, HD61700, tag, owner, clock)); +} + + +//------------------------------------------------- +// alloc_device - allocate a new device object +//------------------------------------------------- + +device_t *hd61700_cpu_device_config::alloc_device(running_machine &machine) const +{ + return pool_alloc(machine_get_pool(machine), hd61700_cpu_device(machine, *this)); +} + + +//------------------------------------------------- +// static_set_config - set the configuration +// structure +//------------------------------------------------- + +void hd61700_cpu_device_config::static_set_config(device_config *device, const hd61700_config &config) +{ + hd61700_cpu_device_config *conf = downcast(device); + *static_cast(conf) = config; +} + + +//************************************************************************** +// HD61700 DEVICE +//************************************************************************** + +//------------------------------------------------- +// hd61700_cpu_device - constructor +//------------------------------------------------- + +hd61700_cpu_device::hd61700_cpu_device(running_machine &machine, const hd61700_cpu_device_config &config) + : cpu_device(machine, config), + m_cpu_config(config) +{ + memset(&m_partial_frame_period, 0, sizeof(m_partial_frame_period)); +} + + +//------------------------------------------------- +// device_start - start up the device +//------------------------------------------------- + +void hd61700_cpu_device::device_start() +{ + m_program = this->space(AS_PROGRAM); + + m_sec_timer = device_timer_alloc(*this, SEC_TIMER); + timer_adjust_periodic(m_sec_timer, ATTOTIME_IN_SEC(1), 0, ATTOTIME_IN_SEC(1)); + + // save state + state_save_register_device_item(this, 0, m_ppc); + state_save_register_device_item(this, 0, m_curpc); + state_save_register_device_item(this, 0, m_pc); + state_save_register_device_item(this, 0, m_flags); + state_save_register_device_item(this, 0, m_fetch_addr); + state_save_register_device_item(this, 0, m_irq_status); + state_save_register_device_item(this, 0, m_state); + state_save_register_device_item(this, 0, prev_ua); + state_save_register_device_item(this, 0, m_icount); + state_save_register_device_item_array(this, 0, m_regsir); + state_save_register_device_item_array(this, 0, m_reg8bit); + state_save_register_device_item_array(this, 0, m_reg16bit); + state_save_register_device_item_array(this, 0, m_regmain); + state_save_register_device_item_array(this, 0, m_lines_status); + + // register state for debugger + state_add(HD61700_PC, "pc", m_pc).callimport().callexport().formatstr("%04X"); + state_add(HD61700_F, "f", m_flags).callimport().callexport().formatstr("%02X"); + state_add(HD61700_SX, "SX", REG_SX).callimport().callexport().formatstr("%02X"); + state_add(HD61700_SY, "SY", REG_SY).callimport().callexport().formatstr("%02X"); + state_add(HD61700_SZ, "SZ", REG_SZ).callimport().callexport().formatstr("%02X"); + + state_add(HD61700_PE, "pe", REG_PE).callimport().callexport().formatstr("%02X"); + state_add(HD61700_PD, "pd", REG_PD).callimport().callexport().formatstr("%02X"); + state_add(HD61700_IB, "ib", REG_IB).callimport().callexport().formatstr("%02X"); + state_add(HD61700_UA, "ua", REG_UA).callimport().callexport().formatstr("%02X"); + state_add(HD61700_IA, "ia", REG_IA).callimport().callexport().formatstr("%02X"); + state_add(HD61700_IE, "ie", REG_IE).callimport().callexport().formatstr("%02X"); + state_add(HD61700_TM, "tm", REG_TM).callimport().callexport().formatstr("%02X"); + + state_add(HD61700_IX, "ix", REG_IX).callimport().callexport().formatstr("%04X"); + state_add(HD61700_IY, "iy", REG_IY).callimport().callexport().formatstr("%04X"); + state_add(HD61700_IZ, "iz", REG_IZ).callimport().callexport().formatstr("%04X"); + state_add(HD61700_US, "us", REG_US).callimport().callexport().formatstr("%04X"); + state_add(HD61700_SS, "ss", REG_SS).callimport().callexport().formatstr("%04X"); + state_add(HD61700_KY, "ky", REG_KY).callimport().callexport().formatstr("%04X"); + + for (int ireg=0; ireg<32; ireg++) + { + astring tmpstr; + state_add(HD61700_MAINREG + ireg, tmpstr.format("R%d", ireg), m_regmain[ireg]).callimport().callexport().formatstr("%02X"); + } + + state_add(STATE_GENPC, "curpc", m_curpc).callimport().callexport().formatstr("%8s").noshow(); + state_add(STATE_GENPCBASE, "curpcbase", m_ppc).callimport().callexport().formatstr("%8s").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).mask(0xff).formatstr("%8s").noshow(); + + // set our instruction counter + m_icountptr = &m_icount; +} + + +//------------------------------------------------- +// device_reset - reset up the device +//------------------------------------------------- + +void hd61700_cpu_device::device_reset() +{ + m_ppc = 0x0000; + m_curpc = 0x0000; + set_pc(0x0000); + m_flags = FLAG_SW; + m_icount = 0; + m_state = 0; + m_irq_status = 0; + prev_ua = 0; + + memset(m_regsir, 0, ARRAY_LENGTH(m_regsir)); + memset(m_reg8bit, 0, ARRAY_LENGTH(m_reg8bit)); + memset(m_reg16bit, 0, ARRAY_LENGTH(m_reg16bit) * sizeof(UINT16)); + memset(m_regmain, 0, ARRAY_LENGTH(m_regmain)); + + for (int i=0;i<6; i++) + m_lines_status[i] = CLEAR_LINE; +} + + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- +void hd61700_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch(id) + { + case SEC_TIMER: + REG_TM++; + if ((REG_TM&0x3f) == 60) + { + REG_TM = (REG_TM & 0xc0) + 0x40; + + if (((REG_IE>>3) & (1<=0; i--) + { + if (REG_IB & (1<>8)&0xff); + push(REG_SS, (m_pc>>0)&0xff); + + set_pc(irq_vector[i]); + m_icount -= 12; + return true; + } + } + + return false; +} + + +//------------------------------------------------- +// execute - execute for the provided number of +// cycles +//------------------------------------------------- + +void hd61700_cpu_device::execute_run() +{ + do + { + debugger_instruction_hook(this, m_curpc); + + // verify that CPU is not in sleep + if (m_state & CPU_SLP) + { + m_icount -= 6; + } + else + { + UINT8 op; + + check_irqs(); + + m_ppc = m_curpc; + + // instruction fetch + op = read_op(); + + // execute the instruction + switch ( op ) + { + case 0x00: //adc + case 0x01: //sbc + case 0x08: //ad + case 0x09: //sb + { + UINT8 arg = read_op(); + UINT8 src = READ_REG(get_sir_im8(arg)); + UINT16 res = READ_REG(arg) + ((op&1) ? -src : +src); + + COND_WRITE_REG(op, arg, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x02: //ld + { + UINT8 arg = read_op(); + COPY_REG(arg, get_sir_im8(arg)); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x04: //anc + case 0x05: //nac + case 0x06: //orc + case 0x07: //xrc + case 0x0c: //an + case 0x0d: //na + case 0x0e: //or + case 0x0f: //xr + { + UINT8 arg = read_op(); + + UINT8 res = make_logic(op, READ_REG(arg), READ_REG(get_sir_im8(arg))); + + COND_WRITE_REG(op, arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + + //na(c) and or(c) always set C flag + if ((op&3) == 1 || (op&3) == 2) + SET_FLAG_C; + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x0a: //adb + case 0x0b: //sbb + { + UINT8 arg = read_op(); + UINT16 res; + + if (op & 0x01) + res = make_bcd_sub(READ_REG(arg), READ_REG(get_sir_im8(arg))); + else + res = make_bcd_add(READ_REG(arg), READ_REG(get_sir_im8(arg))); + + WRITE_REG(arg, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x10: //st + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT16 offset = REG_GET16(src); + + mem_writebyte(REG_UA>>4, offset, READ_REG(arg)); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x11: //ld + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT16 offset = REG_GET16(src); + + WRITE_REG(arg, mem_readbyte(REG_UA>>4, offset)); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x12: //stl + { + UINT8 arg = read_op(); + + if (m_cpu_config.m_lcd_data_w) + (*m_cpu_config.m_lcd_data_w)(*this, READ_REG(arg)); + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x13: //ldl + { + UINT8 arg = read_op(); + UINT8 res = 0xff; + + if (m_cpu_config.m_lcd_data_r) + res = (*m_cpu_config.m_lcd_data_r)(*this); + + WRITE_REG(arg, res); + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x14: //ppo/pfl + { + UINT8 arg = read_op(); + + if (arg & 0x40) + { + m_flags = (m_flags & 0x0f) | (READ_REG(arg) & 0xf0); + } + else + { + if (m_cpu_config.m_lcd_control) + (*m_cpu_config.m_lcd_control)(*this, READ_REG(arg)); + } + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x15: //psr + { + UINT8 arg = read_op(); + WRITE_SREG(arg, READ_REG(arg)&0x1f); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x16: //pst + case 0x17: //pst + { + UINT8 arg = read_op(); + UINT8 src = READ_REG(arg); + UINT8 idx = GET_REG_IDX(op, arg); + + switch (idx) + { + case 0: //PE + case 1: //PD + WRITE_REG8(idx, src); + if (m_cpu_config.m_port_w) + (*m_cpu_config.m_port_w)(*this, REG_PD & REG_PE); + break; + case 2: //IB + REG_IB = (REG_IB & 0x1f) | (src & 0xe0); + break; + case 3: //UA + WRITE_REG8(idx, src); + break; + case 4: //IA + if (m_cpu_config.m_kb_w) + (*m_cpu_config.m_kb_w)(*this, src); + WRITE_REG8(idx, src); + break; + case 5: //IE + REG_IB &= (((src>>3)&0x1f) | 0xe0); + m_irq_status &= ((src>>3)&0x1f); + WRITE_REG8(idx, src); + break; + case 6: //TM + case 7: //TM + // read-only + break; + } + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x18: + { + UINT8 arg = read_op(); + UINT8 op1 = (arg>>5) & 0x03; + switch (op1) + { + case 0x00: //rod + case 0x02: //bid + { + UINT8 src = READ_REG(arg); + UINT8 res = (src>>1)&0x7f; + + if (!(op1&0x02)) + res = res | ((m_flags&FLAG_C) !=0 )<<7; + + WRITE_REG(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + if (src&0x01) SET_FLAG_C; + } + break; + + case 0x01: //rou + case 0x03: //biu + { + UINT8 src = READ_REG(arg); + UINT8 res = (src<<1)&0xfe; + + if (!(op1&0x02)) + res = res | ((m_flags&FLAG_C) !=0 )<<0; + + WRITE_REG(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + if (src&0x80) SET_FLAG_C; + } + break; + } + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x1a: + { + UINT8 arg = read_op(); + UINT8 op1 = (arg>>5) & 0x03; + switch (op1) + { + case 0x00: //did + case 0x01: //diu + { + UINT8 res; + + if (op1&0x01) + res = (READ_REG(arg)<<4)&0xf0; + else + res = (READ_REG(arg)>>4)&0x0f; + + WRITE_REG(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + } + break; + case 0x02: //byd + case 0x03: //byu + { + WRITE_REG(arg, 0); + CLEAR_FLAGS; + break; + } + } + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x1b: //cmp/inv + { + UINT8 arg = read_op(); + UINT8 res = ~(READ_REG(arg)); + if (!(arg & 0x40)) res++; + + WRITE_REG(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + if (res || (arg & 0x40)) SET_FLAG_C; + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x1c: //gpo/gfl + { + UINT8 arg = read_op(); + UINT8 src = 0xff; + + if (arg&0x40) + { + src = m_flags; + } + else + { + if (m_cpu_config.m_port_r) + src = (*m_cpu_config.m_port_r)(*this); + + src&=(~REG_PE); + } + + WRITE_REG(arg, src); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x1d: //gsr + { + UINT8 arg = read_op(); + WRITE_REG(arg, READ_SREG(arg)); + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x1e: //gst + case 0x1f: //gst + { + UINT8 arg = read_op(); + UINT8 idx = GET_REG_IDX(op, arg); + WRITE_REG(arg, READ_REG8(idx)); + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x20: //st + case 0x22: //sti + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + REG_IX += get_sign_mreg(arg); + + mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg)); + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 8; + } + break; + + case 0x21: //st + case 0x23: //sti + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + REG_IZ += get_sign_mreg(arg); + + mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg)); + + RESTORE_REG(op, REG_IZ, prev_ir); + + m_icount -= 8; + } + break; + + case 0x24: //std + { + UINT8 arg = read_op(); + REG_IX += get_sign_mreg(arg); + + mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg)); + m_icount -= 6; + } + break; + + case 0x25: //std + { + UINT8 arg = read_op(); + REG_IZ += get_sign_mreg(arg); + + mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg)); + m_icount -= 6; + } + break; + + case 0x26: //phs + { + UINT8 arg = read_op(); + + push(REG_SS, READ_REG(arg)); + m_icount -= 9; + } + break; + case 0x27: //phu + { + UINT8 arg = read_op(); + + push(REG_US, READ_REG(arg)); + m_icount -= 9; + } + break; + + case 0x28: //ld + case 0x2a: //ldi + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + REG_IX += get_sign_mreg(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX++)); + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 8; + } + break; + + case 0x29: //ld + case 0x2b: //ldi + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + REG_IZ += get_sign_mreg(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ++)); + + RESTORE_REG(op, REG_IZ, prev_ir); + + m_icount -= 8; + } + break; + + case 0x2c: //ldd + { + UINT8 arg = read_op(); + REG_IX += get_sign_mreg(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX)); + + m_icount -= 6; + } + break; + + case 0x2d: //ldd + { + UINT8 arg = read_op(); + REG_IZ += get_sign_mreg(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ)); + + m_icount -= 6; + } + break; + + case 0x2e: //pps + { + UINT8 arg = read_op(); + WRITE_REG(arg, pop(REG_SS)); + + m_icount -= 11; + } + break; + case 0x2f: //ppu + { + UINT8 arg = read_op(); + WRITE_REG(arg, pop(REG_US)); + + m_icount -= 11; + } + break; + + case 0x30: //jp z + case 0x31: //jp nc + case 0x32: //jp lz + case 0x33: //jp uz + case 0x34: //jp nz + case 0x35: //jp c + case 0x36: //jp nlz + case 0x37: //unconditional jp + { + UINT8 lsb = read_op(); + if (m_pc < INT_ROM) read_op(); + UINT8 msb = read_op(); + + if (check_cond(op)) + set_pc((msb<<8) | lsb); + m_icount -= 3; + } + break; + + case 0x38: //adc + case 0x3a: //sbc + case 0x3c: //ad + case 0x3e: //sb + { + UINT8 arg = read_op(); + UINT16 offset = REG_IX + get_sign_mreg(arg); + UINT8 src = mem_readbyte(REG_UA>>4, offset); + + UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ; + + if ((op & 4)) + mem_writebyte(REG_UA>>4, offset, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x39: //adc + case 0x3b: //sbc + case 0x3d: //ad + case 0x3f: //sb + { + UINT8 arg = read_op(); + UINT16 offset = REG_IZ + get_sign_mreg(arg); + UINT8 src = mem_readbyte(REG_UA>>6, offset); + + UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ; + + if ((op & 4)) + mem_writebyte(REG_UA>>6, offset, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x40: //adc + case 0x41: //sbc + case 0x48: //ad + case 0x49: //sb + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + UINT16 res = READ_REG(arg) + ((op&1) ? -src : +src); + + COND_WRITE_REG(op, arg, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x42: //ld + { + UINT8 arg = read_op(); + UINT8 src = read_op() ; + + WRITE_REG(arg, src); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x44: //anc + case 0x45: //nac + case 0x46: //orc + case 0x47: //xrc + case 0x4c: //an + case 0x4d: //na + case 0x4e: //or + case 0x4f: //xr + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + + UINT8 res = make_logic(op, READ_REG(arg), src); + + COND_WRITE_REG(op, arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + + //na(c) and or(c) always set C flag + if ((op&3) == 1 || (op&3) == 2) + SET_FLAG_C; + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x4a: //adb + case 0x4b: //sbb + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + UINT16 res; + + if (op & 0x01) + res = make_bcd_sub(READ_REG(arg), src); + else + res = make_bcd_add(READ_REG(arg), src); + + WRITE_REG(arg, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 3; + } + break; + + case 0x50: //st + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + UINT16 offset = REG_GET16(READ_SREG(arg)); + + mem_writebyte(REG_UA>>4, offset, src); + m_icount -= 8; + } + break; + + case 0x51: //ld + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + + WRITE_REG(arg, src); + m_icount -= 8; + } + break; + + case 0x52: //stl + { + UINT8 arg = read_op(); + + if (m_cpu_config.m_lcd_data_w) + (*m_cpu_config.m_lcd_data_w)(*this, arg); + + m_icount -= 12; + } + break; + + case 0x54: //ppo/pfl + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + + if (arg & 0x40) + { + m_flags = (m_flags & 0x0f) | (src & 0xf0); + } + else + { + if (m_cpu_config.m_lcd_control) + (*m_cpu_config.m_lcd_control)(*this, src); + } + + m_icount -= 3; + } + break; + + case 0x55: //psr + { + UINT8 arg = read_op(); + WRITE_SREG(arg, arg&0x1f); + + m_icount -= 3; + } + break; + + case 0x56: //pst + case 0x57: //pst + { + UINT8 arg = read_op(); + UINT8 src = read_op(); + UINT8 idx = GET_REG_IDX(op, arg); + + switch (idx) + { + case 0: //PE + case 1: //PD + WRITE_REG8(idx, src); + if (m_cpu_config.m_port_w) + (*m_cpu_config.m_port_w)(*this, REG_PD & REG_PE); + break; + case 2: //IB + REG_IB = (REG_IB & 0x1f) | (src & 0xe0); + break; + case 3: //UA + WRITE_REG8(idx, src); + break; + case 4: //IA + if (m_cpu_config.m_kb_w) + (*m_cpu_config.m_kb_w)(*this, src); + WRITE_REG8(idx, src); + break; + case 5: //IE + REG_IB &= (((src>>3)&0x1f) | 0xe0); + m_irq_status &= ((src>>3)&0x1f); + WRITE_REG8(idx, src); + break; + case 6: //TM + case 7: //TM + // read-only + break; + } + + m_icount -= 3; + } + break; + + case 0x58: //bups + case 0x59: //bdns + { + UINT8 arg = read_op(); + UINT8 tmp; + UINT16 res; + + do + { + tmp = mem_readbyte(REG_UA>>4, REG_IX); + mem_writebyte(REG_UA>>6, REG_IZ, tmp); + + res = tmp - arg; + if (REG_IX == REG_IY) + break; + + REG_IX += ((op&1) ? -1 : +1); + REG_IZ += ((op&1) ? -1 : +1); + m_icount -= 6; + } while(res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x5c: //sup + case 0x5d: //sdn + { + UINT8 arg = read_op(); + UINT16 res; + + do + { + res = mem_readbyte(REG_UA>>4, REG_IX) - arg; + + if (REG_IX == REG_IY) + break; + + REG_IX += ((op&1) ? -1 : +1); + m_icount -= 6; + } while(res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x60: //st + case 0x62: //sti + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + REG_IX += get_sign_im8(arg); + + mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg)); + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 8; + } + break; + + case 0x61: //st + case 0x63: //sti + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + REG_IZ += get_sign_im8(arg); + + mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg)); + + RESTORE_REG(op, REG_IZ, prev_ir); + m_icount -= 8; + } + break; + + case 0x64: //std + { + UINT8 arg = read_op(); + REG_IX += get_sign_im8(arg); + + mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg)); + m_icount -= 6; + } + break; + + case 0x65: //std + { + UINT8 arg = read_op(); + REG_IZ += get_sign_im8(arg); + + mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg)); + m_icount -= 6; + } + break; + + case 0x68: //ld + case 0x6a: //ldi + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + REG_IX += get_sign_im8(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX++)); + + RESTORE_REG(op, REG_IX, prev_ir); + m_icount -= 8; + } + break; + + case 0x69: //ld + case 0x6b: //ldi + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + REG_IZ += get_sign_im8(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ++)); + + RESTORE_REG(op, REG_IZ, prev_ir); + m_icount -= 8; + } + break; + + case 0x6c: //ldd + { + UINT8 arg = read_op(); + REG_IX += get_sign_im8(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX)); + m_icount -= 6; + } + break; + + case 0x6d: //ldd + { + UINT8 arg = read_op(); + REG_IZ += get_sign_im8(arg); + + WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ)); + m_icount -= 6; + } + break; + + case 0x70: //cal z + case 0x71: //cal nc + case 0x72: //cal lz + case 0x73: //cal uz + case 0x74: //cal nz + case 0x75: //cal c + case 0x76: //cal nlz + case 0x77: //unconditional cal + { + UINT8 lsb = read_op(); + if (m_pc < INT_ROM) read_op(); + UINT8 msb = read_op(); + + if (check_cond(op)) + { + m_pc--; + push(REG_SS, (m_pc>>8)&0xff); + push(REG_SS, (m_pc>>0)&0xff); + + set_pc((msb<<8) | lsb); + m_icount -= 6; + } + m_icount -= 3; + } + break; + + case 0x78: //adc + case 0x7a: //sbc + case 0x7c: //ad + case 0x7e: //sb + { + UINT8 arg = read_op(); + UINT16 offset = REG_IX + get_sign_im8(arg); + UINT8 src = mem_readbyte(REG_UA>>4, offset); + + UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ; + + if ((op & 4)) + mem_writebyte(REG_UA>>4, offset, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x79: //adc + case 0x7b: //sbc + case 0x7d: //ad + case 0x7f: //sb + { + UINT8 arg = read_op(); + UINT16 offset = REG_IZ + get_sign_im8(arg); + UINT8 src = mem_readbyte(REG_UA>>6, offset); + + UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ; + + if ((op & 4)) + mem_writebyte(REG_UA>>6, offset, res & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0x80: //adcw + case 0x81: //sbcw + case 0x88: //adw + case 0x89: //sbw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT32 res = REG_GET16(arg) + ((op & 0x01) ? -REG_GET16(src) : +REG_GET16(src)); + + if (op & 0x08) REG_PUT16(arg, res&0xffff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xffff); + CHECK_FLAGW_UZ_LZ(res); + CHECK_FLAG_C(res, 0xffff); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x82: //ldw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + + COPY_REG(arg, src); + COPY_REG(arg+1, src+1); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x84: //ancw + case 0x85: //nacw + case 0x86: //orcw + case 0x87: //xrcw + case 0x8c: //anw + case 0x8d: //naw + case 0x8e: //orw + case 0x8f: //xrw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + + UINT8 res0 = make_logic(op, READ_REG(arg), READ_REG(src)); + COND_WRITE_REG(op, arg, res0); + + UINT8 res1 = make_logic(op, READ_REG(arg+1), READ_REG(src+1)); + COND_WRITE_REG(op, arg+1, res1); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res0 || res1); + CHECK_FLAGB_UZ_LZ(res1); + + //na(c) and or(c) always set C flag + if ((op&3) == 1 || (op&3) == 2) + SET_FLAG_C; + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x8a: //adbw + case 0x8b: //sbbw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT16 res0, res1; + + if (op & 0x01) + res0 = make_bcd_sub(READ_REG(arg), READ_REG(src)); + else + res0 = make_bcd_add(READ_REG(arg), READ_REG(src)); + + WRITE_REG(arg, res0 & 0xff); + + res1 = (res0>0xff) ? 1 : 0 ; + + if (op & 0x01) + res1 = make_bcd_sub(READ_REG(arg+1), READ_REG(src+1) + res1); + else + res1 = make_bcd_add(READ_REG(arg+1), READ_REG(src+1) + res1); + + WRITE_REG(arg+1, res1 & 0xff); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res0 || res1); + CHECK_FLAGB_UZ_LZ(res1); + CHECK_FLAG_C(res1, 0xff); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x90: //stw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT16 offset = REG_GET16(src); + + mem_writebyte(REG_UA>>4, offset+0, READ_REG(arg+0)); + mem_writebyte(REG_UA>>4, offset+1, READ_REG(arg+1)); + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x91: //ldw + { + UINT8 arg = read_op(); + UINT8 src = get_sir_im8(arg); + UINT16 offset = REG_GET16(src); + + WRITE_REG(arg+0, mem_readbyte(REG_UA>>4, offset+0)); + WRITE_REG(arg+1, mem_readbyte(REG_UA>>4, offset+1)); + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x92: //stlw + { + UINT8 arg = read_op(); + + if (m_cpu_config.m_lcd_data_w) + { + (*m_cpu_config.m_lcd_data_w)(*this, READ_REG(arg)); + (*m_cpu_config.m_lcd_data_w)(*this, READ_REG(arg+1)); + } + + check_optional_jr(arg); + m_icount -= 19; + } + break; + + case 0x93: //ldcw + { + UINT8 arg = read_op(); + UINT8 reg0, reg1; + + if (m_cpu_config.m_lcd_data_r) + { + reg0 = (*m_cpu_config.m_lcd_data_r)(*this); + reg1 = (*m_cpu_config.m_lcd_data_r)(*this); + } + else + reg0 = reg1 = 0xff; + + WRITE_REG(arg+0, reg0); + WRITE_REG(arg+1, reg1); + + check_optional_jr(arg); + m_icount -= 19; + } + break; + + case 0x96: //pre + case 0x97: //pre + { + UINT8 arg = read_op(); + UINT8 idx = GET_REG_IDX(op, arg); + + if (idx < 5) + m_reg16bit[idx] = REG_GET16(arg); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x98: //rodw + { + UINT8 arg = read_op(); + UINT8 op1 = (arg>>5) & 0x03; + switch (op1) + { + case 0x00: //rodw + case 0x02: //bidw + { + UINT16 src = REG_GET16(arg-1); + UINT16 res = (src>>1)&0x7fff; + + if (!(op1&0x02)) + res = res | ((m_flags&FLAG_C) !=0 )<<15; + + REG_PUT16(arg-1, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xffff); + CHECK_FLAGB_UZ_LZ(res); + if (src&0x01) SET_FLAG_C; + } + break; + + case 0x01: //rouw + case 0x03: //biuw + { + UINT16 src = REG_GET16(arg); + UINT16 res = (src<<1)&0xfffe; + + if (!(op1&0x02)) + res = res | ((m_flags&FLAG_C) !=0 )<<0; + + REG_PUT16(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xffff); + CHECK_FLAGW_UZ_LZ(res); + if (src&0x8000) SET_FLAG_C; + } + break; + } + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x9a: + { + UINT8 arg = read_op(); + UINT8 op1 = (arg>>5) & 0x03; + switch (op1) + { + case 0x00: //didw + { + UINT16 src = (REG_GET16(arg-1)>>4)&0x0fff; + REG_PUT16(arg-1, src); + + CLEAR_FLAGS; + CHECK_FLAG_Z(src & 0xffff); + CHECK_FLAGB_UZ_LZ(src); + } + break; + + case 0x01: //diuw + { + UINT16 src = (REG_GET16(arg)<<4)&0xfff0; + REG_PUT16(arg, src); + + CLEAR_FLAGS; + CHECK_FLAG_Z(src & 0xffff); + CHECK_FLAGW_UZ_LZ(src); + } + break; + + case 0x02: //bydw + { + UINT8 src = READ_REG(arg); + + WRITE_REG(arg, 0); + WRITE_REG(arg-1, src); + + CLEAR_FLAGS; + CHECK_FLAG_Z(src & 0xff); + CHECK_FLAGB_UZ_LZ(src); + } + break; + + case 0x03: //byuw + { + UINT8 src = READ_REG(arg); + + WRITE_REG(arg, 0); + WRITE_REG(arg+1, src); + + CLEAR_FLAGS; + CHECK_FLAG_Z(src & 0xff); + CHECK_FLAGB_UZ_LZ(src); + } + break; + } + + check_optional_jr(arg); + m_icount -= 11; + } + break; + + case 0x9b: //cmpw/invw + { + UINT8 arg = read_op(); + UINT16 res = ~(REG_GET16(arg)); + if (!(arg & 0x40)) res++; + + REG_PUT16(arg, res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xffff); + CHECK_FLAGW_UZ_LZ(res); + + if (res || (arg & 0x40)) SET_FLAG_C; + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x9c: //gpow/gflw + { + UINT8 arg = read_op(); + UINT8 reg0, reg1; + + if (arg&0x40) + { + reg0 = reg1 = m_flags; + } + else + { + if (m_cpu_config.m_port_r) + { + reg0 = (*m_cpu_config.m_port_r)(*this); + reg1 = (*m_cpu_config.m_port_r)(*this); + } + else + reg0 = reg1 = 0xff; + + reg0&=(~REG_PE); + reg1&=(~REG_PE); + + } + + WRITE_REG(arg+0, reg0); + WRITE_REG(arg+1, reg1); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0x9e: //gre + case 0x9f: //gre + { + UINT8 arg = read_op(); + UINT8 idx = GET_REG_IDX(op, arg); + UINT16 src; + + if (idx >= 5) + { + UINT16 port = 0xff; + + if (m_cpu_config.m_kb_r) + port = (*m_cpu_config.m_kb_r)(*this); + + src = (REG_KY & 0x0f00) | (port & 0xf0ff); + } + else + src = m_reg16bit[idx]; + + REG_PUT16(arg, src); + + check_optional_jr(arg); + m_icount -= 8; + } + break; + + case 0xa0: //stw + case 0xa2: //stiw + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg+0)); + mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg+1)); + + RESTORE_REG(op, REG_IX, prev_ir); + m_icount -= 11; + } + break; + + case 0xa1: //stw + case 0xa3: //stiw + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg+0)); + mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg+1)); + + RESTORE_REG(op, REG_IZ, prev_ir); + m_icount -= 11; + } + break; + + case 0xa4: //stdw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + mem_writebyte(REG_UA>>4, REG_IX--, READ_REG(arg-0)); + mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg-1)); + + m_icount -= 9; + } + break; + case 0xa5: //stdw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + mem_writebyte(REG_UA>>6, REG_IZ--, READ_REG(arg-0)); + mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg-1)); + + m_icount -= 9; + } + break; + + case 0xa6: //phsw + { + UINT8 arg = read_op(); + push(REG_SS, READ_REG(arg)); + push(REG_SS, READ_REG(arg-1)); + + m_icount -= 12; + } + break; + case 0xa7: //phuw + { + UINT8 arg = read_op(); + push(REG_US, READ_REG(arg)); + push(REG_US, READ_REG(arg-1)); + + m_icount -= 12; + } + break; + + case 0xa8: //ldw + case 0xaa: //ldiw + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IX; + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + WRITE_REG(arg+0, mem_readbyte(REG_UA>>4, REG_IX++)); + WRITE_REG(arg+1, mem_readbyte(REG_UA>>4, REG_IX++)); + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 11; + } + break; + + case 0xa9: //ldw + case 0xab: //ldiw + { + UINT8 arg = read_op(); + UINT16 prev_ir = REG_IZ; + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + WRITE_REG(arg+0, mem_readbyte(REG_UA>>6, REG_IZ++)); + WRITE_REG(arg+1, mem_readbyte(REG_UA>>6, REG_IZ++)); + + RESTORE_REG(op, REG_IZ, prev_ir); + + m_icount -= 11; + } + break; + + case 0xac: //lddw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + WRITE_REG(arg-0, mem_readbyte(REG_UA>>4, REG_IX--)); + WRITE_REG(arg-1, mem_readbyte(REG_UA>>4, REG_IX)); + + m_icount -= 9; + } + break; + + case 0xad: //lddw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + WRITE_REG(arg-0, mem_readbyte(REG_UA>>6, REG_IZ--)); + WRITE_REG(arg-1, mem_readbyte(REG_UA>>6, REG_IZ)); + + m_icount -= 9; + } + break; + + case 0xae: //ppsw + case 0xaf: //ppuw + { + UINT8 arg = read_op(); + + WRITE_REG(arg, pop((op&1) ? REG_US : REG_SS)); + WRITE_REG(arg+1, pop((op&1) ? REG_US : REG_SS)); + + m_icount -= 14; + } + break; + + case 0xb0: //jr z + case 0xb1: //jr nc + case 0xb2: //jr lz + case 0xb3: //jr uz + case 0xb4: //jr nz + case 0xb5: //jr c + case 0xb6: //jr nlz + case 0xb7: //unconditional jr + { + UINT8 arg = read_op(); + UINT32 new_pc = m_pc-1 + get_im_7(arg); + + if (check_cond(op)) + set_pc(new_pc); + m_icount -= 3; + } + break; + + case 0xb8: //adcw + case 0xbc: //adw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + UINT16 offset = REG_IX + ((arg & 0x80) ? -ir_inc : +ir_inc); + + UINT16 src0 = mem_readbyte(REG_UA>>4, offset) + READ_REG(arg); + UINT16 src1 = mem_readbyte(REG_UA>>4, offset+1) + READ_REG(arg+1) + ((src0>0xff) ? 1 : 0); + + if (op&0x04) + { + mem_writebyte(REG_UA>>4, offset+0, src0 & 0xff); + mem_writebyte(REG_UA>>4, offset+1, src1 & 0xff); + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(src1); + CHECK_FLAG_Z(src0 || src1); + CHECK_FLAG_C(src1, 0xff); + + m_icount -= 15; + } + break; + + case 0xba: //sbcw + case 0xbe: //sbw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + UINT16 offset = REG_IX + ((arg & 0x80) ? -ir_inc : +ir_inc); + + UINT16 src0 = mem_readbyte(REG_UA>>4, offset) - READ_REG(arg); + UINT16 src1 = mem_readbyte(REG_UA>>4, offset+1) - READ_REG(arg+1) - ((src0>0xff) ? 1 : 0); + + if (op&0x04) + { + mem_writebyte(REG_UA>>4, offset+0, src0 & 0xff); + mem_writebyte(REG_UA>>4, offset+1, src1 & 0xff); + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(src1); + CHECK_FLAG_Z(src0 || src1); + CHECK_FLAG_C(src1, 0xff); + + m_icount -= 15; + } + break; + + case 0xb9: //adcw + case 0xbd: //adw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + UINT16 offset = REG_IZ + ((arg & 0x80) ? -ir_inc : +ir_inc); + + UINT16 src0 = mem_readbyte(REG_UA>>6, offset) + READ_REG(arg); + UINT16 src1 = mem_readbyte(REG_UA>>6, offset+1) + READ_REG(arg+1) + ((src0>0xff) ? 1 : 0); + + if (op&0x04) + { + mem_writebyte(REG_UA>>6, offset+0, src0 & 0xff); + mem_writebyte(REG_UA>>6, offset+1, src1 & 0xff); + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(src1); + CHECK_FLAG_Z(src0 || src1); + CHECK_FLAG_C(src1, 0xff); + + m_icount -= 15; + } + break; + + case 0xbb: //sbcw + case 0xbf: //sbw + { + UINT8 arg = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg)); + + UINT16 offset = REG_IZ + ((arg & 0x80) ? -ir_inc : +ir_inc); + + UINT16 src0 = mem_readbyte(REG_UA>>6, offset) - READ_REG(arg); + UINT16 src1 = mem_readbyte(REG_UA>>6, offset+1) - READ_REG(arg+1) - ((src0>0xff) ? 1 : 0); + + if (op&0x04) + { + mem_writebyte(REG_UA>>6, offset+0, src0 & 0xff); + mem_writebyte(REG_UA>>6, offset+1, src1 & 0xff); + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(src1); + CHECK_FLAG_Z(src0 || src1); + CHECK_FLAG_C(src1, 0xff); + + m_icount -= 15; + } + break; + + case 0xc0: //adbcm + case 0xc1: //sbbcm + case 0xc8: //adbm + case 0xc9: //sbbm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 dst = arg; + UINT8 src = get_sir_im8(arg, arg1); + UINT8 c, f; + UINT16 res = 0; + + c = f = 0; + for (int n=GET_IM3(arg1); n>0; n--) + { + if (op & 0x01) + res = make_bcd_sub(READ_REG(dst), READ_REG(src) + c); + else + res = make_bcd_add(READ_REG(dst), READ_REG(src) + c); + + c = (res > 0xff) ? 1 : 0; + + COND_WRITE_REG(op, dst, res&0xff); + + f |= (res&0xff); + dst++; src++; + + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAG_Z(f); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 2; + } + break; + + case 0xc2: //ldm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 dst = arg; + UINT8 src = get_sir_im8(arg, arg1); + + for (int n=GET_IM3(arg1); n>0; n--) + { + COPY_REG(dst++, src++); + m_icount -= 5; + } + + check_optional_jr(arg); + m_icount -= 2; + } + break; + + case 0xc4: //ancm + case 0xc5: //nacm + case 0xc6: //orcm + case 0xc7: //xrcm + case 0xcc: //anm + case 0xcd: //nam + case 0xce: //orm + case 0xcf: //xrm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 dst = arg; + UINT8 src = get_sir_im8(arg, arg1); + UINT8 res = 0, f = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + res = make_logic(op, READ_REG(dst), READ_REG(src)); + + COND_WRITE_REG(op, dst, res); + + f |= res; + + dst++; src++; + + m_icount -= 3; + } + + CLEAR_FLAGS; + CHECK_FLAG_Z(f); + CHECK_FLAGB_UZ_LZ(res); + + //na(c) and or(c) always set C flag + if ((op&3) == 1 || (op&3) == 2) + SET_FLAG_C; + + check_optional_jr(arg); + } + break; + + case 0xca: //adbm + case 0xcb: //sbbm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 dst = arg; + UINT16 res = 0; + UINT8 src, f; + src = arg1 & 0x1f; + f = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + if (op & 0x01) + res = make_bcd_sub(READ_REG(dst), src); + else + res = make_bcd_add(READ_REG(dst), src); + + src = (res > 0xff) ? 1 : 0; + + COND_WRITE_REG(op, dst, res&0xff); + + f |= (res&0xff); + dst++; + + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAG_Z(f); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + check_optional_jr(arg); + m_icount -= 2; + } + break; + + case 0xd0: //stw + { + UINT8 arg = read_op(); + UINT16 offset = REG_GET16(READ_SREG(arg)); + + mem_writebyte(REG_UA>>4, offset+0, read_op()); + mem_writebyte(REG_UA>>4, offset+1, read_op()); + + m_icount -= 11; + } + break; + + case 0xd1: //ldw + { + UINT8 arg = read_op(); + UINT8 reg0 = read_op(); + UINT8 reg1 = read_op(); + + WRITE_REG(arg+0, reg0); + WRITE_REG(arg+1, reg1); + m_icount -= 11; + } + break; + + case 0xd2: //stlm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + + for (int n=GET_IM3(arg1); n>0; n--) + { + if (m_cpu_config.m_lcd_data_w) + (*m_cpu_config.m_lcd_data_w)(*this, READ_REG(arg)); + + arg++; + m_icount -= 8; + } + + m_icount -= 3; + } + break; + + case 0xd3: //ldlm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 src; + + for (int n=GET_IM3(arg1); n>0; n--) + { + if (m_cpu_config.m_lcd_data_r) + src = (*m_cpu_config.m_lcd_data_r)(*this); + else + src = 0xff; + + WRITE_REG(arg, src++); + + m_icount -= 8; + } + + m_icount -= 3; + } + break; + + case 0xd6: //pre + case 0xd7: //pre + { + UINT8 arg = read_op(); + UINT8 lsb = read_op(); + UINT8 msb = read_op(); + UINT8 idx = GET_REG_IDX(op, arg); + + if (idx < 5) + m_reg16bit[idx] = (msb<<8) | lsb; + + m_icount -= 8; + } + break; + + case 0xd8: //bup + case 0xd9: //bdn + { + UINT8 src; + for(;;) + { + src = mem_readbyte(REG_UA>>4, REG_IX); + mem_writebyte(REG_UA>>6, REG_IZ, src); + + if (REG_IX == REG_IY) + break; + + REG_IX += ((op&1) ? -1 : +1); + REG_IZ += ((op&1) ? -1 : +1); + m_icount -= 6; + } + + m_icount -= 9; + } + break; + + case 0xda: + { + UINT8 arg = read_op(); + UINT8 op1 = (arg>>5) & 0x03; + switch (op1) + { + case 0x00: //didm + { + UINT8 arg1 = read_op(); + UINT8 r1 = 0, r2 = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + r2 = r1; + r1 = READ_REG(arg); + r2 = ((r1>>4)&0x0f) | ((r2<<4)&0xf0); + WRITE_REG(arg--, r2); + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(r2); + CHECK_FLAG_Z(r2); + } + break; + + case 0x01: //dium + { + UINT8 arg1 = read_op(); + UINT8 r1 = 0, r2 = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + r2 = r1; + r1 = READ_REG(arg); + r2 = ((r1<<4)&0xf0) | ((r2>>4)&0x0f); + WRITE_REG(arg++, r2); + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(r2); + CHECK_FLAG_Z(r2); + } + break; + + case 0x02: //bydm + { + UINT8 arg1 = read_op(); + UINT8 r1 = 0, r2 = 0, f = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + r2 = r1; + r1 = READ_REG(arg); + WRITE_REG(arg--, r2); + f |= r2; + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(r2); + CHECK_FLAG_Z(f); + } + break; + + case 0x03: //byum + { + UINT8 arg1 = read_op(); + UINT8 r1 = 0, r2 = 0, f = 0; + + for (int n=GET_IM3(arg1); n>0; n--) + { + r2 = r1; + r1 = READ_REG(arg); + WRITE_REG(arg++, r2); + f |= r2; + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAGB_UZ_LZ(r2); + CHECK_FLAG_Z(f); + } + break; + } + } + break; + + case 0xdb: //cmpm/invm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 r1 = 0, r2 = 0, f = 0; + + r2 = (arg&0x40) ? 0 : 1; + + for (int n=GET_IM3(arg1); n>0; n--) + { + r1 = r2 + (~READ_REG(arg)); + WRITE_REG(arg++, r1); + if (r1) r2 = 0; + + f |= r1; + + m_icount -= 5; + } + + CLEAR_FLAGS; + CHECK_FLAG_Z(f); + CHECK_FLAGB_UZ_LZ(r1); + if (f != 0 || (arg & 0x40)) + SET_FLAG_C; + } + break; + + case 0xdc: //sup + case 0xdd: //sdn + { + UINT8 arg = read_op(); + UINT16 res; + + do + { + res = mem_readbyte(REG_UA>>4, REG_IX) - READ_REG(arg); + + if (REG_IX == REG_IY) + break; + + REG_IX += ((op&1) ? -1 : +1); + m_icount -= 6; + } while(res); + + CLEAR_FLAGS; + CHECK_FLAG_Z(res & 0xff); + CHECK_FLAGB_UZ_LZ(res); + CHECK_FLAG_C(res, 0xff); + + m_icount -= 9; + } + break; + + case 0xde: //jp + { + UINT8 arg = read_op(); + set_pc(REG_GET16(arg)); + + m_icount -= 5; + } + break; + + case 0xdf: //jp + { + UINT8 arg = read_op(); + UINT16 offset = REG_GET16(arg); + UINT8 lsb = mem_readbyte(REG_UA>>4, offset+0); + UINT8 msb = mem_readbyte(REG_UA>>4, offset+1); + + set_pc((msb<<8) | lsb); + + m_icount -= 5; + } + break; + + case 0xe0: //stm + case 0xe2: //stim + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT16 prev_ir = REG_IX; + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg++)); + m_icount -= 3; + } + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 5; + } + break; + + case 0xe1: //stm + case 0xe3: //stim + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT16 prev_ir = REG_IZ; + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg++)); + m_icount -= 3; + } + + RESTORE_REG(op, REG_IZ, prev_ir); + + m_icount -= 5; + } + break; + + case 0xe4: //stdm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + mem_writebyte(REG_UA>>4, REG_IX--, READ_REG(arg--)); + m_icount -= 3; + } + + REG_IX++;//todo + + m_icount -= 3; + } + break; + + case 0xe5: //stdm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + mem_writebyte(REG_UA>>6, REG_IZ--, READ_REG(arg--)); + m_icount -= 3; + } + + REG_IZ++; + + m_icount -= 3; + } + break; + + case 0xe6: //phsm + case 0xe7: //phum + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + + for (int n=GET_IM3(arg1); n>0; n--) + { + push((op&1) ? REG_US : REG_SS, READ_REG(arg--)); + + m_icount -= 3; + } + + m_icount -= 3; + } + break; + + case 0xe8: //ldm + case 0xea: //ldim + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT16 prev_ir = REG_IX; + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + WRITE_REG(arg++, mem_readbyte(REG_UA>>4, REG_IX++)); + m_icount -= 3; + } + + RESTORE_REG(op, REG_IX, prev_ir); + + m_icount -= 5; + } + break; + + case 0xe9: //ldm + case 0xeb: //ldim + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT16 prev_ir = REG_IZ; + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + WRITE_REG(arg++, mem_readbyte(REG_UA>>6, REG_IZ++)); + m_icount -= 3; + } + + RESTORE_REG(op, REG_IZ, prev_ir); + + m_icount -= 5; + } + break; + + case 0xec: //lddm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + WRITE_REG(arg--, mem_readbyte(REG_UA>>4, REG_IX--)); + m_icount -= 3; + } + + REG_IX++; + + m_icount -= 3; + } + break; + + case 0xed: //lddm + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1)); + + REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc); + + for (int n=GET_IM3(arg1); n>0; n--) + { + WRITE_REG(arg--, mem_readbyte(REG_UA>>6, REG_IZ--)); + m_icount -= 3; + } + + REG_IZ++; + + m_icount -= 3; + } + break; + + case 0xee: //ppsm + case 0xef: //ppum + { + UINT8 arg = read_op(); + UINT8 arg1 = read_op(); + + for (int n=GET_IM3(arg1); n>0; n--) + { + WRITE_REG(arg++, pop((op&1) ? REG_US : REG_SS)); + m_icount -= 3; + } + + m_icount -= 5; + } + break; + + case 0xf0: //rtn z + case 0xf1: //rtn nc + case 0xf2: //rtn lz + case 0xf3: //rtn uz + case 0xf4: //rtn nz + case 0xf5: //rtn c + case 0xf6: //rtn nlz + case 0xf7: //unconditional rtn + { + if (check_cond(op)) + { + UINT8 lsb = pop(REG_SS) ; + UINT8 msb = pop(REG_SS); + + set_pc((((msb<<8) | (lsb<<0)) + 1)); + } + m_icount -= 3; + } + break; + + case 0xf8: //nop + m_icount -= 3; + break; + + case 0xf9: //clt + REG_TM = 0; + m_icount -= 3; + break; + + case 0xfa: //fst + m_state |= CPU_FAST; + m_icount -= 3; + break; + + case 0xfb: //slw + m_state &= ~CPU_FAST; + m_icount -= 3; + break; + + case 0xfd: //rtni + { + UINT8 lsb = pop(REG_SS); + UINT8 msb = pop(REG_SS); + + set_pc((msb<<8) | (lsb<<0)); + + m_icount -= 5; + } + //fall through + + case 0xfc: //cani + { + for (UINT8 arg=0x10; arg>0; arg>>=1) + { + if (REG_IB & arg) + { + REG_IB &= (~arg); + m_irq_status &= (~arg); + break; + } + } + + m_icount -= 3; + } + break; + + case 0xfe: //off + { + set_pc(0); + REG_UA = REG_IA = 0; + REG_IX = REG_IY = REG_IZ = 0; + REG_PE = 0; + REG_IE = (REG_IE&0x0c) | ((REG_IB>1) & 0x10); + REG_IB &= 0xe3; + if (m_flags & FLAG_SW) + m_flags |= FLAG_APO; + else + m_flags &= ~FLAG_APO; + + m_state |= CPU_SLP; + + m_irq_status = 0; + if (m_cpu_config.m_lcd_control) + (*m_cpu_config.m_lcd_control)(*this, 0); + + if (m_cpu_config.m_kb_w) + (*m_cpu_config.m_kb_w)(*this, 0); + m_icount -= 3; + } + break; + + case 0xff: //trp + { + m_pc--; + push(REG_SS, (m_pc>>8)&0xff); + push(REG_SS, (m_pc>>0)&0xff); + set_pc(0x0022); + m_icount -= 9; + } + break; + + case 0x03: + case 0x19: + case 0x43: + case 0x53: + case 0x5a: + case 0x5b: + case 0x5e: + case 0x5f: + case 0x66: + case 0x67: + case 0x6e: + case 0x6f: + case 0x83: + case 0x94: + case 0x95: + case 0x99: + case 0x9d: + case 0xc3: + case 0xd4: + case 0xd5: + logerror( "%06x: illegal instruction %02x encountered\n", m_pc, op ); + break; + + default: + logerror( "%06x: unimplemented instruction %02x encountered\n", m_pc, op ); + break; + } + } + + //if is in the internal ROM align the pc + if ((m_fetch_addr&1) && m_pc < INT_ROM) + set_pc((m_fetch_addr+1)>>1); + + m_icount -= 3; + } while (m_icount > 0); +} + + +//------------------------------------------------- +// execute_set_input +//------------------------------------------------- + +void hd61700_cpu_device::execute_set_input(int inputnum, int state) +{ + switch (inputnum) + { + case INPUT_LINE_RESET: + REG_UA = 0; + REG_IA = 0; + REG_IX = 0; + REG_IY = 0; + REG_IZ = 0; + REG_PE = 0; + REG_IE = 0; + REG_IB = 0; + m_state &= ~(CPU_SLP | CPU_FAST); + set_pc(0x0000); + break; + case HD61700_KEY_INT: //level sensitive line + if (((REG_IE>>3) & (1<>3) & (1<>3) & (1<>3) & (1<read_word(addr18<<1); + + if (!(m_fetch_addr&1)) + data = (data>>8) ; + } + else + { + if (m_fetch_addr&1) + data = m_program->read_word((addr18+1)<<1); + else + data = m_program->read_word((addr18+0)<<1); + } + + m_fetch_addr += ((m_pc > INT_ROM) ? 2 : 1); + + m_pc = m_fetch_addr>>1; + + m_curpc = make_18bit_addr((m_irq_status) ? 0 : prev_ua, m_pc); + + prev_ua = REG_UA; + + return (data&0xff); +} + +inline UINT8 hd61700_cpu_device::mem_readbyte(UINT8 segment, UINT16 offset) +{ + return m_program->read_word(make_18bit_addr(segment, offset)<<1) & 0xff; +} + +inline void hd61700_cpu_device::mem_writebyte(UINT8 segment, UINT16 offset, UINT8 data) +{ + m_program->write_word(make_18bit_addr(segment, offset)<<1, data); +} + +inline UINT32 hd61700_cpu_device::make_18bit_addr(UINT8 segment, UINT16 offset) +{ + if (offset >= ((REG_IB>>6) & 0x03) * 0x4000) + return (UINT32)((offset | ((segment&0x03)<<16)) & 0x3ffff); + else + return offset; +} + +inline void hd61700_cpu_device::push(UINT16 &offset, UINT8 data) +{ + offset--; + mem_writebyte(REG_UA>>2, offset, data); +} + +inline UINT8 hd61700_cpu_device::pop(UINT16 &offset) +{ + UINT8 data = mem_readbyte(REG_UA>>2, offset); + offset++; + return data; +} + +inline int hd61700_cpu_device::check_cond(UINT32 op) +{ + switch ( op & 0x07 ) + { + case 0x00: // Z set + if ( !(m_flags & FLAG_Z) ) + return 1; + break; + + case 0x01: // NC set + if ( !(m_flags & FLAG_C) ) + return 1; + break; + + case 0x02: // LZ set + if ( !(m_flags & FLAG_LZ) ) + return 1; + break; + + case 0x03: // UZ set + if ( !(m_flags & FLAG_UZ) ) + return 1; + break; + + case 0x04: // NZ set + if ( m_flags & FLAG_Z ) + return 1; + break; + + case 0x05: // C set + if ( m_flags & FLAG_C ) + return 1; + break; + + case 0x06: // NLZ clear + if ( m_flags & FLAG_LZ ) + return 1; + break; + + case 0x07: // unconditional + return 1; + break; + } + + return 0; +} + +inline UINT8 hd61700_cpu_device::make_logic(UINT8 type, UINT8 d1, UINT8 d2) +{ + switch (type&3) + { + case 0: //and + return d1 & d2; + case 1: //nand + return ~(d1 & d2); + case 2: //or + return d1 | d2; + case 3: //xor + return d1 ^ d2; + default: + return 0x00; + } +} + +inline void hd61700_cpu_device::check_optional_jr(UINT8 arg) +{ + if (arg & 0x80) + { + if (m_pc < INT_ROM && !(m_fetch_addr&1)) read_op(); + + UINT8 arg1 = read_op(); + + UINT32 new_pc = m_pc + get_im_7(arg1) - 1; + + set_pc(new_pc); + m_icount -= 3; + } +} + +inline UINT8 hd61700_cpu_device::get_sir_im8(UINT8 arg) +{ + if (((arg>>5) & 0x03) == 0x03) + { + UINT8 arg1 = read_op(); + + return arg1&0x1f; + } + else + { + return READ_SREG(arg)&0x1f; + } +} + +inline UINT8 hd61700_cpu_device::get_sir_im8(UINT8 arg, UINT8 arg1) +{ + if (((arg>>5) & 0x03) == 0x03) + { + return arg1&0x1f; + } + else + { + return READ_SREG(arg)&0x1f; + } +} + +inline int hd61700_cpu_device::get_sign_mreg(UINT8 arg) +{ + int res = READ_REG(get_sir_im8(arg)); + + if (arg & 0x80) res = -res; + + return res; +} + +inline int hd61700_cpu_device::get_sign_im8(UINT8 arg) +{ + int res = read_op(); + + if (arg & 0x80) res = -res; + + return res; +} + +inline int hd61700_cpu_device::get_im_7(UINT8 data) +{ + if (data&0x80) + return 0x80 - data; + else + return data; +} + +inline UINT16 hd61700_cpu_device::make_bcd_sub(UINT8 arg1, UINT8 arg2) +{ + + UINT32 ret = (arg1&0x0f) - (arg2&0x0f); + UINT8 carry; + + if (ret > 0x09) + { + ret = (ret - 0x06) & 0x0f; + carry = 1; + } + else + carry = 0; + + ret += ((arg1&0xf0) - (arg2&0xf0) - (carry<<4)); + + if (ret > 0x9f) + { + ret = (ret - 0x60) & 0x0ff; + carry = 1; + } + else + carry = 0; + + ret -= (carry<<8); + + return ret; +} + +inline UINT16 hd61700_cpu_device::make_bcd_add(UINT8 arg1, UINT8 arg2) +{ + UINT32 ret = (arg1&0x0f) + (arg2&0x0f); + UINT8 carry; + + if (ret > 0x09) + { + ret = (ret + 0x06) & 0x0f; + carry = 1; + } + else + carry = 0; + + ret += ((arg1&0xf0) + (arg2&0xf0) + (carry<<4)); + + if (ret > 0x9f) + { + ret = (ret + 0x60) & 0x0ff; + carry = 1; + } + else + carry = 0; + + ret += (carry<<8); + + return ret; +} diff --git a/src/emu/cpu/hd61700/hd61700.h b/src/emu/cpu/hd61700/hd61700.h new file mode 100644 index 00000000000..76dc22d1ffa --- /dev/null +++ b/src/emu/cpu/hd61700/hd61700.h @@ -0,0 +1,192 @@ +/********************************************************************** + + Hitachi HD61700 + +**********************************************************************/ + +#pragma once + +#ifndef __HD61700_H__ +#define __HD61700_H__ + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_HD61700_CONFIG(_config) \ + hd61700_cpu_device_config::static_set_config(device, _config); \ + +//************************************************************************** +// DEVICE TYPE DEFINITION +//************************************************************************** + +extern const device_type HD61700; + +//************************************************************************** +// DEFINITIONS +//************************************************************************** + +// class definition +class hd61700_cpu_device; +class hd61700_cpu_device_config; + +// cpu port callbacks types +typedef void (*hd61700_lcd_control_func)(hd61700_cpu_device &device, UINT8 data); +typedef UINT8 (*hd61700_lcd_data_r_func)(hd61700_cpu_device &device); +typedef void (*hd61700_lcd_data_w_func)(hd61700_cpu_device &device, UINT8 data); +typedef UINT16 (*hd61700_kb_r_func)(hd61700_cpu_device &device); +typedef void (*hd61700_kb_w_func)(hd61700_cpu_device &device, UINT8 matrix); +typedef UINT8 (*hd61700_port_r_func)(hd61700_cpu_device &device); +typedef void (*hd61700_port_w_func)(hd61700_cpu_device &device, UINT8 data); + +// device config +struct hd61700_config +{ + hd61700_lcd_control_func m_lcd_control; //lcd control + hd61700_lcd_data_r_func m_lcd_data_r; //lcd data read + hd61700_lcd_data_w_func m_lcd_data_w; //lcd data write + hd61700_kb_r_func m_kb_r; //keyboard matrix read + hd61700_kb_w_func m_kb_w; //keyboard matrix write + hd61700_port_r_func m_port_r; //8 bit port read + hd61700_port_w_func m_port_w; //8 bit port write +}; + + +// registers +enum +{ + HD61700_PC=1, HD61700_F, HD61700_SX, HD61700_SY, HD61700_SZ, HD61700_PE, HD61700_PD, + HD61700_IB, HD61700_UA, HD61700_IA, HD61700_IE, HD61700_TM, HD61700_IX, + HD61700_IY, HD61700_IZ, HD61700_US, HD61700_SS, HD61700_KY, HD61700_MAINREG, +}; + +// input lines +enum +{ + HD61700_ON_INT, + HD61700_TIMER_INT, + HD61700_INT2, + HD61700_KEY_INT, + HD61700_INT1, + HD61700_SW +}; + + +// ======================> hd61700_cpu_device_config + +class hd61700_cpu_device_config : public cpu_device_config, + public hd61700_config +{ + friend class hd61700_cpu_device; + +protected: + // construction/destruction + hd61700_cpu_device_config(const machine_config &mconfig, device_type _type, const char *_tag, const device_config *_owner, UINT32 _clock); + +public: + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + + // inline configuration helpers + static void static_set_config(device_config *device, const hd61700_config &config); +protected: + // device_config_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 1; } + virtual UINT32 execute_max_cycles() const { return 52; } + virtual UINT32 execute_input_lines() const { return 6; } + + // device_config_memory_interface overrides + virtual const address_space_config *memory_space_config(int spacenum = 0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } + + // device_config_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 1; } + virtual UINT32 disasm_max_opcode_bytes() const { return 16; } + + // internal state + address_space_config m_program_config; +}; + + +// ======================> hd61700_cpu_device + +class hd61700_cpu_device : public cpu_device +{ + friend class hd61700_cpu_device_config; + +protected: + // construction/destruction + hd61700_cpu_device(running_machine &machine, const hd61700_cpu_device_config &config); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + // device_execute_interface overrides + virtual void execute_run(); + virtual void execute_set_input(int inputnum, int state); + + // device_state_interface overrides + virtual void state_import(const device_state_entry &entry); + void state_string_export(const device_state_entry &entry, astring &string); + + + // device_disasm_interface overrides + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + + // interrupts + bool check_irqs(void); + + // inline helpers + inline void set_pc(INT32 new_pc); + inline UINT8 read_op(); + inline UINT8 mem_readbyte(UINT8 segment, UINT16 offset); + inline void mem_writebyte(UINT8 segment, UINT16 offset, UINT8 data); + inline UINT32 make_18bit_addr(UINT8 segment, UINT16 offset); + inline int check_cond( UINT32 op ); + inline void push(UINT16 &offset, UINT8 data); + inline UINT8 pop(UINT16 &offset); + inline UINT8 make_logic(UINT8 type, UINT8 d1, UINT8 d2); + inline void check_optional_jr(UINT8 arg); + inline UINT8 get_sir_im8(UINT8 arg); + inline UINT8 get_sir_im8(UINT8 arg, UINT8 arg1); + inline int get_sign_mreg(UINT8 op1); + inline int get_sign_im8(UINT8 op1); + inline int get_im_7(UINT8 data); + inline UINT16 make_bcd_sub(UINT8 arg1, UINT8 arg2); + inline UINT16 make_bcd_add(UINT8 arg1, UINT8 arg2); + +protected: + + // internal state + const hd61700_cpu_device_config &m_cpu_config; // reference to the config + static const device_timer_id SEC_TIMER = 1; + emu_timer *m_sec_timer; + + offs_t m_ppc; + offs_t m_curpc; + UINT16 m_pc; + UINT8 m_flags; + UINT32 m_fetch_addr; + UINT8 m_regsir[3]; // 5bit register (sx, sy, sz) + UINT8 m_reg8bit[8]; // 8bit register (pe, pd, ib, ua, ia, ie, tm, tm) + UINT16 m_reg16bit[8]; // 16bit register (ix, iy, iz, us, ss, ky, ky, ky) + UINT8 m_regmain[0x20]; // main registers + UINT8 m_irq_status; + UINT8 m_state; + UINT8 prev_ua; + int m_lines_status[6]; + int m_icount; + + address_space *m_program; + + // flag definitions + static const int FLAG_Z = 0x80; + static const int FLAG_C = 0x40; + static const int FLAG_LZ = 0x20; + static const int FLAG_UZ = 0x10; + static const int FLAG_SW = 0x08; + static const int FLAG_APO = 0x04; +}; + +#endif /* __HD61700_H__ */ diff --git a/src/emu/cpu/hd61700/hd61700d.c b/src/emu/cpu/hd61700/hd61700d.c new file mode 100644 index 00000000000..2ec4b5ceb44 --- /dev/null +++ b/src/emu/cpu/hd61700/hd61700d.c @@ -0,0 +1,437 @@ +#include "emu.h" +#include "debugger.h" +#include "hd61700.h" + +#define EXT_ROM (pc > 0x0c00) +#define INC_POS pos += (type+1) +#define POS (pos + type) + +static const char *const reg_5b[4] = {"sx", "sy", "sz", "sz"}; +static const char *const reg_8b[8] = {"pe", "pd", "ib", "ua", "ia", "ie", "tm", "tm"}; +static const char *const reg_16b[8] = {"ix", "iy", "iz", "us", "ss", "ky", "ky", "ky"}; +static const char *const jp_cond[8] = {"z", "nc", "lz", "uz", "nz", "c", "nlz"}; + +enum +{ + OP_NULL=0, + OP_IM16, + OP_IM16A, + OP_IM3, + OP_IM5, + OP_IM7, + OP_IM8, + OP_IM8I, + OP_IM8_, + OP_IR_IM3, + OP_IR_IM8, + OP_IR_IM8_, + OP_JX_COND, + OP_MREG, + OP_MREG2, + OP_MR_SIR, + OP_MR_SIRI, + OP_REG16, + OP_REG16_, + OP_REG8, + OP_REG8_, + OP_REGIM8, + OP_RMSIM3, + OP_RSIR, +}; + +typedef struct +{ + const char *str; + UINT8 arg1; + UINT8 arg2; + bool optjr; +} hd61700_dasm; + +static const hd61700_dasm hd61700_ops[256] = +{ + // 0x00 + { "adc", OP_MREG, OP_MR_SIR, 1 }, { "sbc", OP_MREG, OP_MR_SIR, 1 }, + { "ld", OP_MREG, OP_MR_SIR, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "anc", OP_MREG, OP_MR_SIR, 1 }, { "nac", OP_MREG, OP_MR_SIR, 1 }, + { "orc", OP_MREG, OP_MR_SIR, 1 }, { "xrc", OP_MREG, OP_MR_SIR, 1 }, + { "ad", OP_MREG, OP_MR_SIR, 1 }, { "sb", OP_MREG, OP_MR_SIR, 1 }, + { "adb", OP_MREG, OP_MR_SIR, 1 }, { "sbb", OP_MREG, OP_MR_SIR, 1 }, + { "an", OP_MREG, OP_MR_SIR, 1 }, { "na", OP_MREG, OP_MR_SIR, 1 }, + { "or", OP_MREG, OP_MR_SIR, 1 }, { "xr", OP_MREG, OP_MR_SIR, 1 }, + + // 0x10 + { "st", OP_MREG, OP_MR_SIRI, 1 }, { "ld", OP_MREG, OP_MR_SIRI,1 }, + { "stl", OP_MREG2, OP_NULL, 1 }, { "ldl", OP_MREG2, OP_NULL, 1 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "psr", OP_RSIR, OP_MREG2, 1 }, + { "pst", OP_REG8, OP_MREG2, 1 }, { "pst", OP_REG8, OP_MREG2, 1 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "???", OP_MREG2, OP_NULL, 1 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "gsr", OP_RSIR, OP_MREG2, 1 }, + { "gst", OP_REG8, OP_MREG2, 1 }, { "gst", OP_REG8, OP_MREG2, 1 }, + + // 0x20 + { "st", OP_MREG, OP_IR_IM8_, 0 }, { "st", OP_MREG, OP_IR_IM8_,0 }, + { "sti", OP_MREG, OP_IR_IM8_, 0 }, { "sti", OP_MREG, OP_IR_IM8_,0 }, + { "std", OP_MREG, OP_IR_IM8_, 0 }, { "std", OP_MREG, OP_IR_IM8_,0 }, + { "phs", OP_MREG2, OP_NULL, 0 }, { "phu", OP_MREG2, OP_NULL, 0 }, + { "ld", OP_MREG, OP_IR_IM8_, 0 }, { "ld", OP_MREG, OP_IR_IM8_,0 }, + { "ldi", OP_MREG, OP_IR_IM8_, 0 }, { "ldi", OP_MREG, OP_IR_IM8_,0 }, + { "ldd", OP_MREG, OP_IR_IM8_, 0 }, { "ldd", OP_MREG, OP_IR_IM8_,0 }, + { "pps", OP_MREG2, OP_NULL, 0 }, { "ppu", OP_MREG2, OP_NULL, 0 }, + + // 0x30 + { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 }, + { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 }, + { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 }, + { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_IM16A, OP_NULL, 0 }, + { "adc", OP_IR_IM8, OP_MREG2, 0 }, { "adc", OP_IR_IM8, OP_MREG2, 0 }, + { "sbc", OP_IR_IM8, OP_MREG2, 0 }, { "sbc", OP_IR_IM8, OP_MREG2, 0 }, + { "ad", OP_IR_IM8, OP_MREG2, 0 }, { "ad", OP_IR_IM8, OP_MREG2, 0 }, + { "sb", OP_IR_IM8, OP_MREG2, 0 }, { "sb", OP_IR_IM8, OP_MREG2, 0 }, + + // 0x40 + { "adc", OP_MREG2, OP_IM8, 1 }, { "sbc", OP_MREG2, OP_IM8, 1 }, + { "ld", OP_MREG2, OP_IM8, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "anc", OP_MREG2, OP_IM8, 1 }, { "nac", OP_MREG2, OP_IM8, 1 }, + { "orc", OP_MREG2, OP_IM8, 1 }, { "xrc", OP_MREG2, OP_IM8, 1 }, + { "ad", OP_MREG2, OP_IM8, 1 }, { "sb", OP_MREG2, OP_IM8, 1 }, + { "adb", OP_MREG2, OP_IM8, 1 }, { "sbb", OP_MREG2, OP_IM8, 1 }, + { "an", OP_MREG2, OP_IM8, 1 }, { "na", OP_MREG2, OP_IM8, 1 }, + { "or", OP_MREG2, OP_IM8, 1 }, { "xr", OP_MREG2, OP_IM8, 1 }, + + // 0x50 + { "st", OP_IM8I, OP_MREG2, 0 }, { "st", OP_IM8, OP_MREG2,0 }, + { "stl", OP_IM8_, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "???", OP_IM8_, OP_NULL, 0 }, { "psr", OP_RSIR, OP_IM5, 0 }, + { "pst", OP_REG8_, OP_IM8, 0 }, { "pst", OP_REG8_, OP_IM8, 0 }, + { "bups", OP_IM8_, OP_NULL, 0 }, { "bdns", OP_IM8_, OP_NULL, 0 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "sup", OP_IM8_, OP_NULL, 0 }, { "sdn", OP_IM8_, OP_NULL, 0 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + + // 0x60 + { "st", OP_MREG2, OP_REGIM8, 0 }, { "st", OP_MREG2, OP_REGIM8, 0 }, + { "sti", OP_MREG2, OP_REGIM8, 0 }, { "sti", OP_MREG2, OP_REGIM8, 0 }, + { "std", OP_MREG2, OP_REGIM8, 0 }, { "std", OP_MREG2, OP_REGIM8, 0 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "ld", OP_MREG2, OP_REGIM8, 0 }, { "ld", OP_MREG2, OP_REGIM8, 0 }, + { "ldi", OP_MREG2, OP_REGIM8, 0 }, { "ldi", OP_MREG2, OP_REGIM8, 0 }, + { "ldd", OP_MREG2, OP_REGIM8, 0 }, { "ldd", OP_MREG2, OP_REGIM8, 0 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + + // 0x70 + { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 }, + { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 }, + { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 }, + { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_IM16A, OP_NULL, 0 }, + { "adc", OP_REGIM8, OP_MREG2, 0 }, { "adc", OP_REGIM8, OP_MREG2, 0 }, + { "sbc", OP_REGIM8, OP_MREG2, 0 }, { "sbc", OP_REGIM8, OP_MREG2, 0 }, + { "ad", OP_REGIM8, OP_MREG2, 0 }, { "ad ", OP_REGIM8, OP_MREG2, 0 }, + { "sb", OP_REGIM8, OP_MREG2, 0 }, { "sb", OP_REGIM8, OP_MREG2, 0 }, + + // 0x80 + { "adcw", OP_MREG, OP_MR_SIR, 1 }, { "sbcw", OP_MREG, OP_MR_SIR, 1 }, + { "ldw", OP_MREG, OP_MR_SIR, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "ancw", OP_MREG, OP_MR_SIR, 1 }, { "nacw", OP_MREG, OP_MR_SIR, 1 }, + { "orcw", OP_MREG, OP_MR_SIR, 1 }, { "xrcw", OP_MREG, OP_MR_SIR, 1 }, + { "adw", OP_MREG, OP_MR_SIR, 1 }, { "sbw", OP_MREG, OP_MR_SIR, 1 }, + { "adbw", OP_MREG, OP_MR_SIR, 1 }, { "sbbw", OP_MREG, OP_MR_SIR, 1 }, + { "anw", OP_MREG, OP_MR_SIR, 1 }, { "naw", OP_MREG, OP_MR_SIR, 1 }, + { "orw", OP_MREG, OP_MR_SIR, 1 }, { "xrw", OP_MREG, OP_MR_SIR, 1 }, + + // 0x90 + { "stw", OP_MREG, OP_MR_SIRI,1 }, { "ldw", OP_MREG, OP_MR_SIRI,1 }, + { "stlw", OP_MREG2, OP_NULL, 1 }, { "ldlw", OP_MREG2, OP_NULL, 1 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "pre", OP_REG16, OP_MREG2, 1 }, { "pre", OP_REG16, OP_MREG2, 1 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "???", OP_MREG2, OP_NULL, 1 }, + { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "gre", OP_REG16, OP_MREG2, 1 }, { "gre", OP_REG16, OP_MREG2, 1 }, + + // 0xa0 + { "stw", OP_MREG, OP_IR_IM8_, 0 }, { "stw", OP_MREG, OP_IR_IM8_, 0 }, + { "stiw", OP_MREG, OP_IR_IM8_, 0 }, { "stiw", OP_MREG, OP_IR_IM8_, 0 }, + { "stdw", OP_MREG, OP_IR_IM8_, 0 }, { "stdw", OP_MREG, OP_IR_IM8_, 0 }, + { "phsw", OP_MREG2, OP_NULL, 0 }, { "phuw", OP_MREG2, OP_NULL, 0 }, + { "ldw", OP_MREG, OP_IR_IM8_, 0 }, { "ldw", OP_MREG, OP_IR_IM8_, 0 }, + { "ldiw", OP_MREG, OP_IR_IM8_, 0 }, { "ldiw", OP_MREG, OP_IR_IM8_, 0 }, + { "lddw", OP_MREG, OP_IR_IM8_, 0 }, { "lddw", OP_MREG, OP_IR_IM8_, 0 }, + { "ppsw", OP_MREG2, OP_NULL, 0 }, { "ppuw", OP_MREG2, OP_NULL, 0 }, + + // 0xb0 + { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 }, + { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 }, + { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 }, + { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_IM7, OP_NULL, 0 }, + { "adcw", OP_IR_IM8, OP_MREG, 0 }, { "adcw", OP_IR_IM8, OP_MREG, 0 }, + { "sbcw", OP_IR_IM8, OP_MREG, 0 }, { "sbcw", OP_IR_IM8, OP_MREG, 0 }, + { "adw", OP_IR_IM8, OP_MREG, 0 }, { "adw", OP_IR_IM8, OP_MREG, 0 }, + { "sbw", OP_IR_IM8, OP_MREG, 0 }, { "sbw", OP_IR_IM8, OP_MREG, 0 }, + + // 0xc0 + { "adbcm",OP_MREG, OP_RMSIM3, 1 }, { "sdbcm",OP_MREG, OP_RMSIM3, 1 }, + { "ldm", OP_MREG, OP_RMSIM3, 1 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "ancm", OP_MREG, OP_RMSIM3, 1 }, { "nacm", OP_MREG, OP_RMSIM3, 1 }, + { "orcm", OP_MREG, OP_RMSIM3, 1 }, { "xrcm", OP_MREG, OP_RMSIM3, 1 }, + { "adbm", OP_MREG, OP_RMSIM3, 1 }, { "sbbm", OP_MREG, OP_RMSIM3, 1 }, + { "adbm", OP_MREG, OP_RMSIM3, 1 }, { "sbbm", OP_MREG, OP_RMSIM3, 1 }, + { "anm", OP_MREG, OP_RMSIM3, 1 }, { "nam", OP_MREG, OP_RMSIM3, 1 }, + { "orm", OP_MREG, OP_RMSIM3, 1 }, { "xrm", OP_MREG, OP_RMSIM3, 1 }, + + // 0xd0 + { "stw", OP_IM16, OP_MR_SIR, 0 }, { "ldw", OP_MREG2, OP_IM16, 0 }, + { "stlm", OP_MREG2, OP_IM3, 0 }, { "ldlm", OP_MREG2, OP_IM3, 0 }, + { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 }, + { "pre", OP_REG16_, OP_IM16, 0 }, { "pre", OP_REG16_, OP_IM16, 0 }, + { "bup", OP_NULL, OP_NULL, 0 }, { "bnd", OP_NULL, OP_NULL, 0 }, + { "???", OP_MREG2, OP_IM3, 0 }, { "???", OP_MREG2, OP_IM3, 0 }, + { "sup", OP_MREG, OP_NULL, 0 }, { "sdn", OP_MREG, OP_NULL, 0 }, + { "jp", OP_MREG, OP_NULL, 0 }, { "jp", OP_MREG, OP_NULL, 0 }, + + // 0xe0 + { "stm", OP_MREG, OP_IR_IM3, 0 }, { "stm", OP_MREG, OP_IR_IM3, 0 }, + { "stim", OP_MREG, OP_IR_IM3, 0 }, { "stim", OP_MREG, OP_IR_IM3, 0 }, + { "stdm", OP_MREG, OP_IR_IM3, 0 }, { "stdm", OP_MREG, OP_IR_IM3, 0 }, + { "phsm", OP_MREG2, OP_IM3, 0 }, { "phum", OP_MREG2, OP_IM3, 0 }, + { "ldm", OP_MREG, OP_IR_IM3, 0 }, { "ldm", OP_MREG, OP_IR_IM3, 0 }, + { "ldim", OP_MREG, OP_IR_IM3, 0 }, { "ldim", OP_MREG, OP_IR_IM3, 0 }, + { "lddm", OP_MREG, OP_IR_IM3, 0 }, { "lddm", OP_MREG, OP_IR_IM3, 0 }, + { "ppsm", OP_MREG2, OP_IM3, 0 }, { "ppum", OP_MREG2, OP_IM3, 0 }, + + // 0xf0 + { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 }, + { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 }, + { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 }, + { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_NULL, OP_NULL, 0 }, + { "nop", OP_JX_COND, OP_NULL, 0 }, { "clt", OP_NULL, OP_NULL, 0 }, + { "fst", OP_NULL, OP_NULL, 0 }, { "slw", OP_NULL, OP_NULL, 0 }, + { "can", OP_NULL, OP_NULL, 0 }, { "rtni", OP_NULL, OP_NULL, 0 }, + { "off", OP_NULL, OP_NULL, 0 }, { "trp", OP_NULL, OP_NULL, 0 }, +}; + + +inline int dasm_im8(char *buffer, UINT16 pc, int arg, const UINT8 *oprom, int &pos, int type) +{ + if (((arg>>5) & 0x03) == 0x03) + { + INC_POS; + UINT8 ret = sprintf( buffer, "0x%02x", oprom[POS] & 0x1f ); + return ret; + } + else + { + return sprintf( buffer, "%s", reg_5b[(arg>>5) & 0x03] ); + } +} + + +inline int dasm_im8(char *buffer, UINT16 pc, int arg, int arg1, const UINT8 *oprom, int &pos) +{ + if (((arg>>5) & 0x03) == 0x03) + { + return sprintf( buffer, "0x%02x", arg1 & 0x1f ); + } + else + { + return sprintf( buffer, "%s", reg_5b[(arg>>5) & 0x03] ); + } +} + + +int dasm_arg(char *buffer, UINT8 op, UINT16 pc, int arg, const UINT8 *oprom, int &pos) +{ + char* buffer_start = buffer; + int type = EXT_ROM; + + switch( arg ) + { + case OP_MREG: + case OP_MREG2: + buffer += sprintf( buffer, "$%02u", oprom[POS] & 0x1f ); + if (arg == OP_MREG2) INC_POS; + break; + + case OP_RSIR: + buffer += sprintf( buffer, "%s", reg_5b[(oprom[POS]>>5) & 0x03] ); + break; + + case OP_REG8: + case OP_REG8_: + buffer += sprintf( buffer, "%s", reg_8b[(BIT(op,0)<<2) + ((oprom[POS]>>5&3))]); + if (arg == OP_REG8_) INC_POS; + break; + + case OP_MR_SIR: + buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type); + INC_POS; + break; + + case OP_IR_IM8: + case OP_IR_IM8_: + buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (oprom[POS]&0x80) ? "-": "+"); + buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type); + buffer += sprintf( buffer, ")"); + if (arg == OP_IR_IM8_) INC_POS; + break; + + case OP_IM8_: + INC_POS; + case OP_IM8: + buffer += sprintf( buffer, "0x%02x", oprom[POS] ); + INC_POS; + break; + + case OP_IM8I: + buffer += sprintf( buffer, "(0x%02x)", oprom[POS] ); + INC_POS; + break; + + case OP_REGIM8: + buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (oprom[POS]&0x80) ? "-": "+"); + buffer += sprintf( buffer, "%x)", oprom[POS] & 0x1f); + INC_POS; + break; + + case OP_JX_COND: + buffer += sprintf( buffer, "%s", jp_cond[op & 0x07] ); + break; + + + case OP_RMSIM3: + { + UINT8 tmp = oprom[POS]; + INC_POS; + buffer += dasm_im8(buffer, pc, tmp, oprom[POS], oprom, pos); + buffer += sprintf( buffer, ", 0x%02x", ((tmp>>5)&7)+1); + INC_POS; + } + break; + + case OP_IR_IM3: + { + UINT8 tmp = oprom[POS]; + INC_POS; + buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (tmp&0x80) ? "-": "+"); + buffer += dasm_im8(buffer, pc, tmp, oprom[POS], oprom, pos); + buffer += sprintf( buffer, "), 0x%02x", ((oprom[POS]>>5)&7)+1 ); + INC_POS; + } + break; + + case OP_IM3: + buffer += sprintf( buffer, "0x%02x", ((oprom[POS]>>5)&7)+1 ); + INC_POS; + break; + + case OP_MR_SIRI: + buffer += sprintf( buffer, "("); + buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type); + buffer += sprintf( buffer, ")"); + INC_POS; + break; + + case OP_IM7: + { + int tmp = oprom[POS]; + if (tmp&0x80) tmp = 0x80 - tmp; + + buffer += sprintf( buffer, "0x%04x", (pc + tmp) & 0xffff ); + INC_POS; + } + break; + + case OP_IM5: + buffer += sprintf( buffer, "0x%02x", oprom[POS]&0x1f ); + INC_POS; + break; + + case OP_REG16: + case OP_REG16_: + buffer += sprintf( buffer, "%s", reg_16b[(BIT(op,0)<<2) + ((oprom[POS]>>5&3))]); + if (arg == OP_REG16_) INC_POS; + break; + + case OP_IM16: + case OP_IM16A: + { + UINT8 tmp1 = oprom[POS]; + INC_POS; + if (!EXT_ROM && arg == OP_IM16A) INC_POS; + UINT8 tmp2 = oprom[POS]; + buffer += sprintf( buffer, "0x%04x", ((tmp2<<8) | tmp1)); + INC_POS; + } + break; + + case OP_NULL: + break; + } + + return buffer - buffer_start; +} + +UINT32 get_dasmflags(UINT8 op) +{ + switch (op) + { + case 0x30: case 0x31: case 0x32: case 0x33: //jp + case 0x34: case 0x35: case 0x36: case 0x37: //jp + case 0x70: case 0x71: case 0x72: case 0x73: //cal + case 0x74: case 0x75: case 0x76: case 0x77: //cal + case 0xb0: case 0xb1: case 0xb2: case 0xb3: //jr + case 0xb4: case 0xb5: case 0xb6: case 0xb7: //jr + case 0xde: //jp + case 0xdf: //jp + return DASMFLAG_STEP_OVER; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: //rtn + case 0xf4: case 0xf5: case 0xf6: case 0xf7: //rtn + case 0xfd: //rtni + return DASMFLAG_STEP_OUT; + } + + return 0; +} + + +CPU_DISASSEMBLE( hd61700 ) +{ + const hd61700_dasm *inst; + UINT32 dasmflags = 0; + UINT8 op, op1; + int pos = 0, type = EXT_ROM; + + op = oprom[POS]; + INC_POS; + + dasmflags = get_dasmflags(op); + + op1 = oprom[POS]; + + inst = &hd61700_ops[op]; + + buffer += sprintf(buffer,"%-8s", inst->str); + + //dasm first arg + buffer += dasm_arg(buffer, op, pc, inst->arg1, oprom, pos); + + //if present dasm second arg + if (inst->arg2 != OP_NULL) + { + buffer += sprintf(buffer,", "); + buffer += dasm_arg(buffer, op, pc, inst->arg2, oprom, pos); + } + + //if required add the optional jr + if (inst->optjr == true && BIT(op1, 7)) + { + buffer += sprintf( buffer, ", jr "); + buffer += dasm_arg(buffer, op, pc+1, OP_IM7, oprom, pos); + + dasmflags = DASMFLAG_STEP_OVER; + } + + if (pos&1) INC_POS; + + return (pos>>1) | dasmflags | DASMFLAG_SUPPORTED; +}