From 14e3abc89fdc7d13cfa2895f77cb7f11ebf176fa Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 13:48:20 +0200 Subject: [PATCH] Seibu SPI and SYS386I: driver and i386 CPU from current MAME (57 sets) - i386 CPU core: the C core of MAME 0.139 (mame2010-libretro), on the 0.78 CPU interface, with save states. Fast memory: the driver gives its plain RAM and ROM, which the CPU fetches, reads and writes directly (a cached region per kind of access) instead of through the memory handlers. - Seibu SPI driver from current MAME: the SXX2C main board with its cartridges, the SXX2E / SXX2F / SXX2G single boards and SYS386I. Senkyu / Battle Balls, Viper Phase 1, Raiden Fighters, Raiden Fighters 2 and Raiden Fighters Jet, 57 sets. - Video, the CRTC, the tile and sprite decryption (SEI252, RISE10, RISE11) as current MAME. - DS2404 RTC from current MAME. Its 256 Hz tick keeps the time it had left across a save state. - intelfsh: 8-bit chips, the E28F008SA of the SPI main board. - YMF271: the clock in the interface (16.384MHz on SXX2G). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MEgow1uRCv8pxMErKhmoHZ --- Makefile.common | 12 + src/cpu/i386/cycles.h | 674 +++++++ src/cpu/i386/i386.c | 868 +++++++++ src/cpu/i386/i386.h | 39 + src/cpu/i386/i386op16.c | 3257 ++++++++++++++++++++++++++++++++ src/cpu/i386/i386op32.c | 3066 ++++++++++++++++++++++++++++++ src/cpu/i386/i386ops.c | 2367 +++++++++++++++++++++++ src/cpu/i386/i386ops.h | 377 ++++ src/cpu/i386/i386priv.h | 1094 +++++++++++ src/cpu/i386/i486ops.c | 424 +++++ src/cpu/i386/pentops.c | 53 + src/cpu/i386/x87ops.c | 352 ++++ src/cpuintrf.c | 6 + src/cpuintrf.h | 3 + src/driver.c | 59 + src/drivers/seibuspi.c | 3063 ++++++++++++++++++++++++++++++ src/includes/seibuspi.h | 36 + src/machine/ds2404.c | 297 +++ src/machine/ds2404.h | 27 + src/machine/intelfsh.c | 42 +- src/machine/intelfsh.h | 12 +- src/machine/seibuspi_machine.c | 507 +++++ src/sound/ymf271.c | 17 +- src/sound/ymf271.h | 1 + src/vidhrdw/seibuspi_vidhrdw.c | 841 +++++++++ 25 files changed, 17474 insertions(+), 20 deletions(-) create mode 100644 src/cpu/i386/cycles.h create mode 100644 src/cpu/i386/i386.c create mode 100644 src/cpu/i386/i386.h create mode 100644 src/cpu/i386/i386op16.c create mode 100644 src/cpu/i386/i386op32.c create mode 100644 src/cpu/i386/i386ops.c create mode 100644 src/cpu/i386/i386ops.h create mode 100644 src/cpu/i386/i386priv.h create mode 100644 src/cpu/i386/i486ops.c create mode 100644 src/cpu/i386/pentops.c create mode 100644 src/cpu/i386/x87ops.c create mode 100644 src/drivers/seibuspi.c create mode 100644 src/includes/seibuspi.h create mode 100644 src/machine/ds2404.c create mode 100644 src/machine/ds2404.h create mode 100644 src/machine/seibuspi_machine.c create mode 100644 src/vidhrdw/seibuspi_vidhrdw.c diff --git a/Makefile.common b/Makefile.common index 1c00a5d9..665fe187 100644 --- a/Makefile.common +++ b/Makefile.common @@ -80,6 +80,7 @@ SOURCES_C += \ $(CORE_DIR)/machine/eeprom.c \ $(CORE_DIR)/machine/idectrl.c \ $(CORE_DIR)/machine/intelfsh.c \ + $(CORE_DIR)/machine/ds2404.c \ $(CORE_DIR)/machine/ataflash.c \ $(CORE_DIR)/machine/mathbox.c \ $(CORE_DIR)/machine/mb87078.c \ @@ -183,6 +184,7 @@ CPUS+=ADSP2115@ CPUS+=ADSP2181@ CPUS+=PSXCPU@ CPUS+=H83002@ +CPUS+=I386@ CPUS+=MN10200@ CPUS+=M37702@ CPUS+=ASAP@ @@ -819,6 +821,7 @@ SOURCES_C += \ $(CORE_DIR)/vidhrdw/raiden_vidhrdw.c $(CORE_DIR)/drivers/raiden.c $(CORE_DIR)/drivers/raiden2.c \ $(CORE_DIR)/vidhrdw/dcon_vidhrdw.c $(CORE_DIR)/drivers/dcon.c \ $(CORE_DIR)/vidhrdw/sengokmj_vidhrdw.c $(CORE_DIR)/drivers/sengokmj.c \ + $(CORE_DIR)/machine/seibuspi_machine.c $(CORE_DIR)/vidhrdw/seibuspi_vidhrdw.c $(CORE_DIR)/drivers/seibuspi.c \ $(CORE_DIR)/sndhrdw/t5182.c \ $(CORE_DIR)/vidhrdw/mustache_vidhrdw.c $(CORE_DIR)/drivers/mustache.c \ $(CORE_DIR)/vidhrdw/darkmist_vidhrdw.c $(CORE_DIR)/drivers/darkmist.c \ @@ -1941,6 +1944,15 @@ else CPUDEFS += -DHAS_H83002=0 endif +CPU=$(strip $(findstring I386@,$(CPUS))) +ifneq ($(CPU),) +OBJDIRS += $(CORE_DIR)/cpu/i386 +CPUDEFS += -DHAS_I386=1 +SOURCES_C += $(CORE_DIR)/cpu/i386/i386.c +else +CPUDEFS += -DHAS_I386=0 +endif + CPU=$(strip $(findstring MN10200@,$(CPUS))) ifneq ($(CPU),) OBJDIRS += $(CORE_DIR)/cpu/mn10200 diff --git a/src/cpu/i386/cycles.h b/src/cpu/i386/cycles.h new file mode 100644 index 00000000..8d06cca8 --- /dev/null +++ b/src/cpu/i386/cycles.h @@ -0,0 +1,674 @@ +#pragma once + +#ifndef __CYCLES_H__ +#define __CYCLES_H__ + +typedef enum +{ + CYCLES_MOV_REG_REG, + CYCLES_MOV_REG_MEM, + CYCLES_MOV_MEM_REG, + CYCLES_MOV_IMM_REG, + CYCLES_MOV_IMM_MEM, + CYCLES_MOV_ACC_MEM, + CYCLES_MOV_MEM_ACC, + CYCLES_MOV_REG_SREG, + CYCLES_MOV_MEM_SREG, + CYCLES_MOV_SREG_REG, + CYCLES_MOV_SREG_MEM, + CYCLES_MOVSX_REG_REG, + CYCLES_MOVSX_MEM_REG, + CYCLES_MOVZX_REG_REG, + CYCLES_MOVZX_MEM_REG, + CYCLES_PUSH_RM, + CYCLES_PUSH_REG_SHORT, + CYCLES_PUSH_SREG, + CYCLES_PUSH_IMM, + CYCLES_PUSHA, + CYCLES_POP_RM, + CYCLES_POP_REG_SHORT, + CYCLES_POP_SREG, + CYCLES_POPA, + CYCLES_XCHG_REG_REG, + CYCLES_XCHG_REG_MEM, + CYCLES_IN, + CYCLES_IN_VAR, + CYCLES_OUT, + CYCLES_OUT_VAR, + CYCLES_LEA, + CYCLES_LDS, + CYCLES_LES, + CYCLES_LFS, + CYCLES_LGS, + CYCLES_LSS, + CYCLES_CLC, + CYCLES_CLD, + CYCLES_CLI, + CYCLES_CLTS, + CYCLES_CMC, + CYCLES_LAHF, + CYCLES_POPF, + CYCLES_PUSHF, + CYCLES_SAHF, + CYCLES_STC, + CYCLES_STD, + CYCLES_STI, + CYCLES_ALU_REG_REG, + CYCLES_ALU_REG_MEM, + CYCLES_ALU_MEM_REG, + CYCLES_ALU_IMM_REG, + CYCLES_ALU_IMM_MEM, + CYCLES_ALU_IMM_ACC, + CYCLES_INC_REG, + CYCLES_INC_MEM, + CYCLES_DEC_REG, + CYCLES_DEC_MEM, + CYCLES_CMP_REG_REG, + CYCLES_CMP_REG_MEM, + CYCLES_CMP_MEM_REG, + CYCLES_CMP_IMM_REG, + CYCLES_CMP_IMM_MEM, + CYCLES_CMP_IMM_ACC, + CYCLES_TEST_REG_REG, + CYCLES_TEST_REG_MEM, + CYCLES_TEST_IMM_REG, + CYCLES_TEST_IMM_MEM, + CYCLES_TEST_IMM_ACC, + CYCLES_NEG_REG, + CYCLES_NEG_MEM, + CYCLES_AAA, + CYCLES_AAS, + CYCLES_DAA, + CYCLES_DAS, + CYCLES_MUL8_ACC_REG, + CYCLES_MUL8_ACC_MEM, + CYCLES_MUL16_ACC_REG, + CYCLES_MUL16_ACC_MEM, + CYCLES_MUL32_ACC_REG, + CYCLES_MUL32_ACC_MEM, + CYCLES_IMUL8_ACC_REG, + CYCLES_IMUL8_ACC_MEM, + CYCLES_IMUL16_ACC_REG, + CYCLES_IMUL16_ACC_MEM, + CYCLES_IMUL32_ACC_REG, + CYCLES_IMUL32_ACC_MEM, + CYCLES_IMUL8_REG_REG, + CYCLES_IMUL8_REG_MEM, + CYCLES_IMUL16_REG_REG, + CYCLES_IMUL16_REG_MEM, + CYCLES_IMUL32_REG_REG, + CYCLES_IMUL32_REG_MEM, + CYCLES_IMUL16_REG_IMM_REG, + CYCLES_IMUL16_MEM_IMM_REG, + CYCLES_IMUL32_REG_IMM_REG, + CYCLES_IMUL32_MEM_IMM_REG, + CYCLES_DIV8_ACC_REG, + CYCLES_DIV8_ACC_MEM, + CYCLES_DIV16_ACC_REG, + CYCLES_DIV16_ACC_MEM, + CYCLES_DIV32_ACC_REG, + CYCLES_DIV32_ACC_MEM, + CYCLES_IDIV8_ACC_REG, + CYCLES_IDIV8_ACC_MEM, + CYCLES_IDIV16_ACC_REG, + CYCLES_IDIV16_ACC_MEM, + CYCLES_IDIV32_ACC_REG, + CYCLES_IDIV32_ACC_MEM, + CYCLES_AAD, + CYCLES_AAM, + CYCLES_CBW, + CYCLES_CWD, + CYCLES_ROTATE_REG, + CYCLES_ROTATE_MEM, + CYCLES_ROTATE_CARRY_REG, + CYCLES_ROTATE_CARRY_MEM, + CYCLES_SHLD_REG, + CYCLES_SHLD_MEM, + CYCLES_SHRD_REG, + CYCLES_SHRD_MEM, + CYCLES_NOT_REG, + CYCLES_NOT_MEM, + CYCLES_CMPS, + CYCLES_INS, + CYCLES_LODS, + CYCLES_MOVS, + CYCLES_OUTS, + CYCLES_SCAS, + CYCLES_STOS, + CYCLES_XLAT, + CYCLES_REP_CMPS_BASE, + CYCLES_REP_INS_BASE, + CYCLES_REP_LODS_BASE, + CYCLES_REP_MOVS_BASE, + CYCLES_REP_OUTS_BASE, + CYCLES_REP_SCAS_BASE, + CYCLES_REP_STOS_BASE, + CYCLES_REP_CMPS, + CYCLES_REP_INS, + CYCLES_REP_LODS, + CYCLES_REP_MOVS, + CYCLES_REP_OUTS, + CYCLES_REP_SCAS, + CYCLES_REP_STOS, + CYCLES_BSF_BASE, + CYCLES_BSF, + CYCLES_BSR_BASE, + CYCLES_BSR, + CYCLES_BT_IMM_REG, + CYCLES_BT_IMM_MEM, + CYCLES_BT_REG_REG, + CYCLES_BT_REG_MEM, + CYCLES_BTC_IMM_REG, + CYCLES_BTC_IMM_MEM, + CYCLES_BTC_REG_REG, + CYCLES_BTC_REG_MEM, + CYCLES_BTR_IMM_REG, + CYCLES_BTR_IMM_MEM, + CYCLES_BTR_REG_REG, + CYCLES_BTR_REG_MEM, + CYCLES_BTS_IMM_REG, + CYCLES_BTS_IMM_MEM, + CYCLES_BTS_REG_REG, + CYCLES_BTS_REG_MEM, + CYCLES_CALL, /* E8 */ + CYCLES_CALL_REG, /* FF /2 */ + CYCLES_CALL_MEM, /* FF /2 */ + CYCLES_CALL_INTERSEG, /* 9A */ + CYCLES_CALL_REG_INTERSEG, /* FF /3 */ + CYCLES_CALL_MEM_INTERSEG, /* FF /3 */ + CYCLES_JMP_SHORT, /* EB */ + CYCLES_JMP, /* E9 */ + CYCLES_JMP_REG, /* FF /4 */ + CYCLES_JMP_MEM, /* FF /4 */ + CYCLES_JMP_INTERSEG, /* EA */ + CYCLES_JMP_REG_INTERSEG, /* FF /5 */ + CYCLES_JMP_MEM_INTERSEG, /* FF /5 */ + CYCLES_RET, /* C3 */ + CYCLES_RET_IMM, /* C2 */ + CYCLES_RET_INTERSEG, /* CB */ + CYCLES_RET_IMM_INTERSEG, /* CA */ + CYCLES_JCC_DISP8, + CYCLES_JCC_FULL_DISP, + CYCLES_JCC_DISP8_NOBRANCH, + CYCLES_JCC_FULL_DISP_NOBRANCH, + CYCLES_JCXZ, + CYCLES_JCXZ_NOBRANCH, + CYCLES_LOOP, + CYCLES_LOOPZ, + CYCLES_LOOPNZ, + CYCLES_SETCC_REG, + CYCLES_SETCC_MEM, + CYCLES_ENTER, + CYCLES_LEAVE, + CYCLES_INT, + CYCLES_INT3, + CYCLES_INTO_OF1, + CYCLES_INTO_OF0, + CYCLES_BOUND_IN_RANGE, + CYCLES_BOUND_OUT_RANGE, + CYCLES_IRET, + CYCLES_HLT, + CYCLES_MOV_REG_CR0, + CYCLES_MOV_REG_CR2, + CYCLES_MOV_REG_CR3, + CYCLES_MOV_CR_REG, + CYCLES_MOV_REG_DR0_3, + CYCLES_MOV_REG_DR6_7, + CYCLES_MOV_DR6_7_REG, + CYCLES_MOV_DR0_3_REG, + CYCLES_MOV_REG_TR6_7, + CYCLES_MOV_TR6_7_REG, + CYCLES_NOP, + CYCLES_WAIT, + CYCLES_ARPL_REG, + CYCLES_ARPL_MEM, + CYCLES_LAR_REG, + CYCLES_LAR_MEM, + CYCLES_LGDT, + CYCLES_LIDT, + CYCLES_LLDT_REG, + CYCLES_LLDT_MEM, + CYCLES_LMSW_REG, + CYCLES_LMSW_MEM, + CYCLES_LSL_REG, + CYCLES_LSL_MEM, + CYCLES_LTR_REG, + CYCLES_LTR_MEM, + CYCLES_SGDT, + CYCLES_SIDT, + CYCLES_SLDT_REG, + CYCLES_SLDT_MEM, + CYCLES_SMSW_REG, + CYCLES_SMSW_MEM, + CYCLES_STR_REG, + CYCLES_STR_MEM, + CYCLES_VERR_REG, + CYCLES_VERR_MEM, + CYCLES_VERW_REG, + CYCLES_VERW_MEM, + CYCLES_LOCK, + + CYCLES_BSWAP, + CYCLES_CMPXCHG8B, + CYCLES_CMPXCHG, + CYCLES_CPUID, + CYCLES_CPUID_EAX1, + CYCLES_INVD, + CYCLES_XADD, + CYCLES_RDTSC, + CYCLES_RSM, + CYCLES_RDMSR, + + CYCLES_FABS, + CYCLES_FADD, + CYCLES_FBLD, + CYCLES_FBSTP, + CYCLES_FCHS, + CYCLES_FCLEX, + CYCLES_FCOM, + CYCLES_FCOS, + CYCLES_FDECSTP, + CYCLES_FDISI, + CYCLES_FDIV, + CYCLES_FDIVR, + CYCLES_FENI, + CYCLES_FFREE, + CYCLES_FIADD, + CYCLES_FICOM, + CYCLES_FIDIV, + CYCLES_FILD, + CYCLES_FIMUL, + CYCLES_FINCSTP, + CYCLES_FINIT, + CYCLES_FIST, + CYCLES_FISUB, + CYCLES_FLD, + CYCLES_FLDZ, + CYCLES_FLD1, + CYCLES_FLDL2E, + CYCLES_FLDL2T, + CYCLES_FLDLG2, + CYCLES_FLDLN2, + CYCLES_FLDPI, + CYCLES_FLDCW, + CYCLES_FLDENV, + CYCLES_FMUL, + CYCLES_FNOP, + CYCLES_FPATAN, + CYCLES_FPREM, + CYCLES_FPREM1, + CYCLES_FPTAN, + CYCLES_FRNDINT, + CYCLES_FRSTOR, + CYCLES_FSAVE, + CYCLES_FSCALE, + CYCLES_FSETPM, + CYCLES_FSIN, + CYCLES_FSINCOS, + CYCLES_FSQRT, + CYCLES_FST, + CYCLES_FSTCW, + CYCLES_FSTENV, + CYCLES_FSTSW, + CYCLES_FSUB, + CYCLES_FSUBR, + CYCLES_FTST, + CYCLES_FUCOM, + CYCLES_FXAM, + CYCLES_FXCH, + CYCLES_FXTRACT, + CYCLES_FYL2X, + CYCLES_FYL2XPI, + CYCLES_CMPXCHG_REG_REG_T, + CYCLES_CMPXCHG_REG_REG_F, + CYCLES_CMPXCHG_REG_MEM_T, + CYCLES_CMPXCHG_REG_MEM_F, + CYCLES_XADD_REG_REG, + CYCLES_XADD_REG_MEM, + + CYCLES_NUM_OPCODES +} X86_CYCLES; + + +#define X86_NUM_CPUS 4 +#define CPU_CYCLES_I386 0 +#define CPU_CYCLES_I486 1 +#define CPU_CYCLES_PENTIUM 2 +#define CPU_CYCLES_MEDIAGX 3 + + +typedef struct +{ + X86_CYCLES op; + UINT8 cpu_cycles[X86_NUM_CPUS][2]; +} X86_CYCLE_TABLE; + +static const X86_CYCLE_TABLE x86_cycle_table[] = +{ + /* opcode rm/pmode */ + /* i386 i486 pentium mediagx */ + { CYCLES_MOV_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_REG_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_MEM_REG, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_IMM_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_ACC_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_MEM_ACC, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_MOV_REG_SREG, { { 2, 18 }, { 3, 3 }, { 2, 2 }, { 1, 6 } } }, + { CYCLES_MOV_MEM_SREG, { { 5, 19 }, { 9, 9 }, { 3, 3 }, { 1, 6 } } }, + { CYCLES_MOV_SREG_REG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } }, + { CYCLES_MOV_SREG_MEM, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } }, + { CYCLES_MOVSX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_MOVSX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_MOVZX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_MOVZX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_PUSH_RM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_PUSH_REG_SHORT, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_PUSH_SREG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_PUSH_IMM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_PUSHA, { { 18, 18 }, { 11, 11 }, { 5, 5 }, { 11, 11 } } }, + { CYCLES_POP_RM, { { 5, 5 }, { 4, 4 }, { 3, 3 }, { 4, 4 } } }, + { CYCLES_POP_REG_SHORT, { { 4, 4 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_POP_SREG, { { 7, 21 }, { 3, 3 }, { 3, 3 }, { 1, 6 } } }, + { CYCLES_POPA, { { 24, 24 }, { 9, 9 }, { 5, 5 }, { 9, 9 } } }, + { CYCLES_XCHG_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_XCHG_REG_MEM, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_IN, { { 12, 26 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } }, + { CYCLES_IN_VAR, { { 13, 27 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } }, + { CYCLES_OUT, { { 10, 24 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } }, + { CYCLES_OUT_VAR, { { 11, 25 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } }, + { CYCLES_LEA, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_LDS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, + { CYCLES_LES, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, + { CYCLES_LFS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, + { CYCLES_LGS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, + { CYCLES_LSS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 10 } } }, + { CYCLES_CLC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_CLD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } }, + { CYCLES_CLI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } }, + { CYCLES_CLTS, { { 6, 6 }, { 7, 7 }, { 10, 10 }, { 7, 7 } } }, + { CYCLES_CMC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_LAHF, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } }, + { CYCLES_POPF, { { 5, 5 }, { 9, 9 }, { 6, 6 }, { 8, 8 } } }, + { CYCLES_PUSHF, { { 4, 4 }, { 4, 4 }, { 9, 9 }, { 2, 2 } } }, + { CYCLES_SAHF, { { 3, 3 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_STC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_STD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } }, + { CYCLES_STI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } }, + { CYCLES_ALU_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_ALU_REG_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_ALU_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_ALU_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_ALU_IMM_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_ALU_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_INC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_INC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_DEC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_DEC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_CMP_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_CMP_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_CMP_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_CMP_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_CMP_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_CMP_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_TEST_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_TEST_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_TEST_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_TEST_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_TEST_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_NEG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_NEG_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_AAA, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, + { CYCLES_AAS, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, + { CYCLES_DAA, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } }, + { CYCLES_DAS, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } }, + { CYCLES_MUL8_ACC_REG, { { 17, 17 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } }, + { CYCLES_MUL8_ACC_MEM, { { 20, 20 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } }, + { CYCLES_MUL16_ACC_REG, { { 25, 25 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } }, + { CYCLES_MUL16_ACC_MEM, { { 28, 28 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } }, + { CYCLES_MUL32_ACC_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_MUL32_ACC_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_IMUL8_ACC_REG, { { 17, 17 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } }, + { CYCLES_IMUL8_ACC_MEM, { { 20, 20 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } }, + { CYCLES_IMUL16_ACC_REG, { { 25, 25 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } }, + { CYCLES_IMUL16_ACC_MEM, { { 28, 28 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } }, + { CYCLES_IMUL32_ACC_REG, { { 41, 41 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_IMUL32_ACC_MEM, { { 44, 44 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_IMUL8_REG_REG, { { 17, 17 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } }, + { CYCLES_IMUL8_REG_MEM, { { 20, 20 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } }, + { CYCLES_IMUL16_REG_REG, { { 25, 25 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } }, + { CYCLES_IMUL16_REG_MEM, { { 28, 28 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } }, + { CYCLES_IMUL32_REG_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_IMUL32_REG_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, + { CYCLES_IMUL16_REG_IMM_REG,{ { 26, 26 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } }, + { CYCLES_IMUL16_MEM_IMM_REG,{ { 27, 27 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } }, + { CYCLES_IMUL32_REG_IMM_REG,{ { 42, 42 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } }, + { CYCLES_IMUL32_MEM_IMM_REG,{ { 43, 43 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } }, + { CYCLES_DIV8_ACC_REG, { { 14, 14 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } }, + { CYCLES_DIV8_ACC_MEM, { { 17, 17 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } }, + { CYCLES_DIV16_ACC_REG, { { 22, 22 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } }, + { CYCLES_DIV16_ACC_MEM, { { 25, 25 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } }, + { CYCLES_DIV32_ACC_REG, { { 38, 38 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } }, + { CYCLES_DIV32_ACC_MEM, { { 41, 41 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } }, + { CYCLES_IDIV8_ACC_REG, { { 19, 19 }, { 19, 19 }, { 22, 22 }, { 20, 20 } } }, + { CYCLES_IDIV8_ACC_MEM, { { 22, 22 }, { 20, 20 }, { 22, 22 }, { 20, 20 } } }, + { CYCLES_IDIV16_ACC_REG, { { 27, 27 }, { 27, 27 }, { 30, 30 }, { 29, 29 } } }, + { CYCLES_IDIV16_ACC_MEM, { { 30, 30 }, { 28, 28 }, { 30, 30 }, { 29, 29 } } }, + { CYCLES_IDIV32_ACC_REG, { { 43, 43 }, { 43, 43 }, { 46, 46 }, { 45, 45 } } }, + { CYCLES_IDIV32_ACC_MEM, { { 46, 46 }, { 44, 44 }, { 46, 46 }, { 45, 45 } } }, + { CYCLES_AAD, { { 19, 19 }, { 14, 14 }, { 10, 10 }, { 7, 7 } } }, + { CYCLES_AAM, { { 17, 17 }, { 15, 15 }, { 18, 18 }, { 19, 19 } } }, + { CYCLES_CBW, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, + { CYCLES_CWD, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } }, + { CYCLES_ROTATE_REG, { { 3, 3 }, { 3, 3 }, { 1, 1 }, { 2, 2 } } }, + { CYCLES_ROTATE_MEM, { { 7, 7 }, { 4, 4 }, { 3, 3 }, { 2, 2 } } }, + { CYCLES_ROTATE_CARRY_REG, { { 9, 9 }, { 8, 8 }, { 7, 7 }, { 8, 8 } } }, + { CYCLES_ROTATE_CARRY_MEM, { { 10, 10 }, { 9, 9 }, { 8, 8 }, { 8, 8 } } }, + { CYCLES_SHLD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } }, + { CYCLES_SHLD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_SHRD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } }, + { CYCLES_SHRD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_NOT_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_NOT_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_CMPS, { { 10, 10 }, { 8, 8 }, { 5, 5 }, { 6, 6 } } }, + { CYCLES_INS, { { 15, 29 }, { 17, 30 }, { 9, 22 }, { 11, 11 } } }, + { CYCLES_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_OUTS, { { 14, 28 }, { 17, 30 }, { 13, 25 }, { 15, 15 } } }, + { CYCLES_SCAS, { { 8, 8 }, { 6, 6 }, { 4, 4 }, { 2, 2 } } }, + { CYCLES_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } }, + { CYCLES_XLAT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } }, + { CYCLES_REP_CMPS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 11, 11 } } }, + { CYCLES_REP_INS_BASE, { { 14, 8 }, { 0, 0 }, { 0, 0 }, { 17, 17 } } }, + { CYCLES_REP_LODS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, + { CYCLES_REP_MOVS_BASE, { { 8, 8 }, { 0, 0 }, { 0, 0 }, { 12, 12 } } }, + { CYCLES_REP_OUTS_BASE, { { 12, 6 }, { 0, 0 }, { 0, 0 }, { 24, 24 } } }, + { CYCLES_REP_SCAS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, + { CYCLES_REP_STOS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, + { CYCLES_REP_CMPS, { { 5, 5 }, { 8, 8 }, { 5, 5 }, { 4, 4 } } }, + { CYCLES_REP_INS, { { 14, 8 }, { 17, 30 }, { 9, 22 }, { 4, 4 } } }, + { CYCLES_REP_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 2, 2 } } }, + { CYCLES_REP_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 2, 2 } } }, + { CYCLES_REP_OUTS, { { 12, 6 }, { 17, 30 }, { 13, 25 }, { 4, 4 } } }, + { CYCLES_REP_SCAS, { { 5, 5 }, { 6, 6 }, { 4, 4 }, { 3, 3 } } }, + { CYCLES_REP_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } }, + { CYCLES_BSF_BASE, { { 11, 11 }, { 6, 6 }, { 6, 6 }, { 4, 4 } } }, + { CYCLES_BSF, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_BSR_BASE, { { 9, 9 }, { 6, 6 }, { 7, 7 }, { 4, 4 } } }, + { CYCLES_BSR, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_BT_IMM_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_BT_IMM_MEM, { { 6, 6 }, { 6, 6 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_BT_REG_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_BT_REG_MEM, { { 12, 12 }, { 12, 12 }, { 9, 9 }, { 7, 7 } } }, + { CYCLES_BTC_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTC_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, + { CYCLES_BTC_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTC_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, + { CYCLES_BTR_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTR_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, + { CYCLES_BTR_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTR_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, + { CYCLES_BTS_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTS_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, + { CYCLES_BTS_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, + { CYCLES_BTS_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, + { CYCLES_CALL, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 3, 3 } } }, + { CYCLES_CALL_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_CALL_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 4, 4 } } }, + { CYCLES_CALL_INTERSEG, { { 17, 34 }, { 18, 20 }, { 4, 13 }, { 9, 14 } } }, + { CYCLES_CALL_REG_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } }, + { CYCLES_CALL_MEM_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } }, + { CYCLES_JMP_SHORT, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JMP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JMP_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_JMP_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_JMP_INTERSEG, { { 12, 27 }, { 17, 19 }, { 3, 3 }, { 8, 12 } } }, + { CYCLES_JMP_REG_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 10 } } }, + { CYCLES_JMP_MEM_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 13 } } }, + { CYCLES_RET, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_RET_IMM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, + { CYCLES_RET_INTERSEG, { { 18, 32 }, { 13, 13 }, { 4, 4 }, { 10, 13 } } }, + { CYCLES_RET_IMM_INTERSEG, { { 18, 32 }, { 14, 14 }, { 4, 4 }, { 10, 13 } } }, + { CYCLES_JCC_DISP8, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JCC_FULL_DISP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JCC_DISP8_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JCC_FULL_DISP_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_JCXZ, { { 9, 9 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } }, + { CYCLES_JCXZ_NOBRANCH, { { 5, 5 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } }, + { CYCLES_LOOP, { { 11, 11 }, { 6, 6 }, { 5, 5 }, { 2, 2 } } }, + { CYCLES_LOOPZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } }, + { CYCLES_LOOPNZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } }, + { CYCLES_SETCC_REG, { { 4, 4 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_SETCC_MEM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_ENTER, { { 10, 10 }, { 14, 14 }, { 11, 11 }, { 13, 13 } } }, + { CYCLES_LEAVE, { { 4, 4 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_INT, { { 37, 37 }, { 30, 30 }, { 16, 16 }, { 19, 19 } } }, + { CYCLES_INT3, { { 33, 33 }, { 26, 26 }, { 13, 13 }, { 19, 19 } } }, + { CYCLES_INTO_OF1, { { 35, 35 }, { 28, 28 }, { 13, 13 }, { 19, 19 } } }, + { CYCLES_INTO_OF0, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } }, + { CYCLES_BOUND_IN_RANGE, { { 10, 10 }, { 7, 7 }, { 8, 8 }, { 7, 7 } } }, + { CYCLES_BOUND_OUT_RANGE, { { 44, 44 }, { 7, 7 }, { 8, 8 }, { 8, 8 } } }, + { CYCLES_IRET, { { 22, 22 }, { 15, 15 }, { 8, 8 }, { 13, 13 } } }, + { CYCLES_HLT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 10, 10 } } }, + { CYCLES_MOV_REG_CR0, { { 11, 11 }, { 16, 16 }, { 16, 16 }, { 20, 18 } } }, + { CYCLES_MOV_REG_CR2, { { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } }, + { CYCLES_MOV_REG_CR3, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 6 } } }, + { CYCLES_MOV_CR_REG, { { 6, 6 }, { 4, 4 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_MOV_REG_DR0_3, { { 22, 22 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, + { CYCLES_MOV_REG_DR6_7, { { 16, 16 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, + { CYCLES_MOV_DR6_7_REG, { { 14, 14 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } }, + { CYCLES_MOV_DR0_3_REG, { { 22, 22 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } }, + { CYCLES_MOV_REG_TR6_7, { { 12, 12 }, { 4, 4 }, { 4, 4 }, { 11, 11 } } }, + { CYCLES_MOV_TR6_7_REG, { { 12, 12 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, + { CYCLES_NOP, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_WAIT, { { 7, 7 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_ARPL_REG, { { 0, 20 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } }, + { CYCLES_ARPL_MEM, { { 0, 21 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } }, + { CYCLES_LAR_REG, { { 0, 15 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } }, + { CYCLES_LAR_MEM, { { 0, 16 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } }, + { CYCLES_LGDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } }, + { CYCLES_LIDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } }, + { CYCLES_LLDT_REG, { { 0, 20 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } }, + { CYCLES_LLDT_MEM, { { 0, 24 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } }, + { CYCLES_LMSW_REG, { { 11, 11 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } }, + { CYCLES_LMSW_MEM, { { 14, 14 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } }, + { CYCLES_LSL_REG, { { 0, 21 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } }, + { CYCLES_LSL_MEM, { { 0, 22 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } }, + { CYCLES_LTR_REG, { { 0, 23 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } }, + { CYCLES_LTR_MEM, { { 0, 27 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } }, + { CYCLES_SGDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_SIDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } }, + { CYCLES_SLDT_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 1 } } }, + { CYCLES_SLDT_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 1 } } }, + { CYCLES_SMSW_REG, { { 2, 2 }, { 2, 2 }, { 4, 4 }, { 4, 4 } } }, + { CYCLES_SMSW_MEM, { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } }, + { CYCLES_STR_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 3 } } }, + { CYCLES_STR_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 3 } } }, + { CYCLES_VERR_REG, { { 0, 10 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, + { CYCLES_VERR_MEM, { { 0, 11 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, + { CYCLES_VERW_REG, { { 0, 15 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, + { CYCLES_VERW_MEM, { { 0, 16 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, + { CYCLES_LOCK, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, + + /* i486+ */ + { CYCLES_BSWAP, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 6, 6 } } }, + { CYCLES_CMPXCHG, { { 0, 0 }, { 6, 6 }, { 5, 5 }, { 6, 6 } } }, + { CYCLES_INVD, { { 0, 0 }, { 4, 4 }, { 15, 15 }, { 20, 20 } } }, + { CYCLES_XADD, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 2, 2 } } }, + + /* Pentium+ */ + { CYCLES_CMPXCHG8B, { { 0, 0 }, { 0, 0 }, { 10, 10 }, { 6, 6 } } }, + { CYCLES_CPUID, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } }, + { CYCLES_CPUID_EAX1, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } }, + { CYCLES_RDTSC, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } }, + { CYCLES_RSM, { { 0, 0 }, { 0, 0 }, { 82, 82 }, { 57, 57 } } }, + { CYCLES_RDMSR, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } }, + + /* FPU */ + { CYCLES_FABS, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FADD, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_FBLD, { { 0, 0 }, { 70, 70 }, { 48, 48 }, { 1, 1 } } }, + { CYCLES_FBSTP, { { 0, 0 }, {172,172 }, {148,148 }, { 1, 1 } } }, + { CYCLES_FCHS, { { 0, 0 }, { 6, 6 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FCLEX, { { 0, 0 }, { 7, 7 }, { 9, 9 }, { 1, 1 } } }, + { CYCLES_FCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_FCOS, { { 0, 0 }, {255,255 }, {124,124 }, { 1, 1 } } }, + { CYCLES_FDECSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FDISI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FDIV, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } }, + { CYCLES_FDIVR, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } }, + { CYCLES_FENI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FFREE, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FIADD, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } }, + { CYCLES_FICOM, { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 1, 1 } } }, + { CYCLES_FIDIV, { { 0, 0 }, { 85, 85 }, { 42, 42 }, { 1, 1 } } }, + { CYCLES_FILD, { { 0, 0 }, { 13, 13 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_FIMUL, { { 0, 0 }, { 23, 23 }, { 7, 7 }, { 1, 1 } } }, + { CYCLES_FINCSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FINIT, { { 0, 0 }, { 17, 17 }, { 16, 16 }, { 1, 1 } } }, + { CYCLES_FIST, { { 0, 0 }, { 29, 29 }, { 6, 6 }, { 1, 1 } } }, + { CYCLES_FISUB, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } }, + { CYCLES_FLD, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FLDZ, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_FLD1, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_FLDL2E, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, + { CYCLES_FLDL2T, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, + { CYCLES_FLDLG2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, + { CYCLES_FLDLN2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, + { CYCLES_FLDPI, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, + { CYCLES_FLDCW, { { 0, 0 }, { 4, 4 }, { 7, 7 }, { 1, 1 } } }, + { CYCLES_FLDENV, { { 0, 0 }, { 44, 44 }, { 37, 37 }, { 1, 1 } } }, + { CYCLES_FMUL, { { 0, 0 }, { 16, 16 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_FNOP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FPATAN, { { 0, 0 }, {218,218 }, {173,173 }, { 1, 1 } } }, + { CYCLES_FPREM, { { 0, 0 }, { 70, 70 }, { 16, 16 }, { 1, 1 } } }, + { CYCLES_FPREM1, { { 0, 0 }, { 72, 72 }, { 20, 20 }, { 1, 1 } } }, + { CYCLES_FPTAN, { { 0, 0 }, {200,200 }, {173,173 }, { 1, 1 } } }, + { CYCLES_FRNDINT, { { 0, 0 }, { 21, 21 }, { 9, 9 }, { 1, 1 } } }, + { CYCLES_FRSTOR, { { 0, 0 }, {131,131 }, { 75, 75 }, { 1, 1 } } }, + { CYCLES_FSAVE, { { 0, 0 }, {154,154 }, {127,127 }, { 1, 1 } } }, + { CYCLES_FSCALE, { { 0, 0 }, { 30, 30 }, { 20, 20 }, { 1, 1 } } }, + { CYCLES_FSETPM, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FSIN, { { 0, 0 }, {255,255 }, {126,126 }, { 1, 1 } } }, + { CYCLES_FSINCOS, { { 0, 0 }, {255,255 }, {137,137 }, { 1, 1 } } }, + { CYCLES_FSQRT, { { 0, 0 }, { 83, 83 }, { 70, 70 }, { 1, 1 } } }, + { CYCLES_FST, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FSTCW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_FSTENV, { { 0, 0 }, { 67, 67 }, { 48, 48 }, { 1, 1 } } }, + { CYCLES_FSTSW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, + { CYCLES_FSUB, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_FSUBR, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, + { CYCLES_FTST, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_FUCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, + { CYCLES_FXAM, { { 0, 0 }, { 8, 8 }, { 21, 21 }, { 1, 1 } } }, + { CYCLES_FXCH, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, + { CYCLES_FXTRACT, { { 0, 0 }, { 16, 16 }, { 13, 13 }, { 1, 1 } } }, + { CYCLES_FYL2X, { { 0, 0 }, {196,196 }, {111,111 }, { 1, 1 } } }, + { CYCLES_FYL2XPI, { { 0, 0 }, {171,171 }, {103,103 }, { 1, 1 } } }, + { CYCLES_CMPXCHG_REG_REG_T, { { 0, 0 }, { 6, 6 }, { 6, 6 }, { 6, 6 } } }, + { CYCLES_CMPXCHG_REG_REG_F, { { 0, 0 }, { 9, 9 }, { 9, 9 }, { 9, 9 } } }, + { CYCLES_CMPXCHG_REG_MEM_T, { { 0, 0 }, { 7, 7 }, { 7, 7 }, { 7, 7 } } }, + { CYCLES_CMPXCHG_REG_MEM_F, { { 0, 0 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, +}; + +#endif /* __CYCLES_H__ */ diff --git a/src/cpu/i386/i386.c b/src/cpu/i386/i386.c new file mode 100644 index 00000000..2b1c4deb --- /dev/null +++ b/src/cpu/i386/i386.c @@ -0,0 +1,868 @@ +/* + Intel 386 emulator + + Written by Ville Linde + + Currently supports: + Intel 386 + Intel 486 + Intel Pentium + Cyrix MediaGX +*/ + +#include +#include "driver.h" +#include "state.h" +#include "i386priv.h" +#include "i386.h" +#include "mamedbg.h" + +int i386_ICount; + +/* the 0.139 core stops on what it does not implement; here it is logged once */ +static void i386_fatal(const char *fmt, ...) +{ + static int reported; + if (!reported) + { + char buf[256]; + va_list va; + va_start(va, fmt); + vsprintf(buf, fmt, va); + va_end(va); + log_cb(RETRO_LOG_ERROR, LOGPRE "%s\n", buf); + reported = 1; + } +} + +/* seems to be defined on mingw-gcc */ +#undef i386 + +int i386_parity_table[256]; +MODRM_TABLE i386_MODRM_table[256]; + +/*************************************************************************/ + +#define INT_DEBUG 1 + +static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg ) +{ + UINT32 v1,v2; + UINT32 base, limit; + int entry; + + if ( seg->selector & 0x4 ) + { + base = cpustate->ldtr.base; + limit = cpustate->ldtr.limit; + } else { + base = cpustate->gdtr.base; + limit = cpustate->gdtr.limit; + } + + if (limit == 0 || seg->selector + 7 > limit) + return; + entry = seg->selector & ~0x7; + + v1 = READ32(cpustate, base + entry ); + v2 = READ32(cpustate, base + entry + 4 ); + + seg->flags = (v2 >> 8) & 0xf0ff; + seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff); + seg->limit = (v2 & 0xf0000) | (v1 & 0xffff); + if (seg->flags & 0x8000) + seg->limit = (seg->limit << 12) | 0xfff; + seg->d = (seg->flags & 0x4000) ? 1 : 0; +} + +static void i386_load_segment_descriptor(i386_state *cpustate, int segment ) +{ + if (PROTECTED_MODE) + { + if (!V8086_MODE) + i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment] ); + else + { + cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; + cpustate->sreg[segment].limit = 0xffff; + cpustate->sreg[segment].flags = (segment == CS) ? 0x009a : 0x0092; + } + } + else + { + cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; + + if( segment == CS && !cpustate->performed_intersegment_jump ) + cpustate->sreg[segment].base |= 0xfff00000; + } +} + +static UINT32 get_flags(i386_state *cpustate) +{ + UINT32 f = 0x2; + f |= cpustate->CF; + f |= cpustate->PF << 2; + f |= cpustate->AF << 4; + f |= cpustate->ZF << 6; + f |= cpustate->SF << 7; + f |= cpustate->TF << 8; + f |= cpustate->IF << 9; + f |= cpustate->DF << 10; + f |= cpustate->OF << 11; + f |= cpustate->IOP1 << 12; + f |= cpustate->IOP2 << 13; + f |= cpustate->NT << 14; + return (cpustate->eflags & cpustate->eflags_mask) | (f & 0xffff); +} + +static void set_flags(i386_state *cpustate, UINT32 f ) +{ + cpustate->CF = (f & 0x1) ? 1 : 0; + cpustate->PF = (f & 0x4) ? 1 : 0; + cpustate->AF = (f & 0x10) ? 1 : 0; + cpustate->ZF = (f & 0x40) ? 1 : 0; + cpustate->SF = (f & 0x80) ? 1 : 0; + cpustate->TF = (f & 0x100) ? 1 : 0; + cpustate->IF = (f & 0x200) ? 1 : 0; + cpustate->DF = (f & 0x400) ? 1 : 0; + cpustate->OF = (f & 0x800) ? 1 : 0; + cpustate->IOP1 = (f & 0x1000) ? 1 : 0; + cpustate->IOP2 = (f & 0x2000) ? 1 : 0; + cpustate->NT = (f & 0x4000) ? 1 : 0; + cpustate->eflags = f & cpustate->eflags_mask; +} + +static void sib_byte(i386_state *cpustate,UINT8 mod, UINT32* out_ea, UINT8* out_segment) +{ + UINT32 ea = 0; + UINT8 segment = 0; + UINT8 scale, i, base; + UINT8 sib = FETCH(cpustate); + scale = (sib >> 6) & 0x3; + i = (sib >> 3) & 0x7; + base = sib & 0x7; + + switch( base ) + { + case 0: ea = REG32(EAX); segment = DS; break; + case 1: ea = REG32(ECX); segment = DS; break; + case 2: ea = REG32(EDX); segment = DS; break; + case 3: ea = REG32(EBX); segment = DS; break; + case 4: ea = REG32(ESP); segment = SS; break; + case 5: + if( mod == 0 ) { + ea = FETCH32(cpustate); + segment = DS; + } else if( mod == 1 ) { + ea = REG32(EBP); + segment = SS; + } else if( mod == 2 ) { + ea = REG32(EBP); + segment = SS; + } + break; + case 6: ea = REG32(ESI); segment = DS; break; + case 7: ea = REG32(EDI); segment = DS; break; + } + switch( i ) + { + case 0: ea += REG32(EAX) * (1 << scale); break; + case 1: ea += REG32(ECX) * (1 << scale); break; + case 2: ea += REG32(EDX) * (1 << scale); break; + case 3: ea += REG32(EBX) * (1 << scale); break; + case 4: break; + case 5: ea += REG32(EBP) * (1 << scale); break; + case 6: ea += REG32(ESI) * (1 << scale); break; + case 7: ea += REG32(EDI) * (1 << scale); break; + } + *out_ea = ea; + *out_segment = segment; +} + +static void modrm_to_EA(i386_state *cpustate,UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment) +{ + INT8 disp8; + INT16 disp16; + INT32 disp32; + UINT8 mod = (mod_rm >> 6) & 0x3; + UINT8 rm = mod_rm & 0x7; + UINT32 ea; + UINT8 segment; + + if( mod_rm >= 0xc0 ) + i386_fatal("i386: Called modrm_to_EA with modrm value %02X !",mod_rm); + + if( cpustate->address_size ) { + switch( rm ) + { + default: + case 0: ea = REG32(EAX); segment = DS; break; + case 1: ea = REG32(ECX); segment = DS; break; + case 2: ea = REG32(EDX); segment = DS; break; + case 3: ea = REG32(EBX); segment = DS; break; + case 4: sib_byte(cpustate, mod, &ea, &segment ); break; + case 5: + if( mod == 0 ) { + ea = FETCH32(cpustate); segment = DS; + } else { + ea = REG32(EBP); segment = SS; + } + break; + case 6: ea = REG32(ESI); segment = DS; break; + case 7: ea = REG32(EDI); segment = DS; break; + } + if( mod == 1 ) { + disp8 = FETCH(cpustate); + ea += (INT32)disp8; + } else if( mod == 2 ) { + disp32 = FETCH32(cpustate); + ea += disp32; + } + + if( cpustate->segment_prefix ) + segment = cpustate->segment_override; + + *out_ea = ea; + *out_segment = segment; + + } else { + switch( rm ) + { + default: + case 0: ea = REG16(BX) + REG16(SI); segment = DS; break; + case 1: ea = REG16(BX) + REG16(DI); segment = DS; break; + case 2: ea = REG16(BP) + REG16(SI); segment = SS; break; + case 3: ea = REG16(BP) + REG16(DI); segment = SS; break; + case 4: ea = REG16(SI); segment = DS; break; + case 5: ea = REG16(DI); segment = DS; break; + case 6: + if( mod == 0 ) { + ea = FETCH16(cpustate); segment = DS; + } else { + ea = REG16(BP); segment = SS; + } + break; + case 7: ea = REG16(BX); segment = DS; break; + } + if( mod == 1 ) { + disp8 = FETCH(cpustate); + ea += (INT32)disp8; + } else if( mod == 2 ) { + disp16 = FETCH16(cpustate); + ea += (INT32)disp16; + } + + if( cpustate->segment_prefix ) + segment = cpustate->segment_override; + + *out_ea = ea & 0xffff; + *out_segment = segment; + } +} + +static UINT32 GetNonTranslatedEA(i386_state *cpustate,UINT8 modrm) +{ + UINT8 segment; + UINT32 ea; + modrm_to_EA(cpustate, modrm, &ea, &segment ); + return ea; +} + +static UINT32 GetEA(i386_state *cpustate,UINT8 modrm) +{ + UINT8 segment; + UINT32 ea; + modrm_to_EA(cpustate, modrm, &ea, &segment ); + return i386_translate(cpustate, segment, ea ); +} + +static void i386_trap(i386_state *cpustate,int irq, int irq_gate) +{ + /* I386 Interrupts/Traps/Faults: + * + * 0x00 Divide by zero + * 0x01 Debug exception + * 0x02 NMI + * 0x03 Int3 + * 0x04 Overflow + * 0x05 Array bounds check + * 0x06 Illegal Opcode + * 0x07 FPU not available + * 0x08 Double fault + * 0x09 Coprocessor segment overrun + * 0x0a Invalid task state + * 0x0b Segment not present + * 0x0c Stack exception + * 0x0d General Protection Fault + * 0x0e Page fault + * 0x0f Reserved + * 0x10 Coprocessor error + */ + UINT32 v1, v2; + UINT32 offset; + UINT16 segment; + int entry = irq * (PROTECTED_MODE ? 8 : 4); + + /* Check if IRQ is out of IDTR's bounds */ + if( entry > cpustate->idtr.limit ) { + i386_fatal("I386 Interrupt: IRQ out of IDTR bounds (IRQ: %d, IDTR Limit: %d)", irq, cpustate->idtr.limit); + } + + if( !(PROTECTED_MODE) ) + { + /* 16-bit */ + PUSH16(cpustate, get_flags(cpustate) & 0xffff ); + PUSH16(cpustate, cpustate->sreg[CS].selector ); + PUSH16(cpustate, cpustate->eip ); + + cpustate->sreg[CS].selector = READ16(cpustate, cpustate->idtr.base + entry + 2 ); + cpustate->eip = READ16(cpustate, cpustate->idtr.base + entry ); + + /* Interrupts that vector through either interrupt gates or trap gates cause TF */ + /* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */ + cpustate->TF = 0; + + if (irq_gate) + { + cpustate->IF = 0; + } + + } + else + { + int type; + /* 32-bit */ + + v1 = READ32(cpustate, cpustate->idtr.base + entry ); + v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 ); + offset = (v2 & 0xffff0000) | (v1 & 0xffff); + segment = (v1 >> 16) & 0xffff; + type = (v2>>8) & 0x1F; + + if(type != 0x0e && type != 0x0f) /* if not 386 interrupt or trap gate */ + { + PUSH16(cpustate, get_flags(cpustate) & 0xffff ); + PUSH16(cpustate, cpustate->sreg[CS].selector ); + PUSH16(cpustate, cpustate->eip ); + } + else + { + PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff ); + PUSH32(cpustate, cpustate->sreg[CS].selector ); + PUSH32(cpustate, cpustate->eip ); + } + + cpustate->sreg[CS].selector = segment; + cpustate->eip = offset; + + /* Interrupts that vector through either interrupt gates or trap gates cause TF */ + /* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */ + if ((type == 14) || (type==15)) + cpustate->TF = 0; + + if (type == 14) + { + cpustate->IF = 0; + } + + } + + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + +} + +static void i386_check_irq_line(i386_state *cpustate) +{ + /* Check if the interrupts are enabled */ + if ( (cpustate->irq_state) && cpustate->IF ) + { + i386_ICount -= 2; + i386_trap(cpustate,cpustate->irq_callback(0), 1); + } +} + +#include "cycles.h" + +static UINT8 *cycle_table_rm[X86_NUM_CPUS]; +static UINT8 *cycle_table_pm[X86_NUM_CPUS]; + +#define CYCLES_NUM(x) (i386_ICount -= (x)) + +static INLINE void CYCLES(i386_state *cpustate,int x) +{ + if (PROTECTED_MODE) + { + i386_ICount -= cpustate->cycle_table_pm[x]; + } + else + { + i386_ICount -= cpustate->cycle_table_rm[x]; + } +} + +static INLINE void CYCLES_RM(i386_state *cpustate,int modrm, int r, int m) +{ + if (modrm >= 0xc0) + { + if (PROTECTED_MODE) + { + i386_ICount -= cpustate->cycle_table_pm[r]; + } + else + { + i386_ICount -= cpustate->cycle_table_rm[r]; + } + } + else + { + if (PROTECTED_MODE) + { + i386_ICount -= cpustate->cycle_table_pm[m]; + } + else + { + i386_ICount -= cpustate->cycle_table_rm[m]; + } + } +} + +static UINT8 cycle_tables[X86_NUM_CPUS][2][CYCLES_NUM_OPCODES]; + +static void build_cycle_table(void) +{ + int i, j; + for (j=0; j < X86_NUM_CPUS; j++) + { + cycle_table_rm[j] = cycle_tables[j][0]; + cycle_table_pm[j] = cycle_tables[j][1]; + + for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++) + { + int opcode = x86_cycle_table[i].op; + cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0]; + cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1]; + } + } +} + +/* Forward declarations */ +static void I386OP(decode_opcode)(i386_state *cpustate); +static void I386OP(decode_two_byte)(i386_state *cpustate); + + + +#include "i386ops.c" +#include "i386op16.c" +#include "i386op32.c" +#include "i486ops.c" +#include "pentops.c" +#include "x87ops.c" +#include "i386ops.h" + +static void I386OP(decode_opcode)(i386_state *cpustate) +{ + cpustate->opcode = FETCH(cpustate); + if( cpustate->operand_size ) + cpustate->opcode_table1_32[cpustate->opcode](cpustate); + else + cpustate->opcode_table1_16[cpustate->opcode](cpustate); +} + +/* Two-byte opcode prefix */ +static void I386OP(decode_two_byte)(i386_state *cpustate) +{ + cpustate->opcode = FETCH(cpustate); + if( cpustate->operand_size ) + cpustate->opcode_table2_32[cpustate->opcode](cpustate); + else + cpustate->opcode_table2_16[cpustate->opcode](cpustate); +} + +/*************************************************************************/ + +static void build_opcode_table(i386_state *cpustate, UINT32 features) +{ + int i; + for (i=0; i < 256; i++) + { + cpustate->opcode_table1_16[i] = I386OP(invalid); + cpustate->opcode_table1_32[i] = I386OP(invalid); + cpustate->opcode_table2_16[i] = I386OP(invalid); + cpustate->opcode_table2_32[i] = I386OP(invalid); + } + + for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++) + { + const X86_OPCODE *op = &x86_opcode_table[i]; + + if ((op->flags & features)) + { + if (op->flags & OP_2BYTE) + { + cpustate->opcode_table2_32[op->opcode] = op->handler32; + cpustate->opcode_table2_16[op->opcode] = op->handler16; + } + else + { + cpustate->opcode_table1_32[op->opcode] = op->handler32; + cpustate->opcode_table1_16[op->opcode] = op->handler16; + } + } + } +} + + +/************************************************************************* + + The interface of the CPU core (MAME 0.78 style): one context, copied + in and out by the CPU switch + +*************************************************************************/ + +static i386_state I; + +static void i386_postload(void) +{ + i386_state *cpustate = &I; + int i; + for (i = 0; i < 6; i++) + i386_load_segment_descriptor(cpustate,i); + CHANGE_PC(cpustate,cpustate->eip); +} + +/* the fast memory regions of the driver */ +static struct +{ + UINT32 start, end; + UINT8 *base; + int flags; +} i386_fastmem[I386_FASTMEM_MAX]; +static int i386_fastmem_count; + +void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags) +{ + if (i386_fastmem_count < I386_FASTMEM_MAX) + { + i386_fastmem[i386_fastmem_count].start = start; + i386_fastmem[i386_fastmem_count].end = end; + i386_fastmem[i386_fastmem_count].base = base; + i386_fastmem[i386_fastmem_count].flags = flags; + i386_fastmem_count++; + } + /* empty the caches */ + memset(I.fast_size, 0, sizeof(I.fast_size)); +} + +/* a miss of the cache: the region of the address, cached; NULL if none */ +static UINT8 *i386_fast_lookup(i386_state *cpustate, UINT32 address, UINT32 len, int kind) +{ + int i; + + for (i = 0; i < i386_fastmem_count; i++) + { + if ((i386_fastmem[i].flags & (1 << kind)) && address >= i386_fastmem[i].start && + address <= i386_fastmem[i].end && i386_fastmem[i].end - address >= len - 1) + { + cpustate->fast_start[kind] = i386_fastmem[i].start; + cpustate->fast_size[kind] = i386_fastmem[i].end - i386_fastmem[i].start + 1; + cpustate->fast_base[kind] = i386_fastmem[i].base; + return i386_fastmem[i].base + (address - i386_fastmem[i].start); + } + } + return NULL; +} + +void i386_init(void) +{ + int i, j; + static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH}; + static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI}; + static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI}; + int cpu = cpu_getactivecpu(); + i386_state *cpustate = &I; + static const char *const sregname[6] = { "es", "cs", "ss", "ds", "fs", "gs" }; + + i386_fastmem_count = 0; + memset(I.fast_size, 0, sizeof(I.fast_size)); + build_cycle_table(); + + for( i=0; i < 256; i++ ) { + int c=0; + for( j=0; j < 8; j++ ) { + if( i & (1 << j) ) + c++; + } + i386_parity_table[i] = ~(c & 0x1) & 0x1; + } + + for( i=0; i < 256; i++ ) { + i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7]; + i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7]; + i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7]; + + i386_MODRM_table[i].rm.b = regs8[i & 0x7]; + i386_MODRM_table[i].rm.w = regs16[i & 0x7]; + i386_MODRM_table[i].rm.d = regs32[i & 0x7]; + } + + state_save_register_UINT32("i386", cpu, "reg", cpustate->reg.d, 8); + for (i = 0; i < 6; i++) + { + char name[16]; + sprintf(name, "%s_sel", sregname[i]); + state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].selector, 1); + sprintf(name, "%s_flags", sregname[i]); + state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].flags, 1); + sprintf(name, "%s_base", sregname[i]); + state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].base, 1); + sprintf(name, "%s_limit", sregname[i]); + state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].limit, 1); + sprintf(name, "%s_d", sregname[i]); + state_save_register_int("i386", cpu, name, &cpustate->sreg[i].d); + } + state_save_register_UINT32("i386", cpu, "eip", &cpustate->eip, 1); + state_save_register_UINT32("i386", cpu, "pc", &cpustate->pc, 1); + state_save_register_UINT32("i386", cpu, "prev_eip", &cpustate->prev_eip, 1); + state_save_register_UINT32("i386", cpu, "eflags", &cpustate->eflags, 1); + state_save_register_UINT32("i386", cpu, "eflags_mask", &cpustate->eflags_mask, 1); + state_save_register_UINT8("i386", cpu, "CF", &cpustate->CF, 1); + state_save_register_UINT8("i386", cpu, "DF", &cpustate->DF, 1); + state_save_register_UINT8("i386", cpu, "SF", &cpustate->SF, 1); + state_save_register_UINT8("i386", cpu, "OF", &cpustate->OF, 1); + state_save_register_UINT8("i386", cpu, "ZF", &cpustate->ZF, 1); + state_save_register_UINT8("i386", cpu, "PF", &cpustate->PF, 1); + state_save_register_UINT8("i386", cpu, "AF", &cpustate->AF, 1); + state_save_register_UINT8("i386", cpu, "IF", &cpustate->IF, 1); + state_save_register_UINT8("i386", cpu, "TF", &cpustate->TF, 1); + state_save_register_UINT8("i386", cpu, "IOP1", &cpustate->IOP1, 1); + state_save_register_UINT8("i386", cpu, "IOP2", &cpustate->IOP2, 1); + state_save_register_UINT8("i386", cpu, "NT", &cpustate->NT, 1); + state_save_register_UINT32("i386", cpu, "cr", cpustate->cr, 5); + state_save_register_UINT32("i386", cpu, "dr", cpustate->dr, 8); + state_save_register_UINT32("i386", cpu, "tr", cpustate->tr, 8); + state_save_register_UINT32("i386", cpu, "idtr_base", &cpustate->idtr.base, 1); + state_save_register_UINT16("i386", cpu, "idtr_limit", &cpustate->idtr.limit, 1); + state_save_register_UINT32("i386", cpu, "gdtr_base", &cpustate->gdtr.base, 1); + state_save_register_UINT16("i386", cpu, "gdtr_limit", &cpustate->gdtr.limit, 1); + state_save_register_UINT32("i386", cpu, "task_base", &cpustate->task.base, 1); + state_save_register_UINT16("i386", cpu, "task_segment", &cpustate->task.segment, 1); + state_save_register_UINT32("i386", cpu, "task_limit", &cpustate->task.limit, 1); + state_save_register_UINT16("i386", cpu, "task_flags", &cpustate->task.flags, 1); + state_save_register_UINT32("i386", cpu, "ldtr_base", &cpustate->ldtr.base, 1); + state_save_register_UINT16("i386", cpu, "ldtr_segment", &cpustate->ldtr.segment, 1); + state_save_register_UINT32("i386", cpu, "ldtr_limit", &cpustate->ldtr.limit, 1); + state_save_register_UINT16("i386", cpu, "ldtr_flags", &cpustate->ldtr.flags, 1); + state_save_register_int("i386", cpu, "halted", &cpustate->halted); + state_save_register_UINT8("i386", cpu, "irq_state", &cpustate->irq_state, 1); + state_save_register_UINT8("i386", cpu, "performed_intersegment_jump", &cpustate->performed_intersegment_jump, 1); + state_save_register_UINT32("i386", cpu, "a20_mask", &cpustate->a20_mask, 1); + state_save_register_func_postload(i386_postload); +} + +void i386_reset(void *param) +{ + i386_state *cpustate = &I; + int (*save_irqcallback)(int); + + save_irqcallback = cpustate->irq_callback; + memset( cpustate, 0, sizeof(*cpustate) ); + cpustate->irq_callback = save_irqcallback; + + cpustate->sreg[CS].selector = 0xf000; + cpustate->sreg[CS].base = 0xffff0000; + cpustate->sreg[CS].limit = 0xffff; + + cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; + cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; + cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092; + + cpustate->idtr.base = 0; + cpustate->idtr.limit = 0x3ff; + + cpustate->a20_mask = ~0; + + cpustate->cr[0] = 0x7ffffff0; /* reserved bits set to 1 */ + cpustate->eflags = 0; + cpustate->eflags_mask = 0x00030000; + cpustate->eip = 0xfff0; + + /* Family 3 (386), Model 0 (DX), Stepping 8 (D1) */ + REG32(EAX) = 0; + REG32(EDX) = (3 << 8) | (0 << 4) | (8); + + build_opcode_table(cpustate, OP_I386); + cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386]; + cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386]; + + CHANGE_PC(cpustate,cpustate->eip); +} + +void i386_exit(void) +{ +} + +int i386_execute(int cycles) +{ + i386_state *cpustate = &I; + + i386_ICount = cycles; + cpustate->base_cycles = cycles; + CHANGE_PC(cpustate,cpustate->eip); + + if (cpustate->halted) + { + cpustate->tsc += cycles; + i386_ICount = 0; + return cycles; + } + + while( i386_ICount > 0 ) + { + cpustate->operand_size = cpustate->sreg[CS].d; + cpustate->address_size = cpustate->sreg[CS].d; + + cpustate->segment_prefix = 0; + cpustate->prev_eip = cpustate->eip; + + CALL_MAME_DEBUG; + + i386_check_irq_line(cpustate); + I386OP(decode_opcode)(cpustate); + } + cpustate->tsc += (cycles - i386_ICount); + return cycles - i386_ICount; +} + +unsigned i386_get_context(void *dst) +{ + if (dst) + *(i386_state *)dst = I; + return sizeof(i386_state); +} + +void i386_set_context(void *src) +{ + if (src) + I = *(i386_state *)src; +} + +unsigned i386_get_reg(int regnum) +{ + i386_state *cpustate = &I; + + switch (regnum) + { + case REG_PC: return cpustate->pc; + case REG_PREVIOUSPC: return cpustate->sreg[CS].base + cpustate->prev_eip; + case REG_SP: return cpustate->sreg[SS].base + REG32(ESP); + case I386_EIP: return cpustate->eip; + case I386_EAX: return REG32(EAX); + case I386_EBX: return REG32(EBX); + case I386_ECX: return REG32(ECX); + case I386_EDX: return REG32(EDX); + case I386_ESI: return REG32(ESI); + case I386_EDI: return REG32(EDI); + case I386_EBP: return REG32(EBP); + case I386_ESP: return REG32(ESP); + case I386_EFLAGS: return get_flags(cpustate); + case I386_CS: return cpustate->sreg[CS].selector; + case I386_SS: return cpustate->sreg[SS].selector; + case I386_DS: return cpustate->sreg[DS].selector; + case I386_ES: return cpustate->sreg[ES].selector; + case I386_FS: return cpustate->sreg[FS].selector; + case I386_GS: return cpustate->sreg[GS].selector; + case I386_CR0: return cpustate->cr[0]; + } + return 0; +} + +void i386_set_reg(int regnum, unsigned val) +{ + i386_state *cpustate = &I; + + switch (regnum) + { + case REG_PC: + cpustate->eip = val - cpustate->sreg[CS].base; + CHANGE_PC(cpustate,cpustate->eip); + break; + case REG_SP: REG32(ESP) = val - cpustate->sreg[SS].base; break; + case I386_EIP: cpustate->eip = val; CHANGE_PC(cpustate,cpustate->eip); break; + case I386_EAX: REG32(EAX) = val; break; + case I386_EBX: REG32(EBX) = val; break; + case I386_ECX: REG32(ECX) = val; break; + case I386_EDX: REG32(EDX) = val; break; + case I386_ESI: REG32(ESI) = val; break; + case I386_EDI: REG32(EDI) = val; break; + case I386_EBP: REG32(EBP) = val; break; + case I386_ESP: REG32(ESP) = val; break; + case I386_EFLAGS: set_flags(cpustate, val); break; + } +} + +void i386_set_irq_line(int irqline, int state) +{ + i386_state *cpustate = &I; + + if (state != CLEAR_LINE && cpustate->halted) + { + cpustate->halted = 0; + } + + if ( irqline == IRQ_LINE_NMI ) + { + /* NMI (I do not think that this is 100% right) */ + if ( state ) + i386_trap(cpustate,2, 1); + } + else if ( irqline == I386_INPUT_LINE_A20 ) + { + cpustate->a20_mask = state ? ~0 : ~(1 << 20); + } + else + { + cpustate->irq_state = state; + } +} + +void i386_set_irq_callback(int (*callback)(int irqline)) +{ + I.irq_callback = callback; +} + +const char *i386_info(void *context, int regnum) +{ + static char buffer[16][47+1]; + static int which = 0; + i386_state *r = context ? (i386_state *)context : &I; + + which = (which + 1) % 16; + buffer[which][0] = '\0'; + + switch( regnum ) + { + case CPU_INFO_REG+I386_EIP: sprintf(buffer[which], "EIP:%08X", r->eip); break; + case CPU_INFO_REG+I386_EAX: sprintf(buffer[which], "EAX:%08X", r->reg.d[EAX]); break; + case CPU_INFO_REG+I386_EBX: sprintf(buffer[which], "EBX:%08X", r->reg.d[EBX]); break; + case CPU_INFO_REG+I386_ECX: sprintf(buffer[which], "ECX:%08X", r->reg.d[ECX]); break; + case CPU_INFO_REG+I386_EDX: sprintf(buffer[which], "EDX:%08X", r->reg.d[EDX]); break; + case CPU_INFO_REG+I386_ESI: sprintf(buffer[which], "ESI:%08X", r->reg.d[ESI]); break; + case CPU_INFO_REG+I386_EDI: sprintf(buffer[which], "EDI:%08X", r->reg.d[EDI]); break; + case CPU_INFO_REG+I386_EBP: sprintf(buffer[which], "EBP:%08X", r->reg.d[EBP]); break; + case CPU_INFO_REG+I386_ESP: sprintf(buffer[which], "ESP:%08X", r->reg.d[ESP]); break; + case CPU_INFO_FLAGS: sprintf(buffer[which], "%08X", r->eflags); break; + case CPU_INFO_NAME: return "I386"; + case CPU_INFO_FAMILY: return "Intel 386"; + case CPU_INFO_VERSION: return "1.0"; + case CPU_INFO_FILE: return __FILE__; + case CPU_INFO_CREDITS: return "Copyright Ville Linde"; + } + return buffer[which]; +} + +unsigned i386_dasm(char *buffer, unsigned pc) +{ + sprintf(buffer, "$%02X", cpu_readmem32ledw(pc)); + return 1; +} diff --git a/src/cpu/i386/i386.h b/src/cpu/i386/i386.h new file mode 100644 index 00000000..6b9c7af2 --- /dev/null +++ b/src/cpu/i386/i386.h @@ -0,0 +1,39 @@ +/*************************************************************************** + + Intel 386 emulator (Ville Linde), from MAME 0.139 + +***************************************************************************/ + +#ifndef I386INTF_H +#define I386INTF_H + +#include "cpuintrf.h" + +/* the A20 gate, as an input line */ +#define I386_INPUT_LINE_A20 1 + +extern int i386_ICount; + +/* the fast memory: a range of plain RAM or ROM at base, which the CPU */ +/* fetches, reads or writes directly (flags), without the memory handlers; */ +/* set from DRIVER_INIT, emptied at the CPU init. Little endian hosts only */ +#define I386_FASTMEM_MAX 8 +#define I386_FASTMEM_FETCH 1 +#define I386_FASTMEM_READ 2 +#define I386_FASTMEM_WRITE 4 +void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags); + +void i386_init(void); +void i386_reset(void *param); +void i386_exit(void); +int i386_execute(int cycles); +unsigned i386_get_context(void *dst); +void i386_set_context(void *src); +unsigned i386_get_reg(int regnum); +void i386_set_reg(int regnum, unsigned val); +void i386_set_irq_line(int irqline, int state); +void i386_set_irq_callback(int (*callback)(int irqline)); +const char *i386_info(void *context, int regnum); +unsigned i386_dasm(char *buffer, unsigned pc); + +#endif diff --git a/src/cpu/i386/i386op16.c b/src/cpu/i386/i386op16.c new file mode 100644 index 00000000..9e7abaff --- /dev/null +++ b/src/cpu/i386/i386op16.c @@ -0,0 +1,3257 @@ +static UINT16 I386OP(shift_rotate16)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift) +{ + UINT16 src = value; + UINT16 dst = value; + + if( shift == 0 ) { + CYCLES_RM(cpustate,modrm, 3, 7); + } else if( shift == 1 ) { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm16, 1 */ + cpustate->CF = (src & 0x8000) ? 1 : 0; + dst = (src << 1) + cpustate->CF; + cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm16, 1 */ + cpustate->CF = (src & 0x1) ? 1 : 0; + dst = (cpustate->CF << 15) | (src >> 1); + cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm16, 1 */ + dst = (src << 1) + cpustate->CF; + cpustate->CF = (src & 0x8000) ? 1 : 0; + cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm16, 1 */ + dst = (cpustate->CF << 15) | (src >> 1); + cpustate->CF = src & 0x1; + cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm16, 1 */ + case 6: + dst = src << 1; + cpustate->CF = (src & 0x8000) ? 1 : 0; + cpustate->OF = (((cpustate->CF << 15) ^ dst) & 0x8000) ? 1 : 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm16, 1 */ + dst = src >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = (dst & 0x8000) ? 1 : 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm16, 1 */ + dst = (INT16)(src) >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + } else { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm16, i8 */ + dst = ((src & ((UINT16)0xffff >> shift)) << shift) | + ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift)); + cpustate->CF = (src >> (16-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm16, i8 */ + dst = ((src & ((UINT16)0xffff << shift)) >> shift) | + ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm16, i8 */ + dst = ((src & ((UINT16)0xffff >> shift)) << shift) | + ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) | + (cpustate->CF << (shift-1)); + cpustate->CF = (src >> (16-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm16, i8 */ + dst = ((src & ((UINT16)0xffff << shift)) >> shift) | + ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) | + (cpustate->CF << (16-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm16, i8 */ + case 6: + dst = src << shift; + cpustate->CF = (src & (1 << (16-shift))) ? 1 : 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm16, i8 */ + dst = src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm16, i8 */ + dst = (INT16)src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF16(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + + } + return dst; +} + + + +static void I386OP(adc_rm16_r16)(i386_state *cpustate) /* Opcode 0x11 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = ADC16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = ADC16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(adc_r16_rm16)(i386_state *cpustate) /* Opcode 0x13 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = ADC16(cpustate, dst, src, cpustate->CF); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = ADC16(cpustate, dst, src, cpustate->CF); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(adc_ax_i16)(i386_state *cpustate) /* Opcode 0x15 */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = ADC16(cpustate, dst, src, cpustate->CF); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(add_rm16_r16)(i386_state *cpustate) /* Opcode 0x01 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = ADD16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = ADD16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(add_r16_rm16)(i386_state *cpustate) /* Opcode 0x03 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = ADD16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = ADD16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(add_ax_i16)(i386_state *cpustate) /* Opcode 0x05 */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = ADD16(cpustate,dst, src); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(and_rm16_r16)(i386_state *cpustate) /* Opcode 0x21 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = AND16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = AND16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(and_r16_rm16)(i386_state *cpustate) /* Opcode 0x23 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = AND16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = AND16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(and_ax_i16)(i386_state *cpustate) /* Opcode 0x25 */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = AND16(cpustate,dst, src); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(bsf_r16_rm16)(i386_state *cpustate) /* Opcode 0x0f bc */ +{ + UINT16 src, dst, temp; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + } + + dst = 0; + + if( src == 0 ) { + cpustate->ZF = 1; + } else { + cpustate->ZF = 0; + temp = 0; + while( (src & (1 << temp)) == 0 ) { + temp++; + dst = temp; + CYCLES(cpustate,CYCLES_BSF); + } + } + CYCLES(cpustate,CYCLES_BSF_BASE); + STORE_REG16(modrm, dst); +} + +static void I386OP(bsr_r16_rm16)(i386_state *cpustate) /* Opcode 0x0f bd */ +{ + UINT16 src, dst, temp; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + } + + dst = 0; + + if( src == 0 ) { + cpustate->ZF = 1; + } else { + cpustate->ZF = 0; + dst = temp = 15; + while( (src & (1 << temp)) == 0 ) { + temp--; + dst = temp; + CYCLES(cpustate,CYCLES_BSR); + } + } + CYCLES(cpustate,CYCLES_BSR_BASE); + STORE_REG16(modrm, dst); +} + + +static void I386OP(bt_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f a3 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_REG_MEM); + } +} + +static void I386OP(btc_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f bb */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTC_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTC_REG_MEM); + } +} + +static void I386OP(btr_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f b3 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTR_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTR_REG_MEM); + } +} + +static void I386OP(bts_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f ab */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTS_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 bit = LOAD_REG16(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTS_REG_MEM); + } +} + +static void I386OP(call_abs16)(i386_state *cpustate) /* Opcode 0x9a */ +{ + UINT16 offset = FETCH16(cpustate); + UINT16 ptr = FETCH16(cpustate); + + if( PROTECTED_MODE ) { + /* TODO */ + i386_fatal("i386: call_abs16 in protected mode unimplemented"); + } else { + if (cpustate->sreg[CS].d) + { + PUSH32(cpustate, cpustate->sreg[CS].selector ); + PUSH32(cpustate, cpustate->eip ); + } + else + { + PUSH16(cpustate, cpustate->sreg[CS].selector ); + PUSH16(cpustate, cpustate->eip ); + } + cpustate->sreg[CS].selector = ptr; + cpustate->eip = offset; + i386_load_segment_descriptor(cpustate,CS); + } + CYCLES(cpustate,CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */ + CHANGE_PC(cpustate,cpustate->eip); +} + +static void I386OP(call_rel16)(i386_state *cpustate) /* Opcode 0xe8 */ +{ + INT16 disp = FETCH16(cpustate); + + PUSH16(cpustate, cpustate->eip ); + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_CALL); /* TODO: Timing = 7 + m */ +} + +static void I386OP(cbw)(i386_state *cpustate) /* Opcode 0x98 */ +{ + REG16(AX) = (INT16)((INT8)REG8(AL)); + CYCLES(cpustate,CYCLES_CBW); +} + +static void I386OP(cmp_rm16_r16)(i386_state *cpustate) /* Opcode 0x39 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } +} + +static void I386OP(cmp_r16_rm16)(i386_state *cpustate) /* Opcode 0x3b */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_MEM_REG); + } +} + +static void I386OP(cmp_ax_i16)(i386_state *cpustate) /* Opcode 0x3d */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_IMM_ACC); +} + +static void I386OP(cmpsw)(i386_state *cpustate) /* Opcode 0xa7 */ +{ + UINT32 eas, ead; + UINT16 src, dst; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ16(cpustate,eas); + dst = READ16(cpustate,ead); + SUB16(cpustate,dst, src); + BUMP_SI(cpustate,2); + BUMP_DI(cpustate,2); + CYCLES(cpustate,CYCLES_CMPS); +} + +static void I386OP(cwd)(i386_state *cpustate) /* Opcode 0x99 */ +{ + if( REG16(AX) & 0x8000 ) { + REG16(DX) = 0xffff; + } else { + REG16(DX) = 0x0000; + } + CYCLES(cpustate,CYCLES_CWD); +} + +static void I386OP(dec_ax)(i386_state *cpustate) /* Opcode 0x48 */ +{ + REG16(AX) = DEC16(cpustate, REG16(AX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_cx)(i386_state *cpustate) /* Opcode 0x49 */ +{ + REG16(CX) = DEC16(cpustate, REG16(CX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_dx)(i386_state *cpustate) /* Opcode 0x4a */ +{ + REG16(DX) = DEC16(cpustate, REG16(DX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_bx)(i386_state *cpustate) /* Opcode 0x4b */ +{ + REG16(BX) = DEC16(cpustate, REG16(BX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_sp)(i386_state *cpustate) /* Opcode 0x4c */ +{ + REG16(SP) = DEC16(cpustate, REG16(SP) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_bp)(i386_state *cpustate) /* Opcode 0x4d */ +{ + REG16(BP) = DEC16(cpustate, REG16(BP) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_si)(i386_state *cpustate) /* Opcode 0x4e */ +{ + REG16(SI) = DEC16(cpustate, REG16(SI) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_di)(i386_state *cpustate) /* Opcode 0x4f */ +{ + REG16(DI) = DEC16(cpustate, REG16(DI) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(imul_r16_rm16)(i386_state *cpustate) /* Opcode 0x0f af */ +{ + UINT8 modrm = FETCH(cpustate); + INT32 result; + INT32 src, dst; + if( modrm >= 0xc0 ) { + src = (INT32)(INT16)LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = (INT32)(INT16)READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */ + } + + dst = (INT32)(INT16)LOAD_REG16(modrm); + result = src * dst; + + STORE_REG16(modrm, (UINT16)result); + + cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); +} + +static void I386OP(imul_r16_rm16_i16)(i386_state *cpustate) /* Opcode 0x69 */ +{ + UINT8 modrm = FETCH(cpustate); + INT32 result; + INT32 src, dst; + if( modrm >= 0xc0 ) { + dst = (INT32)(INT16)LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = (INT32)(INT16)READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ + } + + src = (INT32)(INT16)FETCH16(cpustate); + result = src * dst; + + STORE_REG16(modrm, (UINT16)result); + + cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); +} + +static void I386OP(imul_r16_rm16_i8)(i386_state *cpustate) /* Opcode 0x6b */ +{ + UINT8 modrm = FETCH(cpustate); + INT32 result; + INT32 src, dst; + if( modrm >= 0xc0 ) { + dst = (INT32)(INT16)LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = (INT32)(INT16)READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ + } + + src = (INT32)(INT8)FETCH(cpustate); + result = src * dst; + + STORE_REG16(modrm, (UINT16)result); + + cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); +} + +static void I386OP(in_ax_i8)(i386_state *cpustate) /* Opcode 0xe5 */ +{ + UINT16 port = FETCH(cpustate); + UINT16 data = READPORT16(port); + REG16(AX) = data; + CYCLES(cpustate,CYCLES_IN_VAR); +} + +static void I386OP(in_ax_dx)(i386_state *cpustate) /* Opcode 0xed */ +{ + UINT16 port = REG16(DX); + UINT16 data = READPORT16(port); + REG16(AX) = data; + CYCLES(cpustate,CYCLES_IN); +} + +static void I386OP(inc_ax)(i386_state *cpustate) /* Opcode 0x40 */ +{ + REG16(AX) = INC16(cpustate, REG16(AX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_cx)(i386_state *cpustate) /* Opcode 0x41 */ +{ + REG16(CX) = INC16(cpustate, REG16(CX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_dx)(i386_state *cpustate) /* Opcode 0x42 */ +{ + REG16(DX) = INC16(cpustate, REG16(DX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_bx)(i386_state *cpustate) /* Opcode 0x43 */ +{ + REG16(BX) = INC16(cpustate, REG16(BX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_sp)(i386_state *cpustate) /* Opcode 0x44 */ +{ + REG16(SP) = INC16(cpustate, REG16(SP) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_bp)(i386_state *cpustate) /* Opcode 0x45 */ +{ + REG16(BP) = INC16(cpustate, REG16(BP) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_si)(i386_state *cpustate) /* Opcode 0x46 */ +{ + REG16(SI) = INC16(cpustate, REG16(SI) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_di)(i386_state *cpustate) /* Opcode 0x47 */ +{ + REG16(DI) = INC16(cpustate, REG16(DI) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(iret16)(i386_state *cpustate) /* Opcode 0xcf */ +{ + if( PROTECTED_MODE ) { + /* TODO: Virtual 8086-mode */ + /* TODO: Nested task */ + /* TODO: #SS(0) exception */ + /* TODO: All the protection-related stuff... */ + cpustate->eip = POP16(cpustate); + cpustate->sreg[CS].selector = POP16(cpustate); + set_flags(cpustate, POP16(cpustate) ); + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } else { + /* TODO: #SS(0) exception */ + /* TODO: #GP(0) exception */ + cpustate->eip = POP16(cpustate); + cpustate->sreg[CS].selector = POP16(cpustate); + set_flags(cpustate, POP16(cpustate) ); + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_IRET); +} + +static void I386OP(ja_rel16)(i386_state *cpustate) /* Opcode 0x0f 87 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->CF == 0 && cpustate->ZF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jbe_rel16)(i386_state *cpustate) /* Opcode 0x0f 86 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->CF != 0 || cpustate->ZF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jc_rel16)(i386_state *cpustate) /* Opcode 0x0f 82 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->CF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jg_rel16)(i386_state *cpustate) /* Opcode 0x0f 8f */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jge_rel16)(i386_state *cpustate) /* Opcode 0x0f 8d */ +{ + INT16 disp = FETCH16(cpustate); + if( (cpustate->SF == cpustate->OF) ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jl_rel16)(i386_state *cpustate) /* Opcode 0x0f 8c */ +{ + INT16 disp = FETCH16(cpustate); + if( (cpustate->SF != cpustate->OF) ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jle_rel16)(i386_state *cpustate) /* Opcode 0x0f 8e */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnc_rel16)(i386_state *cpustate) /* Opcode 0x0f 83 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->CF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jno_rel16)(i386_state *cpustate) /* Opcode 0x0f 81 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->OF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnp_rel16)(i386_state *cpustate) /* Opcode 0x0f 8b */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->PF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jns_rel16)(i386_state *cpustate) /* Opcode 0x0f 89 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->SF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnz_rel16)(i386_state *cpustate) /* Opcode 0x0f 85 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->ZF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jo_rel16)(i386_state *cpustate) /* Opcode 0x0f 80 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->OF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jp_rel16)(i386_state *cpustate) /* Opcode 0x0f 8a */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->PF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(js_rel16)(i386_state *cpustate) /* Opcode 0x0f 88 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->SF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jz_rel16)(i386_state *cpustate) /* Opcode 0x0f 84 */ +{ + INT16 disp = FETCH16(cpustate); + if( cpustate->ZF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jcxz16)(i386_state *cpustate) /* Opcode 0xe3 */ +{ + INT8 disp = FETCH(cpustate); + if( REG16(CX) == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */ + } else { + CYCLES(cpustate,CYCLES_JCXZ_NOBRANCH); + } +} + +static void I386OP(jmp_rel16)(i386_state *cpustate) /* Opcode 0xe9 */ +{ + INT16 disp = FETCH16(cpustate); + + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JMP); /* TODO: Timing = 7 + m */ +} + +static void I386OP(jmp_abs16)(i386_state *cpustate) /* Opcode 0xea */ +{ + UINT16 address = FETCH16(cpustate); + UINT16 segment = FETCH16(cpustate); + + if( PROTECTED_MODE ) { + /* TODO: #GP */ + /* TODO: access rights, etc. */ + cpustate->eip = address; + cpustate->sreg[CS].selector = segment; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } else { + cpustate->eip = address; + cpustate->sreg[CS].selector = segment; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_JMP_INTERSEG); +} + +static void I386OP(lea16)(i386_state *cpustate) /* Opcode 0x8d */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 ea = GetNonTranslatedEA(cpustate,modrm); + STORE_REG16(modrm, ea); + CYCLES(cpustate,CYCLES_LEA); +} + +static void I386OP(enter16)(i386_state *cpustate) /* Opcode 0xc8 */ +{ + UINT16 framesize = FETCH16(cpustate); + UINT8 level = FETCH(cpustate) % 32; + UINT8 x; + UINT16 frameptr; + PUSH16(cpustate,REG16(BP)); + + if(!STACK_32BIT) + frameptr = REG16(SP); + else + frameptr = REG32(ESP); + + if(level > 0) + { + for(x=1;xsegment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + REG16(AX) = READ16(cpustate,eas); + BUMP_SI(cpustate,2); + CYCLES(cpustate,CYCLES_LODS); +} + +static void I386OP(loop16)(i386_state *cpustate) /* Opcode 0xe2 */ +{ + INT8 disp = FETCH(cpustate); + REG16(CX)--; + if( REG16(CX) != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOP); /* TODO: Timing = 11 + m */ +} + +static void I386OP(loopne16)(i386_state *cpustate) /* Opcode 0xe0 */ +{ + INT8 disp = FETCH(cpustate); + REG16(CX)--; + if( REG16(CX) != 0 && cpustate->ZF == 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ +} + +static void I386OP(loopz16)(i386_state *cpustate) /* Opcode 0xe1 */ +{ + INT8 disp = FETCH(cpustate); + REG16(CX)--; + if( REG16(CX) != 0 && cpustate->ZF != 0 ) { + if (cpustate->sreg[CS].d) + { + cpustate->eip += disp; + } + else + { + cpustate->eip = (cpustate->eip + disp) & 0xffff; + } + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ +} + +static void I386OP(mov_rm16_r16)(i386_state *cpustate) /* Opcode 0x89 */ +{ + UINT16 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + STORE_RM16(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + WRITE16(cpustate,ea, src); + CYCLES(cpustate,CYCLES_MOV_REG_MEM); + } +} + +static void I386OP(mov_r16_rm16)(i386_state *cpustate) /* Opcode 0x8b */ +{ + UINT16 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOV_MEM_REG); + } +} + +static void I386OP(mov_rm16_i16)(i386_state *cpustate) /* Opcode 0xc7 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 value = FETCH16(cpustate); + STORE_RM16(modrm, value); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 value = FETCH16(cpustate); + WRITE16(cpustate,ea, value); + CYCLES(cpustate,CYCLES_MOV_IMM_MEM); + } +} + +static void I386OP(mov_ax_m16)(i386_state *cpustate) /* Opcode 0xa1 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + /* TODO: Not sure if this is correct... */ + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + REG16(AX) = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_MOV_MEM_ACC); +} + +static void I386OP(mov_m16_ax)(i386_state *cpustate) /* Opcode 0xa3 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + /* TODO: Not sure if this is correct... */ + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + WRITE16(cpustate, ea, REG16(AX) ); + CYCLES(cpustate,CYCLES_MOV_ACC_MEM); +} + +static void I386OP(mov_ax_i16)(i386_state *cpustate) /* Opcode 0xb8 */ +{ + REG16(AX) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_cx_i16)(i386_state *cpustate) /* Opcode 0xb9 */ +{ + REG16(CX) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_dx_i16)(i386_state *cpustate) /* Opcode 0xba */ +{ + REG16(DX) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_bx_i16)(i386_state *cpustate) /* Opcode 0xbb */ +{ + REG16(BX) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_sp_i16)(i386_state *cpustate) /* Opcode 0xbc */ +{ + REG16(SP) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_bp_i16)(i386_state *cpustate) /* Opcode 0xbd */ +{ + REG16(BP) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_si_i16)(i386_state *cpustate) /* Opcode 0xbe */ +{ + REG16(SI) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_di_i16)(i386_state *cpustate) /* Opcode 0xbf */ +{ + REG16(DI) = FETCH16(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(movsw)(i386_state *cpustate) /* Opcode 0xa5 */ +{ + UINT32 eas, ead; + UINT16 v; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + v = READ16(cpustate,eas); + WRITE16(cpustate,ead, v); + BUMP_SI(cpustate,2); + BUMP_DI(cpustate,2); + CYCLES(cpustate,CYCLES_MOVS); +} + +static void I386OP(movsx_r16_rm8)(i386_state *cpustate) /* Opcode 0x0f be */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + INT16 src = (INT8)LOAD_RM8(modrm); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + INT16 src = (INT8)READ8(cpustate,ea); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_MEM_REG); + } +} + +static void I386OP(movzx_r16_rm8)(i386_state *cpustate) /* Opcode 0x0f b6 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 src = (UINT8)LOAD_RM8(modrm); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 src = (UINT8)READ8(cpustate,ea); + STORE_REG16(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_MEM_REG); + } +} + +static void I386OP(or_rm16_r16)(i386_state *cpustate) /* Opcode 0x09 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = OR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = OR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(or_r16_rm16)(i386_state *cpustate) /* Opcode 0x0b */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = OR16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = OR16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(or_ax_i16)(i386_state *cpustate) /* Opcode 0x0d */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = OR16(cpustate,dst, src); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(out_ax_i8)(i386_state *cpustate) /* Opcode 0xe7 */ +{ + UINT16 port = FETCH(cpustate); + UINT16 data = REG16(AX); + WRITEPORT16(port, data); + CYCLES(cpustate,CYCLES_OUT_VAR); +} + +static void I386OP(out_ax_dx)(i386_state *cpustate) /* Opcode 0xef */ +{ + UINT16 port = REG16(DX); + UINT16 data = REG16(AX); + WRITEPORT16(port, data); + CYCLES(cpustate,CYCLES_OUT); +} + +static void I386OP(pop_ax)(i386_state *cpustate) /* Opcode 0x58 */ +{ + REG16(AX) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_cx)(i386_state *cpustate) /* Opcode 0x59 */ +{ + REG16(CX) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_dx)(i386_state *cpustate) /* Opcode 0x5a */ +{ + REG16(DX) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_bx)(i386_state *cpustate) /* Opcode 0x5b */ +{ + REG16(BX) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_sp)(i386_state *cpustate) /* Opcode 0x5c */ +{ + REG16(SP) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_bp)(i386_state *cpustate) /* Opcode 0x5d */ +{ + REG16(BP) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_si)(i386_state *cpustate) /* Opcode 0x5e */ +{ + REG16(SI) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_di)(i386_state *cpustate) /* Opcode 0x5f */ +{ + REG16(DI) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_ds16)(i386_state *cpustate) /* Opcode 0x1f */ +{ + cpustate->sreg[DS].selector = POP16(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,DS); + } else { + i386_load_segment_descriptor(cpustate,DS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_es16)(i386_state *cpustate) /* Opcode 0x07 */ +{ + cpustate->sreg[ES].selector = POP16(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,ES); + } else { + i386_load_segment_descriptor(cpustate,ES); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_fs16)(i386_state *cpustate) /* Opcode 0x0f a1 */ +{ + cpustate->sreg[FS].selector = POP16(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,FS); + } else { + i386_load_segment_descriptor(cpustate,FS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_gs16)(i386_state *cpustate) /* Opcode 0x0f a9 */ +{ + cpustate->sreg[GS].selector = POP16(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,GS); + } else { + i386_load_segment_descriptor(cpustate,GS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_ss16)(i386_state *cpustate) /* Opcode 0x17 */ +{ + cpustate->sreg[SS].selector = POP16(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,SS); + } else { + i386_load_segment_descriptor(cpustate,SS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_rm16)(i386_state *cpustate) /* Opcode 0x8f */ +{ + UINT8 modrm = FETCH(cpustate); + UINT16 value = POP16(cpustate); + + if( modrm >= 0xc0 ) { + STORE_RM16(modrm, value); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE16(cpustate,ea, value); + } + CYCLES(cpustate,CYCLES_POP_RM); +} + +static void I386OP(popa)(i386_state *cpustate) /* Opcode 0x61 */ +{ + REG16(DI) = POP16(cpustate); + REG16(SI) = POP16(cpustate); + REG16(BP) = POP16(cpustate); + REG16(SP) += 2; + REG16(BX) = POP16(cpustate); + REG16(DX) = POP16(cpustate); + REG16(CX) = POP16(cpustate); + REG16(AX) = POP16(cpustate); + CYCLES(cpustate,CYCLES_POPA); +} + +static void I386OP(popf)(i386_state *cpustate) /* Opcode 0x9d */ +{ + UINT16 value = POP16(cpustate); + set_flags(cpustate,value); + CYCLES(cpustate,CYCLES_POPF); +} + +static void I386OP(push_ax)(i386_state *cpustate) /* Opcode 0x50 */ +{ + PUSH16(cpustate, REG16(AX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_cx)(i386_state *cpustate) /* Opcode 0x51 */ +{ + PUSH16(cpustate, REG16(CX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_dx)(i386_state *cpustate) /* Opcode 0x52 */ +{ + PUSH16(cpustate, REG16(DX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_bx)(i386_state *cpustate) /* Opcode 0x53 */ +{ + PUSH16(cpustate, REG16(BX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_sp)(i386_state *cpustate) /* Opcode 0x54 */ +{ + PUSH16(cpustate, REG16(SP) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_bp)(i386_state *cpustate) /* Opcode 0x55 */ +{ + PUSH16(cpustate, REG16(BP) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_si)(i386_state *cpustate) /* Opcode 0x56 */ +{ + PUSH16(cpustate, REG16(SI) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_di)(i386_state *cpustate) /* Opcode 0x57 */ +{ + PUSH16(cpustate, REG16(DI) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_cs16)(i386_state *cpustate) /* Opcode 0x0e */ +{ + PUSH16(cpustate, cpustate->sreg[CS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_ds16)(i386_state *cpustate) /* Opcode 0x1e */ +{ + PUSH16(cpustate, cpustate->sreg[DS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_es16)(i386_state *cpustate) /* Opcode 0x06 */ +{ + PUSH16(cpustate, cpustate->sreg[ES].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_fs16)(i386_state *cpustate) /* Opcode 0x0f a0 */ +{ + PUSH16(cpustate, cpustate->sreg[FS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_gs16)(i386_state *cpustate) /* Opcode 0x0f a8 */ +{ + PUSH16(cpustate, cpustate->sreg[GS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_ss16)(i386_state *cpustate) /* Opcode 0x16 */ +{ + PUSH16(cpustate, cpustate->sreg[SS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_i16)(i386_state *cpustate) /* Opcode 0x68 */ +{ + UINT16 value = FETCH16(cpustate); + PUSH16(cpustate,value); + CYCLES(cpustate,CYCLES_PUSH_IMM); +} + +static void I386OP(pusha)(i386_state *cpustate) /* Opcode 0x60 */ +{ + UINT16 temp = REG16(SP); + PUSH16(cpustate, REG16(AX) ); + PUSH16(cpustate, REG16(CX) ); + PUSH16(cpustate, REG16(DX) ); + PUSH16(cpustate, REG16(BX) ); + PUSH16(cpustate, temp ); + PUSH16(cpustate, REG16(BP) ); + PUSH16(cpustate, REG16(SI) ); + PUSH16(cpustate, REG16(DI) ); + CYCLES(cpustate,CYCLES_PUSHA); +} + +static void I386OP(pushf)(i386_state *cpustate) /* Opcode 0x9c */ +{ + PUSH16(cpustate, get_flags(cpustate) & 0xffff ); + CYCLES(cpustate,CYCLES_PUSHF); +} + +static void I386OP(ret_near16_i16)(i386_state *cpustate) /* Opcode 0xc2 */ +{ + INT16 disp = FETCH16(cpustate); + cpustate->eip = POP16(cpustate); + REG16(SP) += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ +} + +static void I386OP(ret_near16)(i386_state *cpustate) /* Opcode 0xc3 */ +{ + cpustate->eip = POP16(cpustate); + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_RET); /* TODO: Timing = 10 + m */ +} + +static void I386OP(sbb_rm16_r16)(i386_state *cpustate) /* Opcode 0x19 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = SBB16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = SBB16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sbb_r16_rm16)(i386_state *cpustate) /* Opcode 0x1b */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = SBB16(cpustate, dst, src, cpustate->CF); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = SBB16(cpustate, dst, src, cpustate->CF); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sbb_ax_i16)(i386_state *cpustate) /* Opcode 0x1d */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = SBB16(cpustate, dst, src, cpustate->CF); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(scasw)(i386_state *cpustate) /* Opcode 0xaf */ +{ + UINT32 eas; + UINT16 src, dst; + eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ16(cpustate,eas); + dst = REG16(AX); + SUB16(cpustate,dst, src); + BUMP_DI(cpustate,2); + CYCLES(cpustate,CYCLES_SCAS); +} + +static void I386OP(shld16_i8)(i386_state *cpustate) /* Opcode 0x0f a4 */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else if( shift > 15 ) { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (upper << (shift-16)) | (upper >> (32-shift)); + SetSZPF16(dst); + } else { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (16-shift)); + SetSZPF16(dst); + } + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_SHLD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else if( shift > 15 ) { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (upper << (shift-16)) | (upper >> (32-shift)); + SetSZPF16(dst); + } else { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (16-shift)); + SetSZPF16(dst); + } + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHLD_MEM); + } +} + +static void I386OP(shld16_cl)(i386_state *cpustate) /* Opcode 0x0f a5 */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else if( shift > 15 ) { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (upper << (shift-16)) | (upper >> (32-shift)); + SetSZPF16(dst); + } else { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (16-shift)); + SetSZPF16(dst); + } + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_SHLD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else if( shift > 15 ) { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (upper << (shift-16)) | (upper >> (32-shift)); + SetSZPF16(dst); + } else { + cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (16-shift)); + SetSZPF16(dst); + } + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHLD_MEM); + } +} + +static void I386OP(shrd16_i8)(i386_state *cpustate) /* Opcode 0x0f ac */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 15 || shift == 0) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (16-shift)); + SetSZPF16(dst); + } + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_SHRD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 15 || shift == 0) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (16-shift)); + SetSZPF16(dst); + } + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHRD_MEM); + } +} + +static void I386OP(shrd16_cl)(i386_state *cpustate) /* Opcode 0x0f ad */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = REG8(CL); + if( shift > 15 || shift == 0) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (16-shift)); + SetSZPF16(dst); + } + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_SHRD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 upper = LOAD_REG16(modrm); + UINT8 shift = REG8(CL); + if( shift > 15 || shift == 0) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (16-shift)); + SetSZPF16(dst); + } + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHRD_MEM); + } +} + +static void I386OP(stosw)(i386_state *cpustate) /* Opcode 0xab */ +{ + UINT32 ead; + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + WRITE16(cpustate,ead, REG16(AX)); + BUMP_DI(cpustate,2); + CYCLES(cpustate,CYCLES_STOS); +} + +static void I386OP(sub_rm16_r16)(i386_state *cpustate) /* Opcode 0x29 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = SUB16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = SUB16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sub_r16_rm16)(i386_state *cpustate) /* Opcode 0x2b */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = SUB16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = SUB16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sub_ax_i16)(i386_state *cpustate) /* Opcode 0x2d */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = SUB16(cpustate,dst, src); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(test_ax_i16)(i386_state *cpustate) /* Opcode 0xa9 */ +{ + UINT16 src = FETCH16(cpustate); + UINT16 dst = REG16(AX); + dst = src & dst; + SetSZPF16(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_IMM_ACC); +} + +static void I386OP(test_rm16_r16)(i386_state *cpustate) /* Opcode 0x85 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = src & dst; + SetSZPF16(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = src & dst; + SetSZPF16(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_MEM); + } +} + +static void I386OP(xchg_ax_cx)(i386_state *cpustate) /* Opcode 0x91 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(CX); + REG16(CX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_dx)(i386_state *cpustate) /* Opcode 0x92 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(DX); + REG16(DX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_bx)(i386_state *cpustate) /* Opcode 0x93 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(BX); + REG16(BX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_sp)(i386_state *cpustate) /* Opcode 0x94 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(SP); + REG16(SP) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_bp)(i386_state *cpustate) /* Opcode 0x95 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(BP); + REG16(BP) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_si)(i386_state *cpustate) /* Opcode 0x96 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(SI); + REG16(SI) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_ax_di)(i386_state *cpustate) /* Opcode 0x97 */ +{ + UINT16 temp; + temp = REG16(AX); + REG16(AX) = REG16(DI); + REG16(DI) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_r16_rm16)(i386_state *cpustate) /* Opcode 0x87 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 src = LOAD_RM16(modrm); + UINT16 dst = LOAD_REG16(modrm); + STORE_REG16(modrm, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 src = READ16(cpustate,ea); + UINT16 dst = LOAD_REG16(modrm); + STORE_REG16(modrm, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_MEM); + } +} + +static void I386OP(xor_rm16_r16)(i386_state *cpustate) /* Opcode 0x31 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + dst = XOR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate,ea); + dst = XOR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(xor_r16_rm16)(i386_state *cpustate) /* Opcode 0x33 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + dst = LOAD_REG16(modrm); + dst = XOR16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + dst = LOAD_REG16(modrm); + dst = XOR16(cpustate,dst, src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(xor_ax_i16)(i386_state *cpustate) /* Opcode 0x35 */ +{ + UINT16 src, dst; + src = FETCH16(cpustate); + dst = REG16(AX); + dst = XOR16(cpustate,dst, src); + REG16(AX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + + + +static void I386OP(group81_16)(i386_state *cpustate) /* Opcode 0x81 */ +{ + UINT32 ea; + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ADD Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = ADD16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = ADD16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 1: /* OR Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = OR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = OR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 2: /* ADC Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = ADC16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = ADC16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 3: /* SBB Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = SBB16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = SBB16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 4: /* AND Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = AND16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = AND16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 5: /* SUB Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = SUB16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = SUB16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 6: /* XOR Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + dst = XOR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + dst = XOR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 7: /* CMP Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = FETCH16(cpustate); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = FETCH16(cpustate); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } + break; + } +} + +static void I386OP(group83_16)(i386_state *cpustate) /* Opcode 0x83 */ +{ + UINT32 ea; + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ADD Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = ADD16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = ADD16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 1: /* OR Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = OR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = OR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 2: /* ADC Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = ADC16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = ADC16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 3: /* SBB Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = ((UINT16)(INT16)(INT8)FETCH(cpustate)); + dst = SBB16(cpustate, dst, src, cpustate->CF); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = ((UINT16)(INT16)(INT8)FETCH(cpustate)); + dst = SBB16(cpustate, dst, src, cpustate->CF); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 4: /* AND Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = AND16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = AND16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 5: /* SUB Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = SUB16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = SUB16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 6: /* XOR Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = XOR16(cpustate,dst, src); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + dst = XOR16(cpustate,dst, src); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 7: /* CMP Rm16, i16 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + src = (UINT16)(INT16)(INT8)FETCH(cpustate); + SUB16(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } + break; + } +} + +static void I386OP(groupC1_16)(i386_state *cpustate) /* Opcode 0xc1 */ +{ + UINT16 dst; + UINT8 modrm = FETCH(cpustate); + UINT8 shift; + + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate16(cpustate, modrm, dst, shift); + STORE_RM16(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate16(cpustate, modrm, dst, shift); + WRITE16(cpustate,ea, dst); + } +} + +static void I386OP(groupD1_16)(i386_state *cpustate) /* Opcode 0xd1 */ +{ + UINT16 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + dst = i386_shift_rotate16(cpustate, modrm, dst, 1); + STORE_RM16(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + dst = i386_shift_rotate16(cpustate, modrm, dst, 1); + WRITE16(cpustate,ea, dst); + } +} + +static void I386OP(groupD3_16)(i386_state *cpustate) /* Opcode 0xd3 */ +{ + UINT16 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM16(modrm); + dst = i386_shift_rotate16(cpustate, modrm, dst, REG8(CL)); + STORE_RM16(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ16(cpustate,ea); + dst = i386_shift_rotate16(cpustate, modrm, dst, REG8(CL)); + WRITE16(cpustate,ea, dst); + } +} + +static void I386OP(groupF7_16)(i386_state *cpustate) /* Opcode 0xf7 */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* TEST Rm16, i16 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 src = FETCH16(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF16(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 src = FETCH16(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF16(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_MEM); + } + break; + case 2: /* NOT Rm16 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + dst = ~dst; + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_NOT_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + dst = ~dst; + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NOT_MEM); + } + break; + case 3: /* NEG Rm16 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + dst = SUB16(cpustate, 0, dst ); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_NEG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + dst = SUB16(cpustate, 0, dst ); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NEG_MEM); + } + break; + case 4: /* MUL AX, Rm16 */ + { + UINT32 result; + UINT16 src, dst; + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = REG16(AX); + result = (UINT32)src * (UINT32)dst; + REG16(DX) = (UINT16)(result >> 16); + REG16(AX) = (UINT16)result; + + cpustate->CF = cpustate->OF = (REG16(DX) != 0); + } + break; + case 5: /* IMUL AX, Rm16 */ + { + INT32 result; + INT32 src, dst; + if( modrm >= 0xc0 ) { + src = (INT32)(INT16)LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = (INT32)(INT16)READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = (INT32)(INT16)REG16(AX); + result = src * dst; + + REG16(DX) = (UINT16)(result >> 16); + REG16(AX) = (UINT16)result; + + cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); + } + break; + case 6: /* DIV AX, Rm16 */ + { + UINT32 quotient, remainder, result; + UINT16 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_DIV16_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_DIV16_ACC_MEM); + } + + quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX)); + if( src ) { + remainder = quotient % (UINT32)src; + result = quotient / (UINT32)src; + if( result > 0xffff ) { + /* TODO: Divide error */ + } else { + REG16(DX) = (UINT16)remainder; + REG16(AX) = (UINT16)result; + + /* this flag is actually undefined, enable on non-cyrix */ + if (cpustate->cpuid_id0 != 0x69727943) + cpustate->CF = 1; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + case 7: /* IDIV AX, Rm16 */ + { + INT32 quotient, remainder, result; + UINT16 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_IDIV16_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_IDIV16_ACC_MEM); + } + + quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX)); + if( src ) { + remainder = quotient % (INT32)(INT16)src; + result = quotient / (INT32)(INT16)src; + if( result > 0xffff ) { + /* TODO: Divide error */ + } else { + REG16(DX) = (UINT16)remainder; + REG16(AX) = (UINT16)result; + + /* this flag is actually undefined, enable on non-cyrix */ + if (cpustate->cpuid_id0 != 0x69727943) + cpustate->CF = 1; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + } +} + +static void I386OP(groupFF_16)(i386_state *cpustate) /* Opcode 0xff */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* INC Rm16 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + dst = INC16(cpustate,dst); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_INC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + dst = INC16(cpustate,dst); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_INC_MEM); + } + break; + case 1: /* DEC Rm16 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + dst = DEC16(cpustate,dst); + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_DEC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + dst = DEC16(cpustate,dst); + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_DEC_MEM); + } + break; + case 2: /* CALL Rm16 */ + { + UINT16 address; + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ + } + PUSH16(cpustate, cpustate->eip ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 3: /* CALL FAR Rm16 */ + { + UINT16 address = 0, selector = 0; + if( modrm >= 0xc0 ) { + i386_fatal("i386: groupFF_16 /%d NYI", (modrm >> 3) & 0x7); + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ16(cpustate,ea + 0); + selector = READ16(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ + } + PUSH16(cpustate, cpustate->sreg[CS].selector ); + PUSH16(cpustate, cpustate->eip ); + cpustate->sreg[CS].selector = selector; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate, CS ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 4: /* JMP Rm16 */ + { + UINT16 address; + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ + } + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 5: /* JMP FAR Rm16 */ + { + UINT16 address = 0, selector = 0; + if( modrm >= 0xc0 ) { + i386_fatal("i386: groupFF_16 /%d NYI", (modrm >> 3) & 0x7); + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ16(cpustate,ea + 0); + selector = READ16(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ + } + cpustate->sreg[CS].selector = selector; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate, CS ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 6: /* PUSH Rm16 */ + { + UINT16 value; + if( modrm >= 0xc0 ) { + value = LOAD_RM16(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + value = READ16(cpustate,ea); + } + PUSH16(cpustate,value); + CYCLES(cpustate,CYCLES_PUSH_RM); + } + break; + case 7: + I386OP(invalid)(cpustate); + break; + default: + i386_fatal("i386: groupFF_16 /%d unimplemented", (modrm >> 3) & 0x7); + break; + } +} + +static void I386OP(group0F00_16)(i386_state *cpustate) /* Opcode 0x0f 00 */ +{ + UINT32 address, ea; + UINT8 modrm = FETCH(cpustate); + I386_SREG seg; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SLDT */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + STORE_RM16(address, cpustate->ldtr.segment); + CYCLES(cpustate,CYCLES_SLDT_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE16(cpustate, ea, cpustate->ldtr.segment); + CYCLES(cpustate,CYCLES_SLDT_MEM); + } + } + else + { + i386_trap(cpustate,6, 0); + } + break; + case 1: /* STR */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + STORE_RM16(address, cpustate->task.segment); + CYCLES(cpustate,CYCLES_STR_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE16(cpustate, ea, cpustate->task.segment); + CYCLES(cpustate,CYCLES_STR_MEM); + } + } + else + { + i386_trap(cpustate,6, 0); + } + break; + case 2: /* LLDT */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + CYCLES(cpustate,CYCLES_LLDT_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LLDT_MEM); + } + cpustate->ldtr.segment = READ16(cpustate,ea); + memset(&seg, 0, sizeof(seg)); + seg.selector = cpustate->ldtr.segment; + i386_load_protected_mode_segment(cpustate,&seg); + cpustate->ldtr.limit = seg.limit; + cpustate->ldtr.base = seg.base; + } + else + { + i386_trap(cpustate,6, 0); + } + break; + + case 3: /* LTR */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + CYCLES(cpustate,CYCLES_LTR_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LTR_MEM); + } + cpustate->task.segment = READ16(cpustate,ea); + } + else + { + i386_trap(cpustate,6, 0); + } + break; + + default: + i386_fatal("i386: group0F00_16 /%d unimplemented", (modrm >> 3) & 0x7); + break; + } +} + +static void I386OP(group0F01_16)(i386_state *cpustate) /* Opcode 0x0f 01 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT16 address; + UINT32 ea; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->gdtr.limit); + WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff); + CYCLES(cpustate,CYCLES_SGDT); + break; + } + case 1: /* SIDT */ + { + if (modrm >= 0xc0) + { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + } + else + { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->idtr.limit); + WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff); + CYCLES(cpustate,CYCLES_SIDT); + break; + } + case 2: /* LGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->gdtr.limit = READ16(cpustate,ea); + cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff; + CYCLES(cpustate,CYCLES_LGDT); + break; + } + case 3: /* LIDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->idtr.limit = READ16(cpustate,ea); + cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff; + CYCLES(cpustate,CYCLES_LIDT); + break; + } + case 4: /* SMSW */ + { + if( modrm >= 0xc0 ) { + STORE_RM16(modrm, cpustate->cr[0]); + CYCLES(cpustate,CYCLES_SMSW_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE16(cpustate,ea, cpustate->cr[0]); + CYCLES(cpustate,CYCLES_SMSW_MEM); + } + break; + } + case 6: /* LMSW */ + { + /* TODO: Check for protection fault */ + UINT8 b; + if( modrm >= 0xc0 ) { + b = LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_LMSW_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LMSW_MEM); + b = READ8(cpustate,ea); + } + cpustate->cr[0] &= ~0x03; + cpustate->cr[0] |= b & 0x03; + break; + } + default: + i386_fatal("i386: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2); + break; + } +} + +static void I386OP(group0FBA_16)(i386_state *cpustate) /* Opcode 0x0f ba */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 4: /* BT Rm16, i8 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_IMM_MEM); + } + break; + case 5: /* BTS Rm16, i8 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTS_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTS_IMM_MEM); + } + break; + case 6: /* BTR Rm16, i8 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTR_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTR_IMM_MEM); + } + break; + case 7: /* BTC Rm16, i8 */ + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + STORE_RM16(modrm, dst); + CYCLES(cpustate,CYCLES_BTC_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + WRITE16(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTC_IMM_MEM); + } + break; + default: + i386_fatal("i386: group0FBA_16 /%d unknown", (modrm >> 3) & 0x7); + break; + } +} + +static void I386OP(lsl_r16_rm16)(i386_state *cpustate) /* Opcode 0x0f 0x03 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 limit; + I386_SREG seg; + + if(PROTECTED_MODE) + { + memset(&seg, 0, sizeof(seg)); + seg.selector = LOAD_RM16(modrm); + if(seg.selector == 0) + { + SetZF(0); /* not a valid segment */ + } + else + { + /* TODO: check segment type */ + i386_load_protected_mode_segment(cpustate,&seg); + limit = seg.limit; + STORE_REG16(modrm,limit & 0x0000ffff); + SetZF(1); + } + } + else + i386_trap(cpustate,6, 0); +} + +static void I386OP(bound_r16_m16_m16)(i386_state *cpustate) /* Opcode 0x62 */ +{ + UINT8 modrm; + INT16 val, low, high; + + modrm = FETCH(cpustate); + + if (modrm >= 0xc0) + { + low = high = LOAD_RM16(modrm); + } + else + { + UINT32 ea = GetEA(cpustate,modrm); + low = READ16(cpustate,ea + 0); + high = READ16(cpustate,ea + 2); + } + val = LOAD_REG16(modrm); + + if ((val < low) || (val > high)) + { + CYCLES(cpustate,CYCLES_BOUND_OUT_RANGE); + i386_trap(cpustate,5, 0); + } + else + { + CYCLES(cpustate,CYCLES_BOUND_IN_RANGE); + } +} + +static void I386OP(retf16)(i386_state *cpustate) /* Opcode 0xcb */ +{ + cpustate->eip = POP16(cpustate); + cpustate->sreg[CS].selector = POP16(cpustate); + i386_load_segment_descriptor(cpustate, CS ); + CHANGE_PC(cpustate,cpustate->eip); + + CYCLES(cpustate,CYCLES_RET_INTERSEG); +} + +static void I386OP(retf_i16)(i386_state *cpustate) /* Opcode 0xca */ +{ + UINT16 count = FETCH16(cpustate); + + cpustate->eip = POP16(cpustate); + cpustate->sreg[CS].selector = POP16(cpustate); + i386_load_segment_descriptor(cpustate, CS ); + CHANGE_PC(cpustate,cpustate->eip); + + REG16(SP) += count; + CYCLES(cpustate,CYCLES_RET_IMM_INTERSEG); +} + +static void I386OP(xlat16)(i386_state *cpustate) /* Opcode 0xd7 */ +{ + UINT32 ea; + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, REG16(BX) + REG8(AL) ); + } else { + ea = i386_translate(cpustate, DS, REG16(BX) + REG8(AL) ); + } + REG8(AL) = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_XLAT); +} + +static void I386OP(load_far_pointer16)(i386_state *cpustate, int s) +{ + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + i386_fatal("i386: load_far_pointer16 NYI"); + } else { + UINT32 ea = GetEA(cpustate,modrm); + STORE_REG16(modrm, READ16(cpustate,ea + 0)); + cpustate->sreg[s].selector = READ16(cpustate,ea + 2); + i386_load_segment_descriptor(cpustate, s ); + } +} + +static void I386OP(lds16)(i386_state *cpustate) /* Opcode 0xc5 */ +{ + I386OP(load_far_pointer16)(cpustate, DS); + CYCLES(cpustate,CYCLES_LDS); +} + +static void I386OP(lss16)(i386_state *cpustate) /* Opcode 0x0f 0xb2 */ +{ + I386OP(load_far_pointer16)(cpustate, SS); + CYCLES(cpustate,CYCLES_LSS); +} + +static void I386OP(les16)(i386_state *cpustate) /* Opcode 0xc4 */ +{ + I386OP(load_far_pointer16)(cpustate, ES); + CYCLES(cpustate,CYCLES_LES); +} + +static void I386OP(lfs16)(i386_state *cpustate) /* Opcode 0x0f 0xb4 */ +{ + I386OP(load_far_pointer16)(cpustate, FS); + CYCLES(cpustate,CYCLES_LFS); +} + +static void I386OP(lgs16)(i386_state *cpustate) /* Opcode 0x0f 0xb5 */ +{ + I386OP(load_far_pointer16)(cpustate, GS); + CYCLES(cpustate,CYCLES_LGS); +} + diff --git a/src/cpu/i386/i386op32.c b/src/cpu/i386/i386op32.c new file mode 100644 index 00000000..c4de846b --- /dev/null +++ b/src/cpu/i386/i386op32.c @@ -0,0 +1,3066 @@ +static UINT32 I386OP(shift_rotate32)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift) +{ + UINT32 dst, src; + dst = value; + src = value; + + if( shift == 0 ) { + CYCLES_RM(cpustate,modrm, 3, 7); + } else if( shift == 1 ) { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm32, 1 */ + cpustate->CF = (src & 0x80000000) ? 1 : 0; + dst = (src << 1) + cpustate->CF; + cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm32, 1 */ + cpustate->CF = (src & 0x1) ? 1 : 0; + dst = (cpustate->CF << 31) | (src >> 1); + cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm32, 1 */ + dst = (src << 1) + cpustate->CF; + cpustate->CF = (src & 0x80000000) ? 1 : 0; + cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm32, 1 */ + dst = (cpustate->CF << 31) | (src >> 1); + cpustate->CF = src & 0x1; + cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm32, 1 */ + case 6: + dst = src << 1; + cpustate->CF = (src & 0x80000000) ? 1 : 0; + cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm32, 1 */ + dst = src >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = (src & 0x80000000) ? 1 : 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm32, 1 */ + dst = (INT32)(src) >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + + } else { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm32, i8 */ + dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | + ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift)); + cpustate->CF = (src >> (32-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm32, i8 */ + dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | + ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm32, i8 */ + dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | + ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) | + (cpustate->CF << (shift-1)); + cpustate->CF = (src >> (32-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm32, i8 */ + dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | + ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) | + (cpustate->CF << (32-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm32, i8 */ + case 6: + dst = src << shift; + cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm32, i8 */ + dst = src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm32, i8 */ + dst = (INT32)src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF32(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + + } + return dst; +} + + + +static void I386OP(adc_rm32_r32)(i386_state *cpustate) /* Opcode 0x11 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = ADC32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = ADC32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(adc_r32_rm32)(i386_state *cpustate) /* Opcode 0x13 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = ADC32(cpustate, dst, src, cpustate->CF); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = ADC32(cpustate, dst, src, cpustate->CF); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(adc_eax_i32)(i386_state *cpustate) /* Opcode 0x15 */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = ADC32(cpustate, dst, src, cpustate->CF); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(add_rm32_r32)(i386_state *cpustate) /* Opcode 0x01 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = ADD32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = ADD32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(add_r32_rm32)(i386_state *cpustate) /* Opcode 0x03 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = ADD32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = ADD32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(add_eax_i32)(i386_state *cpustate) /* Opcode 0x05 */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = ADD32(cpustate,dst, src); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(and_rm32_r32)(i386_state *cpustate) /* Opcode 0x21 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = AND32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = AND32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(and_r32_rm32)(i386_state *cpustate) /* Opcode 0x23 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = AND32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = AND32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(and_eax_i32)(i386_state *cpustate) /* Opcode 0x25 */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = AND32(cpustate,dst, src); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(bsf_r32_rm32)(i386_state *cpustate) /* Opcode 0x0f bc */ +{ + UINT32 src, dst, temp; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + } + + dst = 0; + + if( src == 0 ) { + cpustate->ZF = 1; + } else { + cpustate->ZF = 0; + temp = 0; + while( (src & (1 << temp)) == 0 ) { + temp++; + dst = temp; + CYCLES(cpustate,CYCLES_BSF); + } + } + CYCLES(cpustate,CYCLES_BSF_BASE); + STORE_REG32(modrm, dst); +} + +static void I386OP(bsr_r32_rm32)(i386_state *cpustate) /* Opcode 0x0f bd */ +{ + UINT32 src, dst, temp; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + } + + dst = 0; + + if( src == 0 ) { + cpustate->ZF = 1; + } else { + cpustate->ZF = 0; + dst = temp = 31; + while( (src & (1 << temp)) == 0 ) { + temp--; + dst = temp; + CYCLES(cpustate,CYCLES_BSR); + } + } + CYCLES(cpustate,CYCLES_BSR_BASE); + STORE_REG32(modrm, dst); +} + +static void I386OP(bt_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f a3 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_REG_MEM); + } +} + +static void I386OP(btc_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f bb */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTC_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTC_REG_MEM); + } +} + +static void I386OP(btr_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f b3 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTR_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTR_REG_MEM); + } +} + +static void I386OP(bts_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f ab */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTS_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 bit = LOAD_REG32(modrm); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTS_REG_MEM); + } +} + +static void I386OP(call_abs32)(i386_state *cpustate) /* Opcode 0x9a */ +{ + UINT32 offset = FETCH32(cpustate); + UINT16 ptr = FETCH16(cpustate); + + if( PROTECTED_MODE ) { + /* TODO */ + i386_fatal("i386: call_abs32 in protected mode unimplemented"); + } else { + PUSH32(cpustate, cpustate->sreg[CS].selector ); + PUSH32(cpustate, cpustate->eip ); + cpustate->sreg[CS].selector = ptr; + cpustate->eip = offset; + i386_load_segment_descriptor(cpustate,CS); + } + CYCLES(cpustate,CYCLES_CALL_INTERSEG); + CHANGE_PC(cpustate,cpustate->eip); +} + +static void I386OP(call_rel32)(i386_state *cpustate) /* Opcode 0xe8 */ +{ + INT32 disp = FETCH32(cpustate); + + PUSH32(cpustate, cpustate->eip ); + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_CALL); /* TODO: Timing = 7 + m */ +} + +static void I386OP(cdq)(i386_state *cpustate) /* Opcode 0x99 */ +{ + if( REG32(EAX) & 0x80000000 ) { + REG32(EDX) = 0xffffffff; + } else { + REG32(EDX) = 0x00000000; + } + CYCLES(cpustate,CYCLES_CWD); +} + +static void I386OP(cmp_rm32_r32)(i386_state *cpustate) /* Opcode 0x39 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } +} + +static void I386OP(cmp_r32_rm32)(i386_state *cpustate) /* Opcode 0x3b */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_MEM_REG); + } +} + +static void I386OP(cmp_eax_i32)(i386_state *cpustate) /* Opcode 0x3d */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_IMM_ACC); +} + +static void I386OP(cmpsd)(i386_state *cpustate) /* Opcode 0xa7 */ +{ + UINT32 eas, ead, src, dst; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ32(cpustate,eas); + dst = READ32(cpustate,ead); + SUB32(cpustate,dst, src); + BUMP_SI(cpustate,4); + BUMP_DI(cpustate,4); + CYCLES(cpustate,CYCLES_CMPS); +} + +static void I386OP(cwde)(i386_state *cpustate) /* Opcode 0x98 */ +{ + REG32(EAX) = (INT32)((INT16)REG16(AX)); + CYCLES(cpustate,CYCLES_CBW); +} + +static void I386OP(dec_eax)(i386_state *cpustate) /* Opcode 0x48 */ +{ + REG32(EAX) = DEC32(cpustate, REG32(EAX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_ecx)(i386_state *cpustate) /* Opcode 0x49 */ +{ + REG32(ECX) = DEC32(cpustate, REG32(ECX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_edx)(i386_state *cpustate) /* Opcode 0x4a */ +{ + REG32(EDX) = DEC32(cpustate, REG32(EDX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_ebx)(i386_state *cpustate) /* Opcode 0x4b */ +{ + REG32(EBX) = DEC32(cpustate, REG32(EBX) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_esp)(i386_state *cpustate) /* Opcode 0x4c */ +{ + REG32(ESP) = DEC32(cpustate, REG32(ESP) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_ebp)(i386_state *cpustate) /* Opcode 0x4d */ +{ + REG32(EBP) = DEC32(cpustate, REG32(EBP) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_esi)(i386_state *cpustate) /* Opcode 0x4e */ +{ + REG32(ESI) = DEC32(cpustate, REG32(ESI) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(dec_edi)(i386_state *cpustate) /* Opcode 0x4f */ +{ + REG32(EDI) = DEC32(cpustate, REG32(EDI) ); + CYCLES(cpustate,CYCLES_DEC_REG); +} + +static void I386OP(imul_r32_rm32)(i386_state *cpustate) /* Opcode 0x0f af */ +{ + UINT8 modrm = FETCH(cpustate); + INT64 result; + INT64 src, dst; + if( modrm >= 0xc0 ) { + src = (INT64)(INT32)LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = (INT64)(INT32)READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ + } + + dst = (INT64)(INT32)LOAD_REG32(modrm); + result = src * dst; + + STORE_REG32(modrm, (UINT32)result); + + cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); +} + +static void I386OP(imul_r32_rm32_i32)(i386_state *cpustate) /* Opcode 0x69 */ +{ + UINT8 modrm = FETCH(cpustate); + INT64 result; + INT64 src, dst; + if( modrm >= 0xc0 ) { + dst = (INT64)(INT32)LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = (INT64)(INT32)READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ + } + + src = (INT64)(INT32)FETCH32(cpustate); + result = src * dst; + + STORE_REG32(modrm, (UINT32)result); + + cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); +} + +static void I386OP(imul_r32_rm32_i8)(i386_state *cpustate) /* Opcode 0x6b */ +{ + UINT8 modrm = FETCH(cpustate); + INT64 result; + INT64 src, dst; + if( modrm >= 0xc0 ) { + dst = (INT64)(INT32)LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = (INT64)(INT32)READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ + } + + src = (INT64)(INT8)FETCH(cpustate); + result = src * dst; + + STORE_REG32(modrm, (UINT32)result); + + cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); +} + +static void I386OP(in_eax_i8)(i386_state *cpustate) /* Opcode 0xe5 */ +{ + UINT16 port = FETCH(cpustate); + UINT32 data = READPORT32(port); + REG32(EAX) = data; + CYCLES(cpustate,CYCLES_IN_VAR); +} + +static void I386OP(in_eax_dx)(i386_state *cpustate) /* Opcode 0xed */ +{ + UINT16 port = REG16(DX); + UINT32 data = READPORT32(port); + REG32(EAX) = data; + CYCLES(cpustate,CYCLES_IN); +} + +static void I386OP(inc_eax)(i386_state *cpustate) /* Opcode 0x40 */ +{ + REG32(EAX) = INC32(cpustate, REG32(EAX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_ecx)(i386_state *cpustate) /* Opcode 0x41 */ +{ + REG32(ECX) = INC32(cpustate, REG32(ECX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_edx)(i386_state *cpustate) /* Opcode 0x42 */ +{ + REG32(EDX) = INC32(cpustate, REG32(EDX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_ebx)(i386_state *cpustate) /* Opcode 0x43 */ +{ + REG32(EBX) = INC32(cpustate, REG32(EBX) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_esp)(i386_state *cpustate) /* Opcode 0x44 */ +{ + REG32(ESP) = INC32(cpustate, REG32(ESP) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_ebp)(i386_state *cpustate) /* Opcode 0x45 */ +{ + REG32(EBP) = INC32(cpustate, REG32(EBP) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_esi)(i386_state *cpustate) /* Opcode 0x46 */ +{ + REG32(ESI) = INC32(cpustate, REG32(ESI) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(inc_edi)(i386_state *cpustate) /* Opcode 0x47 */ +{ + REG32(EDI) = INC32(cpustate, REG32(EDI) ); + CYCLES(cpustate,CYCLES_INC_REG); +} + +static void I386OP(iret32)(i386_state *cpustate) /* Opcode 0xcf */ +{ + if( PROTECTED_MODE ) { + /* TODO: Virtual 8086-mode */ + /* TODO: Nested task */ + /* TODO: #SS(0) exception */ + /* TODO: All the protection-related stuff... */ + cpustate->eip = POP32(cpustate); + cpustate->sreg[CS].selector = POP32(cpustate) & 0xffff; + set_flags(cpustate, POP32(cpustate) ); + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } else { + /* TODO: #SS(0) exception */ + /* TODO: #GP(0) exception */ + cpustate->eip = POP32(cpustate); + cpustate->sreg[CS].selector = POP32(cpustate) & 0xffff; + set_flags(cpustate, POP32(cpustate) ); + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_IRET); +} + +static void I386OP(ja_rel32)(i386_state *cpustate) /* Opcode 0x0f 87 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->CF == 0 && cpustate->ZF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jbe_rel32)(i386_state *cpustate) /* Opcode 0x0f 86 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->CF != 0 || cpustate->ZF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jc_rel32)(i386_state *cpustate) /* Opcode 0x0f 82 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->CF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jg_rel32)(i386_state *cpustate) /* Opcode 0x0f 8f */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jge_rel32)(i386_state *cpustate) /* Opcode 0x0f 8d */ +{ + INT32 disp = FETCH32(cpustate); + if( (cpustate->SF == cpustate->OF) ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jl_rel32)(i386_state *cpustate) /* Opcode 0x0f 8c */ +{ + INT32 disp = FETCH32(cpustate); + if( (cpustate->SF != cpustate->OF) ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jle_rel32)(i386_state *cpustate) /* Opcode 0x0f 8e */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnc_rel32)(i386_state *cpustate) /* Opcode 0x0f 83 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->CF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jno_rel32)(i386_state *cpustate) /* Opcode 0x0f 81 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->OF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnp_rel32)(i386_state *cpustate) /* Opcode 0x0f 8b */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->PF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jns_rel32)(i386_state *cpustate) /* Opcode 0x0f 89 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->SF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jnz_rel32)(i386_state *cpustate) /* Opcode 0x0f 85 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->ZF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jo_rel32)(i386_state *cpustate) /* Opcode 0x0f 80 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->OF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jp_rel32)(i386_state *cpustate) /* Opcode 0x0f 8a */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->PF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(js_rel32)(i386_state *cpustate) /* Opcode 0x0f 88 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->SF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jz_rel32)(i386_state *cpustate) /* Opcode 0x0f 84 */ +{ + INT32 disp = FETCH32(cpustate); + if( cpustate->ZF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH); + } +} + +static void I386OP(jcxz32)(i386_state *cpustate) /* Opcode 0xe3 */ +{ + INT8 disp = FETCH(cpustate); + if( REG32(ECX) == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */ + } else { + CYCLES(cpustate,CYCLES_JCXZ_NOBRANCH); + } +} + +static void I386OP(jmp_rel32)(i386_state *cpustate) /* Opcode 0xe9 */ +{ + UINT32 disp = FETCH32(cpustate); + /* TODO: Segment limit */ + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_JMP); /* TODO: Timing = 7 + m */ +} + +static void I386OP(jmp_abs32)(i386_state *cpustate) /* Opcode 0xea */ +{ + UINT32 address = FETCH32(cpustate); + UINT16 segment = FETCH16(cpustate); + + if( PROTECTED_MODE ) { + /* TODO: #GP */ + /* TODO: access rights, etc. */ + cpustate->eip = address; + cpustate->sreg[CS].selector = segment; + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } else { + cpustate->eip = address; + cpustate->sreg[CS].selector = segment; + i386_load_segment_descriptor(cpustate,CS); + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_JMP_INTERSEG); +} + +static void I386OP(lea32)(i386_state *cpustate) /* Opcode 0x8d */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 ea = GetNonTranslatedEA(cpustate,modrm); + if (!cpustate->address_size) + { + ea &= 0xffff; + } + STORE_REG32(modrm, ea); + CYCLES(cpustate,CYCLES_LEA); +} + +static void I386OP(enter32)(i386_state *cpustate) /* Opcode 0xc8 */ +{ + UINT16 framesize = FETCH16(cpustate); + UINT8 level = FETCH(cpustate) % 32; + UINT8 x; + UINT32 frameptr; + PUSH32(cpustate,REG32(EBP)); + if(!STACK_32BIT) + frameptr = REG16(SP); + else + frameptr = REG32(ESP); + + if(level > 0) + { + for(x=1;xsegment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + REG32(EAX) = READ32(cpustate,eas); + BUMP_SI(cpustate,4); + CYCLES(cpustate,CYCLES_LODS); +} + +static void I386OP(loop32)(i386_state *cpustate) /* Opcode 0xe2 */ +{ + INT8 disp = FETCH(cpustate); + INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); + if( reg != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOP); /* TODO: Timing = 11 + m */ +} + +static void I386OP(loopne32)(i386_state *cpustate) /* Opcode 0xe0 */ +{ + INT8 disp = FETCH(cpustate); + INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); + if( reg != 0 && cpustate->ZF == 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ +} + +static void I386OP(loopz32)(i386_state *cpustate) /* Opcode 0xe1 */ +{ + INT8 disp = FETCH(cpustate); + INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); + if( reg != 0 && cpustate->ZF != 0 ) { + cpustate->eip += disp; + CHANGE_PC(cpustate,cpustate->eip); + } + CYCLES(cpustate,CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ +} + +static void I386OP(mov_rm32_r32)(i386_state *cpustate) /* Opcode 0x89 */ +{ + UINT32 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + STORE_RM32(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + WRITE32(cpustate,ea, src); + CYCLES(cpustate,CYCLES_MOV_REG_MEM); + } +} + +static void I386OP(mov_r32_rm32)(i386_state *cpustate) /* Opcode 0x8b */ +{ + UINT32 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOV_MEM_REG); + } +} + +static void I386OP(mov_rm32_i32)(i386_state *cpustate) /* Opcode 0xc7 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 value = FETCH32(cpustate); + STORE_RM32(modrm, value); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 value = FETCH32(cpustate); + WRITE32(cpustate,ea, value); + CYCLES(cpustate,CYCLES_MOV_IMM_MEM); + } +} + +static void I386OP(mov_eax_m32)(i386_state *cpustate) /* Opcode 0xa1 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + REG32(EAX) = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_MOV_MEM_ACC); +} + +static void I386OP(mov_m32_eax)(i386_state *cpustate) /* Opcode 0xa3 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + WRITE32(cpustate, ea, REG32(EAX) ); + CYCLES(cpustate,CYCLES_MOV_ACC_MEM); +} + +static void I386OP(mov_eax_i32)(i386_state *cpustate) /* Opcode 0xb8 */ +{ + REG32(EAX) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_ecx_i32)(i386_state *cpustate) /* Opcode 0xb9 */ +{ + REG32(ECX) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_edx_i32)(i386_state *cpustate) /* Opcode 0xba */ +{ + REG32(EDX) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_ebx_i32)(i386_state *cpustate) /* Opcode 0xbb */ +{ + REG32(EBX) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_esp_i32)(i386_state *cpustate) /* Opcode 0xbc */ +{ + REG32(ESP) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_ebp_i32)(i386_state *cpustate) /* Opcode 0xbd */ +{ + REG32(EBP) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_esi_i32)(i386_state *cpustate) /* Opcode 0xbe */ +{ + REG32(ESI) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_edi_i32)(i386_state *cpustate) /* Opcode 0xbf */ +{ + REG32(EDI) = FETCH32(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(movsd)(i386_state *cpustate) /* Opcode 0xa5 */ +{ + UINT32 eas, ead, v; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + v = READ32(cpustate,eas); + WRITE32(cpustate,ead, v); + BUMP_SI(cpustate,4); + BUMP_DI(cpustate,4); + CYCLES(cpustate,CYCLES_MOVS); +} + +static void I386OP(movsx_r32_rm8)(i386_state *cpustate) /* Opcode 0x0f be */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + INT32 src = (INT8)LOAD_RM8(modrm); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + INT32 src = (INT8)READ8(cpustate,ea); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_MEM_REG); + } +} + +static void I386OP(movsx_r32_rm16)(i386_state *cpustate) /* Opcode 0x0f bf */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + INT32 src = (INT16)LOAD_RM16(modrm); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + INT32 src = (INT16)READ16(cpustate,ea); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVSX_MEM_REG); + } +} + +static void I386OP(movzx_r32_rm8)(i386_state *cpustate) /* Opcode 0x0f b6 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 src = (UINT8)LOAD_RM8(modrm); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 src = (UINT8)READ8(cpustate,ea); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_MEM_REG); + } +} + +static void I386OP(movzx_r32_rm16)(i386_state *cpustate) /* Opcode 0x0f b7 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 src = (UINT16)LOAD_RM16(modrm); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 src = (UINT16)READ16(cpustate,ea); + STORE_REG32(modrm, src); + CYCLES(cpustate,CYCLES_MOVZX_MEM_REG); + } +} + +static void I386OP(or_rm32_r32)(i386_state *cpustate) /* Opcode 0x09 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = OR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = OR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(or_r32_rm32)(i386_state *cpustate) /* Opcode 0x0b */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = OR32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = OR32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(or_eax_i32)(i386_state *cpustate) /* Opcode 0x0d */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = OR32(cpustate,dst, src); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(out_eax_i8)(i386_state *cpustate) /* Opcode 0xe7 */ +{ + UINT16 port = FETCH(cpustate); + UINT32 data = REG32(EAX); + WRITEPORT32(port, data); + CYCLES(cpustate,CYCLES_OUT_VAR); +} + +static void I386OP(out_eax_dx)(i386_state *cpustate) /* Opcode 0xef */ +{ + UINT16 port = REG16(DX); + UINT32 data = REG32(EAX); + WRITEPORT32(port, data); + CYCLES(cpustate,CYCLES_OUT); +} + +static void I386OP(pop_eax)(i386_state *cpustate) /* Opcode 0x58 */ +{ + REG32(EAX) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_ecx)(i386_state *cpustate) /* Opcode 0x59 */ +{ + REG32(ECX) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_edx)(i386_state *cpustate) /* Opcode 0x5a */ +{ + REG32(EDX) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_ebx)(i386_state *cpustate) /* Opcode 0x5b */ +{ + REG32(EBX) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_esp)(i386_state *cpustate) /* Opcode 0x5c */ +{ + REG32(ESP) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_ebp)(i386_state *cpustate) /* Opcode 0x5d */ +{ + REG32(EBP) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_esi)(i386_state *cpustate) /* Opcode 0x5e */ +{ + REG32(ESI) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_edi)(i386_state *cpustate) /* Opcode 0x5f */ +{ + REG32(EDI) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POP_REG_SHORT); +} + +static void I386OP(pop_ds32)(i386_state *cpustate) /* Opcode 0x1f */ +{ + cpustate->sreg[DS].selector = POP32(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,DS); + } else { + i386_load_segment_descriptor(cpustate,DS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_es32)(i386_state *cpustate) /* Opcode 0x07 */ +{ + cpustate->sreg[ES].selector = POP32(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,ES); + } else { + i386_load_segment_descriptor(cpustate,ES); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_fs32)(i386_state *cpustate) /* Opcode 0x0f a1 */ +{ + cpustate->sreg[FS].selector = POP32(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,FS); + } else { + i386_load_segment_descriptor(cpustate,FS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_gs32)(i386_state *cpustate) /* Opcode 0x0f a9 */ +{ + cpustate->sreg[GS].selector = POP32(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,GS); + } else { + i386_load_segment_descriptor(cpustate,GS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_ss32)(i386_state *cpustate) /* Opcode 0x17 */ +{ + cpustate->sreg[SS].selector = POP32(cpustate); + if( PROTECTED_MODE ) { + i386_load_segment_descriptor(cpustate,SS); + } else { + i386_load_segment_descriptor(cpustate,SS); + } + CYCLES(cpustate,CYCLES_POP_SREG); +} + +static void I386OP(pop_rm32)(i386_state *cpustate) /* Opcode 0x8f */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 value = POP32(cpustate); + + if( modrm >= 0xc0 ) { + STORE_RM32(modrm, value); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE32(cpustate,ea, value); + } + CYCLES(cpustate,CYCLES_POP_RM); +} + +static void I386OP(popad)(i386_state *cpustate) /* Opcode 0x61 */ +{ + REG32(EDI) = POP32(cpustate); + REG32(ESI) = POP32(cpustate); + REG32(EBP) = POP32(cpustate); + REG32(ESP) += 4; + REG32(EBX) = POP32(cpustate); + REG32(EDX) = POP32(cpustate); + REG32(ECX) = POP32(cpustate); + REG32(EAX) = POP32(cpustate); + CYCLES(cpustate,CYCLES_POPA); +} + +static void I386OP(popfd)(i386_state *cpustate) /* Opcode 0x9d */ +{ + UINT32 value = POP32(cpustate); + set_flags(cpustate,value); + CYCLES(cpustate,CYCLES_POPF); +} + +static void I386OP(push_eax)(i386_state *cpustate) /* Opcode 0x50 */ +{ + PUSH32(cpustate, REG32(EAX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_ecx)(i386_state *cpustate) /* Opcode 0x51 */ +{ + PUSH32(cpustate, REG32(ECX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_edx)(i386_state *cpustate) /* Opcode 0x52 */ +{ + PUSH32(cpustate, REG32(EDX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_ebx)(i386_state *cpustate) /* Opcode 0x53 */ +{ + PUSH32(cpustate, REG32(EBX) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_esp)(i386_state *cpustate) /* Opcode 0x54 */ +{ + PUSH32(cpustate, REG32(ESP) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_ebp)(i386_state *cpustate) /* Opcode 0x55 */ +{ + PUSH32(cpustate, REG32(EBP) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_esi)(i386_state *cpustate) /* Opcode 0x56 */ +{ + PUSH32(cpustate, REG32(ESI) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_edi)(i386_state *cpustate) /* Opcode 0x57 */ +{ + PUSH32(cpustate, REG32(EDI) ); + CYCLES(cpustate,CYCLES_PUSH_REG_SHORT); +} + +static void I386OP(push_cs32)(i386_state *cpustate) /* Opcode 0x0e */ +{ + PUSH32(cpustate, cpustate->sreg[CS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_ds32)(i386_state *cpustate) /* Opcode 0x1e */ +{ + PUSH32(cpustate, cpustate->sreg[DS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_es32)(i386_state *cpustate) /* Opcode 0x06 */ +{ + PUSH32(cpustate, cpustate->sreg[ES].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_fs32)(i386_state *cpustate) /* Opcode 0x0f a0 */ +{ + PUSH32(cpustate, cpustate->sreg[FS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_gs32)(i386_state *cpustate) /* Opcode 0x0f a8 */ +{ + PUSH32(cpustate, cpustate->sreg[GS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_ss32)(i386_state *cpustate) /* Opcode 0x16 */ +{ + PUSH32(cpustate, cpustate->sreg[SS].selector ); + CYCLES(cpustate,CYCLES_PUSH_SREG); +} + +static void I386OP(push_i32)(i386_state *cpustate) /* Opcode 0x68 */ +{ + UINT32 value = FETCH32(cpustate); + PUSH32(cpustate,value); + CYCLES(cpustate,CYCLES_PUSH_IMM); +} + +static void I386OP(pushad)(i386_state *cpustate) /* Opcode 0x60 */ +{ + UINT32 temp = REG32(ESP); + PUSH32(cpustate, REG32(EAX) ); + PUSH32(cpustate, REG32(ECX) ); + PUSH32(cpustate, REG32(EDX) ); + PUSH32(cpustate, REG32(EBX) ); + PUSH32(cpustate, temp ); + PUSH32(cpustate, REG32(EBP) ); + PUSH32(cpustate, REG32(ESI) ); + PUSH32(cpustate, REG32(EDI) ); + CYCLES(cpustate,CYCLES_PUSHA); +} + +static void I386OP(pushfd)(i386_state *cpustate) /* Opcode 0x9c */ +{ + PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff ); + CYCLES(cpustate,CYCLES_PUSHF); +} + +static void I386OP(ret_near32_i16)(i386_state *cpustate) /* Opcode 0xc2 */ +{ + INT16 disp = FETCH16(cpustate); + cpustate->eip = POP32(cpustate); + REG32(ESP) += disp; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ +} + +static void I386OP(ret_near32)(i386_state *cpustate) /* Opcode 0xc3 */ +{ + cpustate->eip = POP32(cpustate); + CHANGE_PC(cpustate,cpustate->eip); + CYCLES(cpustate,CYCLES_RET); /* TODO: Timing = 10 + m */ +} + +static void I386OP(sbb_rm32_r32)(i386_state *cpustate) /* Opcode 0x19 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = SBB32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = SBB32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sbb_r32_rm32)(i386_state *cpustate) /* Opcode 0x1b */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = SBB32(cpustate, dst, src, cpustate->CF); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = SBB32(cpustate, dst, src, cpustate->CF); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sbb_eax_i32)(i386_state *cpustate) /* Opcode 0x1d */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = SBB32(cpustate, dst, src, cpustate->CF); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(scasd)(i386_state *cpustate) /* Opcode 0xaf */ +{ + UINT32 eas, src, dst; + eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ32(cpustate,eas); + dst = REG32(EAX); + SUB32(cpustate,dst, src); + BUMP_DI(cpustate,4); + CYCLES(cpustate,CYCLES_SCAS); +} + +static void I386OP(shld32_i8)(i386_state *cpustate) /* Opcode 0x0f a4 */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (32-shift)); + SetSZPF32(dst); + } + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_SHLD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (32-shift)); + SetSZPF32(dst); + } + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHLD_MEM); + } +} + +static void I386OP(shld32_cl)(i386_state *cpustate) /* Opcode 0x0f a5 */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (32-shift)); + SetSZPF32(dst); + } + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_SHLD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; + dst = (dst << shift) | (upper >> (32-shift)); + SetSZPF32(dst); + } + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHLD_MEM); + } +} + +static void I386OP(shrd32_i8)(i386_state *cpustate) /* Opcode 0x0f ac */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (32-shift)); + SetSZPF32(dst); + } + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_SHRD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = FETCH(cpustate); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (32-shift)); + SetSZPF32(dst); + } + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHRD_MEM); + } +} + +static void I386OP(shrd32_cl)(i386_state *cpustate) /* Opcode 0x0f ad */ +{ + /* TODO: Correct flags */ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (32-shift)); + SetSZPF32(dst); + } + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_SHRD_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 upper = LOAD_REG32(modrm); + UINT8 shift = REG8(CL); + if( shift > 31 || shift == 0 ) { + + } else { + cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; + dst = (dst >> shift) | (upper << (32-shift)); + SetSZPF32(dst); + } + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_SHRD_MEM); + } +} + +static void I386OP(stosd)(i386_state *cpustate) /* Opcode 0xab */ +{ + UINT32 eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + WRITE32(cpustate,eas, REG32(EAX)); + BUMP_DI(cpustate,4); + CYCLES(cpustate,CYCLES_STOS); +} + +static void I386OP(sub_rm32_r32)(i386_state *cpustate) /* Opcode 0x29 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = SUB32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = SUB32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sub_r32_rm32)(i386_state *cpustate) /* Opcode 0x2b */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = SUB32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = SUB32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sub_eax_i32)(i386_state *cpustate) /* Opcode 0x2d */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = SUB32(cpustate,dst, src); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(test_eax_i32)(i386_state *cpustate) /* Opcode 0xa9 */ +{ + UINT32 src = FETCH32(cpustate); + UINT32 dst = REG32(EAX); + dst = src & dst; + SetSZPF32(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_IMM_ACC); +} + +static void I386OP(test_rm32_r32)(i386_state *cpustate) /* Opcode 0x85 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = src & dst; + SetSZPF32(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = src & dst; + SetSZPF32(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_MEM); + } +} + +static void I386OP(xchg_eax_ecx)(i386_state *cpustate) /* Opcode 0x91 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(ECX); + REG32(ECX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_edx)(i386_state *cpustate) /* Opcode 0x92 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(EDX); + REG32(EDX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_ebx)(i386_state *cpustate) /* Opcode 0x93 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(EBX); + REG32(EBX) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_esp)(i386_state *cpustate) /* Opcode 0x94 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(ESP); + REG32(ESP) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_ebp)(i386_state *cpustate) /* Opcode 0x95 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(EBP); + REG32(EBP) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_esi)(i386_state *cpustate) /* Opcode 0x96 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(ESI); + REG32(ESI) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_eax_edi)(i386_state *cpustate) /* Opcode 0x97 */ +{ + UINT32 temp; + temp = REG32(EAX); + REG32(EAX) = REG32(EDI); + REG32(EDI) = temp; + CYCLES(cpustate,CYCLES_XCHG_REG_REG); +} + +static void I386OP(xchg_r32_rm32)(i386_state *cpustate) /* Opcode 0x87 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 src = LOAD_RM32(modrm); + UINT32 dst = LOAD_REG32(modrm); + STORE_REG32(modrm, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 src = READ32(cpustate,ea); + UINT32 dst = LOAD_REG32(modrm); + STORE_REG32(modrm, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_MEM); + } +} + +static void I386OP(xor_rm32_r32)(i386_state *cpustate) /* Opcode 0x31 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG32(modrm); + dst = LOAD_RM32(modrm); + dst = XOR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG32(modrm); + dst = READ32(cpustate,ea); + dst = XOR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(xor_r32_rm32)(i386_state *cpustate) /* Opcode 0x33 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + dst = LOAD_REG32(modrm); + dst = XOR32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + dst = LOAD_REG32(modrm); + dst = XOR32(cpustate,dst, src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(xor_eax_i32)(i386_state *cpustate) /* Opcode 0x35 */ +{ + UINT32 src, dst; + src = FETCH32(cpustate); + dst = REG32(EAX); + dst = XOR32(cpustate,dst, src); + REG32(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + + + +static void I386OP(group81_32)(i386_state *cpustate) /* Opcode 0x81 */ +{ + UINT32 ea; + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ADD Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = ADD32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = ADD32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 1: /* OR Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = OR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = OR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 2: /* ADC Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = ADC32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = ADC32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 3: /* SBB Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = SBB32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = SBB32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 4: /* AND Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = AND32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = AND32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 5: /* SUB Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = SUB32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = SUB32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 6: /* XOR Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + dst = XOR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + dst = XOR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 7: /* CMP Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = FETCH32(cpustate); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = FETCH32(cpustate); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } + break; + } +} + +static void I386OP(group83_32)(i386_state *cpustate) /* Opcode 0x83 */ +{ + UINT32 ea; + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ADD Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = ADD32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = ADD32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 1: /* OR Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = OR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = OR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 2: /* ADC Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = ADC32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = ADC32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 3: /* SBB Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = ((UINT32)(INT32)(INT8)FETCH(cpustate)); + dst = SBB32(cpustate, dst, src, cpustate->CF); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = ((UINT32)(INT32)(INT8)FETCH(cpustate)); + dst = SBB32(cpustate, dst, src, cpustate->CF); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 4: /* AND Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = AND32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = AND32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 5: /* SUB Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = SUB32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = SUB32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 6: /* XOR Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = XOR32(cpustate,dst, src); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + dst = XOR32(cpustate,dst, src); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 7: /* CMP Rm32, i32 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + src = (UINT32)(INT32)(INT8)FETCH(cpustate); + SUB32(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } + break; + } +} + +static void I386OP(groupC1_32)(i386_state *cpustate) /* Opcode 0xc1 */ +{ + UINT32 dst; + UINT8 modrm = FETCH(cpustate); + UINT8 shift; + + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate32(cpustate, modrm, dst, shift); + STORE_RM32(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate32(cpustate, modrm, dst, shift); + WRITE32(cpustate,ea, dst); + } +} + +static void I386OP(groupD1_32)(i386_state *cpustate) /* Opcode 0xd1 */ +{ + UINT32 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + dst = i386_shift_rotate32(cpustate, modrm, dst, 1); + STORE_RM32(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + dst = i386_shift_rotate32(cpustate, modrm, dst, 1); + WRITE32(cpustate,ea, dst); + } +} + +static void I386OP(groupD3_32)(i386_state *cpustate) /* Opcode 0xd3 */ +{ + UINT32 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM32(modrm); + dst = i386_shift_rotate32(cpustate, modrm, dst, REG8(CL)); + STORE_RM32(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ32(cpustate,ea); + dst = i386_shift_rotate32(cpustate, modrm, dst, REG8(CL)); + WRITE32(cpustate,ea, dst); + } +} + +static void I386OP(groupF7_32)(i386_state *cpustate) /* Opcode 0xf7 */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* TEST Rm32, i32 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 src = FETCH32(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF32(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 src = FETCH32(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF32(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_MEM); + } + break; + case 2: /* NOT Rm32 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + dst = ~dst; + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_NOT_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + dst = ~dst; + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NOT_MEM); + } + break; + case 3: /* NEG Rm32 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + dst = SUB32(cpustate, 0, dst ); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_NEG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + dst = SUB32(cpustate, 0, dst ); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NEG_MEM); + } + break; + case 4: /* MUL EAX, Rm32 */ + { + UINT64 result; + UINT32 src, dst; + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = REG32(EAX); + result = (UINT64)src * (UINT64)dst; + REG32(EDX) = (UINT32)(result >> 32); + REG32(EAX) = (UINT32)result; + + cpustate->CF = cpustate->OF = (REG32(EDX) != 0); + } + break; + case 5: /* IMUL EAX, Rm32 */ + { + INT64 result; + INT64 src, dst; + if( modrm >= 0xc0 ) { + src = (INT64)(INT32)LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = (INT64)(INT32)READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = (INT64)(INT32)REG32(EAX); + result = src * dst; + + REG32(EDX) = (UINT32)(result >> 32); + REG32(EAX) = (UINT32)result; + + cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); + } + break; + case 6: /* DIV EAX, Rm32 */ + { + UINT64 quotient, remainder, result; + UINT32 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_DIV32_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_DIV32_ACC_MEM); + } + + quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX)); + if( src ) { + remainder = quotient % (UINT64)src; + result = quotient / (UINT64)src; + if( result > 0xffffffff ) { + /* TODO: Divide error */ + } else { + REG32(EDX) = (UINT32)remainder; + REG32(EAX) = (UINT32)result; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + case 7: /* IDIV EAX, Rm32 */ + { + INT64 quotient, remainder, result; + UINT32 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_IDIV32_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_IDIV32_ACC_MEM); + } + + quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX)); + if( src ) { + remainder = quotient % (INT64)(INT32)src; + result = quotient / (INT64)(INT32)src; + if( result > 0xffffffff ) { + /* TODO: Divide error */ + } else { + REG32(EDX) = (UINT32)remainder; + REG32(EAX) = (UINT32)result; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + } +} + +static void I386OP(groupFF_32)(i386_state *cpustate) /* Opcode 0xff */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* INC Rm32 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + dst = INC32(cpustate,dst); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_INC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + dst = INC32(cpustate,dst); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_INC_MEM); + } + break; + case 1: /* DEC Rm32 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + dst = DEC32(cpustate,dst); + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_DEC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + dst = DEC32(cpustate,dst); + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_DEC_MEM); + } + break; + case 2: /* CALL Rm32 */ + { + UINT32 address; + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ + } + PUSH32(cpustate, cpustate->eip ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 3: /* CALL FAR Rm32 */ + { + UINT16 selector = 0; + UINT32 address = 0; + if( modrm >= 0xc0 ) { + i386_fatal("i386: groupFF_32 /%d: NYI", (modrm >> 3) & 0x7); + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ32(cpustate,ea + 0); + selector = READ16(cpustate,ea + 4); + CYCLES(cpustate,CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ + } + PUSH32(cpustate, cpustate->sreg[CS].selector ); + PUSH32(cpustate, cpustate->eip ); + cpustate->sreg[CS].selector = selector; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate, CS ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 4: /* JMP Rm32 */ + { + UINT32 address; + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + CYCLES(cpustate,CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ32(cpustate,ea); + CYCLES(cpustate,CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ + } + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 5: /* JMP FAR Rm32 */ + { + UINT16 selector = 0; + UINT32 address = 0; + if( modrm >= 0xc0 ) { + i386_fatal("i386: groupFF_32 /%d: NYI", (modrm >> 3) & 0x7); + } else { + UINT32 ea = GetEA(cpustate,modrm); + address = READ32(cpustate,ea + 0); + selector = READ16(cpustate,ea + 4); + CYCLES(cpustate,CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ + } + cpustate->sreg[CS].selector = selector; + cpustate->performed_intersegment_jump = 1; + i386_load_segment_descriptor(cpustate, CS ); + cpustate->eip = address; + CHANGE_PC(cpustate,cpustate->eip); + } + break; + case 6: /* PUSH Rm32 */ + { + UINT32 value; + if( modrm >= 0xc0 ) { + value = LOAD_RM32(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + value = READ32(cpustate,ea); + } + PUSH32(cpustate,value); + CYCLES(cpustate,CYCLES_PUSH_RM); + } + break; + default: + i386_fatal("i386: groupFF_32 /%d unimplemented at %08X", (modrm >> 3) & 0x7, cpustate->pc-2); + break; + } +} + +static void I386OP(group0F00_32)(i386_state *cpustate) /* Opcode 0x0f 00 */ +{ + UINT32 address, ea; + UINT8 modrm = FETCH(cpustate); + I386_SREG seg; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SLDT */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + STORE_RM32(address, cpustate->ldtr.segment); + CYCLES(cpustate,CYCLES_SLDT_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE32(cpustate, ea, cpustate->ldtr.segment); + CYCLES(cpustate,CYCLES_SLDT_MEM); + } + } + else + { + i386_trap(cpustate,6, 0); + } + break; + case 1: /* STR */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + STORE_RM32(address, cpustate->task.segment); + CYCLES(cpustate,CYCLES_STR_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE32(cpustate, ea, cpustate->task.segment); + CYCLES(cpustate,CYCLES_STR_MEM); + } + } + else + { + i386_trap(cpustate,6, 0); + } + break; + case 2: /* LLDT */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + CYCLES(cpustate,CYCLES_LLDT_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LLDT_MEM); + } + cpustate->ldtr.segment = READ32(cpustate,ea); + memset(&seg, 0, sizeof(seg)); + seg.selector = cpustate->ldtr.segment; + i386_load_protected_mode_segment(cpustate,&seg); + cpustate->ldtr.limit = seg.limit; + cpustate->ldtr.base = seg.base; + } + else + { + i386_trap(cpustate,6, 0); + } + break; + + case 3: /* LTR */ + if ( PROTECTED_MODE && !V8086_MODE ) + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + CYCLES(cpustate,CYCLES_LTR_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LTR_MEM); + } + cpustate->task.segment = READ32(cpustate,ea); + } + else + { + i386_trap(cpustate,6, 0); + } + break; + + default: + i386_fatal("i386: group0F00_32 /%d unimplemented", (modrm >> 3) & 0x7); + break; + } +} + +static void I386OP(group0F01_32)(i386_state *cpustate) /* Opcode 0x0f 01 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 address, ea; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->gdtr.limit); + WRITE32(cpustate,ea + 2, cpustate->gdtr.base); + CYCLES(cpustate,CYCLES_SGDT); + break; + } + case 1: /* SIDT */ + { + if (modrm >= 0xc0) + { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + } + else + { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->idtr.limit); + WRITE32(cpustate,ea + 2, cpustate->idtr.base); + CYCLES(cpustate,CYCLES_SIDT); + break; + } + case 2: /* LGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->gdtr.limit = READ16(cpustate,ea); + cpustate->gdtr.base = READ32(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_LGDT); + break; + } + case 3: /* LIDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate(cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->idtr.limit = READ16(cpustate,ea); + cpustate->idtr.base = READ32(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_LIDT); + break; + } + default: + i386_fatal("i386: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2); + break; + } +} + +static void I386OP(group0FBA_32)(i386_state *cpustate) /* Opcode 0x0f ba */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 4: /* BT Rm32, i8 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + + CYCLES(cpustate,CYCLES_BT_IMM_MEM); + } + break; + case 5: /* BTS Rm32, i8 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTS_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst |= (1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTS_IMM_MEM); + } + break; + case 6: /* BTR Rm32, i8 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTR_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst &= ~(1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTR_IMM_MEM); + } + break; + case 7: /* BTC Rm32, i8 */ + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + STORE_RM32(modrm, dst); + CYCLES(cpustate,CYCLES_BTC_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT8 bit = FETCH(cpustate); + + if( dst & (1 << bit) ) + cpustate->CF = 1; + else + cpustate->CF = 0; + dst ^= (1 << bit); + + WRITE32(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_BTC_IMM_MEM); + } + break; + default: + i386_fatal("i386: group0FBA_32 /%d unknown", (modrm >> 3) & 0x7); + break; + } +} + +static void I386OP(lsl_r32_rm32)(i386_state *cpustate) /* Opcode 0x0f 0x03 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 limit; + I386_SREG seg; + + if(PROTECTED_MODE) + { + memset(&seg, 0, sizeof(seg)); + seg.selector = LOAD_RM32(modrm); + if(seg.selector == 0) + { + SetZF(0); /* not a valid segment */ + } + else + { + /* TODO: check segment type */ + i386_load_protected_mode_segment(cpustate,&seg); + limit = seg.limit; + STORE_REG32(modrm,limit); + SetZF(1); + } + } + else + i386_trap(cpustate,6, 0); +} + +static void I386OP(bound_r32_m32_m32)(i386_state *cpustate) /* Opcode 0x62 */ +{ + UINT8 modrm; + INT32 val, low, high; + + modrm = FETCH(cpustate); + + if (modrm >= 0xc0) + { + low = high = LOAD_RM32(modrm); + } + else + { + UINT32 ea = GetEA(cpustate,modrm); + low = READ32(cpustate,ea + 0); + high = READ32(cpustate,ea + 4); + } + val = LOAD_REG32(modrm); + + if ((val < low) || (val > high)) + { + CYCLES(cpustate,CYCLES_BOUND_OUT_RANGE); + i386_trap(cpustate,5, 0); + } + else + { + CYCLES(cpustate,CYCLES_BOUND_IN_RANGE); + } +} + +static void I386OP(retf32)(i386_state *cpustate) /* Opcode 0xcb */ +{ + cpustate->eip = POP32(cpustate); + cpustate->sreg[CS].selector = POP32(cpustate); + i386_load_segment_descriptor(cpustate, CS ); + CHANGE_PC(cpustate,cpustate->eip); + + CYCLES(cpustate,CYCLES_RET_INTERSEG); +} + +static void I386OP(retf_i32)(i386_state *cpustate) /* Opcode 0xca */ +{ + UINT16 count = FETCH16(cpustate); + + cpustate->eip = POP32(cpustate); + cpustate->sreg[CS].selector = POP32(cpustate); + i386_load_segment_descriptor(cpustate, CS ); + CHANGE_PC(cpustate,cpustate->eip); + + REG32(ESP) += count; + CYCLES(cpustate,CYCLES_RET_IMM_INTERSEG); +} + +static void I386OP(xlat32)(i386_state *cpustate) /* Opcode 0xd7 */ +{ + UINT32 ea; + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, REG32(EBX) + REG8(AL) ); + } else { + ea = i386_translate(cpustate, DS, REG32(EBX) + REG8(AL) ); + } + REG8(AL) = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_XLAT); +} + +static void I386OP(load_far_pointer32)(i386_state *cpustate, int s) +{ + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + i386_fatal("i386: load_far_pointer32 NYI"); + } else { + UINT32 ea = GetEA(cpustate,modrm); + STORE_REG32(modrm, READ32(cpustate,ea + 0)); + cpustate->sreg[s].selector = READ16(cpustate,ea + 4); + i386_load_segment_descriptor(cpustate, s ); + } +} + +static void I386OP(lds32)(i386_state *cpustate) /* Opcode 0xc5 */ +{ + I386OP(load_far_pointer32)(cpustate, DS); + CYCLES(cpustate,CYCLES_LDS); +} + +static void I386OP(lss32)(i386_state *cpustate) /* Opcode 0x0f 0xb2 */ +{ + I386OP(load_far_pointer32)(cpustate, SS); + CYCLES(cpustate,CYCLES_LSS); +} + +static void I386OP(les32)(i386_state *cpustate) /* Opcode 0xc4 */ +{ + I386OP(load_far_pointer32)(cpustate, ES); + CYCLES(cpustate,CYCLES_LES); +} + +static void I386OP(lfs32)(i386_state *cpustate) /* Opcode 0x0f 0xb4 */ +{ + I386OP(load_far_pointer32)(cpustate, FS); + CYCLES(cpustate,CYCLES_LFS); +} + +static void I386OP(lgs32)(i386_state *cpustate) /* Opcode 0x0f 0xb5 */ +{ + I386OP(load_far_pointer32)(cpustate, GS); + CYCLES(cpustate,CYCLES_LGS); +} diff --git a/src/cpu/i386/i386ops.c b/src/cpu/i386/i386ops.c new file mode 100644 index 00000000..07a2dc38 --- /dev/null +++ b/src/cpu/i386/i386ops.c @@ -0,0 +1,2367 @@ +static UINT8 I386OP(shift_rotate8)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift) +{ + UINT8 src = value; + UINT8 dst = value; + + if( shift == 0 ) { + CYCLES_RM(cpustate,modrm, 3, 7); + } else if( shift == 1 ) { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm8, 1 */ + cpustate->CF = (src & 0x80) ? 1 : 0; + dst = (src << 1) + cpustate->CF; + cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm8, 1 */ + cpustate->CF = (src & 0x1) ? 1 : 0; + dst = (cpustate->CF << 7) | (src >> 1); + cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm8, 1 */ + dst = (src << 1) + cpustate->CF; + cpustate->CF = (src & 0x80) ? 1 : 0; + cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm8, 1 */ + dst = (cpustate->CF << 7) | (src >> 1); + cpustate->CF = src & 0x1; + cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm8, 1 */ + case 6: + dst = src << 1; + cpustate->CF = (src & 0x80) ? 1 : 0; + cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm8, 1 */ + dst = src >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = (dst & 0x80) ? 1 : 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm8, 1 */ + dst = (INT8)(src) >> 1; + cpustate->CF = src & 0x1; + cpustate->OF = 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + + } else { + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ROL rm8, i8 */ + dst = ((src & ((UINT8)0xff >> shift)) << shift) | + ((src & ((UINT8)0xff << (8-shift))) >> (8-shift)); + cpustate->CF = (src >> (8-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 1: /* ROR rm8, i8 */ + dst = ((src & ((UINT8)0xff << shift)) >> shift) | + ((src & ((UINT8)0xff >> (8-shift))) << (8-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 2: /* RCL rm8, i8 */ + dst = ((src & ((UINT8)0xff >> shift)) << shift) | + ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) | + (cpustate->CF << (shift-1)); + cpustate->CF = (src >> (8-shift)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 3: /* RCR rm8, i8 */ + dst = ((src & ((UINT8)0xff << shift)) >> shift) | + ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) | + (cpustate->CF << (8-shift)); + cpustate->CF = (src >> (shift-1)) & 0x1; + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); + break; + case 4: /* SHL/SAL rm8, i8 */ + case 6: + dst = src << shift; + cpustate->CF = (src & (1 << (8-shift))) ? 1 : 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 5: /* SHR rm8, i8 */ + dst = src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + case 7: /* SAR rm8, i8 */ + dst = (INT8)src >> shift; + cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; + SetSZPF8(dst); + CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); + break; + } + } + + return dst; +} + + + +static void I386OP(adc_rm8_r8)(i386_state *cpustate) /* Opcode 0x10 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = ADC8(cpustate, dst, src, cpustate->CF); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = ADC8(cpustate, dst, src, cpustate->CF); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(adc_r8_rm8)(i386_state *cpustate) /* Opcode 0x12 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = ADC8(cpustate, dst, src, cpustate->CF); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = ADC8(cpustate, dst, src, cpustate->CF); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(adc_al_i8)(i386_state *cpustate) /* Opcode 0x14 */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = ADC8(cpustate, dst, src, cpustate->CF); + REG8(AL) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(add_rm8_r8)(i386_state *cpustate) /* Opcode 0x00 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = ADD8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = ADD8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(add_r8_rm8)(i386_state *cpustate) /* Opcode 0x02 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = ADD8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = ADD8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(add_al_i8)(i386_state *cpustate) /* Opcode 0x04 */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = ADD8(cpustate,dst, src); + REG8(AL) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(and_rm8_r8)(i386_state *cpustate) /* Opcode 0x20 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = AND8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = AND8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(and_r8_rm8)(i386_state *cpustate) /* Opcode 0x22 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = AND8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = AND8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(and_al_i8)(i386_state *cpustate) /* Opcode 0x24 */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = AND8(cpustate,dst, src); + REG8(AL) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(clc)(i386_state *cpustate) /* Opcode 0xf8 */ +{ + cpustate->CF = 0; + CYCLES(cpustate,CYCLES_CLC); +} + +static void I386OP(cld)(i386_state *cpustate) /* Opcode 0xfc */ +{ + cpustate->DF = 0; + CYCLES(cpustate,CYCLES_CLD); +} + +static void I386OP(cli)(i386_state *cpustate) /* Opcode 0xfa */ +{ + cpustate->IF = 0; + CYCLES(cpustate,CYCLES_CLI); +} + +static void I386OP(cmc)(i386_state *cpustate) /* Opcode 0xf5 */ +{ + cpustate->CF ^= 1; + CYCLES(cpustate,CYCLES_CMC); +} + +static void I386OP(cmp_rm8_r8)(i386_state *cpustate) /* Opcode 0x38 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } +} + +static void I386OP(cmp_r8_rm8)(i386_state *cpustate) /* Opcode 0x3a */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_MEM_REG); + } +} + +static void I386OP(cmp_al_i8)(i386_state *cpustate) /* Opcode 0x3c */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_IMM_ACC); +} + +static void I386OP(cmpsb)(i386_state *cpustate) /* Opcode 0xa6 */ +{ + UINT32 eas, ead; + UINT8 src, dst; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ8(cpustate,eas); + dst = READ8(cpustate,ead); + SUB8(cpustate,dst, src); + BUMP_SI(cpustate,1); + BUMP_DI(cpustate,1); + CYCLES(cpustate,CYCLES_CMPS); +} + +static void I386OP(in_al_i8)(i386_state *cpustate) /* Opcode 0xe4 */ +{ + UINT16 port = FETCH(cpustate); + UINT8 data = READPORT8(port); + REG8(AL) = data; + CYCLES(cpustate,CYCLES_IN_VAR); +} + +static void I386OP(in_al_dx)(i386_state *cpustate) /* Opcode 0xec */ +{ + UINT16 port = REG16(DX); + UINT8 data = READPORT8(port); + REG8(AL) = data; + CYCLES(cpustate,CYCLES_IN); +} + +static void I386OP(ja_rel8)(i386_state *cpustate) /* Opcode 0x77 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->CF == 0 && cpustate->ZF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jbe_rel8)(i386_state *cpustate) /* Opcode 0x76 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->CF != 0 || cpustate->ZF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jc_rel8)(i386_state *cpustate) /* Opcode 0x72 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->CF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jg_rel8)(i386_state *cpustate) /* Opcode 0x7f */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jge_rel8)(i386_state *cpustate) /* Opcode 0x7d */ +{ + INT8 disp = FETCH(cpustate); + if( (cpustate->SF == cpustate->OF) ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jl_rel8)(i386_state *cpustate) /* Opcode 0x7c */ +{ + INT8 disp = FETCH(cpustate); + if( (cpustate->SF != cpustate->OF) ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jle_rel8)(i386_state *cpustate) /* Opcode 0x7e */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jnc_rel8)(i386_state *cpustate) /* Opcode 0x73 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->CF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jno_rel8)(i386_state *cpustate) /* Opcode 0x71 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->OF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jnp_rel8)(i386_state *cpustate) /* Opcode 0x7b */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->PF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jns_rel8)(i386_state *cpustate) /* Opcode 0x79 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->SF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jnz_rel8)(i386_state *cpustate) /* Opcode 0x75 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->ZF == 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jo_rel8)(i386_state *cpustate) /* Opcode 0x70 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->OF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jp_rel8)(i386_state *cpustate) /* Opcode 0x7a */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->PF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(js_rel8)(i386_state *cpustate) /* Opcode 0x78 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->SF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jz_rel8)(i386_state *cpustate) /* Opcode 0x74 */ +{ + INT8 disp = FETCH(cpustate); + if( cpustate->ZF != 0 ) { + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ + } else { + CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH); + } +} + +static void I386OP(jmp_rel8)(i386_state *cpustate) /* Opcode 0xeb */ +{ + INT8 disp = FETCH(cpustate); + NEAR_BRANCH(cpustate,disp); + CYCLES(cpustate,CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */ +} + +static void I386OP(lahf)(i386_state *cpustate) /* Opcode 0x9f */ +{ + REG8(AH) = get_flags(cpustate) & 0xd7; + CYCLES(cpustate,CYCLES_LAHF); +} + +static void I386OP(lodsb)(i386_state *cpustate) /* Opcode 0xac */ +{ + UINT32 eas; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + REG8(AL) = READ8(cpustate,eas); + BUMP_SI(cpustate,1); + CYCLES(cpustate,CYCLES_LODS); +} + +static void I386OP(mov_rm8_r8)(i386_state *cpustate) /* Opcode 0x88 */ +{ + UINT8 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + STORE_RM8(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + WRITE8(cpustate,ea, src); + CYCLES(cpustate,CYCLES_MOV_REG_MEM); + } +} + +static void I386OP(mov_r8_rm8)(i386_state *cpustate) /* Opcode 0x8a */ +{ + UINT8 src; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + STORE_REG8(modrm, src); + CYCLES(cpustate,CYCLES_MOV_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + STORE_REG8(modrm, src); + CYCLES(cpustate,CYCLES_MOV_MEM_REG); + } +} + +static void I386OP(mov_rm8_i8)(i386_state *cpustate) /* Opcode 0xc6 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT8 value = FETCH(cpustate); + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 value = FETCH(cpustate); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_MOV_IMM_MEM); + } +} + +static void I386OP(mov_r32_cr)(i386_state *cpustate) /* Opcode 0x0f 20 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 cr = (modrm >> 3) & 0x7; + + STORE_RM32(modrm, cpustate->cr[cr]); + CYCLES(cpustate,CYCLES_MOV_CR_REG); +} + +static void I386OP(mov_r32_dr)(i386_state *cpustate) /* Opcode 0x0f 21 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 dr = (modrm >> 3) & 0x7; + + STORE_RM32(modrm, cpustate->dr[dr]); + switch(dr) + { + case 0: + case 1: + case 2: + case 3: + CYCLES(cpustate,CYCLES_MOV_REG_DR0_3); + break; + case 6: + case 7: + CYCLES(cpustate,CYCLES_MOV_REG_DR6_7); + break; + } +} + +static void I386OP(mov_cr_r32)(i386_state *cpustate) /* Opcode 0x0f 22 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 cr = (modrm >> 3) & 0x7; + + cpustate->cr[cr] = LOAD_RM32(modrm); + switch(cr) + { + case 0: CYCLES(cpustate,CYCLES_MOV_REG_CR0); break; + case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break; + case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break; + case 4: CYCLES(cpustate,1); break; /* TODO */ + default: + i386_fatal("i386: mov_cr_r32 CR%d !", cr); + break; + } +} + +static void I386OP(mov_dr_r32)(i386_state *cpustate) /* Opcode 0x0f 23 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 dr = (modrm >> 3) & 0x7; + + cpustate->dr[dr] = LOAD_RM32(modrm); + switch(dr) + { + case 0: + case 1: + case 2: + case 3: + CYCLES(cpustate,CYCLES_MOV_DR0_3_REG); + break; + case 6: + case 7: + CYCLES(cpustate,CYCLES_MOV_DR6_7_REG); + break; + default: + i386_fatal("i386: mov_dr_r32 DR%d !", dr); + break; + } +} + +static void I386OP(mov_al_m8)(i386_state *cpustate) /* Opcode 0xa0 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + /* TODO: Not sure if this is correct... */ + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + REG8(AL) = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_MOV_IMM_MEM); +} + +static void I386OP(mov_m8_al)(i386_state *cpustate) /* Opcode 0xa2 */ +{ + UINT32 offset, ea; + if( cpustate->address_size ) { + offset = FETCH32(cpustate); + } else { + offset = FETCH16(cpustate); + } + /* TODO: Not sure if this is correct... */ + if( cpustate->segment_prefix ) { + ea = i386_translate(cpustate, cpustate->segment_override, offset ); + } else { + ea = i386_translate(cpustate, DS, offset ); + } + WRITE8(cpustate, ea, REG8(AL) ); + CYCLES(cpustate,CYCLES_MOV_MEM_ACC); +} + +static void I386OP(mov_rm16_sreg)(i386_state *cpustate) /* Opcode 0x8c */ +{ + UINT8 modrm = FETCH(cpustate); + int s = (modrm >> 3) & 0x7; + + if( modrm >= 0xc0 ) { + STORE_RM16(modrm, cpustate->sreg[s].selector); + CYCLES(cpustate,CYCLES_MOV_SREG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE16(cpustate,ea, cpustate->sreg[s].selector); + CYCLES(cpustate,CYCLES_MOV_SREG_MEM); + } +} + +static void I386OP(mov_sreg_rm16)(i386_state *cpustate) /* Opcode 0x8e */ +{ + UINT16 selector; + UINT8 modrm = FETCH(cpustate); + int s = (modrm >> 3) & 0x7; + + if( modrm >= 0xc0 ) { + selector = LOAD_RM16(modrm); + CYCLES(cpustate,CYCLES_MOV_REG_SREG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + selector = READ16(cpustate,ea); + CYCLES(cpustate,CYCLES_MOV_MEM_SREG); + } + cpustate->sreg[s].selector = selector; + i386_load_segment_descriptor(cpustate, s ); +} + +static void I386OP(mov_al_i8)(i386_state *cpustate) /* Opcode 0xb0 */ +{ + REG8(AL) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_cl_i8)(i386_state *cpustate) /* Opcode 0xb1 */ +{ + REG8(CL) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_dl_i8)(i386_state *cpustate) /* Opcode 0xb2 */ +{ + REG8(DL) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_bl_i8)(i386_state *cpustate) /* Opcode 0xb3 */ +{ + REG8(BL) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_ah_i8)(i386_state *cpustate) /* Opcode 0xb4 */ +{ + REG8(AH) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_ch_i8)(i386_state *cpustate) /* Opcode 0xb5 */ +{ + REG8(CH) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_dh_i8)(i386_state *cpustate) /* Opcode 0xb6 */ +{ + REG8(DH) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(mov_bh_i8)(i386_state *cpustate) /* Opcode 0xb7 */ +{ + REG8(BH) = FETCH(cpustate); + CYCLES(cpustate,CYCLES_MOV_IMM_REG); +} + +static void I386OP(movsb)(i386_state *cpustate) /* Opcode 0xa4 */ +{ + UINT32 eas, ead; + UINT8 v; + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + v = READ8(cpustate,eas); + WRITE8(cpustate,ead, v); + BUMP_SI(cpustate,1); + BUMP_DI(cpustate,1); + CYCLES(cpustate,CYCLES_MOVS); +} + +static void I386OP(or_rm8_r8)(i386_state *cpustate) /* Opcode 0x08 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = OR8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = OR8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(or_r8_rm8)(i386_state *cpustate) /* Opcode 0x0a */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = OR8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = OR8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(or_al_i8)(i386_state *cpustate) /* Opcode 0x0c */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = OR8(cpustate,dst, src); + REG8(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(out_al_i8)(i386_state *cpustate) /* Opcode 0xe6 */ +{ + UINT16 port = FETCH(cpustate); + UINT8 data = REG8(AL); + WRITEPORT8(port, data); + CYCLES(cpustate,CYCLES_OUT_VAR); +} + +static void I386OP(out_al_dx)(i386_state *cpustate) /* Opcode 0xee */ +{ + UINT16 port = REG16(DX); + UINT8 data = REG8(AL); + WRITEPORT8(port, data); + CYCLES(cpustate,CYCLES_OUT); +} + + +static void I386OP(arpl)(i386_state *cpustate) /* Opcode 0x63 */ +{ + UINT16 src, dst; + UINT8 modrm = FETCH(cpustate); + UINT8 flag = 0; + + if( modrm >= 0xc0 ) { + src = LOAD_REG16(modrm); + dst = LOAD_RM16(modrm); + if( (dst&0x3) < (src&0x3) ) { + dst = (dst&0xfffc) | (src&0x3); + flag = 1; + STORE_RM16(modrm, dst); + } + } else { + UINT32 ea = GetEA(cpustate, modrm); + src = LOAD_REG16(modrm); + dst = READ16(cpustate, ea); + if( (dst&0x3) < (src&0x3) ) { + dst = (dst&0xfffc) | (src&0x3); + flag = 1; + WRITE16(cpustate, ea, dst); + } + } + SetZF(flag); +} + +static void I386OP(push_i8)(i386_state *cpustate) /* Opcode 0x6a */ +{ + UINT8 value = FETCH(cpustate); + PUSH8(cpustate,value); + CYCLES(cpustate,CYCLES_PUSH_IMM); +} + +static void I386OP(ins_generic)(i386_state *cpustate, int size) +{ + UINT32 ead; + UINT8 vb; + UINT16 vw; + UINT32 vd; + + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + + switch(size) { + case 1: + vb = READPORT8(REG16(DX)); + WRITE8(cpustate,ead, vb); + break; + case 2: + vw = READPORT16(REG16(DX)); + WRITE16(cpustate,ead, vw); + break; + case 4: + vd = READPORT32(REG16(DX)); + WRITE32(cpustate,ead, vd); + break; + } + + REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size; + CYCLES(cpustate,CYCLES_INS); /* TODO: Confirm this value */ +} + +static void I386OP(insb)(i386_state *cpustate) /* Opcode 0x6c */ +{ + I386OP(ins_generic)(cpustate, 1); +} + +static void I386OP(insw)(i386_state *cpustate) /* Opcode 0x6d */ +{ + I386OP(ins_generic)(cpustate, 2); +} + +static void I386OP(insd)(i386_state *cpustate) /* Opcode 0x6d */ +{ + I386OP(ins_generic)(cpustate, 4); +} + +static void I386OP(outs_generic)(i386_state *cpustate, int size) +{ + UINT32 eas; + UINT8 vb; + UINT16 vw; + UINT32 vd; + + if( cpustate->segment_prefix ) { + eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } else { + eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) ); + } + + switch(size) { + case 1: + vb = READ8(cpustate,eas); + WRITEPORT8(REG16(DX), vb); + break; + case 2: + vw = READ16(cpustate,eas); + WRITEPORT16(REG16(DX), vw); + break; + case 4: + vd = READ32(cpustate,eas); + WRITEPORT32(REG16(DX), vd); + break; + } + + REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size; + CYCLES(cpustate,CYCLES_OUTS); /* TODO: Confirm this value */ +} + +static void I386OP(outsb)(i386_state *cpustate) /* Opcode 0x6e */ +{ + I386OP(outs_generic)(cpustate, 1); +} + +static void I386OP(outsw)(i386_state *cpustate) /* Opcode 0x6f */ +{ + I386OP(outs_generic)(cpustate, 2); +} + +static void I386OP(outsd)(i386_state *cpustate) /* Opcode 0x6f */ +{ + I386OP(outs_generic)(cpustate, 4); +} + +static void I386OP(repeat)(i386_state *cpustate, int invert_flag) +{ + UINT32 repeated_eip = cpustate->eip; + UINT32 repeated_pc = cpustate->pc; + UINT8 opcode; /* = FETCH(cpustate); */ + UINT32 count; + INT32 cycle_base = 0, cycle_adjustment = 0; + UINT8 prefix_flag=1; + UINT8 *flag = NULL; + + + do { + repeated_eip = cpustate->eip; + repeated_pc = cpustate->pc; + opcode = FETCH(cpustate); + switch(opcode) { + case 0x26: + cpustate->segment_override=ES; + cpustate->segment_prefix=1; + break; + case 0x2e: + cpustate->segment_override=CS; + cpustate->segment_prefix=1; + break; + case 0x36: + cpustate->segment_override=SS; + cpustate->segment_prefix=1; + break; + case 0x3e: + cpustate->segment_override=DS; + cpustate->segment_prefix=1; + break; + case 0x64: + cpustate->segment_override=FS; + cpustate->segment_prefix=1; + break; + case 0x65: + cpustate->segment_override=GS; + cpustate->segment_prefix=1; + break; + case 0x66: + cpustate->operand_size ^= 1; + break; + case 0x67: + cpustate->address_size ^= 1; + break; + default: + prefix_flag=0; + } + } while (prefix_flag); + + + /* (the source and destination addresses, unused, of 0.139 removed) */ + switch(opcode) + { + case 0x6c: + case 0x6d: + /* INSB, INSW, INSD */ + /* TODO: cycle count */ + cycle_base = 8; + cycle_adjustment = -4; + flag = NULL; + break; + + case 0x6e: + case 0x6f: + /* OUTSB, OUTSW, OUTSD */ + /* TODO: cycle count */ + cycle_base = 8; + cycle_adjustment = -4; + flag = NULL; + break; + + case 0xa4: + case 0xa5: + /* MOVSB, MOVSW, MOVSD */ + cycle_base = 8; + cycle_adjustment = -4; + flag = NULL; + break; + + case 0xa6: + case 0xa7: + /* CMPSB, CMPSW, CMPSD */ + cycle_base = 5; + cycle_adjustment = -1; + flag = &cpustate->ZF; + break; + + case 0xac: + case 0xad: + /* LODSB, LODSW, LODSD */ + cycle_base = 5; + cycle_adjustment = 1; + flag = NULL; + break; + + case 0xaa: + case 0xab: + /* STOSB, STOSW, STOSD */ + cycle_base = 5; + cycle_adjustment = 0; + flag = NULL; + break; + + case 0xae: + case 0xaf: + /* SCASB, SCASW, SCASD */ + cycle_base = 5; + cycle_adjustment = 0; + flag = &cpustate->ZF; + break; + + default: + i386_fatal("i386: Invalid REP/opcode %02X combination",opcode); + break; + } + + if( cpustate->address_size ) { + if( REG32(ECX) == 0 ) + return; + } else { + if( REG16(CX) == 0 ) + return; + } + + /* now actually perform the repeat */ + CYCLES_NUM(cycle_base); + do + { + cpustate->eip = repeated_eip; + cpustate->pc = repeated_pc; + I386OP(decode_opcode)(cpustate); + CYCLES_NUM(cycle_adjustment); + + if (cpustate->address_size) + count = --REG32(ECX); + else + count = --REG16(CX); + if (i386_ICount <= 0) + goto outofcycles; + } + while( count && (!flag || (invert_flag ? !*flag : *flag)) ); + return; + +outofcycles: + /* if we run out of cycles to execute, and we are still in the repeat, we need + * to exit this instruction in such a way to go right back into it when we have + * time to execute cycles */ + cpustate->eip = cpustate->prev_eip; + CHANGE_PC(cpustate,cpustate->eip); + CYCLES_NUM(-cycle_base); +} + +static void I386OP(rep)(i386_state *cpustate) /* Opcode 0xf3 */ +{ + I386OP(repeat)(cpustate, 0); +} + +static void I386OP(repne)(i386_state *cpustate) /* Opcode 0xf2 */ +{ + I386OP(repeat)(cpustate, 1); +} + +static void I386OP(sahf)(i386_state *cpustate) /* Opcode 0x9e */ +{ + set_flags(cpustate, (get_flags(cpustate) & 0xffffff00) | (REG8(AH) & 0xd7) ); + CYCLES(cpustate,CYCLES_SAHF); +} + +static void I386OP(sbb_rm8_r8)(i386_state *cpustate) /* Opcode 0x18 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = SBB8(cpustate, dst, src, cpustate->CF); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = SBB8(cpustate, dst, src, cpustate->CF); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sbb_r8_rm8)(i386_state *cpustate) /* Opcode 0x1a */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = SBB8(cpustate, dst, src, cpustate->CF); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = SBB8(cpustate, dst, src, cpustate->CF); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sbb_al_i8)(i386_state *cpustate) /* Opcode 0x1c */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = SBB8(cpustate, dst, src, cpustate->CF); + REG8(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(scasb)(i386_state *cpustate) /* Opcode 0xae */ +{ + UINT32 eas; + UINT8 src, dst; + eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + src = READ8(cpustate,eas); + dst = REG8(AL); + SUB8(cpustate,dst, src); + BUMP_DI(cpustate,1); + CYCLES(cpustate,CYCLES_SCAS); +} + +static void I386OP(setalc)(i386_state *cpustate) /* Opcode 0xd6 (undocumented) */ +{ + if( cpustate->CF ) { + REG8(AL) = 0xff; + } else { + REG8(AL) = 0; + } + CYCLES(cpustate,3); +} + +static void I386OP(seta_rm8)(i386_state *cpustate) /* Opcode 0x0f 97 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->CF == 0 && cpustate->ZF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setbe_rm8)(i386_state *cpustate) /* Opcode 0x0f 96 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->CF != 0 || cpustate->ZF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setc_rm8)(i386_state *cpustate) /* Opcode 0x0f 92 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->CF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setg_rm8)(i386_state *cpustate) /* Opcode 0x0f 9f */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setge_rm8)(i386_state *cpustate) /* Opcode 0x0f 9d */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( (cpustate->SF == cpustate->OF) ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setl_rm8)(i386_state *cpustate) /* Opcode 0x0f 9c */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->SF != cpustate->OF ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setle_rm8)(i386_state *cpustate) /* Opcode 0x0f 9e */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setnc_rm8)(i386_state *cpustate) /* Opcode 0x0f 93 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->CF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setno_rm8)(i386_state *cpustate) /* Opcode 0x0f 91 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->OF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setnp_rm8)(i386_state *cpustate) /* Opcode 0x0f 9b */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->PF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setns_rm8)(i386_state *cpustate) /* Opcode 0x0f 99 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->SF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setnz_rm8)(i386_state *cpustate) /* Opcode 0x0f 95 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->ZF == 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(seto_rm8)(i386_state *cpustate) /* Opcode 0x0f 90 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->OF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setp_rm8)(i386_state *cpustate) /* Opcode 0x0f 9a */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->PF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(sets_rm8)(i386_state *cpustate) /* Opcode 0x0f 98 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->SF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(setz_rm8)(i386_state *cpustate) /* Opcode 0x0f 94 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT8 value = 0; + if( cpustate->ZF != 0 ) { + value = 1; + } + if( modrm >= 0xc0 ) { + STORE_RM8(modrm, value); + CYCLES(cpustate,CYCLES_SETCC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + WRITE8(cpustate,ea, value); + CYCLES(cpustate,CYCLES_SETCC_MEM); + } +} + +static void I386OP(stc)(i386_state *cpustate) /* Opcode 0xf9 */ +{ + cpustate->CF = 1; + CYCLES(cpustate,CYCLES_STC); +} + +static void I386OP(std)(i386_state *cpustate) /* Opcode 0xfd */ +{ + cpustate->DF = 1; + CYCLES(cpustate,CYCLES_STD); +} + +static void I386OP(sti)(i386_state *cpustate) /* Opcode 0xfb */ +{ + cpustate->IF = 1; + CYCLES(cpustate,CYCLES_STI); +} + +static void I386OP(stosb)(i386_state *cpustate) /* Opcode 0xaa */ +{ + UINT32 ead; + ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) ); + WRITE8(cpustate,ead, REG8(AL)); + BUMP_DI(cpustate,1); + CYCLES(cpustate,CYCLES_STOS); +} + +static void I386OP(sub_rm8_r8)(i386_state *cpustate) /* Opcode 0x28 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = SUB8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = SUB8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(sub_r8_rm8)(i386_state *cpustate) /* Opcode 0x2a */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = SUB8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = SUB8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(sub_al_i8)(i386_state *cpustate) /* Opcode 0x2c */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(EAX); + dst = SUB8(cpustate,dst, src); + REG8(EAX) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(test_al_i8)(i386_state *cpustate) /* Opcode 0xa8 */ +{ + UINT8 src = FETCH(cpustate); + UINT8 dst = REG8(AL); + dst = src & dst; + SetSZPF8(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + +static void I386OP(test_rm8_r8)(i386_state *cpustate) /* Opcode 0x84 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = src & dst; + SetSZPF8(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = src & dst; + SetSZPF8(dst); + cpustate->CF = 0; + cpustate->OF = 0; + CYCLES(cpustate,CYCLES_TEST_REG_MEM); + } +} + +static void I386OP(xchg_r8_rm8)(i386_state *cpustate) /* Opcode 0x86 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT8 src = LOAD_RM8(modrm); + UINT8 dst = LOAD_REG8(modrm); + STORE_REG8(modrm, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 src = READ8(cpustate,ea); + UINT8 dst = LOAD_REG8(modrm); + STORE_REG8(modrm, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_XCHG_REG_MEM); + } +} + +static void I386OP(xor_rm8_r8)(i386_state *cpustate) /* Opcode 0x30 */ +{ + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_REG8(modrm); + dst = LOAD_RM8(modrm); + dst = XOR8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = LOAD_REG8(modrm); + dst = READ8(cpustate,ea); + dst = XOR8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } +} + +static void I386OP(xor_r8_rm8)(i386_state *cpustate) /* Opcode 0x32 */ +{ + UINT32 src, dst; + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + dst = LOAD_REG8(modrm); + dst = XOR8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + dst = LOAD_REG8(modrm); + dst = XOR8(cpustate,dst, src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_MEM_REG); + } +} + +static void I386OP(xor_al_i8)(i386_state *cpustate) /* Opcode 0x34 */ +{ + UINT8 src, dst; + src = FETCH(cpustate); + dst = REG8(AL); + dst = XOR8(cpustate,dst, src); + REG8(AL) = dst; + CYCLES(cpustate,CYCLES_ALU_IMM_ACC); +} + + + +static void I386OP(group80_8)(i386_state *cpustate) /* Opcode 0x80 */ +{ + UINT32 ea; + UINT8 src, dst; + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* ADD Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = ADD8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = ADD8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 1: /* OR Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = OR8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = OR8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 2: /* ADC Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = ADC8(cpustate, dst, src, cpustate->CF); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = ADC8(cpustate, dst, src, cpustate->CF); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 3: /* SBB Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = SBB8(cpustate, dst, src, cpustate->CF); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = SBB8(cpustate, dst, src, cpustate->CF); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 4: /* AND Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = AND8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = AND8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 5: /* SUB Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = SUB8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = SUB8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 6: /* XOR Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + dst = XOR8(cpustate,dst, src); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_ALU_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + dst = XOR8(cpustate,dst, src); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_ALU_REG_MEM); + } + break; + case 7: /* CMP Rm8, i8 */ + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + src = FETCH(cpustate); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_REG); + } else { + ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + src = FETCH(cpustate); + SUB8(cpustate,dst, src); + CYCLES(cpustate,CYCLES_CMP_REG_MEM); + } + break; + } +} + +static void I386OP(groupC0_8)(i386_state *cpustate) /* Opcode 0xc0 */ +{ + UINT8 dst; + UINT8 modrm = FETCH(cpustate); + UINT8 shift; + + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate8(cpustate, modrm, dst, shift); + STORE_RM8(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + shift = FETCH(cpustate) & 0x1f; + dst = i386_shift_rotate8(cpustate, modrm, dst, shift); + WRITE8(cpustate,ea, dst); + } +} + +static void I386OP(groupD0_8)(i386_state *cpustate) /* Opcode 0xd0 */ +{ + UINT8 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + dst = i386_shift_rotate8(cpustate, modrm, dst, 1); + STORE_RM8(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + dst = i386_shift_rotate8(cpustate, modrm, dst, 1); + WRITE8(cpustate,ea, dst); + } +} + +static void I386OP(groupD2_8)(i386_state *cpustate) /* Opcode 0xd2 */ +{ + UINT8 dst; + UINT8 modrm = FETCH(cpustate); + + if( modrm >= 0xc0 ) { + dst = LOAD_RM8(modrm); + dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL)); + STORE_RM8(modrm, dst); + } else { + UINT32 ea = GetEA(cpustate,modrm); + dst = READ8(cpustate,ea); + dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL)); + WRITE8(cpustate,ea, dst); + } +} + +static void I386OP(groupF6_8)(i386_state *cpustate) /* Opcode 0xf6 */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* TEST Rm8, i8 */ + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + UINT8 src = FETCH(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF8(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + UINT8 src = FETCH(cpustate); + dst &= src; + cpustate->CF = cpustate->OF = cpustate->AF = 0; + SetSZPF8(dst); + CYCLES(cpustate,CYCLES_TEST_IMM_MEM); + } + break; + case 2: /* NOT Rm8 */ + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + dst = ~dst; + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_NOT_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + dst = ~dst; + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NOT_MEM); + } + break; + case 3: /* NEG Rm8 */ + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + dst = SUB8(cpustate, 0, dst ); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_NEG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + dst = SUB8(cpustate, 0, dst ); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_NEG_MEM); + } + break; + case 4: /* MUL AL, Rm8 */ + { + UINT16 result; + UINT8 src, dst; + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = REG8(AL); + result = (UINT16)src * (UINT16)dst; + REG16(AX) = (UINT16)result; + + cpustate->CF = cpustate->OF = (REG16(AX) > 0xff); + } + break; + case 5: /* IMUL AL, Rm8 */ + { + INT16 result; + INT16 src, dst; + if( modrm >= 0xc0 ) { + src = (INT16)(INT8)LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */ + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = (INT16)(INT8)READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */ + } + + dst = (INT16)(INT8)REG8(AL); + result = src * dst; + + REG16(AX) = (UINT16)result; + + cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result); + } + break; + case 6: /* DIV AL, Rm8 */ + { + UINT16 quotient, remainder, result; + UINT8 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_DIV8_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_DIV8_ACC_MEM); + } + + quotient = (UINT16)REG16(AX); + if( src ) { + remainder = quotient % (UINT16)src; + result = quotient / (UINT16)src; + if( result > 0xff ) { + /* TODO: Divide error */ + } else { + REG8(AH) = (UINT8)remainder & 0xff; + REG8(AL) = (UINT8)result & 0xff; + + /* this flag is actually undefined, enable on non-cyrix */ + if (cpustate->cpuid_id0 != 0x69727943) + cpustate->CF = 1; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + case 7: /* IDIV AL, Rm8 */ + { + INT16 quotient, remainder, result; + UINT8 src; + if( modrm >= 0xc0 ) { + src = LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_IDIV8_ACC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + src = READ8(cpustate,ea); + CYCLES(cpustate,CYCLES_IDIV8_ACC_MEM); + } + + quotient = (INT16)REG16(AX); + if( src ) { + remainder = quotient % (INT16)(INT8)src; + result = quotient / (INT16)(INT8)src; + if( result > 0xff ) { + /* TODO: Divide error */ + } else { + REG8(AH) = (UINT8)remainder & 0xff; + REG8(AL) = (UINT8)result & 0xff; + + /* this flag is actually undefined, enable on non-cyrix */ + if (cpustate->cpuid_id0 != 0x69727943) + cpustate->CF = 1; + } + } else { + /* TODO: Divide by zero */ + } + } + break; + } +} + +static void I386OP(groupFE_8)(i386_state *cpustate) /* Opcode 0xfe */ +{ + UINT8 modrm = FETCH(cpustate); + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* INC Rm8 */ + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + dst = INC8(cpustate,dst); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_INC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + dst = INC8(cpustate,dst); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_INC_MEM); + } + break; + case 1: /* DEC Rm8 */ + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + dst = DEC8(cpustate,dst); + STORE_RM8(modrm, dst); + CYCLES(cpustate,CYCLES_DEC_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + dst = DEC8(cpustate,dst); + WRITE8(cpustate,ea, dst); + CYCLES(cpustate,CYCLES_DEC_MEM); + } + break; + case 6: /* PUSH Rm8 */ + { + UINT8 value; + if( modrm >= 0xc0 ) { + value = LOAD_RM8(modrm); + } else { + UINT32 ea = GetEA(cpustate,modrm); + value = READ8(cpustate,ea); + } + if( cpustate->operand_size ) { + PUSH32(cpustate,value); + } else { + PUSH16(cpustate,value); + } + CYCLES(cpustate,CYCLES_PUSH_RM); + } + break; + default: + i386_fatal("i386: groupFE_8 /%d unimplemented", (modrm >> 3) & 0x7); + break; + } +} + + + +static void I386OP(segment_CS)(i386_state *cpustate) /* Opcode 0x2e */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = CS; + + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(segment_DS)(i386_state *cpustate) /* Opcode 0x3e */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = DS; + CYCLES(cpustate,0); /* TODO: Specify cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(segment_ES)(i386_state *cpustate) /* Opcode 0x26 */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = ES; + CYCLES(cpustate,0); /* TODO: Specify cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(segment_FS)(i386_state *cpustate) /* Opcode 0x64 */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = FS; + CYCLES(cpustate,1); /* TODO: Specify cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(segment_GS)(i386_state *cpustate) /* Opcode 0x65 */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = GS; + CYCLES(cpustate,1); /* TODO: Specify cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(segment_SS)(i386_state *cpustate) /* Opcode 0x36 */ +{ + cpustate->segment_prefix = 1; + cpustate->segment_override = SS; + CYCLES(cpustate,0); /* TODO: Specify cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(operand_size)(i386_state *cpustate) /* Opcode 0x66 */ +{ + cpustate->operand_size ^= 1; + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(address_size)(i386_state *cpustate) /* Opcode 0x67 */ +{ + cpustate->address_size ^= 1; + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(nop)(i386_state *cpustate) /* Opcode 0x90 */ +{ + CYCLES(cpustate,CYCLES_NOP); +} + +static void I386OP(int3)(i386_state *cpustate) /* Opcode 0xcc */ +{ + CYCLES(cpustate,CYCLES_INT3); + i386_trap(cpustate,3, 1); +} + +static void I386OP(int)(i386_state *cpustate) /* Opcode 0xcd */ +{ + int interrupt = FETCH(cpustate); + CYCLES(cpustate,CYCLES_INT); + i386_trap(cpustate,interrupt, 1); +} + +static void I386OP(into)(i386_state *cpustate) /* Opcode 0xce */ +{ + if( cpustate->OF ) { + i386_trap(cpustate,4, 1); + CYCLES(cpustate,CYCLES_INTO_OF1); + } + else + { + CYCLES(cpustate,CYCLES_INTO_OF0); + } +} + +static void I386OP(escape)(i386_state *cpustate) /* Opcodes 0xd8 - 0xdf */ +{ + UINT8 modrm = FETCH(cpustate); + if(modrm < 0xc0) + { + /* the effective address, for its side effects (the segment) */ + (void) GetEA(cpustate,modrm); + } + CYCLES(cpustate,3); /* TODO: confirm this */ + (void) LOAD_RM8(modrm); +} + +static void I386OP(hlt)(i386_state *cpustate) /* Opcode 0xf4 */ +{ + /* TODO: We need to raise an exception in protected mode and when */ + /* the current privilege level is not zero */ + cpustate->halted = 1; + CYCLES(cpustate,CYCLES_HLT); + if (i386_ICount > 0) + i386_ICount = 0; +} + +static void I386OP(decimal_adjust)(i386_state *cpustate, int direction) +{ + UINT8 tmpAL = REG8(AL); + UINT8 tmpCF = cpustate->CF; + + if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) + { + UINT16 t= (UINT16)REG8(AL) + (direction * 0x06); + REG8(AL) = (UINT8)t&0xff; + cpustate->AF = 1; + if (t & 0x100) + cpustate->CF = 1; + if (direction > 0) + tmpAL = REG8(AL); + } + + if (tmpCF || (tmpAL > 0x99)) + { + REG8(AL) += (direction * 0x60); + cpustate->CF = 1; + } + + SetSZPF8(REG8(AL)); +} + +static void I386OP(daa)(i386_state *cpustate) /* Opcode 0x27 */ +{ + I386OP(decimal_adjust)(cpustate, +1); + CYCLES(cpustate,CYCLES_DAA); +} + +static void I386OP(das)(i386_state *cpustate) /* Opcode 0x2f */ +{ + I386OP(decimal_adjust)(cpustate, -1); + CYCLES(cpustate,CYCLES_DAS); +} + +static void I386OP(aaa)(i386_state *cpustate) /* Opcode 0x37 */ +{ + if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) { + REG16(AX) = REG16(AX) + 6; + REG8(AH) = REG8(AH) + 1; + cpustate->AF = 1; + cpustate->CF = 1; + } else { + cpustate->AF = 0; + cpustate->CF = 0; + } + REG8(AL) = REG8(AL) & 0x0f; + CYCLES(cpustate,CYCLES_AAA); +} + +static void I386OP(aas)(i386_state *cpustate) /* Opcode 0x3f */ +{ + if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) + { + REG16(AX) -= 6; + REG8(AH) -= 1; + cpustate->AF = 1; + cpustate->CF = 1; + } + else + { + cpustate->AF = 0; + cpustate->CF = 0; + } + REG8(AL) &= 0x0f; + CYCLES(cpustate,CYCLES_AAS); +} + +static void I386OP(aad)(i386_state *cpustate) /* Opcode 0xd5 */ +{ + UINT8 tempAL = REG8(AL); + UINT8 tempAH = REG8(AH); + UINT8 i = FETCH(cpustate); + + REG8(AL) = (tempAL + (tempAH * i)) & 0xff; + REG8(AH) = 0; + SetSZPF8( REG8(AL) ); + CYCLES(cpustate,CYCLES_AAD); +} + +static void I386OP(aam)(i386_state *cpustate) /* Opcode 0xd4 */ +{ + UINT8 tempAL = REG8(AL); + UINT8 i = FETCH(cpustate); + + REG8(AH) = tempAL / i; + REG8(AL) = tempAL % i; + SetSZPF8( REG8(AL) ); + CYCLES(cpustate,CYCLES_AAM); +} + +static void I386OP(clts)(i386_state *cpustate) /* Opcode 0x0f 0x06 */ +{ + /* TODO: #GP(0) is executed */ + cpustate->cr[0] &= ~0x08; /* clear TS bit */ + CYCLES(cpustate,CYCLES_CLTS); +} + +static void I386OP(wait)(i386_state *cpustate) /* Opcode 0x9B */ +{ + /* TODO */ +} + +static void I386OP(lock)(i386_state *cpustate) /* Opcode 0xf0 */ +{ + CYCLES(cpustate,CYCLES_LOCK); /* TODO: Determine correct cycle count */ + I386OP(decode_opcode)(cpustate); +} + +static void I386OP(mov_r32_tr)(i386_state *cpustate) /* Opcode 0x0f 24 */ +{ + FETCH(cpustate); + CYCLES(cpustate,1); /* TODO: correct cycle count */ +} + +static void I386OP(mov_tr_r32)(i386_state *cpustate) /* Opcode 0x0f 26 */ +{ + FETCH(cpustate); + CYCLES(cpustate,1); /* TODO: correct cycle count */ +} + +static void I386OP(unimplemented)(i386_state *cpustate) +{ + i386_fatal("i386: Unimplemented opcode %02X at %08X", cpustate->opcode, cpustate->pc - 1 ); +} + +static void I386OP(invalid)(i386_state *cpustate) +{ + logerror("i386: Invalid opcode %02X at %08X\n", cpustate->opcode, cpustate->pc - 1); + i386_trap(cpustate, 6, 0); +} diff --git a/src/cpu/i386/i386ops.h b/src/cpu/i386/i386ops.h new file mode 100644 index 00000000..4338f7b5 --- /dev/null +++ b/src/cpu/i386/i386ops.h @@ -0,0 +1,377 @@ +typedef struct { + UINT8 opcode; + UINT32 flags; + void (*handler16)(i386_state *cpustate); + void (*handler32)(i386_state *cpustate); +} X86_OPCODE; + +#define OP_I386 0x1 +#define OP_FPU 0x2 +#define OP_I486 0x4 +#define OP_PENTIUM 0x8 +#define OP_MMX 0x10 +#define OP_PPRO 0x20 +#define OP_SSE 0x40 +#define OP_SSE2 0x80 +#define OP_SSE3 0x100 +#define OP_CYRIX 0x8000 +#define OP_2BYTE 0x80000000 + +static const X86_OPCODE x86_opcode_table[] = +{ +/* Opcode Flags 16-bit handler 32-bit handler */ + { 0x00, OP_I386, I386OP(add_rm8_r8), I386OP(add_rm8_r8), }, + { 0x01, OP_I386, I386OP(add_rm16_r16), I386OP(add_rm32_r32), }, + { 0x02, OP_I386, I386OP(add_r8_rm8), I386OP(add_r8_rm8), }, + { 0x03, OP_I386, I386OP(add_r16_rm16), I386OP(add_r32_rm32), }, + { 0x04, OP_I386, I386OP(add_al_i8), I386OP(add_al_i8), }, + { 0x05, OP_I386, I386OP(add_ax_i16), I386OP(add_eax_i32), }, + { 0x06, OP_I386, I386OP(push_es16), I386OP(push_es32), }, + { 0x07, OP_I386, I386OP(pop_es16), I386OP(pop_es32), }, + { 0x08, OP_I386, I386OP(or_rm8_r8), I386OP(or_rm8_r8), }, + { 0x09, OP_I386, I386OP(or_rm16_r16), I386OP(or_rm32_r32), }, + { 0x0A, OP_I386, I386OP(or_r8_rm8), I386OP(or_r8_rm8), }, + { 0x0B, OP_I386, I386OP(or_r16_rm16), I386OP(or_r32_rm32), }, + { 0x0C, OP_I386, I386OP(or_al_i8), I386OP(or_al_i8), }, + { 0x0D, OP_I386, I386OP(or_ax_i16), I386OP(or_eax_i32), }, + { 0x0E, OP_I386, I386OP(push_cs16), I386OP(push_cs32), }, + { 0x0F, OP_I386, I386OP(decode_two_byte), I386OP(decode_two_byte), }, + { 0x10, OP_I386, I386OP(adc_rm8_r8), I386OP(adc_rm8_r8), }, + { 0x11, OP_I386, I386OP(adc_rm16_r16), I386OP(adc_rm32_r32), }, + { 0x12, OP_I386, I386OP(adc_r8_rm8), I386OP(adc_r8_rm8), }, + { 0x13, OP_I386, I386OP(adc_r16_rm16), I386OP(adc_r32_rm32), }, + { 0x14, OP_I386, I386OP(adc_al_i8), I386OP(adc_al_i8), }, + { 0x15, OP_I386, I386OP(adc_ax_i16), I386OP(adc_eax_i32), }, + { 0x16, OP_I386, I386OP(push_ss16), I386OP(push_ss32), }, + { 0x17, OP_I386, I386OP(pop_ss16), I386OP(pop_ss32), }, + { 0x18, OP_I386, I386OP(sbb_rm8_r8), I386OP(sbb_rm8_r8), }, + { 0x19, OP_I386, I386OP(sbb_rm16_r16), I386OP(sbb_rm32_r32), }, + { 0x1A, OP_I386, I386OP(sbb_r8_rm8), I386OP(sbb_r8_rm8), }, + { 0x1B, OP_I386, I386OP(sbb_r16_rm16), I386OP(sbb_r32_rm32), }, + { 0x1C, OP_I386, I386OP(sbb_al_i8), I386OP(sbb_al_i8), }, + { 0x1D, OP_I386, I386OP(sbb_ax_i16), I386OP(sbb_eax_i32), }, + { 0x1E, OP_I386, I386OP(push_ds16), I386OP(push_ds32), }, + { 0x1F, OP_I386, I386OP(pop_ds16), I386OP(pop_ds32), }, + { 0x20, OP_I386, I386OP(and_rm8_r8), I386OP(and_rm8_r8), }, + { 0x21, OP_I386, I386OP(and_rm16_r16), I386OP(and_rm32_r32), }, + { 0x22, OP_I386, I386OP(and_r8_rm8), I386OP(and_r8_rm8), }, + { 0x23, OP_I386, I386OP(and_r16_rm16), I386OP(and_r32_rm32), }, + { 0x24, OP_I386, I386OP(and_al_i8), I386OP(and_al_i8), }, + { 0x25, OP_I386, I386OP(and_ax_i16), I386OP(and_eax_i32), }, + { 0x26, OP_I386, I386OP(segment_ES), I386OP(segment_ES), }, + { 0x27, OP_I386, I386OP(daa), I386OP(daa), }, + { 0x28, OP_I386, I386OP(sub_rm8_r8), I386OP(sub_rm8_r8), }, + { 0x29, OP_I386, I386OP(sub_rm16_r16), I386OP(sub_rm32_r32), }, + { 0x2A, OP_I386, I386OP(sub_r8_rm8), I386OP(sub_r8_rm8), }, + { 0x2B, OP_I386, I386OP(sub_r16_rm16), I386OP(sub_r32_rm32), }, + { 0x2C, OP_I386, I386OP(sub_al_i8), I386OP(sub_al_i8), }, + { 0x2D, OP_I386, I386OP(sub_ax_i16), I386OP(sub_eax_i32), }, + { 0x2E, OP_I386, I386OP(segment_CS), I386OP(segment_CS), }, + { 0x2F, OP_I386, I386OP(das), I386OP(das), }, + { 0x30, OP_I386, I386OP(xor_rm8_r8), I386OP(xor_rm8_r8), }, + { 0x31, OP_I386, I386OP(xor_rm16_r16), I386OP(xor_rm32_r32), }, + { 0x32, OP_I386, I386OP(xor_r8_rm8), I386OP(xor_r8_rm8), }, + { 0x33, OP_I386, I386OP(xor_r16_rm16), I386OP(xor_r32_rm32), }, + { 0x34, OP_I386, I386OP(xor_al_i8), I386OP(xor_al_i8), }, + { 0x35, OP_I386, I386OP(xor_ax_i16), I386OP(xor_eax_i32), }, + { 0x36, OP_I386, I386OP(segment_SS), I386OP(segment_SS), }, + { 0x37, OP_I386, I386OP(aaa), I386OP(aaa), }, + { 0x38, OP_I386, I386OP(cmp_rm8_r8), I386OP(cmp_rm8_r8), }, + { 0x39, OP_I386, I386OP(cmp_rm16_r16), I386OP(cmp_rm32_r32), }, + { 0x3A, OP_I386, I386OP(cmp_r8_rm8), I386OP(cmp_r8_rm8), }, + { 0x3B, OP_I386, I386OP(cmp_r16_rm16), I386OP(cmp_r32_rm32), }, + { 0x3C, OP_I386, I386OP(cmp_al_i8), I386OP(cmp_al_i8), }, + { 0x3D, OP_I386, I386OP(cmp_ax_i16), I386OP(cmp_eax_i32), }, + { 0x3E, OP_I386, I386OP(segment_DS), I386OP(segment_DS), }, + { 0x3F, OP_I386, I386OP(aas), I386OP(aas), }, + { 0x40, OP_I386, I386OP(inc_ax), I386OP(inc_eax), }, + { 0x41, OP_I386, I386OP(inc_cx), I386OP(inc_ecx), }, + { 0x42, OP_I386, I386OP(inc_dx), I386OP(inc_edx), }, + { 0x43, OP_I386, I386OP(inc_bx), I386OP(inc_ebx), }, + { 0x44, OP_I386, I386OP(inc_sp), I386OP(inc_esp), }, + { 0x45, OP_I386, I386OP(inc_bp), I386OP(inc_ebp), }, + { 0x46, OP_I386, I386OP(inc_si), I386OP(inc_esi), }, + { 0x47, OP_I386, I386OP(inc_di), I386OP(inc_edi), }, + { 0x48, OP_I386, I386OP(dec_ax), I386OP(dec_eax), }, + { 0x49, OP_I386, I386OP(dec_cx), I386OP(dec_ecx), }, + { 0x4A, OP_I386, I386OP(dec_dx), I386OP(dec_edx), }, + { 0x4B, OP_I386, I386OP(dec_bx), I386OP(dec_ebx), }, + { 0x4C, OP_I386, I386OP(dec_sp), I386OP(dec_esp), }, + { 0x4D, OP_I386, I386OP(dec_bp), I386OP(dec_ebp), }, + { 0x4E, OP_I386, I386OP(dec_si), I386OP(dec_esi), }, + { 0x4F, OP_I386, I386OP(dec_di), I386OP(dec_edi), }, + { 0x50, OP_I386, I386OP(push_ax), I386OP(push_eax), }, + { 0x51, OP_I386, I386OP(push_cx), I386OP(push_ecx), }, + { 0x52, OP_I386, I386OP(push_dx), I386OP(push_edx), }, + { 0x53, OP_I386, I386OP(push_bx), I386OP(push_ebx), }, + { 0x54, OP_I386, I386OP(push_sp), I386OP(push_esp), }, + { 0x55, OP_I386, I386OP(push_bp), I386OP(push_ebp), }, + { 0x56, OP_I386, I386OP(push_si), I386OP(push_esi), }, + { 0x57, OP_I386, I386OP(push_di), I386OP(push_edi), }, + { 0x58, OP_I386, I386OP(pop_ax), I386OP(pop_eax), }, + { 0x59, OP_I386, I386OP(pop_cx), I386OP(pop_ecx), }, + { 0x5A, OP_I386, I386OP(pop_dx), I386OP(pop_edx), }, + { 0x5B, OP_I386, I386OP(pop_bx), I386OP(pop_ebx), }, + { 0x5C, OP_I386, I386OP(pop_sp), I386OP(pop_esp), }, + { 0x5D, OP_I386, I386OP(pop_bp), I386OP(pop_ebp), }, + { 0x5E, OP_I386, I386OP(pop_si), I386OP(pop_esi), }, + { 0x5F, OP_I386, I386OP(pop_di), I386OP(pop_edi), }, + { 0x60, OP_I386, I386OP(pusha), I386OP(pushad), }, + { 0x61, OP_I386, I386OP(popa), I386OP(popad), }, + { 0x62, OP_I386, I386OP(bound_r16_m16_m16), I386OP(bound_r32_m32_m32), }, + { 0x63, OP_I386, I386OP(arpl), I386OP(arpl), }, + { 0x64, OP_I386, I386OP(segment_FS), I386OP(segment_FS), }, + { 0x65, OP_I386, I386OP(segment_GS), I386OP(segment_GS), }, + { 0x66, OP_I386, I386OP(operand_size), I386OP(operand_size), }, + { 0x67, OP_I386, I386OP(address_size), I386OP(address_size), }, + { 0x68, OP_I386, I386OP(push_i16), I386OP(push_i32), }, + { 0x69, OP_I386, I386OP(imul_r16_rm16_i16), I386OP(imul_r32_rm32_i32), }, + { 0x6A, OP_I386, I386OP(push_i8), I386OP(push_i8), }, + { 0x6B, OP_I386, I386OP(imul_r16_rm16_i8), I386OP(imul_r32_rm32_i8), }, + { 0x6C, OP_I386, I386OP(insb), I386OP(insb), }, + { 0x6D, OP_I386, I386OP(insw), I386OP(insd), }, + { 0x6E, OP_I386, I386OP(outsb), I386OP(outsb), }, + { 0x6F, OP_I386, I386OP(outsw), I386OP(outsd), }, + { 0x70, OP_I386, I386OP(jo_rel8), I386OP(jo_rel8), }, + { 0x71, OP_I386, I386OP(jno_rel8), I386OP(jno_rel8), }, + { 0x72, OP_I386, I386OP(jc_rel8), I386OP(jc_rel8), }, + { 0x73, OP_I386, I386OP(jnc_rel8), I386OP(jnc_rel8), }, + { 0x74, OP_I386, I386OP(jz_rel8), I386OP(jz_rel8), }, + { 0x75, OP_I386, I386OP(jnz_rel8), I386OP(jnz_rel8), }, + { 0x76, OP_I386, I386OP(jbe_rel8), I386OP(jbe_rel8), }, + { 0x77, OP_I386, I386OP(ja_rel8), I386OP(ja_rel8), }, + { 0x78, OP_I386, I386OP(js_rel8), I386OP(js_rel8), }, + { 0x79, OP_I386, I386OP(jns_rel8), I386OP(jns_rel8), }, + { 0x7A, OP_I386, I386OP(jp_rel8), I386OP(jp_rel8), }, + { 0x7B, OP_I386, I386OP(jnp_rel8), I386OP(jnp_rel8), }, + { 0x7C, OP_I386, I386OP(jl_rel8), I386OP(jl_rel8), }, + { 0x7D, OP_I386, I386OP(jge_rel8), I386OP(jge_rel8), }, + { 0x7E, OP_I386, I386OP(jle_rel8), I386OP(jle_rel8), }, + { 0x7F, OP_I386, I386OP(jg_rel8), I386OP(jg_rel8), }, + { 0x80, OP_I386, I386OP(group80_8), I386OP(group80_8), }, + { 0x81, OP_I386, I386OP(group81_16), I386OP(group81_32), }, + { 0x82, OP_I386, I386OP(group80_8), I386OP(group80_8), }, + { 0x83, OP_I386, I386OP(group83_16), I386OP(group83_32), }, + { 0x84, OP_I386, I386OP(test_rm8_r8), I386OP(test_rm8_r8), }, + { 0x85, OP_I386, I386OP(test_rm16_r16), I386OP(test_rm32_r32), }, + { 0x86, OP_I386, I386OP(xchg_r8_rm8), I386OP(xchg_r8_rm8), }, + { 0x87, OP_I386, I386OP(xchg_r16_rm16), I386OP(xchg_r32_rm32), }, + { 0x88, OP_I386, I386OP(mov_rm8_r8), I386OP(mov_rm8_r8), }, + { 0x89, OP_I386, I386OP(mov_rm16_r16), I386OP(mov_rm32_r32), }, + { 0x8A, OP_I386, I386OP(mov_r8_rm8), I386OP(mov_r8_rm8), }, + { 0x8B, OP_I386, I386OP(mov_r16_rm16), I386OP(mov_r32_rm32), }, + { 0x8C, OP_I386, I386OP(mov_rm16_sreg), I386OP(mov_rm16_sreg), }, + { 0x8D, OP_I386, I386OP(lea16), I386OP(lea32), }, + { 0x8E, OP_I386, I386OP(mov_sreg_rm16), I386OP(mov_sreg_rm16), }, + { 0x8F, OP_I386, I386OP(pop_rm16), I386OP(pop_rm32), }, + { 0x90, OP_I386, I386OP(nop), I386OP(nop), }, + { 0x91, OP_I386, I386OP(xchg_ax_cx), I386OP(xchg_eax_ecx), }, + { 0x92, OP_I386, I386OP(xchg_ax_dx), I386OP(xchg_eax_edx), }, + { 0x93, OP_I386, I386OP(xchg_ax_bx), I386OP(xchg_eax_ebx), }, + { 0x94, OP_I386, I386OP(xchg_ax_sp), I386OP(xchg_eax_esp), }, + { 0x95, OP_I386, I386OP(xchg_ax_bp), I386OP(xchg_eax_ebp), }, + { 0x96, OP_I386, I386OP(xchg_ax_si), I386OP(xchg_eax_esi), }, + { 0x97, OP_I386, I386OP(xchg_ax_di), I386OP(xchg_eax_edi), }, + { 0x98, OP_I386, I386OP(cbw), I386OP(cwde), }, + { 0x99, OP_I386, I386OP(cwd), I386OP(cdq), }, + { 0x9A, OP_I386, I386OP(call_abs16), I386OP(call_abs32), }, + { 0x9B, OP_I386, I386OP(wait), I386OP(wait), }, + { 0x9C, OP_I386, I386OP(pushf), I386OP(pushfd), }, + { 0x9D, OP_I386, I386OP(popf), I386OP(popfd), }, + { 0x9E, OP_I386, I386OP(sahf), I386OP(sahf), }, + { 0x9F, OP_I386, I386OP(lahf), I386OP(lahf), }, + { 0xA0, OP_I386, I386OP(mov_al_m8), I386OP(mov_al_m8), }, + { 0xA1, OP_I386, I386OP(mov_ax_m16), I386OP(mov_eax_m32), }, + { 0xA2, OP_I386, I386OP(mov_m8_al), I386OP(mov_m8_al), }, + { 0xA3, OP_I386, I386OP(mov_m16_ax), I386OP(mov_m32_eax), }, + { 0xA4, OP_I386, I386OP(movsb), I386OP(movsb), }, + { 0xA5, OP_I386, I386OP(movsw), I386OP(movsd), }, + { 0xA6, OP_I386, I386OP(cmpsb), I386OP(cmpsb), }, + { 0xA7, OP_I386, I386OP(cmpsw), I386OP(cmpsd), }, + { 0xA8, OP_I386, I386OP(test_al_i8), I386OP(test_al_i8), }, + { 0xA9, OP_I386, I386OP(test_ax_i16), I386OP(test_eax_i32), }, + { 0xAA, OP_I386, I386OP(stosb), I386OP(stosb), }, + { 0xAB, OP_I386, I386OP(stosw), I386OP(stosd), }, + { 0xAC, OP_I386, I386OP(lodsb), I386OP(lodsb), }, + { 0xAD, OP_I386, I386OP(lodsw), I386OP(lodsd), }, + { 0xAE, OP_I386, I386OP(scasb), I386OP(scasb), }, + { 0xAF, OP_I386, I386OP(scasw), I386OP(scasd), }, + { 0xB0, OP_I386, I386OP(mov_al_i8), I386OP(mov_al_i8), }, + { 0xB1, OP_I386, I386OP(mov_cl_i8), I386OP(mov_cl_i8), }, + { 0xB2, OP_I386, I386OP(mov_dl_i8), I386OP(mov_dl_i8), }, + { 0xB3, OP_I386, I386OP(mov_bl_i8), I386OP(mov_bl_i8), }, + { 0xB4, OP_I386, I386OP(mov_ah_i8), I386OP(mov_ah_i8), }, + { 0xB5, OP_I386, I386OP(mov_ch_i8), I386OP(mov_ch_i8), }, + { 0xB6, OP_I386, I386OP(mov_dh_i8), I386OP(mov_dh_i8), }, + { 0xB7, OP_I386, I386OP(mov_bh_i8), I386OP(mov_bh_i8), }, + { 0xB8, OP_I386, I386OP(mov_ax_i16), I386OP(mov_eax_i32), }, + { 0xB9, OP_I386, I386OP(mov_cx_i16), I386OP(mov_ecx_i32), }, + { 0xBA, OP_I386, I386OP(mov_dx_i16), I386OP(mov_edx_i32), }, + { 0xBB, OP_I386, I386OP(mov_bx_i16), I386OP(mov_ebx_i32), }, + { 0xBC, OP_I386, I386OP(mov_sp_i16), I386OP(mov_esp_i32), }, + { 0xBD, OP_I386, I386OP(mov_bp_i16), I386OP(mov_ebp_i32), }, + { 0xBE, OP_I386, I386OP(mov_si_i16), I386OP(mov_esi_i32), }, + { 0xBF, OP_I386, I386OP(mov_di_i16), I386OP(mov_edi_i32), }, + { 0xC0, OP_I386, I386OP(groupC0_8), I386OP(groupC0_8), }, + { 0xC1, OP_I386, I386OP(groupC1_16), I386OP(groupC1_32), }, + { 0xC2, OP_I386, I386OP(ret_near16_i16), I386OP(ret_near32_i16), }, + { 0xC3, OP_I386, I386OP(ret_near16), I386OP(ret_near32), }, + { 0xC4, OP_I386, I386OP(les16), I386OP(les32), }, + { 0xC5, OP_I386, I386OP(lds16), I386OP(lds32), }, + { 0xC6, OP_I386, I386OP(mov_rm8_i8), I386OP(mov_rm8_i8), }, + { 0xC7, OP_I386, I386OP(mov_rm16_i16), I386OP(mov_rm32_i32), }, + { 0xC8, OP_I386, I386OP(enter16), I386OP(enter32), }, + { 0xC9, OP_I386, I386OP(leave16), I386OP(leave32), }, + { 0xCA, OP_I386, I386OP(retf_i16), I386OP(retf_i32), }, + { 0xCB, OP_I386, I386OP(retf16), I386OP(retf32), }, + { 0xCC, OP_I386, I386OP(int3), I386OP(int3), }, + { 0xCD, OP_I386, I386OP(int), I386OP(int), }, + { 0xCE, OP_I386, I386OP(into), I386OP(into), }, + { 0xCF, OP_I386, I386OP(iret16), I386OP(iret32), }, + { 0xD0, OP_I386, I386OP(groupD0_8), I386OP(groupD0_8), }, + { 0xD1, OP_I386, I386OP(groupD1_16), I386OP(groupD1_32), }, + { 0xD2, OP_I386, I386OP(groupD2_8), I386OP(groupD2_8), }, + { 0xD3, OP_I386, I386OP(groupD3_16), I386OP(groupD3_32), }, + { 0xD4, OP_I386, I386OP(aam), I386OP(aam), }, + { 0xD5, OP_I386, I386OP(aad), I386OP(aad), }, + { 0xD6, OP_I386, I386OP(setalc), I386OP(setalc), }, + { 0xD7, OP_I386, I386OP(xlat16), I386OP(xlat32), }, + { 0xD8, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xD9, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDA, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDB, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDC, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDD, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDE, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xDF, OP_I386, I386OP(escape), I386OP(escape), }, + { 0xD8, OP_FPU, I386OP(fpu_group_d8), I386OP(fpu_group_d8), }, + { 0xD9, OP_FPU, I386OP(fpu_group_d9), I386OP(fpu_group_d9), }, + { 0xDA, OP_FPU, I386OP(fpu_group_da), I386OP(fpu_group_da), }, + { 0xDB, OP_FPU, I386OP(fpu_group_db), I386OP(fpu_group_db), }, + { 0xDC, OP_FPU, I386OP(fpu_group_dc), I386OP(fpu_group_dc), }, + { 0xDD, OP_FPU, I386OP(fpu_group_dd), I386OP(fpu_group_dd), }, + { 0xDE, OP_FPU, I386OP(fpu_group_de), I386OP(fpu_group_de), }, + { 0xDF, OP_FPU, I386OP(fpu_group_df), I386OP(fpu_group_df), }, + { 0xE0, OP_I386, I386OP(loopne16), I386OP(loopne32), }, + { 0xE1, OP_I386, I386OP(loopz16), I386OP(loopz32), }, + { 0xE2, OP_I386, I386OP(loop16), I386OP(loop32), }, + { 0xE3, OP_I386, I386OP(jcxz16), I386OP(jcxz32), }, + { 0xE4, OP_I386, I386OP(in_al_i8), I386OP(in_al_i8), }, + { 0xE5, OP_I386, I386OP(in_ax_i8), I386OP(in_eax_i8), }, + { 0xE6, OP_I386, I386OP(out_al_i8), I386OP(out_al_i8), }, + { 0xE7, OP_I386, I386OP(out_ax_i8), I386OP(out_eax_i8), }, + { 0xE8, OP_I386, I386OP(call_rel16), I386OP(call_rel32), }, + { 0xE9, OP_I386, I386OP(jmp_rel16), I386OP(jmp_rel32), }, + { 0xEA, OP_I386, I386OP(jmp_abs16), I386OP(jmp_abs32), }, + { 0xEB, OP_I386, I386OP(jmp_rel8), I386OP(jmp_rel8), }, + { 0xEC, OP_I386, I386OP(in_al_dx), I386OP(in_al_dx), }, + { 0xED, OP_I386, I386OP(in_ax_dx), I386OP(in_eax_dx), }, + { 0xEE, OP_I386, I386OP(out_al_dx), I386OP(out_al_dx), }, + { 0xEF, OP_I386, I386OP(out_ax_dx), I386OP(out_eax_dx), }, + { 0xF0, OP_I386, I386OP(lock), I386OP(lock), }, + { 0xF1, OP_I386, I386OP(invalid), I386OP(invalid), }, + { 0xF2, OP_I386, I386OP(repne), I386OP(repne), }, + { 0xF3, OP_I386, I386OP(rep), I386OP(rep), }, + { 0xF4, OP_I386, I386OP(hlt), I386OP(hlt), }, + { 0xF5, OP_I386, I386OP(cmc), I386OP(cmc), }, + { 0xF6, OP_I386, I386OP(groupF6_8), I386OP(groupF6_8), }, + { 0xF7, OP_I386, I386OP(groupF7_16), I386OP(groupF7_32), }, + { 0xF8, OP_I386, I386OP(clc), I386OP(clc), }, + { 0xF9, OP_I386, I386OP(stc), I386OP(stc), }, + { 0xFA, OP_I386, I386OP(cli), I386OP(cli), }, + { 0xFB, OP_I386, I386OP(sti), I386OP(sti), }, + { 0xFC, OP_I386, I386OP(cld), I386OP(cld), }, + { 0xFD, OP_I386, I386OP(std), I386OP(std), }, + { 0xFE, OP_I386, I386OP(groupFE_8), I386OP(groupFE_8), }, + { 0xFF, OP_I386, I386OP(groupFF_16), I386OP(groupFF_32), }, + { 0x00, OP_2BYTE|OP_I386, I386OP(group0F00_16), I386OP(group0F00_32), }, + { 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), }, + { 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), }, + { 0x02, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), }, + { 0x03, OP_2BYTE|OP_I386, I386OP(lsl_r16_rm16), I386OP(lsl_r32_rm32), }, + { 0x06, OP_2BYTE|OP_I386, I386OP(clts), I386OP(clts), }, + { 0x08, OP_2BYTE|OP_I486, I486OP(invd), I486OP(invd), }, + { 0x09, OP_2BYTE|OP_I486, I486OP(wbinvd), I486OP(wbinvd), }, + { 0x0B, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), }, + { 0x20, OP_2BYTE|OP_I386, I386OP(mov_r32_cr), I386OP(mov_r32_cr), }, + { 0x21, OP_2BYTE|OP_I386, I386OP(mov_r32_dr), I386OP(mov_r32_dr), }, + { 0x22, OP_2BYTE|OP_I386, I386OP(mov_cr_r32), I386OP(mov_cr_r32), }, + { 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), }, + { 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), }, + { 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), }, + { 0x30, OP_2BYTE|OP_PENTIUM, PENTIUMOP(wrmsr), PENTIUMOP(wrmsr), }, + { 0x31, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdtsc), PENTIUMOP(rdtsc), }, + { 0x32, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdmsr), PENTIUMOP(rdmsr), }, + { 0x74, OP_2BYTE|OP_CYRIX, I386OP(cyrix_unknown), I386OP(cyrix_unknown), }, + { 0x80, OP_2BYTE|OP_I386, I386OP(jo_rel16), I386OP(jo_rel32), }, + { 0x81, OP_2BYTE|OP_I386, I386OP(jno_rel16), I386OP(jno_rel32), }, + { 0x82, OP_2BYTE|OP_I386, I386OP(jc_rel16), I386OP(jc_rel32), }, + { 0x83, OP_2BYTE|OP_I386, I386OP(jnc_rel16), I386OP(jnc_rel32), }, + { 0x84, OP_2BYTE|OP_I386, I386OP(jz_rel16), I386OP(jz_rel32), }, + { 0x85, OP_2BYTE|OP_I386, I386OP(jnz_rel16), I386OP(jnz_rel32), }, + { 0x86, OP_2BYTE|OP_I386, I386OP(jbe_rel16), I386OP(jbe_rel32), }, + { 0x87, OP_2BYTE|OP_I386, I386OP(ja_rel16), I386OP(ja_rel32), }, + { 0x88, OP_2BYTE|OP_I386, I386OP(js_rel16), I386OP(js_rel32), }, + { 0x89, OP_2BYTE|OP_I386, I386OP(jns_rel16), I386OP(jns_rel32), }, + { 0x8A, OP_2BYTE|OP_I386, I386OP(jp_rel16), I386OP(jp_rel32), }, + { 0x8B, OP_2BYTE|OP_I386, I386OP(jnp_rel16), I386OP(jnp_rel32), }, + { 0x8C, OP_2BYTE|OP_I386, I386OP(jl_rel16), I386OP(jl_rel32), }, + { 0x8D, OP_2BYTE|OP_I386, I386OP(jge_rel16), I386OP(jge_rel32), }, + { 0x8E, OP_2BYTE|OP_I386, I386OP(jle_rel16), I386OP(jle_rel32), }, + { 0x8F, OP_2BYTE|OP_I386, I386OP(jg_rel16), I386OP(jg_rel32), }, + { 0x90, OP_2BYTE|OP_I386, I386OP(seto_rm8), I386OP(seto_rm8), }, + { 0x91, OP_2BYTE|OP_I386, I386OP(setno_rm8), I386OP(setno_rm8), }, + { 0x92, OP_2BYTE|OP_I386, I386OP(setc_rm8), I386OP(setc_rm8), }, + { 0x93, OP_2BYTE|OP_I386, I386OP(setnc_rm8), I386OP(setnc_rm8), }, + { 0x94, OP_2BYTE|OP_I386, I386OP(setz_rm8), I386OP(setz_rm8), }, + { 0x95, OP_2BYTE|OP_I386, I386OP(setnz_rm8), I386OP(setnz_rm8), }, + { 0x96, OP_2BYTE|OP_I386, I386OP(setbe_rm8), I386OP(setbe_rm8), }, + { 0x97, OP_2BYTE|OP_I386, I386OP(seta_rm8), I386OP(seta_rm8), }, + { 0x98, OP_2BYTE|OP_I386, I386OP(sets_rm8), I386OP(sets_rm8), }, + { 0x99, OP_2BYTE|OP_I386, I386OP(setns_rm8), I386OP(setns_rm8), }, + { 0x9A, OP_2BYTE|OP_I386, I386OP(setp_rm8), I386OP(setp_rm8), }, + { 0x9B, OP_2BYTE|OP_I386, I386OP(setnp_rm8), I386OP(setnp_rm8), }, + { 0x9C, OP_2BYTE|OP_I386, I386OP(setl_rm8), I386OP(setl_rm8), }, + { 0x9D, OP_2BYTE|OP_I386, I386OP(setge_rm8), I386OP(setge_rm8), }, + { 0x9E, OP_2BYTE|OP_I386, I386OP(setle_rm8), I386OP(setle_rm8), }, + { 0x9F, OP_2BYTE|OP_I386, I386OP(setg_rm8), I386OP(setg_rm8), }, + { 0xA0, OP_2BYTE|OP_I386, I386OP(push_fs16), I386OP(push_fs32), }, + { 0xA1, OP_2BYTE|OP_I386, I386OP(pop_fs16), I386OP(pop_fs32), }, + { 0xA2, OP_2BYTE|OP_I486, I486OP(cpuid), I486OP(cpuid), }, + { 0xA3, OP_2BYTE|OP_I386, I386OP(bt_rm16_r16), I386OP(bt_rm32_r32), }, + { 0xA4, OP_2BYTE|OP_I386, I386OP(shld16_i8), I386OP(shld32_i8), }, + { 0xA5, OP_2BYTE|OP_I386, I386OP(shld16_cl), I386OP(shld32_cl), }, + { 0xA8, OP_2BYTE|OP_I386, I386OP(push_gs16), I386OP(push_gs32), }, + { 0xA9, OP_2BYTE|OP_I386, I386OP(pop_gs16), I386OP(pop_gs32), }, + { 0xAA, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), }, + { 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), }, + { 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), }, + { 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), }, + { 0xAE, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(invalid), }, + { 0xAF, OP_2BYTE|OP_I386, I386OP(imul_r16_rm16), I386OP(imul_r32_rm32), }, + { 0xB0, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm8_r8), I486OP(cmpxchg_rm8_r8), }, + { 0xB1, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm16_r16), I486OP(cmpxchg_rm32_r32), }, + { 0xB2, OP_2BYTE|OP_I386, I386OP(lss16), I386OP(lss32), }, + { 0xB3, OP_2BYTE|OP_I386, I386OP(btr_rm16_r16), I386OP(btr_rm32_r32), }, + { 0xB4, OP_2BYTE|OP_I386, I386OP(lfs16), I386OP(lfs32), }, + { 0xB5, OP_2BYTE|OP_I386, I386OP(lgs16), I386OP(lgs32), }, + { 0xB6, OP_2BYTE|OP_I386, I386OP(movzx_r16_rm8), I386OP(movzx_r32_rm8), }, + { 0xB7, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movzx_r32_rm16), }, + { 0xBA, OP_2BYTE|OP_I386, I386OP(group0FBA_16), I386OP(group0FBA_32), }, + { 0xBB, OP_2BYTE|OP_I386, I386OP(btc_rm16_r16), I386OP(btc_rm32_r32), }, + { 0xBC, OP_2BYTE|OP_I386, I386OP(bsf_r16_rm16), I386OP(bsf_r32_rm32), }, + { 0xBD, OP_2BYTE|OP_I386, I386OP(bsr_r16_rm16), I386OP(bsr_r32_rm32), }, + { 0xBE, OP_2BYTE|OP_I386, I386OP(movsx_r16_rm8), I386OP(movsx_r32_rm8), }, + { 0xBF, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movsx_r32_rm16), }, + { 0xC0, OP_2BYTE|OP_I486, I486OP(xadd_rm8_r8), I486OP(xadd_rm8_r8), }, + { 0xC1, OP_2BYTE|OP_I486, I486OP(xadd_rm16_r16), I486OP(xadd_rm32_r32), }, + { 0xC7, OP_2BYTE|OP_PENTIUM, PENTIUMOP(cmpxchg8b_m64), PENTIUMOP(cmpxchg8b_m64), }, + { 0xC8, OP_2BYTE|OP_I486, I486OP(bswap_eax), I486OP(bswap_eax), }, + { 0xC9, OP_2BYTE|OP_I486, I486OP(bswap_ecx), I486OP(bswap_ecx), }, + { 0xCA, OP_2BYTE|OP_I486, I486OP(bswap_edx), I486OP(bswap_edx), }, + { 0xCB, OP_2BYTE|OP_I486, I486OP(bswap_ebx), I486OP(bswap_ebx), }, + { 0xCC, OP_2BYTE|OP_I486, I486OP(bswap_esp), I486OP(bswap_esp), }, + { 0xCD, OP_2BYTE|OP_I486, I486OP(bswap_ebp), I486OP(bswap_ebp), }, + { 0xCE, OP_2BYTE|OP_I486, I486OP(bswap_esi), I486OP(bswap_esi), }, + { 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), } +}; diff --git a/src/cpu/i386/i386priv.h b/src/cpu/i386/i386priv.h new file mode 100644 index 00000000..d34bd3b3 --- /dev/null +++ b/src/cpu/i386/i386priv.h @@ -0,0 +1,1094 @@ +#ifndef __I386_H__ +#define __I386_H__ + +#include "driver.h" +#include "i386.h" + +#ifdef MSB_FIRST +#define NATIVE_ENDIAN_VALUE_LE_BE(le,be) (be) +#else +#define NATIVE_ENDIAN_VALUE_LE_BE(le,be) (le) +#endif + +#define I386OP(XX) i386_##XX +#define I486OP(XX) i486_##XX +#define PENTIUMOP(XX) pentium_##XX +#define MMXOP(XX) mmx_##XX + + +typedef enum { ES, CS, SS, DS, FS, GS } SREGS; + +typedef enum +{ + AL = NATIVE_ENDIAN_VALUE_LE_BE(0,3), + AH = NATIVE_ENDIAN_VALUE_LE_BE(1,2), + CL = NATIVE_ENDIAN_VALUE_LE_BE(4,7), + CH = NATIVE_ENDIAN_VALUE_LE_BE(5,6), + DL = NATIVE_ENDIAN_VALUE_LE_BE(8,11), + DH = NATIVE_ENDIAN_VALUE_LE_BE(9,10), + BL = NATIVE_ENDIAN_VALUE_LE_BE(12,15), + BH = NATIVE_ENDIAN_VALUE_LE_BE(13,14) +} BREGS; + +typedef enum +{ + AX = NATIVE_ENDIAN_VALUE_LE_BE(0,1), + CX = NATIVE_ENDIAN_VALUE_LE_BE(2,3), + DX = NATIVE_ENDIAN_VALUE_LE_BE(4,5), + BX = NATIVE_ENDIAN_VALUE_LE_BE(6,7), + SP = NATIVE_ENDIAN_VALUE_LE_BE(8,9), + BP = NATIVE_ENDIAN_VALUE_LE_BE(10,11), + SI = NATIVE_ENDIAN_VALUE_LE_BE(12,13), + DI = NATIVE_ENDIAN_VALUE_LE_BE(14,15) +} WREGS; + +typedef enum { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI } DREGS; + +enum +{ + I386_PC = 0, + + /* 8-bit registers */ + I386_AL, + I386_AH, + I386_BL, + I386_BH, + I386_CL, + I386_CH, + I386_DL, + I386_DH, + + /* 16-bit registers */ + I386_AX, + I386_BX, + I386_CX, + I386_DX, + I386_BP, + I386_SP, + I386_SI, + I386_DI, + I386_IP, + + /* 32-bit registers */ + I386_EAX, + I386_ECX, + I386_EDX, + I386_EBX, + I386_EBP, + I386_ESP, + I386_ESI, + I386_EDI, + I386_EIP, + + /* segment registers */ + I386_CS, + I386_CS_BASE, + I386_CS_LIMIT, + I386_CS_FLAGS, + I386_SS, + I386_SS_BASE, + I386_SS_LIMIT, + I386_SS_FLAGS, + I386_DS, + I386_DS_BASE, + I386_DS_LIMIT, + I386_DS_FLAGS, + I386_ES, + I386_ES_BASE, + I386_ES_LIMIT, + I386_ES_FLAGS, + I386_FS, + I386_FS_BASE, + I386_FS_LIMIT, + I386_FS_FLAGS, + I386_GS, + I386_GS_BASE, + I386_GS_LIMIT, + I386_GS_FLAGS, + + /* other */ + I386_EFLAGS, + + I386_CR0, + I386_CR1, + I386_CR2, + I386_CR3, + I386_CR4, + + I386_DR0, + I386_DR1, + I386_DR2, + I386_DR3, + I386_DR4, + I386_DR5, + I386_DR6, + I386_DR7, + + I386_TR6, + I386_TR7, + + I386_GDTR_BASE, + I386_GDTR_LIMIT, + I386_IDTR_BASE, + I386_IDTR_LIMIT, + I386_TR, + I386_TR_BASE, + I386_TR_LIMIT, + I386_TR_FLAGS, + I386_LDTR, + I386_LDTR_BASE, + I386_LDTR_LIMIT, + I386_LDTR_FLAGS, + + X87_CTRL, + X87_STATUS, + X87_ST0, + X87_ST1, + X87_ST2, + X87_ST3, + X87_ST4, + X87_ST5, + X87_ST6, + X87_ST7, +}; + +typedef struct { + UINT16 selector; + UINT16 flags; + UINT32 base; + UINT32 limit; + int d; /* Operand size */ +} I386_SREG; + +typedef struct { + UINT32 base; + UINT16 limit; +} I386_SYS_TABLE; + +typedef struct { + UINT16 segment; + UINT16 flags; + UINT32 base; + UINT32 limit; +} I386_SEG_DESC; + +typedef union { + UINT32 d[8]; + UINT16 w[16]; + UINT8 b[32]; +} I386_GPR; + +typedef union { + UINT64 i; + double f; +} X87_REG; + +typedef struct _i386_state i386_state; +struct _i386_state +{ + I386_GPR reg; + I386_SREG sreg[6]; + UINT32 eip; + UINT32 pc; + UINT32 prev_eip; + UINT32 eflags; + UINT32 eflags_mask; + UINT8 CF; + UINT8 DF; + UINT8 SF; + UINT8 OF; + UINT8 ZF; + UINT8 PF; + UINT8 AF; + UINT8 IF; + UINT8 TF; + UINT8 IOP1; + UINT8 IOP2; + UINT8 NT; + + UINT8 performed_intersegment_jump; + + UINT32 cr[5]; /* Control registers */ + UINT32 dr[8]; /* Debug registers */ + UINT32 tr[8]; /* Test registers */ + + I386_SYS_TABLE gdtr; /* Global Descriptor Table Register */ + I386_SYS_TABLE idtr; /* Interrupt Descriptor Table Register */ + I386_SEG_DESC task; /* Task register */ + I386_SEG_DESC ldtr; /* Local Descriptor Table Register */ + + int halted; + + int operand_size; + int address_size; + + int segment_prefix; + int segment_override; + + int base_cycles; + UINT8 opcode; + + UINT8 irq_state; + int (*irq_callback)(int irqline); + UINT32 a20_mask; + + int cpuid_max_input_value_eax; + UINT32 cpuid_id0, cpuid_id1, cpuid_id2; + UINT32 cpu_version; + UINT32 feature_flags; + UINT64 tsc; + + /* the fast memory cache, by kind of access (not saved: rebuilt on a miss) */ + UINT32 fast_start[3], fast_size[3]; + UINT8 *fast_base[3]; + + /* FPU */ + X87_REG fpu_reg[8]; + UINT16 fpu_control_word; + UINT16 fpu_status_word; + UINT16 fpu_tag_word; + UINT64 fpu_data_ptr; + UINT64 fpu_inst_ptr; + UINT16 fpu_opcode; + int fpu_top; + + void (*opcode_table1_16[256])(i386_state *cpustate); + void (*opcode_table1_32[256])(i386_state *cpustate); + void (*opcode_table2_16[256])(i386_state *cpustate); + void (*opcode_table2_32[256])(i386_state *cpustate); + + UINT8 *cycle_table_pm; + UINT8 *cycle_table_rm; +}; + + +extern int i386_parity_table[256]; + +#define PROTECTED_MODE (cpustate->cr[0] & 0x1) +#define STACK_32BIT (cpustate->sreg[SS].d) +#define V8086_MODE (cpustate->eflags & 0x00020000) + +#define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0) +#define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0) +#define SetOF_Add8(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0) + +#define SetOF_Sub32(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0) +#define SetOF_Sub16(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0) +#define SetOF_Sub8(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0) + +#define SetCF8(x) {cpustate->CF = ((x) & 0x100) ? 1 : 0; } +#define SetCF16(x) {cpustate->CF = ((x) & 0x10000) ? 1 : 0; } +#define SetCF32(x) {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; } + +#define SetSF(x) (cpustate->SF = (x)) +#define SetZF(x) (cpustate->ZF = (x)) +#define SetAF(x,y,z) (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0) +#define SetPF(x) (cpustate->PF = i386_parity_table[(x) & 0xFF]) + +#define SetSZPF8(x) {cpustate->ZF = ((UINT8)(x)==0); cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } +#define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } +#define SetSZPF32(x) {cpustate->ZF = ((UINT32)(x)==0); cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } + +/***********************************************************************************/ + +typedef struct { + struct { + int b; + int w; + int d; + } reg; + struct { + int b; + int w; + int d; + } rm; +} MODRM_TABLE; + +extern MODRM_TABLE i386_MODRM_table[256]; + +#define REG8(x) (cpustate->reg.b[x]) +#define REG16(x) (cpustate->reg.w[x]) +#define REG32(x) (cpustate->reg.d[x]) + +#define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b)) +#define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w)) +#define LOAD_REG32(x) (REG32(i386_MODRM_table[x].reg.d)) +#define LOAD_RM8(x) (REG8(i386_MODRM_table[x].rm.b)) +#define LOAD_RM16(x) (REG16(i386_MODRM_table[x].rm.w)) +#define LOAD_RM32(x) (REG32(i386_MODRM_table[x].rm.d)) + +#define STORE_REG8(x, value) (REG8(i386_MODRM_table[x].reg.b) = value) +#define STORE_REG16(x, value) (REG16(i386_MODRM_table[x].reg.w) = value) +#define STORE_REG32(x, value) (REG32(i386_MODRM_table[x].reg.d) = value) +#define STORE_RM8(x, value) (REG8(i386_MODRM_table[x].rm.b) = value) +#define STORE_RM16(x, value) (REG16(i386_MODRM_table[x].rm.w) = value) +#define STORE_RM32(x, value) (REG32(i386_MODRM_table[x].rm.d) = value) + +#define SWITCH_ENDIAN_32(x) (((((x) << 24) & (0xff << 24)) | (((x) << 8) & (0xff << 16)) | (((x) >> 8) & (0xff << 8)) | (((x) >> 24) & (0xff << 0)))) + +/***********************************************************************************/ + +static INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip) +{ + /* TODO: segment limit */ + return cpustate->sreg[segment].base + ip; +} + +static INLINE int translate_address(i386_state *cpustate, UINT32 *address) +{ + UINT32 a = *address; + UINT32 pdbr = cpustate->cr[3] & 0xfffff000; + UINT32 directory = (a >> 22) & 0x3ff; + UINT32 table = (a >> 12) & 0x3ff; + UINT32 offset = a & 0xfff; + UINT32 page_entry; + + /* TODO: 4MB pages */ + UINT32 page_dir = cpu_readmem32ledw_dword(pdbr + directory * 4); + if (!(cpustate->cr[4] & 0x10)) { + page_entry = cpu_readmem32ledw_dword((page_dir & 0xfffff000) + (table * 4)); + *address = (page_entry & 0xfffff000) | offset; + } else { + if (page_dir & 0x80) + *address = (page_dir & 0xffc00000) | (a & 0x003fffff); + else { + page_entry = cpu_readmem32ledw_dword((page_dir & 0xfffff000) + (table * 4)); + *address = (page_entry & 0xfffff000) | offset; + } + } + return 1; +} + +/* the fast memory: plain RAM and ROM the driver registers with */ +/* i386_set_fastmem, fetched, read and written straight from the host */ +/* memory instead of through the memory handlers (little endian hosts). */ +/* A one-region cache for each kind of access; a miss looks the regions up */ +#define I386_FAST_FETCH 0 +#define I386_FAST_READ 1 +#define I386_FAST_WRITE 2 + +static UINT8 *i386_fast_lookup(i386_state *cpustate, UINT32 address, UINT32 len, int kind); + +static INLINE UINT8 *i386_fast_ptr(i386_state *cpustate, UINT32 address, UINT32 len, int kind) +{ +#ifndef MSB_FIRST + UINT32 off = address - cpustate->fast_start[kind]; + + if (off < cpustate->fast_size[kind] && cpustate->fast_size[kind] - off >= len) + return cpustate->fast_base[kind] + off; + return i386_fast_lookup(cpustate, address, len, kind); +#else + return NULL; +#endif +} + +static INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc) +{ + UINT32 address; + cpustate->pc = i386_translate(cpustate, CS, pc ); + + address = cpustate->pc; + + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } +} + +static INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs) +{ + UINT32 address; + /* TODO: limit */ + cpustate->eip += offs; + cpustate->pc += offs; + + address = cpustate->pc; + + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } +} + +static INLINE UINT8 FETCH(i386_state *cpustate); + +static UINT8 FETCH_slow(i386_state *cpustate) +{ + UINT8 value; + UINT32 address = cpustate->pc; + + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 1, I386_FAST_FETCH); + value = p ? *p : cpu_readmem32ledw(address); + } + cpustate->eip++; + cpustate->pc++; + return value; +} +static UINT16 FETCH16_slow(i386_state *cpustate) +{ + UINT16 value; + UINT32 address = cpustate->pc; + + if( address & 0x1 ) { /* Unaligned read */ + value = (FETCH(cpustate) << 0) | + (FETCH(cpustate) << 8); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 2, I386_FAST_FETCH); + value = p ? *(UINT16 *)p : cpu_readmem32ledw_word(address); + } + cpustate->eip += 2; + cpustate->pc += 2; + } + return value; +} +static UINT32 FETCH32_slow(i386_state *cpustate) +{ + UINT32 value; + UINT32 address = cpustate->pc; + + if( cpustate->pc & 0x3 ) { /* Unaligned read */ + value = (FETCH(cpustate) << 0) | + (FETCH(cpustate) << 8) | + (FETCH(cpustate) << 16) | + (FETCH(cpustate) << 24); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 4, I386_FAST_FETCH); + value = p ? *(UINT32 *)p : cpu_readmem32ledw_dword(address); + } + cpustate->eip += 4; + cpustate->pc += 4; + } + return value; +} + +/* the fetches: straight from the fast memory when the address is in the */ +/* cached region and paging is off, else through the handlers */ +#ifndef MSB_FIRST +#define FAST_FETCH_OFFSET(cs, n) \ + UINT32 off = ((cs)->pc & (cs)->a20_mask) - (cs)->fast_start[I386_FAST_FETCH]; \ + if (off < (cs)->fast_size[I386_FAST_FETCH] && (cs)->fast_size[I386_FAST_FETCH] - off >= (n) && !((cs)->cr[0] & 0x80000000)) +#endif + +static INLINE UINT8 FETCH(i386_state *cpustate) +{ +#ifndef MSB_FIRST + FAST_FETCH_OFFSET(cpustate, 1) + { + cpustate->eip++; + cpustate->pc++; + return cpustate->fast_base[I386_FAST_FETCH][off]; + } +#endif + return FETCH_slow(cpustate); +} + +static INLINE UINT16 FETCH16(i386_state *cpustate) +{ +#ifndef MSB_FIRST + FAST_FETCH_OFFSET(cpustate, 2) + { + const UINT8 *p = cpustate->fast_base[I386_FAST_FETCH] + off; + cpustate->eip += 2; + cpustate->pc += 2; + return p[0] | (p[1] << 8); + } +#endif + return FETCH16_slow(cpustate); +} + +static INLINE UINT32 FETCH32(i386_state *cpustate) +{ +#ifndef MSB_FIRST + FAST_FETCH_OFFSET(cpustate, 4) + { + const UINT8 *p = cpustate->fast_base[I386_FAST_FETCH] + off; + cpustate->eip += 4; + cpustate->pc += 4; + return p[0] | (p[1] << 8) | (p[2] << 16) | ((UINT32)p[3] << 24); + } +#endif + return FETCH32_slow(cpustate); +} + +static INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea); +static INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value); + +static UINT8 READ8_slow(i386_state *cpustate,UINT32 ea) +{ + UINT32 address = ea; + + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 1, I386_FAST_READ); + return p ? *p : cpu_readmem32ledw(address); + } +} +static UINT16 READ16_slow(i386_state *cpustate,UINT32 ea) +{ + UINT16 value; + UINT32 address = ea; + + if( ea & 0x1 ) { /* Unaligned read */ + value = (READ8( cpustate, address+0 ) << 0) | + (READ8( cpustate, address+1 ) << 8); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 2, I386_FAST_READ); + value = p ? *(UINT16 *)p : cpu_readmem32ledw_word(address); + } + } + return value; +} +static UINT32 READ32_slow(i386_state *cpustate,UINT32 ea) +{ + UINT32 value; + UINT32 address = ea; + + if( ea & 0x3 ) { /* Unaligned read */ + value = (READ8( cpustate, address+0 ) << 0) | + (READ8( cpustate, address+1 ) << 8) | + (READ8( cpustate, address+2 ) << 16) | + (READ8( cpustate, address+3 ) << 24); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 4, I386_FAST_READ); + value = p ? *(UINT32 *)p : cpu_readmem32ledw_dword(address); + } + } + return value; +} + +static INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea) +{ + UINT64 value; + UINT32 address = ea; + + if( ea & 0x7 ) { /* Unaligned read */ + value = (((UINT64) READ8( cpustate, address+0 )) << 0) | + (((UINT64) READ8( cpustate, address+1 )) << 8) | + (((UINT64) READ8( cpustate, address+2 )) << 16) | + (((UINT64) READ8( cpustate, address+3 )) << 24) | + (((UINT64) READ8( cpustate, address+4 )) << 32) | + (((UINT64) READ8( cpustate, address+5 )) << 40) | + (((UINT64) READ8( cpustate, address+6 )) << 48) | + (((UINT64) READ8( cpustate, address+7 )) << 56); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + value = (((UINT64) cpu_readmem32ledw_dword(address+0 )) << 0) | + (((UINT64) cpu_readmem32ledw_dword(address+4 )) << 32); + } + return value; +} + +static void WRITE8_slow(i386_state *cpustate,UINT32 ea, UINT8 value) +{ + UINT32 address = ea; + + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 1, I386_FAST_WRITE); + if (p) + *p = value; + else + cpu_writemem32ledw(address, value); + } +} +static void WRITE16_slow(i386_state *cpustate,UINT32 ea, UINT16 value) +{ + UINT32 address = ea; + + if( ea & 0x1 ) { /* Unaligned write */ + WRITE8( cpustate, address+0, value & 0xff ); + WRITE8( cpustate, address+1, (value >> 8) & 0xff ); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 2, I386_FAST_WRITE); + if (p) + *(UINT16 *)p = value; + else + cpu_writemem32ledw_word(address, value); + } + } +} +static void WRITE32_slow(i386_state *cpustate,UINT32 ea, UINT32 value) +{ + UINT32 address = ea; + + if( ea & 0x3 ) { /* Unaligned write */ + WRITE8( cpustate, address+0, value & 0xff ); + WRITE8( cpustate, address+1, (value >> 8) & 0xff ); + WRITE8( cpustate, address+2, (value >> 16) & 0xff ); + WRITE8( cpustate, address+3, (value >> 24) & 0xff ); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + { + UINT8 *p = i386_fast_ptr(cpustate, address, 4, I386_FAST_WRITE); + if (p) + *(UINT32 *)p = value; + else + cpu_writemem32ledw_dword(address, value); + } + } +} + +/* the data accesses: straight from the fast memory when the address is */ +/* in the cached region of the kind and paging is off, else the handlers */ +#ifndef MSB_FIRST +#define FAST_DATA_OFFSET(cs, ea, n, kind) \ + UINT32 off = ((ea) & (cs)->a20_mask) - (cs)->fast_start[kind]; \ + if (off < (cs)->fast_size[kind] && (cs)->fast_size[kind] - off >= (n) && !((cs)->cr[0] & 0x80000000)) +#endif + +static INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 1, I386_FAST_READ) + return cpustate->fast_base[I386_FAST_READ][off]; +#endif + return READ8_slow(cpustate, ea); +} + +static INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 2, I386_FAST_READ) + { + const UINT8 *p = cpustate->fast_base[I386_FAST_READ] + off; + return p[0] | (p[1] << 8); + } +#endif + return READ16_slow(cpustate, ea); +} + +static INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 4, I386_FAST_READ) + { + const UINT8 *p = cpustate->fast_base[I386_FAST_READ] + off; + return p[0] | (p[1] << 8) | (p[2] << 16) | ((UINT32)p[3] << 24); + } +#endif + return READ32_slow(cpustate, ea); +} + +static INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 1, I386_FAST_WRITE) + { + cpustate->fast_base[I386_FAST_WRITE][off] = value; + return; + } +#endif + WRITE8_slow(cpustate, ea, value); +} + +static INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 2, I386_FAST_WRITE) + { + UINT8 *p = cpustate->fast_base[I386_FAST_WRITE] + off; + p[0] = value; + p[1] = value >> 8; + return; + } +#endif + WRITE16_slow(cpustate, ea, value); +} + +static INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value) +{ +#ifndef MSB_FIRST + FAST_DATA_OFFSET(cpustate, ea, 4, I386_FAST_WRITE) + { + UINT8 *p = cpustate->fast_base[I386_FAST_WRITE] + off; + p[0] = value; + p[1] = value >> 8; + p[2] = value >> 16; + p[3] = value >> 24; + return; + } +#endif + WRITE32_slow(cpustate, ea, value); +} + +static INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value) +{ + UINT32 address = ea; + + if( ea & 0x7 ) { /* Unaligned write */ + WRITE8( cpustate, address+0, value & 0xff ); + WRITE8( cpustate, address+1, (value >> 8) & 0xff ); + WRITE8( cpustate, address+2, (value >> 16) & 0xff ); + WRITE8( cpustate, address+3, (value >> 24) & 0xff ); + WRITE8( cpustate, address+4, (value >> 32) & 0xff ); + WRITE8( cpustate, address+5, (value >> 40) & 0xff ); + WRITE8( cpustate, address+6, (value >> 48) & 0xff ); + WRITE8( cpustate, address+7, (value >> 56) & 0xff ); + } else { + if (cpustate->cr[0] & 0x80000000) /* page translation enabled */ + { + translate_address(cpustate,&address); + } + + address &= cpustate->a20_mask; + cpu_writemem32ledw_dword(address+0, value & 0xffffffff); + cpu_writemem32ledw_dword(address+4, (value >> 32) & 0xffffffff); + } +} + +/***********************************************************************************/ + +static INLINE UINT8 OR8(i386_state *cpustate,UINT8 dst, UINT8 src) +{ + UINT8 res = dst | src; + cpustate->CF = cpustate->OF = 0; + SetSZPF8(res); + return res; +} +static INLINE UINT16 OR16(i386_state *cpustate,UINT16 dst, UINT16 src) +{ + UINT16 res = dst | src; + cpustate->CF = cpustate->OF = 0; + SetSZPF16(res); + return res; +} +static INLINE UINT32 OR32(i386_state *cpustate,UINT32 dst, UINT32 src) +{ + UINT32 res = dst | src; + cpustate->CF = cpustate->OF = 0; + SetSZPF32(res); + return res; +} + +static INLINE UINT8 AND8(i386_state *cpustate,UINT8 dst, UINT8 src) +{ + UINT8 res = dst & src; + cpustate->CF = cpustate->OF = 0; + SetSZPF8(res); + return res; +} +static INLINE UINT16 AND16(i386_state *cpustate,UINT16 dst, UINT16 src) +{ + UINT16 res = dst & src; + cpustate->CF = cpustate->OF = 0; + SetSZPF16(res); + return res; +} +static INLINE UINT32 AND32(i386_state *cpustate,UINT32 dst, UINT32 src) +{ + UINT32 res = dst & src; + cpustate->CF = cpustate->OF = 0; + SetSZPF32(res); + return res; +} + +static INLINE UINT8 XOR8(i386_state *cpustate,UINT8 dst, UINT8 src) +{ + UINT8 res = dst ^ src; + cpustate->CF = cpustate->OF = 0; + SetSZPF8(res); + return res; +} +static INLINE UINT16 XOR16(i386_state *cpustate,UINT16 dst, UINT16 src) +{ + UINT16 res = dst ^ src; + cpustate->CF = cpustate->OF = 0; + SetSZPF16(res); + return res; +} +static INLINE UINT32 XOR32(i386_state *cpustate,UINT32 dst, UINT32 src) +{ + UINT32 res = dst ^ src; + cpustate->CF = cpustate->OF = 0; + SetSZPF32(res); + return res; +} + +#define SUB8(cpu, dst, src) SBB8(cpu, dst, src, 0) +static INLINE UINT8 SBB8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 b) +{ + UINT16 res = (UINT16)dst - (UINT16)src - (UINT8)b; + SetCF8(res); + SetOF_Sub8(res,src,dst); + SetAF(res,src,dst); + SetSZPF8(res); + return (UINT8)res; +} + +#define SUB16(cpu, dst, src) SBB16(cpu, dst, src, 0) +static INLINE UINT16 SBB16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT16 b) +{ + UINT32 res = (UINT32)dst - (UINT32)src - (UINT32)b; + SetCF16(res); + SetOF_Sub16(res,src,dst); + SetAF(res,src,dst); + SetSZPF16(res); + return (UINT16)res; +} + +#define SUB32(cpu, dst, src) SBB32(cpu, dst, src, 0) +static INLINE UINT32 SBB32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 b) +{ + UINT64 res = (UINT64)dst - (UINT64)src - (UINT64) b; + SetCF32(res); + SetOF_Sub32(res,src,dst); + SetAF(res,src,dst); + SetSZPF32(res); + return (UINT32)res; +} + +#define ADD8(cpu, dst, src) ADC8(cpu, dst, src, 0) +static INLINE UINT8 ADC8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 c) +{ + UINT16 res = (UINT16)dst + (UINT16)src + (UINT16)c; + SetCF8(res); + SetOF_Add8(res,src,dst); + SetAF(res,src,dst); + SetSZPF8(res); + return (UINT8)res; +} + +#define ADD16(cpu, dst, src) ADC16(cpu, dst, src, 0) +static INLINE UINT16 ADC16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT8 c) +{ + UINT32 res = (UINT32)dst + (UINT32)src + (UINT32)c; + SetCF16(res); + SetOF_Add16(res,src,dst); + SetAF(res,src,dst); + SetSZPF16(res); + return (UINT16)res; +} + +#define ADD32(cpu, dst, src) ADC32(cpu, dst, src, 0) +static INLINE UINT32 ADC32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 c) +{ + UINT64 res = (UINT64)dst + (UINT64)src + (UINT64) c; + SetCF32(res); + SetOF_Add32(res,src,dst); + SetAF(res,src,dst); + SetSZPF32(res); + return (UINT32)res; +} + +static INLINE UINT8 INC8(i386_state *cpustate,UINT8 dst) +{ + UINT16 res = (UINT16)dst + 1; + SetOF_Add8(res,1,dst); + SetAF(res,1,dst); + SetSZPF8(res); + return (UINT8)res; +} +static INLINE UINT16 INC16(i386_state *cpustate,UINT16 dst) +{ + UINT32 res = (UINT32)dst + 1; + SetOF_Add16(res,1,dst); + SetAF(res,1,dst); + SetSZPF16(res); + return (UINT16)res; +} +static INLINE UINT32 INC32(i386_state *cpustate,UINT32 dst) +{ + UINT64 res = (UINT64)dst + 1; + SetOF_Add32(res,1,dst); + SetAF(res,1,dst); + SetSZPF32(res); + return (UINT32)res; +} + +static INLINE UINT8 DEC8(i386_state *cpustate,UINT8 dst) +{ + UINT16 res = (UINT16)dst - 1; + SetOF_Sub8(res,1,dst); + SetAF(res,1,dst); + SetSZPF8(res); + return (UINT8)res; +} +static INLINE UINT16 DEC16(i386_state *cpustate,UINT16 dst) +{ + UINT32 res = (UINT32)dst - 1; + SetOF_Sub16(res,1,dst); + SetAF(res,1,dst); + SetSZPF16(res); + return (UINT16)res; +} +static INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst) +{ + UINT64 res = (UINT64)dst - 1; + SetOF_Sub32(res,1,dst); + SetAF(res,1,dst); + SetSZPF32(res); + return (UINT32)res; +} + + + +static INLINE void PUSH16(i386_state *cpustate,UINT16 value) +{ + UINT32 ea; + if( STACK_32BIT ) { + REG32(ESP) -= 2; + ea = i386_translate(cpustate, SS, REG32(ESP) ); + WRITE16(cpustate, ea, value ); + } else { + REG16(SP) -= 2; + ea = i386_translate(cpustate, SS, REG16(SP) ); + WRITE16(cpustate, ea, value ); + } +} +static INLINE void PUSH32(i386_state *cpustate,UINT32 value) +{ + UINT32 ea; + if( STACK_32BIT ) { + REG32(ESP) -= 4; + ea = i386_translate(cpustate, SS, REG32(ESP) ); + WRITE32(cpustate, ea, value ); + } else { + REG16(SP) -= 4; + ea = i386_translate(cpustate, SS, REG16(SP) ); + WRITE32(cpustate, ea, value ); + } +} +static INLINE void PUSH8(i386_state *cpustate,UINT8 value) +{ + if( cpustate->operand_size ) { + PUSH32(cpustate,(INT32)(INT8)value); + } else { + PUSH16(cpustate,(INT16)(INT8)value); + } +} + +static INLINE UINT8 POP8(i386_state *cpustate) +{ + UINT8 value; + UINT32 ea; + if( STACK_32BIT ) { + ea = i386_translate(cpustate, SS, REG32(ESP) ); + value = READ8(cpustate, ea ); + REG32(ESP) += 1; + } else { + ea = i386_translate(cpustate, SS, REG16(SP) ); + value = READ8(cpustate, ea ); + REG16(SP) += 1; + } + return value; +} +static INLINE UINT16 POP16(i386_state *cpustate) +{ + UINT16 value; + UINT32 ea; + if( STACK_32BIT ) { + ea = i386_translate(cpustate, SS, REG32(ESP) ); + value = READ16(cpustate, ea ); + REG32(ESP) += 2; + } else { + ea = i386_translate(cpustate, SS, REG16(SP) ); + value = READ16(cpustate, ea ); + REG16(SP) += 2; + } + return value; +} +static INLINE UINT32 POP32(i386_state *cpustate) +{ + UINT32 value; + UINT32 ea; + if( STACK_32BIT ) { + ea = i386_translate(cpustate, SS, REG32(ESP) ); + value = READ32(cpustate, ea ); + REG32(ESP) += 4; + } else { + ea = i386_translate(cpustate, SS, REG16(SP) ); + value = READ32(cpustate, ea ); + REG16(SP) += 4; + } + return value; +} + +static INLINE void BUMP_SI(i386_state *cpustate,int adjustment) +{ + if ( cpustate->address_size ) + REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment); + else + REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment); +} + +static INLINE void BUMP_DI(i386_state *cpustate,int adjustment) +{ + if ( cpustate->address_size ) + REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment); + else + REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment); +} + + + +/***********************************************************************************/ + +#define READPORT8(port) (cpu_readport16ledw(port)) +#define READPORT16(port) (cpu_readport16ledw_word(port)) +#define READPORT32(port) (cpu_readport16ledw_dword(port)) +#define WRITEPORT8(port, value) (cpu_writeport16ledw(port, value)) +#define WRITEPORT16(port, value) (cpu_writeport16ledw_word(port, value)) +#define WRITEPORT32(port, value) (cpu_writeport16ledw_dword(port, value)) + +#endif /* __I386_H__ */ diff --git a/src/cpu/i386/i486ops.c b/src/cpu/i386/i486ops.c new file mode 100644 index 00000000..8c9202ff --- /dev/null +++ b/src/cpu/i386/i486ops.c @@ -0,0 +1,424 @@ +/* Intel 486+ specific opcodes */ + +static void I486OP(cpuid)(i386_state *cpustate) /* Opcode 0x0F A2 */ +{ + if (cpustate->cpuid_id0 == 0) + { + /* this 486 doesn't support the CPUID instruction */ + logerror("CPUID not supported at %08x!\n", cpustate->eip); + i386_trap(cpustate, 6, 0); + } + else + { + switch (REG32(EAX)) + { + case 0: + { + REG32(EAX) = cpustate->cpuid_max_input_value_eax; + REG32(EBX) = cpustate->cpuid_id0; + REG32(ECX) = cpustate->cpuid_id2; + REG32(EDX) = cpustate->cpuid_id1; + CYCLES(cpustate,CYCLES_CPUID); + break; + } + + case 1: + { + REG32(EAX) = cpustate->cpu_version; + REG32(EDX) = cpustate->feature_flags; + CYCLES(cpustate,CYCLES_CPUID_EAX1); + break; + } + } + } +} + +static void I486OP(invd)(i386_state *cpustate) /* Opcode 0x0f 08 */ +{ + /* Nothing to do ? */ + CYCLES(cpustate,CYCLES_INVD); +} + +static void I486OP(wbinvd)(i386_state *cpustate) /* Opcode 0x0f 09 */ +{ + /* Nothing to do ? */ +} + +static void I486OP(cmpxchg_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f b0 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + UINT8 src = LOAD_REG8(modrm); + + if( REG8(AL) == dst ) { + STORE_RM8(modrm, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T); + } else { + REG8(AL) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F); + } + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + UINT8 src = LOAD_REG8(modrm); + + if( REG8(AL) == dst ) { + WRITE8(cpustate,modrm, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T); + } else { + REG8(AL) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F); + } + } +} + +static void I486OP(cmpxchg_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f b1 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 src = LOAD_REG16(modrm); + + if( REG16(AX) == dst ) { + STORE_RM16(modrm, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T); + } else { + REG16(AX) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F); + } + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 src = LOAD_REG16(modrm); + + if( REG16(AX) == dst ) { + WRITE16(cpustate,modrm, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T); + } else { + REG16(AX) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F); + } + } +} + +static void I486OP(cmpxchg_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f b1 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 src = LOAD_REG32(modrm); + + if( REG32(EAX) == dst ) { + STORE_RM32(modrm, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T); + } else { + REG32(EAX) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F); + } + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 src = LOAD_REG32(modrm); + + if( REG32(EAX) == dst ) { + WRITE32(cpustate,ea, src); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T); + } else { + REG32(EAX) = dst; + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F); + } + } +} + +static void I486OP(xadd_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f c0 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT8 dst = LOAD_RM8(modrm); + UINT8 src = LOAD_REG8(modrm); + STORE_RM16(modrm, dst + src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT8 dst = READ8(cpustate,ea); + UINT8 src = LOAD_REG8(modrm); + WRITE8(cpustate,ea, dst + src); + STORE_REG8(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_MEM); + } +} + +static void I486OP(xadd_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f c1 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT16 dst = LOAD_RM16(modrm); + UINT16 src = LOAD_REG16(modrm); + STORE_RM16(modrm, dst + src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT16 dst = READ16(cpustate,ea); + UINT16 src = LOAD_REG16(modrm); + WRITE16(cpustate,ea, dst + src); + STORE_REG16(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_MEM); + } +} + +static void I486OP(xadd_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f c1 */ +{ + UINT8 modrm = FETCH(cpustate); + if( modrm >= 0xc0 ) { + UINT32 dst = LOAD_RM32(modrm); + UINT32 src = LOAD_REG32(modrm); + STORE_RM32(modrm, dst + src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_REG); + } else { + UINT32 ea = GetEA(cpustate,modrm); + UINT32 dst = READ32(cpustate,ea); + UINT32 src = LOAD_REG32(modrm); + WRITE32(cpustate,ea, dst + src); + STORE_REG32(modrm, dst); + CYCLES(cpustate,CYCLES_XADD_REG_MEM); + } +} + +static void I486OP(group0F01_16)(i386_state *cpustate) /* Opcode 0x0f 01 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT16 address; + UINT32 ea; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->gdtr.limit); + WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff); + CYCLES(cpustate,CYCLES_SGDT); + break; + } + case 1: /* SIDT */ + { + if (modrm >= 0xc0) + { + address = LOAD_RM16(modrm); + ea = i386_translate( cpustate, CS, address ); + } + else + { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->idtr.limit); + WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff); + CYCLES(cpustate,CYCLES_SIDT); + break; + } + case 2: /* LGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->gdtr.limit = READ16(cpustate,ea); + cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff; + CYCLES(cpustate,CYCLES_LGDT); + break; + } + case 3: /* LIDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM16(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->idtr.limit = READ16(cpustate,ea); + cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff; + CYCLES(cpustate,CYCLES_LIDT); + break; + } + case 4: /* SMSW */ + { + if( modrm >= 0xc0 ) { + STORE_RM16(modrm, cpustate->cr[0]); + CYCLES(cpustate,CYCLES_SMSW_REG); + } else { + ea = GetEA(cpustate,modrm); + WRITE16(cpustate,ea, cpustate->cr[0]); + CYCLES(cpustate,CYCLES_SMSW_MEM); + } + break; + } + case 6: /* LMSW */ + { + /* TODO: Check for protection fault */ + UINT8 b; + if( modrm >= 0xc0 ) { + b = LOAD_RM8(modrm); + CYCLES(cpustate,CYCLES_LMSW_REG); + } else { + ea = GetEA(cpustate,modrm); + CYCLES(cpustate,CYCLES_LMSW_MEM); + b = READ8(cpustate,ea); + } + cpustate->cr[0] &= ~0x03; + cpustate->cr[0] |= b & 0x03; + break; + } + case 7: /* INVLPG */ + { + /* Nothing to do ? */ + break; + } + default: + i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2); + break; + } +} + +static void I486OP(group0F01_32)(i386_state *cpustate) /* Opcode 0x0f 01 */ +{ + UINT8 modrm = FETCH(cpustate); + UINT32 address, ea; + + switch( (modrm >> 3) & 0x7 ) + { + case 0: /* SGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->gdtr.limit); + WRITE32(cpustate,ea + 2, cpustate->gdtr.base); + CYCLES(cpustate,CYCLES_SGDT); + break; + } + case 1: /* SIDT */ + { + if (modrm >= 0xc0) + { + address = LOAD_RM32(modrm); + ea = i386_translate( cpustate, CS, address ); + } + else + { + ea = GetEA(cpustate,modrm); + } + WRITE16(cpustate,ea, cpustate->idtr.limit); + WRITE32(cpustate,ea + 2, cpustate->idtr.base); + CYCLES(cpustate,CYCLES_SIDT); + break; + } + case 2: /* LGDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->gdtr.limit = READ16(cpustate,ea); + cpustate->gdtr.base = READ32(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_LGDT); + break; + } + case 3: /* LIDT */ + { + if( modrm >= 0xc0 ) { + address = LOAD_RM32(modrm); + ea = i386_translate( cpustate, CS, address ); + } else { + ea = GetEA(cpustate,modrm); + } + cpustate->idtr.limit = READ16(cpustate,ea); + cpustate->idtr.base = READ32(cpustate,ea + 2); + CYCLES(cpustate,CYCLES_LIDT); + break; + } + case 7: /* INVLPG */ + { + /* Nothing to do ? */ + break; + } + default: + i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2); + break; + } +} + +static void I486OP(bswap_eax)(i386_state *cpustate) /* Opcode 0x0f 38 */ +{ + REG32(EAX) = SWITCH_ENDIAN_32(REG32(EAX)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_ecx)(i386_state *cpustate) /* Opcode 0x0f 39 */ +{ + REG32(ECX) = SWITCH_ENDIAN_32(REG32(ECX)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_edx)(i386_state *cpustate) /* Opcode 0x0f 3A */ +{ + REG32(EDX) = SWITCH_ENDIAN_32(REG32(EDX)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_ebx)(i386_state *cpustate) /* Opcode 0x0f 3B */ +{ + REG32(EBX) = SWITCH_ENDIAN_32(REG32(EBX)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_esp)(i386_state *cpustate) /* Opcode 0x0f 3C */ +{ + REG32(ESP) = SWITCH_ENDIAN_32(REG32(ESP)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_ebp)(i386_state *cpustate) /* Opcode 0x0f 3D */ +{ + REG32(EBP) = SWITCH_ENDIAN_32(REG32(EBP)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_esi)(i386_state *cpustate) /* Opcode 0x0f 3E */ +{ + REG32(ESI) = SWITCH_ENDIAN_32(REG32(ESI)); + CYCLES(cpustate,1); /* TODO */ +} + +static void I486OP(bswap_edi)(i386_state *cpustate) /* Opcode 0x0f 3F */ +{ + REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI)); + CYCLES(cpustate,1); /* TODO */ +} diff --git a/src/cpu/i386/pentops.c b/src/cpu/i386/pentops.c new file mode 100644 index 00000000..9cbb8b07 --- /dev/null +++ b/src/cpu/i386/pentops.c @@ -0,0 +1,53 @@ +/* Pentium+ specific opcodes */ + +static void PENTIUMOP(rdmsr)(i386_state *cpustate) /* Opcode 0x0f 32 */ +{ + /* TODO */ + CYCLES(cpustate,CYCLES_RDMSR); +} + +static void PENTIUMOP(wrmsr)(i386_state *cpustate) /* Opcode 0x0f 30 */ +{ + /* TODO */ + CYCLES(cpustate,1); /* TODO: correct cycle count */ +} + +static void PENTIUMOP(rdtsc)(i386_state *cpustate) /* Opcode 0x0f 31 */ +{ + UINT64 ts = cpustate->tsc + (cpustate->base_cycles - i386_ICount); + REG32(EAX) = (UINT32)(ts); + REG32(EDX) = (UINT32)(ts >> 32); + + CYCLES(cpustate,CYCLES_RDTSC); +} + +static void I386OP(cyrix_unknown)(i386_state *cpustate) /* Opcode 0x0f 74 */ +{ + CYCLES(cpustate,1); +} + +static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) /* Opcode 0x0f c7 */ +{ + UINT8 modm = FETCH(cpustate); + if( modm >= 0xc0 ) { + i386_fatal("pentium: cmpxchg8b_m64 - invalid modm"); + } else { + UINT32 ea = GetEA(cpustate,modm); + UINT64 value = READ64(cpustate,ea); + UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX); + UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX); + + if( value == edx_eax ) { + WRITE64(cpustate,ea, ecx_ebx); + cpustate->ZF = 1; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T); + } else { + REG32(EDX) = (UINT32) (value >> 32); + REG32(EAX) = (UINT32) (value >> 0); + cpustate->ZF = 0; + CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F); + } + } +} + + diff --git a/src/cpu/i386/x87ops.c b/src/cpu/i386/x87ops.c new file mode 100644 index 00000000..4e6c74db --- /dev/null +++ b/src/cpu/i386/x87ops.c @@ -0,0 +1,352 @@ +/* Intel x87 FPU opcodes */ + +#define ST(x) (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7]) +#define FPU_INFINITY_DOUBLE COMBINE_64_32_32(0x7ff00000, 0x00000000) +#define FPU_INFINITY_SINGLE (0x7f800000) +#define FPU_SIGN_BIT_DOUBLE COMBINE_64_32_32(0x80000000, 0x00000000) +#define FPU_SIGN_BIT_SINGLE (0x80000000) + +/* FPU control word flags */ +#define FPU_MASK_INVALID_OP 0x0001 +#define FPU_MASK_DENORMAL_OP 0x0002 +#define FPU_MASK_ZERO_DIVIDE 0x0004 +#define FPU_MASK_OVERFLOW 0x0008 +#define FPU_MASK_UNDERFLOW 0x0010 +#define FPU_MASK_PRECISION 0x0020 + +/* FPU status word flags */ +#define FPU_BUSY 0x8000 +#define FPU_C3 0x4000 +#define FPU_STACK_TOP_MASK 0x3800 +#define FPU_C2 0x0400 +#define FPU_C1 0x0200 +#define FPU_C0 0x0100 +#define FPU_ERROR_SUMMARY 0x0080 +#define FPU_STACK_FAULT 0x0040 +#define FPU_EXCEPTION_PRECISION 0x0020 +#define FPU_EXCEPTION_UNDERFLOW 0x0010 +#define FPU_EXCEPTION_OVERFLOW 0x0008 +#define FPU_EXCEPTION_ZERO_DIVIDE 0x0004 +#define FPU_EXCEPTION_DENORMAL_OP 0x0002 +#define FPU_EXCEPTION_INVALID_OP 0x0001 + +static INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value) +{ + cpustate->fpu_top--; + if (cpustate->fpu_top < 0) + { + cpustate->fpu_top = 7; + } + + cpustate->fpu_reg[cpustate->fpu_top] = value; +} + +static INLINE X87_REG FPU_POP(i386_state *cpustate) +{ + X87_REG value = cpustate->fpu_reg[cpustate->fpu_top]; + + cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2); /* set FPU register tag to 3 (empty) */ + + cpustate->fpu_top++; + if (cpustate->fpu_top > 7) + { + cpustate->fpu_top = 0; + } + + return value; +} + +static void I386OP(fpu_group_d8)(i386_state *cpustate) /* Opcode 0xd8 */ +{ + UINT8 modrm = FETCH(cpustate); + i386_fatal("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2); +} + +static void I386OP(fpu_group_d9)(i386_state *cpustate) /* Opcode 0xd9 */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + UINT32 ea = GetEA(cpustate,modrm); + + switch ((modrm >> 3) & 0x7) + { + case 5: /* FLDCW */ + { + cpustate->fpu_control_word = READ16(cpustate,ea); + CYCLES(cpustate,1); /* TODO */ + break; + } + + case 7: /* FSTCW */ + { + WRITE16(cpustate,ea, cpustate->fpu_control_word); + CYCLES(cpustate,1); /* TODO */ + break; + } + + default: + i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2); + } + } + else + { + switch (modrm & 0x3f) + { + /* FLD */ + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + { + X87_REG t = ST(modrm & 7); + FPU_PUSH(cpustate,t); + CYCLES(cpustate,1); /* TODO */ + break; + } + + case 0x20: /* FCHS */ + { + ST(0).i ^= FPU_SIGN_BIT_DOUBLE; + CYCLES(cpustate,1); /* TODO */ + break; + } + + case 0x28: /* FLD1 */ + { + X87_REG t; + t.f = 1.0; + FPU_PUSH(cpustate,t); + CYCLES(cpustate,1); /* TODO */ + break; + } + + case 0x2e: /* FLDZ */ + { + X87_REG t; + t.f = 0.0; + FPU_PUSH(cpustate,t); + CYCLES(cpustate,1); /* TODO */ + break; + } + default: + i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2); + } + } +} + +static void I386OP(fpu_group_da)(i386_state *cpustate) /* Opcode 0xda */ +{ + UINT8 modrm = FETCH(cpustate); + i386_fatal("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2); +} + +static void I386OP(fpu_group_db)(i386_state *cpustate) /* Opcode 0xdb */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2); + } + else + { + switch (modrm & 0x3f) + { + case 0x23: /* FINIT */ + { + cpustate->fpu_control_word = 0x37f; + cpustate->fpu_status_word = 0; + cpustate->fpu_tag_word = 0xffff; + cpustate->fpu_data_ptr = 0; + cpustate->fpu_inst_ptr = 0; + cpustate->fpu_opcode = 0; + + CYCLES(cpustate,1); /* TODO */ + break; + } + + case 0x24: /* FSETPM (treated as nop on 387+) */ + { + CYCLES(cpustate,1); + break; + } + + default: + i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2); + } + } +} + +static void I386OP(fpu_group_dc)(i386_state *cpustate) /* Opcode 0xdc */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + /*UINT32 ea = GetEA(cpustate,modrm); */ + + switch ((modrm >> 3) & 0x7) + { + default: + i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2); + } + } + else + { + switch (modrm & 0x3f) + { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + { + /* FDIVR */ + if ((ST(modrm & 7).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0) + { + /* set result as infinity if zero divide is masked */ + if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE) + { + ST(modrm & 7).i |= FPU_INFINITY_DOUBLE; + } + } + else + { + ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f; + } + CYCLES(cpustate,1); /* TODO */ + break; + } + + default: + i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2); + } + } +} + +static void I386OP(fpu_group_dd)(i386_state *cpustate) /* Opcode 0xdd */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + UINT32 ea = GetEA(cpustate,modrm); + + switch ((modrm >> 3) & 0x7) + { + case 7: /* FSTSW */ + { + WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10)); + CYCLES(cpustate,1); /* TODO */ + break; + } + + default: + i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2); + } + } + else + { + switch (modrm & 0x3f) + { + default: + i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2); + } + } +} + +static void I386OP(fpu_group_de)(i386_state *cpustate) /* Opcode 0xde */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + /* UINT32 ea = GetEA(cpustate,modrm); */ + + switch ((modrm >> 3) & 0x7) + { + default: + i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2); + } + } + else + { + switch (modrm & 0x3f) + { + case 0x19: /* FCOMPP */ + { + cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0); + if (ST(0).f > ST(1).f) + { + /* C3 = 0, C2 = 0, C0 = 0 */ + } + else if (ST(0).f < ST(1).f) + { + cpustate->fpu_status_word |= FPU_C0; + } + else if (ST(0).f == ST(1).f) + { + cpustate->fpu_status_word |= FPU_C3; + } + else + { + /* unordered */ + cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0); + } + FPU_POP(cpustate); + FPU_POP(cpustate); + CYCLES(cpustate,1); /* TODO */ + break; + } + + /* FDIVP */ + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + { + if ((ST(0).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0) + { + /* set result as infinity if zero divide is masked */ + if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE) + { + ST(modrm & 7).i |= FPU_INFINITY_DOUBLE; + } + } + else + { + ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f; + } + FPU_POP(cpustate); + CYCLES(cpustate,1); /* TODO */ + break; + } + + default: + i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2); + } + } +} + +static void I386OP(fpu_group_df)(i386_state *cpustate) /* Opcode 0xdf */ +{ + UINT8 modrm = FETCH(cpustate); + + if (modrm < 0xc0) + { + /* UINT32 ea = GetEA(cpustate,modrm); */ + + switch ((modrm >> 3) & 0x7) + { + default: + i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2); + } + } + else + { + switch (modrm & 0x3f) + { + case 0x20: /* FSTSW AX */ + { + REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10); + CYCLES(cpustate,1); /* TODO */ + break; + } + + default: + i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2); + } + } +} diff --git a/src/cpuintrf.c b/src/cpuintrf.c index 17e63afc..77d701f9 100644 --- a/src/cpuintrf.c +++ b/src/cpuintrf.c @@ -151,6 +151,9 @@ #if (HAS_H83002) #include "cpu/h83002/h83002.h" #endif +#if (HAS_I386) +#include "cpu/i386/i386.h" +#endif #if (HAS_M37702) #include "cpu/m37710/m37710.h" #endif @@ -592,6 +595,9 @@ const struct cpu_interface cpuintrf[] = #if (HAS_H83002) CPU0(H83002, h8_3002, 8, 0,1.00,16,24bew, 0,24,BE,2,10 ), #endif +#if (HAS_I386) + CPU0(I386, i386, 1, 0,1.00,32,32ledw, 0,32,LE,1,15 ), +#endif #if (HAS_MN10200) CPU0(MN10200, mn10200, 4, 0,1.00,16,24lew, 0,24,LE,1, 6 ), #endif diff --git a/src/cpuintrf.h b/src/cpuintrf.h index f497f498..f5d657ed 100644 --- a/src/cpuintrf.h +++ b/src/cpuintrf.h @@ -262,6 +262,9 @@ enum #if (HAS_H83002) CPU_H83002, #endif +#if (HAS_I386) + CPU_I386, +#endif #if (HAS_MN10200) CPU_MN10200, #endif diff --git a/src/driver.c b/src/driver.c index 6be059ef..35b4f7e3 100644 --- a/src/driver.c +++ b/src/driver.c @@ -5256,6 +5256,65 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11 DRIVER( nzeroteamb ) /* New Zero Team (V33 SYSTEM TYPE_B hardware, Haoyunlai Trading Company license) */ DRIVER( zerotm2k ) /* Zero Team 2000 */ + /* Seibu SPI / SYS386I games */ + DRIVER( senkyu ) /* Senkyu (Japan, newer) */ + DRIVER( senkyua ) /* Senkyu (Japan, earlier) */ + DRIVER( batlball ) /* Battle Balls (Germany, newer) */ + DRIVER( batlballo ) /* Battle Balls (Germany, earlier) */ + DRIVER( batlballu ) /* Battle Balls (US) */ + DRIVER( batlballa ) /* Battle Balls (Hong Kong) */ + DRIVER( batlballe ) /* Battle Balls (Hong Kong, earlier) */ + DRIVER( batlballpt ) /* Battle Balls (Portugal) */ + DRIVER( viprp1 ) /* Viper Phase 1 (New Version, World) */ + DRIVER( viprp1k ) /* Viper Phase 1 (New Version, Korea) */ + DRIVER( viprp1u ) /* Viper Phase 1 (New Version, US set 1) */ + DRIVER( viprp1ua ) /* Viper Phase 1 (New Version, US set 2) */ + DRIVER( viprp1j ) /* Viper Phase 1 (New Version, Japan) */ + DRIVER( viprp1s ) /* Viper Phase 1 (New Version, Switzerland) */ + DRIVER( viprp1h ) /* Viper Phase 1 (New Version, Holland) */ + DRIVER( viprp1t ) /* Viper Phase 1 (New Version, Germany) */ + DRIVER( viprp1pt ) /* Viper Phase 1 (New Version, Portugal) */ + DRIVER( viprp1ot ) /* Viper Phase 1 (Germany) */ + DRIVER( viprp1oj ) /* Viper Phase 1 (Japan) */ + DRIVER( viprp1hk ) /* Viper Phase 1 (Hong Kong) */ + DRIVER( rdft ) /* Raiden Fighters (Germany) */ + DRIVER( rdftj ) /* Raiden Fighters (Japan, earlier) */ + DRIVER( rdftja ) /* Raiden Fighters (Japan, earliest) */ + DRIVER( rdftu ) /* Raiden Fighters (US, earlier) */ + DRIVER( rdftauge ) /* Raiden Fighters (Evaluation Software For Show, Germany) */ + DRIVER( rdftua ) /* Raiden Fighters (US, newer) */ + DRIVER( rdftjb ) /* Raiden Fighters (Japan, newer) */ + DRIVER( rdftau ) /* Raiden Fighters (Australia) */ + DRIVER( rdftam ) /* Raiden Fighters (Hong Kong) */ + DRIVER( rdftadi ) /* Raiden Fighters (Korea, SUB4 cart) */ + DRIVER( rdfta ) /* Raiden Fighters (Austria) */ + DRIVER( rdftgb ) /* Raiden Fighters (Great Britain) */ + DRIVER( rdftgr ) /* Raiden Fighters (Greece) */ + DRIVER( rdftit ) /* Raiden Fighters (Italy) */ + DRIVER( rdftadia ) /* Raiden Fighters (Korea, SUB2 cart) */ + DRIVER( rdft2 ) /* Raiden Fighters 2 - Operation Hell Dive (Germany) */ + DRIVER( rdft2j ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 1) */ + DRIVER( rdft2a ) /* Raiden Fighters 2 - Operation Hell Dive (Hong Kong) */ + DRIVER( rdft2s ) /* Raiden Fighters 2 - Operation Hell Dive (Switzerland) */ + DRIVER( rdft2ja ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 2) */ + DRIVER( rdft2aa ) /* Raiden Fighters 2 - Operation Hell Dive (Korea) */ + DRIVER( rdft2it ) /* Raiden Fighters 2 - Operation Hell Dive (Italy) */ + DRIVER( rdft2jb ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 3) */ + DRIVER( rdft2jc ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 4) */ + DRIVER( rdft2t ) /* Raiden Fighters 2 - Operation Hell Dive (Taiwan) */ + DRIVER( rdft2u ) /* Raiden Fighters 2 - Operation Hell Dive (US) */ + DRIVER( rfjet ) /* Raiden Fighters Jet (Germany) */ + DRIVER( rfjetu ) /* Raiden Fighters Jet (US) */ + DRIVER( rfjetj ) /* Raiden Fighters Jet (Japan) */ + DRIVER( rfjeta ) /* Raiden Fighters Jet (Korea) */ + DRIVER( rfjett ) /* Raiden Fighters Jet (Taiwan) */ + DRIVER( rdfts ) /* Raiden Fighters (Taiwan, single board) */ + DRIVER( rdft2us ) /* Raiden Fighters 2 - Operation Hell Dive (US, single board) */ + DRIVER( rfjets ) /* Raiden Fighters Jet (US, single board) */ + DRIVER( rfjetsa ) /* Raiden Fighters Jet (US, single board, test version?) */ + DRIVER( rdft22kc ) /* Raiden Fighters 2 - Operation Hell Dive 2000 (China, SYS386I) */ + DRIVER( rfjet2kc ) /* Raiden Fighters Jet 2000 (China, SYS386I) */ + /* Seibu STI System games: Viper: Phase 1 (c) 1995 Viper: Phase 1 (New version) (c) 1996 diff --git a/src/drivers/seibuspi.c b/src/drivers/seibuspi.c new file mode 100644 index 00000000..e2de7483 --- /dev/null +++ b/src/drivers/seibuspi.c @@ -0,0 +1,3063 @@ +/*************************************************************************** + + Seibu SPI hardware + Seibu SYS386I + + Backported from current MAME src/mame/seibu/seibuspi.cpp (Ville Linde, + hap, Nicola Salmoria and others); the video is in vidhrdw/seibuspi.c and + the graphics decryption in machine/seibuspi.c. + + SPI: a main board (Intel 386DX 25MHz, Z80, YMF271, two flash ROMs for the + sound samples, a DS2404 RTC) and a cartridge with the game. The main CPU + uploads the Z80 program, then talks to it through two FIFOs; the Z80 drives + the YMF271, whose external memory is the flash pair (programmed by the + game when the cartridge is changed) and the sample ROMs of the cartridge, + read by the main CPU at 0xa00000. + + Single boards (SXX2E, SXX2F, SXX2G): the Z80 program in a ROM, one FIFO, + the samples in ROM; SXX2F and SXX2G have a 93C46 EEPROM instead of the + DS2404. SYS386I (40MHz 386): two MSM6295 instead of the Z80 sound system. + + Games: + Senkyu / Battle Balls + Viper Phase 1 + Raiden Fighters + Raiden Fighters 2 - Operation Hell Dive + Raiden Fighters Jet + + As in MAME: the alpha blending is preliminary (a table of pens), and + the JP1 jumper of the SXX2C main board is not hooked up. + +***************************************************************************/ + +#include +#include "driver.h" +#include "state.h" +#include "cpu/i386/i386.h" +#include "machine/eeprom.h" +#include "machine/intelfsh.h" +#include "machine/ds2404.h" +#include "includes/seibuspi.h" + +/* the boards */ +enum +{ + SPI_SXX2C = 0, /* SPI main board and cartridge, SEI252 sprites (0x50e) */ + SPI_SXX2C_RISE, /* the same, RISE10 / RISE11 sprites (0x562) */ + SPI_SXX2E, /* single board, SEI252, DS2404 */ + SPI_SXX2F, /* single board, RISE, EEPROM (SXX2G too) */ + SPI_SYS386I /* RISE, EEPROM, two MSM6295 */ +}; + +static int spi_board; + +static UINT8 z80_ram[0x2000]; +static UINT32 z80_prg_transfer_pos; +static UINT8 z80_lastbank; +static UINT8 sb_coin_latch; +static UINT8 oki_bank; + + +/***************************************************************************** + + The sound FIFOs (IDT7201, 512 x 9 bits): 0 from the main CPU to the Z80, + 1 back (SPI main board only) + +*****************************************************************************/ + +#define FIFO_SIZE 512 + +struct spi_fifo +{ + UINT16 data[FIFO_SIZE]; + UINT32 rpos, wpos, count; +}; + +static struct spi_fifo spi_fifo[2]; + +static void fifo_reset(struct spi_fifo *f) +{ + memset(f, 0, sizeof(*f)); +} + +static void fifo_write(struct spi_fifo *f, UINT8 data) +{ + if (f->count == FIFO_SIZE) + { + logerror("SPI: fifo overflow\n"); + return; + } + f->data[f->wpos] = data; + f->wpos = (f->wpos + 1) % FIFO_SIZE; + f->count++; +} + +static UINT8 fifo_read(struct spi_fifo *f) +{ + UINT8 ret; + + if (f->count == 0) + { + logerror("SPI: fifo underflow\n"); + return 0xff; + } + ret = f->data[f->rpos]; + f->rpos = (f->rpos + 1) % FIFO_SIZE; + f->count--; + return ret; +} + +/* the flags as the pins read: 1 while not empty / not full */ +#define FIFO_EF(f) ((f)->count != 0) +#define FIFO_FF(f) ((f)->count != FIFO_SIZE) + +static UINT8 sound_fifo_status(void) +{ + /* d0: fifo full flag (z80) */ + /* d1: fifo empty flag (main) */ + int d1 = (spi_board <= SPI_SXX2C_RISE) ? FIFO_EF(&spi_fifo[1]) << 1 : 0; + return d1 | FIFO_FF(&spi_fifo[0]); +} + + +/***************************************************************************** + + The main CPU + +*****************************************************************************/ + +static void z80_prg_transfer_w(UINT8 data) +{ + if (z80_prg_transfer_pos < memory_region_length(REGION_CPU2)) + { + memory_region(REGION_CPU2)[z80_prg_transfer_pos] = data; + z80_prg_transfer_pos++; + } +} + +static void z80_enable_w(UINT8 data) +{ + /* d0: reset z80 */ + z80_prg_transfer_pos = 0; + cpu_set_reset_line(1, (data & 1) ? CLEAR_LINE : ASSERT_LINE); +} + +static void eeprom_w(UINT8 data) +{ + EEPROM_write_bit((data >> 7) & 1); + EEPROM_set_clock_line((data & 0x40) ? ASSERT_LINE : CLEAR_LINE); + EEPROM_set_cs_line((data & 0x20) ? CLEAR_LINE : ASSERT_LINE); +} + +static UINT32 system_r(void) +{ + UINT32 ret = 0xffffff00 | readinputport(1); + + /* the EEPROM data out on the single boards with one */ + if (spi_board >= SPI_SXX2F) + ret = (ret & ~0x40) | (EEPROM_read_bit() ? 0x40 : 0); + return ret; +} + +/* the I/O at 0x400-0x7ff, over the RAM: the addresses with nothing read */ +/* and write the RAM, as the RAM of MAME is under them */ +static data32_t spi_io_r(offs_t offset, data32_t mem_mask) +{ + offs_t address = 0x400 + offset * 4; + data32_t ret = spi_mainram[address / 4]; + + if (address < 0x440) + return spi_crtc_r(offset, mem_mask); + + switch (address) + { + case 0x600: + /* d0: unknown status, waits for it to be set, video/dma related? */ + ret = (ret & ~0xff) | 0x01; + break; + + case 0x604: + ret = 0xffff0000 | readinputport(0); + break; + + case 0x608: + ret = 0xffffffff; + break; + + case 0x60c: + ret = system_r(); + break; + + case 0x680: + if (spi_board == SPI_SYS386I) + break; + if (!(mem_mask & 0xff)) + { + UINT8 d; + if (spi_board <= SPI_SXX2C_RISE) + d = fifo_read(&spi_fifo[1]); + else + { + /* the coin latch of the single boards */ + d = sb_coin_latch; + sb_coin_latch = 0; + } + ret = (ret & ~0xff) | d; + } + break; + + case 0x684: + if (spi_board != SPI_SYS386I) + ret = (ret & ~0xff) | sound_fifo_status(); + break; + + case 0x688: + if (spi_board == SPI_SXX2E || spi_board == SPI_SXX2F) + ret = 0; + break; + + case 0x6dc: + if (spi_board <= SPI_SXX2E) + { + /* d0, d1, d2 of 0x6dd: unknown, waits for them to be cleared */ + ret &= 0xffff0000; + if (!(mem_mask & 0xff)) + ret |= ds2404_data_r(0); + } + break; + } + return ret; +} + +static void spi_io_w(offs_t offset, data32_t data, data32_t mem_mask) +{ + offs_t address = 0x400 + offset * 4; + int sei252 = (spi_board == SPI_SXX2C || spi_board == SPI_SXX2E); + + if (address < 0x440) + { + spi_crtc_w(offset, data, mem_mask); + return; + } + + switch (address) + { + case 0x480: + spi_tilemap_dma_start_w(0, data, mem_mask); + return; + + case 0x484: + spi_palette_dma_start_w(0, data, mem_mask); + return; + + case 0x490: + spi_video_dma_length_w(0, data, mem_mask); + return; + + case 0x494: + spi_video_dma_address_w(0, data, mem_mask); + return; + + case 0x498: /* ? dma address high bits? (always writes 0) */ + return; + + case 0x50c: /* SEI252: sprite DMA start at 0x50e */ + if (sei252) + { + if (!(mem_mask & 0xffff0000)) + spi_sprite_dma_start(); + return; + } + break; + + case 0x524: case 0x528: case 0x530: case 0x534: case 0x53c: + if (sei252) + return; /* SEI252 sprite decryption keys */ + break; + + case 0x54c: + if (!sei252) + return; /* RISE10/11 sprite decryption key */ + break; + + case 0x560: /* RISE: sprite DMA start at 0x562 */ + if (!sei252) + { + if (!(mem_mask & 0xffff0000)) + spi_sprite_dma_start(); + return; + } + break; + + case 0x600: + if (spi_board <= SPI_SXX2C_RISE) + return; + break; + + case 0x680: + if (spi_board == SPI_SYS386I) + break; + if (!(mem_mask & 0xff)) + fifo_write(&spi_fifo[0], data & 0xff); + return; + + case 0x688: + if (spi_board <= SPI_SXX2C_RISE) + { + if (!(mem_mask & 0xff)) + z80_prg_transfer_w(data & 0xff); + return; + } + if (spi_board != SPI_SYS386I) + return; + break; + + case 0x68c: + if (spi_board <= SPI_SXX2C_RISE) + { + if (!(mem_mask & 0xff)) + z80_enable_w(data & 0xff); + if (!(mem_mask & 0xff0000)) + spi_rf2_layer_bank_w((data >> 16) & 0xff); + return; + } + if (spi_board == SPI_SXX2E) + return; + /* SXX2F, SYS386I: low bits the tile banks, high bits the EEPROM */ + if (!(mem_mask & 0xff0000)) + { + spi_rf2_layer_bank_w((data >> 16) & 0xff); + eeprom_w((data >> 16) & 0xff); + } + if (spi_board == SPI_SYS386I && !(mem_mask & 0xff000000)) + { + oki_bank = (data >> 26) & 1; + OKIM6295_set_bank_base(1, oki_bank * 0x40000); + } + return; + + case 0x690: + if (spi_board == SPI_SXX2F) + return; + break; + + case 0x6d0: + case 0x6d4: + case 0x6d8: + if (spi_board <= SPI_SXX2E) + { + if (!(mem_mask & 0xff)) + { + if (address == 0x6d0) + ds2404_1w_reset_w(0, data & 0xff); + else if (address == 0x6d4) + ds2404_data_w(0, data & 0xff); + else + ds2404_clk_w(0, data & 0xff); + } + return; + } + break; + } + + COMBINE_DATA(&spi_mainram[address / 4]); +} + +static READ32_HANDLER( spi_io32_r ) { return spi_io_r(offset, mem_mask); } +static WRITE32_HANDLER( spi_io32_w ) { spi_io_w(offset, data, mem_mask); } + +static READ32_HANDLER( oki_0_r ) { return OKIM6295_status_0_r(0); } +static READ32_HANDLER( oki_1_r ) { return OKIM6295_status_1_r(0); } +static WRITE32_HANDLER( oki_0_w ) { if (!(mem_mask & 0xff)) OKIM6295_data_0_w(0, data & 0xff); } +static WRITE32_HANDLER( oki_1_w ) { if (!(mem_mask & 0xff)) OKIM6295_data_1_w(0, data & 0xff); } + +static MEMORY_READ32_START( spi_readmem ) + { 0x00000400, 0x000007ff, spi_io32_r }, + { 0x00000000, 0x0003ffff, MRA32_BANK1 }, + { 0x00200000, 0x003fffff, MRA32_BANK2 }, + { 0x00a00000, 0x013fffff, MRA32_BANK4 }, + { 0xffe00000, 0xffffffff, MRA32_BANK3 }, /* ROM location in real-mode */ +MEMORY_END + +static MEMORY_WRITE32_START( spi_writemem ) + { 0x00000400, 0x000007ff, spi_io32_w }, + { 0x00000000, 0x0003ffff, MWA32_BANK1 }, + { 0x00200000, 0x003fffff, MWA32_NOP }, + { 0x00a00000, 0x013fffff, MWA32_NOP }, + { 0xffe00000, 0xffffffff, MWA32_NOP }, +MEMORY_END + +static MEMORY_READ32_START( sxx2e_readmem ) + { 0x00000400, 0x000007ff, spi_io32_r }, + { 0x00000000, 0x0003ffff, MRA32_BANK1 }, + { 0x00200000, 0x003fffff, MRA32_BANK2 }, + { 0xffe00000, 0xffffffff, MRA32_BANK3 }, +MEMORY_END + +static MEMORY_WRITE32_START( sxx2e_writemem ) + { 0x00000400, 0x000007ff, spi_io32_w }, + { 0x00000000, 0x0003ffff, MWA32_BANK1 }, + { 0x00200000, 0x003fffff, MWA32_NOP }, + { 0xffe00000, 0xffffffff, MWA32_NOP }, +MEMORY_END + +static MEMORY_READ32_START( sys386i_readmem ) + { 0x00000400, 0x000007ff, spi_io32_r }, + { 0x00000000, 0x0003ffff, MRA32_BANK1 }, + { 0x00200000, 0x003fffff, MRA32_BANK2 }, + { 0x01200000, 0x01200003, oki_0_r }, + { 0x01200004, 0x01200007, oki_1_r }, + { 0xffe00000, 0xffffffff, MRA32_BANK3 }, +MEMORY_END + +static MEMORY_WRITE32_START( sys386i_writemem ) + { 0x00000400, 0x000007ff, spi_io32_w }, + { 0x00000000, 0x0003ffff, MWA32_BANK1 }, + { 0x00200000, 0x003fffff, MWA32_NOP }, + { 0x01200000, 0x01200003, oki_0_w }, + { 0x01200004, 0x01200007, oki_1_w }, + { 0xffe00000, 0xffffffff, MWA32_NOP }, +MEMORY_END + + +/***************************************************************************** + + The Z80 + +*****************************************************************************/ + +static READ_HANDLER( z80_soundfifo_r ) +{ + return fifo_read(&spi_fifo[0]); +} + +static WRITE_HANDLER( z80_soundfifo_w ) +{ + if (spi_board <= SPI_SXX2C_RISE) + fifo_write(&spi_fifo[1], data); +} + +static READ_HANDLER( z80_soundfifo_status_r ) +{ + /* d0: fifo full flag (main) */ + /* d1: fifo empty flag (z80) */ + int d0 = (spi_board <= SPI_SXX2C_RISE) ? FIFO_FF(&spi_fifo[1]) : 0; + return d0 | FIFO_EF(&spi_fifo[0]) << 1; +} + +static WRITE_HANDLER( z80_bank_w ) +{ + /* d0-d2: bank @ 8000 */ + /* d3: watchdog? */ + UINT8 bank = data & 7; + + if (bank != z80_lastbank) + { + z80_lastbank = bank; + cpu_setbank(5, memory_region(REGION_CPU2) + bank * 0x8000); + } +} + +static WRITE_HANDLER( spi_coin_w ) +{ + coin_counter_w(0, data & 1); + coin_counter_w(1, (data >> 1) & 1); + + /* coin latch used by single boards */ + if (data) + sb_coin_latch = 0xa0 | data; + else + sb_coin_latch = 0; +} + +static READ_HANDLER( z80_jumpers_r ) +{ + /* JP1 (SXX2C only) */ + return (spi_board <= SPI_SXX2C_RISE) ? readinputport(3) : 0; +} + +static MEMORY_READ_START( spi_sound_readmem ) + { 0x0000, 0x1fff, MRA_ROM }, + { 0x2000, 0x3fff, MRA_BANK6 }, + { 0x4008, 0x4008, z80_soundfifo_r }, + { 0x4009, 0x4009, z80_soundfifo_status_r }, + { 0x400a, 0x400a, z80_jumpers_r }, + { 0x4013, 0x4013, input_port_2_r }, + { 0x6000, 0x600f, YMF271_0_r }, + { 0x8000, 0xffff, MRA_BANK5 }, +MEMORY_END + +static MEMORY_WRITE_START( spi_sound_writemem ) + { 0x0000, 0x1fff, MWA_NOP }, + { 0x2000, 0x3fff, MWA_BANK6 }, + { 0x4002, 0x4003, MWA_NOP }, + { 0x4004, 0x4004, spi_coin_w }, + { 0x4008, 0x4008, z80_soundfifo_w }, + { 0x400b, 0x400b, MWA_NOP }, + { 0x401b, 0x401b, z80_bank_w }, + { 0x6000, 0x600f, YMF271_0_w }, +MEMORY_END + + +/***************************************************************************** + + The sound: the YMF271 reads the two flash ROMs on the SPI main board + +*****************************************************************************/ + +static READ_HANDLER( spi_flash_r ) +{ + offset &= 0x1fffff; + return intelfsh_read(offset >> 20, offset & 0xfffff); +} + +static WRITE_HANDLER( spi_flash_w ) +{ + offset &= 0x1fffff; + intelfsh_write(offset >> 20, offset & 0xfffff, data); +} + +static void spi_ymf271_irq(int state) +{ + /* Z80 IM0, RST10 */ + cpu_set_irq_line_and_vector(1, 0, state ? ASSERT_LINE : CLEAR_LINE, 0xd7); +} + +static struct YMF271interface spi_ymf271_interface = +{ + 1, + { REGION_SOUND1 }, + { YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) }, + { spi_flash_r }, + { spi_flash_w }, + { spi_ymf271_irq }, + { 16934400 } +}; + +/* single boards: mono, the samples in ROM */ +static struct YMF271interface sxx2e_ymf271_interface = +{ + 1, + { REGION_SOUND1 }, + { YM3012_VOL(100, MIXER_PAN_CENTER, 100, MIXER_PAN_CENTER) }, + { 0 }, + { 0 }, + { spi_ymf271_irq }, + { 16934400 } +}; + +static struct YMF271interface sxx2g_ymf271_interface = +{ + 1, + { REGION_SOUND1 }, + { YM3012_VOL(100, MIXER_PAN_CENTER, 100, MIXER_PAN_CENTER) }, + { 0 }, + { 0 }, + { spi_ymf271_irq }, + { 16384000 } +}; + +/* SYS386I: 28.636363MHz / 20, pin 7 high */ +static struct OKIM6295interface sys386i_okim6295_interface = +{ + 2, + { 28636363 / 20 / 132, 28636363 / 20 / 132 }, + { REGION_SOUND1, REGION_SOUND2 }, + { 50, 50 } +}; + + +/***************************************************************************** + + Input ports + +*****************************************************************************/ + +#define SPI_PLAYER( player, button3 ) \ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_8WAY | IPF_PLAYER##player ) \ + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_8WAY | IPF_PLAYER##player ) \ + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_8WAY | IPF_PLAYER##player ) \ + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY | IPF_PLAYER##player ) \ + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER##player ) \ + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER##player ) \ + PORT_BIT( 0x0040, IP_ACTIVE_LOW, button3 | IPF_PLAYER##player ) + +#define SPI_INPUTS( button3, flip ) \ + PORT_START /* INPUTS */ \ + SPI_PLAYER( 1, button3 ) \ + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED ) \ + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_8WAY | IPF_PLAYER2 ) \ + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_8WAY | IPF_PLAYER2 ) \ + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_8WAY | IPF_PLAYER2 ) \ + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY | IPF_PLAYER2 ) \ + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 ) \ + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 ) \ + PORT_BIT( 0x4000, IP_ACTIVE_LOW, button3 | IPF_PLAYER2 ) \ + flip + +#define SPI_FLIP_DIP \ + PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Flip_Screen ) ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) + +#define SPI_SYSTEM( coins ) \ + PORT_START /* SYSTEM */ \ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_START1 ) \ + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_START2 ) \ + PORT_BITX( 0x0004, IP_ACTIVE_LOW, IPT_SERVICE, DEF_STR( Service_Mode ), KEYCODE_F2, IP_JOY_NONE ) \ + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_SERVICE1 ) \ + coins \ + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) \ + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED ) \ + PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) + +#define SPI_SYSTEM_UNKNOWN \ + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN ) \ + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN ) + +#define SPI_SYSTEM_COINS \ + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_COIN1 ) \ + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_COIN2 ) + +#define SPI_COIN \ + PORT_START /* COIN (Z80) */ \ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) \ + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) \ + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + +/* JP1 is for SXX2C only */ +#define SPI_JUMPERS \ + PORT_START /* JUMPERS (Z80) */ \ + PORT_DIPNAME( 0x03, 0x03, "JP1" ) /* "Only used when game-board is changed with a new game" in manual */ \ + PORT_DIPSETTING( 0x03, "Update" ) /* "Changing game" in manual */ \ + PORT_DIPSETTING( 0x00, "Normal" ) \ + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + +INPUT_PORTS_START( spi_3button ) + SPI_INPUTS( IPT_BUTTON3, SPI_FLIP_DIP ) + SPI_SYSTEM( SPI_SYSTEM_UNKNOWN ) + SPI_COIN + SPI_JUMPERS +INPUT_PORTS_END + +INPUT_PORTS_START( spi_2button ) + SPI_INPUTS( IPT_UNUSED, SPI_FLIP_DIP ) + SPI_SYSTEM( SPI_SYSTEM_UNKNOWN ) + SPI_COIN + SPI_JUMPERS +INPUT_PORTS_END + +INPUT_PORTS_START( sxx2e ) + SPI_INPUTS( IPT_BUTTON3, SPI_FLIP_DIP ) + SPI_SYSTEM( SPI_SYSTEM_UNKNOWN ) + SPI_COIN +INPUT_PORTS_END + +/* bit 0x40 of SYSTEM: the EEPROM */ +INPUT_PORTS_START( sxx2f ) + SPI_INPUTS( IPT_UNUSED, SPI_FLIP_DIP ) + SPI_SYSTEM( SPI_SYSTEM_UNKNOWN ) + SPI_COIN +INPUT_PORTS_END + +INPUT_PORTS_START( sys386i ) + SPI_INPUTS( IPT_UNUSED, PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNUSED ) ) + SPI_SYSTEM( SPI_SYSTEM_COINS ) + PORT_START /* COIN: unused */ + PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + + +/***************************************************************************** + + Machine + +*****************************************************************************/ + +/* this is a 93C46 but with reset delay */ +static struct EEPROM_interface spi_eeprom_interface = +{ + 6, /* address bits */ + 16, /* data bits */ + "*110", /* read command */ + "*101", /* write command */ + "*111", /* erase command */ + "*10000xxxx", /* lock command */ + "*10011xxxx", /* unlock command */ + 1, /* enable_multi_read */ + 1 /* reset_delay */ +}; + +static INTERRUPT_GEN( spi_interrupt ) +{ + /* where is ack? */ + cpu_set_irq_line_and_vector(0, 0, HOLD_LINE, 0x20); +} + +static void spi_postload(void) +{ + cpu_setbank(5, memory_region(REGION_CPU2) + z80_lastbank * 0x8000); + if (spi_board == SPI_SYS386I) + OKIM6295_set_bank_base(1, oki_bank * 0x40000); +} + +/* the board, the memory banks, the chips and the save states; from every */ +/* DRIVER_INIT, rise: the RISE10 / RISE11 sprite chip instead of the SEI252; */ +/* speedup: the address of the idle loop counter, read by its handler */ +static void spi_common_init(int rise, offs_t speedup) +{ + const struct Memory_ReadAddress32 *map = (const struct Memory_ReadAddress32 *)Machine->drv->cpu[0].memory_read; + + if (map == sys386i_readmem) + spi_board = SPI_SYS386I; + else if (map == sxx2e_readmem) + spi_board = rise ? SPI_SXX2F : SPI_SXX2E; + else + spi_board = rise ? SPI_SXX2C_RISE : SPI_SXX2C; + + spi_mainram = auto_malloc(0x40000); + memset(spi_mainram, 0, 0x40000); + cpu_setbank(1, spi_mainram); + cpu_setbank(2, memory_region(REGION_CPU1)); + cpu_setbank(3, memory_region(REGION_CPU1)); + if (spi_board <= SPI_SXX2C_RISE) + cpu_setbank(4, memory_region(REGION_USER1)); + if (spi_board != SPI_SYS386I) + { + cpu_setbank(5, memory_region(REGION_CPU2)); + cpu_setbank(6, z80_ram); + } + + /* the 386 fetches and reads the ROM and the RAM directly; not the I/O */ + /* at 0x400-0x7ff, and the idle loop counter is read by its handler */ + i386_set_fastmem(0x00200000, 0x003fffff, memory_region(REGION_CPU1), I386_FASTMEM_FETCH | I386_FASTMEM_READ); + i386_set_fastmem(0x00000800, speedup - 1, (UINT8 *)spi_mainram + 0x800, I386_FASTMEM_FETCH | I386_FASTMEM_READ | I386_FASTMEM_WRITE); + i386_set_fastmem(speedup + 4, 0x0003ffff, (UINT8 *)spi_mainram + speedup + 4, I386_FASTMEM_FETCH | I386_FASTMEM_READ | I386_FASTMEM_WRITE); + i386_set_fastmem(speedup, speedup + 3, (UINT8 *)spi_mainram + speedup, I386_FASTMEM_FETCH | I386_FASTMEM_WRITE); + i386_set_fastmem(0x00000000, 0x000003ff, (UINT8 *)spi_mainram, I386_FASTMEM_FETCH | I386_FASTMEM_READ | I386_FASTMEM_WRITE); + i386_set_fastmem(0xffe00000, 0xffffffff, memory_region(REGION_CPU1), I386_FASTMEM_FETCH | I386_FASTMEM_READ); + if (spi_board <= SPI_SXX2C_RISE) + i386_set_fastmem(0x00a00000, 0x013fffff, memory_region(REGION_USER1), I386_FASTMEM_READ); + + if (spi_board <= SPI_SXX2C_RISE) + { + intelfsh_init(0, INTELFSH_INTEL_E28F008SA, NULL); /* Sharp LH28F008 on newer mainboard revision */ + intelfsh_init(1, INTELFSH_INTEL_E28F008SA, NULL); + memcpy(intelfsh_data(0), memory_region(REGION_USER2), 0x100000); + } + if (spi_board <= SPI_SXX2E) + ds2404_init(1995, 1, 1); + if (spi_board >= SPI_SXX2F) + EEPROM_init(&spi_eeprom_interface); + + memset(z80_ram, 0, sizeof(z80_ram)); + memset(spi_fifo, 0, sizeof(spi_fifo)); + z80_prg_transfer_pos = 0; + z80_lastbank = 0; + sb_coin_latch = 0; + oki_bank = 0; + + state_save_register_UINT32("spi", 0, "mainram", spi_mainram, 0x40000 / 4); + state_save_register_UINT8("spi", 0, "z80_ram", z80_ram, sizeof(z80_ram)); + if (spi_board <= SPI_SXX2C_RISE) + state_save_register_UINT8("spi", 0, "z80_rom", memory_region(REGION_CPU2), memory_region_length(REGION_CPU2)); + state_save_register_UINT32("spi", 0, "z80_prg_transfer_pos", &z80_prg_transfer_pos, 1); + state_save_register_UINT8("spi", 0, "z80_lastbank", &z80_lastbank, 1); + state_save_register_UINT8("spi", 0, "sb_coin_latch", &sb_coin_latch, 1); + state_save_register_UINT8("spi", 0, "oki_bank", &oki_bank, 1); + state_save_register_UINT16("spi", 0, "fifo0_data", spi_fifo[0].data, FIFO_SIZE); + state_save_register_UINT32("spi", 0, "fifo0_rpos", &spi_fifo[0].rpos, 1); + state_save_register_UINT32("spi", 0, "fifo0_wpos", &spi_fifo[0].wpos, 1); + state_save_register_UINT32("spi", 0, "fifo0_count", &spi_fifo[0].count, 1); + state_save_register_UINT16("spi", 0, "fifo1_data", spi_fifo[1].data, FIFO_SIZE); + state_save_register_UINT32("spi", 0, "fifo1_rpos", &spi_fifo[1].rpos, 1); + state_save_register_UINT32("spi", 0, "fifo1_wpos", &spi_fifo[1].wpos, 1); + state_save_register_UINT32("spi", 0, "fifo1_count", &spi_fifo[1].count, 1); + state_save_register_func_postload(spi_postload); +} + +static MACHINE_INIT( spi ) +{ + fifo_reset(&spi_fifo[0]); + fifo_reset(&spi_fifo[1]); + z80_lastbank = 0; + sb_coin_latch = 0; + if (spi_board != SPI_SYS386I) + cpu_setbank(5, memory_region(REGION_CPU2)); + + if (spi_board <= SPI_SXX2C_RISE) + { + /* the Z80 waits for its program */ + cpu_set_reset_line(1, ASSERT_LINE); + z80_prg_transfer_pos = 0; + + /* Hack: fix the magic ID byte so users can't "brick" the machine */ + ((UINT8 *)intelfsh_data(0))[0] = memory_region(REGION_USER2)[0]; + } + else if (spi_board == SPI_SYS386I) + { + oki_bank = 0; + OKIM6295_set_bank_base(1, 0); + } +} + +/* the two flash ROMs of the sound samples and the DS2404 */ +static NVRAM_HANDLER( spi ) +{ + if (read_or_write) + { + intelfsh_nvram_save(0, file); + intelfsh_nvram_save(1, file); + ds2404_nvram_save(file); + } + else if (file) + { + intelfsh_nvram_load(0, file); + intelfsh_nvram_load(1, file); + ds2404_nvram_load(file); + } +} + +static NVRAM_HANDLER( sxx2e ) +{ + if (read_or_write) + ds2404_nvram_save(file); + else if (file) + ds2404_nvram_load(file); +} + +/* the EEPROM; no file: from its ROM if there is one, else blank. The */ +/* words of the ROM are little endian as MAME reads them (the checksum of */ +/* rfjets says so), the EEPROM here wants the high byte first */ +static NVRAM_HANDLER( sxx2f ) +{ + if (read_or_write) + EEPROM_save(file); + else if (file) + EEPROM_load(file); + else if (memory_region(REGION_USER3)) + { + UINT8 data[0x80]; + const UINT8 *rom = memory_region(REGION_USER3); + int i; + + for (i = 0; i < 0x80; i += 2) + { + data[i] = rom[i + 1]; + data[i + 1] = rom[i]; + } + EEPROM_set_data(data, 0x80); + } +} + +static MACHINE_DRIVER_START( spi ) + + /* basic machine hardware */ + MDRV_CPU_ADD_TAG("main", I386, 50000000/2) /* AMD or Intel 386DX, 25MHz */ + MDRV_CPU_MEMORY(spi_readmem, spi_writemem) + MDRV_CPU_VBLANK_INT(spi_interrupt, 1) + + MDRV_CPU_ADD_TAG("sound", Z80, 28636363/4) /* Z84C0008PEC, 7.159MHz */ + MDRV_CPU_FLAGS(CPU_AUDIO_CPU) + MDRV_CPU_MEMORY(spi_sound_readmem, spi_sound_writemem) + + /* 28.636363MHz / 4, 448 x 296 pixels */ + MDRV_FRAMES_PER_SECOND(28636363.0 / 4 / 448 / 296) + MDRV_VBLANK_DURATION(3504) /* 56 lines */ + MDRV_INTERLEAVE(222) /* the quantum of MAME, 12000Hz */ + + MDRV_MACHINE_INIT(spi) + MDRV_NVRAM_HANDLER(spi) + + /* video hardware */ + MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER | VIDEO_RGB_DIRECT | VIDEO_NEEDS_6BITS_PER_GUN) + MDRV_SCREEN_SIZE(320, 240) + MDRV_VISIBLE_AREA(0, 319, 0, 239) + MDRV_PALETTE_LENGTH(6144) + + MDRV_VIDEO_START(spi) + MDRV_VIDEO_UPDATE(spi) + + /* sound hardware */ + MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO) + MDRV_SOUND_ADD_TAG("ymf", YMF271, spi_ymf271_interface) +MACHINE_DRIVER_END + +/* the RISE sprites: the same, the board is told by the DRIVER_INIT */ +static MACHINE_DRIVER_START( rdft2 ) + MDRV_IMPORT_FROM(spi) +MACHINE_DRIVER_END + +/* single boards */ + +static MACHINE_DRIVER_START( sxx2e ) + MDRV_IMPORT_FROM(spi) + MDRV_CPU_MODIFY("main") + MDRV_CPU_MEMORY(sxx2e_readmem, sxx2e_writemem) + MDRV_NVRAM_HANDLER(sxx2e) + + /* Single PCBs only output mono sound, SXX2E : unverified */ + MDRV_SOUND_ATTRIBUTES(0) + MDRV_SOUND_REPLACE("ymf", YMF271, sxx2e_ymf271_interface) +MACHINE_DRIVER_END + +static MACHINE_DRIVER_START( sxx2f ) + MDRV_IMPORT_FROM(sxx2e) + MDRV_NVRAM_HANDLER(sxx2f) /* no DS2404, an EEPROM */ + /* Z80 is Z84C0006PCS instead of Z84C0008PEC */ + /* clock is unknown, possibly slower than 7.159MHz */ +MACHINE_DRIVER_END + +static MACHINE_DRIVER_START( sxx2g ) /* clocks differ, but otherwise same hw as sxx2f */ + MDRV_IMPORT_FROM(sxx2f) + MDRV_CPU_REPLACE("main", I386, 28636363) /* AMD AM386DX/DX-40, 28.63636MHz */ + MDRV_CPU_REPLACE("sound", Z80, 4951200) /* Z84C0004PCS, 4.9152MHz (4.9512MHz in MAME) */ + MDRV_SOUND_REPLACE("ymf", YMF271, sxx2g_ymf271_interface) /* 16.384MHz(!) */ +MACHINE_DRIVER_END + +/* SYS386I */ + +static MACHINE_DRIVER_START( sys386i ) + MDRV_IMPORT_FROM(spi) + MDRV_CPU_REPLACE("main", I386, 40000000) /* AMD 386DX, 40MHz */ + MDRV_CPU_MEMORY(sys386i_readmem, sys386i_writemem) + MDRV_CPU_REMOVE("sound") + MDRV_NVRAM_HANDLER(sxx2f) + + MDRV_SOUND_ATTRIBUTES(0) + MDRV_SOUND_REPLACE("ymf", OKIM6295, sys386i_okim6295_interface) +MACHINE_DRIVER_END + + +/***************************************************************************** + + Driver inits: the graphics decryption and the speedups + +*****************************************************************************/ + +#define SPEEDUP(name, address) \ +static READ32_HANDLER( name ) \ +{ \ + offs_t pc = activecpu_get_pc(); \ + if (name##_pc(pc)) cpu_spinuntil_int(); \ + return spi_mainram[address / 4]; \ +} + +static int senkyu_speedup_pc(offs_t pc) { return pc == 0x00305bb2; } +static int senkyua_speedup_pc(offs_t pc) { return pc == 0x0030582e; } +/* batlbalu, batlball */ +static int batlball_speedup_pc(offs_t pc) { return pc == 0x00305996 || pc == 0x003058aa; } +/* viprp1, viprp1s, viprp1ot */ +static int viprp1_speedup_pc(offs_t pc) { return pc == 0x0202769 || pc == 0x02027e9 || pc == 0x02026bd; } +/* viperp1o */ +static int viprp1o_speedup_pc(offs_t pc) { return pc == 0x0201f99; } +/* rdft, rdftj?, rdftau, rdftja?, rdfta / rdftadi / rdftam / rdftit, rdftu, rdftauge */ +static int rdft_speedup_pc(offs_t pc) +{ + return pc == 0x0203f06 || pc == 0x0203f0a || pc == 0x0203f16 || pc == 0x0203f22 || + pc == 0x0203f46 || pc == 0x0203f3a || pc == 0x0203f6e; +} +/* rdft22kc, rdft2 / rdft2j, rdft2us, rdft2a */ +static int rf2_speedup_pc(offs_t pc) { return pc == 0x0203926 || pc == 0x0204372 || pc == 0x020420e || pc == 0x0204366; } +/* rfjet / rfjetu / rfjeta, rfjetj, rfjet2kc, rfjets, rfjetsa */ +static int rfjet_speedup_pc(offs_t pc) +{ + return pc == 0x0206082 || pc == 0x0205f2e || pc == 0x0205c9e || pc == 0x0205b39 || pc == 0x0205bd9; +} + +SPEEDUP( senkyu_speedup, 0x0018cb4 ) +SPEEDUP( senkyua_speedup, 0x0018c9c ) +SPEEDUP( batlball_speedup, 0x0018db4 ) +SPEEDUP( viprp1_speedup, 0x001e2e0 ) +SPEEDUP( viprp1o_speedup, 0x001d49c ) +SPEEDUP( rdft_speedup, 0x00298d0 ) +SPEEDUP( rf2_speedup, 0x00282ac ) +SPEEDUP( rfjet_speedup, 0x002894c ) + +static void init_sei252(offs_t speedup) +{ + seibuspi_text_decrypt(memory_region(REGION_GFX1)); + seibuspi_bg_decrypt(memory_region(REGION_GFX2), memory_region_length(REGION_GFX2)); + seibuspi_sprite_decrypt(memory_region(REGION_GFX3), 0x400000); + spi_common_init(0, speedup); +} + +static DRIVER_INIT( senkyu ) +{ + install_mem_read32_handler(0, 0x0018cb4, 0x0018cb7, senkyu_speedup); + init_sei252(0x0018cb4); +} + +static DRIVER_INIT( senkyua ) +{ + install_mem_read32_handler(0, 0x0018c9c, 0x0018c9f, senkyua_speedup); + init_sei252(0x0018c9c); +} + +static DRIVER_INIT( batlball ) +{ + install_mem_read32_handler(0, 0x0018db4, 0x0018db7, batlball_speedup); + init_sei252(0x0018db4); +} + +static DRIVER_INIT( viprp1 ) +{ + install_mem_read32_handler(0, 0x001e2e0, 0x001e2e3, viprp1_speedup); + init_sei252(0x001e2e0); +} + +static DRIVER_INIT( viprp1o ) +{ + install_mem_read32_handler(0, 0x001d49c, 0x001d49f, viprp1o_speedup); + init_sei252(0x001d49c); +} + +static DRIVER_INIT( rdft ) +{ + install_mem_read32_handler(0, 0x00298d0, 0x00298d3, rdft_speedup); + init_sei252(0x00298d0); +} + +static DRIVER_INIT( rdft2 ) +{ + install_mem_read32_handler(0, 0x00282ac, 0x00282af, rf2_speedup); + seibuspi_rdft2_text_decrypt(memory_region(REGION_GFX1)); + seibuspi_rdft2_bg_decrypt(memory_region(REGION_GFX2), memory_region_length(REGION_GFX2)); + seibuspi_rise10_sprite_decrypt(memory_region(REGION_GFX3), 0x600000); + spi_common_init(1, 0x00282ac); +} + +static DRIVER_INIT( rfjet ) +{ + install_mem_read32_handler(0, 0x002894c, 0x002894f, rfjet_speedup); + seibuspi_rfjet_text_decrypt(memory_region(REGION_GFX1)); + seibuspi_rfjet_bg_decrypt(memory_region(REGION_GFX2), memory_region_length(REGION_GFX2)); + seibuspi_rise11_sprite_decrypt_rfjet(memory_region(REGION_GFX3), 0x800000); + spi_common_init(1, 0x002894c); +} + +static DRIVER_INIT( rdft22kc ) { init_rdft2(); } +static DRIVER_INIT( rfjet2kc ) { init_rfjet(); } + + +/*****************************************************************************/ + +#define ROM_LOAD24_BYTE(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_SKIP(2)) +#define ROM_LOAD24_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(1) | ROM_REVERSE) + +/* SPI games */ + +ROM_START( senkyu ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("fb_1.211", 0x100000, 0x40000, CRC(20a3e5db) SHA1(f1109aeceac7993abc9093d09429718ffc292c77) ) + ROM_LOAD32_BYTE("fb_2.212", 0x100001, 0x40000, CRC(38e90619) SHA1(451ab5f4a5935bb779f9c245c1c4358e80d93c15) ) + ROM_LOAD32_BYTE("fb_3.210", 0x100002, 0x40000, CRC(226f0429) SHA1(69d0fe6671278d7fe215e455bb50abf631cdb484) ) + ROM_LOAD32_BYTE("fb_4.29", 0x100003, 0x40000, CRC(b46d66b7) SHA1(1acd0fea9384e1488b44661e0c99b9672a3f9803) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( senkyua ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("1.bin", 0x100000, 0x40000, CRC(6102c3fb) SHA1(4a55b41d916768f9601513db973b82077bca47c5) ) + ROM_LOAD32_BYTE("2.bin", 0x100001, 0x40000, CRC(d5b8ce46) SHA1(f6e4b8f51146179efb52ecb2b72fdeaee10b7282) ) + ROM_LOAD32_BYTE("3.bin", 0x100002, 0x40000, CRC(e27ceccd) SHA1(3d6b8e97e89939c72d1a5a4a3856025b5f548645) ) + ROM_LOAD32_BYTE("4.bin", 0x100003, 0x40000, CRC(7c6d4549) SHA1(efc6920a2e518afe849fb6fe191e7cd0bc483be5) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( batlball ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("1.211", 0x100000, 0x40000, CRC(d4e48f89) SHA1(10e43a9ff3f6f169de6352280a8a06e7f482271a) ) + ROM_LOAD32_BYTE("2.212", 0x100001, 0x40000, CRC(3077720b) SHA1(b65c3d02ac75eb56e0c5dc1bf6bb6a4e445a41cf) ) + ROM_LOAD32_BYTE("3.210", 0x100002, 0x40000, CRC(520d31e1) SHA1(998ae968113ab5b2891044187d93793903c13452) ) + ROM_LOAD32_BYTE("4.029", 0x100003, 0x40000, CRC(22419b78) SHA1(67475a654d4ad94e5dfda88cbe2f9c1b5ba6d2cc) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( batlballo ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1a.211", 0x100000, 0x40000, CRC(90340e8c) SHA1(303d3c5ffc1a64e1e4aa614105119d9d7768f516) ) + ROM_LOAD32_BYTE("seibu_2a.212", 0x100001, 0x40000, CRC(db655d3e) SHA1(bfd873e0d0daf3759778c76fe72fcf96e84250a4) ) + ROM_LOAD32_BYTE("seibu_3a.210", 0x100002, 0x40000, CRC(659a54a2) SHA1(a6c024e42b104a6198829f0f75baaa294fe9de6c) ) + ROM_LOAD32_BYTE("seibu_4a.029", 0x100003, 0x40000, CRC(51183421) SHA1(d97da1693e429cb7a061f08274070eb3e6966ec0) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu_6.413", 0x000000, 0x20000, CRC(338556f9) SHA1(dfab6e1562dd9c373aa094a3791ecd4cd3c9b6f5) ) + ROM_LOAD24_BYTE("seibu_5.48", 0x000002, 0x10000, CRC(6ccfb72e) SHA1(825b917ecd8495de23d55d2d2902d9d7c54ce4ed) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("seibu_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( batlballu ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("sen1.bin", 0x100000, 0x40000, CRC(13849bf0) SHA1(ffa829a8b8a05a8fbaf883a30759f2ad8071a85b) ) + ROM_LOAD32_BYTE("sen2.bin", 0x100001, 0x40000, CRC(2ae5f7e2) SHA1(cef9ddea8b1d21f20a48c2523c9420c1800720c8) ) + ROM_LOAD32_BYTE("sen3.bin", 0x100002, 0x40000, CRC(98e6f19f) SHA1(433f8463e63bba32730d3c098354f8c95257df3f) ) + ROM_LOAD32_BYTE("sen4.bin", 0x100003, 0x40000, CRC(1343ec56) SHA1(8ecc8d7b425ff6512ffa969a7f26423fa50ad258) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( batlballa ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("senkyua1.bin", 0x100000, 0x40000, CRC(ec3c4d4d) SHA1(6c57b8fbb77ce1615850842d06c054e88e240eef) ) + ROM_LOAD32_BYTE("2.212", 0x100001, 0x40000, CRC(3077720b) SHA1(b65c3d02ac75eb56e0c5dc1bf6bb6a4e445a41cf) ) + ROM_LOAD32_BYTE("3.210", 0x100002, 0x40000, CRC(520d31e1) SHA1(998ae968113ab5b2891044187d93793903c13452) ) + ROM_LOAD32_BYTE("4.029", 0x100003, 0x40000, CRC(22419b78) SHA1(67475a654d4ad94e5dfda88cbe2f9c1b5ba6d2cc) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region22.u1053", 0x000000, 0x100000, CRC(5fee8413) SHA1(6d6a62fa01293b4ba4b349a39820d024add6ea22) ) +ROM_END + +ROM_START( batlballe ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("1_10-16", 0x100000, 0x40000, CRC(6b1baa07) SHA1(29b8f4016e9bffdcdb6ec405cd443ca0a80de5d5) ) + ROM_LOAD32_BYTE("2_10-16", 0x100001, 0x40000, CRC(3c890639) SHA1(968c4a5efc5ebbe4e4cc81f834c286c02596c24e) ) + ROM_LOAD32_BYTE("3_10-16", 0x100002, 0x40000, CRC(8c30180e) SHA1(47b99b04e2e74f1ee5095aed3f45aba66cd3da3f) ) + ROM_LOAD32_BYTE("4_10-16", 0x100003, 0x40000, CRC(048c7aaa) SHA1(5eca2cdf4e6f077988509c3c42c86408b21ffbf1) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region22.u1053", 0x000000, 0x100000, CRC(5fee8413) SHA1(6d6a62fa01293b4ba4b349a39820d024add6ea22) ) +ROM_END + +ROM_START( batlballpt ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("senkyu_prog0_171195.u0211", 0x100000, 0x40000, CRC(dcc227b6) SHA1(10d72ebdd218887521226c82a61c2cdebcd9af99) ) + ROM_LOAD32_BYTE("2.u0212", 0x100001, 0x40000, CRC(03ab203f) SHA1(de5771883624440a9842b109b764b52811facfad) ) + ROM_LOAD32_BYTE("3.u0210", 0x100002, 0x40000, CRC(9eb9c8b4) SHA1(fc4f8feac3840776f842d03d86b37a669bba4f12) ) + ROM_LOAD32_BYTE("4.u029", 0x100003, 0x40000, CRC(c37ae2a5) SHA1(ee33f7baf852ef36b4f7f71a08d82acf1e7460b8) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("fb_6.413", 0x000000, 0x20000, CRC(b57115c9) SHA1(eb95f416f522032ca949bfb6348f1ff824101f2d) ) + ROM_LOAD24_BYTE("fb_5.48", 0x000002, 0x10000, CRC(440a9ae3) SHA1(3f57e6da91f0dac2d816c873759f1e1d3259caf1) ) + + ROM_REGION( 0x300000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("fb_bg-1d.415", 0x000000, 0x200000, CRC(eae7a1fc) SHA1(26d8a9f4e554848977ec1f6a8aad8751b558a8d4) ) + ROM_LOAD24_BYTE("fb_bg-1p.410", 0x000002, 0x100000, CRC(b46e774e) SHA1(00b6c1d0b0ea37f4354acab543b270c0bf45896d) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("fb_obj-1.322", 0x000000, 0x400000, CRC(29f86f68) SHA1(1afe809ce00a25f8b27543e4188edc3e3e604951) ) + ROM_LOAD("fb_obj-2.324", 0x400000, 0x400000, CRC(c9e3130b) SHA1(12b5d5363142e8efb3b7fc44289c0afffa5011c6) ) + ROM_LOAD("fb_obj-3.323", 0x800000, 0x400000, CRC(f6c3bc49) SHA1(d0eb9c6aa3954d94e3a442a48e0fe6cc279f5513) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("fb_pcm-1.215", 0x000000, 0x080000, CRC(1d83891c) SHA1(09502437562275c14c0f3a0e62b19e91bedb4693) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + ROM_LOAD32_BYTE("fb_7.216", 0x800000, 0x080000, CRC(874d7b59) SHA1(0236753636c9a818780b23f5f506697b9f6d93c7) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region96.u1053", 0x000000, 0x100000, CRC(a0ebae75) SHA1(31f7955a529a4e2492b530e54878ed7a13f49c94) ) +ROM_END + +ROM_START( viprp1 ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu1.211", 0x000000, 0x80000, CRC(e5caf4ff) SHA1(7c87a4e8e8dacfb7cc0be8f778352bce2801e59b) ) + ROM_LOAD32_BYTE("seibu2.212", 0x000001, 0x80000, CRC(688a998e) SHA1(0c48374b6800cd00e3ee96c0fb12119a680b091d) ) + ROM_LOAD32_BYTE("seibu3.210", 0x000002, 0x80000, CRC(990fa76a) SHA1(7619a631d6f83b3677eb47f984aff684e9518d6d) ) + ROM_LOAD32_BYTE("seibu4.29", 0x000003, 0x80000, CRC(13e3e343) SHA1(aac0c7450059847f53b5081e4abf26303a50f999) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_regionbe.u1053", 0x000000, 0x100000, CRC(a4c181d0) SHA1(0aeea4cac4030f60ee77d62deca6b67c318c0866) ) +ROM_END + +ROM_START( viprp1k ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu1.211", 0x000000, 0x80000, CRC(5495c930) SHA1(056237965aefa4c0ea7782e0ee5ba1b58a045d7a) ) + ROM_LOAD32_BYTE("seibu2.212", 0x000001, 0x80000, CRC(e0ad22ae) SHA1(1911d17f0b462a9bada9efee85e531f2445e4ac6) ) + ROM_LOAD32_BYTE("seibu3.210", 0x000002, 0x80000, CRC(db7bcb90) SHA1(45f0a44e24d7b4b996d833e579f405bcf7584563) ) + ROM_LOAD32_BYTE("seibu4.29", 0x000003, 0x80000, CRC(c6188bf9) SHA1(746a205c428a080c36d0daf1d4f6b2b0f8efb977) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(1a35f2d8) SHA1(cd9b140f144a8c72756e18913eaef121963be341) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(e88bf049) SHA1(62f35840dc90b505118ed81ac0d75397a689783b) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region24.u1053", 0x000000, 0x100000, CRC(72a33dc4) SHA1(65a52f576ca4d240418fedd9a4922edcd6c0c8d1) ) +ROM_END + +ROM_START( viprp1u ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu1.u0211", 0x000000, 0x80000, CRC(3f412b80) SHA1(ccffce101d20971278c0f6c5f4efcf3ab687aba6) ) /* New version, "=U.S.A=" seems part of title */ + ROM_LOAD32_BYTE("seibu2.u0212", 0x000001, 0x80000, CRC(2e6c2376) SHA1(b6e660dc7c89cf565c6e055683e84ffcf8179709) ) + ROM_LOAD32_BYTE("seibu3.u0210", 0x000002, 0x80000, CRC(c38f7b4e) SHA1(d5bf2c7f2f6c812c65005facfd40ac6d3b61f29d) ) + ROM_LOAD32_BYTE("seibu4.u029", 0x000003, 0x80000, CRC(523cbef3) SHA1(5d15261b8fb108e0ba4dfd14d259984ef81ce877) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( viprp1ua ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibus_1", 0x000000, 0x80000, CRC(882c299c) SHA1(36309b99764c684bd17eb512e661bafd3f3298e2) ) /* New version, "=U.S.A=" seems part of title */ + ROM_LOAD32_BYTE("seibus_2", 0x000001, 0x80000, CRC(6ce586e9) SHA1(511731996638666cbe81a1d97affce855e255bf7) ) + ROM_LOAD32_BYTE("seibus_3", 0x000002, 0x80000, CRC(f9dd9128) SHA1(ff7460699424de9e9d953343c42e0ef0fa1f0e30) ) + ROM_LOAD32_BYTE("seibus_4", 0x000003, 0x80000, CRC(cb06440c) SHA1(c73647fb72c1579f05298fd884d8aeb3765bfff4) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( viprp1j ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("v_1-n.211", 0x000000, 0x80000, CRC(55f10b72) SHA1(2a1ebaa969f346bf3659ed8b0f469dce9eaf3b4b) ) + ROM_LOAD32_BYTE("v_2-n.212", 0x000001, 0x80000, CRC(0f888283) SHA1(7e5ac81279b9c7a06f07cb8ae76938cdd5c9beee) ) + ROM_LOAD32_BYTE("v_3-n.210", 0x000002, 0x80000, CRC(842434ac) SHA1(982d219c1d329122789c552208db2f4aaa4af7e4) ) + ROM_LOAD32_BYTE("v_4-n.29", 0x000003, 0x80000, CRC(a3948824) SHA1(fe076951427126c8b7fe81be84ecf0699597225b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( viprp1s ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("viper_prg0.bin", 0x000000, 0x80000, CRC(ed9980b8) SHA1(bc324e9121ee1e55237bd91681f163ec7790de4c) ) + ROM_LOAD32_BYTE("viper_prg1.bin", 0x000001, 0x80000, CRC(9d4d3486) SHA1(ded6fa32b973046e50c40c40c446590b5f6d0b76) ) + ROM_LOAD32_BYTE("viper_prg2.bin", 0x000002, 0x80000, CRC(d7ea460b) SHA1(aed10adacd073f7d2b35f12ba4b7876e5c99d142) ) + ROM_LOAD32_BYTE("viper_prg3.bin", 0x000003, 0x80000, CRC(ca6df094) SHA1(921eec141ce2d449047172fa9cdf39d459b5cc7b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu5.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("seibu6.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region9c.u1053", 0x000000, 0x100000, CRC(d73d640c) SHA1(61a99af2a153de9d53e28872a2493e2ba797a325) ) +ROM_END + +ROM_START( viprp1h ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("viper_prg0_010995.u0211", 0x000000, 0x80000, CRC(e42fcc93) SHA1(5b2848a1da0e5d37e04ac646e67bbb84678c0292) ) /* same code as viprp1s, different region byte value */ + ROM_LOAD32_BYTE("viper_prg1_010995.u0212", 0x000001, 0x80000, CRC(9d4d3486) SHA1(ded6fa32b973046e50c40c40c446590b5f6d0b76) ) + ROM_LOAD32_BYTE("viper_prg2_010995.u0210", 0x000002, 0x80000, CRC(d7ea460b) SHA1(aed10adacd073f7d2b35f12ba4b7876e5c99d142) ) + ROM_LOAD32_BYTE("viper_prg3_010995.u029", 0x000003, 0x80000, CRC(ca6df094) SHA1(921eec141ce2d449047172fa9cdf39d459b5cc7b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("viper_fix_010995.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("viper_fixp_010995.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region90.u1053", 0x000000, 0x100000, CRC(8da617a2) SHA1(29c6ee05ed1c9a428a89d625b72692296c38424b) ) +ROM_END + +ROM_START( viprp1t ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("viper_prg0_010995.u0211", 0x000000, 0x80000, CRC(f998dcf7) SHA1(c2dc876e4dc51062caf3d0df7c3c9cc9a5201760) ) /* same code as viprp1s and viprp1h, different region byte value */ + ROM_LOAD32_BYTE("viper_prg1_010995.u0212", 0x000001, 0x80000, CRC(9d4d3486) SHA1(ded6fa32b973046e50c40c40c446590b5f6d0b76) ) + ROM_LOAD32_BYTE("viper_prg2_010995.u0210", 0x000002, 0x80000, CRC(d7ea460b) SHA1(aed10adacd073f7d2b35f12ba4b7876e5c99d142) ) + ROM_LOAD32_BYTE("viper_prg3_010995.u029", 0x000003, 0x80000, CRC(ca6df094) SHA1(921eec141ce2d449047172fa9cdf39d459b5cc7b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("viper_fix_010995.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("viper_fixp_010995.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( viprp1pt ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("viper_prg0_010995.u0211", 0x000000, 0x80000, CRC(0d4c69a6) SHA1(d46706419c280838050a44cc27d6e469c021f295) ) /* same code as viprp1s, viprp1h and viprp1t , different region byte value */ + ROM_LOAD32_BYTE("viper_prg1_010995.u0212", 0x000001, 0x80000, CRC(9d4d3486) SHA1(ded6fa32b973046e50c40c40c446590b5f6d0b76) ) + ROM_LOAD32_BYTE("viper_prg2_010995.u0210", 0x000002, 0x80000, CRC(d7ea460b) SHA1(aed10adacd073f7d2b35f12ba4b7876e5c99d142) ) + ROM_LOAD32_BYTE("viper_prg3_010995.u029", 0x000003, 0x80000, CRC(ca6df094) SHA1(921eec141ce2d449047172fa9cdf39d459b5cc7b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("viper_fix_010995.u0413", 0x000000, 0x20000, CRC(5ece677c) SHA1(b782cf3296f866f79fafa69ff719211c9d4026df) ) + ROM_LOAD24_BYTE("viper_fixp_010995.u048", 0x000002, 0x10000, CRC(44844ef8) SHA1(bcbe24d2ffb64f9165ba4ab7de27f44b99b5ff5a) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region96.u1053", 0x000000, 0x100000, CRC(a0ebae75) SHA1(31f7955a529a4e2492b530e54878ed7a13f49c94) ) +ROM_END + +ROM_START( viprp1ot ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("ov1.bin", 0x000000, 0x80000, CRC(cbad0e28) SHA1(fbc9b3b243ae0d556f41e8bef5f09489bb9e302b) ) + ROM_LOAD32_BYTE("ov2.bin", 0x000001, 0x80000, CRC(0e2bbcb5) SHA1(5e53d60357fb0f9efa441261fac79e153eb35f3d) ) + ROM_LOAD32_BYTE("ov3.bin", 0x000002, 0x80000, CRC(0e86686b) SHA1(0af207ea77ef378364d80d20ecbfba2f043f2405) ) + ROM_LOAD32_BYTE("ov4.bin", 0x000003, 0x80000, CRC(9d7dd325) SHA1(550a8b5ed60e7ac50c40ec3eaa2cd6462be4a619) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("v_5-o.413", 0x000000, 0x20000, CRC(6d863acc) SHA1(3e3e14f51b9394b24d7cbf562f1cfffc9ec2216d) ) + ROM_LOAD24_BYTE("v_6-o.48", 0x000002, 0x10000, CRC(fe7cb8f7) SHA1(55c7ab977c3666c8770deb62718d535673ffd4f8) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( viprp1oj ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("v_1-o.211", 0x000000, 0x80000, CRC(4430be64) SHA1(96501a490042c289060d8510f6f79fbf64f79c1a) ) + ROM_LOAD32_BYTE("v_2-o.212", 0x000001, 0x80000, CRC(ffbd88f7) SHA1(cd7f291117dd18bd80fb1130eb87936ff7517ee3) ) + ROM_LOAD32_BYTE("v_3-o.210", 0x000002, 0x80000, CRC(6146db39) SHA1(04e68bfff320a3ffcb47686fa012a038538adc1a) ) + ROM_LOAD32_BYTE("v_4-o.29", 0x000003, 0x80000, CRC(dc8dd2b6) SHA1(20970706240c38c54084b4ae24b7ad23b31aa3de) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("v_5-o.413", 0x000000, 0x20000, CRC(6d863acc) SHA1(3e3e14f51b9394b24d7cbf562f1cfffc9ec2216d) ) + ROM_LOAD24_BYTE("v_6-o.48", 0x000002, 0x10000, CRC(fe7cb8f7) SHA1(55c7ab977c3666c8770deb62718d535673ffd4f8) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( viprp1hk ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1", 0x000000, 0x80000, CRC(283ba7b7) SHA1(28122e04b72f1163c69f3f845f6a493fdb6ed652) ) /* Old Version, "=HONG KONG=" seems part of title */ + ROM_LOAD32_BYTE("seibu_2", 0x000001, 0x80000, CRC(2c4db249) SHA1(a6372c9a3cde5f262ec5ef446945f6d3ad506e88) ) + ROM_LOAD32_BYTE("seibu_3", 0x000002, 0x80000, CRC(91989503) SHA1(8c215fac200cc693396dbd57e0939e7efe883342) ) + ROM_LOAD32_BYTE("seibu_4", 0x000003, 0x80000, CRC(12c9582d) SHA1(a79e26514e5ab8703a7a8c3ac39b359cfa4117c1) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("seibu_5", 0x000000, 0x20000, CRC(80920fed) SHA1(b35ed080925f6d0a0b6d2d1ab4fa919f625b1e6a) ) /* Different from both "new" & "old" versions */ + ROM_LOAD24_BYTE("seibu_6", 0x000002, 0x10000, CRC(e71a8722) SHA1(3e0133fe1f85058ca6d9ac59d731f342c6b50e92) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("v_bg-11.415", 0x000000, 0x200000, CRC(6fc96736) SHA1(12df47d8af2c1febc1bce5bcf3218766447885bd) ) + ROM_LOAD24_BYTE("v_bg-12.415", 0x000002, 0x100000, CRC(d3c7281c) SHA1(340bca1f31486609b3c34dd7830362a216ff648e) ) + ROM_LOAD24_WORD("v_bg-21.410", 0x300000, 0x100000, CRC(d65b4318) SHA1(6522970d95ffa7fa2f32e0b5b4f0eb69e0286b36) ) + ROM_LOAD24_BYTE("v_bg-22.416", 0x300002, 0x080000, CRC(24a0a23a) SHA1(0b0330717620e3f3274a25845d9edaf8023b9db2) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("v_obj-1.322", 0x000000, 0x400000, CRC(3be5b631) SHA1(fd1064428d28ca166a9267b968c0ba846cfed656) ) + ROM_LOAD("v_obj-2.324", 0x400000, 0x400000, CRC(924153b4) SHA1(db5dadcfb4cd5e6efe9d995085936ce4f4eb4254) ) + ROM_LOAD("v_obj-3.323", 0x800000, 0x400000, CRC(e9fb9062) SHA1(18e97b4c5cced2b529e6e72d8041c6f78fcec76e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_BYTE("v_pcm.215", 0x000000, 0x080000, CRC(e3111b60) SHA1(f7a7747f29c392876e43efcb4e6c0741454082f2) ) + ROM_CONTINUE( 0x400000, 0x080000 ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region22.u1053", 0x000000, 0x100000, CRC(5fee8413) SHA1(6d6a62fa01293b4ba4b349a39820d024add6ea22) ) +ROM_END + +ROM_START( rdft ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("raiden-fi_prg0_121196.u0211", 0x000000, 0x80000, CRC(adcb5dbc) SHA1(3831becd1e052d81dd00ee098ee630fe35164df8) ) + ROM_LOAD32_BYTE("raiden-fi_prg1_121196.u0212", 0x000001, 0x80000, CRC(60c5b92e) SHA1(ca67f97f9e7d8a21667dc59e7d390dff91179b08) ) + ROM_LOAD32_BYTE("raiden-fi_prg2_121196.u0210", 0x000002, 0x80000, CRC(44b86db5) SHA1(bb05c6d27af86084cd3e17a189826c836f229c8b) ) + ROM_LOAD32_BYTE("raiden-fi_prg3_121196.u029", 0x000003, 0x80000, CRC(e70727ce) SHA1(2e4e896d50cf086e682054cb2e9c223af04cd0cb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( rdftj ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("gd_1.211", 0x000000, 0x80000, CRC(f6b2cbdc) SHA1(040c4ff961c8be388c8279b06b777d528c2acc1b) ) + ROM_LOAD32_BYTE("gd_2.212", 0x000001, 0x80000, CRC(1982f812) SHA1(4f12fc3fd7f7a4beda4d29cc81e3a58d255e441f) ) + ROM_LOAD32_BYTE("gd_3.210", 0x000002, 0x80000, CRC(b0f59f44) SHA1(d44fe074ddab35cd0190535cd9fbd7f9e49312a4) ) + ROM_LOAD32_BYTE("gd_4.29", 0x000003, 0x80000, CRC(cd8705bd) SHA1(b19a1486d6b899a134d7b518863ddc8f07967e8b) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdftja ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rf1.bin", 0x000000, 0x80000, CRC(46861b75) SHA1(079c589c490d49f7ec97a7e68c5b6e7e37872827) ) + ROM_LOAD32_BYTE("rf2.bin", 0x000001, 0x80000, CRC(6388ed11) SHA1(aebbccfb0f704cdceb45ea71216275dd83880e15) ) + ROM_LOAD32_BYTE("rf3.bin", 0x000002, 0x80000, CRC(beafcd24) SHA1(2dbc47ecef6f898a371a841df2c72151da9c5a8d) ) + ROM_LOAD32_BYTE("rf4.bin", 0x000003, 0x80000, CRC(5236f45f) SHA1(8b05d977d3d07796007a00a52d2396475dc2f7dc) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdftu ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rdftu_gd_1.211", 0x000000, 0x80000, CRC(47810c48) SHA1(8dc8848d3e7467ea887c50fd5675fba2cc741121) ) + ROM_LOAD32_BYTE("rdftu_gd_2.212", 0x000001, 0x80000, CRC(13911750) SHA1(8899accb059ed84170924750bb39ae7383ebd959) ) + ROM_LOAD32_BYTE("rdftu_gd_3.210", 0x000002, 0x80000, CRC(10761b03) SHA1(e67db2e7c2176987419158fc4cee00fd9b99d03f) ) + ROM_LOAD32_BYTE("rdftu_gd_4.29", 0x000003, 0x80000, CRC(e5a3f01d) SHA1(5ca338f85a020d43d2618f88e798a076d13a5c7f) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( rdftauge ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu.1.u0211", 0x000000, 0x80000, CRC(3e79da3c) SHA1(8d33da1dadb791ff97b353532ca647eb462c2ae4) ) + ROM_LOAD32_BYTE("seibu.2.u0212", 0x000001, 0x80000, CRC(a6fbf98c) SHA1(ce0f5f6f1f5656dbac0a6b977795026276c8fa86) ) + ROM_LOAD32_BYTE("seibu.3.u0210", 0x000002, 0x80000, CRC(ad31cc17) SHA1(12b735519cad190887cdbc6680d879f791ab3726) ) + ROM_LOAD32_BYTE("seibu.4.u029", 0x000003, 0x80000, CRC(756d99ae) SHA1(38c234acf3e8204a29a9adb077328d37d97cfd6d) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0416", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region9e.u1053", 0x000000, 0x100000, CRC(7ad6f17e) SHA1(9a2cc77a4f86c00208f739bd53aca4f55adf7ea7) ) +ROM_END + +ROM_START( rdftua ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x080000, CRC(ddbadc30) SHA1(d419847db8b7f4ca6f161bfa309314eafeea8b40) ) // socket is silkscreened on pcb PRG0 - sldh + ROM_LOAD32_BYTE("raiden-f_prg2.u0212", 0x000001, 0x080000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_WORD("raiden-f_prg34.u0219", 0x000002, 0x100000, CRC(63f01d17) SHA1(74dbd0417b974583da87fc6c7a081b03fd4e16b8) ) // socket is silkscreened on pcb PRG23 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("raiden-f_fix.u0425", 0x000000, 0x20000, CRC(2be2936b) SHA1(9e719f7328a52af220b6f084c1e0990ca6e2d533) ) // socket is silkscreened on pcb FIX01 + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) // pads are silkscreened on pcb OBJ3 + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("raiden-f_pcm2.u0217", 0x000000, 0x100000, CRC(3f8d4a48) SHA1(30664a2908daaeaee58f7e157516b522c952e48d) ) // pads are silkscreened SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + /* SOUND1 socket is unpopulated */ + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( rdftjb ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x080000, CRC(b70afcc2) SHA1(70ac545a9fc30df310254997674878fbc2c2d718) ) // socket is silkscreened on pcb PRG0 - sldh + ROM_LOAD32_BYTE("raiden-f_prg2.u0212", 0x000001, 0x080000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_WORD("raiden-f_prg34.u0219", 0x000002, 0x100000, CRC(63f01d17) SHA1(74dbd0417b974583da87fc6c7a081b03fd4e16b8) ) // socket is silkscreened on pcb PRG23 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("raiden-f_fix.u0425", 0x000000, 0x20000, CRC(2be2936b) SHA1(9e719f7328a52af220b6f084c1e0990ca6e2d533) ) // socket is silkscreened on pcb FIX01 + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) // pads are silkscreened on pcb OBJ3 + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("raiden-f_pcm2.u0217", 0x000000, 0x100000, CRC(3f8d4a48) SHA1(30664a2908daaeaee58f7e157516b522c952e48d) ) // pads are silkscreened SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + /* SOUND1 socket is unpopulated */ + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdftau ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("1.u0211", 0x000000, 0x80000, CRC(6339c60d) SHA1(871d5bc9fc695651ceb6fcfdab32084320fe239d) ) + ROM_LOAD32_BYTE("2.u0212", 0x000001, 0x80000, CRC(a88bda02) SHA1(27dc720d28f56cf443a4eb0bbaaf4bf3b194056d) ) + ROM_LOAD32_BYTE("3.u0210", 0x000002, 0x80000, CRC(a73e337e) SHA1(93323875c676f38eca3298fcf4a34911db2d78a8) ) + ROM_LOAD32_BYTE("4.u029", 0x000003, 0x80000, CRC(8cc628f0) SHA1(7534eae8a1ea461adad483002b3cecf132e0e325) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region9e.u1053", 0x000000, 0x100000, CRC(7ad6f17e) SHA1(9a2cc77a4f86c00208f739bd53aca4f55adf7ea7) ) +ROM_END + +ROM_START( rdftam ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x080000, CRC(156d8db0) SHA1(93662b3ee494e37a56428a7aa3dad7a957835950) ) // socket is silkscreened on pcb PRG0 - sldh + ROM_LOAD32_BYTE("raiden-f_prg2.u0212", 0x000001, 0x080000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_WORD("raiden-f_prg34.u0219", 0x000002, 0x100000, CRC(63f01d17) SHA1(74dbd0417b974583da87fc6c7a081b03fd4e16b8) ) // socket is silkscreened on pcb PRG23 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("raiden-f_fix.u0425", 0x000000, 0x20000, CRC(2be2936b) SHA1(9e719f7328a52af220b6f084c1e0990ca6e2d533) ) // socket is silkscreened on pcb FIX01 + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) // pads are silkscreened on pcb OBJ3 + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("raiden-f_pcm2.u0217", 0x000000, 0x100000, CRC(3f8d4a48) SHA1(30664a2908daaeaee58f7e157516b522c952e48d) ) // pads are silkscreened SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + /* SOUND1 socket is unpopulated */ + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region22.u1053", 0x000000, 0x100000, CRC(5fee8413) SHA1(6d6a62fa01293b4ba4b349a39820d024add6ea22) ) +ROM_END + +ROM_START( rdftadi ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x080000, CRC(fc0e2885) SHA1(79621155d992d504e993bd3ee0d6ff3903bd5415) ) // socket is silkscreened on pcb PRG0 - sldh + ROM_LOAD32_BYTE("raiden-f_prg2.u0212", 0x000001, 0x080000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_WORD("raiden-f_prg34.u0219", 0x000002, 0x100000, CRC(63f01d17) SHA1(74dbd0417b974583da87fc6c7a081b03fd4e16b8) ) // socket is silkscreened on pcb PRG23 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("raiden-f_fix.u0425", 0x000000, 0x20000, CRC(2be2936b) SHA1(9e719f7328a52af220b6f084c1e0990ca6e2d533) ) // socket is silkscreened on pcb FIX01 + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) // pads are silkscreened on pcb OBJ3 + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("raiden-f_pcm2.u0217", 0x000000, 0x100000, CRC(3f8d4a48) SHA1(30664a2908daaeaee58f7e157516b522c952e48d) ) // pads are silkscreened SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + /* SOUND1 socket is unpopulated */ + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region24.u1053", 0x000000, 0x100000, CRC(72a33dc4) SHA1(65a52f576ca4d240418fedd9a4922edcd6c0c8d1) ) +ROM_END + +ROM_START( rdfta ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(c3bb2e58) SHA1(399ac4b387ba38f5fdad5c4172b2d3baeafd8773) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) + ROM_LOAD32_BYTE("seibu_3.u0210", 0x000002, 0x80000, CRC(47fc3c96) SHA1(7378f8caa847f89f235b5be6779118721076873b) ) + ROM_LOAD32_BYTE("seibu_4.u029", 0x000003, 0x80000, CRC(271bdd4b) SHA1(0a805568cbd6a9c18bdb755a41972ff6bba9e6eb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region82.u1053", 0x000000, 0x100000, CRC(4f463a87) SHA1(0e27904745da61a3ba7c48c5b4c7d45989bbd05b) ) +ROM_END + +ROM_START( rdftgb ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(2403035f) SHA1(9763cca3864d6127050e1507b572efa68f664b3c) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) + ROM_LOAD32_BYTE("seibu_3.u0210", 0x000002, 0x80000, CRC(47fc3c96) SHA1(7378f8caa847f89f235b5be6779118721076873b) ) + ROM_LOAD32_BYTE("seibu_4.u029", 0x000003, 0x80000, CRC(271bdd4b) SHA1(0a805568cbd6a9c18bdb755a41972ff6bba9e6eb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region8c.u1053", 0x000000, 0x100000, CRC(b836dc5b) SHA1(80400429970f8997978ee723d3067a39ebc0e126) ) +ROM_END + +ROM_START( rdftgr ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(ca0d6273) SHA1(f761d68ec9a49d66d9f3adc663663f716cdd3735) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) + ROM_LOAD32_BYTE("seibu_3.u0210", 0x000002, 0x80000, CRC(47fc3c96) SHA1(7378f8caa847f89f235b5be6779118721076873b) ) + ROM_LOAD32_BYTE("seibu_4.u029", 0x000003, 0x80000, CRC(271bdd4b) SHA1(0a805568cbd6a9c18bdb755a41972ff6bba9e6eb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region8e.u1053", 0x000000, 0x100000, CRC(15dd4929) SHA1(e0f68e9e4d775d70e85ea6b5dd29beeb0e940b1c) ) +ROM_END + +ROM_START( rdftit ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(de0c3e3c) SHA1(b00225bad282e46b5825608f76eea6670bfe5527) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) + ROM_LOAD32_BYTE("seibu_3.u0210", 0x000002, 0x80000, CRC(47fc3c96) SHA1(7378f8caa847f89f235b5be6779118721076873b) ) + ROM_LOAD32_BYTE("seibu_4.u029", 0x000003, 0x80000, CRC(271bdd4b) SHA1(0a805568cbd6a9c18bdb755a41972ff6bba9e6eb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // some mask ROMs might be labeled GD BG1-D ect + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region92.u1053", 0x000000, 0x100000, CRC(204d82d0) SHA1(444f4aefa27d8f5d1a2f7f08f826ea84b0ccbd02) ) +ROM_END + +ROM_START( rdftadia ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(fc0e2885) SHA1(79621155d992d504e993bd3ee0d6ff3903bd5415) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) + ROM_LOAD32_BYTE("seibu_3.u0210", 0x000002, 0x80000, CRC(47fc3c96) SHA1(7378f8caa847f89f235b5be6779118721076873b) ) + ROM_LOAD32_BYTE("seibu_4.u029", 0x000003, 0x80000, CRC(271bdd4b) SHA1(0a805568cbd6a9c18bdb755a41972ff6bba9e6eb) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) + ROM_LOAD24_BYTE("seibu_5.u0423", 0x000000, 0x10000, CRC(8f8d4e14) SHA1(06c803975767ae98f40ba7ac5764a5bc8baa3a30) ) + ROM_LOAD24_BYTE("seibu_6.u0424", 0x000001, 0x10000, CRC(6ac64968) SHA1(ec395205c24c4f864a1f805bb0d4641562d4faa9) ) + ROM_LOAD24_BYTE("seibu_7.u048", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0415", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0410", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0424", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u049", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) + ROM_LOAD32_WORD("gun_dogs_pcm.u0217", 0x000000, 0x100000, CRC(31253ad7) SHA1(c81c8d50f8f287f5cbfaec77b30d969b01ce11a9) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu_8.u0216", 0x800000, 0x080000, CRC(f88cb6e4) SHA1(fb35b41307b490d5d08e4b8a70f8ff4ce2ca8105) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region24.u1053", 0x000000, 0x100000, CRC(72a33dc4) SHA1(65a52f576ca4d240418fedd9a4922edcd6c0c8d1) ) +ROM_END + +ROM_START( rdft2 ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.tun", 0x000000, 0x80000, CRC(3cb3fdca) SHA1(4b472dfd65c7bbbcb92a295aa73b0fa70581455b) ) + ROM_LOAD32_BYTE("prg1.bin", 0x000001, 0x80000, CRC(cab55d88) SHA1(246e13880d34b6c7c3f4ab5e18fa8a0547c03d9d) ) + ROM_LOAD32_BYTE("prg2.bin", 0x000002, 0x80000, CRC(83758b0e) SHA1(63adb2d09e7bd7dba47a55b3b579d543dfb553e3) ) + ROM_LOAD32_BYTE("prg3.bin", 0x000003, 0x80000, CRC(084fb5e4) SHA1(588bfe091662b88f02f528181a2f1d9c67c7b280) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( rdft2j ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.sei", 0x000000, 0x80000, CRC(a60c4e7c) SHA1(7789b029d0ac084c7e5e662a7168edaed8f11633) ) + ROM_LOAD32_BYTE("prg1.bin", 0x000001, 0x80000, CRC(cab55d88) SHA1(246e13880d34b6c7c3f4ab5e18fa8a0547c03d9d) ) + ROM_LOAD32_BYTE("prg2.bin", 0x000002, 0x80000, CRC(83758b0e) SHA1(63adb2d09e7bd7dba47a55b3b579d543dfb553e3) ) + ROM_LOAD32_BYTE("prg3.bin", 0x000003, 0x80000, CRC(084fb5e4) SHA1(588bfe091662b88f02f528181a2f1d9c67c7b280) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdft2a ) + // The SUB8 board is also capable of having two 23C8100 roms at U0223 and U0219 for PRG instead of the four roms below. + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program, all are 27C040 */ + ROM_LOAD32_BYTE("seibu__1.u0211", 0x000000, 0x80000, CRC(046b3f0e) SHA1(033898f658d6007f891828835734422d4af36321) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_BYTE("seibu__2.u0212", 0x000001, 0x80000, CRC(cab55d88) SHA1(246e13880d34b6c7c3f4ab5e18fa8a0547c03d9d) ) // socket is silkscreened on pcb PRG2 + ROM_LOAD32_BYTE("seibu__3.u0221", 0x000002, 0x80000, CRC(83758b0e) SHA1(63adb2d09e7bd7dba47a55b3b579d543dfb553e3) ) // socket is silkscreened on pcb PRG3 + ROM_LOAD32_BYTE("seibu__4.u0220", 0x000003, 0x80000, CRC(084fb5e4) SHA1(588bfe091662b88f02f528181a2f1d9c67c7b280) ) // socket is silkscreened on pcb PRG4 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms - all are 27C512 */ + ROM_LOAD24_BYTE("seibu__5.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) // socket is silkscreened on pcb FIX0 + ROM_LOAD24_BYTE("seibu__6.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) // socket is silkscreened on pcb FIX1 + ROM_LOAD24_BYTE("seibu__7.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms - half are MX semiconductor MX23C3210MC, half are some sort of 23C1610 equivalent with no visible manufacturer name */ + ROM_LOAD24_WORD("raiden-f2bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("raiden-f2__bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("raiden-f2bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("raiden-f2__bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites - all are paired MX semconductor MX23C3210TC and MX23C1610TC mask roms */ + ROM_LOAD("raiden-f2obj-3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) // pads are silkscreened on pcb OBJ3 + ROM_LOAD("raiden-f2obj-6.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) // pads are silkscreened on pcb OBJ3B + ROM_LOAD("raiden-f2obj-2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("raiden-f2obj-5.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) // pads are silkscreened on pcb OBJ2B + ROM_LOAD("raiden-f2obj-1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("raiden-f2obj-4.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) // pads are silkscreened on pcb OBJ1B + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms - sound0 is some sort of 23C1610 equivalent with no visible manufacturer name, sound1 is a 27C040 */ + ROM_LOAD32_WORD("raiden-f2__pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) // pads are silkscreened on pcb SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu__8.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) // socket is silkscreened on pcb SOUND1 + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region22.u1053", 0x000000, 0x100000, CRC(5fee8413) SHA1(6d6a62fa01293b4ba4b349a39820d024add6ea22) ) +ROM_END + +ROM_START( rdft2s ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program, all are 27C040 */ + ROM_LOAD32_BYTE("seibu__1.u0211", 0x000000, 0x80000, CRC(28b2a185) SHA1(a42adc166992629e96b1ad2fa0859643689fb5c4) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_BYTE("seibu__2.u0212", 0x000001, 0x80000, CRC(cab55d88) SHA1(246e13880d34b6c7c3f4ab5e18fa8a0547c03d9d) ) // socket is silkscreened on pcb PRG2 + ROM_LOAD32_BYTE("seibu__3.u0221", 0x000002, 0x80000, CRC(83758b0e) SHA1(63adb2d09e7bd7dba47a55b3b579d543dfb553e3) ) // socket is silkscreened on pcb PRG3 + ROM_LOAD32_BYTE("seibu__4.u0220", 0x000003, 0x80000, CRC(084fb5e4) SHA1(588bfe091662b88f02f528181a2f1d9c67c7b280) ) // socket is silkscreened on pcb PRG4 + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms - all are 27C512 */ + ROM_LOAD24_BYTE("seibu__5.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) // socket is silkscreened on pcb FIX0 + ROM_LOAD24_BYTE("seibu__6.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) // socket is silkscreened on pcb FIX1 + ROM_LOAD24_BYTE("seibu__7.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) // socket is silkscreened on pcb FIXP + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms - half are MX semiconductor MX23C3210MC, half are some sort of 23C1610 equivalent with no visible manufacturer name */ + ROM_LOAD24_WORD("raiden-f2bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("raiden-f2__bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("raiden-f2bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("raiden-f2__bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites - all are paired MX semconductor MX23C3210TC and MX23C1610TC mask roms */ + ROM_LOAD("raiden-f2obj-3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) // pads are silkscreened on pcb OBJ3 + ROM_LOAD("raiden-f2obj-6.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) // pads are silkscreened on pcb OBJ3B + ROM_LOAD("raiden-f2obj-2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("raiden-f2obj-5.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) // pads are silkscreened on pcb OBJ2B + ROM_LOAD("raiden-f2obj-1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("raiden-f2obj-4.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) // pads are silkscreened on pcb OBJ1B + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms - sound0 is some sort of 23C1610 equivalent with no visible manufacturer name, sound1 is a 27C040 */ + ROM_LOAD32_WORD("raiden-f2__pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) // pads are silkscreened on pcb SOUND0 + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu__8.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) // socket is silkscreened on pcb SOUND1 + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region9c.u1053", 0x000000, 0x100000, CRC(d73d640c) SHA1(61a99af2a153de9d53e28872a2493e2ba797a325) ) +ROM_END + +ROM_START( rdft2ja ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rf2.1", 0x000000, 0x80000, CRC(391d5057) SHA1(a1849142cbf7344ac1279781597e27b3b8ae6127) ) + ROM_LOAD32_BYTE("rf2_2.bin", 0x000001, 0x80000, CRC(ec73a767) SHA1(83f3905afe49401793c0ea0193cb31d3ba1e1739) ) + ROM_LOAD32_BYTE("rf2_3.bin", 0x000002, 0x80000, CRC(e66243b2) SHA1(54e67af37a4586fd1afc79085ed433d599e1bb87) ) + ROM_LOAD32_BYTE("rf2_4.bin", 0x000003, 0x80000, CRC(92b7b73e) SHA1(128649b2a6a0616113bd0f9846fb6cf814ae326d) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rf2_5.bin", 0x000001, 0x10000, CRC(377cac2f) SHA1(f7c9323d79b77f6c8c02ba2c6cdca127d6e5cb5c) ) + ROM_LOAD24_BYTE("rf2_6.bin", 0x000000, 0x10000, CRC(42bd5372) SHA1(c38df85b25070db9640eac541f71c0511bab0c98) ) + ROM_LOAD24_BYTE("rf2_7.bin", 0x000002, 0x10000, CRC(1efaac7e) SHA1(8252af56dcb7a6306dc3422070176778e3c511c2) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdft2aa ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rf2_1.bin", 0x000000, 0x80000, CRC(72198410) SHA1(ca4bc858f6bf247a343b0fdae1d1a3cdabc4a3c3) ) + ROM_LOAD32_BYTE("rf2_2.bin", 0x000001, 0x80000, CRC(ec73a767) SHA1(83f3905afe49401793c0ea0193cb31d3ba1e1739) ) + ROM_LOAD32_BYTE("rf2_3.bin", 0x000002, 0x80000, CRC(e66243b2) SHA1(54e67af37a4586fd1afc79085ed433d599e1bb87) ) + ROM_LOAD32_BYTE("rf2_4.bin", 0x000003, 0x80000, CRC(92b7b73e) SHA1(128649b2a6a0616113bd0f9846fb6cf814ae326d) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rf2_5.bin", 0x000001, 0x10000, CRC(377cac2f) SHA1(f7c9323d79b77f6c8c02ba2c6cdca127d6e5cb5c) ) + ROM_LOAD24_BYTE("rf2_6.bin", 0x000000, 0x10000, CRC(42bd5372) SHA1(c38df85b25070db9640eac541f71c0511bab0c98) ) + ROM_LOAD24_BYTE("rf2_7.bin", 0x000002, 0x10000, CRC(1efaac7e) SHA1(8252af56dcb7a6306dc3422070176778e3c511c2) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region24.u1053", 0x000000, 0x100000, CRC(72a33dc4) SHA1(65a52f576ca4d240418fedd9a4922edcd6c0c8d1) ) +ROM_END + +ROM_START( rdft2it ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu1.bin",0x000000, 0x80000, CRC(501b92a9) SHA1(3e1c5cc63906ec7b97a3478557ec2638c515d726) ) + ROM_LOAD32_BYTE("seibu2.bin",0x000001, 0x80000, CRC(ec73a767) SHA1(83f3905afe49401793c0ea0193cb31d3ba1e1739) ) + ROM_LOAD32_BYTE("seibu3.bin",0x000002, 0x80000, CRC(e66243b2) SHA1(54e67af37a4586fd1afc79085ed433d599e1bb87) ) + ROM_LOAD32_BYTE("seibu4.bin",0x000003, 0x80000, CRC(92b7b73e) SHA1(128649b2a6a0616113bd0f9846fb6cf814ae326d) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("seibu5.bin", 0x000001, 0x10000, CRC(377cac2f) SHA1(f7c9323d79b77f6c8c02ba2c6cdca127d6e5cb5c) ) + ROM_LOAD24_BYTE("seibu6.bin", 0x000000, 0x10000, CRC(42bd5372) SHA1(c38df85b25070db9640eac541f71c0511bab0c98) ) + ROM_LOAD24_BYTE("seibu7.bin", 0x000002, 0x10000, CRC(1efaac7e) SHA1(8252af56dcb7a6306dc3422070176778e3c511c2) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("seibu8.bin", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region92.u1053", 0x000000, 0x100000, CRC(204d82d0) SHA1(444f4aefa27d8f5d1a2f7f08f826ea84b0ccbd02) ) +ROM_END + +ROM_START( rdft2jb ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.rom", 0x000000, 0x80000, CRC(fc42cab8) SHA1(2e33fc8d77fdc4ee58e93fc191d12f2fe9cc3c65) ) + ROM_LOAD32_BYTE("prg1.rom", 0x000001, 0x80000, CRC(a0f09dc5) SHA1(e8ad20be1f04752b0884571384d4490813ed82d9) ) + ROM_LOAD32_BYTE("prg2.rom", 0x000002, 0x80000, CRC(368580e0) SHA1(184036a0cbddbf79b62e388b93cb93b885faee88) ) + ROM_LOAD32_BYTE("prg3.rom", 0x000003, 0x80000, CRC(7ad45c01) SHA1(d782057658dd000c1cf0a4726a6ed821e6f2be67) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rf2_5.bin", 0x000001, 0x10000, CRC(377cac2f) SHA1(f7c9323d79b77f6c8c02ba2c6cdca127d6e5cb5c) ) + ROM_LOAD24_BYTE("rf2_6.bin", 0x000000, 0x10000, CRC(42bd5372) SHA1(c38df85b25070db9640eac541f71c0511bab0c98) ) + ROM_LOAD24_BYTE("rf2_7.bin", 0x000002, 0x10000, CRC(1efaac7e) SHA1(8252af56dcb7a6306dc3422070176778e3c511c2) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdft2jc ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0211", 0x000000, 0x80000, CRC(36b6407c) SHA1(b3f5bb3c582aca71e0c7d9da5951b30c7389cc24) ) + ROM_LOAD32_BYTE("seibu_2.u0212", 0x000001, 0x80000, CRC(65ee556e) SHA1(13311850aabba9fc373adfd5cd590c114505933f) ) + ROM_LOAD32_BYTE("seibu_3.u0221", 0x000002, 0x80000, CRC(d2458358) SHA1(18a9cfee77a6a09584bc3fb0073c822d12de5bf1) ) + ROM_LOAD32_BYTE("seibu_4.u0220", 0x000003, 0x80000, CRC(5c4412f9) SHA1(c72603bee3ce14f40d4bf5e3ae3f041b923edd57) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rdft2t ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0", 0x000000, 0x80000, CRC(7e8c3acc) SHA1(63f4f9f7df7fa028737d9f7dfae96795cde58541) ) + ROM_LOAD32_BYTE("prg1", 0x000001, 0x80000, CRC(22cb5b68) SHA1(35f86ad7771fe9aaac3904ed34a96d0cc10ef21c) ) + ROM_LOAD32_BYTE("prg2", 0x000002, 0x80000, CRC(3eca68dd) SHA1(98378654adf055d72ae685f90e36643c9d6419d7) ) + ROM_LOAD32_BYTE("prg3", 0x000003, 0x80000, CRC(4124daa4) SHA1(42f225c0328df59ffeacc215d37010f825bf507e) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rf2_5.bin", 0x000001, 0x10000, CRC(377cac2f) SHA1(f7c9323d79b77f6c8c02ba2c6cdca127d6e5cb5c) ) + ROM_LOAD24_BYTE("rf2_6.bin", 0x000000, 0x10000, CRC(42bd5372) SHA1(c38df85b25070db9640eac541f71c0511bab0c98) ) + ROM_LOAD24_BYTE("rf2_7.bin", 0x000002, 0x10000, CRC(1efaac7e) SHA1(8252af56dcb7a6306dc3422070176778e3c511c2) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region20.u1053", 0x000000, 0x100000, CRC(f2051161) SHA1(45cbd5fd9ae0ca0c5c3450bca5f6806ddce3c56f) ) +ROM_END + +ROM_START( rdft2u ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("1.bin", 0x000000, 0x80000, CRC(b7d6c866) SHA1(eefe63dfc641c3904dd150a10ffeb68137068725) ) + ROM_LOAD32_BYTE("2.bin", 0x000001, 0x80000, CRC(ff7747c5) SHA1(7481d0484001ff7367af56e8ea99f985cce405f2) ) + ROM_LOAD32_BYTE("3.bin", 0x000002, 0x80000, CRC(86e3d1a8) SHA1(2757cfda57c82dd0f66427caf54eb1f40e85740d) ) + ROM_LOAD32_BYTE("4.bin", 0x000003, 0x80000, CRC(2e409a76) SHA1(cf90aa14a07b5aa861f6f7cc9b1968171e532557) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u0434", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u0433", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u0431", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u0432", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u0429", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u0430", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm.u0217", 0x000000, 0x100000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(b7bd3703) SHA1(6427a7e6de10d6743d6e64b984a1d1c647f5643a) ) + + ROM_REGION( 0x0345, REGION_USER4, ROMREGION_DISPOSE ) /* pals */ + ROM_LOAD("rm81.u0529.bin", 0x0000, 0x0117, CRC(acd55c8e) SHA1(b965e828fecd61b836aca337637e53d7360d9dc4) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm82.u0330.bin", 0x0117, 0x0117, CRC(64c71423) SHA1(1da3502bec0c843b7198d1d9ab60f9fd4b110a8e) ) // AMD PALCE16V8H-15SC/4 + ROM_LOAD("rm83.u0331.bin", 0x022e, 0x0117, CRC(6e10d66b) SHA1(995d2a0da680ec19ee253098c91a4780dd8403c6) ) // AMD PALCE16V8H-15SC/4 + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( rfjet ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.u0211", 0x000000, 0x80000, CRC(e5a3b304) SHA1(f7285f9c69c589fcc71082dc0b9225fdccec855f) ) + ROM_LOAD32_BYTE("prg1.u0212", 0x000001, 0x80000, CRC(395e6da7) SHA1(736f777cb1b6bf5541832b8ea89594738ca6d829) ) + ROM_LOAD32_BYTE("prg2.u0221", 0x000002, 0x80000, CRC(82f7a57e) SHA1(5300015e25d5f2f82eda3ed54bc105d645518498) ) + ROM_LOAD32_BYTE("prg3.u0220", 0x000003, 0x80000, CRC(cbdf100d) SHA1(c9efd11103429f7f36c1652cadb5384d925cb767) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0543", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0544", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0545", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0546", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u0442", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u0443", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0444", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm-d.u0227", 0x000000, 0x100000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(d4fc3da1) SHA1(a03bd97e36a21d27a834b9691b27a7eb7ac51ff2) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region80.u1053", 0x000000, 0x100000, CRC(e2adaff5) SHA1(9297afaf78209724515d8f78de8cee7bc7cb796b) ) +ROM_END + +ROM_START( rfjetu ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0u.u0211", 0x000000, 0x80000, CRC(15ac2040) SHA1(7309a9dd9c91fef0e761dcf8639f421ce7abc97f) ) + ROM_LOAD32_BYTE("prg1.u0212", 0x000001, 0x80000, CRC(395e6da7) SHA1(736f777cb1b6bf5541832b8ea89594738ca6d829) ) + ROM_LOAD32_BYTE("prg2.u0221", 0x000002, 0x80000, CRC(82f7a57e) SHA1(5300015e25d5f2f82eda3ed54bc105d645518498) ) + ROM_LOAD32_BYTE("prg3.u0220", 0x000003, 0x80000, CRC(cbdf100d) SHA1(c9efd11103429f7f36c1652cadb5384d925cb767) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0543", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0544", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0545", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0546", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u0442", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u0443", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0444", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm-d.u0227", 0x000000, 0x100000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(d4fc3da1) SHA1(a03bd97e36a21d27a834b9691b27a7eb7ac51ff2) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region10.u1053", 0x000000, 0x100000, CRC(4319d998) SHA1(a064ce647453a9b3bccf7f1d6d0d52b5a72e09dd) ) +ROM_END + +ROM_START( rfjetj ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.bin", 0x000000, 0x80000, CRC(d82fb71f) SHA1(63a458fd007c353f4fae54a4882f5c565fe1efa4) ) + ROM_LOAD32_BYTE("prg1.bin", 0x000001, 0x80000, CRC(7e21c669) SHA1(731852e5925dccc9d0d1ae4bcafa238f157f4079) ) + ROM_LOAD32_BYTE("prg2.bin", 0x000002, 0x80000, CRC(2f402d55) SHA1(d0d852239abb6f4d73e263de5544fc0893e7a7ab) ) + ROM_LOAD32_BYTE("prg3.bin", 0x000003, 0x80000, CRC(d619e2ad) SHA1(9dbff1babf62c3c5478a84d2a82a428de5949154) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0543", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0544", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0545", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0546", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u0442", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u0443", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0444", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm-d.u0227", 0x000000, 0x100000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(d4fc3da1) SHA1(a03bd97e36a21d27a834b9691b27a7eb7ac51ff2) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region01.u1053", 0x000000, 0x100000, CRC(7ae7ab76) SHA1(a2b196f470bf64af94002fc4e2640fadad00418f) ) +ROM_END + +ROM_START( rfjeta ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0a.u0211", 0x000000, 0x80000, CRC(3418d4f5) SHA1(f8766d7b3708a196de417ee757787220b2a9ced1) ) + ROM_LOAD32_BYTE("prg1.u0212", 0x000001, 0x80000, CRC(395e6da7) SHA1(736f777cb1b6bf5541832b8ea89594738ca6d829) ) + ROM_LOAD32_BYTE("prg2.u0221", 0x000002, 0x80000, CRC(82f7a57e) SHA1(5300015e25d5f2f82eda3ed54bc105d645518498) ) + ROM_LOAD32_BYTE("prg3.u0220", 0x000003, 0x80000, CRC(cbdf100d) SHA1(c9efd11103429f7f36c1652cadb5384d925cb767) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0543", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0544", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0545", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0546", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u0442", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u0443", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0444", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm-d.u0227", 0x000000, 0x100000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(d4fc3da1) SHA1(a03bd97e36a21d27a834b9691b27a7eb7ac51ff2) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region24.u1053", 0x000000, 0x100000, CRC(72a33dc4) SHA1(65a52f576ca4d240418fedd9a4922edcd6c0c8d1) ) +ROM_END + +ROM_START( rfjett ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE( "prg0.u0211", 0x000000, 0x080000, CRC(a4734579) SHA1(dfbd8e2a3178c7cfd7bd3698999f14bc80f5212f) ) + ROM_LOAD32_BYTE( "prg1.u0212", 0x000001, 0x080000, CRC(5e4ad3a4) SHA1(ff66e16f48978b88b298c78e21309208ccb3ff15) ) + ROM_LOAD32_BYTE( "prg2.u0221", 0x000002, 0x080000, CRC(21c9942e) SHA1(ededa05a4b5dae2dec5c4409f22e9a66d2c8e98e) ) + ROM_LOAD32_BYTE( "prg3.u0220", 0x000003, 0x080000, CRC(ea3657f4) SHA1(2291e31243af7d2e79ae727d9b5484e8d49cc7d9) ) + + ROM_REGION( 0x40000, REGION_CPU2, ROMREGION_ERASE00 ) /* 256K RAM, ROM from Z80 point-of-view */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0543", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0544", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0545", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0546", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u0442", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u0443", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0444", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION32_LE( 0xa00000, REGION_USER1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD32_WORD("pcm-d.u0227", 0x000000, 0x100000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_CONTINUE( 0x400000, 0x100000 ) + ROM_LOAD32_BYTE("sound1.u0222", 0x800000, 0x080000, CRC(d4fc3da1) SHA1(a03bd97e36a21d27a834b9691b27a7eb7ac51ff2) ) + + ROM_REGION( 0x100000, REGION_USER2, 0 ) /* on SPI motherboard */ + ROM_LOAD("flash0_blank_region20.u1053", 0x000000, 0x100000, CRC(f2051161) SHA1(45cbd5fd9ae0ca0c5c3450bca5f6806ddce3c56f) ) +ROM_END + +ROM_START( rdfts ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("seibu_1.u0259", 0x000000, 0x080000, CRC(e278dddd) SHA1(fe54a0d0f9e8596268f7f37e85d71c5c2d8b2846) ) // socket is silkscreened on pcb PRG0 + ROM_LOAD32_BYTE("raiden-f_prg2.u0258", 0x000001, 0x080000, CRC(58ccb10c) SHA1(0cce4057bfada78121d9586574b98d46cdd7dd46) ) // socket is silkscreened on pcb PRG1 + ROM_LOAD32_WORD("raiden-f_prg34.u0262", 0x000002, 0x100000, CRC(63f01d17) SHA1(74dbd0417b974583da87fc6c7a081b03fd4e16b8) ) // socket is silkscreened on pcb PRG23 + + ROM_REGION( 0x40000, REGION_CPU2, 0 ) /* 256K ROM for the Z80 */ + ROM_LOAD("seibu_zprg.u1139", 0x000000, 0x20000, CRC(c1fda3e8) SHA1(c1d3a7ba0601a80534ec32249de71d33a828a162) ) // pads are silkscreened ZPRG + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_WORD("raiden-f_fix.u0535", 0x000000, 0x20000, CRC(2be2936b) SHA1(9e719f7328a52af220b6f084c1e0990ca6e2d533) ) // socket is silkscreened on pcb FIX01 + ROM_LOAD24_BYTE("seibu_fix2.u0528", 0x000002, 0x10000, CRC(4d87e1ea) SHA1(3230e9b643fad773e61ab8ce09c0cd7d4d0558e3) ) // socket is silkscreened on pcb FIX2 + + ROM_REGION( 0x600000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("gun_dogs_bg1-d.u0526", 0x000000, 0x200000, CRC(6a68054c) SHA1(5cbfc4ac90045f1401c2dda7a51936558c9de07e) ) // pads are silkscreened on pcb BG12 + ROM_LOAD24_BYTE("gun_dogs_bg1-p.u0531", 0x000002, 0x100000, CRC(3400794a) SHA1(719808f7442bac612cefd7b7fffcd665e6337ad0) ) // pads are silkscreened on pcb BG12P + ROM_LOAD24_WORD("gun_dogs_bg2-d.u0534", 0x300000, 0x200000, CRC(61cd2991) SHA1(bb608e3948bf9ea35b5e1615d2ba6858d029dcbe) ) // pads are silkscreened on pcb BG3 + ROM_LOAD24_BYTE("gun_dogs_bg2-p.u0530", 0x300002, 0x100000, CRC(502d5799) SHA1(c3a0e1a4f5a7b35572ae1ff31315da4ed08aa2fe) ) // pads are silkscreened on pcb BG3P + + ROM_REGION( 0xc00000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("gun_dogs_obj-1.u0322", 0x000000, 0x400000, CRC(59d86c99) SHA1(d3c9241e7b51fe21f8351051b063f91dc69bf905) ) // pads are silkscreened on pcb OBJ1 + ROM_LOAD("gun_dogs_obj-2.u0324", 0x400000, 0x400000, CRC(1ceb0b6f) SHA1(97225a9b3e7be18080aa52f6570af2cce8f25c06) ) // pads are silkscreened on pcb OBJ2 + ROM_LOAD("gun_dogs_obj-3.u0323", 0x800000, 0x400000, CRC(36e93234) SHA1(51917a80b7da5c32a9434a1076fc2916d62e6a3e) ) // pads are silkscreened on pcb OBJ3 + + ROM_REGION( 0x200000, REGION_SOUND1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD("raiden-f_pcm2.u0975", 0x000000, 0x200000, CRC(3f8d4a48) SHA1(30664a2908daaeaee58f7e157516b522c952e48d) ) // pads are silkscreened SOUND0 + /* SOUND1 socket is unpopulated */ +ROM_END + +ROM_START( rdft2us ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("prg0.u0259", 0x000000, 0x80000, CRC(ff3eeec1) SHA1(88c1741e4936db9a5b13e562061b0f1cc6fa6b36) ) + ROM_LOAD32_BYTE("prg1.u0258", 0x000001, 0x80000, CRC(e2cf77d6) SHA1(173cc0e304c9dadea4ed0812ebb64c6c83549912) ) + ROM_LOAD32_BYTE("prg2.u0265", 0x000002, 0x80000, CRC(cae87e1f) SHA1(e460aad693eb2702ae11f758b11d37f852d00790) ) + ROM_LOAD32_BYTE("prg3.u0264", 0x000003, 0x80000, CRC(83f4fb5f) SHA1(73f58daa1aae0c4978db409cedd736fb49b15f1c) ) + + ROM_REGION( 0x40000, REGION_CPU2, 0 ) /* 256K ROM for the Z80 */ + ROM_LOAD("zprg.u091", 0x000000, 0x20000, CRC(cc543c4f) SHA1(6e5c93fd3d21c594571b071d4a830211e1f162b2) ) + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.u0524", 0x000001, 0x10000, CRC(6fdf4cf6) SHA1(7e9d4a49e829dfdc373c0f5acfbe8c7a91ac115b) ) + ROM_LOAD24_BYTE("fix1.u0518", 0x000000, 0x10000, CRC(69b7899b) SHA1(d3cacd4ef4d2c95d803403101beb9d4be75fae61) ) + ROM_LOAD24_BYTE("fixp.u0514", 0x000002, 0x10000, CRC(99a5fece) SHA1(44ae95d650ed6e00202d3438f5f91a5e52e319cb) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.u0538", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.u075", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj3b.u078", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.u074", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj2b.u077", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.u073", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj1b.u076", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION( 0x280000, REGION_SOUND1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD("pcm.u0103", 0x000000, 0x200000, CRC(2edc30b5) SHA1(c25d690d633657fc3687636b9070f36bd305ae06) ) + ROM_LOAD("sound1.u0107", 0x200000, 0x080000, CRC(20384b0e) SHA1(9c5d725418543df740f9145974ed6ffbbabee1d0) ) /* Different sound1 than SPI carts */ +ROM_END + +ROM_START( rfjets ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rfj-06.u0259", 0x000000, 0x80000, CRC(c835aa7a) SHA1(291eada97ceb907dfea15688ce6055e63b3aa675) ) /* PRG0 */ + ROM_LOAD32_BYTE("rfj-07.u0258", 0x000001, 0x80000, CRC(3b6ca1ca) SHA1(9db019c0ddecfb58e2be5c345d78352f700035bf) ) /* PRG1 */ + ROM_LOAD32_BYTE("rfj-08.u0265", 0x000002, 0x80000, CRC(1f5dd06c) SHA1(6f5a8c9035971a470212cd0a89b94181011602c3) ) /* PRG2 */ + ROM_LOAD32_BYTE("rfj-09.u0264", 0x000003, 0x80000, CRC(cc71c402) SHA1(b040e600744e7b3f52de0fa852ce3ae08ae49985) ) /* PRG3 */ + + ROM_REGION( 0x40000, REGION_CPU2, 0 ) /* 256K ROM for the Z80 */ + ROM_LOAD("rfj-05.u091", 0x000000, 0x40000, CRC(a55e8799) SHA1(5d4ca9ae920ab54e23ee3b1b33db72711e744516) ) /* ZPRG */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rfj-01.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) /* FIX0 */ + ROM_LOAD24_BYTE("rfj-02.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) /* FIX1 */ + ROM_LOAD24_BYTE("rfj-03.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) /* FIXP */ + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0545", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u073", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u074", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u075", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION( 0x280000, REGION_SOUND1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD("pcm-d.u0103", 0x000000, 0x200000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_LOAD("rfj-04.u0107", 0x200000, 0x080000, CRC(c050da03) SHA1(1002dac51a3a4932c4f0074c1f3d97a597d98755) ) /* SOUND1 */ + + ROM_REGION16_BE( 0x80, REGION_USER3, 0 ) + ROM_LOAD16_WORD( "st93c46.bin", 0x0000, 0x0080, CRC(8fe8063b) SHA1(afb0141580e1b2bd149092a9cc9e8b4072b1ef10) ) +ROM_END + +ROM_START( rfjetsa ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_BYTE("rfj-06.u0259", 0x000000, 0x80000, CRC(b0c8d47e) SHA1(1dde30d25f9e8eaa301343ae1d272b5c0044bc1f) ) /* PRG0 */ + ROM_LOAD32_BYTE("rfj-07.u0258", 0x000001, 0x80000, CRC(17189b39) SHA1(6471170ae770d762e15f1503ef9a6832c202da6c) ) /* PRG1 */ + ROM_LOAD32_BYTE("rfj-08.u0265", 0x000002, 0x80000, CRC(ab6d724b) SHA1(ef7e42b1bf649a354fe22b0edd00475ced4151be) ) /* PRG2 */ + ROM_LOAD32_BYTE("rfj-09.u0264", 0x000003, 0x80000, CRC(b119a67c) SHA1(4fa7dd0e86a3f7c6efa6ae9cf72991b652c877b9) ) /* PRG3 */ + + ROM_REGION( 0x40000, REGION_CPU2, 0 ) /* 256K ROM for the Z80 */ + ROM_LOAD("rfj-05.u091", 0x000000, 0x40000, CRC(a55e8799) SHA1(5d4ca9ae920ab54e23ee3b1b33db72711e744516) ) /* ZPRG */ + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rfj-01.u0524", 0x000001, 0x10000, CRC(8bc080be) SHA1(ad296fb98242c963072346a8de289e704b445ad4) ) /* FIX0 */ + ROM_LOAD24_BYTE("rfj-02.u0518", 0x000000, 0x10000, CRC(bded85e7) SHA1(ccb8c438ce6b9a742e3ab15be970b1e636783626) ) /* FIX1 */ + ROM_LOAD24_BYTE("rfj-03.u0514", 0x000002, 0x10000, CRC(015d0748) SHA1(b1e8eaeba63a7914f1dc27d7e3ca5d0b6db202ed) ) /* FIXP */ + + ROM_REGION( 0x900000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0545", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u073", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u074", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u075", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION( 0x280000, REGION_SOUND1, ROMREGION_ERASE00 ) /* sound roms */ + ROM_LOAD("pcm-d.u0103", 0x000000, 0x200000, CRC(8ee3ff45) SHA1(2801b23495866c91c8f8bebd37d5fcae7a625838) ) + ROM_LOAD("rfj-04.u0107", 0x200000, 0x080000, CRC(c050da03) SHA1(1002dac51a3a4932c4f0074c1f3d97a597d98755) ) /* SOUND1 */ +ROM_END + +ROM_START( rdft22kc ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_WORD("prg0-1.267", 0x000000, 0x100000, CRC(0d7d6eb8) SHA1(3a71e1e0ba5bb500dc026debbb6189723c0c2890) ) + ROM_LOAD32_WORD("prg2-3.266", 0x000002, 0x100000, CRC(ead53e69) SHA1(b0e2e06f403317054ecb48d2747034424245f129) ) + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("fix0.524", 0x000001, 0x10000, CRC(ed11d043) SHA1(fd3a5a33aa4d795941d64c0d23f9d6f8222843e3) ) + ROM_LOAD24_BYTE("fix1.518", 0x000000, 0x10000, CRC(7036d70a) SHA1(3535b52c0fa1a1158cacc041f8aba2b9a1b43af5) ) + ROM_LOAD24_BYTE("fix2.514", 0x000002, 0x10000, CRC(29b465da) SHA1(644454ab5e0dc1028e9512f85adfe5d8adb757de) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.535", 0x000000, 0x400000, CRC(6143f576) SHA1(c034923d0663d9ef24357a03098b8cb81dbab9f8) ) + ROM_LOAD24_BYTE("bg-1p.544", 0x000002, 0x200000, CRC(55e64ef7) SHA1(aae991268948d07342ee8ba1b3761bd180aab8ec) ) + ROM_LOAD24_WORD("bg-2d.536", 0x600000, 0x400000, CRC(c607a444) SHA1(dc1aa96a42e9394ca6036359670a4ec6f830c96d) ) + ROM_LOAD24_BYTE("bg-2p.545", 0x600002, 0x200000, CRC(f0830248) SHA1(6075df96b49e70d2243fef691e096119e7a4d044) ) + + ROM_REGION( 0x1200000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj3.075", 0x0000000, 0x400000, CRC(e08f42dc) SHA1(5188d71d4355eaf43ea8893b4cfc4fe80cc24f41) ) + ROM_LOAD("obj6.078", 0x0400000, 0x200000, CRC(1b6a523c) SHA1(99a420dbc8e22e7832ccda7cec9fa661a2a2687a) ) + ROM_LOAD("obj2.074", 0x0600000, 0x400000, CRC(7aeadd8e) SHA1(47103c0579240c5b1add4d0b164eaf76f5fa97f0) ) + ROM_LOAD("obj5.077", 0x0a00000, 0x200000, CRC(5d790a5d) SHA1(1ed5d4ad4c9a7e505ce35dcc90d184c26ce891dc) ) + ROM_LOAD("obj1.073", 0x0c00000, 0x400000, CRC(c2c50f02) SHA1(b81397b5800c6d49f58b7ac7ff6eac56da3c5257) ) + ROM_LOAD("obj4.076", 0x1000000, 0x200000, CRC(5259321f) SHA1(3c70c1147e49f81371d0f60f7108d9718d56faf4) ) + + ROM_REGION( 0x80000, REGION_SOUND1, 0 ) /* sound data for MSM6295 */ + ROM_LOAD("pcm0.1022", 0x000000, 0x80000, CRC(fd599b35) SHA1(00c0307d1b503bd5ce02d7960ce5e1ad600a7290) ) + + ROM_REGION( 0x80000, REGION_SOUND2, 0 ) /* sound data for MSM6295 */ + ROM_LOAD("pcm1.1023", 0x000000, 0x80000, CRC(8b716356) SHA1(42ee1896c02518cd1e9cb0dc130321834665a79e) ) +ROM_END + +ROM_START( rfjet2kc ) + ROM_REGION32_LE( 0x200000, REGION_CPU1, 0 ) /* i386 program */ + ROM_LOAD32_WORD("prg01.u267", 0x000000, 0x100000, CRC(36019fa8) SHA1(28baf0ed4a53b818c1e6986d5d3491373524eca1) ) + ROM_LOAD32_WORD("prg23.u266", 0x000002, 0x100000, CRC(65695dde) SHA1(1b25dde03bc9319414144fc13b34c455112f4076) ) + + ROM_REGION( 0x30000, REGION_GFX1, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* text layer roms */ + ROM_LOAD24_BYTE("rfj-01.524", 0x000001, 0x10000, CRC(e9d53007) SHA1(29aa7b70d5d5eb5e31426ac84143be44bc0597aa) ) + ROM_LOAD24_BYTE("rfj-02.518", 0x000000, 0x10000, CRC(dd3eabd3) SHA1(31c8f7a0cd262096a77673b040326605db542ab8) ) + ROM_LOAD24_BYTE("rfj-03.514", 0x000002, 0x10000, CRC(0daa8aac) SHA1(08a98fb3079ea9f78aa5b950bfeb30b0a805bab7) ) + + ROM_REGION( 0xc00000, REGION_GFX2, ROMREGION_ERASEFF | ROMREGION_DISPOSE ) /* background layer roms */ + ROM_LOAD24_WORD("bg-1d.u0535", 0x000000, 0x400000, CRC(edfd96da) SHA1(4813267f104619f569e5777e75b75304321abb49) ) + ROM_LOAD24_BYTE("bg-1p.u0537", 0x000002, 0x200000, CRC(a4cc4631) SHA1(cc1c4f4de8a078ca774f5a328a9a58291949b1fb) ) + ROM_LOAD24_WORD("bg-2d.u0536", 0x600000, 0x200000, CRC(731fbb59) SHA1(13cd29ec4d4c73582c5fb363218e737886826e5f) ) + ROM_LOAD24_BYTE("bg-2p.u0547", 0x600002, 0x100000, CRC(03652c25) SHA1(c0d77285111bc84e008362981ac02a246678ed0a) ) + + ROM_REGION( 0x1800000, REGION_GFX3, ROMREGION_DISPOSE ) /* sprites */ + ROM_LOAD("obj-1.u073", 0x0000000, 0x800000, CRC(58a59896) SHA1(edeaaa69987bd5d08c47ed9bf47a3901e2dcc892) ) + ROM_LOAD("obj-2.u074", 0x0800000, 0x800000, CRC(a121d1e3) SHA1(1851ae81f2ae9d3404aadd9fbc0ed7f9230290b9) ) + ROM_LOAD("obj-3.u0749", 0x1000000, 0x800000, CRC(bc2c0c63) SHA1(c8d395722f7012c3be366a0fc9b224c537afabae) ) + + ROM_REGION( 0x80000, REGION_SOUND1, 0 ) /* sound data for MSM6295 */ + ROM_LOAD("rfj-05.u1022", 0x000000, 0x80000, CRC(fd599b35) SHA1(00c0307d1b503bd5ce02d7960ce5e1ad600a7290) ) + + ROM_REGION( 0x80000, REGION_SOUND2, 0 ) /* sound data for MSM6295 */ + ROM_LOAD("rfj-04.u1023", 0x000000, 0x80000, CRC(1d10cd08) SHA1(c431d3f1a7b580024b083dafb76c53b771c88726) ) +ROM_END + + +/*****************************************************************************/ + +GAMEX( 1995, senkyu, 0, spi, spi_3button, senkyu, ROT0, "Seibu Kaihatsu", "Senkyu (Japan, newer)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, senkyua, senkyu, spi, spi_3button, senkyua, ROT0, "Seibu Kaihatsu", "Senkyu (Japan, earlier)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlball, senkyu, spi, spi_3button, batlball, ROT0, "Seibu Kaihatsu (Tuning license)", "Battle Balls (Germany, newer)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlballo, senkyu, spi, spi_3button, batlball, ROT0, "Seibu Kaihatsu (Tuning license)", "Battle Balls (Germany, earlier)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlballu, senkyu, spi, spi_3button, batlball, ROT0, "Seibu Kaihatsu (Fabtek license)", "Battle Balls (US)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlballa, senkyu, spi, spi_3button, batlball, ROT0, "Seibu Kaihatsu (Metrotainment license)", "Battle Balls (Hong Kong)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlballe, senkyu, spi, spi_3button, batlball, ROT0, "Seibu Kaihatsu (Metrotainment license)", "Battle Balls (Hong Kong, earlier)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, batlballpt, senkyu, spi, spi_3button, senkyua, ROT0, "Seibu Kaihatsu", "Battle Balls (Portugal)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1, 0, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (New Version, World)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1k, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu (Dream Island license)", "Viper Phase 1 (New Version, Korea)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1u, viprp1, spi, spi_3button, viprp1o, ROT270, "Seibu Kaihatsu (Fabtek license)", "Viper Phase 1 (New Version, US set 1)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1ua, viprp1, spi, spi_3button, viprp1o, ROT270, "Seibu Kaihatsu (Fabtek license)", "Viper Phase 1 (New Version, US set 2)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1j, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (New Version, Japan)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1s, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (New Version, Switzerland)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1h, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (New Version, Holland)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1t, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu (Tuning license)", "Viper Phase 1 (New Version, Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1pt, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (New Version, Portugal)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1ot, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu (Tuning license)", "Viper Phase 1 (Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1oj, viprp1, spi, spi_3button, viprp1o, ROT270, "Seibu Kaihatsu", "Viper Phase 1 (Japan)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1995, viprp1hk, viprp1, spi, spi_3button, viprp1, ROT270, "Seibu Kaihatsu (Metrotainment license)", "Viper Phase 1 (Hong Kong)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdft, 0, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Tuning license)", "Raiden Fighters (Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftj, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Japan, earlier)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftja, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Japan, earliest)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftu, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden Fighters (US, earlier)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftauge, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Tuning license)", "Raiden Fighters (Evaluation Software For Show, Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftua, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden Fighters (US, newer)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftjb, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Japan, newer)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftau, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Australia)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftam, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Metrotainment license)", "Raiden Fighters (Hong Kong)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftadi, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Dream Island license)", "Raiden Fighters (Korea, SUB4 cart)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdfta, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Austria)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftgb, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Great Britain)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftgr, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Greece)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftit, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu", "Raiden Fighters (Italy)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdftadia, rdft, spi, spi_3button, rdft, ROT270, "Seibu Kaihatsu (Dream Island license)", "Raiden Fighters (Korea, SUB2 cart)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2, 0, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu (Tuning license)", "Raiden Fighters 2 - Operation Hell Dive (Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2j, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Japan set 1)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2a, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu (Metrotainment license)", "Raiden Fighters 2 - Operation Hell Dive (Hong Kong)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2s, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Switzerland)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2ja, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Japan set 2)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2aa, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu (Dream Island license)", "Raiden Fighters 2 - Operation Hell Dive (Korea)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2it, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Italy)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2jb, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Japan set 3)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2jc, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Japan set 4)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2t, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive (Taiwan)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2u, rdft2, rdft2, spi_2button, rdft2, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden Fighters 2 - Operation Hell Dive (US)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1998, rfjet, 0, rdft2, spi_2button, rfjet, ROT270, "Seibu Kaihatsu (Tuning license)", "Raiden Fighters Jet (Germany)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1998, rfjetu, rfjet, rdft2, spi_2button, rfjet, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden Fighters Jet (US)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1998, rfjetj, rfjet, rdft2, spi_2button, rfjet, ROT270, "Seibu Kaihatsu", "Raiden Fighters Jet (Japan)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1998, rfjeta, rfjet, rdft2, spi_2button, rfjet, ROT270, "Seibu Kaihatsu (Dream Island license)", "Raiden Fighters Jet (Korea)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1998, rfjett, rfjet, rdft2, spi_2button, rfjet, ROT270, "Seibu Kaihatsu", "Raiden Fighters Jet (Taiwan)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1996, rdfts, rdft, sxx2e, sxx2e, rdft, ROT270, "Seibu Kaihatsu (Explorer System Corp. license)", "Raiden Fighters (Taiwan, single board)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1997, rdft2us, rdft2, sxx2f, sxx2f, rdft2, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden Fighters 2 - Operation Hell Dive (US, single board)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1999, rfjets, rfjet, sxx2g, sxx2f, rfjet, ROT270, "Seibu Kaihatsu", "Raiden Fighters Jet (US, single board)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 1999, rfjetsa, rfjet, sxx2g, sxx2f, rfjet, ROT270, "Seibu Kaihatsu", "Raiden Fighters Jet (US, single board, test version?)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 2000, rdft22kc, rdft2, sys386i, sys386i, rdft22kc, ROT270, "Seibu Kaihatsu", "Raiden Fighters 2 - Operation Hell Dive 2000 (China, SYS386I)", GAME_IMPERFECT_GRAPHICS ) +GAMEX( 2000, rfjet2kc, rfjet, sys386i, sys386i, rfjet2kc, ROT270, "Seibu Kaihatsu", "Raiden Fighters Jet 2000 (China, SYS386I)", GAME_IMPERFECT_GRAPHICS ) diff --git a/src/includes/seibuspi.h b/src/includes/seibuspi.h new file mode 100644 index 00000000..bd82fe79 --- /dev/null +++ b/src/includes/seibuspi.h @@ -0,0 +1,36 @@ +/*************************************************************************** + + Seibu SPI hardware + +***************************************************************************/ + +#ifndef SEIBUSPI_H +#define SEIBUSPI_H + +/* machine/seibuspi.c: the graphics decryption */ +void seibuspi_text_decrypt(UINT8 *rom); +void seibuspi_bg_decrypt(UINT8 *rom, int size); +void seibuspi_rdft2_text_decrypt(UINT8 *rom); +void seibuspi_rdft2_bg_decrypt(UINT8 *rom, int size); +void seibuspi_rfjet_text_decrypt(UINT8 *rom); +void seibuspi_rfjet_bg_decrypt(UINT8 *rom, int size); +void seibuspi_sprite_decrypt(UINT8 *src, int rom_size); +void seibuspi_rise10_sprite_decrypt(UINT8 *rom, int size); +void seibuspi_rise11_sprite_decrypt_rfjet(UINT8 *rom, int size); + +/* vidhrdw/seibuspi.c */ +extern data32_t *spi_mainram; /* 0x40000 bytes, the video DMA source */ + +VIDEO_START( spi ); +VIDEO_UPDATE( spi ); + +READ32_HANDLER( spi_crtc_r ); +WRITE32_HANDLER( spi_crtc_w ); +WRITE32_HANDLER( spi_tilemap_dma_start_w ); +WRITE32_HANDLER( spi_palette_dma_start_w ); +WRITE32_HANDLER( spi_video_dma_length_w ); +WRITE32_HANDLER( spi_video_dma_address_w ); +void spi_sprite_dma_start(void); +void spi_rf2_layer_bank_w(UINT8 data); + +#endif diff --git a/src/machine/ds2404.c b/src/machine/ds2404.c new file mode 100644 index 00000000..25a0a38f --- /dev/null +++ b/src/machine/ds2404.c @@ -0,0 +1,297 @@ +/*************************************************************************** + + Dallas DS2404 EconoRAM Time Chip (3-wire interface) + + Backported from current MAME src/devices/machine/ds2404.cpp: the SRAM + through the scratchpad, and the 40-bit real time clock that counts in + 1/256 seconds from a reference date. + +***************************************************************************/ + +#include +#include +#include "driver.h" +#include "state.h" +#include "ds2404.h" + +enum +{ + DS2404_IDLE = 0, + DS2404_COMMAND, + DS2404_ADDRESS1, + DS2404_ADDRESS2, + DS2404_OFFSET, + DS2404_INIT_COMMAND, + DS2404_READ_MEMORY, + DS2404_WRITE_SCRATCHPAD, + DS2404_READ_SCRATCHPAD, + DS2404_COPY_SCRATCHPAD +}; + +static UINT16 ds2404_address; +static UINT16 ds2404_offset; +static UINT16 ds2404_end_offset; +static UINT8 ds2404_a1, ds2404_a2; +static UINT8 ds2404_sram[ 512 ]; /* 4096 bits */ +static UINT8 ds2404_ram[ 32 ]; /* the scratchpad: 256 bits */ +static UINT8 ds2404_rtc[ 5 ]; /* 40-bit RTC */ +static UINT8 ds2404_state[ 8 ]; +static UINT8 ds2404_state_ptr; +static mame_timer *ds2404_timer; +static double ds2404_timer_left; /* time to the next tick, for save states */ + +static void ds2404_tick( int param ) +{ + int i; + + for( i = 0; i < 5; i++ ) + { + ds2404_rtc[ i ]++; + if( ds2404_rtc[ i ] != 0 ) + break; + } +} + +/* 0.78 does not save its timers: the tick goes on with the time it had left */ +static void ds2404_presave( void ) +{ + ds2404_timer_left = timer_timeleft( ds2404_timer ); + if( ds2404_timer_left < 0 ) + ds2404_timer_left = 0; +} + +static void ds2404_postload( void ) +{ + timer_adjust( ds2404_timer, ds2404_timer_left, 0, TIME_IN_HZ( 256 ) ); +} + +void ds2404_init( int ref_year, int ref_month, int ref_day ) +{ + struct tm ref_tm; + time_t ref_time, current_time; + + memset( &ref_tm, 0, sizeof( ref_tm ) ); + ref_tm.tm_year = ref_year - 1900; + ref_tm.tm_mon = ref_month - 1; + ref_tm.tm_mday = ref_day; + ref_time = mktime( &ref_tm ); + + time( ¤t_time ); + current_time -= ref_time; + + ds2404_rtc[ 0 ] = 0; + ds2404_rtc[ 1 ] = ( current_time >> 0 ) & 0xff; + ds2404_rtc[ 2 ] = ( current_time >> 8 ) & 0xff; + ds2404_rtc[ 3 ] = ( current_time >> 16 ) & 0xff; + ds2404_rtc[ 4 ] = ( current_time >> 24 ) & 0xff; + + memset( ds2404_sram, 0, sizeof( ds2404_sram ) ); + memset( ds2404_ram, 0, sizeof( ds2404_ram ) ); + memset( ds2404_state, DS2404_IDLE, sizeof( ds2404_state ) ); + ds2404_state_ptr = 0; + ds2404_address = 0; + ds2404_offset = 0; + ds2404_end_offset = 0; + ds2404_a1 = ds2404_a2 = 0; + + ds2404_timer = timer_alloc( ds2404_tick ); + timer_adjust( ds2404_timer, TIME_IN_HZ( 256 ), 0, TIME_IN_HZ( 256 ) ); + ds2404_timer_left = 0; + + state_save_register_UINT16( "ds2404", 0, "address", &ds2404_address, 1 ); + state_save_register_UINT16( "ds2404", 0, "offset", &ds2404_offset, 1 ); + state_save_register_UINT16( "ds2404", 0, "end_offset", &ds2404_end_offset, 1 ); + state_save_register_UINT8( "ds2404", 0, "a1", &ds2404_a1, 1 ); + state_save_register_UINT8( "ds2404", 0, "a2", &ds2404_a2, 1 ); + state_save_register_UINT8( "ds2404", 0, "sram", ds2404_sram, sizeof( ds2404_sram ) ); + state_save_register_UINT8( "ds2404", 0, "ram", ds2404_ram, sizeof( ds2404_ram ) ); + state_save_register_UINT8( "ds2404", 0, "rtc", ds2404_rtc, sizeof( ds2404_rtc ) ); + state_save_register_UINT8( "ds2404", 0, "state", ds2404_state, sizeof( ds2404_state ) ); + state_save_register_UINT8( "ds2404", 0, "state_ptr", &ds2404_state_ptr, 1 ); + state_save_register_double( "ds2404", 0, "timer_left", &ds2404_timer_left, 1 ); + state_save_register_func_presave( ds2404_presave ); + state_save_register_func_postload( ds2404_postload ); +} + +static void ds2404_rom_cmd( UINT8 cmd ) +{ + switch( cmd ) + { + case 0xcc: /* skip ROM */ + ds2404_state[ 0 ] = DS2404_COMMAND; + ds2404_state_ptr = 0; + break; + + default: + logerror( "DS2404: unknown ROM command %02X\n", cmd ); + break; + } +} + +static void ds2404_cmd( UINT8 cmd ) +{ + switch( cmd ) + { + case 0x0f: /* write scratchpad */ + ds2404_state[ 0 ] = DS2404_ADDRESS1; + ds2404_state[ 1 ] = DS2404_ADDRESS2; + ds2404_state[ 2 ] = DS2404_INIT_COMMAND; + ds2404_state[ 3 ] = DS2404_WRITE_SCRATCHPAD; + ds2404_state_ptr = 0; + break; + + case 0x55: /* copy scratchpad */ + ds2404_state[ 0 ] = DS2404_ADDRESS1; + ds2404_state[ 1 ] = DS2404_ADDRESS2; + ds2404_state[ 2 ] = DS2404_OFFSET; + ds2404_state[ 3 ] = DS2404_INIT_COMMAND; + ds2404_state[ 4 ] = DS2404_COPY_SCRATCHPAD; + ds2404_state_ptr = 0; + break; + + case 0xf0: /* read memory */ + ds2404_state[ 0 ] = DS2404_ADDRESS1; + ds2404_state[ 1 ] = DS2404_ADDRESS2; + ds2404_state[ 2 ] = DS2404_INIT_COMMAND; + ds2404_state[ 3 ] = DS2404_READ_MEMORY; + ds2404_state_ptr = 0; + break; + + default: + logerror( "DS2404: unknown command %02X\n", cmd ); + break; + } +} + +static UINT8 ds2404_readmem( void ) +{ + if( ds2404_address < 0x200 ) + return ds2404_sram[ ds2404_address ]; + else if( ds2404_address >= 0x202 && ds2404_address <= 0x206 ) + return ds2404_rtc[ ds2404_address - 0x202 ]; + return 0; +} + +static void ds2404_writemem( UINT8 value ) +{ + if( ds2404_address < 0x200 ) + ds2404_sram[ ds2404_address ] = value; + else if( ds2404_address >= 0x202 && ds2404_address <= 0x206 ) + ds2404_rtc[ ds2404_address - 0x202 ] = value; +} + +WRITE_HANDLER( ds2404_1w_reset_w ) +{ + ds2404_state[ 0 ] = DS2404_IDLE; + ds2404_state_ptr = 0; +} + +WRITE_HANDLER( ds2404_3w_reset_w ) +{ + ds2404_state[ 0 ] = DS2404_COMMAND; + ds2404_state_ptr = 0; +} + +READ_HANDLER( ds2404_data_r ) +{ + UINT8 value = 0; + + switch( ds2404_state[ ds2404_state_ptr ] ) + { + case DS2404_READ_MEMORY: + value = ds2404_readmem(); + break; + + case DS2404_READ_SCRATCHPAD: + if( ds2404_offset < 0x20 ) + { + value = ds2404_ram[ ds2404_offset ]; + ds2404_offset++; + } + break; + } + return value; +} + +WRITE_HANDLER( ds2404_data_w ) +{ + int i; + + switch( ds2404_state[ ds2404_state_ptr ] ) + { + case DS2404_IDLE: + ds2404_rom_cmd( data & 0xff ); + break; + + case DS2404_COMMAND: + ds2404_cmd( data & 0xff ); + break; + + case DS2404_ADDRESS1: + ds2404_a1 = data & 0xff; + ds2404_state_ptr++; + break; + + case DS2404_ADDRESS2: + ds2404_a2 = data & 0xff; + ds2404_state_ptr++; + break; + + case DS2404_OFFSET: + ds2404_end_offset = data & 0xff; + ds2404_state_ptr++; + break; + + case DS2404_WRITE_SCRATCHPAD: + if( ds2404_offset < 0x20 ) + { + ds2404_ram[ ds2404_offset ] = data & 0xff; + ds2404_offset++; + } + break; + } + + if( ds2404_state[ ds2404_state_ptr ] == DS2404_INIT_COMMAND ) + { + switch( ds2404_state[ ds2404_state_ptr + 1 ] ) + { + case DS2404_READ_MEMORY: + ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1; + ds2404_address -= 1; + break; + + case DS2404_WRITE_SCRATCHPAD: + case DS2404_READ_SCRATCHPAD: + ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1; + ds2404_offset = ds2404_address & 0x1f; + break; + + case DS2404_COPY_SCRATCHPAD: + ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1; + for( i = 0; i <= ds2404_end_offset; i++ ) + { + /* MAME reads past the 32 bytes of the scratchpad here: stay in it */ + ds2404_writemem( ds2404_ram[ i & 0x1f ] ); + ds2404_address++; + } + break; + } + ds2404_state_ptr++; + } +} + +WRITE_HANDLER( ds2404_clk_w ) +{ + if( ds2404_state[ ds2404_state_ptr ] == DS2404_READ_MEMORY ) + ds2404_address++; +} + +void ds2404_nvram_load( mame_file *file ) +{ + mame_fread( file, ds2404_sram, sizeof( ds2404_sram ) ); +} + +void ds2404_nvram_save( mame_file *file ) +{ + mame_fwrite( file, ds2404_sram, sizeof( ds2404_sram ) ); +} diff --git a/src/machine/ds2404.h b/src/machine/ds2404.h new file mode 100644 index 00000000..7ffbc33c --- /dev/null +++ b/src/machine/ds2404.h @@ -0,0 +1,27 @@ +/*************************************************************************** + + Dallas DS2404 EconoRAM Time Chip (3-wire interface) + + Backported from current MAME src/devices/machine/ds2404.cpp + +***************************************************************************/ + +#ifndef DS2404_H +#define DS2404_H + +#include "driver.h" + +/* the reference date the RTC counts the seconds from */ +void ds2404_init( int ref_year, int ref_month, int ref_day ); + +WRITE_HANDLER( ds2404_1w_reset_w ); +WRITE_HANDLER( ds2404_3w_reset_w ); +READ_HANDLER( ds2404_data_r ); +WRITE_HANDLER( ds2404_data_w ); +WRITE_HANDLER( ds2404_clk_w ); + +/* the 512 bytes of SRAM; no file: zeroes */ +void ds2404_nvram_load( mame_file *file ); +void ds2404_nvram_save( mame_file *file ); + +#endif diff --git a/src/machine/intelfsh.c b/src/machine/intelfsh.c index 63f5c9ac..a5e1b365 100644 --- a/src/machine/intelfsh.c +++ b/src/machine/intelfsh.c @@ -1,6 +1,6 @@ /*************************************************************************** - Intel / Sharp 16-bit flash memories, the Intel command set + Intel / Sharp 8-bit and 16-bit flash memories, the Intel command set Backported from current MAME src/devices/machine/intelfsh.cpp. A block erase takes the time of MAME (1 second for a 64KB block, 300 / 600 ms @@ -29,7 +29,8 @@ struct intelfsh_chip { int type; UINT16 *data; - UINT32 words; + UINT32 words; /* the size in units: words, bytes on an 8-bit chip */ + UINT8 bits; UINT8 maker_id; UINT16 device_id; UINT8 mode; @@ -112,6 +113,12 @@ void intelfsh_init( int chip, int type, UINT16 *data ) c->device_id = 0x15; break; + case INTELFSH_INTEL_E28F008SA: + bytes = 0x100000; + c->maker_id = 0x89; /* Intel */ + c->device_id = 0xa2; + break; + default: case INTELFSH_INTEL_TE28F160: bytes = 0x200000; @@ -119,7 +126,8 @@ void intelfsh_init( int chip, int type, UINT16 *data ) c->device_id = 0xd0; break; } - c->words = bytes / 2; + c->bits = ( type == INTELFSH_INTEL_E28F008SA ) ? 8 : 16; + c->words = ( c->bits == 8 ) ? bytes : bytes / 2; c->data = data != NULL ? data : auto_malloc( bytes ); memset( c->data, 0xff, bytes ); c->mode = FM_NORMAL; @@ -127,7 +135,10 @@ void intelfsh_init( int chip, int type, UINT16 *data ) c->timer = timer_alloc( intelfsh_delay ); c->timer_left = -1; - state_save_register_UINT16( "intelfsh", chip, "data", c->data, c->words ); + if( c->bits == 8 ) + state_save_register_UINT8( "intelfsh", chip, "data", (UINT8 *)c->data, c->words ); + else + state_save_register_UINT16( "intelfsh", chip, "data", c->data, c->words ); state_save_register_UINT8( "intelfsh", chip, "mode", &c->mode, 1 ); state_save_register_UINT8( "intelfsh", chip, "status", &c->status, 1 ); state_save_register_UINT8( "intelfsh", chip, "master_lock", &c->master_lock, 1 ); @@ -153,7 +164,7 @@ UINT16 *intelfsh_data( int chip ) UINT32 intelfsh_size( int chip ) { - return chips[ chip ].words * 2; + return chips[ chip ].bits == 8 ? chips[ chip ].words : chips[ chip ].words * 2; } void intelfsh_reset( int chip ) @@ -174,6 +185,8 @@ UINT16 intelfsh_read( int chip, UINT32 offset ) { default: case FM_NORMAL: + if( c->bits == 8 ) + return ( (UINT8 *)c->data )[ offset % c->words ]; return c->data[ offset % c->words ]; case FM_READSTATUS: @@ -232,11 +245,11 @@ static void intelfsh_erase( int chip, UINT32 offset ) } else { - base = ( ( offset % c->words ) * 2 ) & ~0xffff; + base = ( ( offset % c->words ) * ( c->bits / 8 ) ) & ~0xffff; size = 0x10000; duration = TIME_IN_SEC( 1 ); } - memset( c->data + base / 2, 0xff, size ); + memset( (UINT8 *)c->data + base, 0xff, size ); timer_adjust( c->timer, duration, chip, 0 ); } @@ -288,7 +301,10 @@ void intelfsh_write( int chip, UINT32 offset, UINT16 data ) break; case FM_WRITEPART1: - c->data[ offset % c->words ] &= data; + if( c->bits == 8 ) + ( (UINT8 *)c->data )[ offset % c->words ] &= data; + else + c->data[ offset % c->words ] &= data; c->status = 0x80; c->mode = FM_READSTATUS; break; @@ -366,6 +382,11 @@ void intelfsh_nvram_load( int chip, mame_file *file ) UINT8 buffer[ 0x1000 ]; UINT32 i, j; + if( c->bits == 8 ) + { + mame_fread( file, c->data, c->words ); + return; + } for( i = 0; i < c->words; i += sizeof( buffer ) / 2 ) { mame_fread( file, buffer, sizeof( buffer ) ); @@ -380,6 +401,11 @@ void intelfsh_nvram_save( int chip, mame_file *file ) UINT8 buffer[ 0x1000 ]; UINT32 i, j; + if( c->bits == 8 ) + { + mame_fwrite( file, c->data, c->words ); + return; + } for( i = 0; i < c->words; i += sizeof( buffer ) / 2 ) { for( j = 0; j < sizeof( buffer ) / 2; j++ ) diff --git a/src/machine/intelfsh.h b/src/machine/intelfsh.h index 95d2a2aa..074b7da6 100644 --- a/src/machine/intelfsh.h +++ b/src/machine/intelfsh.h @@ -1,6 +1,6 @@ /*************************************************************************** - Intel / Sharp 16-bit flash memories, the Intel command set + Intel / Sharp 8-bit and 16-bit flash memories, the Intel command set Backported from current MAME src/devices/machine/intelfsh.cpp (R. Belmont and others), the parts the 16-bit Intel chips use: read array, read ID, @@ -21,20 +21,22 @@ enum { INTELFSH_INTEL_E28F400B = 0, /* 512KB, Intel 0x89 / 0x4471, bottom boot blocks */ INTELFSH_INTEL_TE28F160, /* 2MB, Sharp 0xb0 / 0xd0, 64KB blocks */ - INTELFSH_INTEL_28F640J5 /* 8MB StrataFlash, Intel 0x89 / 0x15, 64KB blocks (as MAME), write buffer */ + INTELFSH_INTEL_28F640J5, /* 8MB StrataFlash, Intel 0x89 / 0x15, 64KB blocks (as MAME), write buffer */ + INTELFSH_INTEL_E28F008SA /* 1MB, 8-bit, Intel 0x89 / 0xa2, 64KB blocks */ }; /* data: the contents (size bytes, host order words), NULL to allocate them; */ -/* they start erased. Chip 0 is the first one a driver sets up */ +/* they start erased. Chip 0 is the first one a driver sets up. On an 8-bit */ +/* chip the contents are bytes, and the offsets and the data are bytes too */ void intelfsh_init( int chip, int type, UINT16 *data ); UINT16 *intelfsh_data( int chip ); UINT32 intelfsh_size( int chip ); /* in bytes */ -UINT16 intelfsh_read( int chip, UINT32 offset ); /* word offset */ +UINT16 intelfsh_read( int chip, UINT32 offset ); /* word offset (byte offset on an 8-bit chip) */ void intelfsh_write( int chip, UINT32 offset, UINT16 data ); void intelfsh_reset( int chip ); /* the reset pin: back to read array mode */ -/* the contents in the NVRAM file, as little endian words */ +/* the contents in the NVRAM file, as little endian words (bytes on an 8-bit chip) */ void intelfsh_nvram_load( int chip, mame_file *file ); void intelfsh_nvram_save( int chip, mame_file *file ); diff --git a/src/machine/seibuspi_machine.c b/src/machine/seibuspi_machine.c new file mode 100644 index 00000000..b0db7b6c --- /dev/null +++ b/src/machine/seibuspi_machine.c @@ -0,0 +1,507 @@ +/*************************************************************************** + + Seibu SPI hardware: the graphics decryption + + Backported from current MAME src/mame/seibu/seibuspi_m.cpp, + seibuspi_v.cpp and seibu_helper.cpp (Ville Linde, hap, Nicola Salmoria): + the tiles (all games), the SEI252 sprites (Senkyu, Viper Phase 1, + Raiden Fighters), the RISE10 sprites (Raiden Fighters 2) and the RISE11 + sprites (Raiden Fighters Jet). + +***************************************************************************/ + +#include +#include "driver.h" +#include "includes/seibuspi.h" + +/* unsigned, the decryption shifts the bits up to bit 31 */ +#undef BIT +#define BIT(x,n) ((UINT32)(((x)>>(n))&1)) + +/* add two numbers generating carry from one bit to the next only if */ +/* the corresponding bit in carry_mask is 1; the carry out of the top bit */ +/* is xored into bit 0. The bit by bit loop of MAME, all the bits at once: */ +/* the carries are propagated until they settle */ +static UINT32 seibu_partial_carry_sum(UINT32 add1, UINT32 add2, UINT32 carry_mask, int bits) +{ + UINT32 m = (bits == 32) ? 0xffffffff : ((1u << bits) - 1); + UINT32 a = add1 & m, b = add2 & m; + UINT32 g = a & b, p = a ^ b, cin = 0, cout; + + for (;;) + { + UINT32 n; + cout = carry_mask & m & (g | (p & cin)); + n = (cout << 1) & m; + if (n == cin) + break; + cin = n; + } + + return ((p ^ cin) & m) ^ ((cout >> (bits - 1)) & 1); +} + + +/************************************************************************** + +Tile encryption +--------------- + +The tile graphics encryption uses the same algorithm in all games. This is +similar to, but simpler than, that used by the SEI252, RISE10 and RISE11 +custom chips. + +- Take 24 bits of gfx data (used to decrypt 4 pixels at 6 bpp) and perform + a bit permutation on them (the permutation is the same in all games). +- Take the low 12 bits of the tile code and add a 24-bit number (KEY1) to it. +- Add the two 24-bit numbers resulting from the above steps, but with a + catch: while performing the sum, some bits generate carry as usual, other + bits don't, depending on a 24-bit key (KEY2). Note that the carry generated + by bit 23 (if enabled) wraps around to bit 0. +- XOR the result with a 24-bit number (KEY3). + +The decryption is actually programmable; the games write the key to the +custom CRTC on startup!! (writes to 000414) + +**************************************************************************/ + +static UINT32 decrypt_tile(UINT32 val, int tileno, UINT32 key1, UINT32 key2, UINT32 key3) +{ + val = BITSWAP24(val, 18,19,9,5, 10,17,16,20, 21,22,6,11, 15,14,4,23, 0,1,7,8, 13,12,3,2); + + return seibu_partial_carry_sum(val, tileno + key1, key2, 24) ^ key3; +} + +static void decrypt_text(UINT8 *rom, UINT32 key1, UINT32 key2, UINT32 key3) +{ + int i; + + for (i = 0; i < 0x10000; i++) + { + UINT32 w = (rom[(i * 3) + 0] << 16) | (rom[(i * 3) + 1] << 8) | (rom[(i * 3) + 2]); + + w = decrypt_tile(w, i >> 4, key1, key2, key3); + + rom[(i * 3) + 0] = (w >> 16) & 0xff; + rom[(i * 3) + 1] = (w >> 8) & 0xff; + rom[(i * 3) + 2] = w & 0xff; + } +} + +static void decrypt_bg(UINT8 *rom, int size, UINT32 key1, UINT32 key2, UINT32 key3) +{ + int i, j; + + for (j = 0; j < size; j += 0xc0000) + { + for (i = 0; i < 0x40000; i++) + { + UINT32 w = (rom[j + (i * 3) + 0] << 16) | (rom[j + (i * 3) + 1] << 8) | (rom[j + (i * 3) + 2]); + + w = decrypt_tile(w, i >> 6, key1, key2, key3); + + rom[j + (i * 3) + 0] = (w >> 16) & 0xff; + rom[j + (i * 3) + 1] = (w >> 8) & 0xff; + rom[j + (i * 3) + 2] = w & 0xff; + } + } +} + +/* the keys the games write to the CRTC: Senkyu, Viper Phase 1, Raiden Fighters */ +void seibuspi_text_decrypt(UINT8 *rom) +{ + decrypt_text(rom, 0x5a3845, 0x77cf5b, 0x1378df); +} + +void seibuspi_bg_decrypt(UINT8 *rom, int size) +{ + decrypt_bg(rom, size, 0x5a3845, 0x77cf5b, 0x1378df); +} + +/* Raiden Fighters 2 */ +void seibuspi_rdft2_text_decrypt(UINT8 *rom) +{ + decrypt_text(rom, 0x823146, 0x4de2f8, 0x157adc); +} + +void seibuspi_rdft2_bg_decrypt(UINT8 *rom, int size) +{ + decrypt_bg(rom, size, 0x823146, 0x4de2f8, 0x157adc); +} + +/* Raiden Fighters Jet */ +void seibuspi_rfjet_text_decrypt(UINT8 *rom) +{ + decrypt_text(rom, 0xaea754, 0xfe8530, 0xccb666); +} + +void seibuspi_rfjet_bg_decrypt(UINT8 *rom, int size) +{ + decrypt_bg(rom, size, 0xaea754, 0xfe8530, 0xccb666); +} + + +/* +SEI252 sprites: this is the main key as written by the game. +There are 256 values; the one to use is key_table[(address >> 8) & 0xff]. + +Bits 0-3 select the permutation on 16 bits of the source data. +Bits 4-14 are added to the source data, with partial carry. +Bit 15 is still unknown. +*/ +static const UINT16 key_table[256]= +{ + 0x3ad7,0x54b1,0x2d41,0x8ca0,0xa69b,0x9018,0x9db9,0x6559, + 0xe9a7,0xb087,0x8a5e,0x821c,0xaafc,0x2ae7,0x557b,0xcd80, + 0xcfee,0x653e,0x9b31,0x7ab5,0x8b2a,0xbda8,0x707a,0x3c83, + 0xcbb7,0x7157,0x8226,0x5c4a,0x8bf2,0x6397,0x13e2,0x3102, + 0x8093,0x44cd,0x5f2d,0x7639,0xa7a4,0x9974,0x5263,0x8318, + 0xb78c,0xa120,0xafb4,0x615f,0x6e0b,0x1d7d,0x8c29,0x4466, + 0x3f35,0x794e,0xaea6,0x601c,0xe478,0xcf6e,0x4ee3,0xa009, + 0x4b99,0x51d3,0x3474,0x3e4d,0xe5b7,0x9088,0xb5c0,0xba9f, + 0x5646,0xa0af,0x970b,0xb14f,0x8216,0x2386,0x496d,0x9245, + 0x7e4c,0xad5f,0x89d9,0xb801,0xdf64,0x8ca8,0xe019,0xde9b, + 0x6836,0x70e2,0x7dcd,0x7ac1,0x98ef,0x71aa,0x7d6f,0x70bd, + 0x9e14,0x75b6,0x8153,0xab6c,0x1f85,0x79cd,0xb2a1,0x934a, + 0x6f74,0x37d7,0xa05a,0x6563,0x1972,0x2dcd,0x7e59,0x6a60, + 0x5163,0x84c4,0xc451,0x8d80,0x4287,0x57e8,0xacc9,0x539d, + 0xbe71,0xdb7c,0x9424,0xb224,0xcc0f,0xe3dd,0xb79c,0x461e, + 0x96a9,0x4c7c,0x5443,0x6b2b,0x3cdc,0xbee8,0x2602,0x3282, + 0x7f9c,0x59c3,0xc69a,0x39f4,0x5138,0xb7ca,0x6ca7,0x62e7, + 0xc455,0x56cf,0x8a9a,0x695c,0x5af2,0xdebf,0x4dbb,0xdaec, + 0xb564,0xc89c,0x7d2d,0x6dc3,0xa15a,0x6584,0xb8ea,0xb7ac, + 0x88d8,0xc5aa,0x98c5,0xc506,0xc13c,0x7f59,0xab65,0x8fc8, + 0x3a3c,0xd5f6,0x554d,0x5682,0x8ce7,0x40fc,0x8fd7,0x535c, + 0x6aa0,0x52fe,0x8834,0x5316,0x6c27,0x80a9,0x9e6f,0x2c08, + 0x4092,0xc7c1,0xc468,0x9520,0xbc4d,0xb621,0x3cdb,0xdce8, + 0x481f,0xd0bd,0x3a57,0x807e,0x3025,0x5aa0,0x5e49,0xa29b, + 0xd2d6,0x7bee,0x97f0,0xe28e,0x2fff,0x48e4,0x6367,0x933f, + 0x57c5,0x28d4,0x68a0,0xd22e,0x39a6,0x9d2b,0x7a64,0x7e72, + 0x5379,0xe86c,0x7554,0x8fbb,0xc06a,0x9533,0x7eec,0x4d52, + 0xa800,0x5d35,0xa47d,0xe515,0x8d19,0x703b,0x5a2e,0x627c, + 0x7cea,0x1b2c,0x5a05,0x8598,0x9e00,0xcf01,0x62d9,0x7a10, + 0x1f42,0x87ce,0x575d,0x6e23,0x86ef,0x93c2,0x3d1a,0x89aa, + 0xe199,0xba1d,0x1b72,0x4513,0x5131,0xc23c,0xba9f,0xa069, + 0xfbfb,0xda92,0x42b2,0x3a48,0xdb96,0x5fad,0xba96,0xc6eb, +}; + +static const UINT8 spi_bitswap[16][16] = +{ + { 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, + { 7, 6, 5,14, 0,15, 4, 3, 2, 8, 9,10,11,12,13, 1, }, + { 9,15,14,13,12, 0, 1, 2,10, 8, 7, 6, 5, 4, 3,11, }, + { 5, 4, 3, 2, 9,14,13,12,11, 6, 7, 8, 1,15, 0,10, }, + { 12,11, 0, 7, 8, 5, 6,15,10,13,14, 1, 2, 3, 4, 9, }, + { 14, 0, 1, 2, 3, 9, 8, 7,15, 5, 6,13,12,11,10, 4, }, + { 13,12,11,10, 2, 7, 8, 9, 0,14,15, 3, 4, 5, 6, 1, }, + { 2, 9,10,11,12, 7, 6, 5,14, 3, 4, 0,15, 1, 8,13, }, + { 8, 7, 4, 3, 2,13,12,11, 0, 9,10,14,15, 6, 5, 1, }, + { 3, 2,10,11,12, 5,14, 0, 1, 4,15, 6, 7, 8, 9,13, }, + { 2,10, 6, 5, 4,14,13,12,11, 1, 0,15, 9, 8, 7, 3, }, + { 12,11, 8, 1,15, 3, 2, 9,10,13,14, 4, 5, 6, 7, 0, }, + { 8, 7, 0,11,12, 5, 6,15,14, 9,10, 1, 2, 3, 4,13, }, + { 3, 2, 1, 0,14, 9, 8, 7, 6, 4,15,13,12,11,10, 5, }, + { 2,10,11,12,13, 7, 8, 9,15, 1, 0, 3, 4, 5, 6,14, }, + { 12,11,10, 9, 2, 7, 6, 5, 4,13,14, 0,15, 1, 8, 3, }, +}; + +static int key(int table, int addr) +{ + int xorbit = 8 + ((table & 0xc) >> 2); + return BIT(key_table[addr & 0xff] >> 4, table) ^ BIT(addr, xorbit); +} + +void seibuspi_sprite_decrypt(UINT8 *src, int rom_size) +{ + int i, j, addr; + UINT16 y1, y2, y3; + UINT32 s1, s2, add1, add2; + const UINT8 *bs; + UINT8 plane0, plane1, plane2, plane3, plane4, plane5; + + add1 = add2 = 0; + for (i = 0; i < rom_size/2; i++) + { + int new_addr = ((i & 0xff) == 0); + addr = i >> 8; + + y1 = src[2 * i + 0 * rom_size + 0] + (src[2 * i + 0 * rom_size + 1] << 8); + y2 = src[2 * i + 1 * rom_size + 0] + (src[2 * i + 1 * rom_size + 1] << 8); + y3 = src[2 * i + 2 * rom_size + 0] + (src[2 * i + 2 * rom_size + 1] << 8); + + + /* first of all, permutate 16 of the 48 bits */ + bs = spi_bitswap[key_table[addr & 0xff] & 0xf]; + y3 = BITSWAP16(y3, bs[0],bs[1],bs[2],bs[3],bs[4],bs[5],bs[6],bs[7], + bs[8],bs[9],bs[10],bs[11],bs[12],bs[13],bs[14],bs[15]); + + + /* planes 4 & 5, interleaved */ + s1 = (BIT(y1, 4) << 0) | + (BIT(y3, 7) << 1) | + (BIT(y3, 6) << 2) | + (BIT(y2,12) << 3) | + (BIT(y2, 3) << 4) | + (BIT(y1,10) << 5) | + (BIT(y1, 1) << 6) | + (BIT(y3,14) << 7) | + (BIT(y3, 2) << 8) | + (BIT(y2, 9) << 9) | + (BIT(y2, 0) << 10) | + (BIT(y1, 7) << 11) | + (BIT(y3,12) << 12) | + (BIT(y2,15) << 13) | + (BIT(y2, 6) << 14) | + (BIT(y1,13) << 15); + + if (new_addr) /* the keys change every 256 words */ + add1 = (BIT(addr,11) << 0) | + (BIT(addr,10) << 1) | + (key(10,addr) << 2) | + (key( 5,addr) << 3) | + (key( 4,addr) << 4) | + (BIT(addr,11) << 5) | + (BIT(addr,11) << 6) | + (key( 7,addr) << 7) | + (key( 6,addr) << 8) | + (key( 1,addr) << 9) | + (key( 0,addr) << 10) | + (BIT(addr,11) << 11) | + (key( 9,addr) << 12) | + (key( 8,addr) << 13) | + (key( 3,addr) << 14) | + (key( 2,addr) << 15); + + /* planes 0-3, interleaved */ + s2 = (BIT(y1, 5) << 0) | + (BIT(y3, 0) << 1) | + (BIT(y3, 5) << 2) | + (BIT(y2,13) << 3) | + (BIT(y2, 4) << 4) | + (BIT(y1,11) << 5) | + (BIT(y1, 2) << 6) | + (BIT(y3, 9) << 7) | + (BIT(y3, 3) << 8) | + (BIT(y2, 8) << 9) | + (BIT(y1,15) << 10) | + (BIT(y1, 6) << 11) | + (BIT(y3,11) << 12) | + (BIT(y2,14) << 13) | + (BIT(y2, 5) << 14) | + (BIT(y1,12) << 15) | + (BIT(y1, 3) << 16) | + (BIT(y3, 8) << 17) | + (BIT(y3,15) << 18) | + (BIT(y2,11) << 19) | + (BIT(y2, 2) << 20) | + (BIT(y1, 9) << 21) | + (BIT(y1, 0) << 22) | + (BIT(y3,10) << 23) | + (BIT(y3, 1) << 24) | + (BIT(y2,10) << 25) | + (BIT(y2, 1) << 26) | + (BIT(y1, 8) << 27) | + (BIT(y3,13) << 28) | + (BIT(y3, 4) << 29) | + (BIT(y2, 7) << 30) | + (BIT(y1,14) << 31); + + if (new_addr) /* the keys change every 256 words */ + add2 = (key( 0,addr) << 0) | + (key( 1,addr) << 1) | + (key( 2,addr) << 2) | + (key( 3,addr) << 3) | + (key( 4,addr) << 4) | + (key( 5,addr) << 5) | + (key( 6,addr) << 6) | + (key( 7,addr) << 7) | + (key( 8,addr) << 8) | + (key( 9,addr) << 9) | + (key(10,addr) << 10) | + (BIT(addr,10) << 11) | + (BIT(addr,11) << 12) | + (BIT(addr,11) << 13) | + (BIT(addr,11) << 14) | + (BIT(addr,11) << 15) | + (BIT(addr,11) << 16) | + (key( 7,addr) << 17) | + (BIT(addr,11) << 18) | + (key( 6,addr) << 19) | + (BIT(addr,11) << 20) | + (key( 5,addr) << 21) | + (BIT(addr,11) << 22) | + (key( 4,addr) << 23) | + (BIT(addr,10) << 24) | + (key( 3,addr) << 25) | + (key(10,addr) << 26) | + (key( 2,addr) << 27) | + (key( 9,addr) << 28) | + (key( 1,addr) << 29) | + (key( 8,addr) << 30) | + (key( 0,addr) << 31); + + s1 = seibu_partial_carry_sum(s1, add1, 0x3a59, 16) ^ 0x843a; + s2 = seibu_partial_carry_sum(s2, add2, 0x28d49cac, 32) ^ 0xc8e29f84; + + + /* reorder the bits in the order MAME expects to decode the graphics */ + plane0 = plane1 = plane2 = plane3 = plane4 = plane5 = 0; + for (j = 0; j < 8; j++) + { + plane5 |= (BIT(s1, 2 * j + 1) << j); + plane4 |= (BIT(s1, 2 * j + 0) << j); + plane3 |= (BIT(s2, 4 * j + 3) << j); + plane2 |= (BIT(s2, 4 * j + 2) << j); + plane1 |= (BIT(s2, 4 * j + 1) << j); + plane0 |= (BIT(s2, 4 * j + 0) << j); + } + + src[2 * i + 0 * rom_size + 0] = plane5; + src[2 * i + 0 * rom_size + 1] = plane4; + src[2 * i + 1 * rom_size + 0] = plane3; + src[2 * i + 1 * rom_size + 1] = plane2; + src[2 * i + 2 * rom_size + 0] = plane1; + src[2 * i + 2 * rom_size + 1] = plane0; + } +} + + +static void sprite_reorder(UINT8 *buffer) +{ + UINT8 temp[64]; + int j; + + for (j = 0; j < 16; j++) + { + temp[2 * (j * 2) + 0] = buffer[2 * j + 0]; + temp[2 * (j * 2) + 1] = buffer[2 * j + 1]; + temp[2 * (j * 2) + 2] = buffer[2 * j + 32]; + temp[2 * (j * 2) + 3] = buffer[2 * j + 33]; + } + memcpy(buffer, temp, 64); +} + +/* RISE10: Raiden Fighters 2 */ +void seibuspi_rise10_sprite_decrypt(UINT8 *rom, int size) +{ + int i; + + for (i = 0; i < size / 2; i++) + { + UINT32 plane54 = rom[0 * size + 2 * i] + (rom[0 * size + 2 * i + 1] << 8); + UINT32 plane3210 = BITSWAP32( + (UINT32)(rom[2 * size + 2 * i] + (rom[2 * size + 2 * i + 1] << 8) + (rom[1 * size + 2 * i] << 16) + ((UINT32)rom[1 * size + 2 * i + 1] << 24)), + 23,13,24,4,16,12,25,30, + 3,5,29,17,14,22,2,11, + 27,6,15,21,1,28,10,20, + 7,31,26,0,18,9,19,8); + + plane54 = seibu_partial_carry_sum(plane54, 0xabcb, 0x55aa, 16) ^ 0x6699; + plane3210 = seibu_partial_carry_sum(plane3210, 0x654321d9 ^ 0x42, 0x1d463748, 32) ^ 0x0ca352a9; + + rom[0 * size + 2 * i] = plane54 >> 8; + rom[0 * size + 2 * i + 1] = plane54 >> 0; + rom[1 * size + 2 * i] = plane3210 >> 24; + rom[1 * size + 2 * i + 1] = plane3210 >> 16; + rom[2 * size + 2 * i] = plane3210 >> 8; + rom[2 * size + 2 * i + 1] = plane3210 >> 0; + } + + for (i = 0; i < size / 2; i += 32) + { + sprite_reorder(&rom[0 * size + 2 * i]); + sprite_reorder(&rom[1 * size + 2 * i]); + sprite_reorder(&rom[2 * size + 2 * i]); + } +} + +/* RISE11 */ +static void seibuspi_rise11_sprite_decrypt(UINT8 *rom, int size, + UINT32 k1, UINT32 k2, UINT32 k3, UINT32 k4, UINT32 k5, int feversoc_kludge) +{ + int i; + UINT16 b1, b2, b3; + UINT32 plane543, plane210; + + for (i = 0; i < size/2; i++) + { + b1 = rom[0 * size + 2 * i] + (rom[0 * size + 2 * i + 1] << 8); + b2 = rom[1 * size + 2 * i] + (rom[1 * size + 2 * i + 1] << 8); + b3 = rom[2 * size + 2 * i] + (rom[2 * size + 2 * i + 1] << 8); + + plane543 = (BIT(b2,11)<< 0) | + (BIT(b1, 6)<< 1) | + (BIT(b3,12)<< 2) | + (BIT(b3, 3)<< 3) | + (BIT(b2,12)<< 4) | + (BIT(b3,14)<< 5) | + (BIT(b3, 4)<< 6) | + (BIT(b1,11)<< 7) | + (BIT(b1,12)<< 8) | + (BIT(b1, 2)<< 9) | + (BIT(b2, 5)<<10) | + (BIT(b1, 9)<<11) | + (BIT(b3, 1)<<12) | + (BIT(b2, 2)<<13) | + (BIT(b2,10)<<14) | + (BIT(b3, 5)<<15) | + (BIT(b1, 3)<<16) | + (BIT(b2, 7)<<17) | + (BIT(b1,15)<<18) | + (BIT(b3, 9)<<19) | + (BIT(b2,13)<<20) | + (BIT(b1, 4)<<21) | + (BIT(b3, 2)<<22) | + (BIT(b2, 0)<<23); + + plane210 = (BIT(b1,14)<< 0) | + (BIT(b1, 1)<< 1) | + (BIT(b1,13)<< 2) | + (BIT(b3, 0)<< 3) | + (BIT(b1, 7)<< 4) | + (BIT(b2,14)<< 5) | + (BIT(b2, 4)<< 6) | + (BIT(b2, 9)<< 7) | + (BIT(b3, 8)<< 8) | + (BIT(b2, 1)<< 9) | + (BIT(b3, 7)<<10) | + (BIT(b2, 6)<<11) | + (BIT(b1, 0)<<12) | + (BIT(b3,11)<<13) | + (BIT(b2, 8)<<14) | + (BIT(b3,13)<<15) | + (BIT(b1, 8)<<16) | + (BIT(b3,10)<<17) | + (BIT(b3, 6)<<18) | + (BIT(b1,10)<<19) | + (BIT(b2,15)<<20) | + (BIT(b2, 3)<<21) | + (BIT(b1, 5)<<22) | + (BIT(b3,15)<<23); + + plane543 = seibu_partial_carry_sum(plane543, k1, k2, 32) ^ k3; + plane210 = seibu_partial_carry_sum(plane210, i, k4, 24) ^ k5; + if (feversoc_kludge) + plane210 = seibu_partial_carry_sum(plane210, 1, 0x000001, 24); + + rom[0 * size + 2 * i] = plane543 >> 16; + rom[0 * size + 2 * i + 1] = plane543 >> 8; + rom[1 * size + 2 * i] = plane543 >> 0; + rom[1 * size + 2 * i + 1] = plane210 >> 16; + rom[2 * size + 2 * i] = plane210 >> 8; + rom[2 * size + 2 * i + 1] = plane210 >> 0; + } + + for (i = 0; i < size / 2; i += 32) + { + sprite_reorder(&rom[0 * size + 2 * i]); + sprite_reorder(&rom[1 * size + 2 * i]); + sprite_reorder(&rom[2 * size + 2 * i]); + } +} + +/* Raiden Fighters Jet */ +void seibuspi_rise11_sprite_decrypt_rfjet(UINT8 *rom, int size) +{ + seibuspi_rise11_sprite_decrypt(rom, size, 0xabcb64, 0x55aadd, 0xab6a4c, 0xd6375b, 0x8bf23b, 0); +} diff --git a/src/sound/ymf271.c b/src/sound/ymf271.c index b08efc0a..72ed831b 100644 --- a/src/sound/ymf271.c +++ b/src/sound/ymf271.c @@ -561,9 +561,11 @@ static void update_irq(YMF271Chip *chip) chip->irq_callback(chip->irqstate ? 1 : 0); } -static double clocks_to_time(UINT32 clocks) +static int ymf271_clock[MAX_YMF271]; + +static double clocks_to_time(int chipnum, UINT32 clocks) { - return (double)clocks / (double)YMF271_CLOCK; + return (double)clocks / (double)ymf271_clock[chipnum]; } static void timer_a_expired(int chipnum) @@ -575,7 +577,7 @@ static void timer_a_expired(int chipnum) chip->irqstate |= 1; update_irq(chip); } - timer_adjust(chip->timA, clocks_to_time(384 * (1024 - chip->timerA)), chipnum, 0); + timer_adjust(chip->timA, clocks_to_time(chipnum, 384 * (1024 - chip->timerA)), chipnum, 0); } static void timer_b_expired(int chipnum) @@ -588,7 +590,7 @@ static void timer_b_expired(int chipnum) chip->irqstate |= 2; update_irq(chip); } - timer_adjust(chip->timB, clocks_to_time(384 * 16 * (256 - chip->timerB)), chipnum, 0); + timer_adjust(chip->timB, clocks_to_time(chipnum, 384 * 16 * (256 - chip->timerB)), chipnum, 0); } /* utility register write (bank 6): sync, timers, external memory access, test */ @@ -622,9 +624,9 @@ static void write_util(int chipnum, UINT8 address, UINT8 data) /* bit0/1 load A/B, bit2/3 enable IRQ A/B, bit4/5 reset flag A/B. A timer is (re)loaded on the rising edge of its load bit */ if (~chip->timer_ctrl & data & 1) - timer_adjust(chip->timA, clocks_to_time(384 * (1024 - chip->timerA)), chipnum, 0); + timer_adjust(chip->timA, clocks_to_time(chipnum, 384 * (1024 - chip->timerA)), chipnum, 0); if (~chip->timer_ctrl & data & 2) - timer_adjust(chip->timB, clocks_to_time(384 * 16 * (256 - chip->timerB)), chipnum, 0); + timer_adjust(chip->timB, clocks_to_time(chipnum, 384 * 16 * (256 - chip->timerB)), chipnum, 0); if (data & 0x10) { chip->status &= ~0x01; @@ -1415,7 +1417,8 @@ int YMF271_sh_start( const struct MachineSound *msound ) vol[0] = intf->mixing_level[i] & 0xffff; vol[1] = intf->mixing_level[i] >> 16; /* outputs CH0 / CH1 at the chip's sample rate, clock / 384 = 44.1 kHz */ - chip->stream = stream_init_multi(2, name, vol, YMF271_CLOCK / 384, i, ymf271_update); + ymf271_clock[i] = intf->clock[i] ? intf->clock[i] : YMF271_CLOCK; + chip->stream = stream_init_multi(2, name, vol, ymf271_clock[i] / 384, i, ymf271_update); ymf271_reset(chip); ymf271_state_register(i); diff --git a/src/sound/ymf271.h b/src/sound/ymf271.h index 6bd0fe76..d264f853 100644 --- a/src/sound/ymf271.h +++ b/src/sound/ymf271.h @@ -11,6 +11,7 @@ struct YMF271interface read8_handler ext_read[MAX_YMF271]; /* external memory read */ write8_handler ext_write[MAX_YMF271]; /* external memory write */ void (*irq_callback[MAX_YMF271])(int state); /* irq callback */ + int clock[MAX_YMF271]; /* clock in Hz, 0 for the usual 16.9344 MHz */ }; int YMF271_sh_start( const struct MachineSound *msound ); diff --git a/src/vidhrdw/seibuspi_vidhrdw.c b/src/vidhrdw/seibuspi_vidhrdw.c new file mode 100644 index 00000000..cf0acd1d --- /dev/null +++ b/src/vidhrdw/seibuspi_vidhrdw.c @@ -0,0 +1,841 @@ +/*************************************************************************** + + Seibu SPI hardware: the video + + Backported from current MAME src/mame/seibu/seibuspi_v.cpp, + sei25x_rise1x_spr.cpp and seibu_crtc.cpp (Ville Linde, hap, Nicola + Salmoria, Angelo Salese). + + The main CPU builds the tilemaps, the palette and the sprite list in its + RAM, and copies them to the video chip by DMA. Four layers: back, middle + and fore (16x16 tiles, 6bpp, 512x512) and text (8x8, 5bpp, 512x256), + the back, middle and fore ones with an optional scroll per line; the + sprites (16x16, 6bpp, up to 8x8 tiles) have four priorities between the + layers. Some pens are blended half and half with what is under them. + + As in MAME the screen is built by hand in 32 bits: the sprites are drawn + in a 16-bit buffer first (pen and priority), then the layers and the + sprites of each priority go to the screen in order, through the alpha + table. The graphics are decoded here to one byte per pixel, from the + regions the driver decrypted; the regions are dropped afterwards. + +***************************************************************************/ + +#include +#include "driver.h" +#include "state.h" +#include "includes/seibuspi.h" + +#define SPI_SCREEN_W 320 +#define SPI_SCREEN_H 240 + +data32_t *spi_mainram; + +static data32_t spi_tilemap_ram[0x4000 / 4]; +static data32_t spi_palette_ram[0x3000 / 4]; +static data16_t spi_sprite_ram[0x1000 / 2]; +static UINT16 spi_crtc_ram[0x40 / 2]; +static UINT32 spi_pens[6144]; +static UINT8 alpha_table[0x2000]; +static UINT8 alpha_color[0x2000 / 32]; /* a pen of these 32 is blended */ + +static data32_t video_dma_length; +static data32_t video_dma_address; +static UINT16 layer_enable; +static UINT16 layer_bank; +static UINT8 rf2_layer_bank; +static UINT8 rowscroll_enable; +static UINT16 scrollram[6]; + +static int midl_layer_offset, fore_layer_offset, text_layer_offset; +static int fore_layer_d13, back_layer_d14, midl_layer_d14, fore_layer_d14; +static int bg_fore_layer_position; + +/* the graphics, one byte per pixel */ +static UINT8 *tile_gfx, *tile_flags; +static int tile_count; +static UINT8 *char_gfx, *char_flags; +static int char_count; +static UINT8 *sprite_gfx, *sprite_flags; +static int sprite_count; + +#define GFX_TRANSPARENT 1 /* all the pixels are the transparent pen */ +#define GFX_OPAQUE 2 /* none is */ + +/* the sprites: pen (color << 6 | pixel) and priority << 14, 0xffff for none; */ +/* for each line the priorities drawn in it and the span of x, to skip the rest */ +static UINT16 sprite_bitmap[SPI_SCREEN_H][SPI_SCREEN_W]; +static UINT8 sprite_row_pri[SPI_SCREEN_H]; +static INT16 sprite_row_minx[SPI_SCREEN_H], sprite_row_maxx[SPI_SCREEN_H]; + + +/*****************************************************************************/ + +static void set_layer_offsets(void) +{ + if (rowscroll_enable) + { + fore_layer_offset = 0x1000 / 4; + midl_layer_offset = 0x2000 / 4; + text_layer_offset = 0x3000 / 4; + } + else + { + fore_layer_offset = 0x1000 / 4 / 2; + midl_layer_offset = 0x2000 / 4 / 2; + text_layer_offset = 0x3000 / 4 / 2; + } + + fore_layer_d13 = layer_bank << 2 & 0x2000; + back_layer_d14 = rf2_layer_bank << 14 & 0x4000; + midl_layer_d14 = rf2_layer_bank << 13 & 0x4000; + fore_layer_d14 = rf2_layer_bank << 12 & 0x4000; +} + +static void set_pen(int pen, UINT32 data) +{ + int r = data & 0x1f, g = (data >> 5) & 0x1f, b = (data >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + spi_pens[pen] = (r << 16) | (g << 8) | b; +} + +void spi_rf2_layer_bank_w(UINT8 data) +{ + /* 00000fmb */ + /* f: fore layer d14 */ + /* m: middle layer d14 */ + /* b: back layer d14 */ + rf2_layer_bank = data; + set_layer_offsets(); +} + + +/***************************************************************************** + + The CRTC (0x400-0x43f): 16-bit registers, two per dword. The registers + with a callback in MAME read back 0 (their RAM is never written), but + 0x1a (the layer bank, the game reads it). + +*****************************************************************************/ + +static void crtc_reg_w(int reg, UINT16 data) +{ + switch (reg) + { + case 0x14 / 2: /* decryption key: the tiles are decrypted at load */ + if (data != 0 && data != 1) + logerror("SPI: decryption key %04X\n", data); + break; + + case 0x1a / 2: /* r000f000 0010100a, r: rowscroll enable, f: fore layer d13 */ + layer_bank = data; + rowscroll_enable = (layer_bank >> 15) & 1; + set_layer_offsets(); + break; + + case 0x1c / 2: /* 00000000 000stfmb (0=on, 1=off): sprites, text, fore, middle, back */ + layer_enable = data; + break; + + case 0x20 / 2: case 0x22 / 2: case 0x24 / 2: + case 0x26 / 2: case 0x28 / 2: case 0x2a / 2: + scrollram[reg - 0x20 / 2] = data; + break; + + case 0x2c / 2: case 0x2e / 2: case 0x30 / 2: case 0x32 / 2: + case 0x34 / 2: case 0x36 / 2: case 0x38 / 2: case 0x3a / 2: + break; /* layer scroll base, unused */ + + default: + spi_crtc_ram[reg] = data; + break; + } +} + +READ32_HANDLER( spi_crtc_r ) +{ + int reg = offset * 2; + UINT16 lo = (reg == 0x1a / 2) ? layer_bank : spi_crtc_ram[reg]; + UINT16 hi = (reg + 1 == 0x1a / 2) ? layer_bank : spi_crtc_ram[reg + 1]; + + return lo | (hi << 16); +} + +WRITE32_HANDLER( spi_crtc_w ) +{ + int half; + + for (half = 0; half < 2; half++) + { + int reg = offset * 2 + half; + UINT16 mask = (mem_mask >> (16 * half)) & 0xffff; + UINT16 old, d; + + if (mask == 0xffff) + continue; + if (reg == 0x1a / 2) + old = layer_bank; + else if (reg == 0x1c / 2) + old = layer_enable; + else if (reg >= 0x20 / 2 && reg <= 0x2a / 2) + old = scrollram[reg - 0x20 / 2]; + else + old = spi_crtc_ram[reg]; + d = (old & mask) | (((data >> (16 * half)) & 0xffff) & ~mask); + crtc_reg_w(reg, d); + } +} + + +/***************************************************************************** + + The DMAs from the main RAM + +*****************************************************************************/ + +WRITE32_HANDLER( spi_video_dma_length_w ) +{ + COMBINE_DATA(&video_dma_length); +} + +WRITE32_HANDLER( spi_video_dma_address_w ) +{ + COMBINE_DATA(&video_dma_address); +} + +WRITE32_HANDLER( spi_tilemap_dma_start_w ) +{ + int index = video_dma_address / 4; + int i; + + /* back layer */ + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[i] = spi_mainram[index++ & 0xffff]; + + /* back layer row scroll */ + if (rowscroll_enable) + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[0x800 / 4 + i] = spi_mainram[index++ & 0xffff]; + + /* fore layer */ + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[i + fore_layer_offset] = spi_mainram[index++ & 0xffff]; + + /* fore layer row scroll */ + if (rowscroll_enable) + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[0x2800 / 4 + i] = spi_mainram[index++ & 0xffff]; + + /* middle layer */ + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[i + midl_layer_offset] = spi_mainram[index++ & 0xffff]; + + /* middle layer row scroll */ + if (rowscroll_enable) + for (i = 0; i < 0x800 / 4; i++) + spi_tilemap_ram[0x1800 / 4 + i] = spi_mainram[index++ & 0xffff]; + + /* text layer */ + for (i = 0; i < 0x1000 / 4; i++) + spi_tilemap_ram[i + text_layer_offset] = spi_mainram[index++ & 0xffff]; +} + +WRITE32_HANDLER( spi_palette_dma_start_w ) +{ + int dma_length = (video_dma_length + 1) * 2; + int i; + + if (dma_length > 0x3000) + dma_length = 0x3000; + for (i = 0; i < dma_length / 4; i++) + { + UINT32 color = spi_mainram[(video_dma_address / 4 + i) & 0xffff]; + if (spi_palette_ram[i] != color) + { + spi_palette_ram[i] = color; + set_pen((i * 2), color); + set_pen((i * 2) + 1, color >> 16); + } + } +} + +void spi_sprite_dma_start(void) +{ + int i; + + for (i = 0; i < 0x1000 / 4; i++) + { + UINT32 d = spi_mainram[((video_dma_address / 4) + i) & 0xffff]; + spi_sprite_ram[i << 1] = d & 0xffff; + spi_sprite_ram[(i << 1) | 1] = (d >> 16) & 0xffff; + } +} + + +/***************************************************************************** + + The graphics decoding, to one byte per pixel (the layouts of MAME) + +*****************************************************************************/ + +/* 16x16 tiles, 6 planes { 0, 4, 8, 12, 16, 20 }, x STEP4(3,-1) STEP4(27,-1) */ +/* STEP4(51,-1) STEP4(75,-1), y STEP16(0,96): four groups of 24 bits a row, */ +/* each four pixels; 8x8 chars, 5 planes { 4, 8, 12, 16, 20 }, two groups */ +static void decode_group24(const UINT8 *src, UINT8 *dest, int planes) +{ + UINT32 w = (src[0] << 16) | (src[1] << 8) | src[2]; + int i, p; + + for (i = 0; i < 4; i++) + { + int pix = 0; + for (p = 0; p < planes; p++) + { + /* plane p at bit offset 4 * (p + 6 - planes), pixel i at offset 3 - i */ + int bit = 23 - (4 * (p + 6 - planes) + 3 - i); + pix |= ((w >> bit) & 1) << (planes - 1 - p); + } + dest[i] = pix; + } +} + +static void decode_tiles(const UINT8 *src, int count, int size, int planes, UINT8 *gfx, UINT8 *flags) +{ + int n, y, g, i; + int bytes_per_row = size / 4 * 3; /* 12 for tiles, 6 for chars */ + int transpen = (1 << planes) - 1; + + for (n = 0; n < count; n++) + { + UINT8 *dest = gfx + n * size * size; + int opaque = 1, transparent = 1; + + for (y = 0; y < size; y++) + for (g = 0; g < size / 4; g++) + decode_group24(src + n * size * bytes_per_row + y * bytes_per_row + g * 3, dest + y * size + g * 4, planes); + for (i = 0; i < size * size; i++) + { + if (dest[i] == transpen) + opaque = 0; + else + transparent = 0; + } + flags[n] = (transparent ? GFX_TRANSPARENT : 0) | (opaque ? GFX_OPAQUE : 0); + } +} + +/* 16x16 sprites, the region in thirds, planes { 0, 8, F/3, F/3+8, 2F/3, 2F/3+8 }, */ +/* x STEP8(7,-1) STEP8(23,-1), y STEP16(0,32) */ +static void decode_sprites(const UINT8 *src, int third, int count, UINT8 *gfx) +{ + int n, y, x; + + for (n = 0; n < count; n++) + { + for (y = 0; y < 16; y++) + { + const UINT8 *s0 = src + n * 64 + y * 4; + const UINT8 *s1 = s0 + third; + const UINT8 *s2 = s1 + third; + UINT8 *dest = gfx + n * 256 + y * 16; + + for (x = 0; x < 16; x++) + { + int o = (x < 8) ? 0 : 2; + int b = x & 7; + dest[x] = (((s0[o] >> b) & 1) << 5) | (((s0[o + 1] >> b) & 1) << 4) | + (((s1[o] >> b) & 1) << 3) | (((s1[o + 1] >> b) & 1) << 2) | + (((s2[o] >> b) & 1) << 1) | ((s2[o + 1] >> b) & 1); + } + } + } +} + + +/*****************************************************************************/ + +static void spi_postload(void) +{ + int i; + + for (i = 0; i < 0x3000 / 4; i++) + { + set_pen((i * 2), spi_palette_ram[i]); + set_pen((i * 2) + 1, spi_palette_ram[i] >> 16); + } + set_layer_offsets(); +} + +VIDEO_START( spi ) +{ + int region_length = memory_region_length(REGION_GFX2); + + video_dma_length = 0; + video_dma_address = 0; + layer_enable = 0; + layer_bank = 0; + rf2_layer_bank = 0; + rowscroll_enable = 0; + memset(scrollram, 0, sizeof(scrollram)); + memset(spi_crtc_ram, 0, sizeof(spi_crtc_ram)); + memset(spi_tilemap_ram, 0, sizeof(spi_tilemap_ram)); + memset(spi_palette_ram, 0, sizeof(spi_palette_ram)); + memset(spi_sprite_ram, 0, sizeof(spi_sprite_ram)); + memset(spi_pens, 0, sizeof(spi_pens)); + memset(sprite_bitmap, 0xff, sizeof(sprite_bitmap)); + memset(sprite_row_pri, 0, sizeof(sprite_row_pri)); + set_layer_offsets(); + + if (region_length <= 0x300000) + bg_fore_layer_position = 0x2000; + else if (region_length <= 0x600000) + bg_fore_layer_position = 0x4000; + else + bg_fore_layer_position = 0x8000; + + /* the graphics */ + tile_count = region_length / 192; + tile_gfx = auto_malloc(tile_count * 256); + tile_flags = auto_malloc(tile_count); + char_count = memory_region_length(REGION_GFX1) / 48; + char_gfx = auto_malloc(char_count * 64); + char_flags = auto_malloc(char_count); + sprite_count = memory_region_length(REGION_GFX3) / 3 / 64; + sprite_gfx = auto_malloc(sprite_count * 256); + sprite_flags = auto_malloc(sprite_count); + if (!tile_gfx || !tile_flags || !char_gfx || !char_flags || !sprite_gfx || !sprite_flags) + return 1; + decode_tiles(memory_region(REGION_GFX2), tile_count, 16, 6, tile_gfx, tile_flags); + decode_tiles(memory_region(REGION_GFX1), char_count, 8, 5, char_gfx, char_flags); + decode_sprites(memory_region(REGION_GFX3), memory_region_length(REGION_GFX3) / 3, sprite_count, sprite_gfx); + { + int n, i; + for (n = 0; n < sprite_count; n++) + { + const UINT8 *g = sprite_gfx + n * 256; + int opaque = 1, transparent = 1; + for (i = 0; i < 256; i++) + { + if (g[i] == 63) + opaque = 0; + else + transparent = 0; + } + sprite_flags[n] = (transparent ? GFX_TRANSPARENT : 0) | (opaque ? GFX_OPAQUE : 0); + } + } + + /* TODO : Differs per games? */ + /* alpha blending (preliminary) */ + memset(alpha_table, 0, sizeof(alpha_table)); + + /* sprites(0000-0fff): */ + /*memset(alpha_table + 0x700, 1, 0x10); breaks rdft */ + memset(alpha_table + 0x730, 1, 0x10); + memset(alpha_table + 0x780, 1, 0x20); + /*memset(alpha_table + 0x7c0, 1, 0x40); breaks batlball */ + /*memset(alpha_table + 0xf00, 1, 0x40); breaks rdft */ + memset(alpha_table + 0xfc0, 1, 0x40); + + /* back layer(1000-11ff): nope */ + /* fore layer(1200-13ff): */ + memset(alpha_table + 0x1200 + 0x160, 1, 0x20); + memset(alpha_table + 0x1200 + 0x1b0, 1, 0x10); + memset(alpha_table + 0x1200 + 0x1f0, 1, 0x10); + /* midl layer(1400-15ff) */ + memset(alpha_table + 0x1400 + 0x1b0, 1, 0x10); + memset(alpha_table + 0x1400 + 0x1f0, 1, 0x10); + /* text layer(1600-17ff) */ + memset(alpha_table + 0x1600 + 0x170, 1, 0x10); + memset(alpha_table + 0x1600 + 0x1f0, 1, 0x10); + { + int i; + memset(alpha_color, 0, sizeof(alpha_color)); + for (i = 0; i < 0x2000; i++) + if (alpha_table[i]) + alpha_color[i >> 5] = 1; + } + + state_save_register_UINT32("spi_video", 0, "tilemap_ram", spi_tilemap_ram, 0x4000 / 4); + state_save_register_UINT32("spi_video", 0, "palette_ram", spi_palette_ram, 0x3000 / 4); + state_save_register_UINT16("spi_video", 0, "sprite_ram", spi_sprite_ram, 0x1000 / 2); + state_save_register_UINT16("spi_video", 0, "crtc_ram", spi_crtc_ram, 0x40 / 2); + state_save_register_UINT32("spi_video", 0, "video_dma_length", &video_dma_length, 1); + state_save_register_UINT32("spi_video", 0, "video_dma_address", &video_dma_address, 1); + state_save_register_UINT16("spi_video", 0, "layer_enable", &layer_enable, 1); + state_save_register_UINT16("spi_video", 0, "layer_bank", &layer_bank, 1); + state_save_register_UINT8("spi_video", 0, "rf2_layer_bank", &rf2_layer_bank, 1); + state_save_register_UINT8("spi_video", 0, "rowscroll_enable", &rowscroll_enable, 1); + state_save_register_UINT16("spi_video", 0, "scrollram", scrollram, 6); + state_save_register_func_postload(spi_postload); + + return 0; +} + + +/***************************************************************************** + + The screen + +*****************************************************************************/ + +static INLINE UINT32 spi_alpha_blend(UINT32 d, UINT32 s) +{ + /* level 0x7f, as MAME */ + return ((((s & 0x0000ff) * 0x7f + (d & 0x0000ff) * 0x81) >> 8)) | + ((((s & 0x00ff00) * 0x7f + (d & 0x00ff00) * 0x81) >> 8) & 0x00ff00) | + ((((s & 0xff0000) * 0x7f + (d & 0xff0000) * 0x81) >> 8) & 0xff0000); +} + +static INLINE void blend_pixel(UINT32 *dest, int pen) +{ + if (alpha_table[pen]) + *dest = spi_alpha_blend(*dest, spi_pens[pen]); + else + *dest = spi_pens[pen]; +} + +/* the sprites in the raw buffer, the last one first (the first one on top) */ +static void draw_sprites(void) +{ + int i, ax, ay, x, y; + + /* clear what the frame before drew */ + for (y = 0; y < SPI_SCREEN_H; y++) + { + if (sprite_row_pri[y]) + for (x = sprite_row_minx[y]; x <= sprite_row_maxx[y]; x++) + sprite_bitmap[y][x] = 0xffff; + sprite_row_pri[y] = 0; + sprite_row_minx[y] = SPI_SCREEN_W; + sprite_row_maxx[y] = -1; + } + + for (i = 0x1000 / 2 - 4; i >= 0; i -= 4) + { + const UINT16 *spr = &spi_sprite_ram[i]; + UINT32 code = spr[1]; + int flipy, sizey, flipx, sizex, pri, color, ext, sx0, sy0; + + if ((code % sprite_count) == 0) + continue; + + flipy = (spr[0] >> 15) & 1; + sizey = ((spr[0] >> 12) & 7) + 1; + flipx = (spr[0] >> 11) & 1; + sizex = ((spr[0] >> 8) & 7) + 1; + pri = (spr[0] >> 6) & 3; + color = spr[0] & 0x3f; + ext = (spr[2] >> 12) & 1; + sx0 = spr[2] & 0x1ff; + sy0 = spr[3] & 0x1ff; + + if (sx0 >= 0x180) sx0 -= 0x200; + if (sy0 >= 0x180) sy0 -= 0x200; + + color = (color << 6) | (pri << 14); + if (sprite_count > 0x10000 && ext) + code |= 0x10000; + + for (ax = 0; ax < sizex; ax++) + { + int sx = flipx ? (sx0 + 16 * (sizex - ax - 1)) : (sx0 + 16 * ax); + for (ay = 0; ay < sizey; ay++) + { + int sy = flipy ? (sy0 + 16 * (sizey - ay - 1)) : (sy0 + 16 * ay); + int c = code % sprite_count; + const UINT8 *gfx = sprite_gfx + c * 256; + int x0 = 0, x1 = 16, y0 = 0, y1 = 16; + + code++; + if (sx >= SPI_SCREEN_W || sy >= SPI_SCREEN_H || sx <= -16 || sy <= -16) + continue; + if (sprite_flags[c] & GFX_TRANSPARENT) + continue; + if (sx < 0) x0 = -sx; + if (sx + 16 > SPI_SCREEN_W) x1 = SPI_SCREEN_W - sx; + if (sy < 0) y0 = -sy; + if (sy + 16 > SPI_SCREEN_H) y1 = SPI_SCREEN_H - sy; + + for (y = y0; y < y1; y++) + { + const UINT8 *src = gfx + (flipy ? 15 - y : y) * 16; + UINT16 *dest = &sprite_bitmap[sy + y][sx]; + sprite_row_pri[sy + y] |= 1 << pri; + if (sx + x0 < sprite_row_minx[sy + y]) sprite_row_minx[sy + y] = sx + x0; + if (sx + x1 - 1 > sprite_row_maxx[sy + y]) sprite_row_maxx[sy + y] = sx + x1 - 1; + if (flipx) + { + const UINT8 *s = src + 15; + for (x = x0; x < x1; x++) + { + int pix = s[-x]; + if (pix != 63) + dest[x] = color + pix; + } + } + else + { + for (x = x0; x < x1; x++) + { + int pix = src[x]; + if (pix != 63) + dest[x] = color + pix; + } + } + } + } + } + } +} + +static void blend_sprite(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int pri) +{ + int x, y; + + if (layer_enable & 0x10) + return; + + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + const UINT16 *src = sprite_bitmap[y]; + UINT32 *dest = (UINT32 *)bitmap->line[y]; + int x0 = sprite_row_minx[y], x1 = sprite_row_maxx[y]; + + if (!(sprite_row_pri[y] & (1 << pri))) + continue; + if (x0 < cliprect->min_x) x0 = cliprect->min_x; + if (x1 > cliprect->max_x) x1 = cliprect->max_x; + for (x = x0; x <= x1; x++) + { + int pen = src[x]; + if (((pen & 0xc000) == (pri << 14)) && (pen != 0xffff)) + blend_pixel(&dest[x], pen & ~0xc000); + } + } +} + +enum { LAYER_BACK = 0, LAYER_MIDL, LAYER_FORE }; + +/* a 16x16 layer, 32x32 tiles in columns */ +/* sprites_only: only where the priority 0 sprites are (the back layer */ +/* drawn again over them; elsewhere it would draw the same pixels again) */ +static void combine_layer(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int layer, int sx, int sy, int opaque, const data32_t *rowscroll, int sprites_only) +{ + int x, y, maxx; + int offset, colorbase, codeor; + + switch (layer) + { + default: + case LAYER_BACK: + offset = 0; + colorbase = 4096; + codeor = back_layer_d14; + break; + case LAYER_MIDL: + offset = midl_layer_offset; + colorbase = 4096 + 16 * 64; + codeor = 0x2000 | midl_layer_d14; + break; + case LAYER_FORE: + offset = fore_layer_offset; + colorbase = 4096 + 8 * 64; + codeor = bg_fore_layer_position | fore_layer_d13 | fore_layer_d14; + break; + } + + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + UINT32 *dest = (UINT32 *)bitmap->line[y]; + int rx = sx; + int my = (y + sy) & 511; + int row = my >> 4; + int line = (my & 15) * 16; + + if (rowscroll) + { + /* the adder probably comes from the CRTC */ + int r = (y + 19) & 511; + rx += (INT16)(rowscroll[r >> 1] >> ((r & 1) * 16)); + } + + x = cliprect->min_x; + maxx = cliprect->max_x; + if (sprites_only) + { + if (!(sprite_row_pri[y] & 1)) + continue; + if (sprite_row_minx[y] > x) x = sprite_row_minx[y]; + if (sprite_row_maxx[y] < maxx) maxx = sprite_row_maxx[y]; + } + while (x <= maxx) + { + int mx = (x + rx) & 511; + int tile_index = (mx >> 4) * 32 + row; + UINT32 tile = (spi_tilemap_ram[(tile_index >> 1) + offset] >> ((tile_index & 1) * 16)) & 0xffff; + int code = (tile & 0x1fff) | codeor; + int pens = colorbase + ((tile >> 13) & 7) * 64; + const UINT8 *src; + int span = 16 - (mx & 15); + int i; + + if (code >= tile_count) + code %= tile_count; + src = tile_gfx + code * 256 + line; + + if (x + span > maxx + 1) + span = maxx + 1 - x; + + /* the span stays in the tile: its pixels from mx & 15 on */ + src += mx & 15; + if (!opaque && (tile_flags[code] & GFX_TRANSPARENT)) + ; /* nothing to draw */ + else if (!(alpha_color[pens >> 5] | alpha_color[(pens >> 5) + 1])) + { + /* nothing blended: the pens straight */ + const UINT32 *pal = &spi_pens[pens]; + UINT32 *d = &dest[x]; + if (opaque || (tile_flags[code] & GFX_OPAQUE)) + { + for (i = 0; i < span; i++) + d[i] = pal[src[i]]; + } + else + { + for (i = 0; i < span; i++) + { + int pix = src[i]; + if (pix != 63) + d[i] = pal[pix]; + } + } + } + else + { + for (i = 0; i < span; i++) + { + int pix = src[i]; + if (opaque || pix != 63) + blend_pixel(&dest[x + i], pens + pix); + } + } + x += span; + } + } +} + +/* the text layer, 8x8, 64x32 tiles in rows, no scroll */ +static void combine_text(struct mame_bitmap *bitmap, const struct rectangle *cliprect) +{ + int x, y; + + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + UINT32 *dest = (UINT32 *)bitmap->line[y]; + int my = y & 255; + int row = my >> 3; + int line = (my & 7) * 8; + + x = cliprect->min_x; + while (x <= cliprect->max_x) + { + int mx = x & 511; + int tile_index = row * 64 + (mx >> 3); + UINT32 tile = (spi_tilemap_ram[(tile_index >> 1) + text_layer_offset] >> ((tile_index & 1) * 16)) & 0xffff; + int code = tile & 0xfff; + int pens = 5632 + ((tile >> 12) & 0xf) * 32; + const UINT8 *src; + int span = 8 - (mx & 7); + int i; + + if (code >= char_count) + code %= char_count; + src = char_gfx + code * 64 + line; + + if (x + span > cliprect->max_x + 1) + span = cliprect->max_x + 1 - x; + + src += mx & 7; + if (char_flags[code] & GFX_TRANSPARENT) + ; /* nothing to draw */ + else if (!alpha_color[pens >> 5]) + { + const UINT32 *pal = &spi_pens[pens]; + UINT32 *d = &dest[x]; + for (i = 0; i < span; i++) + { + int pix = src[i]; + if (pix != 31) + d[i] = pal[pix]; + } + } + else + { + for (i = 0; i < span; i++) + { + int pix = src[i]; + if (pix != 31) + blend_pixel(&dest[x + i], pens + pix); + } + } + x += span; + } + } +} + +VIDEO_UPDATE( spi ) +{ + const data32_t *back_rowscroll, *midl_rowscroll, *fore_rowscroll; + + if (rowscroll_enable) + { + back_rowscroll = &spi_tilemap_ram[0x200]; + midl_rowscroll = &spi_tilemap_ram[0x600]; + fore_rowscroll = &spi_tilemap_ram[0xa00]; + } + else + { + back_rowscroll = NULL; + midl_rowscroll = NULL; + fore_rowscroll = NULL; + } + + if (!(layer_enable & 0x10)) + draw_sprites(); + + if (layer_enable & 1) + fillbitmap(bitmap, 0, cliprect); + else + combine_layer(bitmap, cliprect, LAYER_BACK, scrollram[0], scrollram[1], 1, back_rowscroll, 0); + + blend_sprite(bitmap, cliprect, 0); + + /* if fore layer is enabled, draw priority 0 sprites behind back layer */ + if ((layer_enable & 0x15) == 0) + combine_layer(bitmap, cliprect, LAYER_BACK, scrollram[0], scrollram[1], 0, back_rowscroll, 1); + + /* if fore layer is enabled, draw priority 1 sprites behind middle layer */ + if (~layer_enable & 4) + blend_sprite(bitmap, cliprect, 1); + + if (~layer_enable & 2) + combine_layer(bitmap, cliprect, LAYER_MIDL, scrollram[2], scrollram[3], 0, midl_rowscroll, 0); + + /* if fore layer is disabled, draw priority 1 sprites above middle layer */ + if (layer_enable & 4) + blend_sprite(bitmap, cliprect, 1); + + blend_sprite(bitmap, cliprect, 2); + + if (~layer_enable & 4) + combine_layer(bitmap, cliprect, LAYER_FORE, scrollram[4], scrollram[5], 0, fore_rowscroll, 0); + + blend_sprite(bitmap, cliprect, 3); + + if (~layer_enable & 8) + combine_text(bitmap, cliprect); +}