diff options
Diffstat (limited to 'src/emu/cpu/h83002/h83002.c')
-rw-r--r-- | src/emu/cpu/h83002/h83002.c | 3863 |
1 files changed, 3863 insertions, 0 deletions
diff --git a/src/emu/cpu/h83002/h83002.c b/src/emu/cpu/h83002/h83002.c new file mode 100644 index 00000000000..b0e01bfc0ff --- /dev/null +++ b/src/emu/cpu/h83002/h83002.c @@ -0,0 +1,3863 @@ +/*************************************************************************** + + h83002.c: Hitachi H8/3002 microcontroller emulator + + Original by The_Author & DynaChicken for the ZiNc emulator. + + Rewrite for MAME by R. Belmont, including... + - Changed types to MAME standards + - Added MAME cpuintrf glue + - Put all per-CPU state in a struct + - Fixed ADD flag calcs + - Added support for all 8 flag bits + - Added cycle timing (probably not right yet) + - Fixed and optimized interrupt handling + - Optimized main execution loop + - Added new opcodes for ND-1 and System 23 BIOS programs + - Improved I/O and timer support + - Fixed major error in 7Cxx/7Dxx series bit opcodes where the wrong + instructions were being picked. + + TS 20060412 Added exts.l, sub.l, divxs.w (buggy), jsr @reg, rotxl.l reg, mov.l @(adr, reg), reg + + Note: The H8/3000 series is normally back-compatible to the 8-bit H8/300, + but the 3002 does not include "emulation mode" - it always runs in full + 16/32-bit ("advanced") mode. So this core is not suitable for general + H8/300 emulation. + +****************************************************************************/ + +#include "debugger.h" +#include "h83002.h" +#include "h8priv.h" + +#define H8_SP (7) + +#define h8_mem_read8(x) program_read_byte_16be(x) +#define h8_mem_read16(x) program_read_word_16be(x) +#define h8_mem_write8(x, y) program_write_byte_16be(x, y) +#define h8_mem_write16(x, y) program_write_word_16be(x, y) + +// timing macros +// note: we assume a system 12 - type setup where external access is 3+1 states +// timing will be off somewhat for other configurations. +#define H8_IFETCH_TIMING(x) h8_cyccnt -= (x) * 4; +#define H8_BRANCH_TIMING(x) h8_cyccnt -= (x) * 4; +#define H8_STACK_TIMING(x) h8_cyccnt -= (x) * 4; +#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xffff10) h8_cyccnt -= (x) * 3; else h8_cyccnt -= (x) * 4; +#define H8_WORD_TIMING(x, adr) if (address24 >= 0xffff10) h8_cyccnt -= (x) * 3; else h8_cyccnt -= (x) * 4; +#define H8_IOP_TIMING(x) h8_cyccnt -= (x); + +extern UINT8 h8_register_read8(UINT32 address); +extern void h8_register_write8(UINT32 address, UINT8 val); + +INLINE UINT32 h8_mem_read32(offs_t address) +{ + UINT32 result = program_read_word_16be(address) << 16; + return result | program_read_word_16be(address + 2); +} + +INLINE void h8_mem_write32(offs_t address, UINT32 data) +{ + program_write_word_16be(address, data >> 16); + program_write_word_16be(address + 2, data); +} + + +h83002_state h8; + +static INT32 h8_cyccnt; + +static UINT32 udata32, address24; +static INT32 sdata32; +static UINT16 udata16, ext16; +static INT16 sdata16; +static UINT8 udata8; +static INT8 sdata8; +static UINT8 srcreg, dstreg; + +/* internal functions */ + +static void h8_check_irqs(void); + +static void h8_group0(UINT16 opcode); +static void h8_group1(UINT16 opcode); +static void h8_group5(UINT16 opcode); +static void h8_group6(UINT16 opcode); +static void h8_group7(UINT16 opcode); + +static int h8_branch(UINT8 condition); + +static UINT8 h8_mov8(UINT8 src); +static UINT16 h8_mov16(UINT16 src); +static UINT32 h8_mov32(UINT32 src); + +static UINT8 h8_add8(UINT8 src, UINT8 dst); +static UINT16 h8_add16(UINT16 src, UINT16 dst); +static UINT32 h8_add32(UINT32 src, UINT32 dst); + +static UINT8 h8_sub8(UINT8 src, UINT8 dst); +static UINT16 h8_sub16(UINT16 src, UINT16 dst); +static UINT32 h8_sub32(UINT32 src, UINT32 dst); + +static UINT8 h8_addx8(UINT8 src, UINT8 dst); + +static void h8_cmp8(UINT8 src, UINT8 dst); +static void h8_cmp16(UINT16 src, UINT16 dst); +static void h8_cmp32(UINT32 src, UINT32 dst); +static UINT8 h8_subx8(UINT8 src, UINT8 dst); + +static UINT8 h8_or8(UINT8 src, UINT8 dst); +static UINT16 h8_or16(UINT16 src, UINT16 dst); + +static UINT8 h8_xor8(UINT8 src, UINT8 dst); +static UINT16 h8_xor16(UINT16 src, UINT16 dst); +static UINT32 h8_xor32(UINT32 src, UINT32 dst); + +static UINT8 h8_and8(UINT8 src, UINT8 dst); +static UINT16 h8_and16(UINT16 src, UINT16 dst); +static UINT32 h8_and32(UINT32 src, UINT32 dst); + +static INT8 h8_neg8(INT8 src); +static INT16 h8_neg16(INT16 src); + +static UINT16 h8_divxu8 (UINT16 dst, UINT8 src); +static UINT32 h8_divxu16(UINT32 dst, UINT16 src); + +static UINT8 h8_not8(UINT8 src); +static UINT16 h8_not16(UINT16 src); + +static UINT8 h8_rotl8(UINT8 src); +static UINT16 h8_rotl16(UINT16 src); + +static UINT8 h8_rotxl8(UINT8 src); +static UINT16 h8_rotxl16(UINT16 src); +static UINT32 h8_rotxl32(UINT32 src); + +static UINT8 h8_rotxr8(UINT8 src); +static UINT16 h8_rotxr16(UINT16 src); + +static UINT8 h8_shll8(UINT8 src); +static UINT16 h8_shll16(UINT16 src); +static UINT32 h8_shll32(UINT32 src); + +static UINT8 h8_shlr8(UINT8 src); +static UINT16 h8_shlr16(UINT16 src); +static UINT32 h8_shlr32(UINT32 src); + +static INT8 h8_shal8(INT8 src); +static INT16 h8_shal16(INT16 src); + +static INT8 h8_shar8(INT8 src); +static INT16 h8_shar16(INT16 src); +static INT32 h8_shar32(INT32 src); + +static UINT8 h8_dec8(UINT8 src); +static UINT16 h8_dec16(UINT16 src); +static UINT32 h8_dec32(UINT32 src); + +static UINT8 h8_inc8(UINT8 src); +static UINT16 h8_inc16(UINT16 src); +static UINT32 h8_inc32(UINT32 src); + +//static UINT8 h8_bnot8(UINT8 src, UINT8 dst); +static UINT8 h8_bst8(UINT8 src, UINT8 dst); +static UINT8 h8_bist8(UINT8 src, UINT8 dst); +static UINT8 h8_bset8(UINT8 src, UINT8 dst); +static UINT8 h8_bclr8(UINT8 src, UINT8 dst); +static void h8_btst8(UINT8 src, UINT8 dst); +static void h8_bld8(UINT8 src, UINT8 dst); // loads to carry +static void h8_bor8(UINT8 src, UINT8 dst); // result in carry +//static void h8_bxor8(UINT8 src, UINT8 dst); + +static INT32 h8_mulxs16(INT16 src, INT16 dst); +static UINT32 h8_divxs16(INT16 src, INT32 dst); + +/* implementation */ + +#ifdef MAME_DEBUG +extern offs_t h8_disasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +#endif /* MAME_DEBUG */ + +void h8_3002_InterruptRequest(UINT8 source) +{ + if(source>31) + { + h8.h8_IRQrequestH |= (1<<(source-32)); + } + else + { + h8.h8_IRQrequestL |= (1<<source); + } +} + + +static UINT8 h8_get_ccr(void) +{ + h8.ccr = 0; + if(h8.h8nflag)h8.ccr |= NFLAG; + if(h8.h8zflag)h8.ccr |= ZFLAG; + if(h8.h8vflag)h8.ccr |= VFLAG; + if(h8.h8cflag)h8.ccr |= CFLAG; + if(h8.h8uflag)h8.ccr |= UFLAG; + if(h8.h8hflag)h8.ccr |= HFLAG; + if(h8.h8uiflag)h8.ccr |= UIFLAG; + if(h8.h8iflag)h8.ccr |= IFLAG; + return h8.ccr; +} + +static char *h8_get_ccr_str(void) +{ + static char res[8]; + + memset(res, 0, 8); + if(h8.h8iflag) strcat(res, "I"); else strcat(res, "i"); + if(h8.h8uiflag)strcat(res, "U"); else strcat(res, "u"); + if(h8.h8hflag) strcat(res, "H"); else strcat(res, "h"); + if(h8.h8uflag) strcat(res, "U"); else strcat(res, "u"); + if(h8.h8nflag) strcat(res, "N"); else strcat(res, "n"); + if(h8.h8zflag) strcat(res, "Z"); else strcat(res, "z"); + if(h8.h8vflag) strcat(res, "V"); else strcat(res, "v"); + if(h8.h8cflag) strcat(res, "C"); else strcat(res, "c"); + + return res; +} + +static void h8_set_ccr(UINT8 data) +{ + h8.ccr = data; + + h8.h8nflag = 0; + h8.h8zflag = 0; + h8.h8vflag = 0; + h8.h8cflag = 0; + h8.h8hflag = 0; + h8.h8iflag = 0; + h8.h8uflag = 0; + h8.h8uiflag = 0; + + if(h8.ccr & NFLAG) h8.h8nflag = 1; + if(h8.ccr & ZFLAG) h8.h8zflag = 1; + if(h8.ccr & VFLAG) h8.h8vflag = 1; + if(h8.ccr & CFLAG) h8.h8cflag = 1; + if(h8.ccr & HFLAG) h8.h8hflag = 1; + if(h8.ccr & UFLAG) h8.h8uflag = 1; + if(h8.ccr & UIFLAG) h8.h8uiflag = 1; + if(h8.ccr & IFLAG) h8.h8iflag = 1; + + h8_check_irqs(); +} + +static INT16 h8_getreg16(UINT8 reg) +{ + if(reg > 7) + { + return h8.regs[reg-8]>>16; + } + else + { + return h8.regs[reg]; + } +} + +static void h8_setreg16(UINT8 reg, UINT16 data) +{ + if(reg > 7) + { + h8.regs[reg-8] &= 0xffff; + h8.regs[reg-8] |= data<<16; + } + else + { + h8.regs[reg] &= 0xffff0000; + h8.regs[reg] |= data; + } +} + +static UINT8 h8_getreg8(UINT8 reg) +{ + if(reg > 7) + { + return h8.regs[reg-8]; + } + else + { + return h8.regs[reg]>>8; + } +} + +static void h8_setreg8(UINT8 reg, UINT8 data) +{ + if(reg > 7) + { + h8.regs[reg-8] &= 0xffffff00; + h8.regs[reg-8] |= data; + } + else + { + h8.regs[reg] &= 0xffff00ff; + h8.regs[reg] |= data<<8; + } +} + +static UINT32 h8_getreg32(UINT8 reg) +{ + return h8.regs[reg]; +} + +static void h8_setreg32(UINT8 reg, UINT32 data) +{ + h8.regs[reg] = data; +} + +static void h8_onstateload(void) +{ + h8_set_ccr(h8.ccr); +} + +static void h8_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + memset(&h8, 0, sizeof(h8)); + h8.h8iflag = 1; + + h8.irq_cb = irqcallback; + + state_save_register_item("H8/3002", index, h8.h8err); + state_save_register_item_array("H8/3002", index, h8.regs); + state_save_register_item("H8/3002", index, h8.pc); + state_save_register_item("H8/3002", index, h8.ppc); + state_save_register_item("H8/3002", index, h8.h8_IRQrequestH); + state_save_register_item("H8/3002", index, h8.h8_IRQrequestL); + state_save_register_item("H8/3002", index, h8.ccr); + + state_save_register_item_array("H8/3002", index, h8.per_regs); + state_save_register_item("H8/3002", index, h8.h8TSTR); + state_save_register_item("H8/3002", index, h8.h8TCNT0); + state_save_register_item("H8/3002", index, h8.h8TCNT1); + state_save_register_item("H8/3002", index, h8.h8TCNT2); + state_save_register_item("H8/3002", index, h8.h8TCNT3); + state_save_register_item("H8/3002", index, h8.h8TCNT4); + + state_save_register_func_postload(h8_onstateload); + + h8_itu_init(); +} + +static void h8_reset(void) +{ + h8.h8err = 0; + h8.pc = h8_mem_read32(0) & 0xffffff; + change_pc(h8.pc); + + // disable timers + h8.h8TSTR = 0; + + h8_itu_reset(); +} + +static void h8_GenException(UINT8 vectornr) +{ + // push PC on stack + // extended mode stack push! + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-4); + h8_mem_write32(h8_getreg32(H8_SP), h8.pc); + // push ccr + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-2); + h8_mem_write16(h8_getreg32(H8_SP), h8_get_ccr()); + + // generate address from vector + h8_set_ccr(h8_get_ccr() | 0x80); + h8.pc = h8_mem_read32(vectornr * 4) & 0xffffff; + change_pc(h8.pc); + + // I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR) + H8_IFETCH_TIMING(2); + H8_STACK_TIMING(2); +} + +static int h8_get_priority(UINT8 bit) +{ + int res = 0; + switch(bit) + { + case 12: // IRQ0 + if (h8.per_regs[0xF8]&0x80) res = 1; break; + case 13: // IRQ1 + if (h8.per_regs[0xF8]&0x40) res = 1; break; + case 14: // IRQ2 + case 15: // IRQ3 + if (h8.per_regs[0xF8]&0x20) res = 1; break; + case 16: // IRQ4 + case 17: // IRQ5 + if (h8.per_regs[0xF8]&0x10) res = 1; break; + } + return res; +} + +static void h8_check_irqs(void) +{ + int lv = -1; + if (h8.h8iflag == 0) + { + lv = 0; + } + else + { + if ((h8.per_regs[0xF2]&0x08)/*SYSCR*/ == 0) + { + if (h8.h8uiflag == 0) + lv = 1; + } + } + + // any interrupts wanted and can accept ? + if(((h8.h8_IRQrequestH != 0) || (h8.h8_IRQrequestL != 0)) && (lv >= 0)) + { + UINT8 bit, source; + // which one ? + for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++) + { + if( h8.h8_IRQrequestL & (1<<bit) ) + { + if (h8_get_priority(bit) >= lv) + { + // mask off + h8.h8_IRQrequestL &= ~(1<<bit); + source = bit; + } + } + } + // which one ? + for(bit = 0; source == 0xff && bit < 32; bit++) + { + if( h8.h8_IRQrequestH & (1<<bit) ) + { + if (h8_get_priority(bit + 32) >= lv) + { + // mask off + h8.h8_IRQrequestH &= ~(1<<bit); + source = bit + 32; + } + } + } + + // call the MAME callback if it's one of the 6 + // external IRQs + if (source >= 12 && source <= 17) + { + (*h8.irq_cb)(source - 12 + H8_IRQ0); + } + + if (source != 0xff) + h8_GenException(source); + } +} + +static int h8_execute(int cycles) +{ + UINT16 opcode=0; + + h8_cyccnt = cycles; + + h8_check_irqs(); + + while ((h8_cyccnt > 0) && (!h8.h8err)) + { + h8.ppc = h8.pc; + +#ifdef MAME_DEBUG + CALL_MAME_DEBUG; +#endif + opcode = cpu_readop16(h8.pc); +// mame_printf_debug("[%06x]: %04x => %x\n", h8.pc, opcode, (opcode>>12)&0xf); + h8.pc += 2; + + switch((opcode>>12) & 0xf) + { + case 0x0: + h8_group0(opcode); + break; + case 0x1: + h8_group1(opcode); + break; + case 0x2: + // mov.b @xx:8, Rd (abs) + dstreg = (opcode>>8) & 0xf; + udata8 = h8_mem_read8(0xffff00+(opcode & 0xff)); + h8_mov8(udata8); // flags calculation, dont care about others + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x3: // pass + // mov.b Rs, @xx:8 (abs) + srcreg = (opcode>>8) & 0xf; + udata8 = h8_getreg8(srcreg); + h8_mov8(udata8); // flags calculation, dont care about others + h8_mem_write8(0xffff00+(opcode & 0xff), udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, 0xffff00+(opcode & 0xff)); + break; + case 0x4: + // bcc @xx:8 + sdata8 = (opcode & 0xff); + if( h8_branch((opcode >> 8) & 0xf) == 1)h8.pc += sdata8; + change_pc(h8.pc); + break; + case 0x5: + h8_group5(opcode); + break; + case 0x6: + h8_group6(opcode); + break; + case 0x7: + h8_group7(opcode); + break; + case 0x8: + // add.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_add8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1) + break; + case 0x9: + // addx.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_addx8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1) + break; + case 0xa: + // cmp.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + h8_cmp8(opcode & 0xff, h8_getreg8(dstreg)); + H8_IFETCH_TIMING(1); + break; + case 0xb: + // subx.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_subx8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0xc: + // or.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_or8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0xd: + // xor.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_xor8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0xe: // pass + // and.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_and8(opcode & 0xff, h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1) + break; + case 0xf: // pass + // mov.b #xx:8, Rd + dstreg = (opcode>>8) & 0xf; + udata8 = h8_mov8(opcode & 0xff); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + } + } + + if (h8.h8err) + { + fatalerror("H8/3002: Unknown opcode (PC=%x) %x", h8.ppc, opcode); + + } + + return cycles - h8_cyccnt; +} + +static void h8_group0(UINT16 opcode) +{ + switch((opcode>>8)&0xf) + { + case 0: + // nop + H8_IFETCH_TIMING(1); + break; + case 0x1: + // 010x where x should always be 0! + if((opcode & 0xf) != 0) + { + h8.h8err = 1; + break; + } + switch((opcode>>4) & 0xf) + { + // 0100 mov.l prefix + case 0xf: // and.l Rn, Rn + ext16 = h8_mem_read16(h8.pc); + h8.pc += 2; + if (ext16 & 0x88) + { + h8.h8err = 1; + } + else + { + switch((ext16>>8)&0xff) + { + case 0x65: + dstreg = ext16 & 0x7; + udata32 = h8_xor32(h8_getreg32((ext16>>4) & 0x7), h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(2); + break; + case 0x66: + dstreg = ext16 & 0x7; + udata32 = h8_and32(h8_getreg32((ext16>>4) & 0x7), h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(2); + break; + default: + h8.h8err = 1; + break; + } + } + break; + + case 0: + ext16 = h8_mem_read16(h8.pc); + h8.pc+=2; + switch((ext16 >> 8) & 0xff) + { + case 0x69: + if((ext16 & 0x80) == 0x80) + { + // mov.l rx, @rx + udata32 = h8_mov32(h8_getreg32(ext16 & 7)); + h8_mem_write32(h8_getreg32((ext16 >> 4) & 7), udata32); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(2, h8_getreg32((ext16 >> 4) & 7)); + } + else + { + // mov.l @rx, rx + udata32 = h8_mem_read32(h8_getreg32( (ext16 >> 4) &7)); + h8_mov32(udata32); + h8_setreg32(ext16 & 7, udata32); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(2, h8_getreg32( (ext16 >> 4) &7)); + } + break; + case 0x6b: + // mov.l rx, @xx / mov.l @xx, rx + switch((ext16 >> 4)&0xf) + { + case 0x2: + // mov.l @aa:24, erx + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata32=h8_mem_read32(address24); + h8_mov32(udata32); // flags only + h8_setreg32(ext16 & 0x7, udata32); + H8_IFETCH_TIMING(4); + H8_WORD_TIMING(2, address24); + break; + case 0xa: + // mov.l erx, @aa:24 + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata32=h8_getreg32(ext16 & 0x7); + h8_mov32(udata32); // flags only + h8_mem_write32(address24, udata32); + H8_IFETCH_TIMING(4); + H8_WORD_TIMING(2, address24); + break; + default: + h8.h8err = 1; + break; + } + break; + case 0x6d: + if(ext16 & 0x80) + { + // mov.l rs, @-erd + srcreg = (ext16>>4)&7; + h8_setreg32(srcreg, h8_getreg32(srcreg)-4); + address24 = h8_getreg32(srcreg) & 0xffffff; + udata32 = h8_getreg32(ext16 & 0x7); + h8_mem_write32(address24, udata32); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(2, address24); + H8_IOP_TIMING(2); + } + else + { + // mov.l @ers+, rd + srcreg = (ext16 >>4)&7; + address24 = h8_getreg32(srcreg) & 0xffffff; + h8_setreg32(srcreg, h8_getreg32(srcreg)+4); + udata32 = h8_mem_read32(address24); + h8_setreg32(ext16 & 0x7, udata32); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(2, address24); + H8_IOP_TIMING(2); + } + h8_mov32(udata32); + break; + case 0x6f: + // mov.l @(displ16 + Rs), rd + sdata16=h8_mem_read16(h8.pc); // sign extend displacements ! + h8.pc += 2; + address24 = (h8_getreg32((ext16 >> 4)&7)) & 0xffffff; + address24 += sdata16; + H8_IFETCH_TIMING(3); + H8_WORD_TIMING(2, address24); + if(ext16 & 0x80) + { + udata32 = h8_getreg32(ext16 & 0x7); + h8_mem_write32(address24, udata32); + } + else + { + udata32 = h8_mem_read32(address24); + h8_setreg32(ext16 & 0x7, udata32); + } + h8_mov32(udata32); + break; + case 0x78: + // prefix for + // mov.l (@aa:x, rx), Rx + //00000A10 010078606B2600201AC2 MOV.L @($00201AC2,ER6),ER6 + // mov.l @(displ24 + Rs), rd + srcreg = (ext16 >> 4) & 7; + + // 6b20 + udata16 = h8_mem_read16(h8.pc); + h8.pc += 2; + dstreg = udata16 & 7; + + address24 = h8_mem_read32(h8.pc); + h8.pc += 4; + address24 += h8_getreg32(srcreg); + address24 &= 0xffffff; + + if ( (ext16 & 0x80) && ((udata16 & ~7) == 0x6ba0) ) + { + udata32 = h8_getreg32(dstreg); + h8_mem_write32(address24, udata32); + } + else if ( (!(ext16 & 0x80)) && ((udata16 & ~7) == 0x6b20) ) + { + udata32 = h8_mem_read32(address24); + h8_setreg32(dstreg, udata32); + } + else + { + h8.h8err = 1; + } + + h8_mov32(udata32); + + H8_IFETCH_TIMING(5); + H8_WORD_TIMING(2, address24); + + break; + default: + h8.h8err = 1; + break; + } + break; + case 0xc: + // mulxs + ext16 = h8_mem_read16(h8.pc); + h8.pc+=2; + if(((ext16>>8) & 0xf) == 0) + { + h8.h8err = 1; + } + else if(((ext16>>8) & 0xf) == 2) + { + sdata32 = h8_getreg32(ext16 & 0x7); + sdata16 = h8_getreg16((ext16>>4) & 0xf); + sdata32 = h8_mulxs16(sdata16, sdata32); + h8_setreg32(ext16 & 0x7, sdata32); + H8_IFETCH_TIMING(2); + H8_IOP_TIMING(20); + } + else + { + logerror("H8/3002: Unk. group 0 mulxs %x\n", opcode); + h8.h8err = 1; + } + break; + + case 0xd: + //divxs - probbaly buggy (flags?) + ext16 = h8_mem_read16(h8.pc); + h8.pc+=2; + if(((ext16>>8) & 0xf) == 0) + { + h8.h8err = 1; + } + else if(((ext16>>8) & 0xf) == 3) + { + sdata32 = h8_getreg32(ext16 & 0x7); + sdata16 = h8_getreg16((ext16>>4) & 0xf); + sdata32 = h8_divxs16(sdata16, sdata32); + h8_setreg32(ext16 & 0x7, sdata32); + H8_IFETCH_TIMING(2); + H8_IOP_TIMING(20); + } + else + { + h8.h8err = 1; + } + + + break; + + default: + h8.h8err = 1; + break; + } + break; + case 0x2: + // stc ccr, rd + if(((opcode>>4) & 0xf) == 0) + { + h8_setreg8(opcode & 0xf, h8_get_ccr()); + H8_IFETCH_TIMING(1); + } + else + { + logerror("H8/3002: Unk. group 0 2 %x\n", opcode); + h8.h8err = 1; + } + break; + case 0x3: + // ldc rd, ccr + if(((opcode>>4) & 0xf) == 0) + { + udata8 = h8_getreg8(opcode & 0xf); + h8_set_ccr(udata8); + H8_IFETCH_TIMING(1); + } + else + { + logerror("H8/3002: Unk. group 0 3 %x\n", opcode); + h8.h8err = 1; + } + break; + case 0x4: // pass + // orc + udata8 = h8_or8(opcode & 0xff, h8_get_ccr()); + h8_set_ccr(udata8); + H8_IFETCH_TIMING(1); + break; + case 0x6: + // andc + udata8 = h8_and8(opcode & 0xff, h8_get_ccr()); + h8_set_ccr(udata8); + H8_IFETCH_TIMING(1) + break; + // ldc + case 0x8: + // add.b rx, ry + dstreg = opcode & 0xf; + udata8 = h8_add8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1) + break; + // add.w rx, ry + case 0x9: + dstreg = opcode & 0xf; + udata16 = h8_add16(h8_getreg16((opcode>>4) &0xf), h8_getreg16(dstreg)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1) + break; + // inc.b rx + case 0xA: + if(opcode&0x80) + { + if(opcode & 0x8) + { + logerror("H8/3002: Unk. group 0 a %x\n", opcode); + h8.h8err = 1; + } + else + { + dstreg = opcode & 0x7; + udata32 = h8_add32(h8_getreg32((opcode>>4) &0x7), h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1) + } + } + else + { + if(opcode & 0xf0) + { + logerror("H8/3002: Unk. group 0 a2 %x\n", opcode); + h8.h8err =1; + } + else + { + dstreg = opcode & 0xf; + udata8 = h8_inc8(h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + } + } + break; + case 0xb: + switch((opcode>>4)& 0xf) + { + case 0: + if(opcode & 8) + { + h8.h8err = 1; + } + else + { + dstreg = opcode & 7; + udata32 = h8_getreg32(dstreg) + 1; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1) + } + break; + case 5: + dstreg = opcode & 0xf; + udata16 = h8_inc16(h8_getreg16(dstreg)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 7: + dstreg = opcode & 0x7; + udata32 = h8_inc32(h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + case 8: + if(opcode & 8) + { + h8.h8err = 1; + } + else + { + dstreg = opcode & 7; + udata32 = h8_getreg32(dstreg) + 2; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1) + } + break; + case 9: + if(opcode & 8) + { + h8.h8err = 1; + } + else + { + dstreg = opcode & 7; + udata32 = h8_getreg32(dstreg) + 4; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1) + } + break; + case 0xd: + dstreg = opcode & 0xf; + udata16 = h8_inc16(h8_getreg16(dstreg)); + if(h8.h8vflag) + { + udata16 = h8_inc16(udata16); // slow and easy + h8.h8vflag = 1; + } + else + udata16 = h8_inc16(udata16); // slow and easy + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 0xf: + dstreg = opcode & 0x7; + udata32 = h8_inc32(h8_getreg32(dstreg)); + if(h8.h8vflag) + { + udata32 = h8_inc32(udata32); // slow and easy + h8.h8vflag = 1; + } + else + udata32 = h8_inc32(udata32); // slow and easy + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + default: + logerror("H8/3002: Unk. group 0 b %x\n", opcode); + h8.h8err = 1; + break; + } + break; + // mov.b rx, ry + case 0xc: // pass + dstreg = opcode & 0xf; + udata8 = h8_mov8(h8_getreg8((opcode>>4) &0xf)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0xd: + // mov.w rx, ry + dstreg = opcode & 0xf; + udata16 = h8_mov16(h8_getreg16((opcode>>4) &0xf)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 0xf: + if(opcode & 0x80) + { + if(opcode & 8) + { + logerror("H8/3002: Unk. group 0 f %x\n", opcode); + h8.h8err = 1; + } + else + { + dstreg = opcode & 0x7; + udata32 = h8_mov32(h8_getreg32((opcode>>4) &0x7)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + } + } + else + { + h8.h8err = 1; + logerror("H8/3002: Unk. group 0 f2 %x\n", opcode); + if((opcode & 0xf0) !=0) + { + h8.h8err = 1; + } + else + { + h8.h8err = 1; + } + } + break; + default: + logerror("H8/3002: Unk. group 0 tdef %x\n", opcode); + h8.h8err = 1; + break; + } +} + +static void h8_group1(UINT16 opcode) +{ + switch((opcode>>8)&0xf) + { + case 0x0: + switch((opcode>>4)&0xf) + { + case 0x0: + // shll.b Rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_shll8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x1: + // shll.w Rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_shll16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + case 0x3: + // shal.l Rx + udata32 = h8_getreg32(opcode & 0x7); + udata32 = h8_shll32(udata32); + h8_setreg32(opcode & 0x7, udata32); + H8_IFETCH_TIMING(1); + break; + + case 0x8: + // shal.b Rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_shal8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + // shal.w Rx + case 0x9: + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_shal16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + + default: + logerror("H8/3002: Unk. group 1 0 %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0x1: + switch((opcode>>4)&0xf) + { + case 0x0: + // shlr.b rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_shlr8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x1: + // shlr.w rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_shlr16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + // shlr.l rx + case 0x3: + udata32 = h8_getreg32(opcode & 0x7); + udata32 = h8_shlr32(udata32); + h8_setreg32(opcode & 0x7, udata32); + H8_IFETCH_TIMING(1); + break; + case 0x8: + // shar.b rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_shar8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x9: + // shar.w rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_shar16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + case 0xb: + // shar.l rx + udata32 = h8_getreg32(opcode & 0x7); + udata32 = h8_shar32(udata32); + h8_setreg32(opcode & 0x7, udata32); + H8_IFETCH_TIMING(1); + break; + default: + logerror("H8/3002: Unk. group 1 1 %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0x2: + switch((opcode>>4)&0xf) + { + case 0x0: + // rotxl.b Rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_rotxl8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x1: + // rotxl.w Rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_rotxl16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + + case 0x3: + // rotxl.l Rx + udata32 = h8_getreg32(opcode & 0x7); + udata32 = h8_rotxl32(udata32); + h8_setreg32(opcode & 0xf, udata32); + H8_IFETCH_TIMING(1); + break; + + case 0x8: + // rotl.b Rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_rotl8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x9: + // rotl.w Rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_rotl16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + // rotl.l Rx + default: + logerror("H8/3002: Unk. group 1 2 %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0x3: + switch((opcode>>4)&0xf) + { + case 0x0: + // rotxr.b Rx + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_rotxr8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x1: + // rotxr.w Rx + udata16 = h8_getreg16(opcode & 0xf); + udata16 = h8_rotxr16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + break; + default: + logerror("H8/3002: Unk. group 1 3 %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0x4: + // or.b rs, rd + dstreg = opcode & 0xf; + udata8 = h8_or8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x5: + // xor.b rs, rd + dstreg = opcode & 0xf; + udata8 = h8_xor8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x6: + // and.b rs, rd + dstreg = opcode & 0xf; + udata8 = h8_and8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1) + break; + // not + case 0x7: + switch((opcode>>4)&0xf) + { + case 0x0: + // not.b Rx + dstreg = opcode & 0xf; + udata8 = h8_not8(h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x1: + // not.w Rx + dstreg = opcode & 0xf; + udata16 = h8_not16(h8_getreg16(dstreg)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + + case 0x5: + // extu.w Rx + dstreg = opcode & 0xf; + udata16 = h8_getreg16(dstreg) & 0x00ff; + h8_setreg16(dstreg, udata16); + h8.h8nflag = 0; + h8.h8vflag = 0; + h8.h8zflag = ((udata16 == 0) ? 1 : 0); + H8_IFETCH_TIMING(1); + break; + case 0x7: + // extu.l Rx + dstreg = opcode & 0x7; + udata32 = h8_getreg32(dstreg) & 0x0000ffff; + h8_setreg32(dstreg, udata32); + h8.h8nflag = 0; + h8.h8vflag = 0; + h8.h8zflag = ((udata32 == 0) ? 1 : 0); + H8_IFETCH_TIMING(1); + break; + case 0x8: + // neg.b Rx + //sprintf(output, "%4.4x neg.b %s", opcode, reg_names8[opcode & 0xf]); + dstreg = opcode & 0xf; + sdata8 = h8_neg8(h8_getreg8(dstreg)); + h8_setreg8(dstreg, sdata8); + H8_IFETCH_TIMING(1); + break; + case 0x9: + // neg.w Rx + //sprintf(output, "%4.4x neg.w %s", opcode, reg_names16[opcode & 0xf]); + dstreg = opcode & 0xf; + sdata16 = h8_neg16(h8_getreg16(dstreg)); + h8_setreg16(dstreg, sdata16); + H8_IFETCH_TIMING(1); + break; + case 0xf: + // exts.l Rx + dstreg = opcode & 0xf; + udata32=h8_getreg32(dstreg)&0xffff; + if(udata32&0x8000) + { + udata32|=0xffff0000; + } + h8_setreg32(dstreg, udata32); + + h8.h8vflag = 0; + h8.h8nflag = (udata32 & 0xffff0000) ? 1 : 0; + h8.h8zflag = (udata32) ? 0 : 1; + + H8_IFETCH_TIMING(1); + break; + + default: + logerror("H8/3002: Unk. group 1 7-9 %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0x8: + // sub.b rs, rd + dstreg = opcode & 0xf; + udata8 = h8_sub8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0x9: + // sub.w rs, rd + dstreg = opcode & 0xf; + udata16 = h8_sub16(h8_getreg16((opcode>>4) &0xf), h8_getreg16(dstreg)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + // sub.b rx + case 0xA: + if(opcode&0x80) + { + //logerror("H8/3002: Unk. group 1 A %x\n", opcode); + + // sub.l rs,rd + dstreg = opcode & 0x7; + udata32=h8_sub32(h8_getreg32((opcode>>4) &0x7), h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(2); + break; + + } + else + { + if(opcode & 0xf0) + { + logerror("H8/3002: Unk. group A2 0 %x\n", opcode); + h8.h8err = 1; + } + else + { + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_dec8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + } + } + break; + // + case 0xb: + switch((opcode>>4)& 0xf) + { + case 0: // subs.l #1, rN (decrement without touching flags) + dstreg = opcode & 0x7; + udata32 = h8_getreg32(dstreg); + udata32--; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + case 5: // dec.w #1, rN + dstreg = opcode & 0xf; + udata16 = h8_dec16(h8_getreg16(dstreg)); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 7: // dec.l #1, rN + dstreg = opcode & 0x7; + udata32 = h8_dec32(h8_getreg32(dstreg)); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + case 8: // subs.l #2, rN (decrement without touching flags) + dstreg = opcode & 0x7; + udata32 = h8_getreg32(dstreg); + udata32-=2; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + case 9: // subs.l #4, rN (decrement without touching flags) + dstreg = opcode & 0x7; + udata32 = h8_getreg32(dstreg); + udata32-=4; + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + case 0xd: // dec.w #2, rN + dstreg = opcode & 0xf; + udata16 = h8_dec16(h8_getreg16(dstreg)); + if (h8.h8vflag) + { + udata16 = h8_dec16(udata16); + h8.h8vflag = 1; + } + else + udata16 = h8_dec16(udata16); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 0xf: // dec.l #2, rN + dstreg = opcode & 0x7; + udata32 = h8_dec32(h8_getreg32(dstreg)); + if (h8.h8vflag) + { + udata32 = h8_dec32(udata32); + h8.h8vflag = 1; + } + else + udata32 = h8_dec32(udata32); + h8_setreg32(dstreg, udata32); + H8_IFETCH_TIMING(1); + break; + + default: + logerror("H8/3002: Unk. group 1 B %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0xc: + // cmp.b rs, rd + h8_cmp8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(opcode & 0xf)); + H8_IFETCH_TIMING(1); + break; + case 0xd: + // cmp.w rx, ry + h8_cmp16(h8_getreg16((opcode>>4) &0xf), h8_getreg16(opcode & 0xf)); + H8_IFETCH_TIMING(1); + break; + case 0xe: + // subx.b rx, ry + dstreg = opcode & 0xf; + udata8 = h8_subx8(h8_getreg8((opcode>>4) &0xf), h8_getreg8(dstreg)); + h8_setreg8(dstreg, udata8); + H8_IFETCH_TIMING(1); + break; + case 0xf: + if(opcode & 0x80) + { + if(opcode & 8) + { + logerror("H8/3002: Unk. group 1 f %x\n", opcode); + h8.h8err = 1; + } + else + { + h8_cmp32(h8_getreg32((opcode>>4) & 0x7), h8_getreg32(opcode & 0x7)); + H8_IFETCH_TIMING(1); + } + } + else + { + logerror("H8/3002: Unk. group 1 f2 %x\n", opcode); + h8.h8err = 1; + } + break; + default: + logerror("H8/3002: Unk. group 1 def %x\n", opcode); + h8.h8err = 1; + break; + } +} + + +static void h8_group5(UINT16 opcode) +{ + switch((opcode>>8)&0xf) + { + case 0x0: + // mulxu.b + udata8 = h8_getreg8((opcode>>4)&0xf); + udata16 = h8_getreg16(opcode & 0xf); + udata16 &= 0xff; + udata16 = udata16*udata8; + // no flags modified! + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + H8_IOP_TIMING(12); + break; + case 0x1: + // divxu.b + udata8 = h8_getreg8((opcode>>4)&0xf); + udata16 = h8_getreg16(opcode & 0x0f); + udata16 = h8_divxu8(udata16,udata8); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + H8_IOP_TIMING(12); + break; + case 0x2: + // mulxu.w + udata16 = h8_getreg16((opcode>>4)&0xf); + udata32 = h8_getreg32(opcode & 7); + udata32 &= 0xffff; + udata32 = udata32*udata16; + // no flags modified! + h8_setreg32(opcode & 7, udata32); + H8_IFETCH_TIMING(1); + H8_IOP_TIMING(20); + break; + case 0x3: + // divxu.w + udata16 = h8_getreg16((opcode>>4)&0xf); + udata32 = h8_getreg32(opcode & 7); + udata32 = h8_divxu16(udata32,udata16); + h8_setreg32(opcode & 7, udata32); + H8_IFETCH_TIMING(1); + H8_IOP_TIMING(20); + break; + case 0x4: + if(opcode == 0x5470) + { + // rts + udata32 = h8_mem_read32(h8_getreg32(H8_SP)); + h8_setreg32(H8_SP, h8_getreg32(H8_SP)+4); + // extended mode + h8.pc = udata32; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); + H8_STACK_TIMING(2); + H8_IOP_TIMING(2); + } + else + { + logerror("H8/3002: Unk. group 5 1 %x\n", opcode); + h8.h8err = 1; + } + break; + case 0x5: + // bsr 8 + sdata8 = opcode & 0xff; + // extended mode stack push! + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-4); + h8_mem_write32(h8_getreg32(H8_SP), h8.pc); + h8.pc = h8.pc + sdata8; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); H8_STACK_TIMING(2); + break; + case 0x6: + // rte + if(opcode == 0x5670) + { + // restore CCR + udata16 = h8_mem_read16(h8_getreg32(H8_SP)); + h8_setreg32(H8_SP, h8_getreg32(H8_SP)+2); + // extended mode restore PC + udata32 = h8_mem_read32(h8_getreg32(H8_SP)); + h8_setreg32(H8_SP, h8_getreg32(H8_SP)+4); + // extended mode + h8.pc = udata32; + change_pc(h8.pc); + // must do this last, because set_ccr() does a check_irq() + h8_set_ccr((UINT8)udata16); + H8_IFETCH_TIMING(2); + H8_STACK_TIMING(2); + H8_IOP_TIMING(2); + } + else + { + logerror("H8/3002: Unk. group 5 6 %x\n", opcode); + h8.h8err = 1; + } + break; + // trapa + case 0x7: + logerror("H8/3002: Unk. group 5 7 %x\n", opcode); + h8.h8err = 1; + break; + case 0x8: + // bcc @xx:16 + if(opcode & 0xf) + { + logerror("H8/3002: Unk. group 5 8 %x\n", opcode); + h8.h8err = 1; + } + else + { + sdata16 = h8_mem_read16(h8.pc); + h8.pc += 2; + if( h8_branch((opcode >> 4) & 0xf) == 1)h8.pc += sdata16; + change_pc(h8.pc); + H8_IOP_TIMING(2) + } + break; + case 0x9: + // jmp @erd + address24 = h8_getreg32((opcode>>4)&7); + address24 &= 0xffffff; + h8.pc = address24; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); + break; + // jmp @aa:24 + case 0xa: + address24=h8_mem_read32(h8.pc-2); + address24 &= 0xffffff; + h8.pc = address24; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); + H8_IOP_TIMING(2); + break; + // jmp @aa:8 + case 0xc: + if(opcode & 0xff) + { + logerror("H8/3002: Unk. group 5 c %x\n", opcode); + h8.h8err = 1; + } + else + { + // bsr d:16 + sdata16=h8_mem_read16(h8.pc); + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-4); + h8_mem_write32(h8_getreg32(H8_SP), h8.pc+2); + h8.pc += sdata16 + 2; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); H8_STACK_TIMING(2); H8_IOP_TIMING(2); + } + break; + case 0xd: + // jsr @reg + address24=h8_getreg32((opcode>>4)&7); + address24 &= 0xffffff; + // extended mode stack push! + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-4); + h8_mem_write32(h8_getreg32(H8_SP), h8.pc); + h8.pc = address24; + change_pc(h8.pc); + H8_STACK_TIMING(2); + H8_IOP_TIMING(2); + break; + case 0xe: + // jsr @aa:24 + address24=h8_mem_read32(h8.pc-2); + address24 &= 0xffffff; + // extended mode stack push! + h8_setreg32(H8_SP, h8_getreg32(H8_SP)-4); + h8_mem_write32(h8_getreg32(H8_SP), h8.pc+2); + h8.pc = address24; + change_pc(h8.pc); + H8_IFETCH_TIMING(2); + H8_STACK_TIMING(2); + H8_IOP_TIMING(2); + break; + // jsr @aa:8 + default: + logerror("H8/3002: Unk. group 5 def %x\n", opcode); + h8.h8err = 1; + break; + } +} + +static void h8_group6(UINT16 opcode) +{ + switch((opcode>>8)&0xf) + { + case 0:case 1:case 2:case 3: + { + UINT8 bitnr; + + dstreg = opcode & 0xf; + udata8 = h8_getreg8(dstreg); + bitnr = h8_getreg8((opcode>>4)& 0xf)&7; + + switch((opcode>>8)&0xf) + { + case 0: udata8 = h8_bset8(bitnr, udata8); h8_setreg8(dstreg, udata8); H8_IFETCH_TIMING(1); break; + case 2: udata8 = h8_bclr8(bitnr, udata8); h8_setreg8(dstreg, udata8); H8_IFETCH_TIMING(1); break; + case 3: h8_btst8(bitnr, udata8); H8_IFETCH_TIMING(1); break; + default: + logerror("H8/3002: Unk. group 6 def 0-3-0 %x\n", opcode); + h8.h8err = 1; + break; + } + } + break; + case 0x4: + // or.w rs, rd + dstreg = opcode & 0xf; + udata16 = h8_getreg16(dstreg); + udata16 = h8_or16(h8_getreg16((opcode>>4) & 0xf), udata16); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 0x5: + // xor.w rs, rd + dstreg = opcode & 0xf; + udata16 = h8_getreg16(dstreg); + udata16 = h8_xor16(h8_getreg16((opcode>>4) & 0xf), udata16); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1); + break; + case 0x6: + // and.w rs, rd + dstreg = opcode & 0xf; + udata16 = h8_getreg16(dstreg); + udata16 = h8_and16(h8_getreg16((opcode>>4) & 0xf), udata16); + h8_setreg16(dstreg, udata16); + H8_IFETCH_TIMING(1) + break; + case 0x7: + // bst/bist #imm, rd + if(opcode & 0x80) + { + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_bist8((opcode>>4) & 7, udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + } + else + { + udata8 = h8_getreg8(opcode & 0xf); + udata8 = h8_bst8((opcode>>4) & 7, udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + } + break; + case 0x8: + if(opcode & 0x80) + { + // mov.b rx, @rx + udata8 = h8_getreg8(opcode & 0xf); + address24 = h8_getreg32((opcode>>4)&7) & 0xffffff; + h8_mov8(udata8); + h8_mem_write8(address24, udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + } + else + { + // mov.b @rx, rx + address24 = h8_getreg32((opcode>>4)&7) & 0xffffff; + udata8 = h8_mem_read8(address24); + h8_mov8(udata8); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + } + break; + case 0x9: + if(opcode & 0x80) + { + // mov.w rx, @rx + address24 = h8_getreg32((opcode>>4)&7) & 0xffffff; + udata16 = h8_getreg16(opcode & 0xf); + h8_mov16(udata16); + h8_mem_write16(address24, udata16); + H8_IFETCH_TIMING(1); + H8_WORD_TIMING(1, address24); + } + else + { + // mov.w @rx, rx + address24 = h8_getreg32((opcode>>4)&7) & 0xffffff; + udata16 = h8_mem_read16(address24); + h8_mov16(udata16); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + H8_WORD_TIMING(1, address24); + } + break; + case 0xa: + // mov.b rx, @xx + switch((opcode>>4)&0xf) + { + case 0x0: + sdata16=h8_mem_read16(h8.pc); + h8.pc += 2; + address24 = sdata16 & 0xffffff; + udata8=h8_mem_read8(address24); + h8_mov8(udata8); // flags only + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + break; + case 0x2: + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata8=h8_mem_read8(address24); + h8_mov8(udata8); // flags only + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(2); + H8_BYTE_TIMING(1, address24); + break; + case 0x8: + sdata16=h8_mem_read16(h8.pc); + h8.pc += 2; + address24 = sdata16 & 0xffffff; + udata8=h8_getreg8(opcode & 0xf); + h8_mov8(udata8); // flags only + h8_mem_write8(address24, udata8); + H8_IFETCH_TIMING(3); + H8_BYTE_TIMING(1, address24); + break; + case 0xa: // pass + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata8=h8_getreg8(opcode & 0xf); + h8_mov8(udata8); // flags only + h8_mem_write8(address24, udata8); + H8_IFETCH_TIMING(3); + H8_BYTE_TIMING(1, address24); + break; + default: + logerror("H8/3002: Unk. group 6 a %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0xb: + // mov.w rx, @xx / mov.w @xx, rx + switch((opcode>>4)&0xf) + { + case 0x0: + sdata16=h8_mem_read16(h8.pc); + address24 = sdata16; + address24 &= 0xffffff; + h8.pc += 2; + udata16=h8_mem_read16(address24); + h8_mov16(udata16); // flags only + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(1, address24); + break; + case 0x2: + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata16=h8_mem_read16(address24); + h8_mov16(udata16); // flags only + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(4); + H8_WORD_TIMING(1, address24); + break; + case 0x8: + sdata16=h8_mem_read16(h8.pc); + address24 = sdata16; + address24 &= 0xffffff; + h8.pc += 2; + udata16=h8_getreg16(opcode & 0xf); + h8_mov16(udata16); // flags only + h8_mem_write16(address24, udata16); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(1, address24); + break; + case 0xa: // pass + address24=h8_mem_read32(h8.pc); + h8.pc += 4; + udata16=h8_getreg16(opcode & 0xf); + h8_mov16(udata16); // flags only + h8_mem_write16(address24, udata16); + H8_IFETCH_TIMING(4); + H8_WORD_TIMING(1, address24); + break; + default: + logerror("H8/3002: Unk. group 6b %x\n", opcode); + h8.h8err = 1; + break; + } + break; + case 0xc: + if(opcode & 0x80) + { + // mov.b rx, @-erx + srcreg = (opcode>>4)&7; + h8_setreg32(srcreg, h8_getreg32(srcreg)-1); + address24 = h8_getreg32(srcreg) & 0xffffff; + udata8 = h8_getreg8(opcode & 0xf); + h8_mem_write8(address24, udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + H8_IOP_TIMING(2); + } + else + { + // mov.b @erx+,rx + srcreg = (opcode>>4)&7; + address24 = h8_getreg32(srcreg) & 0xffffff; + h8_setreg32(srcreg, h8_getreg32(srcreg)+1); + udata8 = h8_mem_read8(address24); + h8_setreg8(opcode & 0xf, udata8); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + H8_IOP_TIMING(2); + } + h8_mov8(udata8); + break; + case 0xd: + if(opcode & 0x80) + { + // mov.w rs, @-erd + srcreg = (opcode>>4)&7; + h8_setreg32(srcreg, h8_getreg32(srcreg)-2); + address24 = h8_getreg32(srcreg) & 0xffffff; + udata16 = h8_getreg16(opcode & 0xf); + h8_mem_write16(address24, udata16); + H8_IFETCH_TIMING(1); + H8_WORD_TIMING(1, address24); + H8_IOP_TIMING(2); + } + else + { + // mov.w @ers+, rd + srcreg = (opcode>>4)&7; + address24 = h8_getreg32(srcreg) & 0xffffff; + h8_setreg32(srcreg, h8_getreg32(srcreg)+2); + udata16 = h8_mem_read16(address24); + h8_setreg16(opcode & 0xf, udata16); + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING(1, address24); + H8_IOP_TIMING(2); + } + h8_mov16(udata16); + break; + case 0xe: // pass + // mov.b @(displ16 + Rs), rd + sdata16=h8_mem_read16(h8.pc); // sign extend displacements ! + h8.pc += 2; + address24 = (h8_getreg32((opcode>>4)&7)) & 0xffffff; + address24 += sdata16; + if(opcode & 0x80) + { + udata8 = h8_getreg8(opcode & 0xf); + h8_mem_write8(address24, udata8); + } + else + { + udata8 = h8_mem_read8(address24); + h8_setreg8(opcode & 0xf, udata8); + } + h8_mov8(udata8); + H8_IFETCH_TIMING(2); + H8_BYTE_TIMING(1, address24); + break; + case 0xf: + // mov.w @(displ16 + Rs), rd + sdata16=h8_mem_read16(h8.pc); // sign extend displacements ! + h8.pc += 2; + address24 = (h8_getreg32((opcode>>4)&7)) & 0xffffff; + address24 += sdata16; + if(opcode & 0x80) + { + udata16 = h8_getreg16(opcode & 0xf); + h8_mem_write16(address24, udata16); + } + else + { + udata16 = h8_mem_read16(address24); + h8_setreg16(opcode & 0xf, udata16); + } + h8_mov16(udata16); + H8_IFETCH_TIMING(2); + H8_WORD_TIMING(1, address24); + break; + default: + logerror("H8/3002: Unk. group 6 def %x\n", opcode); + h8.h8err = 1; + break; + } +} + +static void h8_group7(UINT16 opcode) +{ + switch((opcode>>8)&0xf) + { + case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7: + { + UINT8 bitnr; + + dstreg = opcode & 0xf; + udata8 = h8_getreg8(dstreg); + bitnr = (opcode>>4)&7; + + if(((opcode>>4)&0x8) == 0) + { + switch((opcode>>8)&7) + { + case 0: udata8 = h8_bset8(bitnr, udata8); h8_setreg8(dstreg, udata8); H8_IFETCH_TIMING(1); break; + case 2: udata8 = h8_bclr8(bitnr, udata8); h8_setreg8(dstreg, udata8);H8_IFETCH_TIMING(1);break; + case 3: h8_btst8(bitnr, udata8); H8_IFETCH_TIMING(1); break; + case 7: h8_bld8(bitnr, udata8); H8_IFETCH_TIMING(1); break; + default: + logerror("H8/3002: Unk. group 7 0-7 def %x\n", opcode); + h8.h8err = 1; + break; + } + } + else + { + switch((opcode>>8)&7) + { + default: + logerror("H8/3002: Unk. group 7 0-7-1 def %x\n", opcode); + h8.h8err = 1; + break; + } + } + } + break; + case 0x8: + ext16 = h8_mem_read16(h8.pc); + h8.pc += 2; + udata32 = h8_mem_read32(h8.pc); + h8.pc += 4; + + if(((ext16>>8) & 0xf) == 0xa) + { + if(((ext16>>4) & 0xf) == 0xa) + { + udata8 = h8_getreg8(ext16 & 0xf); + h8_mov8(udata8); // update flags ! + udata32 += h8_getreg32((opcode >> 4) & 7); + h8_mem_write8(udata32, udata8); + } + else + { + udata32 += h8_getreg32((opcode >> 4) & 7); + udata8 = h8_mem_read8(udata32); + h8_mov8(udata8); // update flags ! + h8_setreg8(ext16 & 0xf, udata8); + } + H8_BYTE_TIMING(1, udata32); + H8_IFETCH_TIMING(4); + } + else if ((ext16 & 0xfff0) == 0x6b20) // mov.w @(24-bit direct, rN), rM + { + udata32 += h8_getreg32((opcode >> 4) & 7); + udata16 = h8_mem_read16(udata32); + h8_setreg16(ext16 & 0xf, udata16); + h8_mov16(udata16); // update flags ! + H8_WORD_TIMING(1, udata32); + H8_IFETCH_TIMING(4); + } + else if ((ext16 & 0xfff0) == 0x6ba0) // mov.w rM, @(24-bit direct, rN) + { + udata32 += h8_getreg32((opcode >> 4) & 7); + udata16 = h8_getreg16(ext16 & 0xf); + h8_mem_write16(udata32, udata16); + h8_mov16(udata16); // update flags ! + H8_WORD_TIMING(1, udata32); + H8_IFETCH_TIMING(4); + } + else + { + logerror("H8/3002: Unk. group 7 8 %x\n", opcode); + h8.h8err = 1; + } + break; + + + // xxx.w #aa:16, rd + case 0x9: + if( ((opcode>>4) & 0xf) > 0x6) + { + logerror("H8/3002: Unk. group 7 9 %x\n", opcode); + h8.h8err = 1; + } + else + { + UINT16 dst16; + udata16 = h8_mem_read16(h8.pc); + h8.pc += 2; + dstreg = opcode&0xf; + dst16 = h8_getreg16(dstreg); + + switch((opcode>>4)&7) + { + case 0: dst16 = h8_mov16(udata16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2);break; + case 1: dst16 = h8_add16(udata16, dst16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2); break; + case 2: h8_cmp16(udata16, dst16); H8_IFETCH_TIMING(2); break; + case 3: dst16 = h8_sub16(udata16, dst16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2); break; + case 4: dst16 = h8_or16(udata16, dst16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2); break; + case 5: dst16 = h8_xor16(udata16, dst16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2); break; + case 6: dst16 = h8_and16(udata16, dst16); h8_setreg16(dstreg, dst16); H8_IFETCH_TIMING(2); break; + default: + logerror("H8/3002: Unk. group 7 9 %x\n", opcode); + h8.h8err = 1; + break; + } + } + break; + // xxx.l #aa:32, erd + case 0xa: + if( (((opcode>>4) & 0xf) > 0x6) || (opcode & 0x8)) + { + logerror("H8/3002: Unk. group 7 a %x\n", opcode); + h8.h8err = 1; + } + else + { + UINT32 dst32; + udata32 = h8_mem_read32(h8.pc); + dstreg = opcode&0x7; + h8.pc +=4; + dst32 = h8_getreg32(dstreg); + + switch((opcode>>4)&7) + { + case 0: dst32 = h8_mov32(udata32); h8_setreg32(dstreg, dst32); H8_IFETCH_TIMING(3); break; + case 1: dst32 = h8_add32(udata32, dst32); h8_setreg32(dstreg, dst32); H8_IFETCH_TIMING(3); break; + case 2: h8_cmp32(udata32, dst32); H8_IFETCH_TIMING(3); break; + case 6: dst32 = h8_and32(udata32, dst32); h8_setreg32(dstreg, dst32); H8_IFETCH_TIMING(3); break; + default: + logerror("H8/3002: Unk. group 7 a2 %x\n", opcode); + h8.h8err = 1; + break; + } + } + break; + // eepmov + case 0xb: + if ((opcode & 0xff) == 0xd4) + { + UINT16 cnt = h8_getreg16(4); + + H8_IFETCH_TIMING(1); + H8_BYTE_TIMING((2*cnt)+2, h8.regs[5]); + + // eepmov.w + while (cnt > 0) + { + h8_mem_write8(h8.regs[6], h8_mem_read8(h8.regs[5])); + h8.regs[5]++; + h8.regs[6]++; + cnt--; + } + h8_setreg16(4, 0); + h8.pc += 2; + } + else + { + logerror("H8/3002: Unk. eepmov form\n"); + h8.h8err = 1; + } + break; + // bxx.b #xx:3, @rd + case 0xc: + { + UINT8 bitnr; + + address24 = h8_getreg32((opcode>>4) & 0x7); + udata8 = h8_mem_read8(address24); + H8_BYTE_TIMING(1, address24); + + ext16 = h8_mem_read16(h8.pc); + h8.pc += 2; + H8_IFETCH_TIMING(2); + + switch(ext16>>8) + { + // BTST Rn,@ERd + case 0x63: + srcreg = (ext16>>4)&0xf; + bitnr = h8_getreg8(srcreg)&7; + h8_btst8(bitnr, udata8); + break; + // btst.b #imm, @Rn + case 0x73: + bitnr = (ext16>>4)&7; + h8_btst8(bitnr, udata8); + break; + default: + h8.h8err=1; + } + } + break; + case 0xd: + { + UINT8 bitnr; + sdata16 = h8_mem_read16(h8.pc); + h8.pc += 2; + address24 = h8_getreg32((opcode>>4) & 0x7); + udata8 = h8_mem_read8(address24); + bitnr = (sdata16>>4)&7; + + if(((sdata16>>4)&0x8) == 0) + { + switch ((sdata16>>8)&0xff) + { + // bset.b #imm, @Rn + case 0x70: udata8 = h8_bset8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); break; + // bclr.b #imm, @Rn + case 0x72: udata8 = h8_bclr8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); break; + default: + h8.h8err=1; + logerror("H8/3002: Unk. group 7 cd-1 %x (%x)\n", opcode, (sdata16>>4)&7); + break; + } + } + else + { + switch ((sdata16>>8)&7) + { + default: + h8.h8err=1; + logerror("H8/3002: Unk. group 7 cd-2 %x %x\n", opcode, sdata16); + break; + } + } + } + break; + // bxxx.b #imm, @aa:8 + case 0xe: + case 0xf: + { + UINT8 bitnr=0; + ext16 = h8_mem_read16(h8.pc); + h8.pc += 2; + address24 = 0xffff00 + (opcode & 0xff); + udata8 = h8_mem_read8(address24); + + switch((ext16>>8)&0xff) + { + case 0x30: + case 0x60: + bitnr = (ext16>>4)&7; + udata8 = h8_bset8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + break; + case 0x70: + bitnr = (ext16>>4)&7; + if(ext16&0x80) h8.h8err = 1; + udata8 = h8_bset8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + break; + case 0x32: + case 0x62: + bitnr = h8_getreg8((ext16>>4)&0xf)&7; + udata8 = h8_bclr8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + break; + case 0x72: + bitnr = (ext16>>4)&7; + if(ext16&0x80) h8.h8err = 1; + udata8 = h8_bclr8(bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + break; + case 0x63: + bitnr = h8_getreg8((ext16>>4)&0xf)&7; + h8_btst8(bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24); + break; + case 0x73: + bitnr = (ext16>>4)&7; + if(ext16&0x80) h8.h8err = 1; + h8_btst8(bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24); + break; + case 0x74: + bitnr = (ext16>>4)&7; + if(ext16&0x80) + { + // bior + h8.h8err = 1; + } + else + { + h8_bor8(bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24); + } + break; + case 0x67: + bitnr = (ext16>>4)&7; + if(ext16&0x80) + { + // bist + h8.h8err = 1; + } + else + { + h8_bst8(bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + } + break; + case 0x77: + bitnr = (ext16>>4)&7; + if(ext16&0x80) + { + // bild + h8.h8err = 1; + } + else + { + h8_bld8(bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24); + } + break; + default: + h8.h8err = 1; + break; + } + if(h8.h8err) + logerror("H8/3002: Unk. group 7 e %x\n", opcode); + } + break; + default: + logerror("H8/3002: Unk. group 7 def %x\n", opcode); + h8.h8err = 1; + break; + } +} + + +static UINT8 h8_mov8(UINT8 src) +{ + // N and Z modified + h8.h8nflag = (src>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(src==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return src; +} + +static UINT16 h8_mov16(UINT16 src) +{ + // N and Z modified + h8.h8nflag = (src>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(src==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + return src; +} + +static UINT32 h8_mov32(UINT32 src) +{ + // N and Z modified + h8.h8nflag = (src>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(src==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return src; +} + +static UINT8 h8_sub8(UINT8 src, UINT8 dst) +{ + UINT16 res; + + res = (UINT16)dst - src; + // H,N,Z,V,C modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = (((src^dst) & (res^dst))>>7) & 1; + h8.h8cflag = (res >> 8) & 1; + + // zflag + if((res&0xff)==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src^dst^res) & 0x10) ? 1 : 0; + + return res; +} + +static UINT16 h8_sub16(UINT16 src, UINT16 dst) +{ + UINT32 res; + + res = (UINT32)dst - src; + // H,N,Z,V,C modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = (((src^dst) & (res^dst))>>15) & 1; + h8.h8cflag = (res >> 16) & 1; + // h8.h8hflag = (res>>28) & 1; + + // zflag + if((res&0xffff)==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0; + + return res; +} + +static UINT32 h8_sub32(UINT32 src, UINT32 dst) +{ + UINT64 res; + + res = (UINT64)dst - src; + // H,N,Z,V,C modified + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = (((src^dst) & (res^dst))>>31) & 1; + h8.h8cflag = (res >> 32) & 1; + // h8.h8hflag = (res>>28) & 1; + + // zflag + if((res&0xffffffff)==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0; + + return res; +} + + + + +static UINT8 h8_add8(UINT8 src, UINT8 dst) +{ + UINT16 res; + + res = (UINT16)src + dst; + // H,N,Z,V,C modified + h8.h8nflag = (res & 0x80) ? 1 : 0; + h8.h8vflag = ((src^res) & (dst^res) & 0x80) ? 1 : 0; + h8.h8cflag = (res & 0x100) ? 1 : 0; + h8.h8zflag = (res & 0xff) ? 0 : 1; + h8.h8hflag = ((src^dst^res) & 0x10) ? 1 : 0; + + return (UINT8)res; +} + +static UINT16 h8_add16(UINT16 src, UINT16 dst) +{ + UINT32 res; + + res = (UINT32)src + dst; + // H,N,Z,V,C modified + h8.h8nflag = (res & 0x8000) ? 1 : 0; + h8.h8vflag = ((src^res) & (dst^res) & 0x8000) ? 1 : 0; + h8.h8cflag = (res & 0x10000) ? 1 : 0; + h8.h8zflag = (res & 0xffff) ? 0 : 1; + h8.h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0; + + return res; +} + +static UINT32 h8_add32(UINT32 src, UINT32 dst) +{ + UINT64 res; + + res = (UINT64)src + dst; + // H,N,Z,V,C modified + h8.h8nflag = (res & 0x80000000) ? 1 : 0; + h8.h8vflag = (((src^res) & (dst^res)) & 0x80000000) ? 1 : 0; + h8.h8cflag = ((res) & (((UINT64)1) << 32)) ? 1 : 0; + h8.h8zflag = (res & 0xffffffff) ? 0 : 1; + h8.h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0; + + return res; +} + + +static UINT8 h8_addx8(UINT8 src, UINT8 dst) +{ + UINT16 res; + + res = (UINT16)src + dst + h8.h8cflag; + // H,N,Z,V,C modified + h8.h8nflag = (res & 0x80) ? 1 : 0; + h8.h8vflag = ((src^res) & (dst^res) & 0x80) ? 1 : 0; + h8.h8cflag = (res >> 8) & 1; + h8.h8hflag = ((src^dst^res) & 0x10) ? 1 : 0; + h8.h8zflag = (res & 0xff) ? 0 : h8.h8zflag; + + return (UINT8)res; +} + +static void h8_cmp8(UINT8 src, UINT8 dst) +{ + UINT16 res = (UINT16)dst - src; + + h8.h8cflag = (res & 0x100) ? 1 : 0; + h8.h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x80) ? 1 : 0; + h8.h8zflag = ((res & 0xff) == 0) ? 1 : 0; + h8.h8nflag = (res & 0x80) ? 1 : 0; + h8.h8hflag = ((src^dst^res) & 0x10) ? 1 : 0; +} + +static void h8_cmp16(UINT16 src, UINT16 dst) +{ + UINT32 res = (UINT32)dst - src; + + h8.h8cflag = (res & 0x10000) ? 1 : 0; + h8.h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x8000) ? 1 : 0; + h8.h8zflag = ((res & 0xffff) == 0) ? 1 : 0; + h8.h8nflag = (res & 0x8000) ? 1 : 0; + h8.h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0; +} + +static void h8_cmp32(UINT32 src, UINT32 dst) +{ + UINT64 res = (UINT64)dst - src; + + h8.h8cflag = (res & (UINT64)U64(0x100000000)) ? 1 : 0; + h8.h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x80000000) ? 1 : 0; + h8.h8zflag = ((res & 0xffffffff) == 0) ? 1 : 0; + h8.h8nflag = (res & 0x80000000) ? 1 : 0; + h8.h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0; +} + + +static UINT8 h8_subx8(UINT8 src, UINT8 dst) +{ + UINT16 res; + + res = (UINT16)dst - src - (h8.h8cflag) ? 1 : 0; + // H,N,Z,V,C modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = (((src^dst) & (res^dst))>>7) & 1; + h8.h8cflag = (res >> 8) & 1; + + // zflag + if((res&0xff)==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src^dst^res) & 0x10) ? 1 : 0; + + return res; +} + +static UINT8 h8_or8(UINT8 src, UINT8 dst) +{ + UINT8 res; + res = src | dst; + + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_or16(UINT16 src, UINT16 dst) +{ + UINT16 res; + res = src | dst; + + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_xor8(UINT8 src, UINT8 dst) +{ + UINT8 res; + res = src ^ dst; + + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_xor16(UINT16 src, UINT16 dst) +{ + UINT16 res; + res = src ^ dst; + + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_xor32(UINT32 src, UINT32 dst) +{ + UINT32 res; + res = src ^ dst; + + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_and8(UINT8 src, UINT8 dst) +{ + UINT8 res; + + res = src & dst; + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_and16(UINT16 src, UINT16 dst) +{ + UINT16 res; + + res = src & dst; + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_and32(UINT32 src, UINT32 dst) +{ + UINT32 res; + + res = src & dst; + // N and Z modified + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static void h8_btst8(UINT8 bit, UINT8 dst) +{ + // test single bit and update Z flag + if( (dst & (1<<bit)) == 0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } +} + +static void h8_bld8(UINT8 bit, UINT8 dst) +{ + // load bit to carry + h8.h8cflag = (dst >> bit) & 1; +} + +#ifdef UNUSED_FUNCTION +static UINT8 h8_bnot8(UINT8 src, UINT8 dst) +{ + UINT8 res; + + // invert single bit, no effect on C flag + res = dst ^ (1<<src); + + return res; +} +#endif + +static UINT8 h8_bst8(UINT8 src, UINT8 dst) +{ + UINT8 res; + + // store carry flag in bit position + if(h8.h8cflag == 1) + { + res = dst | (1<<src); + } + else + { + res = dst & ~(1<<src); // mask off + } + return res; +} + +static UINT8 h8_bist8(UINT8 src, UINT8 dst) +{ + UINT8 res; + + // store inverse of carry flag in bit position + if(h8.h8cflag == 0) + { + res = dst | (1<<src); + } + else + { + res = dst & ~(1<<src); // mask off + } + return res; +} + +static UINT8 h8_bset8(UINT8 src, UINT8 dst) +{ + // pass + UINT8 res; + res = dst | (1<<src); + return res; +} + +// does not affect result, res in C flag only +static void h8_bor8(UINT8 src, UINT8 dst) +{ + // pass + UINT8 res; + + res = dst & (1<<src); + h8.h8cflag |= res ? 1 : 0; +} + +#ifdef UNUSED_FUNCTION +static void h8_bxor8(UINT8 src, UINT8 dst) +{ + dst >>= src; + dst &= 0x1; + h8.h8cflag ^= dst; +} +#endif + +static UINT8 h8_bclr8(UINT8 src, UINT8 dst) +{ + // pass + UINT8 res; + res = dst & ~(1<<src); + return res; +} + +static INT8 h8_neg8(INT8 src) +{ + INT8 res; + + if((UINT8)src == 0x80) + { + // overflow ! + h8.h8vflag = 1; + res = 0x80; + } + else + { + h8.h8vflag = 0; + res = 0-src; + } + + // N and Z modified + h8.h8nflag = (res>>7) & 1; + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src|res)&0x08) ? 1 : 0; + h8.h8cflag = ((src|res)&0x80) ? 1 : 0; + + return res; +} + +static INT16 h8_neg16(INT16 src) +{ + INT16 res; + + if((UINT16)src == 0x8000) + { + // overflow ! + h8.h8vflag = 1; + res = 0x8000; + } + else + { + h8.h8vflag = 0; + res = 0-src; + } + + // N and Z modified + h8.h8nflag = (res>>15) & 1; + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + h8.h8hflag = ((src|res)&0x0800) ? 1 : 0; + h8.h8cflag = ((src|res)&0x8000) ? 1 : 0; + + return res; +} + +static UINT8 h8_not8(UINT8 src) +{ + UINT8 res; + + res = ~src; + + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_not16(UINT16 src) +{ + UINT16 res; + + res = ~src; + + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_rotxr8(UINT8 src) +{ + UINT8 res; + + // rotate through carry right + res = src>>1; + if(h8.h8cflag)res |= 0x80; // put cflag in upper bit + h8.h8cflag = src & 1; + + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_rotxr16(UINT16 src) +{ + UINT16 res; + + // rotate through carry right + res = src>>1; + if(h8.h8cflag)res |= 0x8000; // put cflag in upper bit + h8.h8cflag = src & 1; + + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_rotxl8(UINT8 src) +{ + UINT8 res; + + // rotate through carry + res = src<<1; + res |= (h8.h8cflag & 1); + h8.h8cflag = (src>>7) & 1; + + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_rotxl16(UINT16 src) +{ + UINT16 res; + + // rotate through carry + res = src<<1; + res |= (h8.h8cflag & 1); + h8.h8cflag = (src>>15) & 1; + + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_rotxl32(UINT32 src) +{ + UINT32 res; + + // rotate through carry + res = src<<1; + res |= (h8.h8cflag & 1); + h8.h8cflag = (src>>31) & 1; + + // N and Z modified + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + + +static UINT8 h8_rotl8(UINT8 src) +{ + UINT8 res; + + // rotate + res = src<<1; + h8.h8cflag = (src>>7) & 1; + res |= (h8.h8cflag & 1); + + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_rotl16(UINT16 src) +{ + UINT16 res; + + // rotate + res = src<<1; + h8.h8cflag = (src>>15) & 1; + res |= (h8.h8cflag & 1); + + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_shll8(UINT8 src) +{ + UINT8 res; + h8.h8cflag = (src>>7) & 1; + res = src<<1; + // N and Z modified + h8.h8nflag = (res>>7) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_shll16(UINT16 src) +{ + UINT16 res; + h8.h8cflag = (src>>15) & 1; + res = src<<1; + // N and Z modified + h8.h8nflag = (res>>15) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_shll32(UINT32 src) +{ + UINT32 res; + h8.h8cflag = (src>>31) & 1; + res = src<<1; + // N and Z modified + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_shlr8(UINT8 src) +{ + UINT8 res; + h8.h8cflag = src&1; + res = src>>1; + // N and Z modified + h8.h8nflag = 0; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_shlr16(UINT16 src) +{ + UINT16 res; + h8.h8cflag = src&1; + res = src>>1; + // N and Z modified + h8.h8nflag = 0; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_shlr32(UINT32 src) +{ + UINT32 res; + h8.h8cflag = src&1; + res = src>>1; + + // N and Z modified, V always cleared + h8.h8nflag = 0; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT8 h8_shar8(INT8 src) +{ + INT8 res; + h8.h8cflag = src&1; + res = (src>>1)|(src&0x80); + // N and Z modified + h8.h8nflag = (res>>7)&1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT16 h8_shar16(INT16 src) +{ + INT16 res; + h8.h8cflag = src&1; + res = (src>>1)|(src&0x8000); + // N and Z modified + h8.h8nflag = (res>>15)&1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT32 h8_shar32(INT32 src) +{ + INT32 res; + + h8.h8cflag = src&1; + res = (src>>1)|(src&0x80000000); + // N and Z modified + h8.h8nflag = (res>>31) & 1; + h8.h8vflag = 0; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT8 h8_shal8(INT8 src) +{ + INT8 res; + + h8.h8cflag = (src>>7)&1; + res = src<<1; + // N and Z modified + h8.h8nflag = (res>>7)&1; + h8.h8vflag = (((src>>7)&(~src>>6)) | ((~src>>7)&(~src>>6)))&1; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT16 h8_shal16(INT16 src) +{ + INT16 res; + + h8.h8cflag = (src>>15)&1; + res = src<<1; + // N and Z modified + h8.h8nflag = (res>>15)&1; + h8.h8vflag = (((src>>15)&(~src>>14)) | ((~src>>15)&(~src>>14)))&1; + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_dec8(UINT8 src) +{ + UINT8 res; + + res = src - 1; + // N and Z modified + h8.h8nflag = (res>>7)&1; + if(src == 0x80) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_dec16(UINT16 src) +{ + UINT16 res; + + res = src - 1; + // N and Z modified + h8.h8nflag = (res>>15)&1; + if(src == 0x8000) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_dec32(UINT32 src) +{ + UINT32 res; + + res = src - 1; + // N and Z modified + h8.h8nflag = (res>>31)&1; + if(src == 0x80000000) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT8 h8_inc8(UINT8 src) +{ + UINT8 res; + + res = src + 1; + // N and Z modified + h8.h8nflag = (res>>7)&1; + if(src == 0x7f) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT16 h8_inc16(UINT16 src) +{ + UINT16 res; + + res = src + 1; + // N and Z modified + h8.h8nflag = (res>>15)&1; + if(src == 0x7fff) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static UINT32 h8_inc32(UINT32 src) +{ + UINT32 res; + + res = src + 1; + // N and Z modified + h8.h8nflag = (res>>31)&1; + if(src == 0x7fffffff) + { + h8.h8vflag = 1; + } + else + { + h8.h8vflag = 0; + } + + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + + return res; +} + +static INT32 h8_mulxs16(INT16 src, INT16 dst) +{ + INT32 res; + + res = (INT32)src * dst; + + // N and Z modified + h8.h8nflag = (res>>31)&1; + // zflag + if(res==0) + { + h8.h8zflag = 1; + } + else + { + h8.h8zflag = 0; + } + return res; +} + +static UINT32 h8_divxs16(INT16 src, INT32 dst) +{ + // NOT tested ! + UINT32 res,r1,r2; + INT16 remainder, quotient; + + if(src!=0) + { + quotient = dst/src; + h8.h8zflag = 0; + } + else + { + quotient = 0; + h8.h8zflag = 1; + } + remainder = dst%src; + + r1=*("ient); + r2=*(&remainder); + res=(r2<<16)|r1; + + h8.h8nflag = (quotient<0)?1:0; + + return res; + +} + +static UINT16 h8_divxu8(UINT16 dst, UINT8 src) +{ + UINT8 remainder, quotient; + UINT16 res = 0; + // N and Z modified + h8.h8nflag = (src>>7)&1; + // zflag + if(src==0) + { + h8.h8zflag = 1; + // dont do anything on division by zero ! + } + else + { + h8.h8zflag = 0; + quotient = dst / src; + remainder = dst % src; + res = (remainder << 8) | quotient; + } + return res; +} + +static UINT32 h8_divxu16(UINT32 dst, UINT16 src) +{ + UINT16 remainder, quotient; + UINT32 res = 0; + // N and Z modified + h8.h8nflag = (src>>15)&1; + // zflag + if(src==0) + { + h8.h8zflag = 1; + // dont do anything on division by zero ! + } + else + { + h8.h8zflag = 0; + quotient = dst / src; + remainder = dst % src; + res = (remainder << 16) | quotient; + } + return res; +} + +// input: branch condition +// output: 1 if condition met, 0 if not condition met +static int h8_branch(UINT8 condition) +{ + int taken = 0; + + // a branch always eats 2 ifetch states, regardless of if it's taken + H8_IFETCH_TIMING(2) + + switch(condition) + { + case 0: // bt + taken = 1; + break; + case 1: // bf + break; + case 2: // bhi (C | Z) == 0) + if((h8.h8cflag | h8.h8zflag) == 0)taken = 1; + break; + case 3: // bls + if((h8.h8cflag | h8.h8zflag) == 1)taken = 1; + break; + case 4: // bcc C = 0 + if(h8.h8cflag == 0)taken = 1; + break; + case 5: // bcs C = 1 + if(h8.h8cflag == 1)taken = 1; + break; + case 6: // bne Z = 0 + if(h8.h8zflag == 0)taken = 1; + break; + case 7: // beq Z = 1 + if(h8.h8zflag == 1)taken = 1; + break; + case 8: // bvc V = 0 + h8.h8err = 1; + if(h8.h8vflag == 0)taken = 1; + break; + case 9: // bvs V = 1 + h8.h8err = 1; + if(h8.h8vflag == 1)taken = 1; + break; + case 0xa: // bpl N = 0 + if(h8.h8nflag == 0)taken = 1; + break; + case 0xb: // bmi N = 1 + if(h8.h8nflag == 1)taken = 1; + break; + case 0xc: // bge (N ^ V) = 0 + if((h8.h8nflag ^ h8.h8vflag) == 0)taken = 1; + break; + case 0xd: // blt (N ^ V) = 1 + if((h8.h8nflag ^ h8.h8vflag) == 1)taken = 1; + break; + case 0xe: // bgt (Z | (N ^ V)) = 0 + if((h8.h8zflag | (h8.h8nflag ^ h8.h8vflag)) == 0)taken = 1; + break; + case 0xf: // ble (Z | (N ^ V)) = 1 + if((h8.h8zflag | (h8.h8nflag ^ h8.h8vflag)) == 1)taken = 1; + break; + } + return taken; +} + +// MAME interface stuff + +static void h8_get_context(void *context) +{ + *(h83002_state *)context = h8; +} + +static void h8_set_context(void *context) +{ + h8 = *(h83002_state *)context; +} + +static void h8_set_info(UINT32 state, cpuinfo *info) +{ + switch(state) { + case CPUINFO_INT_PC: h8.pc = info->i; change_pc(h8.pc); break; + case CPUINFO_INT_REGISTER + H8_PC: h8.pc = info->i; change_pc(h8.pc); break; + case CPUINFO_INT_REGISTER + H8_CCR: h8_set_ccr(info->i); break; + + case CPUINFO_INT_REGISTER + H8_E0: h8.regs[0] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E1: h8.regs[1] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E2: h8.regs[2] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E3: h8.regs[3] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E4: h8.regs[4] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E5: h8.regs[5] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E6: h8.regs[6] = info->i; break; + case CPUINFO_INT_REGISTER + H8_E7: h8.regs[7] = info->i; break; + + case CPUINFO_INT_INPUT_STATE + H8_IRQ0: if (info->i) h8_3002_InterruptRequest(12); break; + case CPUINFO_INT_INPUT_STATE + H8_IRQ1: if (info->i) h8_3002_InterruptRequest(13); break; + case CPUINFO_INT_INPUT_STATE + H8_IRQ2: if (info->i) h8_3002_InterruptRequest(14); break; + case CPUINFO_INT_INPUT_STATE + H8_IRQ3: if (info->i) h8_3002_InterruptRequest(15); break; + case CPUINFO_INT_INPUT_STATE + H8_IRQ4: if (info->i) h8_3002_InterruptRequest(16); break; + case CPUINFO_INT_INPUT_STATE + H8_IRQ5: if (info->i) h8_3002_InterruptRequest(17); break; + + default: + fatalerror("h8_set_info unknown request %x", state); + break; + } +} + +static READ16_HANDLER( h8_itu_r ) +{ + if (mem_mask == 0) + { + // 16-bit read + return h8_register_read8(offset*2 + 0xffff10)<<8 | h8_register_read8((offset*2) + 1 + 0xffff10); + } + else if (mem_mask == 0xff) + { + return h8_register_read8(offset*2 + 0xffff10)<<8; + } + else if (mem_mask == 0xff00) + { + return h8_register_read8((offset*2) + 1 + 0xffff10); + } + + return 0; +} + +static WRITE16_HANDLER( h8_itu_w ) +{ + if (mem_mask == 0) + { + // 16-bit write + h8_register_write8(offset*2 + 0xffff10, data>>8); + h8_register_write8((offset*2) + 1 + 0xffff10, data&0xff); + } + else if (mem_mask == 0xff) + { + h8_register_write8(offset*2 + 0xffff10, data>>8); + } + else if (mem_mask == 0xff00) + { + h8_register_write8((offset*2) + 1 + 0xffff10, data&0xff); + } +} + +// On-board RAM and peripherals +static ADDRESS_MAP_START( h8_internal_map, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0xfffd10, 0xffff0f) AM_RAM + AM_RANGE(0xffff10, 0xffffff) AM_READWRITE( h8_itu_r, h8_itu_w ) +ADDRESS_MAP_END + +void h8_3002_get_info(UINT32 state, cpuinfo *info) +{ + switch(state) { + // Interface functions and variables + case CPUINFO_PTR_SET_INFO: info->setinfo = h8_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = h8_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext= h8_set_context; break; + case CPUINFO_PTR_INIT: info->init = h8_init; break; + case CPUINFO_PTR_RESET: info->reset = h8_reset; break; + case CPUINFO_PTR_EXIT: info->exit = 0; break; + case CPUINFO_PTR_EXECUTE: info->execute = h8_execute; break; + case CPUINFO_PTR_BURN: info->burn = 0; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = h8_disasm; break; +#endif /* MAME_DEBUG */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h8_cyccnt; break; + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h83002_state); break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break; + + // Bus sizes + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 24; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + // Internal maps + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_h8_internal_map; break; + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map = 0; break; + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map = 0; break; + + // CPU misc parameters + case CPUINFO_STR_NAME: strcpy(info->s, "H8/3002"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_FLAGS: strcpy(info->s, h8_get_ccr_str()); break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break; + case CPUINFO_INT_INPUT_LINES: info->i = 16; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break; + + // CPU main state + case CPUINFO_INT_PC: info->i = h8.pc; break; + case CPUINFO_INT_PREVIOUSPC: info->i = h8.ppc; break; + + case CPUINFO_INT_REGISTER + H8_PC: info->i = h8.pc; break; + case CPUINFO_INT_REGISTER + H8_CCR: info->i = h8_get_ccr(); break; + + case CPUINFO_INT_REGISTER + H8_E0: info->i = h8.regs[0]; break; + case CPUINFO_INT_REGISTER + H8_E1: info->i = h8.regs[1]; break; + case CPUINFO_INT_REGISTER + H8_E2: info->i = h8.regs[2]; break; + case CPUINFO_INT_REGISTER + H8_E3: info->i = h8.regs[3]; break; + case CPUINFO_INT_REGISTER + H8_E4: info->i = h8.regs[4]; break; + case CPUINFO_INT_REGISTER + H8_E5: info->i = h8.regs[5]; break; + case CPUINFO_INT_REGISTER + H8_E6: info->i = h8.regs[6]; break; + case CPUINFO_INT_REGISTER + H8_E7: info->i = h8.regs[7]; break; + + // CPU debug stuff + case CPUINFO_STR_REGISTER + H8_PC: sprintf(info->s, "PC :%08x", h8.pc); break; + case CPUINFO_STR_REGISTER + H8_CCR: sprintf(info->s, "CCR :%08x", h8_get_ccr()); break; + + case CPUINFO_STR_REGISTER + H8_E0: sprintf(info->s, "ER0 :%08x", h8.regs[0]); break; + case CPUINFO_STR_REGISTER + H8_E1: sprintf(info->s, "ER1 :%08x", h8.regs[1]); break; + case CPUINFO_STR_REGISTER + H8_E2: sprintf(info->s, "ER2 :%08x", h8.regs[2]); break; + case CPUINFO_STR_REGISTER + H8_E3: sprintf(info->s, "ER3 :%08x", h8.regs[3]); break; + case CPUINFO_STR_REGISTER + H8_E4: sprintf(info->s, "ER4 :%08x", h8.regs[4]); break; + case CPUINFO_STR_REGISTER + H8_E5: sprintf(info->s, "ER5 :%08x", h8.regs[5]); break; + case CPUINFO_STR_REGISTER + H8_E6: sprintf(info->s, "ER6 :%08x", h8.regs[6]); break; + case CPUINFO_STR_REGISTER + H8_E7: sprintf(info->s, " SP :%08x", h8.regs[7]); break; + } +} |