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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MEgow1uRCv8pxMErKhmoHZ
This commit is contained in:
Claude committed 2026-10-24 17:54:15 +02:00
1 parent ac620b3686
commit 14e3abc89f
25 files changed
+17474 -20

No files matched your search

+12
View File
@@ -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
+674
View File
@@ -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__ */
+868
View File
@@ -0,0 +1,868 @@
/*
Intel 386 emulator
Written by Ville Linde
Currently supports:
Intel 386
Intel 486
Intel Pentium
Cyrix MediaGX
*/
#include <string.h>
#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;
}
+39
View File
@@ -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
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+377
View File
@@ -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), }
};
File diff suppressed because it is too large. Load diff
+424
View File
@@ -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 */
}
+53
View File
@@ -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);
}
}
}
+352
View File
@@ -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);
}
}
}
+6
View File
@@ -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
+3
View File
@@ -262,6 +262,9 @@ enum
#if (HAS_H83002)
CPU_H83002,
#endif
#if (HAS_I386)
CPU_I386,
#endif
#if (HAS_MN10200)
CPU_MN10200,
#endif
+59
View File
@@ -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
File diff suppressed because it is too large. Load diff
+36
View File
@@ -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
+297
View File
@@ -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 <string.h>
#include <time.h>
#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( &current_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 ) );
}
+27
View File
@@ -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
+34 -8
View File
@@ -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++ )
+7 -5
View File
@@ -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 );
+507
View File
@@ -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 <string.h>
#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);
}
+10 -7
View File
@@ -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);
+1
View File
@@ -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 );
+841
View File
@@ -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 <string.h>
#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);
}