From e8cfb9e5133e9185b5c7c44ecf80d2d85b6a29ff Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Thu, 23 Dec 2010 02:46:39 +0000 Subject: [PATCH] Implemented a preliminary V25/V35 CPU core [Alex Jackson] --- .gitattributes | 8 +- src/emu/cpu/cpu.mak | 17 +- src/emu/cpu/nec/nec.c | 908 +++--------------------------------- src/emu/cpu/nec/nec.h | 58 +-- src/emu/cpu/nec/necea.h | 46 +- src/emu/cpu/nec/necinstr.c | 672 ++++++++++++++++++++++++++ src/emu/cpu/nec/necinstr.h | 3 +- src/emu/cpu/nec/necmodrm.h | 24 +- src/emu/cpu/nec/necpriv.h | 172 ++++--- src/emu/cpu/nec/v25.c | 622 ++++++++++++++++++++++++ src/emu/cpu/nec/v25instr.c | 34 ++ src/emu/cpu/nec/v25instr.h | 510 ++++++++++++++++++++ src/emu/cpu/nec/v25priv.h | 455 ++++++++++++++++++ src/emu/cpu/nec/v25sfr.c | 137 ++++++ src/mame/drivers/cb2001.c | 2 +- src/mame/drivers/m107.c | 2 +- src/mame/drivers/m72.c | 2 +- src/mame/drivers/m90.c | 46 +- src/mame/drivers/m92.c | 34 +- src/mame/drivers/segas32.c | 13 +- src/mame/includes/segas32.h | 1 + src/mame/machine/segas32.c | 27 +- 22 files changed, 2722 insertions(+), 1071 deletions(-) create mode 100644 src/emu/cpu/nec/necinstr.c create mode 100644 src/emu/cpu/nec/v25.c create mode 100644 src/emu/cpu/nec/v25instr.c create mode 100644 src/emu/cpu/nec/v25instr.h create mode 100644 src/emu/cpu/nec/v25priv.h create mode 100644 src/emu/cpu/nec/v25sfr.c diff --git a/.gitattributes b/.gitattributes index 6ccd6325e79..0ca98b62ccc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -319,13 +319,19 @@ src/emu/cpu/mn10200/mn10200.c svneol=native#text/plain src/emu/cpu/mn10200/mn10200.h svneol=native#text/plain src/emu/cpu/mn10200/mn102dis.c svneol=native#text/plain src/emu/cpu/nec/nec.c svneol=native#text/plain -src/emu/cpu/nec/nec.h -text svneol=native#text/plain +src/emu/cpu/nec/nec.h svneol=native#text/plain src/emu/cpu/nec/necdasm.c svneol=native#text/plain src/emu/cpu/nec/necea.h svneol=native#text/plain src/emu/cpu/nec/nechost.h svneol=native#text/plain +src/emu/cpu/nec/necinstr.c svneol=native#text/plain src/emu/cpu/nec/necinstr.h svneol=native#text/plain src/emu/cpu/nec/necmodrm.h svneol=native#text/plain src/emu/cpu/nec/necpriv.h svneol=native#text/plain +src/emu/cpu/nec/v25.c svneol=native#text/plain +src/emu/cpu/nec/v25instr.c svneol=native#text/plain +src/emu/cpu/nec/v25instr.h svneol=native#text/plain +src/emu/cpu/nec/v25priv.h svneol=native#text/plain +src/emu/cpu/nec/v25sfr.c svneol=native#text/plain src/emu/cpu/pdp1/pdp1.c svneol=native#text/plain src/emu/cpu/pdp1/pdp1.h svneol=native#text/plain src/emu/cpu/pdp1/pdp1dasm.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index ef0d4e67133..a17c77b990a 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -1147,6 +1147,8 @@ $(CPUOBJ)/powerpc/ppcdrc.o: $(CPUSRC)/powerpc/ppcdrc.c \ ifneq ($(filter NEC,$(CPUS)),) OBJDIRS += $(CPUOBJ)/nec CPUOBJS += $(CPUOBJ)/nec/nec.o +CPUOBJS += $(CPUOBJ)/nec/v25.o +CPUOBJS += $(CPUOBJ)/nec/v25sfr.o DASMOBJS += $(CPUOBJ)/nec/necdasm.o endif @@ -1159,11 +1161,24 @@ endif $(CPUOBJ)/nec/nec.o: $(CPUSRC)/nec/nec.c \ $(CPUSRC)/nec/nec.h \ $(CPUSRC)/nec/necea.h \ - $(CPUSRC)/nec/nechost.h \ + $(CPUSRC)/nec/necinstr.c \ $(CPUSRC)/nec/necinstr.h \ $(CPUSRC)/nec/necmodrm.h \ $(CPUSRC)/nec/necpriv.h +$(CPUOBJ)/nec/v25.o: $(CPUSRC)/nec/v25.c \ + $(CPUSRC)/nec/nec.h \ + $(CPUSRC)/nec/necea.h \ + $(CPUSRC)/nec/necinstr.c \ + $(CPUSRC)/nec/v25instr.c \ + $(CPUSRC)/nec/v25instr.h \ + $(CPUSRC)/nec/necmodrm.h \ + $(CPUSRC)/nec/v25priv.h + +$(CPUOBJ)/nec/v25sfr.o: $(CPUSRC)/nec/v25sfr.c \ + $(CPUSRC)/nec/nec.h \ + $(CPUSRC)/nec/v25priv.h + $(CPUOBJ)/v30mz/v30mz.o: $(CPUSRC)/v30mz/v30mz.c \ $(CPUSRC)/v30mz/v30mz.h \ $(CPUSRC)/v30mz/necmodrm.h \ diff --git a/src/emu/cpu/nec/nec.c b/src/emu/cpu/nec/nec.c index 15590d9ed03..3b69dc72de8 100644 --- a/src/emu/cpu/nec/nec.c +++ b/src/emu/cpu/nec/nec.c @@ -111,73 +111,19 @@ typedef UINT8 BYTE; typedef UINT16 WORD; typedef UINT32 DWORD; -#include "necpriv.h" #include "nec.h" +#include "necpriv.h" -#define PC(n) (((n)->sregs[PS]<<4)+(n)->ip) - -/* default configuration */ -static const nec_config default_config = -{ - NULL -}; +#define PC(n) ((Sreg(PS)<<4)+(n)->ip) extern int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *config); -/* NEC registers */ -typedef union -{ /* eight general registers */ - UINT16 w[8]; /* viewed as 16 bits registers */ - UINT8 b[16]; /* or as 8 bit registers */ -} necbasicregs; - -typedef struct _nec_state_t nec_state_t; -struct _nec_state_t -{ - necbasicregs regs; - offs_t fetch_xor; - UINT16 sregs[4]; - - UINT16 ip; - - INT32 SignVal; - UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ - UINT8 TF, IF, DF, MF; /* 0 or 1 valued flags */ /* OB[19.07.99] added Mode Flag V30 */ - UINT32 int_vector; - UINT32 pending_irq; - UINT32 nmi_state; - UINT32 irq_state; - UINT32 poll_state; - UINT8 no_interrupt; - - device_irq_callback irq_callback; - legacy_cpu_device *device; - address_space *program; - direct_read_data *direct; - address_space *io; - int icount; - - const nec_config *config; - - UINT8 prefetch_size; - UINT8 prefetch_cycles; - INT8 prefetch_count; - UINT8 prefetch_reset; - UINT32 chip_type; - - UINT32 prefix_base; /* base address of the latest prefix segment */ - UINT8 seg_prefix; /* prefix segment indicator */ - -}; - INLINE nec_state_t *get_safe_token(running_device *device) { assert(device != NULL); assert(device->type() == V20 || - device->type() == V25 || device->type() == V30 || - device->type() == V33 || - device->type() == V35); + device->type() == V33); return (nec_state_t *)downcast(device)->token(); } @@ -199,7 +145,7 @@ static void do_prefetch(nec_state_t *nec_state, int previous_ICount) /* The implementation is not accurate, but comes close. * It does not respect that the V30 will fetch two bytes * at once directly, but instead uses only 2 cycles instead - * of 4. There are however only very few sources publicy + * of 4. There are however only very few sources publicly * available and they are vague. */ while (nec_state->prefetch_count<0) @@ -229,7 +175,7 @@ static void do_prefetch(nec_state_t *nec_state, int previous_ICount) INLINE UINT8 fetch(nec_state_t *nec_state) { prefetch(nec_state); - return nec_state->direct->read_raw_byte(FETCH_XOR((nec_state->sregs[PS]<<4)+nec_state->ip++)); + return nec_state->direct->read_raw_byte(FETCH_XOR((Sreg(PS)<<4)+nec_state->ip++)); } INLINE UINT16 fetchword(nec_state_t *nec_state) @@ -245,21 +191,10 @@ INLINE UINT16 fetchword(nec_state_t *nec_state) static UINT8 parity_table[256]; -#include "emu.h" - static UINT8 fetchop(nec_state_t *nec_state) { - UINT8 ret; - prefetch(nec_state); - ret = nec_state->direct->read_decrypted_byte(FETCH_XOR( ( nec_state->sregs[PS]<<4)+nec_state->ip++)); - - if (nec_state->MF == 1) - if (nec_state->config->v25v35_decryptiontable) - { - ret = nec_state->config->v25v35_decryptiontable[ret]; - } - return ret; + return nec_state->direct->read_decrypted_byte(FETCH_XOR( ( Sreg(PS)<<4)+nec_state->ip++)); } @@ -279,7 +214,7 @@ static CPU_RESET( nec ) nec_state->TF = 0; nec_state->IF = 0; nec_state->DF = 0; - nec_state->MF = 0; + nec_state->MF = 1; nec_state->SignVal = 0; nec_state->int_vector = 0; nec_state->pending_irq = 0; @@ -293,7 +228,7 @@ static CPU_RESET( nec ) nec_state->ParityVal = 0; - nec_state->sregs[PS] = 0xffff; + Sreg(PS) = 0xffff; CHANGE_PC; @@ -305,10 +240,6 @@ static CPU_RESET( nec ) } nec_state->ZeroVal = nec_state->ParityVal = 1; - SetMD(1); /* set the mode-flag = native mode */ - - /* for v25+ / v35+ there is an internal decryption table */ - //nec_state->config->v25v35_decryptiontable = gussun_test_decryption_table; for (i = 0; i < 256; i++) { @@ -330,13 +261,12 @@ static CPU_EXIT( nec ) } -static void nec_interrupt(nec_state_t *nec_state, unsigned int_num,BOOLEAN md_flag) +static void nec_interrupt(nec_state_t *nec_state, unsigned int_num, ATTR_UNUSED unsigned mode) { UINT32 dest_seg, dest_off; i_pushf(nec_state); nec_state->TF = nec_state->IF = 0; - if (md_flag) SetMD(0); /* clear Mode-flag = start 8080 emulation mode */ if (int_num == -1) { @@ -349,10 +279,10 @@ static void nec_interrupt(nec_state_t *nec_state, unsigned int_num,BOOLEAN md_fl dest_off = read_mem_word(int_num*4); dest_seg = read_mem_word(int_num*4+2); - PUSH(nec_state->sregs[PS]); + PUSH(Sreg(PS)); PUSH(nec_state->ip); nec_state->ip = (WORD)dest_off; - nec_state->sregs[PS] = (WORD)dest_seg; + Sreg(PS) = (WORD)dest_seg; CHANGE_PC; } @@ -381,671 +311,7 @@ static void external_int(nec_state_t *nec_state) /* OPCODES */ /****************************************************************************/ -#define OP(num,func_name) static void func_name(nec_state_t *nec_state) - -OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x06, i_push_es ) { PUSH(nec_state->sregs[DS1]); CLKS(12,8,3); } -OP( 0x07, i_pop_es ) { POP(nec_state->sregs[DS1]); CLKS(12,8,5); } - -OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x0e, i_push_cs ) { PUSH(nec_state->sregs[PS]); CLKS(12,8,3); } -OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2; - switch (FETCH()) { - case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = nec_state->regs.b[CL] & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ - case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = nec_state->regs.b[CL] & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ - case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = nec_state->regs.b[CL] & 0x7; tmp &= ~(1<regs.b[CL] & 0xf; tmp &= ~(1<regs.b[CL] & 0x7; tmp |= (1<regs.b[CL] & 0xf; tmp |= (1<regs.b[CL] & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */ - case 0x17 : BITOP_WORD; CLKS(4,4,4); tmp2 = nec_state->regs.b[CL] & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */ - - case 0x18 : BITOP_BYTE; CLKS(4,4,4); tmp2 = (FETCH()) & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ - case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ - case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<regs.b[AL] & 0xf; nec_state->regs.b[AL] = (nec_state->regs.b[AL] & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; - case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (nec_state->regs.b[AL] & 0xf)<<4; nec_state->regs.b[AL] = (nec_state->regs.b[AL] & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; - case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(nec_state)); break; - case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(nec_state)); break; - case 0x92 : CLK(2); break; /* V25/35 FINT */ - case 0xe0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC(nec_state)); break; - case 0xf0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC(nec_state)); break; - case 0xff : ModRM = FETCH(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC(nec_state)); break; - default: logerror("%06x: Unknown V20 instruction\n",PC(nec_state)); break; - } -} - -OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x16, i_push_ss ) { PUSH(nec_state->sregs[SS]); CLKS(12,8,3); } -OP( 0x17, i_pop_ss ) { POP(nec_state->sregs[SS]); CLKS(12,8,5); nec_state->no_interrupt=1; } - -OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x1e, i_push_ds ) { PUSH(nec_state->sregs[DS0]); CLKS(12,8,3); } -OP( 0x1f, i_pop_ds ) { POP(nec_state->sregs[DS0]); CLKS(12,8,5); } - -OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x26, i_es ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS1]<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } -OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); } - -OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x2e, i_cs ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[PS]<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } -OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); } - -OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } -OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} -OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } -OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; nec_state->regs.b[AL]=dst; CLKS(4,4,2); } -OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; nec_state->regs.w[AW]=dst; CLKS(4,4,2); } -OP( 0x36, i_ss ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[SS]<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } -OP( 0x37, i_aaa ) { ADJB(6, (nec_state->regs.b[AL] > 0xf9) ? 2 : 1); CLKS(7,7,4); } - -OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); } -OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,EA);} -OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); } -OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,EA); } -OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); } -OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); } -OP( 0x3e, i_ds ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS0]<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } -OP( 0x3f, i_aas ) { ADJB(-6, (nec_state->regs.b[AL] < 6) ? -2 : -1); CLKS(7,7,4); } - -OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); } -OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); } -OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); } -OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); } -OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); } -OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); } -OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); } -OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); } - -OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); } -OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); } -OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); } -OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); } -OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); } -OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); } -OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); } -OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); } - -OP( 0x50, i_push_ax ) { PUSH(nec_state->regs.w[AW]); CLKS(12,8,3); } -OP( 0x51, i_push_cx ) { PUSH(nec_state->regs.w[CW]); CLKS(12,8,3); } -OP( 0x52, i_push_dx ) { PUSH(nec_state->regs.w[DW]); CLKS(12,8,3); } -OP( 0x53, i_push_bx ) { PUSH(nec_state->regs.w[BW]); CLKS(12,8,3); } -OP( 0x54, i_push_sp ) { PUSH(nec_state->regs.w[SP]); CLKS(12,8,3); } -OP( 0x55, i_push_bp ) { PUSH(nec_state->regs.w[BP]); CLKS(12,8,3); } -OP( 0x56, i_push_si ) { PUSH(nec_state->regs.w[IX]); CLKS(12,8,3); } -OP( 0x57, i_push_di ) { PUSH(nec_state->regs.w[IY]); CLKS(12,8,3); } - -OP( 0x58, i_pop_ax ) { POP(nec_state->regs.w[AW]); CLKS(12,8,5); } -OP( 0x59, i_pop_cx ) { POP(nec_state->regs.w[CW]); CLKS(12,8,5); } -OP( 0x5a, i_pop_dx ) { POP(nec_state->regs.w[DW]); CLKS(12,8,5); } -OP( 0x5b, i_pop_bx ) { POP(nec_state->regs.w[BW]); CLKS(12,8,5); } -OP( 0x5c, i_pop_sp ) { POP(nec_state->regs.w[SP]); CLKS(12,8,5); } -OP( 0x5d, i_pop_bp ) { POP(nec_state->regs.w[BP]); CLKS(12,8,5); } -OP( 0x5e, i_pop_si ) { POP(nec_state->regs.w[IX]); CLKS(12,8,5); } -OP( 0x5f, i_pop_di ) { POP(nec_state->regs.w[IY]); CLKS(12,8,5); } - -OP( 0x60, i_pusha ) { - unsigned tmp=nec_state->regs.w[SP]; - PUSH(nec_state->regs.w[AW]); - PUSH(nec_state->regs.w[CW]); - PUSH(nec_state->regs.w[DW]); - PUSH(nec_state->regs.w[BW]); - PUSH(tmp); - PUSH(nec_state->regs.w[BP]); - PUSH(nec_state->regs.w[IX]); - PUSH(nec_state->regs.w[IY]); - CLKS(67,35,20); -} -OP( 0x61, i_popa ) { - unsigned tmp; - POP(nec_state->regs.w[IY]); - POP(nec_state->regs.w[IX]); - POP(nec_state->regs.w[BP]); - POP(tmp); - POP(nec_state->regs.w[BW]); - POP(nec_state->regs.w[DW]); - POP(nec_state->regs.w[CW]); - POP(nec_state->regs.w[AW]); - CLKS(75,43,22); -} -OP( 0x62, i_chkind ) { - UINT32 low,high,tmp; - GetModRM; - low = GetRMWord(ModRM); - high= GetnextRMWord; - tmp= RegWord(ModRM); - if (tmphigh) { - nec_interrupt(nec_state, 5,0); - } - nec_state->icount-=20; - logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(nec_state),high,low,tmp); -} -OP( 0x63, i_brkn ) { nec_interrupt(nec_state, FETCH(),1); CLKS(50,50,24); } // timing not verified, used by riskchal / gussun -OP( 0x64, i_repnc ) { UINT32 next = fetchop(nec_state); UINT16 c = nec_state->regs.w[CW]; - switch(next) { /* Segments */ - case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS1]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[PS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[SS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS0]<<4; next = fetchop(nec_state); CLK(2); break; - } - - switch(next) { - case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && !CF); nec_state->regs.w[CW]=c; break; - default: logerror("%06x: REPNC invalid\n",PC(nec_state)); nec_instruction[next](nec_state); - } - nec_state->seg_prefix=FALSE; -} - -OP( 0x65, i_repc ) { UINT32 next = fetchop(nec_state); UINT16 c = nec_state->regs.w[CW]; - switch(next) { /* Segments */ - case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS1]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[PS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[SS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS0]<<4; next = fetchop(nec_state); CLK(2); break; - } - - switch(next) { - case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && CF); nec_state->regs.w[CW]=c; break; - default: logerror("%06x: REPC invalid\n",PC(nec_state)); nec_instruction[next](nec_state); - } - nec_state->seg_prefix=FALSE; -} - -OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,nec_state->regs.w[SP]); } -OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?38:47;} -OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,nec_state->regs.w[SP]); } -OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?31:39; } -OP( 0x6c, i_insb ) { PutMemB(DS1,nec_state->regs.w[IY],read_port_byte(nec_state->regs.w[DW])); nec_state->regs.w[IY]+= -2 * nec_state->DF + 1; CLK(8); } -OP( 0x6d, i_insw ) { PutMemW(DS1,nec_state->regs.w[IY],read_port_word(nec_state->regs.w[DW])); nec_state->regs.w[IY]+= -4 * nec_state->DF + 2; CLKS(18,10,8); } -OP( 0x6e, i_outsb ) { write_port_byte(nec_state->regs.w[DW],GetMemB(DS0,nec_state->regs.w[IX])); nec_state->regs.w[IX]+= -2 * nec_state->DF + 1; CLK(8); } -OP( 0x6f, i_outsw ) { write_port_word(nec_state->regs.w[DW],GetMemW(DS0,nec_state->regs.w[IX])); nec_state->regs.w[IX]+= -4 * nec_state->DF + 2; CLKS(18,10,8); } - -OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); } -OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); } -OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); } -OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); } -OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); } -OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); } -OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); } -OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); } -OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); } -OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); } -OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); } -OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); } -OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); } -OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); } -OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); } -OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); } - -OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH(); - if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) - switch (ModRM & 0x38) { - case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; - case 0x08: ORB; PutbackRMByte(ModRM,dst); break; - case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; - case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; - case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; - case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; - case 0x30: XORB; PutbackRMByte(ModRM,dst); break; - case 0x38: SUBB; break; /* CMP */ - } -} - -OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8); - if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) - switch (ModRM & 0x38) { - case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; - case 0x08: ORW; PutbackRMWord(ModRM,dst); break; - case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; - case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; - case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; - case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; - case 0x30: XORW; PutbackRMWord(ModRM,dst); break; - case 0x38: SUBW; break; /* CMP */ - } -} - -OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH()); - if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) - switch (ModRM & 0x38) { - case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; - case 0x08: ORB; PutbackRMByte(ModRM,dst); break; - case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; - case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; - case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; - case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; - case 0x30: XORB; PutbackRMByte(ModRM,dst); break; - case 0x38: SUBB; break; /* CMP */ - } -} - -OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH())); - if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) - switch (ModRM & 0x38) { - case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; - case 0x08: ORW; PutbackRMWord(ModRM,dst); break; - case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; - case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; - case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; - case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; - case 0x30: XORW; PutbackRMWord(ModRM,dst); break; - case 0x38: SUBW; break; /* CMP */ - } -} - -OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); } -OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,EA); } -OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); } -OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,EA); } - -OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); } -OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,EA); } -OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); } -OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,EA); } -OP( 0x8c, i_mov_wsreg ) { GetModRM; PutRMWord(ModRM,nec_state->sregs[(ModRM & 0x38) >> 3]); CLKR(14,14,5,14,10,3,2,EA); } -OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(*GetEA[ModRM])(nec_state); RegWord(ModRM)=EO; CLKS(4,4,2); } -OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,EA); - switch (ModRM & 0x38) { - case 0x00: nec_state->sregs[DS1] = src; break; /* mov es,ew */ - case 0x08: nec_state->sregs[PS] = src; break; /* mov cs,ew */ - case 0x10: nec_state->sregs[SS] = src; break; /* mov ss,ew */ - case 0x18: nec_state->sregs[DS0] = src; break; /* mov ds,ew */ - default: logerror("%06x: Mov Sreg - Invalid register\n",PC(nec_state)); - } - nec_state->no_interrupt=1; -} -OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); nec_state->icount-=21; } -OP( 0x90, i_nop ) { CLK(3); } -OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } -OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } -OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } -OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } -OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } -OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } -OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } - -OP( 0x98, i_cbw ) { nec_state->regs.b[AH] = (nec_state->regs.b[AL] & 0x80) ? 0xff : 0; CLK(2); } -OP( 0x99, i_cwd ) { nec_state->regs.w[DW] = (nec_state->regs.b[AH] & 0x80) ? 0xffff : 0; CLK(4); } -OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(nec_state->sregs[PS]); PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; nec_state->sregs[PS] = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,nec_state->regs.w[SP]); } -OP( 0x9b, i_wait ) { if (!nec_state->poll_state) nec_state->ip--; CLK(5); } -OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); } -OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (nec_state->TF) nec_trap(nec_state); } -OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (nec_state->regs.b[AH] & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); } -OP( 0x9f, i_lahf ) { nec_state->regs.b[AH] = CompressFlags() & 0xff; CLKS(3,3,2); } - -OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); nec_state->regs.b[AL] = GetMemB(DS0, addr); CLKS(10,10,5); } -OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); nec_state->regs.w[AW] = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); } -OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, nec_state->regs.b[AL]); CLKS(9,9,3); } -OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, nec_state->regs.w[AW]); CLKW(13,13,5,13,9,3,addr); } -OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,nec_state->regs.w[IX]); PutMemB(DS1,nec_state->regs.w[IY], tmp); nec_state->regs.w[IY] += -2 * nec_state->DF + 1; nec_state->regs.w[IX] += -2 * nec_state->DF + 1; CLKS(8,8,6); } -OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,nec_state->regs.w[IX]); PutMemW(DS1,nec_state->regs.w[IY], tmp); nec_state->regs.w[IY] += -4 * nec_state->DF + 2; nec_state->regs.w[IX] += -4 * nec_state->DF + 2; CLKS(16,16,10); } -OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, nec_state->regs.w[IY]); UINT32 dst = GetMemB(DS0, nec_state->regs.w[IX]); SUBB; nec_state->regs.w[IY] += -2 * nec_state->DF + 1; nec_state->regs.w[IX] += -2 * nec_state->DF + 1; CLKS(14,14,14); } -OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, nec_state->regs.w[IY]); UINT32 dst = GetMemW(DS0, nec_state->regs.w[IX]); SUBW; nec_state->regs.w[IY] += -4 * nec_state->DF + 2; nec_state->regs.w[IX] += -4 * nec_state->DF + 2; CLKS(14,14,14); } - -OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); } -OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); } -OP( 0xaa, i_stosb ) { PutMemB(DS1,nec_state->regs.w[IY],nec_state->regs.b[AL]); nec_state->regs.w[IY] += -2 * nec_state->DF + 1; CLKS(4,4,3); } -OP( 0xab, i_stosw ) { PutMemW(DS1,nec_state->regs.w[IY],nec_state->regs.w[AW]); nec_state->regs.w[IY] += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,nec_state->regs.w[IY]); } -OP( 0xac, i_lodsb ) { nec_state->regs.b[AL] = GetMemB(DS0,nec_state->regs.w[IX]); nec_state->regs.w[IX] += -2 * nec_state->DF + 1; CLKS(4,4,3); } -OP( 0xad, i_lodsw ) { nec_state->regs.w[AW] = GetMemW(DS0,nec_state->regs.w[IX]); nec_state->regs.w[IX] += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,nec_state->regs.w[IX]); } -OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, nec_state->regs.w[IY]); UINT32 dst = nec_state->regs.b[AL]; SUBB; nec_state->regs.w[IY] += -2 * nec_state->DF + 1; CLKS(4,4,3); } -OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, nec_state->regs.w[IY]); UINT32 dst = nec_state->regs.w[AW]; SUBW; nec_state->regs.w[IY] += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,nec_state->regs.w[IY]); } - -OP( 0xb0, i_mov_ald8 ) { nec_state->regs.b[AL] = FETCH(); CLKS(4,4,2); } -OP( 0xb1, i_mov_cld8 ) { nec_state->regs.b[CL] = FETCH(); CLKS(4,4,2); } -OP( 0xb2, i_mov_dld8 ) { nec_state->regs.b[DL] = FETCH(); CLKS(4,4,2); } -OP( 0xb3, i_mov_bld8 ) { nec_state->regs.b[BL] = FETCH(); CLKS(4,4,2); } -OP( 0xb4, i_mov_ahd8 ) { nec_state->regs.b[AH] = FETCH(); CLKS(4,4,2); } -OP( 0xb5, i_mov_chd8 ) { nec_state->regs.b[CH] = FETCH(); CLKS(4,4,2); } -OP( 0xb6, i_mov_dhd8 ) { nec_state->regs.b[DH] = FETCH(); CLKS(4,4,2); } -OP( 0xb7, i_mov_bhd8 ) { nec_state->regs.b[BH] = FETCH(); CLKS(4,4,2); } - -OP( 0xb8, i_mov_axd16 ) { nec_state->regs.b[AL] = FETCH(); nec_state->regs.b[AH] = FETCH(); CLKS(4,4,2); } -OP( 0xb9, i_mov_cxd16 ) { nec_state->regs.b[CL] = FETCH(); nec_state->regs.b[CH] = FETCH(); CLKS(4,4,2); } -OP( 0xba, i_mov_dxd16 ) { nec_state->regs.b[DL] = FETCH(); nec_state->regs.b[DH] = FETCH(); CLKS(4,4,2); } -OP( 0xbb, i_mov_bxd16 ) { nec_state->regs.b[BL] = FETCH(); nec_state->regs.b[BH] = FETCH(); CLKS(4,4,2); } -OP( 0xbc, i_mov_spd16 ) { nec_state->regs.b[SPL] = FETCH(); nec_state->regs.b[SPH] = FETCH(); CLKS(4,4,2); } -OP( 0xbd, i_mov_bpd16 ) { nec_state->regs.b[BPL] = FETCH(); nec_state->regs.b[BPH] = FETCH(); CLKS(4,4,2); } -OP( 0xbe, i_mov_sid16 ) { nec_state->regs.b[IXL] = FETCH(); nec_state->regs.b[IXH] = FETCH(); CLKS(4,4,2); } -OP( 0xbf, i_mov_did16 ) { nec_state->regs.b[IYL] = FETCH(); nec_state->regs.b[IYH] = FETCH(); CLKS(4,4,2); } - -OP( 0xc0, i_rotshft_bd8 ) { - UINT32 src, dst; UINT8 c; - GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; - c=FETCH(); - CLKM(7,7,2,19,19,6); - if (c) switch (ModRM & 0x38) { - case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_BYTE(c); break; - } -} - -OP( 0xc1, i_rotshft_wd8 ) { - UINT32 src, dst; UINT8 c; - GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; - c=FETCH(); - CLKM(7,7,2,27,19,6); - if (c) switch (ModRM & 0x38) { - case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_WORD(c); break; - } -} - -OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); nec_state->regs.w[SP]+=count; CHANGE_PC; CLKS(24,24,10); } -OP( 0xc3, i_ret ) { POP(nec_state->ip); CHANGE_PC; CLKS(19,19,10); } -OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; nec_state->sregs[DS1] = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } -OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; nec_state->sregs[DS0] = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } -OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:11; } -OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:15; } - -OP( 0xc8, i_enter ) { - UINT32 nb = FETCH(); - UINT32 i,level; - - nec_state->icount-=23; - nb += FETCH() << 8; - level = FETCH(); - PUSH(nec_state->regs.w[BP]); - nec_state->regs.w[BP]=nec_state->regs.w[SP]; - nec_state->regs.w[SP] -= nb; - for (i=1;iregs.w[BP]-i*2)); - nec_state->icount-=16; - } - if (level) PUSH(nec_state->regs.w[BP]); -} -OP( 0xc9, i_leave ) { - nec_state->regs.w[SP]=nec_state->regs.w[BP]; - POP(nec_state->regs.w[BP]); - nec_state->icount-=8; -} -OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); POP(nec_state->sregs[PS]); nec_state->regs.w[SP]+=count; CHANGE_PC; CLKS(32,32,16); } -OP( 0xcb, i_retf ) { POP(nec_state->ip); POP(nec_state->sregs[PS]); CHANGE_PC; CLKS(29,29,16); } -OP( 0xcc, i_int3 ) { nec_interrupt(nec_state, 3,0); CLKS(50,50,24); } -OP( 0xcd, i_int ) { nec_interrupt(nec_state, FETCH(),0); CLKS(50,50,24); } -OP( 0xce, i_into ) { if (OF) { nec_interrupt(nec_state, 4,0); CLKS(52,52,26); } else CLK(3); } -OP( 0xcf, i_iret ) { POP(nec_state->ip); POP(nec_state->sregs[PS]); i_popf(nec_state); SetMD(1); CHANGE_PC; CLKS(39,39,19); } - -OP( 0xd0, i_rotshft_b ) { - UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; - CLKM(6,6,2,16,16,7); - switch (ModRM & 0x38) { - case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; - case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; - case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; - case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; - case 0x20: SHL_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; - case 0x28: SHR_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; - case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_BYTE(1); nec_state->OverVal = 0; break; - } -} - -OP( 0xd1, i_rotshft_w ) { - UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; - CLKM(6,6,2,24,16,7); - switch (ModRM & 0x38) { - case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x20: SHL_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x28: SHR_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; - case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_WORD(1); nec_state->OverVal = 0; break; - } -} - -OP( 0xd2, i_rotshft_bcl ) { - UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; - c=nec_state->regs.b[CL]; - CLKM(7,7,2,19,19,6); - if (c) switch (ModRM & 0x38) { - case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_BYTE(c); break; - } -} - -OP( 0xd3, i_rotshft_wcl ) { - UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; - c=nec_state->regs.b[CL]; - CLKM(7,7,2,27,19,6); - if (c) switch (ModRM & 0x38) { - case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC(nec_state)); break; - case 0x38: SHRA_WORD(c); break; - } -} - -OP( 0xd4, i_aam ) { UINT32 mult=FETCH(); mult=0; nec_state->regs.b[AH] = nec_state->regs.b[AL] / 10; nec_state->regs.b[AL] %= 10; SetSZPF_Word(nec_state->regs.w[AW]); CLKS(15,15,12); } -OP( 0xd5, i_aad ) { UINT32 mult=FETCH(); mult=0; nec_state->regs.b[AL] = nec_state->regs.b[AH] * 10 + nec_state->regs.b[AL]; nec_state->regs.b[AH] = 0; SetSZPF_Byte(nec_state->regs.b[AL]); CLKS(7,7,8); } -OP( 0xd6, i_setalc ) { nec_state->regs.b[AL] = (CF)?0xff:0x00; nec_state->icount-=3; logerror("%06x: Undefined opcode (SETALC)\n",PC(nec_state)); } -OP( 0xd7, i_trans ) { UINT32 dest = (nec_state->regs.w[BW]+nec_state->regs.b[AL])&0xffff; nec_state->regs.b[AL] = GetMemB(DS0, dest); CLKS(9,9,5); } -OP( 0xd8, i_fpo ) { GetModRM; nec_state->icount-=2; logerror("%06x: Unimplemented floating point control %04x\n",PC(nec_state),ModRM); } - -OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); nec_state->regs.w[CW]--; if (!ZF && nec_state->regs.w[CW]) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } -OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); nec_state->regs.w[CW]--; if ( ZF && nec_state->regs.w[CW]) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } -OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); nec_state->regs.w[CW]--; if (nec_state->regs.w[CW]) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } -OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (nec_state->regs.w[CW] == 0) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } -OP( 0xe4, i_inal ) { UINT8 port = FETCH(); nec_state->regs.b[AL] = read_port_byte(port); CLKS(9,9,5); } -OP( 0xe5, i_inax ) { UINT8 port = FETCH(); nec_state->regs.w[AW] = read_port_word(port); CLKW(13,13,7,13,9,5,port); } -OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, nec_state->regs.b[AL]); CLKS(8,8,3); } -OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, nec_state->regs.w[AW]); CLKW(12,12,5,12,8,3,port); } - -OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(nec_state->ip); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=24; } -OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=15; } -OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); nec_state->sregs[PS] = (WORD)tmp1; nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=27; } -OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); nec_state->icount-=12; nec_state->ip = (WORD)(nec_state->ip+tmp); } -OP( 0xec, i_inaldx ) { nec_state->regs.b[AL] = read_port_byte(nec_state->regs.w[DW]); CLKS(8,8,5);} -OP( 0xed, i_inaxdx ) { nec_state->regs.w[AW] = read_port_word(nec_state->regs.w[DW]); CLKW(12,12,7,12,8,5,nec_state->regs.w[DW]); } -OP( 0xee, i_outdxal ) { write_port_byte(nec_state->regs.w[DW], nec_state->regs.b[AL]); CLKS(8,8,3); } -OP( 0xef, i_outdxax ) { write_port_word(nec_state->regs.w[DW], nec_state->regs.w[AW]); CLKW(12,12,5,12,8,3,nec_state->regs.w[DW]); } - -OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC(nec_state)); nec_state->no_interrupt=1; CLK(2); } -OP( 0xf2, i_repne ) { UINT32 next = fetchop(nec_state); UINT16 c = nec_state->regs.w[CW]; - switch(next) { /* Segments */ - case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS1]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[PS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[SS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS0]<<4; next = fetchop(nec_state); CLK(2); break; - } - - switch(next) { - case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==0); nec_state->regs.w[CW]=c; break; - case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==0); nec_state->regs.w[CW]=c; break; - case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==0); nec_state->regs.w[CW]=c; break; - case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==0); nec_state->regs.w[CW]=c; break; - default: logerror("%06x: REPNE invalid\n",PC(nec_state)); nec_instruction[next](nec_state); - } - nec_state->seg_prefix=FALSE; -} -OP( 0xf3, i_repe ) { UINT32 next = fetchop(nec_state); UINT16 c = nec_state->regs.w[CW]; - switch(next) { /* Segments */ - case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS1]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[PS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[SS]<<4; next = fetchop(nec_state); CLK(2); break; - case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=nec_state->sregs[DS0]<<4; next = fetchop(nec_state); CLK(2); break; - } - - switch(next) { - case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==1); nec_state->regs.w[CW]=c; break; - case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==1); nec_state->regs.w[CW]=c; break; - case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); nec_state->regs.w[CW]=c; break; - case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==1); nec_state->regs.w[CW]=c; break; - case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==1); nec_state->regs.w[CW]=c; break; - default: logerror("%06x: REPE invalid\n",PC(nec_state)); nec_instruction[next](nec_state); - } - nec_state->seg_prefix=FALSE; -} -OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC(nec_state)); nec_state->icount=0; } -OP( 0xf5, i_cmc ) { nec_state->CarryVal = !CF; CLK(2); } -OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; - GetModRM; tmp = GetRMByte(ModRM); - switch (ModRM & 0x38) { - case 0x00: tmp &= FETCH(); nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Byte(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ - case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC(nec_state)); break; - case 0x10: PutbackRMByte(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ - case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ - case 0x20: uresult = nec_state->regs.b[AL]*tmp; nec_state->regs.w[AW]=(WORD)uresult; nec_state->CarryVal=nec_state->OverVal=(nec_state->regs.b[AH]!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ - case 0x28: result = (INT16)((INT8)nec_state->regs.b[AL])*(INT16)((INT8)tmp); nec_state->regs.w[AW]=(WORD)result; nec_state->CarryVal=nec_state->OverVal=(nec_state->regs.b[AH]!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ - case 0x30: if (tmp) { DIVUB; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; - case 0x38: if (tmp) { DIVB; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; - } -} - -OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2; - GetModRM; tmp = GetRMWord(ModRM); - switch (ModRM & 0x38) { - case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Word(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ - case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC(nec_state)); break; - case 0x10: PutbackRMWord(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ - case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ - case 0x20: uresult = nec_state->regs.w[AW]*tmp; nec_state->regs.w[AW]=uresult&0xffff; nec_state->regs.w[DW]=((UINT32)uresult)>>16; nec_state->CarryVal=nec_state->OverVal=(nec_state->regs.w[DW]!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ - case 0x28: result = (INT32)((INT16)nec_state->regs.w[AW])*(INT32)((INT16)tmp); nec_state->regs.w[AW]=result&0xffff; nec_state->regs.w[DW]=result>>16; nec_state->CarryVal=nec_state->OverVal=(nec_state->regs.w[DW]!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ - case 0x30: if (tmp) { DIVUW; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; - case 0x38: if (tmp) { DIVW; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; - } -} - -OP( 0xf8, i_clc ) { nec_state->CarryVal = 0; CLK(2); } -OP( 0xf9, i_stc ) { nec_state->CarryVal = 1; CLK(2); } -OP( 0xfa, i_di ) { SetIF(0); CLK(2); } -OP( 0xfb, i_ei ) { SetIF(1); CLK(2); } -OP( 0xfc, i_cld ) { SetDF(0); CLK(2); } -OP( 0xfd, i_std ) { SetDF(1); CLK(2); } -OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); - switch(ModRM & 0x38) { - case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */ - case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */ - default: logerror("%06x: FE Pre with unimplemented mod\n",PC(nec_state)); - } -} -OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); - switch(ModRM & 0x38) { - case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */ - case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */ - case 0x10: PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */ - case 0x18: tmp1 = nec_state->sregs[PS]; nec_state->sregs[PS] = GetnextRMWord; PUSH(tmp1); PUSH(nec_state->ip); nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */ - case 0x20: nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=13; break; /* JMP */ - case 0x28: nec_state->ip = tmp; nec_state->sregs[PS] = GetnextRMWord; CHANGE_PC; nec_state->icount-=15; break; /* JMP FAR */ - case 0x30: PUSH(tmp); nec_state->icount-=4; break; - default: logerror("%06x: FF Pre with unimplemented mod\n",PC(nec_state)); - } -} - -static void i_invalid(nec_state_t *nec_state) -{ - nec_state->icount-=10; - logerror("%06x: Invalid Opcode\n",PC(nec_state)); -} +#include "necinstr.c" /*****************************************************************************/ @@ -1083,19 +349,13 @@ static void set_poll_line(nec_state_t *nec_state, int state) static CPU_DISASSEMBLE( nec ) { - nec_state_t *nec_state = get_safe_token(device); - - return necv_dasm_one(buffer, pc, oprom, nec_state->config); + return necv_dasm_one(buffer, pc, oprom, NULL); } static void nec_init(legacy_cpu_device *device, device_irq_callback irqcallback, int type) { - const nec_config *config = device->baseconfig().static_config() ? (const nec_config *)device->baseconfig().static_config() : &default_config; nec_state_t *nec_state = get_safe_token(device); - nec_state->config = config; - - state_save_register_device_item_array(device, 0, nec_state->regs.w); state_save_register_device_item_array(device, 0, nec_state->sregs); @@ -1144,7 +404,7 @@ static CPU_EXECUTE( necv ) if (nec_state->no_interrupt) nec_state->no_interrupt--; - debugger_instruction_hook(device, (nec_state->sregs[PS]<<4) + nec_state->ip); + debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip); prev_ICount = nec_state->icount; nec_instruction[fetchop(nec_state)](nec_state); do_prefetch(nec_state, prev_ICount); @@ -1209,41 +469,41 @@ static CPU_SET_INFO( nec ) case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + NEC_PC: - if( info->i - (nec_state->sregs[PS]<<4) < 0x10000 ) + if( info->i - (Sreg(PS)<<4) < 0x10000 ) { - nec_state->ip = info->i - (nec_state->sregs[PS]<<4); + nec_state->ip = info->i - (Sreg(PS)<<4); } else { - nec_state->sregs[PS] = info->i >> 4; + Sreg(PS) = info->i >> 4; nec_state->ip = info->i & 0x0000f; } break; case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break; case CPUINFO_INT_SP: - if( info->i - (nec_state->sregs[SS]<<4) < 0x10000 ) + if( info->i - (Sreg(SS)<<4) < 0x10000 ) { - nec_state->regs.w[SP] = info->i - (nec_state->sregs[SS]<<4); + Wreg(SP) = info->i - (Sreg(SS)<<4); } else { - nec_state->sregs[SS] = info->i >> 4; - nec_state->regs.w[SP] = info->i & 0x0000f; + Sreg(SS) = info->i >> 4; + Wreg(SP) = info->i & 0x0000f; } break; - case CPUINFO_INT_REGISTER + NEC_SP: nec_state->regs.w[SP] = info->i; break; + case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break; case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break; - case CPUINFO_INT_REGISTER + NEC_AW: nec_state->regs.w[AW] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_CW: nec_state->regs.w[CW] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_DW: nec_state->regs.w[DW] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_BW: nec_state->regs.w[BW] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_BP: nec_state->regs.w[BP] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_IX: nec_state->regs.w[IX] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_IY: nec_state->regs.w[IY] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_ES: nec_state->sregs[DS1] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_CS: nec_state->sregs[PS] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_SS: nec_state->sregs[SS] = info->i; break; - case CPUINFO_INT_REGISTER + NEC_DS: nec_state->sregs[DS0] = info->i; break; + case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break; case CPUINFO_INT_REGISTER + NEC_VECTOR: nec_state->int_vector = info->i; break; } } @@ -1290,22 +550,22 @@ static CPU_GET_INFO( nec ) case CPUINFO_INT_PREVIOUSPC: /* not supported */ break; case CPUINFO_INT_PC: - case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((nec_state->sregs[PS]<<4) + nec_state->ip); break; + case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break; case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break; - case CPUINFO_INT_SP: info->i = (nec_state->sregs[SS]<<4) + nec_state->regs.w[SP]; break; - case CPUINFO_INT_REGISTER + NEC_SP: info->i = nec_state->regs.w[SP]; break; + case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break; case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break; - case CPUINFO_INT_REGISTER + NEC_AW: info->i = nec_state->regs.w[AW]; break; - case CPUINFO_INT_REGISTER + NEC_CW: info->i = nec_state->regs.w[CW]; break; - case CPUINFO_INT_REGISTER + NEC_DW: info->i = nec_state->regs.w[DW]; break; - case CPUINFO_INT_REGISTER + NEC_BW: info->i = nec_state->regs.w[BW]; break; - case CPUINFO_INT_REGISTER + NEC_BP: info->i = nec_state->regs.w[BP]; break; - case CPUINFO_INT_REGISTER + NEC_IX: info->i = nec_state->regs.w[IX]; break; - case CPUINFO_INT_REGISTER + NEC_IY: info->i = nec_state->regs.w[IY]; break; - case CPUINFO_INT_REGISTER + NEC_ES: info->i = nec_state->sregs[DS1]; break; - case CPUINFO_INT_REGISTER + NEC_CS: info->i = nec_state->sregs[PS]; break; - case CPUINFO_INT_REGISTER + NEC_SS: info->i = nec_state->sregs[SS]; break; - case CPUINFO_INT_REGISTER + NEC_DS: info->i = nec_state->sregs[DS0]; break; + case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break; + case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break; + case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break; + case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break; + case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break; + case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break; + case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break; + case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break; + case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break; + case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break; + case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break; case CPUINFO_INT_REGISTER + NEC_VECTOR: info->i = nec_state->int_vector; break; case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break; @@ -1329,7 +589,7 @@ static CPU_GET_INFO( nec ) case CPUINFO_STR_FLAGS: flags = CompressFlags(); sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", - flags & 0x8000 ? 'M':'.', + flags & 0x8000 ? 'N':'E', flags & 0x4000 ? '?':'.', flags & 0x2000 ? '?':'.', flags & 0x1000 ? '?':'.', @@ -1343,25 +603,25 @@ static CPU_GET_INFO( nec ) flags & 0x0010 ? 'A':'.', flags & 0x0008 ? '?':'.', flags & 0x0004 ? 'P':'.', - flags & 0x0002 ? 'N':'.', + flags & 0x0002 ? '.':'?', flags & 0x0001 ? 'C':'.'); break; - case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%04X", (nec_state->sregs[PS]<<4) + nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%04X", (Sreg(PS)<<4) + nec_state->ip); break; case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break; - case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", nec_state->regs.w[SP]); break; + case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break; case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break; - case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", nec_state->regs.w[AW]); break; - case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", nec_state->regs.w[CW]); break; - case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", nec_state->regs.w[DW]); break; - case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", nec_state->regs.w[BW]); break; - case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", nec_state->regs.w[BP]); break; - case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", nec_state->regs.w[IX]); break; - case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", nec_state->regs.w[IY]); break; - case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", nec_state->sregs[DS1]); break; - case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", nec_state->sregs[PS]); break; - case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", nec_state->sregs[SS]); break; - case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", nec_state->sregs[DS0]); break; + case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break; + case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break; + case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break; + case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break; + case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break; + case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break; + case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break; + case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break; + case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break; + case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break; + case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break; case CPUINFO_STR_REGISTER + NEC_VECTOR: sprintf(info->s, "V:%02X", nec_state->int_vector); break; } } @@ -1390,29 +650,6 @@ CPU_GET_INFO( v20 ) } -/************************************************************************** - * CPU-specific set_info - **************************************************************************/ - -CPU_GET_INFO( v25 ) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; - case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v20); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "V25"); break; - - default: CPU_GET_INFO_CALL(nec); break; - } -} - - /************************************************************************** * CPU-specific set_info **************************************************************************/ @@ -1450,27 +687,6 @@ CPU_GET_INFO( v33 ) } } - -/************************************************************************** - * CPU-specific set_info - **************************************************************************/ - -CPU_GET_INFO( v35 ) -{ - switch (state) - { - /* --- the following bits of info are returned as pointers to data or functions --- */ - case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v30); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "V35"); break; - - default: CPU_GET_INFO_CALL(nec); break; - } -} - DEFINE_LEGACY_CPU_DEVICE(V20, v20); -DEFINE_LEGACY_CPU_DEVICE(V25, v25); DEFINE_LEGACY_CPU_DEVICE(V30, v30); DEFINE_LEGACY_CPU_DEVICE(V33, v33); -DEFINE_LEGACY_CPU_DEVICE(V35, v35); diff --git a/src/emu/cpu/nec/nec.h b/src/emu/cpu/nec/nec.h index 93070d1b5d4..3c47aa8c051 100644 --- a/src/emu/cpu/nec/nec.h +++ b/src/emu/cpu/nec/nec.h @@ -1,29 +1,29 @@ -/* ASG 971222 -- rewrote this interface */ -#ifndef __NEC_H_ -#define __NEC_H_ - - -typedef struct _nec_config nec_config; -struct _nec_config -{ - const UINT8* v25v35_decryptiontable; // internal decryption table -}; - -#define NEC_INPUT_LINE_POLL 20 - -enum -{ - NEC_PC=0, - NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY, - NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS, - NEC_VECTOR, NEC_PENDING -}; - -/* Public functions */ -DECLARE_LEGACY_CPU_DEVICE(V20, v20); -DECLARE_LEGACY_CPU_DEVICE(V25, v25); -DECLARE_LEGACY_CPU_DEVICE(V30, v30); -DECLARE_LEGACY_CPU_DEVICE(V33, v33); -DECLARE_LEGACY_CPU_DEVICE(V35, v35); - -#endif +/* ASG 971222 -- rewrote this interface */ +#ifndef __NEC_H_ +#define __NEC_H_ + + +typedef struct _nec_config nec_config; +struct _nec_config +{ + const UINT8* v25v35_decryptiontable; // internal decryption table +}; + +#define NEC_INPUT_LINE_POLL 20 + +enum +{ + NEC_PC=0, + NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY, + NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS, + NEC_VECTOR, NEC_PENDING +}; + +/* Public functions */ +DECLARE_LEGACY_CPU_DEVICE(V20, v20); +DECLARE_LEGACY_CPU_DEVICE(V25, v25); +DECLARE_LEGACY_CPU_DEVICE(V30, v30); +DECLARE_LEGACY_CPU_DEVICE(V33, v33); +DECLARE_LEGACY_CPU_DEVICE(V35, v35); + +#endif diff --git a/src/emu/cpu/nec/necea.h b/src/emu/cpu/nec/necea.h index 17f72a1177e..cafbb27a620 100644 --- a/src/emu/cpu/nec/necea.h +++ b/src/emu/cpu/nec/necea.h @@ -3,32 +3,32 @@ static UINT32 EA; static UINT16 EO; static UINT16 E16; -static unsigned EA_000(nec_state_t *nec_state) { EO=nec_state->regs.w[BW]+nec_state->regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_001(nec_state_t *nec_state) { EO=nec_state->regs.w[BW]+nec_state->regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_002(nec_state_t *nec_state) { EO=nec_state->regs.w[BP]+nec_state->regs.w[IX]; EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_003(nec_state_t *nec_state) { EO=nec_state->regs.w[BP]+nec_state->regs.w[IY]; EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_004(nec_state_t *nec_state) { EO=nec_state->regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_005(nec_state_t *nec_state) { EO=nec_state->regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_000(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_001(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_002(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IX); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_003(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IY); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_004(nec_state_t *nec_state) { EO=Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_005(nec_state_t *nec_state) { EO=Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; } static unsigned EA_006(nec_state_t *nec_state) { EO=FETCH(); EO+=FETCH()<<8; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_007(nec_state_t *nec_state) { EO=nec_state->regs.w[BW]; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_007(nec_state_t *nec_state) { EO=Wreg(BW); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_100(nec_state_t *nec_state) { EO=(nec_state->regs.w[BW]+nec_state->regs.w[IX]+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_101(nec_state_t *nec_state) { EO=(nec_state->regs.w[BW]+nec_state->regs.w[IY]+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_102(nec_state_t *nec_state) { EO=(nec_state->regs.w[BP]+nec_state->regs.w[IX]+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_103(nec_state_t *nec_state) { EO=(nec_state->regs.w[BP]+nec_state->regs.w[IY]+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_104(nec_state_t *nec_state) { EO=(nec_state->regs.w[IX]+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_105(nec_state_t *nec_state) { EO=(nec_state->regs.w[IY]+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_106(nec_state_t *nec_state) { EO=(nec_state->regs.w[BP]+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_107(nec_state_t *nec_state) { EO=(nec_state->regs.w[BW]+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_100(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_101(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_102(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_103(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_104(nec_state_t *nec_state) { EO=(Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_105(nec_state_t *nec_state) { EO=(Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_106(nec_state_t *nec_state) { EO=(Wreg(BP)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_107(nec_state_t *nec_state) { EO=(Wreg(BW)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_200(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BW]+nec_state->regs.w[IX]+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_201(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BW]+nec_state->regs.w[IY]+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_202(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BP]+nec_state->regs.w[IX]+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_203(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BP]+nec_state->regs.w[IY]+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_204(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[IX]+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_205(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[IY]+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } -static unsigned EA_206(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BP]+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } -static unsigned EA_207(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=nec_state->regs.w[BW]+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_200(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_201(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_202(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IX)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_203(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IY)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_204(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_205(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_206(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_207(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } static unsigned (*const GetEA[192])(nec_state_t *)={ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, diff --git a/src/emu/cpu/nec/necinstr.c b/src/emu/cpu/nec/necinstr.c new file mode 100644 index 00000000000..4a85241227b --- /dev/null +++ b/src/emu/cpu/nec/necinstr.c @@ -0,0 +1,672 @@ +#define OP(num,func_name) static void func_name(nec_state_t *nec_state) + +OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x06, i_push_es ) { PUSH(Sreg(DS1)); CLKS(12,8,3); } +OP( 0x07, i_pop_es ) { POP(Sreg(DS1)); CLKS(12,8,5); } + +OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x0e, i_push_cs ) { PUSH(Sreg(PS)); CLKS(12,8,3); } +OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2; + switch (FETCH()) { + case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; + case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; + case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(nec_state)); break; + case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(nec_state)); break; + case 0x92 : CLK(2); break; /* V25/35 FINT */ + case 0xe0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC(nec_state)); break; + case 0xf0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC(nec_state)); break; + case 0xff : ModRM = FETCH(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC(nec_state)); break; + default: logerror("%06x: Unknown V20 instruction\n",PC(nec_state)); break; + } +} + +OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x16, i_push_ss ) { PUSH(Sreg(SS)); CLKS(12,8,3); } +OP( 0x17, i_pop_ss ) { POP(Sreg(SS)); CLKS(12,8,5); nec_state->no_interrupt=1; } + +OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x1e, i_push_ds ) { PUSH(Sreg(DS0)); CLKS(12,8,3); } +OP( 0x1f, i_pop_ds ) { POP(Sreg(DS0)); CLKS(12,8,5); } + +OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x26, i_es ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); } + +OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x2e, i_cs ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); } + +OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x36, i_ss ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x37, i_aaa ) { ADJB(6, (Breg(AL) > 0xf9) ? 2 : 1); CLKS(7,7,4); } + +OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); } +OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,EA);} +OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); } +OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); } +OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); } +OP( 0x3e, i_ds ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x3f, i_aas ) { ADJB(-6, (Breg(AL) < 6) ? -2 : -1); CLKS(7,7,4); } + +OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); } +OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); } +OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); } +OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); } +OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); } +OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); } +OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); } +OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); } + +OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); } +OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); } +OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); } +OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); } +OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); } +OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); } +OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); } +OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); } + +OP( 0x50, i_push_ax ) { PUSH(Wreg(AW)); CLKS(12,8,3); } +OP( 0x51, i_push_cx ) { PUSH(Wreg(CW)); CLKS(12,8,3); } +OP( 0x52, i_push_dx ) { PUSH(Wreg(DW)); CLKS(12,8,3); } +OP( 0x53, i_push_bx ) { PUSH(Wreg(BW)); CLKS(12,8,3); } +OP( 0x54, i_push_sp ) { PUSH(Wreg(SP)); CLKS(12,8,3); } +OP( 0x55, i_push_bp ) { PUSH(Wreg(BP)); CLKS(12,8,3); } +OP( 0x56, i_push_si ) { PUSH(Wreg(IX)); CLKS(12,8,3); } +OP( 0x57, i_push_di ) { PUSH(Wreg(IY)); CLKS(12,8,3); } + +OP( 0x58, i_pop_ax ) { POP(Wreg(AW)); CLKS(12,8,5); } +OP( 0x59, i_pop_cx ) { POP(Wreg(CW)); CLKS(12,8,5); } +OP( 0x5a, i_pop_dx ) { POP(Wreg(DW)); CLKS(12,8,5); } +OP( 0x5b, i_pop_bx ) { POP(Wreg(BW)); CLKS(12,8,5); } +OP( 0x5c, i_pop_sp ) { POP(Wreg(SP)); CLKS(12,8,5); } +OP( 0x5d, i_pop_bp ) { POP(Wreg(BP)); CLKS(12,8,5); } +OP( 0x5e, i_pop_si ) { POP(Wreg(IX)); CLKS(12,8,5); } +OP( 0x5f, i_pop_di ) { POP(Wreg(IY)); CLKS(12,8,5); } + +OP( 0x60, i_pusha ) { + unsigned tmp=Wreg(SP); + PUSH(Wreg(AW)); + PUSH(Wreg(CW)); + PUSH(Wreg(DW)); + PUSH(Wreg(BW)); + PUSH(tmp); + PUSH(Wreg(BP)); + PUSH(Wreg(IX)); + PUSH(Wreg(IY)); + CLKS(67,35,20); +} +OP( 0x61, i_popa ) { + unsigned tmp; + POP(Wreg(IY)); + POP(Wreg(IX)); + POP(Wreg(BP)); + POP(tmp); + POP(Wreg(BW)); + POP(Wreg(DW)); + POP(Wreg(CW)); + POP(Wreg(AW)); + CLKS(75,43,22); +} +OP( 0x62, i_chkind ) { + UINT32 low,high,tmp; + GetModRM; + low = GetRMWord(ModRM); + high= GetnextRMWord; + tmp= RegWord(ModRM); + if (tmphigh) { + nec_interrupt(nec_state, 5,0); + } + nec_state->icount-=20; + logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(nec_state),high,low,tmp); +} +OP( 0x64, i_repnc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + default: logerror("%06x: REPNC invalid\n",PC(nec_state)); nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} + +OP( 0x65, i_repc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + default: logerror("%06x: REPC invalid\n",PC(nec_state)); nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} + +OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,Wreg(SP)); } +OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?38:47;} +OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,Wreg(SP)); } +OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?31:39; } +OP( 0x6c, i_insb ) { PutMemB(DS1,Wreg(IY),read_port_byte(Wreg(DW))); Wreg(IY)+= -2 * nec_state->DF + 1; CLK(8); } +OP( 0x6d, i_insw ) { PutMemW(DS1,Wreg(IY),read_port_word(Wreg(DW))); Wreg(IY)+= -4 * nec_state->DF + 2; CLKS(18,10,8); } +OP( 0x6e, i_outsb ) { write_port_byte(Wreg(DW),GetMemB(DS0,Wreg(IX))); Wreg(IX)+= -2 * nec_state->DF + 1; CLK(8); } +OP( 0x6f, i_outsw ) { write_port_word(Wreg(DW),GetMemW(DS0,Wreg(IX))); Wreg(IX)+= -4 * nec_state->DF + 2; CLKS(18,10,8); } + +OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); } +OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); } +OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); } +OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); } +OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); } +OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); } +OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); } +OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); } +OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); } +OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); } +OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); } +OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); } +OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); } +OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); } +OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); } +OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); } + +OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH(); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) + switch (ModRM & 0x38) { + case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; + case 0x08: ORB; PutbackRMByte(ModRM,dst); break; + case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; + case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; + case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; + case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; + case 0x30: XORB; PutbackRMByte(ModRM,dst); break; + case 0x38: SUBB; break; /* CMP */ + } +} + +OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) + switch (ModRM & 0x38) { + case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; + case 0x08: ORW; PutbackRMWord(ModRM,dst); break; + case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; + case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; + case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; + case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; + case 0x30: XORW; PutbackRMWord(ModRM,dst); break; + case 0x38: SUBW; break; /* CMP */ + } +} + +OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH()); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) + switch (ModRM & 0x38) { + case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; + case 0x08: ORB; PutbackRMByte(ModRM,dst); break; + case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; + case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; + case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; + case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; + case 0x30: XORB; PutbackRMByte(ModRM,dst); break; + case 0x38: SUBB; break; /* CMP */ + } +} + +OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH())); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) + switch (ModRM & 0x38) { + case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; + case 0x08: ORW; PutbackRMWord(ModRM,dst); break; + case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; + case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; + case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; + case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; + case 0x30: XORW; PutbackRMWord(ModRM,dst); break; + case 0x38: SUBW; break; /* CMP */ + } +} + +OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); } +OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,EA); } +OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); } +OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,EA); } + +OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); } +OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,EA); } +OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); } +OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,EA); } +OP( 0x8c, i_mov_wsreg ) { GetModRM; + switch (ModRM & 0x38) { + case 0x00: PutRMWord(ModRM,Sreg(DS1)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x08: PutRMWord(ModRM,Sreg(PS)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x10: PutRMWord(ModRM,Sreg(SS)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x18: PutRMWord(ModRM,Sreg(DS0)); CLKR(14,14,5,14,10,3,2,EA); break; + default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state)); + } +} +OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(*GetEA[ModRM])(nec_state); RegWord(ModRM)=EO; CLKS(4,4,2); } +OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,EA); + switch (ModRM & 0x38) { + case 0x00: Sreg(DS1) = src; break; /* mov es,ew */ + case 0x08: Sreg(PS) = src; break; /* mov cs,ew */ + case 0x10: Sreg(SS) = src; break; /* mov ss,ew */ + case 0x18: Sreg(DS0) = src; break; /* mov ds,ew */ + default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state)); + } + nec_state->no_interrupt=1; +} +OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); nec_state->icount-=21; } +OP( 0x90, i_nop ) { CLK(3); } +OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } +OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } +OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } +OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } +OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } +OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } +OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } + +OP( 0x98, i_cbw ) { Breg(AH) = (Breg(AL) & 0x80) ? 0xff : 0; CLK(2); } +OP( 0x99, i_cwd ) { Wreg(DW) = (Breg(AH) & 0x80) ? 0xffff : 0; CLK(4); } +OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(Sreg(PS)); PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; Sreg(PS) = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,Wreg(SP)); } +OP( 0x9b, i_wait ) { if (!nec_state->poll_state) nec_state->ip--; CLK(5); } +OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); } +OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (nec_state->TF) nec_trap(nec_state); } +OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (Breg(AH) & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); } +OP( 0x9f, i_lahf ) { Breg(AH) = CompressFlags() & 0xff; CLKS(3,3,2); } + +OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); Breg(AL) = GetMemB(DS0, addr); CLKS(10,10,5); } +OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); Wreg(AW) = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); } +OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, Breg(AL)); CLKS(9,9,3); } +OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, Wreg(AW)); CLKW(13,13,5,13,9,3,addr); } +OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,Wreg(IX)); PutMemB(DS1,Wreg(IY), tmp); Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(8,8,6); } +OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,Wreg(IX)); PutMemW(DS1,Wreg(IY), tmp); Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(16,16,10); } +OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = GetMemB(DS0, Wreg(IX)); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(14,14,14); } +OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = GetMemW(DS0, Wreg(IX)); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(14,14,14); } + +OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); } +OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); } +OP( 0xaa, i_stosb ) { PutMemB(DS1,Wreg(IY),Breg(AL)); Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xab, i_stosw ) { PutMemW(DS1,Wreg(IY),Wreg(AW)); Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } +OP( 0xac, i_lodsb ) { Breg(AL) = GetMemB(DS0,Wreg(IX)); Wreg(IX) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xad, i_lodsw ) { Wreg(AW) = GetMemW(DS0,Wreg(IX)); Wreg(IX) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IX)); } +OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = Breg(AL); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = Wreg(AW); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } + +OP( 0xb0, i_mov_ald8 ) { Breg(AL) = FETCH(); CLKS(4,4,2); } +OP( 0xb1, i_mov_cld8 ) { Breg(CL) = FETCH(); CLKS(4,4,2); } +OP( 0xb2, i_mov_dld8 ) { Breg(DL) = FETCH(); CLKS(4,4,2); } +OP( 0xb3, i_mov_bld8 ) { Breg(BL) = FETCH(); CLKS(4,4,2); } +OP( 0xb4, i_mov_ahd8 ) { Breg(AH) = FETCH(); CLKS(4,4,2); } +OP( 0xb5, i_mov_chd8 ) { Breg(CH) = FETCH(); CLKS(4,4,2); } +OP( 0xb6, i_mov_dhd8 ) { Breg(DH) = FETCH(); CLKS(4,4,2); } +OP( 0xb7, i_mov_bhd8 ) { Breg(BH) = FETCH(); CLKS(4,4,2); } + +OP( 0xb8, i_mov_axd16 ) { Breg(AL) = FETCH(); Breg(AH) = FETCH(); CLKS(4,4,2); } +OP( 0xb9, i_mov_cxd16 ) { Breg(CL) = FETCH(); Breg(CH) = FETCH(); CLKS(4,4,2); } +OP( 0xba, i_mov_dxd16 ) { Breg(DL) = FETCH(); Breg(DH) = FETCH(); CLKS(4,4,2); } +OP( 0xbb, i_mov_bxd16 ) { Breg(BL) = FETCH(); Breg(BH) = FETCH(); CLKS(4,4,2); } +OP( 0xbc, i_mov_spd16 ) { Wreg(SP) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbd, i_mov_bpd16 ) { Wreg(BP) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbe, i_mov_sid16 ) { Wreg(IX) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbf, i_mov_did16 ) { Wreg(IY) = FETCHWORD(); CLKS(4,4,2); } + +OP( 0xc0, i_rotshft_bd8 ) { + UINT32 src, dst; UINT8 c; + GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; + c=FETCH(); + CLKM(7,7,2,19,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; + case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(c); break; + } +} + +OP( 0xc1, i_rotshft_wd8 ) { + UINT32 src, dst; UINT8 c; + GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; + c=FETCH(); + CLKM(7,7,2,27,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; + case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(c); break; + } +} + +OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); Wreg(SP)+=count; CHANGE_PC; CLKS(24,24,10); } +OP( 0xc3, i_ret ) { POP(nec_state->ip); CHANGE_PC; CLKS(19,19,10); } +OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS1) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } +OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS0) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } +OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:11; } +OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:15; } + +OP( 0xc8, i_enter ) { + UINT32 nb = FETCH(); + UINT32 i,level; + + nec_state->icount-=23; + nb += FETCH() << 8; + level = FETCH(); + PUSH(Wreg(BP)); + Wreg(BP)=Wreg(SP); + Wreg(SP) -= nb; + for (i=1;iicount-=16; + } + if (level) PUSH(Wreg(BP)); +} +OP( 0xc9, i_leave ) { + Wreg(SP)=Wreg(BP); + POP(Wreg(BP)); + nec_state->icount-=8; +} +OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); POP(Sreg(PS)); Wreg(SP)+=count; CHANGE_PC; CLKS(32,32,16); } +OP( 0xcb, i_retf ) { POP(nec_state->ip); POP(Sreg(PS)); CHANGE_PC; CLKS(29,29,16); } +OP( 0xcc, i_int3 ) { nec_interrupt(nec_state, 3,0); CLKS(50,50,24); } +OP( 0xcd, i_int ) { nec_interrupt(nec_state, FETCH(),0); CLKS(50,50,24); } +OP( 0xce, i_into ) { if (OF) { nec_interrupt(nec_state, 4,0); CLKS(52,52,26); } else CLK(3); } +OP( 0xcf, i_iret ) { POP(nec_state->ip); POP(Sreg(PS)); i_popf(nec_state); CHANGE_PC; CLKS(39,39,19); } + +OP( 0xd0, i_rotshft_b ) { + UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; + CLKM(6,6,2,16,16,7); + switch (ModRM & 0x38) { + case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x20: SHL_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; + case 0x28: SHR_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; + case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(1); nec_state->OverVal = 0; break; + } +} + +OP( 0xd1, i_rotshft_w ) { + UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; + CLKM(6,6,2,24,16,7); + switch (ModRM & 0x38) { + case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x20: SHL_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x28: SHR_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(1); nec_state->OverVal = 0; break; + } +} + +OP( 0xd2, i_rotshft_bcl ) { + UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; + c=Breg(CL); + CLKM(7,7,2,19,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; + case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(c); break; + } +} + +OP( 0xd3, i_rotshft_wcl ) { + UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; + c=Breg(CL); + CLKM(7,7,2,27,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; + case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(c); break; + } +} + +OP( 0xd4, i_aam ) { UINT32 mult=FETCH(); mult=0; Breg(AH) = Breg(AL) / 10; Breg(AL) %= 10; SetSZPF_Word(Wreg(AW)); CLKS(15,15,12); } +OP( 0xd5, i_aad ) { UINT32 mult=FETCH(); mult=0; Breg(AL) = Breg(AH) * 10 + Breg(AL); Breg(AH) = 0; SetSZPF_Byte(Breg(AL)); CLKS(7,7,8); } +OP( 0xd6, i_setalc ) { Breg(AL) = (CF)?0xff:0x00; nec_state->icount-=3; logerror("%06x: Undefined opcode (SETALC)\n",PC(nec_state)); } +OP( 0xd7, i_trans ) { UINT32 dest = (Wreg(BW)+Breg(AL))&0xffff; Breg(AL) = GetMemB(DS0, dest); CLKS(9,9,5); } +OP( 0xd8, i_fpo ) { GetModRM; nec_state->icount-=2; logerror("%06x: Unimplemented floating point control %04x\n",PC(nec_state),ModRM); } + +OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (!ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } +OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if ( ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } +OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } +OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (Wreg(CW) == 0) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } +OP( 0xe4, i_inal ) { UINT8 port = FETCH(); Breg(AL) = read_port_byte(port); CLKS(9,9,5); } +OP( 0xe5, i_inax ) { UINT8 port = FETCH(); Wreg(AW) = read_port_word(port); CLKW(13,13,7,13,9,5,port); } +OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, Breg(AL)); CLKS(8,8,3); } +OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, Wreg(AW)); CLKW(12,12,5,12,8,3,port); } + +OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(nec_state->ip); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=24; } +OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=15; } +OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); Sreg(PS) = (WORD)tmp1; nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=27; } +OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); nec_state->icount-=12; nec_state->ip = (WORD)(nec_state->ip+tmp); } +OP( 0xec, i_inaldx ) { Breg(AL) = read_port_byte(Wreg(DW)); CLKS(8,8,5);} +OP( 0xed, i_inaxdx ) { Wreg(AW) = read_port_word(Wreg(DW)); CLKW(12,12,7,12,8,5,Wreg(DW)); } +OP( 0xee, i_outdxal ) { write_port_byte(Wreg(DW), Breg(AL)); CLKS(8,8,3); } +OP( 0xef, i_outdxax ) { write_port_word(Wreg(DW), Wreg(AW)); CLKW(12,12,5,12,8,3,Wreg(DW)); } + +OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC(nec_state)); nec_state->no_interrupt=1; CLK(2); } +OP( 0xf2, i_repne ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + default: logerror("%06x: REPNE invalid\n",PC(nec_state)); nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} +OP( 0xf3, i_repe ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + default: logerror("%06x: REPE invalid\n",PC(nec_state)); nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} +OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC(nec_state)); nec_state->icount=0; } +OP( 0xf5, i_cmc ) { nec_state->CarryVal = !CF; CLK(2); } +OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; + GetModRM; tmp = GetRMByte(ModRM); + switch (ModRM & 0x38) { + case 0x00: tmp &= FETCH(); nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Byte(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ + case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC(nec_state)); break; + case 0x10: PutbackRMByte(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ + case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ + case 0x20: uresult = Breg(AL)*tmp; Wreg(AW)=(WORD)uresult; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ + case 0x28: result = (INT16)((INT8)Breg(AL))*(INT16)((INT8)tmp); Wreg(AW)=(WORD)result; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ + case 0x30: if (tmp) { DIVUB; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + case 0x38: if (tmp) { DIVB; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + } +} + +OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2; + GetModRM; tmp = GetRMWord(ModRM); + switch (ModRM & 0x38) { + case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Word(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ + case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC(nec_state)); break; + case 0x10: PutbackRMWord(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ + case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ + case 0x20: uresult = Wreg(AW)*tmp; Wreg(AW)=uresult&0xffff; Wreg(DW)=((UINT32)uresult)>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ + case 0x28: result = (INT32)((INT16)Wreg(AW))*(INT32)((INT16)tmp); Wreg(AW)=result&0xffff; Wreg(DW)=result>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ + case 0x30: if (tmp) { DIVUW; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + case 0x38: if (tmp) { DIVW; } else nec_interrupt(nec_state, 0,0); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + } +} + +OP( 0xf8, i_clc ) { nec_state->CarryVal = 0; CLK(2); } +OP( 0xf9, i_stc ) { nec_state->CarryVal = 1; CLK(2); } +OP( 0xfa, i_di ) { SetIF(0); CLK(2); } +OP( 0xfb, i_ei ) { SetIF(1); CLK(2); } +OP( 0xfc, i_cld ) { SetDF(0); CLK(2); } +OP( 0xfd, i_std ) { SetDF(1); CLK(2); } +OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); + switch(ModRM & 0x38) { + case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */ + case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */ + default: logerror("%06x: FE Pre with unimplemented mod\n",PC(nec_state)); + } +} +OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); + switch(ModRM & 0x38) { + case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */ + case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */ + case 0x10: PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */ + case 0x18: tmp1 = Sreg(PS); Sreg(PS) = GetnextRMWord; PUSH(tmp1); PUSH(nec_state->ip); nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */ + case 0x20: nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=13; break; /* JMP */ + case 0x28: nec_state->ip = tmp; Sreg(PS) = GetnextRMWord; CHANGE_PC; nec_state->icount-=15; break; /* JMP FAR */ + case 0x30: PUSH(tmp); nec_state->icount-=4; break; + default: logerror("%06x: FF Pre with unimplemented mod\n",PC(nec_state)); + } +} + +static void i_invalid(nec_state_t *nec_state) +{ + nec_state->icount-=10; + logerror("%06x: Invalid Opcode\n",PC(nec_state)); +} diff --git a/src/emu/cpu/nec/necinstr.h b/src/emu/cpu/nec/necinstr.h index 07e118583b5..30bc3ffcbb2 100644 --- a/src/emu/cpu/nec/necinstr.h +++ b/src/emu/cpu/nec/necinstr.h @@ -97,7 +97,6 @@ static void i_pop_di(nec_state_t *nec_state); static void i_pusha(nec_state_t *nec_state); static void i_popa(nec_state_t *nec_state); static void i_chkind(nec_state_t *nec_state); -static void i_brkn(nec_state_t *nec_state); static void i_repnc(nec_state_t *nec_state); static void i_repc(nec_state_t *nec_state); static void i_push_d16(nec_state_t *nec_state); @@ -348,7 +347,7 @@ static void (*const nec_instruction[256])(nec_state_t *nec_state) = i_pusha, /* 0x60 */ i_popa, /* 0x61 */ i_chkind, /* 0x62 */ - i_brkn, /* 0x63 - V25S/V35S only */ + i_invalid, /* 0x63 */ i_repnc, /* 0x64 */ i_repc, /* 0x65 */ i_invalid, /* 0x66 */ diff --git a/src/emu/cpu/nec/necmodrm.h b/src/emu/cpu/nec/necmodrm.h index e21519fcddc..cf8956b8106 100644 --- a/src/emu/cpu/nec/necmodrm.h +++ b/src/emu/cpu/nec/necmodrm.h @@ -9,15 +9,15 @@ static struct { } RM; } Mod_RM; -#define RegWord(ModRM) nec_state->regs.w[Mod_RM.reg.w[ModRM]] -#define RegByte(ModRM) nec_state->regs.b[Mod_RM.reg.b[ModRM]] +#define RegWord(ModRM) Wreg(Mod_RM.reg.w[ModRM]) +#define RegByte(ModRM) Breg(Mod_RM.reg.b[ModRM]) #define GetRMWord(ModRM) \ - ((ModRM) >= 0xc0 ? nec_state->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(nec_state), read_mem_word( EA ) )) + ((ModRM) >= 0xc0 ? Wreg(Mod_RM.RM.w[ModRM]) : ( (*GetEA[ModRM])(nec_state), read_mem_word( EA ) )) #define PutbackRMWord(ModRM,val) \ { \ - if (ModRM >= 0xc0) nec_state->regs.w[Mod_RM.RM.w[ModRM]]=val; \ + if (ModRM >= 0xc0) Wreg(Mod_RM.RM.w[ModRM])=val; \ else write_mem_word(EA,val); \ } @@ -26,7 +26,7 @@ static struct { #define PutRMWord(ModRM,val) \ { \ if (ModRM >= 0xc0) \ - nec_state->regs.w[Mod_RM.RM.w[ModRM]]=val; \ + Wreg(Mod_RM.RM.w[ModRM])=val; \ else { \ (*GetEA[ModRM])(nec_state); \ write_mem_word( EA ,val); \ @@ -37,7 +37,7 @@ static struct { { \ WORD val; \ if (ModRM >= 0xc0) \ - nec_state->regs.w[Mod_RM.RM.w[ModRM]] = FETCHWORD(); \ + Wreg(Mod_RM.RM.w[ModRM]) = FETCHWORD(); \ else { \ (*GetEA[ModRM])(nec_state); \ val = FETCHWORD(); \ @@ -46,12 +46,12 @@ static struct { } #define GetRMByte(ModRM) \ - ((ModRM) >= 0xc0 ? nec_state->regs.b[Mod_RM.RM.b[ModRM]] : read_mem_byte( (*GetEA[ModRM])(nec_state) )) + ((ModRM) >= 0xc0 ? Breg(Mod_RM.RM.b[ModRM]) : read_mem_byte( (*GetEA[ModRM])(nec_state) )) #define PutRMByte(ModRM,val) \ { \ if (ModRM >= 0xc0) \ - nec_state->regs.b[Mod_RM.RM.b[ModRM]]=val; \ + Breg(Mod_RM.RM.b[ModRM])=val; \ else \ write_mem_byte( (*GetEA[ModRM])(nec_state) ,val); \ } @@ -59,7 +59,7 @@ static struct { #define PutImmRMByte(ModRM) \ { \ if (ModRM >= 0xc0) \ - nec_state->regs.b[Mod_RM.RM.b[ModRM]]=FETCH(); \ + Breg(Mod_RM.RM.b[ModRM])=FETCH(); \ else { \ (*GetEA[ModRM])(nec_state); \ write_mem_byte( EA , FETCH() ); \ @@ -69,7 +69,7 @@ static struct { #define PutbackRMByte(ModRM,val) \ { \ if (ModRM >= 0xc0) \ - nec_state->regs.b[Mod_RM.RM.b[ModRM]]=val; \ + Breg(Mod_RM.RM.b[ModRM])=val; \ else \ write_mem_byte(EA,val); \ } @@ -96,9 +96,9 @@ static struct { #define DEF_ald8 \ UINT32 src = FETCH(); \ - UINT32 dst = nec_state->regs.b[AL] + UINT32 dst = Breg(AL) #define DEF_axd16 \ UINT32 src = FETCH(); \ - UINT32 dst = nec_state->regs.w[AW]; \ + UINT32 dst = Wreg(AW); \ src += (FETCH() << 8) diff --git a/src/emu/cpu/nec/necpriv.h b/src/emu/cpu/nec/necpriv.h index 5c8ca972fd4..aa7e52a0220 100644 --- a/src/emu/cpu/nec/necpriv.h +++ b/src/emu/cpu/nec/necpriv.h @@ -1,7 +1,3 @@ - -typedef enum { DS1, PS, SS, DS0 } SREGS; -typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS; - #define NEC_NMI_INT_VECTOR 2 /* Cpu types, steps of 8 to help the cycle count calculation */ @@ -14,6 +10,51 @@ typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS; #define TRUE 1 #endif +/* NEC registers */ +typedef union +{ /* eight general registers */ + UINT16 w[8]; /* viewed as 16 bits registers */ + UINT8 b[16]; /* or as 8 bit registers */ +} necbasicregs; + +typedef struct _nec_state_t nec_state_t; +struct _nec_state_t +{ + necbasicregs regs; + offs_t fetch_xor; + UINT16 sregs[4]; + + UINT16 ip; + + INT32 SignVal; + UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ + UINT8 TF, IF, DF, MF; /* 0 or 1 valued flags */ + UINT32 int_vector; + UINT32 pending_irq; + UINT32 nmi_state; + UINT32 irq_state; + UINT32 poll_state; + UINT8 no_interrupt; + + device_irq_callback irq_callback; + legacy_cpu_device *device; + address_space *program; + direct_read_data *direct; + address_space *io; + int icount; + + UINT8 prefetch_size; + UINT8 prefetch_cycles; + INT8 prefetch_count; + UINT8 prefetch_reset; + UINT32 chip_type; + + UINT32 prefix_base; /* base address of the latest prefix segment */ + UINT8 seg_prefix; /* prefix segment indicator */ +}; + +typedef enum { DS1, PS, SS, DS0 } SREGS; +typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS; typedef enum { AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1), AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0), @@ -23,16 +64,12 @@ typedef enum { DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4), BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7), BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6), - SPL = NATIVE_ENDIAN_VALUE_LE_BE(0x8, 0x9), - SPH = NATIVE_ENDIAN_VALUE_LE_BE(0x9, 0x8), - BPL = NATIVE_ENDIAN_VALUE_LE_BE(0xa, 0xb), - BPH = NATIVE_ENDIAN_VALUE_LE_BE(0xb, 0xa), - IXL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd), - IXH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc), - IYL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf), - IYH = NATIVE_ENDIAN_VALUE_LE_BE(0xf, 0xe) } BREGS; +#define Sreg(x) nec_state->sregs[x] +#define Wreg(x) nec_state->regs.w[x] +#define Breg(x) nec_state->regs.b[x] + /* parameter x = result, y = source 1, z = source 2 */ #define SetTF(x) (nec_state->TF = (x)) @@ -76,7 +113,6 @@ typedef enum { #define PF parity_table[(BYTE)nec_state->ParityVal] #define AF (nec_state->AuxVal!=0) #define OF (nec_state->OverVal!=0) -#define MD (nec_state->MF!=0) /************************************************************************/ @@ -94,9 +130,9 @@ typedef enum { #define CHANGE_PC do { EMPTY_PREFETCH(); } while (0) -#define SegBase(Seg) (nec_state->sregs[Seg] << 4) +#define SegBase(Seg) (Sreg(Seg) << 4) -#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : nec_state->sregs[Seg] << 4) +#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4) #define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off))) #define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off))) @@ -112,8 +148,8 @@ typedef enum { #define EMPTY_PREFETCH() nec_state->prefetch_reset = 1 -#define PUSH(val) { nec_state->regs.w[SP]-=2; write_mem_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP])),val); } -#define POP(var) { var = read_mem_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP]))); nec_state->regs.w[SP]+=2; } +#define PUSH(val) { Wreg(SP)-=2; write_mem_word((((Sreg(SS)<<4)+Wreg(SP))),val); } +#define POP(var) { var = read_mem_word((((Sreg(SS)<<4)+Wreg(SP)))); Wreg(SP)+=2; } #define GetModRM UINT32 ModRM=FETCH() @@ -136,39 +172,39 @@ typedef enum { #define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } /************************************************************************/ -#define CompressFlags() (WORD)(CF | (PF << 2) | (AF << 4) | (ZF << 6) \ +#define CompressFlags() (WORD)(CF | 0x02 | (PF << 2) | (AF << 4) | (ZF << 6) \ | (SF << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \ - | (nec_state->DF << 10) | (OF << 11)| (MD << 15)) + | (nec_state->DF << 10) | (OF << 11) | (nec_state->MF << 15)) #define ExpandFlags(f) \ { \ - nec_state->CarryVal = (f) & 1; \ - nec_state->ParityVal = !((f) & 4); \ - nec_state->AuxVal = (f) & 16; \ - nec_state->ZeroVal = !((f) & 64); \ - nec_state->SignVal = (f) & 128 ? -1 : 0; \ - nec_state->TF = ((f) & 256) == 256; \ - nec_state->IF = ((f) & 512) == 512; \ - nec_state->DF = ((f) & 1024) == 1024; \ - nec_state->OverVal = (f) & 2048; \ + nec_state->CarryVal = (f) & 0x0001; \ + nec_state->ParityVal = !((f) & 0x0004); \ + nec_state->AuxVal = (f) & 0x0010; \ + nec_state->ZeroVal = !((f) & 0x0040); \ + nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \ + nec_state->TF = ((f) & 0x0100) == 0x0100; \ + nec_state->IF = ((f) & 0x0200) == 0x0200; \ + nec_state->DF = ((f) & 0x0400) == 0x0400; \ + nec_state->OverVal = (f) & 0x0800; \ nec_state->MF = ((f) & 0x8000) == 0x8000; \ } #define IncWordReg(Reg) \ - unsigned tmp = (unsigned)nec_state->regs.w[Reg]; \ + unsigned tmp = (unsigned)Wreg(Reg); \ unsigned tmp1 = tmp+1; \ nec_state->OverVal = (tmp == 0x7fff); \ SetAF(tmp1,tmp,1); \ SetSZPF_Word(tmp1); \ - nec_state->regs.w[Reg]=tmp1 + Wreg(Reg)=tmp1 #define DecWordReg(Reg) \ - unsigned tmp = (unsigned)nec_state->regs.w[Reg]; \ + unsigned tmp = (unsigned)Wreg(Reg); \ unsigned tmp1 = tmp-1; \ nec_state->OverVal = (tmp == 0x8000); \ SetAF(tmp1,tmp,1); \ SetSZPF_Word(tmp1); \ - nec_state->regs.w[Reg]=tmp1 + Wreg(Reg)=tmp1 #define JMP(flag) \ int tmp; \ @@ -184,26 +220,26 @@ typedef enum { } #define ADJ4(param1,param2) \ - if (AF || ((nec_state->regs.b[AL] & 0xf) > 9)) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ { \ UINT16 tmp; \ - tmp = nec_state->regs.b[AL] + param1; \ - nec_state->regs.b[AL] = tmp; \ + tmp = Breg(AL) + param1; \ + Breg(AL) = tmp; \ nec_state->AuxVal = 1; \ nec_state->CarryVal |= tmp & 0x100; \ } \ - if (CF || (nec_state->regs.b[AL]>0x9f)) \ + if (CF || (Breg(AL)>0x9f)) \ { \ - nec_state->regs.b[AL] += param2; \ + Breg(AL) += param2; \ nec_state->CarryVal = 1; \ } \ - SetSZPF_Byte(nec_state->regs.b[AL]) + SetSZPF_Byte(Breg(AL)) #define ADJB(param1,param2) \ - if (AF || ((nec_state->regs.b[AL] & 0xf) > 9)) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ { \ - nec_state->regs.b[AL] += param1; \ - nec_state->regs.b[AH] += param2; \ + Breg(AL) += param1; \ + Breg(AH) += param2; \ nec_state->AuxVal = 1; \ nec_state->CarryVal = 1; \ } \ @@ -212,12 +248,12 @@ typedef enum { nec_state->AuxVal = 0; \ nec_state->CarryVal = 0; \ } \ - nec_state->regs.b[AL] &= 0x0F + Breg(AL) &= 0x0F #define BITOP_BYTE \ ModRM = FETCH(); \ if (ModRM >= 0xc0) { \ - tmp=nec_state->regs.b[Mod_RM.RM.b[ModRM]]; \ + tmp=Breg(Mod_RM.RM.b[ModRM]); \ } \ else { \ (*GetEA[ModRM])(nec_state); \ @@ -227,7 +263,7 @@ typedef enum { #define BITOP_WORD \ ModRM = FETCH(); \ if (ModRM >= 0xc0) { \ - tmp=nec_state->regs.w[Mod_RM.RM.w[ModRM]]; \ + tmp=Wreg(Mod_RM.RM.w[ModRM]); \ } \ else { \ (*GetEA[ModRM])(nec_state); \ @@ -242,9 +278,9 @@ typedef enum { #define XchgAWReg(Reg) \ WORD tmp; \ - tmp = nec_state->regs.w[Reg]; \ - nec_state->regs.w[Reg] = nec_state->regs.w[AW]; \ - nec_state->regs.w[AW] = tmp + tmp = Wreg(Reg); \ + Wreg(Reg) = Wreg(AW); \ + Wreg(AW) = tmp #define ROL_BYTE nec_state->CarryVal = dst & 0x80; dst = (dst << 1)+CF #define ROL_WORD nec_state->CarryVal = dst & 0x8000; dst = (dst << 1)+CF @@ -262,50 +298,50 @@ typedef enum { #define SHRA_WORD(c) nec_state->icount-=c; dst = ((INT16)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT16)((WORD)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) #define DIVUB \ - uresult = nec_state->regs.w[AW]; \ + uresult = Wreg(AW); \ uresult2 = uresult % tmp; \ if ((uresult /= tmp) > 0xff) { \ nec_interrupt(nec_state, 0,0); break; \ } else { \ - nec_state->regs.b[AL] = uresult; \ - nec_state->regs.b[AH] = uresult2; \ + Breg(AL) = uresult; \ + Breg(AH) = uresult2; \ } #define DIVB \ - result = (INT16)nec_state->regs.w[AW]; \ + result = (INT16)Wreg(AW); \ result2 = result % (INT16)((INT8)tmp); \ if ((result /= (INT16)((INT8)tmp)) > 0xff) { \ nec_interrupt(nec_state, 0,0); break; \ } else { \ - nec_state->regs.b[AL] = result; \ - nec_state->regs.b[AH] = result2; \ + Breg(AL) = result; \ + Breg(AH) = result2; \ } #define DIVUW \ - uresult = (((UINT32)nec_state->regs.w[DW]) << 16) | nec_state->regs.w[AW];\ + uresult = (((UINT32)Wreg(DW)) << 16) | Wreg(AW);\ uresult2 = uresult % tmp; \ if ((uresult /= tmp) > 0xffff) { \ nec_interrupt(nec_state, 0,0); break; \ } else { \ - nec_state->regs.w[AW]=uresult; \ - nec_state->regs.w[DW]=uresult2; \ + Wreg(AW)=uresult; \ + Wreg(DW)=uresult2; \ } #define DIVW \ - result = ((UINT32)nec_state->regs.w[DW] << 16) + nec_state->regs.w[AW]; \ + result = ((UINT32)Wreg(DW) << 16) + Wreg(AW); \ result2 = result % (INT32)((INT16)tmp); \ if ((result /= (INT32)((INT16)tmp)) > 0xffff) { \ nec_interrupt(nec_state, 0,0); break; \ } else { \ - nec_state->regs.w[AW]=result; \ - nec_state->regs.w[DW]=result2; \ + Wreg(AW)=result; \ + Wreg(DW)=result2; \ } #define ADD4S { \ int i,v1,v2,result; \ - int count = (nec_state->regs.b[CL]+1)/2; \ - unsigned di = nec_state->regs.w[IY]; \ - unsigned si = nec_state->regs.w[IX]; \ + int count = (Breg(CL)+1)/2; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ static const UINT8 table[3]={18,19,19}; \ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for add4s\n",PC(nec_state)); \ nec_state->ZeroVal = nec_state->CarryVal = 0; \ @@ -327,10 +363,10 @@ typedef enum { } #define SUB4S { \ - int count = (nec_state->regs.b[CL]+1)/2; \ + int count = (Breg(CL)+1)/2; \ int i,v1,v2,result; \ - unsigned di = nec_state->regs.w[IY]; \ - unsigned si = nec_state->regs.w[IX]; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ static const UINT8 table[3]={18,19,19}; \ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for sub4s\n",PC(nec_state)); \ nec_state->ZeroVal = nec_state->CarryVal = 0; \ @@ -357,10 +393,10 @@ typedef enum { } #define CMP4S { \ - int count = (nec_state->regs.b[CL]+1)/2; \ + int count = (Breg(CL)+1)/2; \ int i,v1,v2,result; \ - unsigned di = nec_state->regs.w[IY]; \ - unsigned si = nec_state->regs.w[IX]; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ static const UINT8 table[3]={14,19,19}; \ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for cmp4s\n",PC(nec_state)); \ nec_state->ZeroVal = nec_state->CarryVal = 0; \ diff --git a/src/emu/cpu/nec/v25.c b/src/emu/cpu/nec/v25.c new file mode 100644 index 00000000000..f619de1426b --- /dev/null +++ b/src/emu/cpu/nec/v25.c @@ -0,0 +1,622 @@ +/**************************************************************************** + + NEC V25/V35 emulator + + --------------------------------------------- + + TODO: + + Using V20/V30 cycle counts for now. Cycle counts change + depending on whether the internal RAM access is enabled. + Also, the clock divider can be changed to 1/2, 1/4 or 1/8. + + IBRK flag (trap I/O instructions) included but not implemented. + + Most special function registers not implemented yet. + + It would be nice if the internal ram area was viewable in the debugger. + +****************************************************************************/ + +#include "emu.h" +#include "debugger.h" + +typedef UINT8 BOOLEAN; +typedef UINT8 BYTE; +typedef UINT16 WORD; +typedef UINT32 DWORD; + +#include "nec.h" +#include "v25priv.h" + +/* default configuration */ +static const nec_config default_config = +{ + NULL +}; + +extern int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *config); + +INLINE v25_state_t *get_safe_token(running_device *device) +{ + assert(device != NULL); + assert(device->type() == V25 || device->type() == V35); + return (v25_state_t *)downcast(device)->token(); +} + +/* The interrupt number of a pending external interrupt pending NMI is 2. */ +/* For INTR interrupts, the level is caught on the bus during an INTA cycle */ + +#define INT_IRQ 0x01 +#define NMI_IRQ 0x02 + +INLINE void prefetch(v25_state_t *nec_state) +{ + nec_state->prefetch_count--; +} + +static void do_prefetch(v25_state_t *nec_state, int previous_ICount) +{ + int diff = previous_ICount - (int) nec_state->icount; + + /* The implementation is not accurate, but comes close. + * It does not respect that the V30 will fetch two bytes + * at once directly, but instead uses only 2 cycles instead + * of 4. There are however only very few sources publicly + * available and they are vague. + */ + while (nec_state->prefetch_count<0) + { + nec_state->prefetch_count++; + if (diff>nec_state->prefetch_cycles) + diff -= nec_state->prefetch_cycles; + else + nec_state->icount -= nec_state->prefetch_cycles; + } + + if (nec_state->prefetch_reset) + { + nec_state->prefetch_count = 0; + nec_state->prefetch_reset = 0; + return; + } + + while (diff>=nec_state->prefetch_cycles && nec_state->prefetch_count < nec_state->prefetch_size) + { + diff -= nec_state->prefetch_cycles; + nec_state->prefetch_count++; + } + +} + +INLINE UINT8 fetch(v25_state_t *nec_state) +{ + prefetch(nec_state); + return nec_state->direct->read_raw_byte(FETCH_XOR((Sreg(PS)<<4)+nec_state->ip++)); +} + +INLINE UINT16 fetchword(v25_state_t *nec_state) +{ + UINT16 r = FETCH(); + r |= (FETCH()<<8); + return r; +} + +#define nec_state_t v25_state_t + +#include "v25instr.h" +#include "necea.h" +#include "necmodrm.h" + +static UINT8 parity_table[256]; + +static UINT8 fetchop(v25_state_t *nec_state) +{ + UINT8 ret; + + prefetch(nec_state); + ret = nec_state->direct->read_decrypted_byte(FETCH_XOR( ( Sreg(PS)<<4)+nec_state->ip++)); + + if (nec_state->MF == 0) + if (nec_state->config->v25v35_decryptiontable) + { + ret = nec_state->config->v25v35_decryptiontable[ret]; + } + return ret; +} + + + +/***************************************************************************/ + +static CPU_RESET( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + unsigned int i,j,c; + + static const WREGS wreg_name[8]={ AW, CW, DW, BW, SP, BP, IX, IY }; + static const BREGS breg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH }; + + memset( &nec_state->ram.w, 0, sizeof(nec_state->ram.w)); + + nec_state->ip = 0; + nec_state->IBRK = 1; + nec_state->F0 = 0; + nec_state->F1 = 0; + nec_state->TF = 0; + nec_state->IF = 0; + nec_state->DF = 0; + nec_state->RB = 7; + nec_state->SignVal = 0; + nec_state->int_vector = 0; + nec_state->pending_irq = 0; + nec_state->nmi_state = 0; + nec_state->irq_state = 0; + nec_state->poll_state = 0; + nec_state->mode_state = nec_state->MF = (nec_state->config->v25v35_decryptiontable) ? 0 : 1; + nec_state->AuxVal = 0; + nec_state->OverVal = 0; + nec_state->ZeroVal = 0; + nec_state->CarryVal = 0; + nec_state->ParityVal = 0; + + nec_state->PRC = 0x4E; + nec_state->IDB = 0xFF; + + Sreg(PS) = 0xffff; + + CHANGE_PC; + + for (i = 0;i < 256; i++) + { + for (j = i, c = 0; j > 0; j >>= 1) + if (j & 1) c++; + parity_table[i] = !(c & 1); + } + + nec_state->ZeroVal = nec_state->ParityVal = 1; + + for (i = 0; i < 256; i++) + { + Mod_RM.reg.b[i] = breg_name[(i & 0x38) >> 3]; + Mod_RM.reg.w[i] = wreg_name[(i & 0x38) >> 3]; + } + + for (i = 0xc0; i < 0x100; i++) + { + Mod_RM.RM.w[i] = wreg_name[i & 7]; + Mod_RM.RM.b[i] = breg_name[i & 7]; + } + + nec_state->poll_state = 1; +} + +static CPU_EXIT( v25 ) +{ + +} + +static void nec_interrupt(v25_state_t *nec_state, unsigned int_num, unsigned mode) +{ + UINT32 dest_seg, dest_off; + + i_pushf(nec_state); + nec_state->TF = nec_state->IF = 0; + + switch(mode) + { + case 0: + nec_state->MF = nec_state->mode_state; + break; + case 1: /* BRKN: force native mode */ + nec_state->MF = 1; + break; + case 2: /* BRKS: force secure mode */ + if (nec_state->config->v25v35_decryptiontable) + nec_state->MF = 0; + else + logerror("%06x: BRKS executed with no decryption table\n",PC(nec_state)); + } + + if (int_num == -1) + { + int_num = (*nec_state->irq_callback)(nec_state->device, 0); + + nec_state->irq_state = CLEAR_LINE; + nec_state->pending_irq &= ~INT_IRQ; + } + + dest_off = read_mem_word(int_num*4); + dest_seg = read_mem_word(int_num*4+2); + + PUSH(Sreg(PS)); + PUSH(nec_state->ip); + nec_state->ip = (WORD)dest_off; + Sreg(PS) = (WORD)dest_seg; + CHANGE_PC; +} + +static void nec_trap(v25_state_t *nec_state) +{ + nec_instruction[fetchop(nec_state)](nec_state); + nec_interrupt(nec_state, 1,0); +} + +static void external_int(v25_state_t *nec_state) +{ + if( nec_state->pending_irq & NMI_IRQ ) + { + nec_interrupt(nec_state, NEC_NMI_INT_VECTOR,0); + nec_state->pending_irq &= ~NMI_IRQ; + } + else if( nec_state->pending_irq ) + { + /* the actual vector is retrieved after pushing flags */ + /* and clearing the IF */ + nec_interrupt(nec_state, (UINT32)-1,0); + } +} + +/****************************************************************************/ +/* OPCODES */ +/****************************************************************************/ + +#include "necinstr.c" +#include "v25instr.c" + +/*****************************************************************************/ + +static void set_irq_line(v25_state_t *nec_state, int irqline, int state) +{ + if (irqline == INPUT_LINE_NMI) + { + if( nec_state->nmi_state == state ) return; + nec_state->nmi_state = state; + if (state != CLEAR_LINE) + { + nec_state->pending_irq |= NMI_IRQ; + } + } + else + { + nec_state->irq_state = state; + if (state == CLEAR_LINE) + { + // if (!nec_state->IF) NS010718 fix interrupt request loss + nec_state->pending_irq &= ~INT_IRQ; + } + else + { + // if (nec_state->IF) NS010718 fix interrupt request loss + nec_state->pending_irq |= INT_IRQ; + } + } +} + +static void set_poll_line(v25_state_t *nec_state, int state) +{ + nec_state->poll_state = state; +} + +static CPU_DISASSEMBLE( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + + return necv_dasm_one(buffer, pc, oprom, nec_state->config); +} + +static void v25_init(legacy_cpu_device *device, device_irq_callback irqcallback, int type) +{ + const nec_config *config = device->baseconfig().static_config() ? (const nec_config *)device->baseconfig().static_config() : &default_config; + v25_state_t *nec_state = get_safe_token(device); + + nec_state->config = config; + + + state_save_register_device_item_array(device, 0, nec_state->ram.w); + + state_save_register_device_item(device, 0, nec_state->ip); + state_save_register_device_item(device, 0, nec_state->IBRK); + state_save_register_device_item(device, 0, nec_state->F0); + state_save_register_device_item(device, 0, nec_state->F1); + state_save_register_device_item(device, 0, nec_state->TF); + state_save_register_device_item(device, 0, nec_state->IF); + state_save_register_device_item(device, 0, nec_state->DF); + state_save_register_device_item(device, 0, nec_state->MF); + state_save_register_device_item(device, 0, nec_state->RB); + state_save_register_device_item(device, 0, nec_state->PRC); + state_save_register_device_item(device, 0, nec_state->IDB); + state_save_register_device_item(device, 0, nec_state->SignVal); + state_save_register_device_item(device, 0, nec_state->int_vector); + state_save_register_device_item(device, 0, nec_state->pending_irq); + state_save_register_device_item(device, 0, nec_state->nmi_state); + state_save_register_device_item(device, 0, nec_state->irq_state); + state_save_register_device_item(device, 0, nec_state->poll_state); + state_save_register_device_item(device, 0, nec_state->mode_state); + state_save_register_device_item(device, 0, nec_state->AuxVal); + state_save_register_device_item(device, 0, nec_state->OverVal); + state_save_register_device_item(device, 0, nec_state->ZeroVal); + state_save_register_device_item(device, 0, nec_state->CarryVal); + state_save_register_device_item(device, 0, nec_state->ParityVal); + + nec_state->irq_callback = irqcallback; + nec_state->device = device; + nec_state->program = device->space(AS_PROGRAM); + nec_state->direct = &nec_state->program->direct(); + nec_state->io = device->space(AS_IO); +} + + + +static CPU_EXECUTE( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + int prev_ICount; + + while(nec_state->icount>0) { + /* Dispatch IRQ */ + if (nec_state->pending_irq && nec_state->no_interrupt==0) + { + if (nec_state->pending_irq & NMI_IRQ) + external_int(nec_state); + else if (nec_state->IF) + external_int(nec_state); + } + + /* No interrupt allowed between last instruction and this one */ + if (nec_state->no_interrupt) + nec_state->no_interrupt--; + + debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip); + prev_ICount = nec_state->icount; + nec_instruction[fetchop(nec_state)](nec_state); + do_prefetch(nec_state, prev_ICount); + } +} + +/* Wrappers for the different CPU types */ +static CPU_INIT( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + + v25_init(device, irqcallback, 0); + nec_state->fetch_xor = 0; + nec_state->chip_type=V20_TYPE; + nec_state->prefetch_size = 4; /* 3 words */ + nec_state->prefetch_cycles = 4; /* four cycles per byte */ +} + +static CPU_INIT( v35 ) +{ + v25_state_t *nec_state = get_safe_token(device); + + v25_init(device, irqcallback, 1); + nec_state->fetch_xor = BYTE_XOR_LE(0); + nec_state->chip_type=V30_TYPE; + nec_state->prefetch_size = 6; /* 3 words */ + nec_state->prefetch_cycles = 2; /* two cycles per byte / four per word */ + +} + + + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static CPU_SET_INFO( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_poll_line(nec_state, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: + if( info->i - (Sreg(PS)<<4) < 0x10000 ) + { + nec_state->ip = info->i - (Sreg(PS)<<4); + } + else + { + Sreg(PS) = info->i >> 4; + nec_state->ip = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break; + case CPUINFO_INT_SP: + if( info->i - (Sreg(SS)<<4) < 0x10000 ) + { + Wreg(SP) = info->i - (Sreg(SS)<<4); + } + else + { + Sreg(SS) = info->i >> 4; + Wreg(SP) = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break; + case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_VECTOR: nec_state->int_vector = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static CPU_GET_INFO( v25v35 ) +{ + v25_state_t *nec_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + int flags; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(v25_state_t); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 80; break; + + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 20; break; + case DEVINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: info->i = (nec_state->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = nec_state->nmi_state; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: info->i = nec_state->poll_state; break; + + case CPUINFO_INT_PREVIOUSPC: /* not supported */ break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break; + case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break; + case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break; + case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break; + case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break; + case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break; + case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break; + case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break; + case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break; + case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break; + case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break; + case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break; + case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break; + case CPUINFO_INT_REGISTER + NEC_VECTOR: info->i = nec_state->int_vector; break; + case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(v25); break; + case CPUINFO_FCT_INIT: /* set per-CPU */ break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(v25); break; + case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(v25); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v25); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v25); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "NEC"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Alex W. Jackson, based on NEC V emulator by Bryan McPhail"); break; + + case CPUINFO_STR_FLAGS: + flags = CompressFlags(); + sprintf(info->s, "%c %d %c%c%c%c%c%c%c%c%c%c%c%c", + flags & 0x8000 ? 'N':'S', + (flags & 0x7000) >> 12, + flags & 0x0800 ? 'O':'.', + flags & 0x0400 ? 'D':'.', + flags & 0x0200 ? 'I':'.', + flags & 0x0100 ? 'T':'.', + flags & 0x0080 ? 'S':'.', + flags & 0x0040 ? 'Z':'.', + flags & 0x0020 ? '1':'.', + flags & 0x0010 ? 'A':'.', + flags & 0x0008 ? '0':'.', + flags & 0x0004 ? 'P':'.', + flags & 0x0002 ? '.':'I', + flags & 0x0001 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%04X", (Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break; + case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break; + case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break; + case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break; + case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break; + case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break; + case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break; + case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break; + case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break; + case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break; + case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break; + case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break; + case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break; + case CPUINFO_STR_REGISTER + NEC_VECTOR: sprintf(info->s, "V:%02X", nec_state->int_vector); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v25 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v25); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V25"); break; + + default: CPU_GET_INFO_CALL(v25v35); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v35 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v35); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V35"); break; + + default: CPU_GET_INFO_CALL(v25v35); break; + } +} + +DEFINE_LEGACY_CPU_DEVICE(V25, v25); +DEFINE_LEGACY_CPU_DEVICE(V35, v35); diff --git a/src/emu/cpu/nec/v25instr.c b/src/emu/cpu/nec/v25instr.c new file mode 100644 index 00000000000..ee16098bb9b --- /dev/null +++ b/src/emu/cpu/nec/v25instr.c @@ -0,0 +1,34 @@ +OP( 0x0f, i_pre_v25 ) { UINT32 ModRM, tmp, tmp2; + switch (FETCH()) { + case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; + case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; + case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(nec_state)); break; + case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(nec_state)); break; + case 0x92 : CLK(2); break; /* V25/35 FINT */ + default: logerror("%06x: Unknown V25 instruction\n",PC(nec_state)); break; + } +} + +OP( 0x63, i_brkn ) { nec_interrupt(nec_state, FETCH(),1); CLKS(50,50,24); } +OP( 0xF1, i_brks ) { nec_interrupt(nec_state, FETCH(),2); CLKS(50,50,24); } diff --git a/src/emu/cpu/nec/v25instr.h b/src/emu/cpu/nec/v25instr.h new file mode 100644 index 00000000000..77a8503bc2f --- /dev/null +++ b/src/emu/cpu/nec/v25instr.h @@ -0,0 +1,510 @@ +static void i_add_br8(nec_state_t *nec_state); +static void i_add_wr16(nec_state_t *nec_state); +static void i_add_r8b(nec_state_t *nec_state); +static void i_add_r16w(nec_state_t *nec_state); +static void i_add_ald8(nec_state_t *nec_state); +static void i_add_axd16(nec_state_t *nec_state); +static void i_push_es(nec_state_t *nec_state); +static void i_pop_es(nec_state_t *nec_state); +static void i_or_br8(nec_state_t *nec_state); +static void i_or_r8b(nec_state_t *nec_state); +static void i_or_wr16(nec_state_t *nec_state); +static void i_or_r16w(nec_state_t *nec_state); +static void i_or_ald8(nec_state_t *nec_state); +static void i_or_axd16(nec_state_t *nec_state); +static void i_push_cs(nec_state_t *nec_state); +ATTR_UNUSED static void i_pre_nec(nec_state_t *nec_state); +static void i_pre_v25(nec_state_t *nec_state); +static void i_adc_br8(nec_state_t *nec_state); +static void i_adc_wr16(nec_state_t *nec_state); +static void i_adc_r8b(nec_state_t *nec_state); +static void i_adc_r16w(nec_state_t *nec_state); +static void i_adc_ald8(nec_state_t *nec_state); +static void i_adc_axd16(nec_state_t *nec_state); +static void i_push_ss(nec_state_t *nec_state); +static void i_pop_ss(nec_state_t *nec_state); +static void i_sbb_br8(nec_state_t *nec_state); +static void i_sbb_wr16(nec_state_t *nec_state); +static void i_sbb_r8b(nec_state_t *nec_state); +static void i_sbb_r16w(nec_state_t *nec_state); +static void i_sbb_ald8(nec_state_t *nec_state); +static void i_sbb_axd16(nec_state_t *nec_state); +static void i_push_ds(nec_state_t *nec_state); +static void i_pop_ds(nec_state_t *nec_state); +static void i_and_br8(nec_state_t *nec_state); +static void i_and_r8b(nec_state_t *nec_state); +static void i_and_wr16(nec_state_t *nec_state); +static void i_and_r16w(nec_state_t *nec_state); +static void i_and_ald8(nec_state_t *nec_state); +static void i_and_axd16(nec_state_t *nec_state); +static void i_es(nec_state_t *nec_state); +static void i_daa(nec_state_t *nec_state); +static void i_sub_br8(nec_state_t *nec_state); +static void i_sub_wr16(nec_state_t *nec_state); +static void i_sub_r8b(nec_state_t *nec_state); +static void i_sub_r16w(nec_state_t *nec_state); +static void i_sub_ald8(nec_state_t *nec_state); +static void i_sub_axd16(nec_state_t *nec_state); +static void i_cs(nec_state_t *nec_state); +static void i_das(nec_state_t *nec_state); +static void i_xor_br8(nec_state_t *nec_state); +static void i_xor_r8b(nec_state_t *nec_state); +static void i_xor_wr16(nec_state_t *nec_state); +static void i_xor_r16w(nec_state_t *nec_state); +static void i_xor_ald8(nec_state_t *nec_state); +static void i_xor_axd16(nec_state_t *nec_state); +static void i_ss(nec_state_t *nec_state); +static void i_aaa(nec_state_t *nec_state); +static void i_cmp_br8(nec_state_t *nec_state); +static void i_cmp_wr16(nec_state_t *nec_state); +static void i_cmp_r8b(nec_state_t *nec_state); +static void i_cmp_r16w(nec_state_t *nec_state); +static void i_cmp_ald8(nec_state_t *nec_state); +static void i_cmp_axd16(nec_state_t *nec_state); +static void i_ds(nec_state_t *nec_state); +static void i_aas(nec_state_t *nec_state); +static void i_inc_ax(nec_state_t *nec_state); +static void i_inc_cx(nec_state_t *nec_state); +static void i_inc_dx(nec_state_t *nec_state); +static void i_inc_bx(nec_state_t *nec_state); +static void i_inc_sp(nec_state_t *nec_state); +static void i_inc_bp(nec_state_t *nec_state); +static void i_inc_si(nec_state_t *nec_state); +static void i_inc_di(nec_state_t *nec_state); +static void i_dec_ax(nec_state_t *nec_state); +static void i_dec_cx(nec_state_t *nec_state); +static void i_dec_dx(nec_state_t *nec_state); +static void i_dec_bx(nec_state_t *nec_state); +static void i_dec_sp(nec_state_t *nec_state); +static void i_dec_bp(nec_state_t *nec_state); +static void i_dec_si(nec_state_t *nec_state); +static void i_dec_di(nec_state_t *nec_state); +static void i_push_ax(nec_state_t *nec_state); +static void i_push_cx(nec_state_t *nec_state); +static void i_push_dx(nec_state_t *nec_state); +static void i_push_bx(nec_state_t *nec_state); +static void i_push_sp(nec_state_t *nec_state); +static void i_push_bp(nec_state_t *nec_state); +static void i_push_si(nec_state_t *nec_state); +static void i_push_di(nec_state_t *nec_state); +static void i_pop_ax(nec_state_t *nec_state); +static void i_pop_cx(nec_state_t *nec_state); +static void i_pop_dx(nec_state_t *nec_state); +static void i_pop_bx(nec_state_t *nec_state); +static void i_pop_sp(nec_state_t *nec_state); +static void i_pop_bp(nec_state_t *nec_state); +static void i_pop_si(nec_state_t *nec_state); +static void i_pop_di(nec_state_t *nec_state); +static void i_pusha(nec_state_t *nec_state); +static void i_popa(nec_state_t *nec_state); +static void i_chkind(nec_state_t *nec_state); +static void i_brkn(nec_state_t *nec_state); +static void i_repnc(nec_state_t *nec_state); +static void i_repc(nec_state_t *nec_state); +static void i_push_d16(nec_state_t *nec_state); +static void i_imul_d16(nec_state_t *nec_state); +static void i_push_d8(nec_state_t *nec_state); +static void i_imul_d8(nec_state_t *nec_state); +static void i_insb(nec_state_t *nec_state); +static void i_insw(nec_state_t *nec_state); +static void i_outsb(nec_state_t *nec_state); +static void i_outsw(nec_state_t *nec_state); +static void i_jo(nec_state_t *nec_state); +static void i_jno(nec_state_t *nec_state); +static void i_jc(nec_state_t *nec_state); +static void i_jnc(nec_state_t *nec_state); +static void i_jz(nec_state_t *nec_state); +static void i_jnz(nec_state_t *nec_state); +static void i_jce(nec_state_t *nec_state); +static void i_jnce(nec_state_t *nec_state); +static void i_js(nec_state_t *nec_state); +static void i_jns(nec_state_t *nec_state); +static void i_jp(nec_state_t *nec_state); +static void i_jnp(nec_state_t *nec_state); +static void i_jl(nec_state_t *nec_state); +static void i_jnl(nec_state_t *nec_state); +static void i_jle(nec_state_t *nec_state); +static void i_jnle(nec_state_t *nec_state); +static void i_80pre(nec_state_t *nec_state); +static void i_82pre(nec_state_t *nec_state); +static void i_81pre(nec_state_t *nec_state); +static void i_83pre(nec_state_t *nec_state); +static void i_test_br8(nec_state_t *nec_state); +static void i_test_wr16(nec_state_t *nec_state); +static void i_xchg_br8(nec_state_t *nec_state); +static void i_xchg_wr16(nec_state_t *nec_state); +static void i_mov_br8(nec_state_t *nec_state); +static void i_mov_r8b(nec_state_t *nec_state); +static void i_mov_wr16(nec_state_t *nec_state); +static void i_mov_r16w(nec_state_t *nec_state); +static void i_mov_wsreg(nec_state_t *nec_state); +static void i_lea(nec_state_t *nec_state); +static void i_mov_sregw(nec_state_t *nec_state); +static void i_invalid(nec_state_t *nec_state); +static void i_popw(nec_state_t *nec_state); +static void i_nop(nec_state_t *nec_state); +static void i_xchg_axcx(nec_state_t *nec_state); +static void i_xchg_axdx(nec_state_t *nec_state); +static void i_xchg_axbx(nec_state_t *nec_state); +static void i_xchg_axsp(nec_state_t *nec_state); +static void i_xchg_axbp(nec_state_t *nec_state); +static void i_xchg_axsi(nec_state_t *nec_state); +static void i_xchg_axdi(nec_state_t *nec_state); +static void i_cbw(nec_state_t *nec_state); +static void i_cwd(nec_state_t *nec_state); +static void i_call_far(nec_state_t *nec_state); +static void i_pushf(nec_state_t *nec_state); +static void i_popf(nec_state_t *nec_state); +static void i_sahf(nec_state_t *nec_state); +static void i_lahf(nec_state_t *nec_state); +static void i_mov_aldisp(nec_state_t *nec_state); +static void i_mov_axdisp(nec_state_t *nec_state); +static void i_mov_dispal(nec_state_t *nec_state); +static void i_mov_dispax(nec_state_t *nec_state); +static void i_movsb(nec_state_t *nec_state); +static void i_movsw(nec_state_t *nec_state); +static void i_cmpsb(nec_state_t *nec_state); +static void i_cmpsw(nec_state_t *nec_state); +static void i_test_ald8(nec_state_t *nec_state); +static void i_test_axd16(nec_state_t *nec_state); +static void i_stosb(nec_state_t *nec_state); +static void i_stosw(nec_state_t *nec_state); +static void i_lodsb(nec_state_t *nec_state); +static void i_lodsw(nec_state_t *nec_state); +static void i_scasb(nec_state_t *nec_state); +static void i_scasw(nec_state_t *nec_state); +static void i_mov_ald8(nec_state_t *nec_state); +static void i_mov_cld8(nec_state_t *nec_state); +static void i_mov_dld8(nec_state_t *nec_state); +static void i_mov_bld8(nec_state_t *nec_state); +static void i_mov_ahd8(nec_state_t *nec_state); +static void i_mov_chd8(nec_state_t *nec_state); +static void i_mov_dhd8(nec_state_t *nec_state); +static void i_mov_bhd8(nec_state_t *nec_state); +static void i_mov_axd16(nec_state_t *nec_state); +static void i_mov_cxd16(nec_state_t *nec_state); +static void i_mov_dxd16(nec_state_t *nec_state); +static void i_mov_bxd16(nec_state_t *nec_state); +static void i_mov_spd16(nec_state_t *nec_state); +static void i_mov_bpd16(nec_state_t *nec_state); +static void i_mov_sid16(nec_state_t *nec_state); +static void i_mov_did16(nec_state_t *nec_state); +static void i_rotshft_bd8(nec_state_t *nec_state); +static void i_rotshft_wd8(nec_state_t *nec_state); +static void i_ret_d16(nec_state_t *nec_state); +static void i_ret(nec_state_t *nec_state); +static void i_les_dw(nec_state_t *nec_state); +static void i_lds_dw(nec_state_t *nec_state); +static void i_mov_bd8(nec_state_t *nec_state); +static void i_mov_wd16(nec_state_t *nec_state); +static void i_enter(nec_state_t *nec_state); +static void i_leave(nec_state_t *nec_state); +static void i_retf_d16(nec_state_t *nec_state); +static void i_retf(nec_state_t *nec_state); +static void i_int3(nec_state_t *nec_state); +static void i_int(nec_state_t *nec_state); +static void i_into(nec_state_t *nec_state); +static void i_iret(nec_state_t *nec_state); +static void i_rotshft_b(nec_state_t *nec_state); +static void i_rotshft_w(nec_state_t *nec_state); +static void i_rotshft_bcl(nec_state_t *nec_state); +static void i_rotshft_wcl(nec_state_t *nec_state); +static void i_aam(nec_state_t *nec_state); +static void i_aad(nec_state_t *nec_state); +static void i_setalc(nec_state_t *nec_state); +static void i_trans(nec_state_t *nec_state); +static void i_fpo(nec_state_t *nec_state); +static void i_loopne(nec_state_t *nec_state); +static void i_loope(nec_state_t *nec_state); +static void i_loop(nec_state_t *nec_state); +static void i_jcxz(nec_state_t *nec_state); +static void i_inal(nec_state_t *nec_state); +static void i_inax(nec_state_t *nec_state); +static void i_outal(nec_state_t *nec_state); +static void i_outax(nec_state_t *nec_state); +static void i_call_d16(nec_state_t *nec_state); +static void i_jmp_d16(nec_state_t *nec_state); +static void i_jmp_far(nec_state_t *nec_state); +static void i_jmp_d8(nec_state_t *nec_state); +static void i_inaldx(nec_state_t *nec_state); +static void i_inaxdx(nec_state_t *nec_state); +static void i_outdxal(nec_state_t *nec_state); +static void i_outdxax(nec_state_t *nec_state); +static void i_lock(nec_state_t *nec_state); +static void i_brks(nec_state_t *nec_state); +static void i_repne(nec_state_t *nec_state); +static void i_repe(nec_state_t *nec_state); +static void i_hlt(nec_state_t *nec_state); +static void i_cmc(nec_state_t *nec_state); +static void i_f6pre(nec_state_t *nec_state); +static void i_f7pre(nec_state_t *nec_state); +static void i_clc(nec_state_t *nec_state); +static void i_stc(nec_state_t *nec_state); +static void i_di(nec_state_t *nec_state); +static void i_ei(nec_state_t *nec_state); +static void i_cld(nec_state_t *nec_state); +static void i_std(nec_state_t *nec_state); +static void i_fepre(nec_state_t *nec_state); +static void i_ffpre(nec_state_t *nec_state); + +static void i_wait(nec_state_t *nec_state); + +static void (*const nec_instruction[256])(nec_state_t *nec_state) = +{ + i_add_br8, /* 0x00 */ + i_add_wr16, /* 0x01 */ + i_add_r8b, /* 0x02 */ + i_add_r16w, /* 0x03 */ + i_add_ald8, /* 0x04 */ + i_add_axd16, /* 0x05 */ + i_push_es, /* 0x06 */ + i_pop_es, /* 0x07 */ + i_or_br8, /* 0x08 */ + i_or_wr16, /* 0x09 */ + i_or_r8b, /* 0x0a */ + i_or_r16w, /* 0x0b */ + i_or_ald8, /* 0x0c */ + i_or_axd16, /* 0x0d */ + i_push_cs, /* 0x0e */ + i_pre_v25, /* 0x0f */ + i_adc_br8, /* 0x10 */ + i_adc_wr16, /* 0x11 */ + i_adc_r8b, /* 0x12 */ + i_adc_r16w, /* 0x13 */ + i_adc_ald8, /* 0x14 */ + i_adc_axd16, /* 0x15 */ + i_push_ss, /* 0x16 */ + i_pop_ss, /* 0x17 */ + i_sbb_br8, /* 0x18 */ + i_sbb_wr16, /* 0x19 */ + i_sbb_r8b, /* 0x1a */ + i_sbb_r16w, /* 0x1b */ + i_sbb_ald8, /* 0x1c */ + i_sbb_axd16, /* 0x1d */ + i_push_ds, /* 0x1e */ + i_pop_ds, /* 0x1f */ + i_and_br8, /* 0x20 */ + i_and_wr16, /* 0x21 */ + i_and_r8b, /* 0x22 */ + i_and_r16w, /* 0x23 */ + i_and_ald8, /* 0x24 */ + i_and_axd16, /* 0x25 */ + i_es, /* 0x26 */ + i_daa, /* 0x27 */ + i_sub_br8, /* 0x28 */ + i_sub_wr16, /* 0x29 */ + i_sub_r8b, /* 0x2a */ + i_sub_r16w, /* 0x2b */ + i_sub_ald8, /* 0x2c */ + i_sub_axd16, /* 0x2d */ + i_cs, /* 0x2e */ + i_das, /* 0x2f */ + i_xor_br8, /* 0x30 */ + i_xor_wr16, /* 0x31 */ + i_xor_r8b, /* 0x32 */ + i_xor_r16w, /* 0x33 */ + i_xor_ald8, /* 0x34 */ + i_xor_axd16, /* 0x35 */ + i_ss, /* 0x36 */ + i_aaa, /* 0x37 */ + i_cmp_br8, /* 0x38 */ + i_cmp_wr16, /* 0x39 */ + i_cmp_r8b, /* 0x3a */ + i_cmp_r16w, /* 0x3b */ + i_cmp_ald8, /* 0x3c */ + i_cmp_axd16, /* 0x3d */ + i_ds, /* 0x3e */ + i_aas, /* 0x3f */ + i_inc_ax, /* 0x40 */ + i_inc_cx, /* 0x41 */ + i_inc_dx, /* 0x42 */ + i_inc_bx, /* 0x43 */ + i_inc_sp, /* 0x44 */ + i_inc_bp, /* 0x45 */ + i_inc_si, /* 0x46 */ + i_inc_di, /* 0x47 */ + i_dec_ax, /* 0x48 */ + i_dec_cx, /* 0x49 */ + i_dec_dx, /* 0x4a */ + i_dec_bx, /* 0x4b */ + i_dec_sp, /* 0x4c */ + i_dec_bp, /* 0x4d */ + i_dec_si, /* 0x4e */ + i_dec_di, /* 0x4f */ + i_push_ax, /* 0x50 */ + i_push_cx, /* 0x51 */ + i_push_dx, /* 0x52 */ + i_push_bx, /* 0x53 */ + i_push_sp, /* 0x54 */ + i_push_bp, /* 0x55 */ + i_push_si, /* 0x56 */ + i_push_di, /* 0x57 */ + i_pop_ax, /* 0x58 */ + i_pop_cx, /* 0x59 */ + i_pop_dx, /* 0x5a */ + i_pop_bx, /* 0x5b */ + i_pop_sp, /* 0x5c */ + i_pop_bp, /* 0x5d */ + i_pop_si, /* 0x5e */ + i_pop_di, /* 0x5f */ + i_pusha, /* 0x60 */ + i_popa, /* 0x61 */ + i_chkind, /* 0x62 */ + i_brkn, /* 0x63 - V25S/V35S only */ + i_repnc, /* 0x64 */ + i_repc, /* 0x65 */ + i_invalid, /* 0x66 */ + i_invalid, /* 0x67 */ + i_push_d16, /* 0x68 */ + i_imul_d16, /* 0x69 */ + i_push_d8, /* 0x6a */ + i_imul_d8, /* 0x6b */ + i_insb, /* 0x6c */ + i_insw, /* 0x6d */ + i_outsb, /* 0x6e */ + i_outsw, /* 0x6f */ + i_jo, /* 0x70 */ + i_jno, /* 0x71 */ + i_jc, /* 0x72 */ + i_jnc, /* 0x73 */ + i_jz, /* 0x74 */ + i_jnz, /* 0x75 */ + i_jce, /* 0x76 */ + i_jnce, /* 0x77 */ + i_js, /* 0x78 */ + i_jns, /* 0x79 */ + i_jp, /* 0x7a */ + i_jnp, /* 0x7b */ + i_jl, /* 0x7c */ + i_jnl, /* 0x7d */ + i_jle, /* 0x7e */ + i_jnle, /* 0x7f */ + i_80pre, /* 0x80 */ + i_81pre, /* 0x81 */ + i_82pre, /* 0x82 */ + i_83pre, /* 0x83 */ + i_test_br8, /* 0x84 */ + i_test_wr16, /* 0x85 */ + i_xchg_br8, /* 0x86 */ + i_xchg_wr16, /* 0x87 */ + i_mov_br8, /* 0x88 */ + i_mov_wr16, /* 0x89 */ + i_mov_r8b, /* 0x8a */ + i_mov_r16w, /* 0x8b */ + i_mov_wsreg, /* 0x8c */ + i_lea, /* 0x8d */ + i_mov_sregw, /* 0x8e */ + i_popw, /* 0x8f */ + i_nop, /* 0x90 */ + i_xchg_axcx, /* 0x91 */ + i_xchg_axdx, /* 0x92 */ + i_xchg_axbx, /* 0x93 */ + i_xchg_axsp, /* 0x94 */ + i_xchg_axbp, /* 0x95 */ + i_xchg_axsi, /* 0x96 */ + i_xchg_axdi, /* 0x97 */ + i_cbw, /* 0x98 */ + i_cwd, /* 0x99 */ + i_call_far, /* 0x9a */ + i_wait, /* 0x9b */ + i_pushf, /* 0x9c */ + i_popf, /* 0x9d */ + i_sahf, /* 0x9e */ + i_lahf, /* 0x9f */ + i_mov_aldisp, /* 0xa0 */ + i_mov_axdisp, /* 0xa1 */ + i_mov_dispal, /* 0xa2 */ + i_mov_dispax, /* 0xa3 */ + i_movsb, /* 0xa4 */ + i_movsw, /* 0xa5 */ + i_cmpsb, /* 0xa6 */ + i_cmpsw, /* 0xa7 */ + i_test_ald8, /* 0xa8 */ + i_test_axd16, /* 0xa9 */ + i_stosb, /* 0xaa */ + i_stosw, /* 0xab */ + i_lodsb, /* 0xac */ + i_lodsw, /* 0xad */ + i_scasb, /* 0xae */ + i_scasw, /* 0xaf */ + i_mov_ald8, /* 0xb0 */ + i_mov_cld8, /* 0xb1 */ + i_mov_dld8, /* 0xb2 */ + i_mov_bld8, /* 0xb3 */ + i_mov_ahd8, /* 0xb4 */ + i_mov_chd8, /* 0xb5 */ + i_mov_dhd8, /* 0xb6 */ + i_mov_bhd8, /* 0xb7 */ + i_mov_axd16, /* 0xb8 */ + i_mov_cxd16, /* 0xb9 */ + i_mov_dxd16, /* 0xba */ + i_mov_bxd16, /* 0xbb */ + i_mov_spd16, /* 0xbc */ + i_mov_bpd16, /* 0xbd */ + i_mov_sid16, /* 0xbe */ + i_mov_did16, /* 0xbf */ + i_rotshft_bd8, /* 0xc0 */ + i_rotshft_wd8, /* 0xc1 */ + i_ret_d16, /* 0xc2 */ + i_ret, /* 0xc3 */ + i_les_dw, /* 0xc4 */ + i_lds_dw, /* 0xc5 */ + i_mov_bd8, /* 0xc6 */ + i_mov_wd16, /* 0xc7 */ + i_enter, /* 0xc8 */ + i_leave, /* 0xc9 */ + i_retf_d16, /* 0xca */ + i_retf, /* 0xcb */ + i_int3, /* 0xcc */ + i_int, /* 0xcd */ + i_into, /* 0xce */ + i_iret, /* 0xcf */ + i_rotshft_b, /* 0xd0 */ + i_rotshft_w, /* 0xd1 */ + i_rotshft_bcl, /* 0xd2 */ + i_rotshft_wcl, /* 0xd3 */ + i_aam, /* 0xd4 */ + i_aad, /* 0xd5 */ + i_setalc, /* 0xd6 */ + i_trans, /* 0xd7 */ + i_fpo, /* 0xd8 */ + i_fpo, /* 0xd9 */ + i_fpo, /* 0xda */ + i_fpo, /* 0xdb */ + i_fpo, /* 0xdc */ + i_fpo, /* 0xdd */ + i_fpo, /* 0xde */ + i_fpo, /* 0xdf */ + i_loopne, /* 0xe0 */ + i_loope, /* 0xe1 */ + i_loop, /* 0xe2 */ + i_jcxz, /* 0xe3 */ + i_inal, /* 0xe4 */ + i_inax, /* 0xe5 */ + i_outal, /* 0xe6 */ + i_outax, /* 0xe7 */ + i_call_d16, /* 0xe8 */ + i_jmp_d16, /* 0xe9 */ + i_jmp_far, /* 0xea */ + i_jmp_d8, /* 0xeb */ + i_inaldx, /* 0xec */ + i_inaxdx, /* 0xed */ + i_outdxal, /* 0xee */ + i_outdxax, /* 0xef */ + i_lock, /* 0xf0 */ + i_brks, /* 0xf1 */ + i_repne, /* 0xf2 */ + i_repe, /* 0xf3 */ + i_hlt, /* 0xf4 */ + i_cmc, /* 0xf5 */ + i_f6pre, /* 0xf6 */ + i_f7pre, /* 0xf7 */ + i_clc, /* 0xf8 */ + i_stc, /* 0xf9 */ + i_di, /* 0xfa */ + i_ei, /* 0xfb */ + i_cld, /* 0xfc */ + i_std, /* 0xfd */ + i_fepre, /* 0xfe */ + i_ffpre /* 0xff */ +}; diff --git a/src/emu/cpu/nec/v25priv.h b/src/emu/cpu/nec/v25priv.h new file mode 100644 index 00000000000..fbf292ade41 --- /dev/null +++ b/src/emu/cpu/nec/v25priv.h @@ -0,0 +1,455 @@ +#define NEC_NMI_INT_VECTOR 2 + +/* Cpu types, steps of 8 to help the cycle count calculation */ +#define V33_TYPE 0 +#define V30_TYPE 8 +#define V20_TYPE 16 + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/* internal RAM and register banks */ +typedef union +{ + UINT16 w[128]; + UINT8 b[256]; +} internalram; + +typedef struct _v25_state_t v25_state_t; +struct _v25_state_t +{ + internalram ram; + offs_t fetch_xor; + + UINT16 ip; + + INT32 SignVal; + UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ + UINT8 IBRK, F0, F1, TF, IF, DF, MF; /* 0 or 1 valued flags */ + UINT8 RB; /* current register bank */ + UINT32 int_vector; + UINT32 pending_irq; + UINT32 nmi_state; + UINT32 irq_state; + UINT32 poll_state; + UINT32 mode_state; + UINT8 no_interrupt; + + /* special function registers */ + UINT8 PRC, IDB; + + device_irq_callback irq_callback; + legacy_cpu_device *device; + address_space *program; + direct_read_data *direct; + address_space *io; + int icount; + + const nec_config *config; + + UINT8 prefetch_size; + UINT8 prefetch_cycles; + INT8 prefetch_count; + UINT8 prefetch_reset; + UINT32 chip_type; + + UINT32 prefix_base; /* base address of the latest prefix segment */ + UINT8 seg_prefix; /* prefix segment indicator */ +}; + +typedef enum { + DS1 = 0x0E/2, + PS = 0x0C/2, + SS = 0x0A/2, + DS0 = 0x08/2, +} SREGS; + +typedef enum { + AW = 0x1E/2, + CW = 0x1C/2, + DW = 0x1A/2, + BW = 0x18/2, + SP = 0x16/2, + BP = 0x14/2, + IX = 0x12/2, + IY = 0x10/2, +} WREGS; + +typedef enum { + AL = NATIVE_ENDIAN_VALUE_LE_BE(0x1E, 0x1F), + AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1F, 0x1E), + CL = NATIVE_ENDIAN_VALUE_LE_BE(0x1C, 0x1D), + CH = NATIVE_ENDIAN_VALUE_LE_BE(0x1D, 0x1C), + DL = NATIVE_ENDIAN_VALUE_LE_BE(0x1A, 0x1B), + DH = NATIVE_ENDIAN_VALUE_LE_BE(0x1B, 0x1A), + BL = NATIVE_ENDIAN_VALUE_LE_BE(0x18, 0x19), + BH = NATIVE_ENDIAN_VALUE_LE_BE(0x19, 0x18), +} BREGS; + +#define Sreg(x) nec_state->ram.w[(nec_state->RB << 4) + (x)] +#define Wreg(x) nec_state->ram.w[(nec_state->RB << 4) + (x)] +#define Breg(x) nec_state->ram.b[(nec_state->RB << 5) + (x)] + +#define PC(n) ((Sreg(PS)<<4)+(n)->ip) + +/* parameter x = result, y = source 1, z = source 2 */ + +#define SetTF(x) (nec_state->TF = (x)) +#define SetIF(x) (nec_state->IF = (x)) +#define SetDF(x) (nec_state->DF = (x)) +#define SetMD(x) (nec_state->MF = (x)) /* OB [19.07.99] Mode Flag V30 */ + +#define SetCFB(x) (nec_state->CarryVal = (x) & 0x100) +#define SetCFW(x) (nec_state->CarryVal = (x) & 0x10000) +#define SetAF(x,y,z) (nec_state->AuxVal = ((x) ^ ((y) ^ (z))) & 0x10) +#define SetSF(x) (nec_state->SignVal = (x)) +#define SetZF(x) (nec_state->ZeroVal = (x)) +#define SetPF(x) (nec_state->ParityVal = (x)) + +#define SetSZPF_Byte(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT8)(x)) +#define SetSZPF_Word(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT16)(x)) + +#define SetOFW_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000) +#define SetOFB_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80) +#define SetOFW_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000) +#define SetOFB_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80) + +#define ADDB { UINT32 res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; } +#define ADDW { UINT32 res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; } + +#define SUBB { UINT32 res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; } +#define SUBW { UINT32 res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; } + +#define ORB dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define ORW dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define ANDB dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define ANDW dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define XORB dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define XORW dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define CF (nec_state->CarryVal!=0) +#define SF (nec_state->SignVal<0) +#define ZF (nec_state->ZeroVal==0) +#define PF parity_table[(BYTE)nec_state->ParityVal] +#define AF (nec_state->AuxVal!=0) +#define OF (nec_state->OverVal!=0) + +/************************************************************************/ + +int v25_read_byte(v25_state_t *nec_state, unsigned a); +int v25_read_word(v25_state_t *nec_state, unsigned a); +void v25_write_byte(v25_state_t *nec_state, unsigned a, unsigned d); +void v25_write_word(v25_state_t *nec_state, unsigned a, unsigned d); + +#define read_mem_byte(a) v25_read_byte(nec_state,(a)) +#define read_mem_word(a) v25_read_word(nec_state,(a)) +#define write_mem_byte(a,d) v25_write_byte(nec_state,(a),(d)) +#define write_mem_word(a,d) v25_write_word(nec_state,(a),(d)) + +#define read_port_byte(a) nec_state->io->read_byte(a) +#define read_port_word(a) nec_state->io->read_word_unaligned(a) +#define write_port_byte(a,d) nec_state->io->write_byte((a),(d)) +#define write_port_word(a,d) nec_state->io->write_word_unaligned((a),(d)) + +/************************************************************************/ + +#define CHANGE_PC do { EMPTY_PREFETCH(); } while (0) + +#define SegBase(Seg) (Sreg(Seg) << 4) + +#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4) + +#define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off))) +#define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off))) + +#define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); } +#define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); } + +/* prefetch timing */ + +#define FETCH() fetch(nec_state) +#define FETCH_XOR(a) ((a) ^ nec_state->fetch_xor) +#define FETCHWORD() fetchword(nec_state) +#define EMPTY_PREFETCH() nec_state->prefetch_reset = 1 + + +#define PUSH(val) { Wreg(SP)-=2; write_mem_word((((Sreg(SS)<<4)+Wreg(SP))),val); } +#define POP(var) { var = read_mem_word((((Sreg(SS)<<4)+Wreg(SP)))); Wreg(SP)+=2; } + +#define GetModRM UINT32 ModRM=FETCH() + +/* Cycle count macros: + CLK - cycle count is the same on all processors + CLKS - cycle count differs between processors, list all counts + CLKW - cycle count for word read/write differs for odd/even source/destination address + CLKM - cycle count for reg/mem instructions + CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses + + + Prefetch & buswait time is not emulated. + Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated. +*/ + +#define CLK(all) nec_state->icount-=all +#define CLKS(v20,v30,v33) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33; nec_state->icount-=(ccount>>nec_state->chip_type)&0x7f; } +#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } +#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_state->icount-=( ModRM >=0xc0 )?((ccount>>nec_state->chip_type)&0x7f):((mcount>>nec_state->chip_type)&0x7f); } +#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } + +/************************************************************************/ +#define CompressFlags() (WORD)(CF | (nec_state->IBRK << 1) | (PF << 2) | (nec_state->F0 << 3) | (AF << 4) \ + | (nec_state->F1 << 5) | (ZF << 6) | (SF << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \ + | (nec_state->DF << 10) | (OF << 11) | (nec_state->RB << 12) | (nec_state->MF << 15)) + +#define ExpandFlags(f) \ +{ \ + nec_state->CarryVal = (f) & 0x0001; \ + nec_state->IBRK = ((f) & 0x0002) == 0x0002; \ + nec_state->ParityVal = !((f) & 0x0004); \ + nec_state->F0 = ((f) & 0x0008) == 0x0008; \ + nec_state->AuxVal = (f) & 0x0010; \ + nec_state->F1 = ((f) & 0x0020) == 0x0020; \ + nec_state->ZeroVal = !((f) & 0x0040); \ + nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \ + nec_state->TF = ((f) & 0x0100) == 0x0100; \ + nec_state->IF = ((f) & 0x0200) == 0x0200; \ + nec_state->DF = ((f) & 0x0400) == 0x0400; \ + nec_state->OverVal = (f) & 0x0800; \ + /* RB only changes on interrupts, so skip it */ \ + nec_state->MF = ((f) & 0x8000) == 0x8000; \ +} + +#define IncWordReg(Reg) \ + unsigned tmp = (unsigned)Wreg(Reg); \ + unsigned tmp1 = tmp+1; \ + nec_state->OverVal = (tmp == 0x7fff); \ + SetAF(tmp1,tmp,1); \ + SetSZPF_Word(tmp1); \ + Wreg(Reg)=tmp1 + +#define DecWordReg(Reg) \ + unsigned tmp = (unsigned)Wreg(Reg); \ + unsigned tmp1 = tmp-1; \ + nec_state->OverVal = (tmp == 0x8000); \ + SetAF(tmp1,tmp,1); \ + SetSZPF_Word(tmp1); \ + Wreg(Reg)=tmp1 + +#define JMP(flag) \ + int tmp; \ + EMPTY_PREFETCH(); \ + tmp = (int)((INT8)FETCH()); \ + if (flag) \ + { \ + static const UINT8 table[3]={3,10,10}; \ + nec_state->ip = (WORD)(nec_state->ip+tmp); \ + nec_state->icount-=table[nec_state->chip_type/8]; \ + CHANGE_PC; \ + return; \ + } + +#define ADJ4(param1,param2) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ + { \ + UINT16 tmp; \ + tmp = Breg(AL) + param1; \ + Breg(AL) = tmp; \ + nec_state->AuxVal = 1; \ + nec_state->CarryVal |= tmp & 0x100; \ + } \ + if (CF || (Breg(AL)>0x9f)) \ + { \ + Breg(AL) += param2; \ + nec_state->CarryVal = 1; \ + } \ + SetSZPF_Byte(Breg(AL)) + +#define ADJB(param1,param2) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ + { \ + Breg(AL) += param1; \ + Breg(AH) += param2; \ + nec_state->AuxVal = 1; \ + nec_state->CarryVal = 1; \ + } \ + else \ + { \ + nec_state->AuxVal = 0; \ + nec_state->CarryVal = 0; \ + } \ + Breg(AL) &= 0x0F + +#define BITOP_BYTE \ + ModRM = FETCH(); \ + if (ModRM >= 0xc0) { \ + tmp=Breg(Mod_RM.RM.b[ModRM]); \ + } \ + else { \ + (*GetEA[ModRM])(nec_state); \ + tmp=read_mem_byte(EA); \ + } + +#define BITOP_WORD \ + ModRM = FETCH(); \ + if (ModRM >= 0xc0) { \ + tmp=Wreg(Mod_RM.RM.w[ModRM]); \ + } \ + else { \ + (*GetEA[ModRM])(nec_state); \ + tmp=read_mem_word(EA); \ + } + +#define BIT_NOT \ + if (tmp & (1<CarryVal = dst & 0x80; dst = (dst << 1)+CF +#define ROL_WORD nec_state->CarryVal = dst & 0x8000; dst = (dst << 1)+CF +#define ROR_BYTE nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7) +#define ROR_WORD nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<15) +#define ROLC_BYTE dst = (dst << 1) + CF; SetCFB(dst) +#define ROLC_WORD dst = (dst << 1) + CF; SetCFW(dst) +#define RORC_BYTE dst = (CF<<8)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1 +#define RORC_WORD dst = (CF<<16)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1 +#define SHL_BYTE(c) nec_state->icount-=c; dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHL_WORD(c) nec_state->icount-=c; dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) +#define SHR_BYTE(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHR_WORD(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) +#define SHRA_BYTE(c) nec_state->icount-=c; dst = ((INT8)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT8)((BYTE)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHRA_WORD(c) nec_state->icount-=c; dst = ((INT16)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT16)((WORD)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) + +#define DIVUB \ + uresult = Wreg(AW); \ + uresult2 = uresult % tmp; \ + if ((uresult /= tmp) > 0xff) { \ + nec_interrupt(nec_state, 0,0); break; \ + } else { \ + Breg(AL) = uresult; \ + Breg(AH) = uresult2; \ + } + +#define DIVB \ + result = (INT16)Wreg(AW); \ + result2 = result % (INT16)((INT8)tmp); \ + if ((result /= (INT16)((INT8)tmp)) > 0xff) { \ + nec_interrupt(nec_state, 0,0); break; \ + } else { \ + Breg(AL) = result; \ + Breg(AH) = result2; \ + } + +#define DIVUW \ + uresult = (((UINT32)Wreg(DW)) << 16) | Wreg(AW);\ + uresult2 = uresult % tmp; \ + if ((uresult /= tmp) > 0xffff) { \ + nec_interrupt(nec_state, 0,0); break; \ + } else { \ + Wreg(AW)=uresult; \ + Wreg(DW)=uresult2; \ + } + +#define DIVW \ + result = ((UINT32)Wreg(DW) << 16) + Wreg(AW); \ + result2 = result % (INT32)((INT16)tmp); \ + if ((result /= (INT32)((INT16)tmp)) > 0xffff) { \ + nec_interrupt(nec_state, 0,0); break; \ + } else { \ + Wreg(AW)=result; \ + Wreg(DW)=result2; \ + } + +#define ADD4S { \ + int i,v1,v2,result; \ + int count = (Breg(CL)+1)/2; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={18,19,19}; \ + if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for add4s\n",PC(nec_state)); \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS0, si); \ + tmp2 = GetMemB(DS1, di); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + result = v1+v2+nec_state->CarryVal; \ + nec_state->CarryVal = result > 99 ? 1 : 0; \ + result = result % 100; \ + v1 = ((result/10)<<4) | (result % 10); \ + PutMemB(DS1, di,v1); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} + +#define SUB4S { \ + int count = (Breg(CL)+1)/2; \ + int i,v1,v2,result; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={18,19,19}; \ + if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for sub4s\n",PC(nec_state)); \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS1, di); \ + tmp2 = GetMemB(DS0, si); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + if (v1 < (v2+nec_state->CarryVal)) { \ + v1+=100; \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 1; \ + } else { \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 0; \ + } \ + v1 = ((result/10)<<4) | (result % 10); \ + PutMemB(DS1, di,v1); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} + +#define CMP4S { \ + int count = (Breg(CL)+1)/2; \ + int i,v1,v2,result; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={14,19,19}; \ + if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for cmp4s\n",PC(nec_state)); \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS1, di); \ + tmp2 = GetMemB(DS0, si); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + if (v1 < (v2+nec_state->CarryVal)) { \ + v1+=100; \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 1; \ + } else { \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 0; \ + } \ + v1 = ((result/10)<<4) | (result % 10); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} diff --git a/src/emu/cpu/nec/v25sfr.c b/src/emu/cpu/nec/v25sfr.c new file mode 100644 index 00000000000..8ec4ccfbc70 --- /dev/null +++ b/src/emu/cpu/nec/v25sfr.c @@ -0,0 +1,137 @@ +/**************************************************************************** + + NEC V25/V35 special function registers and internal ram access + +****************************************************************************/ + +#include "emu.h" +#include "nec.h" +#include "v25priv.h" + +#define RAMEN (nec_state->PRC & 0x40) + +int read_sfr(v25_state_t *nec_state, unsigned o) +{ + switch(o) + { + case 0xEA: /* FLAG */ + return ((nec_state->F0 << 3) | (nec_state->F1 << 5)); + case 0xEB: /* PRC */ + return nec_state->PRC; + break; + case 0xFF: /* IDB */ + return nec_state->IDB; + break; + default: + logerror("%06x: Read from special function register %02x\n",PC(nec_state),o); + return 0; + } +} + +void write_sfr(v25_state_t *nec_state, unsigned o, unsigned d) +{ + switch(o) + { + case 0xEA: /* FLAG */ + nec_state->F0 = ((d & 0x08) == 0x08); \ + nec_state->F1 = ((d & 0x20) == 0x20); \ + break; + case 0xEB: /* PRC */ + nec_state->PRC = d & 0x4F; + break; + case 0xFF: /* IDB */ + nec_state->IDB = d; + break; + default: + logerror("%06x: Wrote %02x to special function register %02x\n",PC(nec_state),d,o); + } +} + +int v25_read_byte(v25_state_t *nec_state, unsigned a) +{ + unsigned page = a >> 8; + unsigned offs = a & 0xff; + + if(RAMEN && page == (nec_state->IDB << 4 | 0xE)) + return nec_state->ram.b[BYTE_XOR_LE(offs)]; + + if(a == 0xFFFFF || page == (nec_state->IDB << 4 | 0xF)) + return read_sfr(nec_state, offs); + + return nec_state->program->read_byte(a); +} + +int v25_read_word(v25_state_t *nec_state, unsigned a) +{ + if( a & 1 ) + return (v25_read_byte(nec_state, a) | (v25_read_byte(nec_state, a + 1) << 8)); + + unsigned page = a >> 8; + unsigned offs = a & 0xff; + + if(RAMEN && page == (nec_state->IDB << 4 | 0xE)) + return nec_state->ram.w[offs/2]; + + if(page == (nec_state->IDB << 4 | 0xF)) + return (read_sfr(nec_state, offs) | (read_sfr(nec_state, offs+1) << 8)); + + if(a == 0xFFFFE) /* not sure about this */ + return (nec_state->program->read_byte(a) | (read_sfr(nec_state, 0xFF) << 8)); + + return nec_state->program->read_word(a); +} + +void v25_write_byte(v25_state_t *nec_state, unsigned a, unsigned d) +{ + unsigned page = a >> 8; + unsigned offs = a & 0xff; + + if(RAMEN && page == (nec_state->IDB << 4 | 0xE)) + { + nec_state->ram.b[BYTE_XOR_LE(offs)] = d; + return; + } + + if(a == 0xFFFFF || page == (nec_state->IDB << 4 | 0xF)) + { + write_sfr(nec_state, offs, d); + return; + } + + nec_state->program->write_byte(a, d); +} + +void v25_write_word(v25_state_t *nec_state, unsigned a, unsigned d) +{ + if( a & 1 ) + { + v25_write_byte(nec_state, a, d & 0xff); + v25_write_byte(nec_state, a + 1, d >> 8); + return; + } + + unsigned page = a >> 8; + unsigned offs = a & 0xff; + + if(RAMEN && page == (nec_state->IDB << 4 | 0xE)) + { + nec_state->ram.w[offs/2] = d; + return; + } + + if(page == (nec_state->IDB << 4 | 0xF)) + { + write_sfr(nec_state, offs, d & 0xff); + write_sfr(nec_state, offs + 1, d >> 8); + return; + } + + if(a == 0xFFFFE) /* not sure about this */ + { + nec_state->program->write_byte(a, d & 0xff); + write_sfr(nec_state, 0xFF, d >> 8); + return; + } + + nec_state->program->write_word(a, d); +} diff --git a/src/mame/drivers/cb2001.c b/src/mame/drivers/cb2001.c index 967f168d340..37ba7dce5da 100644 --- a/src/mame/drivers/cb2001.c +++ b/src/mame/drivers/cb2001.c @@ -792,7 +792,7 @@ static const ay8910_interface cb2001_ay8910_config = static const nec_config cb2001_config = { cb2001_decryption_table, }; static MACHINE_CONFIG_START( cb2001, driver_device ) - MDRV_CPU_ADD("maincpu", V30, 20000000) // CPU91A-011-0016JK004; encrypted cpu like nec v25/35 used in some irem game + MDRV_CPU_ADD("maincpu", V35, 20000000) // CPU91A-011-0016JK004; encrypted cpu like nec v25/35 used in some irem game MDRV_CPU_CONFIG(cb2001_config) MDRV_CPU_PROGRAM_MAP(cb2001_map) MDRV_CPU_IO_MAP(cb2001_io) diff --git a/src/mame/drivers/m107.c b/src/mame/drivers/m107.c index fbba3c37610..0697aee19af 100644 --- a/src/mame/drivers/m107.c +++ b/src/mame/drivers/m107.c @@ -824,7 +824,7 @@ static MACHINE_CONFIG_START( firebarr, driver_device ) MDRV_CPU_PROGRAM_MAP(main_map) MDRV_CPU_IO_MAP(main_portmap) - MDRV_CPU_ADD("soundcpu", V30, 14318000/2) + MDRV_CPU_ADD("soundcpu", V35, 14318000/2) MDRV_CPU_PROGRAM_MAP(sound_map) MDRV_CPU_CONFIG(firebarr_config) diff --git a/src/mame/drivers/m72.c b/src/mame/drivers/m72.c index c5e68c8b9bd..9a9725d067d 100644 --- a/src/mame/drivers/m72.c +++ b/src/mame/drivers/m72.c @@ -2318,7 +2318,7 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_START( cosmccop, driver_device ) /* basic machine hardware */ - MDRV_CPU_ADD("maincpu", V30,MASTER_CLOCK/2/2) + MDRV_CPU_ADD("maincpu", V35,MASTER_CLOCK/2/2) MDRV_CPU_PROGRAM_MAP(kengo_map) MDRV_CPU_IO_MAP(kengo_portmap) diff --git a/src/mame/drivers/m90.c b/src/mame/drivers/m90.c index 88e57b205ee..4e9ddf7ba18 100644 --- a/src/mame/drivers/m90.c +++ b/src/mame/drivers/m90.c @@ -689,7 +689,7 @@ static INTERRUPT_GEN( bomblord_interrupt ) /* Basic hardware -- no decryption table is setup for CPU */ static MACHINE_CONFIG_START( m90, driver_device ) /* basic machine hardware */ - MDRV_CPU_ADD("maincpu", V30,XTAL_32MHz/2/2) /* verified clock on cpu is 16Mhz but probably divided internally by 2 */ + MDRV_CPU_ADD("maincpu", V35,XTAL_32MHz/2/2) /* verified clock on cpu is 16Mhz but probably divided internally by 2 */ MDRV_CPU_PROGRAM_MAP(m90_main_cpu_map) MDRV_CPU_IO_MAP(m90_main_cpu_io_map) MDRV_CPU_VBLANK_INT("screen", m90_interrupt) @@ -763,47 +763,11 @@ MACHINE_CONFIG_END static const nec_config bomberman_config ={ bomberman_decryption_table, }; -static MACHINE_CONFIG_START( bombrman, driver_device ) - - /* basic machine hardware */ - MDRV_CPU_ADD("maincpu", V30,XTAL_32MHz/2/2) /* verified clock on cpu is 16Mhz but probably divided internally by 2 */ +static MACHINE_CONFIG_DERIVED( bombrman, m90 ) + MDRV_CPU_MODIFY("maincpu") MDRV_CPU_CONFIG(bomberman_config) - MDRV_CPU_PROGRAM_MAP(m90_main_cpu_map) - MDRV_CPU_IO_MAP(m90_main_cpu_io_map) - MDRV_CPU_VBLANK_INT("screen", m90_interrupt) - - MDRV_CPU_ADD("soundcpu", Z80, XTAL_3_579545MHz) /* verified on pcb */ - MDRV_CPU_PROGRAM_MAP(m90_sound_cpu_map) - MDRV_CPU_IO_MAP(m90_sound_cpu_io_map) - MDRV_CPU_VBLANK_INT_HACK(nmi_line_pulse,128) /* clocked by V1? (Vigilante) */ - /* IRQs are generated by main Z80 and YM2151 */ - MDRV_SOUND_START(m72) - MDRV_SOUND_RESET(m72) - - /* video hardware */ - MDRV_SCREEN_ADD("screen", RASTER) - MDRV_SCREEN_REFRESH_RATE(60) - MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) - MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) - MDRV_SCREEN_SIZE(64*8, 64*8) + MDRV_SCREEN_MODIFY("screen") MDRV_SCREEN_VISIBLE_AREA(10*8, 50*8-1, 17*8, 47*8-1) - - MDRV_GFXDECODE(m90) - MDRV_PALETTE_LENGTH(512) - - MDRV_VIDEO_START(m90) - MDRV_VIDEO_UPDATE(m90) - - /* sound hardware */ - MDRV_SPEAKER_STANDARD_MONO("mono") - - MDRV_SOUND_ADD("ymsnd", YM2151, XTAL_3_579545MHz) /* verified on pcb */ - MDRV_SOUND_CONFIG(ym2151_config) - MDRV_SOUND_ROUTE(0, "mono", 0.15) - MDRV_SOUND_ROUTE(1, "mono", 0.15) - - MDRV_SOUND_ADD("dac", DAC, 0) - MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10) MACHINE_CONFIG_END static const nec_config dynablaster_config ={ dynablaster_decryption_table, }; @@ -811,7 +775,7 @@ static const nec_config dynablaster_config ={ dynablaster_decryption_table, }; static MACHINE_CONFIG_START( bbmanw, driver_device ) /* basic machine hardware */ - MDRV_CPU_ADD("maincpu", V30,XTAL_32MHz/2/2) /* verified clock on cpu is 16Mhz but probably divided internally by 2 */ + MDRV_CPU_ADD("maincpu", V35,XTAL_32MHz/2/2) /* verified clock on cpu is 16Mhz but probably divided internally by 2 */ MDRV_CPU_CONFIG(dynablaster_config) MDRV_CPU_PROGRAM_MAP(m90_main_cpu_map) MDRV_CPU_IO_MAP(m90_main_cpu_io_map) diff --git a/src/mame/drivers/m92.c b/src/mame/drivers/m92.c index e448106b108..3c28807135b 100644 --- a/src/mame/drivers/m92.c +++ b/src/mame/drivers/m92.c @@ -181,7 +181,7 @@ Notes: 62256: 32K x8 SRAM Custom chips: - NANAO 08J27261A1 (PLCC84, encrypted V30 sound CPU, clocked at 14.31818MHz on pins 78 & 79) + NANAO 08J27261A1 (PLCC84, encrypted V35 sound CPU, clocked at 14.31818MHz on pins 78 & 79) NANAO GA23 (QFP180) @@ -924,7 +924,7 @@ static MACHINE_CONFIG_START( m92, driver_device ) MDRV_CPU_PROGRAM_MAP(m92_map) MDRV_CPU_IO_MAP(m92_portmap) - MDRV_CPU_ADD("soundcpu" ,V30, 14318180/2) /* 14.31818 MHz */ + MDRV_CPU_ADD("soundcpu" ,V35, 14318180/2) /* 14.31818 MHz */ MDRV_CPU_PROGRAM_MAP(sound_map) MDRV_MACHINE_START(m92) @@ -1293,7 +1293,7 @@ ROM_START( gunforce ) ROM_LOAD16_BYTE( "gf_h1-c.5l", 0x040001, 0x20000, CRC(c84188b7) SHA1(ff710be742f610d90538db296acdd435260bef12) ) ROM_LOAD16_BYTE( "gf_l1-c.5j", 0x040000, 0x20000, CRC(b189f72a) SHA1(f17d87349a57e1a4b20c4947e41edd7c39eaca13) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "gf_sh0.rom", 0x000001, 0x010000, CRC(3f8f16e0) SHA1(a9f568c1b585c2cf13b21716954dac0a89936fc6) ) ROM_LOAD16_BYTE( "gf_sl0.rom", 0x000000, 0x010000, CRC(db0b13a3) SHA1(6723026010610b706725a5284a7b8d70fe479dae) ) @@ -1320,7 +1320,7 @@ ROM_START( gunforcej ) ROM_LOAD16_BYTE( "gfb_h1-e.5l", 0x040001, 0x20000, CRC(d9744f5d) SHA1(056d6e6e9874c33dcebe2e0ec946117d5eaa5d76) ) ROM_LOAD16_BYTE( "gfb_l1-e.5j", 0x040000, 0x20000, CRC(a0f7b61b) SHA1(5fc7fc3f57e82a9ae4e1f3c3e8e3e3b0bd3ff8f5) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "gf_sh0.rom",0x000001, 0x010000, CRC(3f8f16e0) SHA1(a9f568c1b585c2cf13b21716954dac0a89936fc6) ) ROM_LOAD16_BYTE( "gf_sl0.rom",0x000000, 0x010000, CRC(db0b13a3) SHA1(6723026010610b706725a5284a7b8d70fe479dae) ) @@ -1347,7 +1347,7 @@ ROM_START( gunforceu ) ROM_LOAD16_BYTE( "gf_h1-d.5l", 0x040001, 0x20000, CRC(08a3736c) SHA1(0ae904cf486a371f8b635c1f9dc5201e38a73f5a) ) ROM_LOAD16_BYTE( "gf_l1-d.5j", 0x040000, 0x20000, CRC(435f524f) SHA1(65c282ec50123747880850bc32c7ace0471ed9f2) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "gf_sh0.rom",0x000001, 0x010000, CRC(3f8f16e0) SHA1(a9f568c1b585c2cf13b21716954dac0a89936fc6) ) ROM_LOAD16_BYTE( "gf_sl0.rom",0x000000, 0x010000, CRC(db0b13a3) SHA1(6723026010610b706725a5284a7b8d70fe479dae) ) @@ -1455,7 +1455,7 @@ ROM_START( hook ) ROM_LOAD16_BYTE( "h-h1.rom", 0x080001, 0x020000, CRC(264ba1f0) SHA1(49ecf9b3e5375629607fb747abe264406065580b) ) ROM_LOAD16_BYTE( "h-l1.rom", 0x080000, 0x020000, CRC(f9913731) SHA1(be7871d6843e76f66fae6b501c5ee83ccc366463) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "h-sh0.rom", 0x000001, 0x010000, CRC(86a4e56e) SHA1(61163010e713be64368a4126f17d33cbdcf0c5ed) ) ROM_LOAD16_BYTE( "h-sl0.rom", 0x000000, 0x010000, CRC(10fd9676) SHA1(1b51181a8f0711997e107e9a8b8f44341d08ea81) ) @@ -1482,7 +1482,7 @@ ROM_START( hooku ) ROM_LOAD16_BYTE( "h-h1.rom", 0x080001, 0x020000, CRC(264ba1f0) SHA1(49ecf9b3e5375629607fb747abe264406065580b) ) ROM_LOAD16_BYTE( "h-l1.rom", 0x080000, 0x020000, CRC(f9913731) SHA1(be7871d6843e76f66fae6b501c5ee83ccc366463) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "h-sh0.rom", 0x000001, 0x010000, CRC(86a4e56e) SHA1(61163010e713be64368a4126f17d33cbdcf0c5ed) ) ROM_LOAD16_BYTE( "h-sl0.rom", 0x000000, 0x010000, CRC(10fd9676) SHA1(1b51181a8f0711997e107e9a8b8f44341d08ea81) ) @@ -1509,7 +1509,7 @@ ROM_START( hookj ) ROM_LOAD16_BYTE( "h-h1.rom", 0x080001, 0x020000, CRC(264ba1f0) SHA1(49ecf9b3e5375629607fb747abe264406065580b) ) ROM_LOAD16_BYTE( "h-l1.rom", 0x080000, 0x020000, CRC(f9913731) SHA1(be7871d6843e76f66fae6b501c5ee83ccc366463) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "h-sh0-a.3l", 0x000001, 0x010000, CRC(bd3d1f61) SHA1(0c884a0b5519f9c0823128872baf7b0c4078e5c4) ) ROM_LOAD16_BYTE( "h-sl0-a.3n", 0x000000, 0x010000, CRC(76371def) SHA1(b7a86fd4eecdd8a538c32e08cd920c27bd50924b) ) @@ -1561,7 +1561,7 @@ ROM_START( rtypeleo ) ROM_LOAD16_BYTE( "rtl-h1-d.bin", 0x080001, 0x020000, CRC(352ff444) SHA1(e302bc8dbf80abe5c1aaf02e92473fc72a796e72) ) ROM_LOAD16_BYTE( "rtl-l1-d.bin", 0x080000, 0x020000, CRC(fd34ea46) SHA1(aca12d46ebff94505d03884e45805e84bbece6a7) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "rtl-sh0a.bin", 0x000001, 0x010000, CRC(e518b4e3) SHA1(44ec1d6b27bc3e49ad967f43960398ba1a19c5e3) ) ROM_LOAD16_BYTE( "rtl-sl0a.bin", 0x000000, 0x010000, CRC(896f0d36) SHA1(9246b1a5a8717dd823340d4cb79012a3df6fa4b7) ) @@ -1588,7 +1588,7 @@ ROM_START( rtypeleoj ) ROM_LOAD16_BYTE( "rtl-h1-d.bin", 0x080001, 0x020000, CRC(352ff444) SHA1(e302bc8dbf80abe5c1aaf02e92473fc72a796e72) ) ROM_LOAD16_BYTE( "rtl-l1-d.bin", 0x080000, 0x020000, CRC(fd34ea46) SHA1(aca12d46ebff94505d03884e45805e84bbece6a7) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "rtl-sh0a.bin", 0x000001, 0x010000, CRC(e518b4e3) SHA1(44ec1d6b27bc3e49ad967f43960398ba1a19c5e3) ) ROM_LOAD16_BYTE( "rtl-sl0a.bin", 0x000000, 0x010000, CRC(896f0d36) SHA1(9246b1a5a8717dd823340d4cb79012a3df6fa4b7) ) @@ -1615,7 +1615,7 @@ ROM_START( mysticri ) ROM_LOAD16_BYTE( "mr-h1-b.bin", 0x080001, 0x010000, CRC(e17649b9) SHA1(fb09a0ccd22475d81ba667c88d1b5eb7cc64728f) ) ROM_LOAD16_BYTE( "mr-l1-b.bin", 0x080000, 0x010000, CRC(a87c62b4) SHA1(d3cae0f420faeb4556767b6ad817fc39d31b7273) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "mr-sh0.bin", 0x000001, 0x010000, CRC(50d335e4) SHA1(a1a92e95fbd6b99d904a82cea4a1ff6fd2ac8dde) ) ROM_LOAD16_BYTE( "mr-sl0.bin", 0x000000, 0x010000, CRC(0fa32721) SHA1(1561ddd2597592060b8a78f1dff6cbb25fb7cd2e) ) @@ -1642,7 +1642,7 @@ ROM_START( gunhohki ) ROM_LOAD16_BYTE( "mr-h1.bin", 0x080001, 0x010000, CRC(c9532b60) SHA1(b83322ba7bb3eea4c64dd65b3c0a5cade61841d8) ) ROM_LOAD16_BYTE( "mr-l1.bin", 0x080000, 0x010000, CRC(6349b520) SHA1(406620d9c63ce3d6801105c8122e1d0bbe6152ad) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "mr-sh0.bin", 0x000001, 0x010000, CRC(50d335e4) SHA1(a1a92e95fbd6b99d904a82cea4a1ff6fd2ac8dde) ) ROM_LOAD16_BYTE( "mr-sl0.bin", 0x000000, 0x010000, CRC(0fa32721) SHA1(1561ddd2597592060b8a78f1dff6cbb25fb7cd2e) ) @@ -1669,7 +1669,7 @@ ROM_START( mysticrib ) ROM_LOAD16_BYTE( "h1", 0x080001, 0x010000, CRC(4dcb085b) SHA1(7c053f5ef2978e574d3d2d9f5c12035473d13c3b) ) ROM_LOAD16_BYTE( "l1", 0x080000, 0x010000, CRC(88df4f70) SHA1(f55769a107fe3f5446d8268f66e895b02727c61e) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ // older revision code? rev 3.31, doesn't work? ROM_LOAD16_BYTE( "sh0", 0x000001, 0x010000, CRC(fc7221ee) SHA1(4e714f31ce0d1bb2f6c649a26af748f96912848e) ) ROM_LOAD16_BYTE( "sl0", 0x000000, 0x010000, CRC(65c809e6) SHA1(45a860b250219a15aa8a2177251f4d3f2e559b9e) ) @@ -1698,7 +1698,7 @@ ROM_START( uccops ) ROM_LOAD16_BYTE( "uc_h1.rom", 0x080001, 0x020000, CRC(8d29bcd6) SHA1(470b77d1b8f88824bac294bd12a205a23dad2287) ) ROM_LOAD16_BYTE( "uc_l1.rom", 0x080000, 0x020000, CRC(a8a402d8) SHA1(0b40fb69f0a3e24e6b60117d2d2fd4cc170bc621) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "uc_sh0.rom", 0x000001, 0x010000, CRC(df90b198) SHA1(6b334457f06f6b9cfb355ba3d399bebb37b5733e) ) ROM_LOAD16_BYTE( "uc_sl0.rom", 0x000000, 0x010000, CRC(96c11aac) SHA1(16c47b4f97f0532fff30bb163f26d8cf6b923a2e) ) @@ -1725,7 +1725,7 @@ ROM_START( uccopsu ) ROM_LOAD16_BYTE( "uc_h1-g.rom", 0x080001, 0x020000, CRC(6b8ca2de) SHA1(1096b93bbaa4c97d4900e8c083cde99195cad5ba) ) ROM_LOAD16_BYTE( "uc_l1-g.rom", 0x080000, 0x020000, CRC(2bdec7dd) SHA1(58817099e74fd5bc299b7bc14d83ee75ed200b53) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "uc_sh0.rom", 0x000001, 0x010000, CRC(df90b198) SHA1(6b334457f06f6b9cfb355ba3d399bebb37b5733e) ) ROM_LOAD16_BYTE( "uc_sl0.rom", 0x000000, 0x010000, CRC(96c11aac) SHA1(16c47b4f97f0532fff30bb163f26d8cf6b923a2e) ) @@ -1766,7 +1766,7 @@ ROM_START( uccopsar ) /* Alpha Renewal Version */ ROM_LOAD16_BYTE( "uc_h1.ic27", 0x080001, 0x020000, CRC(79d79742) SHA1(f9c03c4d42b5b3d0f0185462868b04f1bb679f90) ) ROM_LOAD16_BYTE( "uc_l1.ic38", 0x080000, 0x020000, CRC(37211581) SHA1(b8fdff96b2c7d5cf2975dcf81c00581ccb595c15) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "uc_sh0.ic30", 0x000001, 0x010000, CRC(f0ca1b03) SHA1(07154a2c747091f8be23587c109d91ed1672da6e) ) ROM_LOAD16_BYTE( "uc_sl0.ic31", 0x000000, 0x010000, CRC(d1661723) SHA1(bdc00196aa2074e7b21e5949f73e9f2b93d76fd9) ) @@ -1793,7 +1793,7 @@ ROM_START( uccopsj ) ROM_LOAD16_BYTE( "uc_h1_a.ic27", 0x080001, 0x020000, CRC(83f78dea) SHA1(6d197c3ea76beac31c3ea6e54a3ffea9d6c0c653) ) ROM_LOAD16_BYTE( "uc_l1_a.ic38", 0x080000, 0x020000, CRC(19628280) SHA1(e6c06cb7c37e46a7db3b4f318e836aa5a2390eda) ) - ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V30 = NANAO custom D80001 (?) */ + ROM_REGION( 0x100000, "soundcpu", 0 ) /* 1MB for the audio CPU - encrypted V35 = NANAO custom D80001 (?) */ ROM_LOAD16_BYTE( "uc_sh0.ic30", 0x000001, 0x010000, CRC(f0ca1b03) SHA1(07154a2c747091f8be23587c109d91ed1672da6e) ) ROM_LOAD16_BYTE( "uc_sl0.ic31", 0x000000, 0x010000, CRC(d1661723) SHA1(bdc00196aa2074e7b21e5949f73e9f2b93d76fd9) ) diff --git a/src/mame/drivers/segas32.c b/src/mame/drivers/segas32.c index 80798577ad3..987ade72a8c 100644 --- a/src/mame/drivers/segas32.c +++ b/src/mame/drivers/segas32.c @@ -2232,11 +2232,14 @@ static MACHINE_CONFIG_START( system32, driver_device ) MACHINE_CONFIG_END +static const nec_config ga2_v25_config ={ ga2_v25_opcode_table, }; + static MACHINE_CONFIG_DERIVED( system32_v25, system32 ) /* add a V25 for protection */ MDRV_CPU_ADD("mcu", V25, 10000000) MDRV_CPU_PROGRAM_MAP(ga2_v25_map) + MDRV_CPU_CONFIG(ga2_v25_config) MACHINE_CONFIG_END @@ -2475,7 +2478,7 @@ ROM_END ************************************************************************************************************************** ************************************************************************************************************************** Arabian Fight - protected via a custom V20 with encrypted code + protected via a custom V25 with encrypted code */ ROM_START( arabfgt ) @@ -2542,7 +2545,7 @@ ROM_END /************************************************************************************************************************** Arabian Fight (Japan) - protected via a custom V20 with encrypted code + protected via a custom V25 with encrypted code */ ROM_START( arabfgtj ) ROM_REGION( 0x200000, "maincpu", 0 ) /* v60 code + data */ @@ -2818,7 +2821,7 @@ ROM_END ************************************************************************************************************************** ************************************************************************************************************************** Golden Axe: The Return of Death Adder - protected via a custom V20 with encrypted code + protected via a custom V25 with encrypted code */ ROM_START( ga2 ) ROM_REGION( 0x200000, "maincpu", 0 ) /* v60 code + data */ @@ -2853,7 +2856,7 @@ ROM_END /************************************************************************************************************************** Golden Axe: The Return of Death Adder (U.S.) - protected via a custom V20 with encrypted code + protected via a custom V25 with encrypted code Sega Game ID codes: Game: 833-8932-02 GOLDEN AXE II AC USA Rom board: 833-8933-01 @@ -2893,7 +2896,7 @@ ROM_END /************************************************************************************************************************** Golden Axe: The Return of Death Adder (Japan) - protected via a custom V20 with encrypted code + protected via a custom V25 with encrypted code */ ROM_START( ga2j ) ROM_REGION( 0x200000, "maincpu", 0 ) /* v60 code + data */ diff --git a/src/mame/includes/segas32.h b/src/mame/includes/segas32.h index a06d3117fd8..767dd3accfc 100644 --- a/src/mame/includes/segas32.h +++ b/src/mame/includes/segas32.h @@ -29,6 +29,7 @@ WRITE16_HANDLER( jleague_protection_w ); READ16_HANDLER( dbzvrvs_protection_r ); WRITE16_HANDLER( dbzvrvs_protection_w ); +extern const UINT8 ga2_v25_opcode_table[]; void decrypt_ga2_protrom(running_machine *machine); READ16_HANDLER( ga2_dpram_r ); WRITE16_HANDLER( ga2_dpram_w ); diff --git a/src/mame/machine/segas32.c b/src/mame/machine/segas32.c index 2302b609823..dae81b3377e 100644 --- a/src/mame/machine/segas32.c +++ b/src/mame/machine/segas32.c @@ -12,7 +12,7 @@ #define xxxx 0x00 -static const UINT8 ga2_v25_opcode_table[256] = { +const UINT8 ga2_v25_opcode_table[256] = { xxxx,xxxx,0xEA,xxxx,xxxx,0x8B,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xFA, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x49,xxxx,xxxx,xxxx, @@ -33,41 +33,22 @@ static const UINT8 ga2_v25_opcode_table[256] = { #undef xxxx -static void nec_v25_cpu_decrypt(running_machine *machine) +void decrypt_ga2_protrom(running_machine *machine) { int i; - address_space *space = cputag_get_address_space(machine, "mcu", ADDRESS_SPACE_PROGRAM); UINT8 *rom = memory_region(machine, "mcu"); - UINT8* decrypted = auto_alloc_array(machine, UINT8, 0x10000); UINT8* temp = auto_alloc_array(machine, UINT8, 0x100000); - // set CPU3 opcode base - space->set_decrypted_region(0x00000, 0x0ffff, decrypted); - space->set_decrypted_region(0xf0000, 0xfffff, decrypted); - // make copy of ROM so original can be overwritten memcpy(temp, rom, 0x10000); + // unscramble the address lines for(i = 0; i < 0x10000; i++) - { - int j = BITSWAP16(i, 14, 11, 15, 12, 13, 4, 3, 7, 5, 10, 2, 8, 9, 6, 1, 0); - - // normal ROM data with address swap undone - rom[i] = temp[j]; - - // decryped opcodes with address swap undone - decrypted[i] = ga2_v25_opcode_table[ temp[j] ]; - } + rom[i] = temp[BITSWAP16(i, 14, 11, 15, 12, 13, 4, 3, 7, 5, 10, 2, 8, 9, 6, 1, 0)]; auto_free(machine, temp); } -void decrypt_ga2_protrom(running_machine *machine) -{ - nec_v25_cpu_decrypt(machine); -} - - WRITE16_HANDLER( ga2_dpram_w ) { /* does it ever actually write.. */