Added WinChip 2 emulation, along with (currently non-recompiled) 3DNow! instruction emulation.
This commit is contained in:
parent
5043cff3f9
commit
da2d819ed4
8 changed files with 607 additions and 25 deletions
112
src/386_ops.h
112
src/386_ops.h
|
|
@ -104,6 +104,15 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ILLEGAL(uint32_t fetchdat)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
|
||||
// fatal("Illegal instruction %08X\n", fetchdat);
|
||||
x86illegal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "x86_ops_arith.h"
|
||||
#include "x86_ops_atomic.h"
|
||||
#include "x86_ops_bcd.h"
|
||||
|
|
@ -118,6 +127,7 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
|||
#include "x86_ops_jump.h"
|
||||
#include "x86_ops_misc.h"
|
||||
#include "x86_ops_mmx.h"
|
||||
#include "x86_ops_3dnow.h"
|
||||
#include "x86_ops_mmx_arith.h"
|
||||
#include "x86_ops_mmx_cmp.h"
|
||||
#include "x86_ops_mmx_logic.h"
|
||||
|
|
@ -140,15 +150,6 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
|||
#include "x86_ops_string.h"
|
||||
#include "x86_ops_xchg.h"
|
||||
|
||||
static int ILLEGAL(uint32_t fetchdat)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
|
||||
// fatal("Illegal instruction %08X\n", fetchdat);
|
||||
x86illegal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int op0F_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
int opcode = fetchdat & 0xff;
|
||||
|
|
@ -455,7 +456,98 @@ OpFn OP_TABLE(winchip_0f)[1024] =
|
|||
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||
};
|
||||
|
||||
OpFn OP_TABLE(pentium_0f)[1024] =
|
||||
OpFn OP_TABLE(winchip2_0f)[1024] =
|
||||
{
|
||||
/*16-bit data, 16-bit addr*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
|
||||
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
|
||||
|
||||
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
|
||||
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
|
||||
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
|
||||
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
|
||||
|
||||
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
|
||||
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
|
||||
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
|
||||
|
||||
/*32-bit data, 16-bit addr*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
|
||||
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
|
||||
|
||||
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
|
||||
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
|
||||
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
|
||||
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
|
||||
|
||||
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
|
||||
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
|
||||
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
|
||||
|
||||
/*16-bit data, 32-bit addr*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
|
||||
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
|
||||
|
||||
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
|
||||
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
|
||||
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
|
||||
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
|
||||
|
||||
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
|
||||
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
|
||||
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||
|
||||
/*32-bit data, 32-bit addr*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
|
||||
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
|
||||
|
||||
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
|
||||
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
|
||||
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
|
||||
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
|
||||
|
||||
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
|
||||
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
|
||||
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||
};
|
||||
|
||||
OpFn OP_TABLE(pentium_0f)[1024] =
|
||||
{
|
||||
/*16-bit data, 16-bit addr*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ static uint8_t opcode_modrm[256] =
|
|||
};
|
||||
static uint8_t opcode_0f_modrm[256] =
|
||||
{
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/
|
||||
|
|
|
|||
146
src/cpu.c
146
src/cpu.c
|
|
@ -34,6 +34,7 @@ OpFn *x86_dynarec_opcodes_df_a16;
|
|||
OpFn *x86_dynarec_opcodes_df_a32;
|
||||
OpFn *x86_dynarec_opcodes_REPE;
|
||||
OpFn *x86_dynarec_opcodes_REPNE;
|
||||
OpFn *x86_dynarec_opcodes_3DNOW;
|
||||
|
||||
OpFn *x86_opcodes;
|
||||
OpFn *x86_opcodes_0f;
|
||||
|
|
@ -55,6 +56,7 @@ OpFn *x86_opcodes_df_a16;
|
|||
OpFn *x86_opcodes_df_a32;
|
||||
OpFn *x86_opcodes_REPE;
|
||||
OpFn *x86_opcodes_REPNE;
|
||||
OpFn *x86_opcodes_3DNOW;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -68,6 +70,12 @@ enum
|
|||
CPUID_MMX = (1 << 23)
|
||||
};
|
||||
|
||||
/*Addition flags returned by CPUID function 0x80000001*/
|
||||
enum
|
||||
{
|
||||
CPUID_3DNOW = (1 << 31)
|
||||
};
|
||||
|
||||
int cpu = 3, cpu_manufacturer = 0;
|
||||
CPU *cpu_s;
|
||||
int cpu_multi;
|
||||
|
|
@ -79,6 +87,7 @@ int cpu_hasMMX, cpu_hasMSR;
|
|||
int cpu_hasCR4;
|
||||
int cpu_hasCX8;
|
||||
int cpu_hasVME;
|
||||
int cpu_has3DNOW;
|
||||
int cpu_use_dynarec;
|
||||
int cpu_cyrix_alignment;
|
||||
|
||||
|
|
@ -402,8 +411,22 @@ CPU cpus_WinChip[] =
|
|||
{"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2},
|
||||
{"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7},
|
||||
{"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
|
||||
{"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
|
||||
{"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
|
||||
{"", -1, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_WinChip_SS7[] =
|
||||
{
|
||||
/*IDT WinChip (Super Socket 7)*/
|
||||
{"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
|
||||
{"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
|
||||
{"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
|
||||
{"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
|
||||
{"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
|
||||
{"", -1, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
@ -505,6 +528,7 @@ void cpu_set()
|
|||
cpu_hasMSR = 0;
|
||||
cpu_hasCR4 = 0;
|
||||
cpu_hasCX8 = 0;
|
||||
cpu_has3DNOW = 0;
|
||||
ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0;
|
||||
has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86);
|
||||
|
||||
|
|
@ -548,8 +572,10 @@ void cpu_set()
|
|||
x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f);
|
||||
x86_opcodes_REPE = ops_REPE;
|
||||
x86_opcodes_REPNE = ops_REPNE;
|
||||
x86_opcodes_3DNOW = ops_3DNOW;
|
||||
x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
|
||||
x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE;
|
||||
x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW;
|
||||
|
||||
if (hasfpu)
|
||||
{
|
||||
|
|
@ -950,7 +976,7 @@ void cpu_set()
|
|||
timing_bt = 3-1; /*branch taken*/
|
||||
timing_bnt = 1; /*branch not taken*/
|
||||
cpu_hasrdtsc = 1;
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
msr.fcr = (1 << 8) | (1 << 16);
|
||||
cpu_hasMMX = cpu_hasMSR = 1;
|
||||
cpu_hasCR4 = 1;
|
||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||
|
|
@ -978,6 +1004,46 @@ void cpu_set()
|
|||
codegen_timing_set(&codegen_timing_winchip);
|
||||
break;
|
||||
|
||||
case CPU_WINCHIP2:
|
||||
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
|
||||
timing_rr = 1; /*register dest - register src*/
|
||||
timing_rm = 2; /*register dest - memory src*/
|
||||
timing_mr = 2; /*memory dest - register src*/
|
||||
timing_mm = 3;
|
||||
timing_rml = 2; /*register dest - memory src long*/
|
||||
timing_mrl = 2; /*memory dest - register src long*/
|
||||
timing_mml = 3;
|
||||
timing_bt = 3-1; /*branch taken*/
|
||||
timing_bnt = 1; /*branch not taken*/
|
||||
cpu_hasrdtsc = 1;
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
|
||||
cpu_hasMMX = cpu_hasMSR = cpu_has3DNOW = 1;
|
||||
cpu_hasCR4 = 1;
|
||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||
/*unknown*/
|
||||
timing_int_rm = 26;
|
||||
timing_int_v86 = 82;
|
||||
timing_int_pm = 44;
|
||||
timing_int_pm_outer = 71;
|
||||
timing_iret_rm = 7;
|
||||
timing_iret_v86 = 26;
|
||||
timing_iret_pm = 10;
|
||||
timing_iret_pm_outer = 26;
|
||||
timing_call_rm = 4;
|
||||
timing_call_pm = 15;
|
||||
timing_call_pm_gate = 26;
|
||||
timing_call_pm_gate_inner = 35;
|
||||
timing_retf_rm = 4;
|
||||
timing_retf_pm = 7;
|
||||
timing_retf_pm_outer = 23;
|
||||
timing_jmp_rm = 5;
|
||||
timing_jmp_pm = 7;
|
||||
timing_jmp_pm_gate = 17;
|
||||
timing_misaligned = 2;
|
||||
cpu_cyrix_alignment = 1;
|
||||
codegen_timing_set(&codegen_timing_winchip);
|
||||
break;
|
||||
|
||||
case CPU_PENTIUM:
|
||||
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
|
||||
timing_rr = 1; /*register dest - register src*/
|
||||
|
|
@ -1308,7 +1374,7 @@ void cpu_CPUID()
|
|||
else
|
||||
{
|
||||
EBX = 0x746e6543; /*CentaurHauls*/
|
||||
ECX = 0x736c7561;
|
||||
ECX = 0x736c7561;
|
||||
EDX = 0x48727561;
|
||||
}
|
||||
}
|
||||
|
|
@ -1317,14 +1383,74 @@ void cpu_CPUID()
|
|||
EAX = 0x540;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
|
||||
if (cpu_hasCX8)
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
if (cpu_hasCX8)
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
if (msr.fcr & (1 << 9))
|
||||
EDX |= CPUID_MMX;
|
||||
}
|
||||
else
|
||||
EAX = EBX = ECX = EDX = 0;
|
||||
break;
|
||||
|
||||
case CPU_WINCHIP2:
|
||||
switch (EAX)
|
||||
{
|
||||
case 0:
|
||||
EAX = 1;
|
||||
if (msr.fcr2 & (1 << 14))
|
||||
{
|
||||
EBX = msr.fcr3 >> 32;
|
||||
ECX = msr.fcr3 & 0xffffffff;
|
||||
EDX = msr.fcr2 >> 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
EBX = 0x746e6543; /*CentaurHauls*/
|
||||
ECX = 0x736c7561;
|
||||
EDX = 0x48727561;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
EAX = 0x580;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
|
||||
if (cpu_hasCX8)
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
if (msr.fcr & (1 << 9))
|
||||
EDX |= CPUID_MMX;
|
||||
break;
|
||||
case 0x80000000:
|
||||
EAX = 0x80000005;
|
||||
break;
|
||||
case 0x80000001:
|
||||
EAX = 0x580;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
|
||||
if (cpu_hasCX8)
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
if (msr.fcr & (1 << 9))
|
||||
EDX |= CPUID_MMX;
|
||||
if (cpu_has3DNOW)
|
||||
EDX |= CPUID_3DNOW;
|
||||
break;
|
||||
|
||||
case 0x80000002: /*Processor name string*/
|
||||
EAX = 0x20544449; /*IDT WinChip 2-3D*/
|
||||
EBX = 0x436e6957;
|
||||
ECX = 0x20706968;
|
||||
EDX = 0x44332d32;
|
||||
break;
|
||||
|
||||
case 0x80000005: /*Cache information*/
|
||||
EBX = 0x08800880; /*TLBs*/
|
||||
ECX = 0x20040120; /*L1 data cache*/
|
||||
EDX = 0x20020120; /*L1 instruction cache*/
|
||||
break;
|
||||
|
||||
default:
|
||||
EAX = EBX = ECX = EDX = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_PENTIUM:
|
||||
if (!EAX)
|
||||
|
|
@ -1447,6 +1573,7 @@ void cpu_RDMSR()
|
|||
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
|
||||
{
|
||||
case CPU_WINCHIP:
|
||||
case CPU_WINCHIP2:
|
||||
EAX = EDX = 0;
|
||||
switch (ECX)
|
||||
{
|
||||
|
|
@ -1507,6 +1634,7 @@ void cpu_WRMSR()
|
|||
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
|
||||
{
|
||||
case CPU_WINCHIP:
|
||||
case CPU_WINCHIP2:
|
||||
switch (ECX)
|
||||
{
|
||||
case 0x02:
|
||||
|
|
@ -1525,9 +1653,13 @@ void cpu_WRMSR()
|
|||
msr.fcr = EAX;
|
||||
cpu_hasMMX = EAX & (1 << 9);
|
||||
if (EAX & (1 << 1))
|
||||
cpu_hasCX8 = 1;
|
||||
cpu_hasCX8 = 1;
|
||||
else
|
||||
cpu_hasCX8 = 0;
|
||||
cpu_hasCX8 = 0;
|
||||
if ((EAX & (1 << 20)) && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2)
|
||||
cpu_has3DNOW = 1;
|
||||
else
|
||||
cpu_has3DNOW = 0;
|
||||
if (EAX & (1 << 29))
|
||||
CPUID = 0;
|
||||
else
|
||||
|
|
|
|||
15
src/cpu.h
15
src/cpu.h
|
|
@ -28,12 +28,13 @@ extern int cpu, cpu_manufacturer;
|
|||
|
||||
/*586 class CPUs*/
|
||||
#define CPU_WINCHIP 15
|
||||
#define CPU_PENTIUM 16
|
||||
#define CPU_PENTIUMMMX 17
|
||||
#define CPU_Cx6x86 18
|
||||
#define CPU_Cx6x86MX 19
|
||||
#define CPU_Cx6x86L 20
|
||||
#define CPU_CxGX1 21
|
||||
#define CPU_WINCHIP2 16
|
||||
#define CPU_PENTIUM 17
|
||||
#define CPU_PENTIUMMMX 18
|
||||
#define CPU_Cx6x86 19
|
||||
#define CPU_Cx6x86MX 20
|
||||
#define CPU_Cx6x86L 21
|
||||
#define CPU_CxGX1 22
|
||||
|
||||
#define MANU_INTEL 0
|
||||
#define MANU_AMD 1
|
||||
|
|
@ -84,6 +85,7 @@ extern CPU cpus_i486[];
|
|||
extern CPU cpus_Am486[];
|
||||
extern CPU cpus_Cx486[];
|
||||
extern CPU cpus_WinChip[];
|
||||
extern CPU cpus_WinChip_SS7[];
|
||||
extern CPU cpus_Pentium5V[];
|
||||
extern CPU cpus_PentiumS5[];
|
||||
extern CPU cpus_Pentium[];
|
||||
|
|
@ -111,6 +113,7 @@ extern int cpu_hasMMX;
|
|||
extern int cpu_hasCR4;
|
||||
extern int cpu_hasVME;
|
||||
extern int cpu_hasCX8;
|
||||
extern int cpu_has3DNOW;
|
||||
|
||||
#define CR4_TSD (1 << 2)
|
||||
#define CR4_DE (1 << 3)
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ typedef union MMX_REG
|
|||
int16_t sw[4];
|
||||
uint8_t b[8];
|
||||
int8_t sb[8];
|
||||
float f[2];
|
||||
} MMX_REG;
|
||||
|
||||
struct
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ MODEL models[] =
|
|||
|
||||
{"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 256, 1, at_i430vx_init, NULL},
|
||||
|
||||
{"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL},
|
||||
{"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL},
|
||||
|
||||
{"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ extern OpFn *x86_dynarec_opcodes_df_a16;
|
|||
extern OpFn *x86_dynarec_opcodes_df_a32;
|
||||
extern OpFn *x86_dynarec_opcodes_REPE;
|
||||
extern OpFn *x86_dynarec_opcodes_REPNE;
|
||||
extern OpFn *x86_dynarec_opcodes_3DNOW;
|
||||
|
||||
extern OpFn dynarec_ops_286[1024];
|
||||
extern OpFn dynarec_ops_286_0f[1024];
|
||||
|
|
@ -33,6 +34,7 @@ extern OpFn dynarec_ops_386[1024];
|
|||
extern OpFn dynarec_ops_386_0f[1024];
|
||||
|
||||
extern OpFn dynarec_ops_winchip_0f[1024];
|
||||
extern OpFn dynarec_ops_winchip2_0f[1024];
|
||||
|
||||
extern OpFn dynarec_ops_pentium_0f[1024];
|
||||
extern OpFn dynarec_ops_pentiummmx_0f[1024];
|
||||
|
|
@ -67,6 +69,8 @@ extern OpFn dynarec_ops_fpu_686_df_a32[256];
|
|||
extern OpFn dynarec_ops_REPE[1024];
|
||||
extern OpFn dynarec_ops_REPNE[1024];
|
||||
|
||||
extern OpFn dynarec_ops_3DNOW[256];
|
||||
|
||||
extern OpFn *x86_opcodes;
|
||||
extern OpFn *x86_opcodes_0f;
|
||||
extern OpFn *x86_opcodes_d8_a16;
|
||||
|
|
@ -87,6 +91,7 @@ extern OpFn *x86_opcodes_df_a16;
|
|||
extern OpFn *x86_opcodes_df_a32;
|
||||
extern OpFn *x86_opcodes_REPE;
|
||||
extern OpFn *x86_opcodes_REPNE;
|
||||
extern OpFn *x86_opcodes_3DNOW;
|
||||
|
||||
extern OpFn ops_286[1024];
|
||||
extern OpFn ops_286_0f[1024];
|
||||
|
|
@ -95,6 +100,7 @@ extern OpFn ops_386[1024];
|
|||
extern OpFn ops_386_0f[1024];
|
||||
|
||||
extern OpFn ops_winchip_0f[1024];
|
||||
extern OpFn ops_winchip2_0f[1024];
|
||||
|
||||
extern OpFn ops_pentium_0f[1024];
|
||||
extern OpFn ops_pentiummmx_0f[1024];
|
||||
|
|
@ -130,4 +136,6 @@ extern OpFn ops_fpu_686_df_a32[256];
|
|||
extern OpFn ops_REPE[1024];
|
||||
extern OpFn ops_REPNE[1024];
|
||||
|
||||
extern OpFn ops_3DNOW[256];
|
||||
|
||||
#endif /*_X86_OPS_H*/
|
||||
|
|
|
|||
346
src/x86_ops_3dnow.h
Normal file
346
src/x86_ops_3dnow.h
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
#include <math.h>
|
||||
|
||||
static int opPREFETCH_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
static int opPREFETCH_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFEMMS(uint32_t fetchdat)
|
||||
{
|
||||
ILLEGAL_ON(!cpu_hasMMX);
|
||||
if (cr0 & 4)
|
||||
{
|
||||
x86_int(7);
|
||||
return 1;
|
||||
}
|
||||
x87_emms();
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPAVGUSB(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] + src.b[0] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] + src.b[1] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] + src.b[2] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] + src.b[3] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] + src.b[4] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] + src.b[5] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] + src.b[6] + 1) >> 1;
|
||||
cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] + src.b[7] + 1) >> 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPF2ID(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sl[0] = (int32_t)src.f[0];
|
||||
cpu_state.MM[cpu_reg].sl[1] = (int32_t)src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFACC(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
float tempf;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
tempf = cpu_state.MM[cpu_reg].f[0] + cpu_state.MM[cpu_reg].f[1];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1];
|
||||
cpu_state.MM[cpu_reg].f[0] = tempf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFADD(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] += src.f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] += src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFCMPEQ(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] == src.f[0]) ? 0xffffffff : 0;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] == src.f[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFCMPGE(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] >= src.f[0]) ? 0xffffffff : 0;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] >= src.f[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFCMPGT(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] > src.f[0]) ? 0xffffffff : 0;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] > src.f[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFMAX(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
if (src.f[0] > cpu_state.MM[cpu_reg].f[0])
|
||||
cpu_state.MM[cpu_reg].f[0] = src.f[0];
|
||||
if (src.f[1] > cpu_state.MM[cpu_reg].f[1])
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFMIN(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
if (src.f[0] < cpu_state.MM[cpu_reg].f[0])
|
||||
cpu_state.MM[cpu_reg].f[0] = src.f[0];
|
||||
if (src.f[1] < cpu_state.MM[cpu_reg].f[1])
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFMUL(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] *= src.f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] *= src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFRCP(uint32_t fetchdat)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t i;
|
||||
float f;
|
||||
} src;
|
||||
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
src.f = cpu_state.MM[cpu_rm].f[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = 1.0/src.f;
|
||||
cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*Since opPFRCP() calculates a full precision reciprocal, treat the followup iterations as MOVs*/
|
||||
static int opPFRCPIT1(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = src.f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFRCPIT2(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = src.f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFRSQRT(uint32_t fetchdat)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t i;
|
||||
float f;
|
||||
} src;
|
||||
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
src.f = cpu_state.MM[cpu_rm].f[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = 1.0/sqrt(src.f);
|
||||
cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*Since opPFRSQRT() calculates a full precision inverse square root, treat the followup iteration as a NOP*/
|
||||
static int opPFRSQIT1(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
UNUSED(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFSUB(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] -= src.f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] -= src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFSUBR(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = src.f[0] - cpu_state.MM[cpu_reg].f[0];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[1] - cpu_state.MM[cpu_reg].f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPI2FD(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = (float)src.sl[0];
|
||||
cpu_state.MM[cpu_reg].f[1] = (float)src.sl[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPMULHRW(uint32_t fetchdat)
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] = (((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)cpu_state.MM[cpu_rm].sw[0]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[1] = (((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)cpu_state.MM[cpu_rm].sw[1]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[2] = (((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)cpu_state.MM[cpu_rm].sw[2]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[3] = (((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)cpu_state.MM[cpu_rm].sw[3]) + 0x8000) >> 16;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
|
||||
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
|
||||
cpu_state.MM[cpu_reg].w[0] = ((int32_t)(cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[1] = ((int32_t)(cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[2] = ((int32_t)(cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + 0x8000) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[3] = ((int32_t)(cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) + 0x8000) >> 16;
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpFn OP_TABLE(3DNOW)[256] =
|
||||
{
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FD, ILLEGAL, ILLEGAL,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2ID, ILLEGAL, ILLEGAL,
|
||||
/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*90*/ opPFCMPGE, ILLEGAL, ILLEGAL, ILLEGAL, opPFMIN, ILLEGAL, opPFRCP, opPFRSQRT, ILLEGAL, ILLEGAL, opPFSUB, ILLEGAL, ILLEGAL, ILLEGAL, opPFADD, ILLEGAL,
|
||||
/*a0*/ opPFCMPGT, ILLEGAL, ILLEGAL, ILLEGAL, opPFMAX, ILLEGAL, opPFRCPIT1, opPFRSQIT1, ILLEGAL, ILLEGAL, opPFSUBR, ILLEGAL, ILLEGAL, ILLEGAL, opPFACC, ILLEGAL,
|
||||
/*b0*/ opPFCMPEQ, ILLEGAL, ILLEGAL, ILLEGAL, opPFMUL, ILLEGAL, opPFRCPIT2, opPMULHRW, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPAVGUSB,
|
||||
|
||||
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
};
|
||||
|
||||
static int op3DNOW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
opcode = fastreadb(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
return x86_opcodes_3DNOW[opcode](0);
|
||||
}
|
||||
static int op3DNOW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
opcode = fastreadb(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
return x86_opcodes_3DNOW[opcode](0);
|
||||
}
|
||||
Loading…
Reference in a new issue