mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 04:16:07 -10:00
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:
25 files changed
+17474
-20
No files matched your search
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -262,6 +262,9 @@ enum
|
||||
#if (HAS_H83002)
|
||||
CPU_H83002,
|
||||
#endif
|
||||
#if (HAS_I386)
|
||||
CPU_I386,
|
||||
#endif
|
||||
#if (HAS_MN10200)
|
||||
CPU_MN10200,
|
||||
#endif
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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( ¤t_time );
|
||||
current_time -= ref_time;
|
||||
|
||||
ds2404_rtc[ 0 ] = 0;
|
||||
ds2404_rtc[ 1 ] = ( current_time >> 0 ) & 0xff;
|
||||
ds2404_rtc[ 2 ] = ( current_time >> 8 ) & 0xff;
|
||||
ds2404_rtc[ 3 ] = ( current_time >> 16 ) & 0xff;
|
||||
ds2404_rtc[ 4 ] = ( current_time >> 24 ) & 0xff;
|
||||
|
||||
memset( ds2404_sram, 0, sizeof( ds2404_sram ) );
|
||||
memset( ds2404_ram, 0, sizeof( ds2404_ram ) );
|
||||
memset( ds2404_state, DS2404_IDLE, sizeof( ds2404_state ) );
|
||||
ds2404_state_ptr = 0;
|
||||
ds2404_address = 0;
|
||||
ds2404_offset = 0;
|
||||
ds2404_end_offset = 0;
|
||||
ds2404_a1 = ds2404_a2 = 0;
|
||||
|
||||
ds2404_timer = timer_alloc( ds2404_tick );
|
||||
timer_adjust( ds2404_timer, TIME_IN_HZ( 256 ), 0, TIME_IN_HZ( 256 ) );
|
||||
ds2404_timer_left = 0;
|
||||
|
||||
state_save_register_UINT16( "ds2404", 0, "address", &ds2404_address, 1 );
|
||||
state_save_register_UINT16( "ds2404", 0, "offset", &ds2404_offset, 1 );
|
||||
state_save_register_UINT16( "ds2404", 0, "end_offset", &ds2404_end_offset, 1 );
|
||||
state_save_register_UINT8( "ds2404", 0, "a1", &ds2404_a1, 1 );
|
||||
state_save_register_UINT8( "ds2404", 0, "a2", &ds2404_a2, 1 );
|
||||
state_save_register_UINT8( "ds2404", 0, "sram", ds2404_sram, sizeof( ds2404_sram ) );
|
||||
state_save_register_UINT8( "ds2404", 0, "ram", ds2404_ram, sizeof( ds2404_ram ) );
|
||||
state_save_register_UINT8( "ds2404", 0, "rtc", ds2404_rtc, sizeof( ds2404_rtc ) );
|
||||
state_save_register_UINT8( "ds2404", 0, "state", ds2404_state, sizeof( ds2404_state ) );
|
||||
state_save_register_UINT8( "ds2404", 0, "state_ptr", &ds2404_state_ptr, 1 );
|
||||
state_save_register_double( "ds2404", 0, "timer_left", &ds2404_timer_left, 1 );
|
||||
state_save_register_func_presave( ds2404_presave );
|
||||
state_save_register_func_postload( ds2404_postload );
|
||||
}
|
||||
|
||||
static void ds2404_rom_cmd( UINT8 cmd )
|
||||
{
|
||||
switch( cmd )
|
||||
{
|
||||
case 0xcc: /* skip ROM */
|
||||
ds2404_state[ 0 ] = DS2404_COMMAND;
|
||||
ds2404_state_ptr = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror( "DS2404: unknown ROM command %02X\n", cmd );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ds2404_cmd( UINT8 cmd )
|
||||
{
|
||||
switch( cmd )
|
||||
{
|
||||
case 0x0f: /* write scratchpad */
|
||||
ds2404_state[ 0 ] = DS2404_ADDRESS1;
|
||||
ds2404_state[ 1 ] = DS2404_ADDRESS2;
|
||||
ds2404_state[ 2 ] = DS2404_INIT_COMMAND;
|
||||
ds2404_state[ 3 ] = DS2404_WRITE_SCRATCHPAD;
|
||||
ds2404_state_ptr = 0;
|
||||
break;
|
||||
|
||||
case 0x55: /* copy scratchpad */
|
||||
ds2404_state[ 0 ] = DS2404_ADDRESS1;
|
||||
ds2404_state[ 1 ] = DS2404_ADDRESS2;
|
||||
ds2404_state[ 2 ] = DS2404_OFFSET;
|
||||
ds2404_state[ 3 ] = DS2404_INIT_COMMAND;
|
||||
ds2404_state[ 4 ] = DS2404_COPY_SCRATCHPAD;
|
||||
ds2404_state_ptr = 0;
|
||||
break;
|
||||
|
||||
case 0xf0: /* read memory */
|
||||
ds2404_state[ 0 ] = DS2404_ADDRESS1;
|
||||
ds2404_state[ 1 ] = DS2404_ADDRESS2;
|
||||
ds2404_state[ 2 ] = DS2404_INIT_COMMAND;
|
||||
ds2404_state[ 3 ] = DS2404_READ_MEMORY;
|
||||
ds2404_state_ptr = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror( "DS2404: unknown command %02X\n", cmd );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 ds2404_readmem( void )
|
||||
{
|
||||
if( ds2404_address < 0x200 )
|
||||
return ds2404_sram[ ds2404_address ];
|
||||
else if( ds2404_address >= 0x202 && ds2404_address <= 0x206 )
|
||||
return ds2404_rtc[ ds2404_address - 0x202 ];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ds2404_writemem( UINT8 value )
|
||||
{
|
||||
if( ds2404_address < 0x200 )
|
||||
ds2404_sram[ ds2404_address ] = value;
|
||||
else if( ds2404_address >= 0x202 && ds2404_address <= 0x206 )
|
||||
ds2404_rtc[ ds2404_address - 0x202 ] = value;
|
||||
}
|
||||
|
||||
WRITE_HANDLER( ds2404_1w_reset_w )
|
||||
{
|
||||
ds2404_state[ 0 ] = DS2404_IDLE;
|
||||
ds2404_state_ptr = 0;
|
||||
}
|
||||
|
||||
WRITE_HANDLER( ds2404_3w_reset_w )
|
||||
{
|
||||
ds2404_state[ 0 ] = DS2404_COMMAND;
|
||||
ds2404_state_ptr = 0;
|
||||
}
|
||||
|
||||
READ_HANDLER( ds2404_data_r )
|
||||
{
|
||||
UINT8 value = 0;
|
||||
|
||||
switch( ds2404_state[ ds2404_state_ptr ] )
|
||||
{
|
||||
case DS2404_READ_MEMORY:
|
||||
value = ds2404_readmem();
|
||||
break;
|
||||
|
||||
case DS2404_READ_SCRATCHPAD:
|
||||
if( ds2404_offset < 0x20 )
|
||||
{
|
||||
value = ds2404_ram[ ds2404_offset ];
|
||||
ds2404_offset++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
WRITE_HANDLER( ds2404_data_w )
|
||||
{
|
||||
int i;
|
||||
|
||||
switch( ds2404_state[ ds2404_state_ptr ] )
|
||||
{
|
||||
case DS2404_IDLE:
|
||||
ds2404_rom_cmd( data & 0xff );
|
||||
break;
|
||||
|
||||
case DS2404_COMMAND:
|
||||
ds2404_cmd( data & 0xff );
|
||||
break;
|
||||
|
||||
case DS2404_ADDRESS1:
|
||||
ds2404_a1 = data & 0xff;
|
||||
ds2404_state_ptr++;
|
||||
break;
|
||||
|
||||
case DS2404_ADDRESS2:
|
||||
ds2404_a2 = data & 0xff;
|
||||
ds2404_state_ptr++;
|
||||
break;
|
||||
|
||||
case DS2404_OFFSET:
|
||||
ds2404_end_offset = data & 0xff;
|
||||
ds2404_state_ptr++;
|
||||
break;
|
||||
|
||||
case DS2404_WRITE_SCRATCHPAD:
|
||||
if( ds2404_offset < 0x20 )
|
||||
{
|
||||
ds2404_ram[ ds2404_offset ] = data & 0xff;
|
||||
ds2404_offset++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( ds2404_state[ ds2404_state_ptr ] == DS2404_INIT_COMMAND )
|
||||
{
|
||||
switch( ds2404_state[ ds2404_state_ptr + 1 ] )
|
||||
{
|
||||
case DS2404_READ_MEMORY:
|
||||
ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1;
|
||||
ds2404_address -= 1;
|
||||
break;
|
||||
|
||||
case DS2404_WRITE_SCRATCHPAD:
|
||||
case DS2404_READ_SCRATCHPAD:
|
||||
ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1;
|
||||
ds2404_offset = ds2404_address & 0x1f;
|
||||
break;
|
||||
|
||||
case DS2404_COPY_SCRATCHPAD:
|
||||
ds2404_address = ( ds2404_a2 << 8 ) | ds2404_a1;
|
||||
for( i = 0; i <= ds2404_end_offset; i++ )
|
||||
{
|
||||
/* MAME reads past the 32 bytes of the scratchpad here: stay in it */
|
||||
ds2404_writemem( ds2404_ram[ i & 0x1f ] );
|
||||
ds2404_address++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ds2404_state_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_HANDLER( ds2404_clk_w )
|
||||
{
|
||||
if( ds2404_state[ ds2404_state_ptr ] == DS2404_READ_MEMORY )
|
||||
ds2404_address++;
|
||||
}
|
||||
|
||||
void ds2404_nvram_load( mame_file *file )
|
||||
{
|
||||
mame_fread( file, ds2404_sram, sizeof( ds2404_sram ) );
|
||||
}
|
||||
|
||||
void ds2404_nvram_save( mame_file *file )
|
||||
{
|
||||
mame_fwrite( file, ds2404_sram, sizeof( ds2404_sram ) );
|
||||
}
|
||||
@@ -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
@@ -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++ )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user