Added MMX emulation (probably some bugs). Implemented RDMSR/WRMSR for Winchip.

This commit is contained in:
TomW 2013-08-03 15:05:50 +01:00
commit 119fe36820
17 changed files with 2362 additions and 65 deletions

View file

@ -1210,8 +1210,6 @@ void cpu_386_flags_rebuild()
int oldi;
static uint64_t tsc = 0;
uint32_t testr[9];
int dontprint=0;

View file

@ -76,6 +76,13 @@ static inline uint32_t POP_L()
#include "x86_ops_io.h"
#include "x86_ops_jump.h"
#include "x86_ops_misc.h"
#include "x86_ops_mmx.h"
#include "x86_ops_mmx_arith.h"
#include "x86_ops_mmx_cmp.h"
#include "x86_ops_mmx_logic.h"
#include "x86_ops_mmx_mov.h"
#include "x86_ops_mmx_pack.h"
#include "x86_ops_mmx_shift.h"
#include "x86_ops_mov.h"
#include "x86_ops_mov_ctrl.h"
#include "x86_ops_mov_seg.h"
@ -95,6 +102,8 @@ static inline uint32_t POP_L()
static int ILLEGAL(uint32_t fetchdat)
{
pc = oldpc;
// fatal("Illegal instruction %08X\n", fetchdat);
x86illegal();
return 0;
}
@ -103,13 +112,20 @@ static int op0F_w_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
pc++;
if (x86_opcodes_0f[opcode] == ILLEGAL && opcode != 0xff)
{
fatal("Illegal 0f instruction %02X w_a16\n", opcode);
}
return x86_opcodes_0f[opcode](fetchdat >> 8);
}
static int op0F_l_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
pc++;
if (x86_opcodes_0f[opcode | 0x100] == ILLEGAL && opcode != 0xff)
{
fatal("Illegal 0f instruction %02X l_a16\n", opcode);
}
return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8);
}
@ -117,6 +133,10 @@ static int op0F_w_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
pc++;
if (x86_opcodes_0f[opcode | 0x200] == ILLEGAL && opcode != 0xff)
{
fatal("Illegal 0f instruction %02X w_a32\n", opcode);
}
return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8);
}
@ -124,6 +144,10 @@ static int op0F_l_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
pc++;
if (x86_opcodes_0f[opcode | 0x300] == ILLEGAL && opcode != 0xff)
{
fatal("Illegal 0f instruction %02X l_a32\n", opcode);
}
return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8);
}
@ -232,7 +256,7 @@ OpFn ops_386_0f[1024] =
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ ILLEGAL, opRDTSC, 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,
@ -254,7 +278,7 @@ OpFn ops_386_0f[1024] =
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ ILLEGAL, opRDTSC, 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,
@ -276,7 +300,7 @@ OpFn ops_386_0f[1024] =
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ ILLEGAL, opRDTSC, 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,
@ -298,7 +322,7 @@ OpFn ops_386_0f[1024] =
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ ILLEGAL, opRDTSC, 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,
@ -316,6 +340,97 @@ OpFn ops_386_0f[1024] =
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
};
OpFn ops_winchip_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, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ 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*/ 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,ILLEGAL, 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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*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,
/*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, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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, ILLEGAL, 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, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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*/ 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*/ 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,ILLEGAL, 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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*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,
/*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, opLOADALL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*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, ILLEGAL, 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 ops_286[1024] =
{
/*16-bit data, 16-bit addr*/

124
src/cpu.c
View file

@ -4,6 +4,14 @@
#include "io.h"
#include "x86_ops.h"
enum
{
CPUID_FPU = (1 << 0),
CPUID_TSC = (1 << 4),
CPUID_MSR = (1 << 5),
CPUID_MMX = (1 << 23)
};
int cpu = 3, cpu_manufacturer = 0;
CPU *cpu_s;
int cpu_multi;
@ -11,6 +19,8 @@ int cpu_iscyrix;
int cpu_16bitbus;
int cpu_busspeed;
int cpu_hasrdtsc;
int cpu_hasMMX, cpu_hasMSR;
uint64_t tsc = 0;
int timing_rr;
int timing_mr, timing_mrl;
@ -18,6 +28,14 @@ int timing_rm, timing_rml;
int timing_mm, timing_mml;
int timing_bt, timing_bnt;
static struct
{
uint32_t tr1, tr12;
uint32_t cesr;
uint32_t fcr;
uint64_t fcr2, fcr3;
} msr;
/*Available cpuspeeds :
0 = 16 MHz
1 = 20 MHz
@ -239,6 +257,8 @@ void cpu_set()
cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
cpu_multi = cpu_s->multi;
cpu_hasrdtsc = 0;
cpu_hasMMX = 0;
cpu_hasMSR = 0;
if (cpu_iscyrix)
io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
@ -250,6 +270,8 @@ void cpu_set()
x86_setopcodes(ops_386, ops_386_0f);
memset(&msr, 0, sizeof(msr));
switch (cpu_s->cpu_type)
{
case CPU_8088:
@ -370,6 +392,7 @@ void cpu_set()
break;
case CPU_WINCHIP:
x86_setopcodes(ops_386, ops_winchip_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
@ -380,6 +403,8 @@ 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);
cpu_hasMMX = cpu_hasMSR = 1;
break;
default:
@ -403,7 +428,7 @@ void cpu_CPUID()
{
EAX = CPUID;
EBX = ECX = 0;
EDX = 1; /*FPU*/
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = 0;
@ -438,7 +463,7 @@ void cpu_CPUID()
{
EAX = CPUID;
EBX = ECX = 0;
EDX = 1; /*FPU*/
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = 0;
@ -448,15 +473,26 @@ void cpu_CPUID()
if (!EAX)
{
EAX = 1;
EBX = 0x746e6543; /*CentaurHauls*/
ECX = 0x736c7561;
EDX = 0x48727561;
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;
}
}
else if (EAX == 1)
{
EAX = CPUID;
EAX = 0x540;
EBX = ECX = 0;
EDX = 1; /*FPU*/
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
}
else
EAX = 0;
@ -464,6 +500,80 @@ void cpu_CPUID()
}
}
void cpu_RDMSR()
{
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
EAX = EDX = 0;
switch (ECX)
{
case 0x02:
EAX = msr.tr1;
break;
case 0x0e:
EAX = msr.tr12;
break;
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
case 0x11:
EAX = msr.cesr;
break;
case 0x107:
EAX = msr.fcr;
break;
case 0x108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
case 0x10a:
EAX = cpu_multi & 3;
break;
}
break;
}
}
void cpu_WRMSR()
{
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
EAX = EDX = 0;
switch (ECX)
{
case 0x02:
msr.tr1 = EAX & 2;
break;
case 0x0e:
msr.tr12 = EAX & 0x228;
break;
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
case 0x11:
msr.cesr = EAX & 0xff00ff;
break;
case 0x107:
msr.fcr = EAX;
cpu_hasMMX = EAX & (1 << 9);
if (EAX & (1 << 29))
CPUID = 0;
else
CPUID = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
break;
case 0x108:
msr.fcr2 = EAX | ((uint64_t)EDX << 32);
break;
case 0x109:
msr.fcr3 = EAX | ((uint64_t)EDX << 32);
break;
}
break;
}
}
static int cyrix_addr;

View file

@ -71,8 +71,15 @@ extern int cpu_busspeed;
extern int cpu_multi;
extern int cpu_hasrdtsc;
extern int cpu_hasMSR;
extern int cpu_hasMMX;
extern uint64_t tsc;
void cyrix_write(uint16_t addr, uint8_t val, void *priv);
uint8_t cyrix_read(uint16_t addr, void *priv);
extern int is8086;
void cpu_RDMSR();
void cpu_WRMSR();

View file

@ -10,3 +10,5 @@ extern OpFn ops_286_0f[1024];
extern OpFn ops_386[1024];
extern OpFn ops_386_0f[1024];
extern OpFn ops_winchip_0f[1024];

View file

@ -2,7 +2,7 @@
static int opESCAPE_ ## num ##_a16(uint32_t fetchdat) \
{ \
flags_rebuild(); \
if ((cr0 & 6) == 4) \
if (cr0 & 0xc) \
{ \
x86_int(7); \
} \
@ -24,7 +24,7 @@
static int opESCAPE_ ## num ## _a32(uint32_t fetchdat) \
{ \
flags_rebuild(); \
if ((cr0 & 6) == 4) \
if (cr0 & 0xc) \
{ \
x86_int(7); \
} \
@ -55,6 +55,11 @@ opESCAPE(df);
static int opWAIT(uint32_t fetchdat)
{
if ((cr0 & 0xa) == 0xa)
{
x86_int(7);
return 0;
}
cycles -= 4;
return 0;
}

View file

@ -675,4 +675,29 @@ static int opCPUID(uint32_t fetchdat)
return 0;
}
static int opRDMSR(uint32_t fetchdat)
{
if (cpu_hasMSR)
{
cpu_RDMSR();
cycles -= 9;
return 0;
}
pc = oldpc;
x86illegal();
return 0;
}
static int opWRMSR(uint32_t fetchdat)
{
if (cpu_hasMSR)
{
cpu_WRMSR();
cycles -= 9;
return 0;
}
pc = oldpc;
x86illegal();
return 0;
}

49
src/x86_ops_mmx.h Normal file
View file

@ -0,0 +1,49 @@
#define SSATB(val) (((val) < -128) ? -128 : (((val) > 127) ? 127 : (val)))
#define SSATW(val) (((val) < -32768) ? -32768 : (((val) > 32767) ? 32767 : (val)))
#define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val)))
#define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val)))
#define MMX_GETSRC() \
if (mod == 3) \
{ \
src = MM[rm]; \
cycles--; \
} \
else \
{ \
src.l[0] = readmeml(easeg, eaaddr); \
src.l[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0; \
cycles -= 2; \
}
#define MMX_ENTER() \
if (!cpu_hasMMX) \
{ \
pc = oldpc; \
x86illegal(); \
return 0; \
} \
if (cr0 & 0xc) \
{ \
x86_int(7); \
return 0; \
} \
x87_set_mmx()
int opEMMS(uint32_t fetchdat)
{
if (!cpu_hasMMX)
{
pc = oldpc;
x86illegal();
return 0;
}
if (cr0 & 4)
{
x86_int(7);
return 0;
}
x87_emms();
cycles -= 100; /*Guess*/
return 0;
}

625
src/x86_ops_mmx_arith.h Normal file
View file

@ -0,0 +1,625 @@
int opPADDB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] += src.b[0];
MM[reg].b[1] += src.b[1];
MM[reg].b[2] += src.b[2];
MM[reg].b[3] += src.b[3];
MM[reg].b[4] += src.b[4];
MM[reg].b[5] += src.b[5];
MM[reg].b[6] += src.b[6];
MM[reg].b[7] += src.b[7];
return 0;
}
int opPADDB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] += src.b[0];
MM[reg].b[1] += src.b[1];
MM[reg].b[2] += src.b[2];
MM[reg].b[3] += src.b[3];
MM[reg].b[4] += src.b[4];
MM[reg].b[5] += src.b[5];
MM[reg].b[6] += src.b[6];
MM[reg].b[7] += src.b[7];
return 0;
}
int opPADDW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] += src.w[0];
MM[reg].w[1] += src.w[1];
MM[reg].w[2] += src.w[2];
MM[reg].w[3] += src.w[3];
return 0;
}
int opPADDW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] += src.w[0];
MM[reg].w[1] += src.w[1];
MM[reg].w[2] += src.w[2];
MM[reg].w[3] += src.w[3];
return 0;
}
int opPADDD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] += src.l[0];
MM[reg].l[1] += src.l[1];
return 0;
}
int opPADDD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].l[0] += src.l[0];
MM[reg].l[1] += src.l[1];
return 0;
}
int opPADDSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].sb[0] = SSATB(MM[reg].sb[0] + src.sb[0]);
MM[reg].sb[1] = SSATB(MM[reg].sb[1] + src.sb[1]);
MM[reg].sb[2] = SSATB(MM[reg].sb[2] + src.sb[2]);
MM[reg].sb[3] = SSATB(MM[reg].sb[3] + src.sb[3]);
MM[reg].sb[4] = SSATB(MM[reg].sb[4] + src.sb[4]);
MM[reg].sb[5] = SSATB(MM[reg].sb[5] + src.sb[5]);
MM[reg].sb[6] = SSATB(MM[reg].sb[6] + src.sb[6]);
MM[reg].sb[7] = SSATB(MM[reg].sb[7] + src.sb[7]);
return 0;
}
int opPADDSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].sb[0] = SSATB(MM[reg].sb[0] + src.sb[0]);
MM[reg].sb[1] = SSATB(MM[reg].sb[1] + src.sb[1]);
MM[reg].sb[2] = SSATB(MM[reg].sb[2] + src.sb[2]);
MM[reg].sb[3] = SSATB(MM[reg].sb[3] + src.sb[3]);
MM[reg].sb[4] = SSATB(MM[reg].sb[4] + src.sb[4]);
MM[reg].sb[5] = SSATB(MM[reg].sb[5] + src.sb[5]);
MM[reg].sb[6] = SSATB(MM[reg].sb[6] + src.sb[6]);
MM[reg].sb[7] = SSATB(MM[reg].sb[7] + src.sb[7]);
return 0;
}
int opPADDUSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = USATB(MM[reg].b[0] + src.b[0]);
MM[reg].b[1] = USATB(MM[reg].b[1] + src.b[1]);
MM[reg].b[2] = USATB(MM[reg].b[2] + src.b[2]);
MM[reg].b[3] = USATB(MM[reg].b[3] + src.b[3]);
MM[reg].b[4] = USATB(MM[reg].b[4] + src.b[4]);
MM[reg].b[5] = USATB(MM[reg].b[5] + src.b[5]);
MM[reg].b[6] = USATB(MM[reg].b[6] + src.b[6]);
MM[reg].b[7] = USATB(MM[reg].b[7] + src.b[7]);
return 0;
}
int opPADDUSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = USATB(MM[reg].b[0] + src.b[0]);
MM[reg].b[1] = USATB(MM[reg].b[1] + src.b[1]);
MM[reg].b[2] = USATB(MM[reg].b[2] + src.b[2]);
MM[reg].b[3] = USATB(MM[reg].b[3] + src.b[3]);
MM[reg].b[4] = USATB(MM[reg].b[4] + src.b[4]);
MM[reg].b[5] = USATB(MM[reg].b[5] + src.b[5]);
MM[reg].b[6] = USATB(MM[reg].b[6] + src.b[6]);
MM[reg].b[7] = USATB(MM[reg].b[7] + src.b[7]);
return 0;
}
int opPADDSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].sw[0] = SSATW(MM[reg].sw[0] + src.sw[0]);
MM[reg].sw[1] = SSATW(MM[reg].sw[1] + src.sw[1]);
MM[reg].sw[2] = SSATW(MM[reg].sw[2] + src.sw[2]);
MM[reg].sw[3] = SSATW(MM[reg].sw[3] + src.sw[3]);
return 0;
}
int opPADDSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].sw[0] = SSATW(MM[reg].sw[0] + src.sw[0]);
MM[reg].sw[1] = SSATW(MM[reg].sw[1] + src.sw[1]);
MM[reg].sw[2] = SSATW(MM[reg].sw[2] + src.sw[2]);
MM[reg].sw[3] = SSATW(MM[reg].sw[3] + src.sw[3]);
return 0;
}
int opPADDUSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = USATW(MM[reg].w[0] + src.w[0]);
MM[reg].w[1] = USATW(MM[reg].w[1] + src.w[1]);
MM[reg].w[2] = USATW(MM[reg].w[2] + src.w[2]);
MM[reg].w[3] = USATW(MM[reg].w[3] + src.w[3]);
return 0;
}
int opPADDUSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = USATW(MM[reg].w[0] + src.w[0]);
MM[reg].w[1] = USATW(MM[reg].w[1] + src.w[1]);
MM[reg].w[2] = USATW(MM[reg].w[2] + src.w[2]);
MM[reg].w[3] = USATW(MM[reg].w[3] + src.w[3]);
return 0;
}
int opPMADDWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
if (MM[reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
MM[reg].l[0] = 0x80000000;
else
MM[reg].sl[0] = ((int32_t)MM[reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)MM[reg].sw[1] * (int32_t)src.sw[1]);
if (MM[reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
MM[reg].l[1] = 0x80000000;
else
MM[reg].sl[1] = ((int32_t)MM[reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)MM[reg].sw[3] * (int32_t)src.sw[3]);
return 0;
}
int opPMADDWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
if (MM[reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
MM[reg].l[0] = 0x80000000;
else
MM[reg].sl[0] = ((int32_t)MM[reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)MM[reg].sw[1] * (int32_t)src.sw[1]);
if (MM[reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
MM[reg].l[1] = 0x80000000;
else
MM[reg].sl[1] = ((int32_t)MM[reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)MM[reg].sw[3] * (int32_t)src.sw[3]);
return 0;
}
int opPMULLW_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[reg].w[0] *= MM[rm].w[0];
MM[reg].w[1] *= MM[rm].w[1];
MM[reg].w[2] *= MM[rm].w[2];
MM[reg].w[3] *= MM[rm].w[3];
cycles--;
}
else
{
MMX_REG src;
src.l[0] = readmeml(easeg, eaaddr);
src.l[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].w[0] *= src.w[0];
MM[reg].w[1] *= src.w[1];
MM[reg].w[2] *= src.w[2];
MM[reg].w[3] *= src.w[3];
cycles -= 2;
}
return 0;
}
int opPMULLW_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[reg].w[0] *= MM[rm].w[0];
MM[reg].w[1] *= MM[rm].w[1];
MM[reg].w[2] *= MM[rm].w[2];
MM[reg].w[3] *= MM[rm].w[3];
cycles--;
}
else
{
MMX_REG src;
src.l[0] = readmeml(easeg, eaaddr);
src.l[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].w[0] *= src.w[0];
MM[reg].w[1] *= src.w[1];
MM[reg].w[2] *= src.w[2];
MM[reg].w[3] *= src.w[3];
cycles -= 2;
}
return 0;
}
int opPMULHW_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[reg].w[0] = ((int32_t)MM[reg].sw[0] * (int32_t)MM[rm].sw[0]) >> 16;
MM[reg].w[1] = ((int32_t)MM[reg].sw[1] * (int32_t)MM[rm].sw[1]) >> 16;
MM[reg].w[2] = ((int32_t)MM[reg].sw[2] * (int32_t)MM[rm].sw[2]) >> 16;
MM[reg].w[3] = ((int32_t)MM[reg].sw[3] * (int32_t)MM[rm].sw[3]) >> 16;
cycles--;
}
else
{
MMX_REG src;
src.l[0] = readmeml(easeg, eaaddr);
src.l[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].w[0] = ((int32_t)MM[reg].sw[0] * (int32_t)src.sw[0]) >> 16;
MM[reg].w[1] = ((int32_t)MM[reg].sw[1] * (int32_t)src.sw[1]) >> 16;
MM[reg].w[2] = ((int32_t)MM[reg].sw[2] * (int32_t)src.sw[2]) >> 16;
MM[reg].w[3] = ((int32_t)MM[reg].sw[3] * (int32_t)src.sw[3]) >> 16;
cycles -= 2;
}
return 0;
}
int opPMULHW_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[reg].w[0] = ((int32_t)MM[reg].sw[0] * (int32_t)MM[rm].sw[0]) >> 16;
MM[reg].w[1] = ((int32_t)MM[reg].sw[1] * (int32_t)MM[rm].sw[1]) >> 16;
MM[reg].w[2] = ((int32_t)MM[reg].sw[2] * (int32_t)MM[rm].sw[2]) >> 16;
MM[reg].w[3] = ((int32_t)MM[reg].sw[3] * (int32_t)MM[rm].sw[3]) >> 16;
cycles--;
}
else
{
MMX_REG src;
src.l[0] = readmeml(easeg, eaaddr);
src.l[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].w[0] = ((int32_t)MM[reg].sw[0] * (int32_t)src.sw[0]) >> 16;
MM[reg].w[1] = ((int32_t)MM[reg].sw[1] * (int32_t)src.sw[1]) >> 16;
MM[reg].w[2] = ((int32_t)MM[reg].sw[2] * (int32_t)src.sw[2]) >> 16;
MM[reg].w[3] = ((int32_t)MM[reg].sw[3] * (int32_t)src.sw[3]) >> 16;
cycles -= 2;
}
return 0;
}
int opPSUBB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] -= src.b[0];
MM[reg].b[1] -= src.b[1];
MM[reg].b[2] -= src.b[2];
MM[reg].b[3] -= src.b[3];
MM[reg].b[4] -= src.b[4];
MM[reg].b[5] -= src.b[5];
MM[reg].b[6] -= src.b[6];
MM[reg].b[7] -= src.b[7];
return 0;
}
int opPSUBB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] -= src.b[0];
MM[reg].b[1] -= src.b[1];
MM[reg].b[2] -= src.b[2];
MM[reg].b[3] -= src.b[3];
MM[reg].b[4] -= src.b[4];
MM[reg].b[5] -= src.b[5];
MM[reg].b[6] -= src.b[6];
MM[reg].b[7] -= src.b[7];
return 0;
}
int opPSUBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] -= src.w[0];
MM[reg].w[1] -= src.w[1];
MM[reg].w[2] -= src.w[2];
MM[reg].w[3] -= src.w[3];
return 0;
}
int opPSUBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] -= src.w[0];
MM[reg].w[1] -= src.w[1];
MM[reg].w[2] -= src.w[2];
MM[reg].w[3] -= src.w[3];
return 0;
}
int opPSUBD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] -= src.l[0];
MM[reg].l[1] -= src.l[1];
return 0;
}
int opPSUBD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].l[0] -= src.l[0];
MM[reg].l[1] -= src.l[1];
return 0;
}
int opPSUBSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].sb[0] = SSATB(MM[reg].sb[0] - src.sb[0]);
MM[reg].sb[1] = SSATB(MM[reg].sb[1] - src.sb[1]);
MM[reg].sb[2] = SSATB(MM[reg].sb[2] - src.sb[2]);
MM[reg].sb[3] = SSATB(MM[reg].sb[3] - src.sb[3]);
MM[reg].sb[4] = SSATB(MM[reg].sb[4] - src.sb[4]);
MM[reg].sb[5] = SSATB(MM[reg].sb[5] - src.sb[5]);
MM[reg].sb[6] = SSATB(MM[reg].sb[6] - src.sb[6]);
MM[reg].sb[7] = SSATB(MM[reg].sb[7] - src.sb[7]);
return 0;
}
int opPSUBSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].sb[0] = SSATB(MM[reg].sb[0] - src.sb[0]);
MM[reg].sb[1] = SSATB(MM[reg].sb[1] - src.sb[1]);
MM[reg].sb[2] = SSATB(MM[reg].sb[2] - src.sb[2]);
MM[reg].sb[3] = SSATB(MM[reg].sb[3] - src.sb[3]);
MM[reg].sb[4] = SSATB(MM[reg].sb[4] - src.sb[4]);
MM[reg].sb[5] = SSATB(MM[reg].sb[5] - src.sb[5]);
MM[reg].sb[6] = SSATB(MM[reg].sb[6] - src.sb[6]);
MM[reg].sb[7] = SSATB(MM[reg].sb[7] - src.sb[7]);
return 0;
}
int opPSUBUSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = USATB(MM[reg].b[0] - src.b[0]);
MM[reg].b[1] = USATB(MM[reg].b[1] - src.b[1]);
MM[reg].b[2] = USATB(MM[reg].b[2] - src.b[2]);
MM[reg].b[3] = USATB(MM[reg].b[3] - src.b[3]);
MM[reg].b[4] = USATB(MM[reg].b[4] - src.b[4]);
MM[reg].b[5] = USATB(MM[reg].b[5] - src.b[5]);
MM[reg].b[6] = USATB(MM[reg].b[6] - src.b[6]);
MM[reg].b[7] = USATB(MM[reg].b[7] - src.b[7]);
return 0;
}
int opPSUBUSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = USATB(MM[reg].b[0] - src.b[0]);
MM[reg].b[1] = USATB(MM[reg].b[1] - src.b[1]);
MM[reg].b[2] = USATB(MM[reg].b[2] - src.b[2]);
MM[reg].b[3] = USATB(MM[reg].b[3] - src.b[3]);
MM[reg].b[4] = USATB(MM[reg].b[4] - src.b[4]);
MM[reg].b[5] = USATB(MM[reg].b[5] - src.b[5]);
MM[reg].b[6] = USATB(MM[reg].b[6] - src.b[6]);
MM[reg].b[7] = USATB(MM[reg].b[7] - src.b[7]);
return 0;
}
int opPSUBSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].sw[0] = SSATW(MM[reg].sw[0] - src.sw[0]);
MM[reg].sw[1] = SSATW(MM[reg].sw[1] - src.sw[1]);
MM[reg].sw[2] = SSATW(MM[reg].sw[2] - src.sw[2]);
MM[reg].sw[3] = SSATW(MM[reg].sw[3] - src.sw[3]);
return 0;
}
int opPSUBSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].sw[0] = SSATW(MM[reg].sw[0] - src.sw[0]);
MM[reg].sw[1] = SSATW(MM[reg].sw[1] - src.sw[1]);
MM[reg].sw[2] = SSATW(MM[reg].sw[2] - src.sw[2]);
MM[reg].sw[3] = SSATW(MM[reg].sw[3] - src.sw[3]);
return 0;
}
int opPSUBUSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = USATW(MM[reg].w[0] - src.w[0]);
MM[reg].w[1] = USATW(MM[reg].w[1] - src.w[1]);
MM[reg].w[2] = USATW(MM[reg].w[2] - src.w[2]);
MM[reg].w[3] = USATW(MM[reg].w[3] - src.w[3]);
return 0;
}
int opPSUBUSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = USATW(MM[reg].w[0] - src.w[0]);
MM[reg].w[1] = USATW(MM[reg].w[1] - src.w[1]);
MM[reg].w[2] = USATW(MM[reg].w[2] - src.w[2]);
MM[reg].w[3] = USATW(MM[reg].w[3] - src.w[3]);
return 0;
}

205
src/x86_ops_mmx_cmp.h Normal file
View file

@ -0,0 +1,205 @@
static int opPCMPEQB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = (MM[reg].b[0] == src.b[0]) ? 0xff : 0;
MM[reg].b[1] = (MM[reg].b[1] == src.b[1]) ? 0xff : 0;
MM[reg].b[2] = (MM[reg].b[2] == src.b[2]) ? 0xff : 0;
MM[reg].b[3] = (MM[reg].b[3] == src.b[3]) ? 0xff : 0;
MM[reg].b[4] = (MM[reg].b[4] == src.b[4]) ? 0xff : 0;
MM[reg].b[5] = (MM[reg].b[5] == src.b[5]) ? 0xff : 0;
MM[reg].b[6] = (MM[reg].b[6] == src.b[6]) ? 0xff : 0;
MM[reg].b[7] = (MM[reg].b[7] == src.b[7]) ? 0xff : 0;
return 0;
}
static int opPCMPEQB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = (MM[reg].b[0] == src.b[0]) ? 0xff : 0;
MM[reg].b[1] = (MM[reg].b[1] == src.b[1]) ? 0xff : 0;
MM[reg].b[2] = (MM[reg].b[2] == src.b[2]) ? 0xff : 0;
MM[reg].b[3] = (MM[reg].b[3] == src.b[3]) ? 0xff : 0;
MM[reg].b[4] = (MM[reg].b[4] == src.b[4]) ? 0xff : 0;
MM[reg].b[5] = (MM[reg].b[5] == src.b[5]) ? 0xff : 0;
MM[reg].b[6] = (MM[reg].b[6] == src.b[6]) ? 0xff : 0;
MM[reg].b[7] = (MM[reg].b[7] == src.b[7]) ? 0xff : 0;
return 0;
}
static int opPCMPGTB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = (MM[reg].sb[0] > src.sb[0]) ? 0xff : 0;
MM[reg].b[1] = (MM[reg].sb[1] > src.sb[1]) ? 0xff : 0;
MM[reg].b[2] = (MM[reg].sb[2] > src.sb[2]) ? 0xff : 0;
MM[reg].b[3] = (MM[reg].sb[3] > src.sb[3]) ? 0xff : 0;
MM[reg].b[4] = (MM[reg].sb[4] > src.sb[4]) ? 0xff : 0;
MM[reg].b[5] = (MM[reg].sb[5] > src.sb[5]) ? 0xff : 0;
MM[reg].b[6] = (MM[reg].sb[6] > src.sb[6]) ? 0xff : 0;
MM[reg].b[7] = (MM[reg].sb[7] > src.sb[7]) ? 0xff : 0;
return 0;
}
static int opPCMPGTB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = (MM[reg].sb[0] > src.sb[0]) ? 0xff : 0;
MM[reg].b[1] = (MM[reg].sb[1] > src.sb[1]) ? 0xff : 0;
MM[reg].b[2] = (MM[reg].sb[2] > src.sb[2]) ? 0xff : 0;
MM[reg].b[3] = (MM[reg].sb[3] > src.sb[3]) ? 0xff : 0;
MM[reg].b[4] = (MM[reg].sb[4] > src.sb[4]) ? 0xff : 0;
MM[reg].b[5] = (MM[reg].sb[5] > src.sb[5]) ? 0xff : 0;
MM[reg].b[6] = (MM[reg].sb[6] > src.sb[6]) ? 0xff : 0;
MM[reg].b[7] = (MM[reg].sb[7] > src.sb[7]) ? 0xff : 0;
return 0;
}
static int opPCMPEQW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = (MM[reg].w[0] == src.w[0]) ? 0xffff : 0;
MM[reg].w[1] = (MM[reg].w[1] == src.w[1]) ? 0xffff : 0;
MM[reg].w[2] = (MM[reg].w[2] == src.w[2]) ? 0xffff : 0;
MM[reg].w[3] = (MM[reg].w[3] == src.w[3]) ? 0xffff : 0;
return 0;
}
static int opPCMPEQW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = (MM[reg].w[0] == src.w[0]) ? 0xffff : 0;
MM[reg].w[1] = (MM[reg].w[1] == src.w[1]) ? 0xffff : 0;
MM[reg].w[2] = (MM[reg].w[2] == src.w[2]) ? 0xffff : 0;
MM[reg].w[3] = (MM[reg].w[3] == src.w[3]) ? 0xffff : 0;
return 0;
}
static int opPCMPGTW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = (MM[reg].sw[0] > src.sw[0]) ? 0xffff : 0;
MM[reg].w[1] = (MM[reg].sw[1] > src.sw[1]) ? 0xffff : 0;
MM[reg].w[2] = (MM[reg].sw[2] > src.sw[2]) ? 0xffff : 0;
MM[reg].w[3] = (MM[reg].sw[3] > src.sw[3]) ? 0xffff : 0;
return 0;
}
static int opPCMPGTW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = (MM[reg].sw[0] > src.sw[0]) ? 0xffff : 0;
MM[reg].w[1] = (MM[reg].sw[1] > src.sw[1]) ? 0xffff : 0;
MM[reg].w[2] = (MM[reg].sw[2] > src.sw[2]) ? 0xffff : 0;
MM[reg].w[3] = (MM[reg].sw[3] > src.sw[3]) ? 0xffff : 0;
return 0;
}
static int opPCMPEQD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = (MM[reg].l[0] == src.l[0]) ? 0xffffffff : 0;
MM[reg].l[1] = (MM[reg].l[1] == src.l[1]) ? 0xffffffff : 0;
return 0;
}
static int opPCMPEQD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = (MM[reg].l[0] == src.l[0]) ? 0xffffffff : 0;
MM[reg].l[1] = (MM[reg].l[1] == src.l[1]) ? 0xffffffff : 0;
return 0;
}
static int opPCMPGTD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = (MM[reg].sl[0] > src.sl[0]) ? 0xffffffff : 0;
MM[reg].l[1] = (MM[reg].sl[1] > src.sl[1]) ? 0xffffffff : 0;
return 0;
}
static int opPCMPGTD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = (MM[reg].sl[0] > src.sl[0]) ? 0xffffffff : 0;
MM[reg].l[1] = (MM[reg].sl[1] > src.sl[1]) ? 0xffffffff : 0;
return 0;
}

91
src/x86_ops_mmx_logic.h Normal file
View file

@ -0,0 +1,91 @@
int opPAND_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].q &= src.q;
return 0;
}
int opPAND_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].q &= src.q;
return 0;
}
int opPANDN_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].q &= ~src.q;
return 0;
}
int opPANDN_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].q &= ~src.q;
return 0;
}
int opPOR_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].q |= src.q;
return 0;
}
int opPOR_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].q |= src.q;
return 0;
}
int opPXOR_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].q ^= src.q;
return 0;
}
int opPXOR_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].q ^= src.q;
return 0;
}

163
src/x86_ops_mmx_mov.h Normal file
View file

@ -0,0 +1,163 @@
int opMOVD_l_mm_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[reg].l[0] = regs[rm].l;
MM[reg].l[1] = 0;
cycles--;
}
else
{
uint32_t dst;
dst = readmeml(easeg, eaaddr); if (abrt) return 0;
MM[reg].l[0] = dst;
MM[reg].l[1] = 0;
cycles -= 2;
}
return 0;
}
int opMOVD_l_mm_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[reg].l[0] = regs[rm].l;
MM[reg].l[1] = 0;
cycles--;
}
else
{
uint32_t dst;
dst = readmeml(easeg, eaaddr); if (abrt) return 0;
MM[reg].l[0] = dst;
MM[reg].l[1] = 0;
cycles -= 2;
}
return 0;
}
int opMOVD_mm_l_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
regs[rm].l = MM[reg].l[0];
cycles--;
}
else
{
writememl(easeg, eaaddr, MM[reg].l[0]); if (abrt) return 0;
cycles -= 2;
}
return 0;
}
int opMOVD_mm_l_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
regs[rm].l = MM[reg].l[0];
cycles--;
}
else
{
writememl(easeg, eaaddr, MM[reg].l[0]); if (abrt) return 0;
cycles -= 2;
}
return 0;
}
int opMOVQ_q_mm_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[reg].q = MM[rm].q;
cycles--;
}
else
{
uint32_t dst[2];
dst[0] = readmeml(easeg, eaaddr);
dst[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].l[0] = dst[0];
MM[reg].l[1] = dst[1];
cycles -= 2;
}
return 0;
}
int opMOVQ_q_mm_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[reg].q = MM[rm].q;
cycles--;
}
else
{
uint32_t dst[2];
dst[0] = readmeml(easeg, eaaddr);
dst[1] = readmeml(easeg, eaaddr + 4); if (abrt) return 0;
MM[reg].l[0] = dst[0];
MM[reg].l[1] = dst[1];
cycles -= 2;
}
return 0;
}
int opMOVQ_mm_q_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[rm].q = MM[reg].q;
cycles--;
}
else
{
writememl(easeg, eaaddr, MM[reg].l[0]);
writememl(easeg, eaaddr + 4, MM[reg].l[1]); if (abrt) return 0;
cycles -= 2;
}
return 0;
}
int opMOVQ_mm_q_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[rm].q = MM[reg].q;
cycles--;
}
else
{
writememl(easeg, eaaddr, MM[reg].l[0]);
writememl(easeg, eaaddr + 4, MM[reg].l[1]); if (abrt) return 0;
cycles -= 2;
}
return 0;
}

322
src/x86_ops_mmx_pack.h Normal file
View file

@ -0,0 +1,322 @@
int opPUNPCKLDQ_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (mod == 3)
{
MM[reg].l[1] = MM[rm].l[0];
cycles--;
}
else
{
uint32_t src;
src = readmeml(easeg, eaaddr); if (abrt) return 0;
MM[reg].l[1] = src;
cycles -= 2;
}
return 0;
}
int opPUNPCKLDQ_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (mod == 3)
{
MM[reg].l[1] = MM[rm].l[0];
cycles--;
}
else
{
uint32_t src;
src = readmeml(easeg, eaaddr); if (abrt) return 0;
MM[reg].l[1] = src;
cycles -= 2;
}
return 0;
}
int opPUNPCKHDQ_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = src.l[1];
return 0;
}
int opPUNPCKHDQ_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].l[0] = src.l[1];
return 0;
}
int opPUNPCKLBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[7] = src.b[3];
MM[reg].b[6] = MM[reg].b[3];
MM[reg].b[5] = src.b[2];
MM[reg].b[4] = MM[reg].b[2];
MM[reg].b[3] = src.b[1];
MM[reg].b[2] = MM[reg].b[1];
MM[reg].b[1] = src.b[0];
MM[reg].b[0] = MM[reg].b[0];
return 0;
}
int opPUNPCKLBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[7] = src.b[3];
MM[reg].b[6] = MM[reg].b[3];
MM[reg].b[5] = src.b[2];
MM[reg].b[4] = MM[reg].b[2];
MM[reg].b[3] = src.b[1];
MM[reg].b[2] = MM[reg].b[1];
MM[reg].b[1] = src.b[0];
MM[reg].b[0] = MM[reg].b[0];
return 0;
}
int opPUNPCKHBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = MM[reg].b[4];
MM[reg].b[1] = src.b[4];
MM[reg].b[2] = MM[reg].b[5];
MM[reg].b[3] = src.b[5];
MM[reg].b[4] = MM[reg].b[6];
MM[reg].b[5] = src.b[6];
MM[reg].b[6] = MM[reg].b[7];
MM[reg].b[7] = src.b[7];
return 0;
}
int opPUNPCKHBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].b[0] = MM[reg].b[4];
MM[reg].b[1] = src.b[4];
MM[reg].b[2] = MM[reg].b[5];
MM[reg].b[3] = src.b[5];
MM[reg].b[4] = MM[reg].b[6];
MM[reg].b[5] = src.b[6];
MM[reg].b[6] = MM[reg].b[7];
MM[reg].b[7] = src.b[7];
return 0;
}
int opPUNPCKLWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[3] = src.w[1];
MM[reg].w[2] = MM[reg].w[1];
MM[reg].w[1] = src.w[0];
MM[reg].w[0] = MM[reg].w[0];
return 0;
}
int opPUNPCKLWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[3] = src.w[1];
MM[reg].w[2] = MM[reg].w[1];
MM[reg].w[1] = src.w[0];
MM[reg].w[0] = MM[reg].w[0];
return 0;
}
int opPUNPCKHWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = MM[reg].w[2];
MM[reg].w[1] = src.w[2];
MM[reg].w[2] = MM[reg].w[3];
MM[reg].w[3] = src.w[3];
return 0;
}
int opPUNPCKHWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
MM[reg].w[0] = MM[reg].w[2];
MM[reg].w[1] = src.w[2];
MM[reg].w[2] = MM[reg].w[3];
MM[reg].w[3] = src.w[3];
return 0;
}
int opPACKSSWB_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].sb[0] = SSATB(dst.sw[0]);
MM[reg].sb[1] = SSATB(dst.sw[1]);
MM[reg].sb[2] = SSATB(dst.sw[2]);
MM[reg].sb[3] = SSATB(dst.sw[3]);
MM[reg].sb[4] = SSATB(src.sw[0]);
MM[reg].sb[5] = SSATB(src.sw[1]);
MM[reg].sb[6] = SSATB(src.sw[2]);
MM[reg].sb[7] = SSATB(src.sw[3]);
return 0;
}
int opPACKSSWB_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].sb[0] = SSATB(dst.sw[0]);
MM[reg].sb[1] = SSATB(dst.sw[1]);
MM[reg].sb[2] = SSATB(dst.sw[2]);
MM[reg].sb[3] = SSATB(dst.sw[3]);
MM[reg].sb[4] = SSATB(src.sw[0]);
MM[reg].sb[5] = SSATB(src.sw[1]);
MM[reg].sb[6] = SSATB(src.sw[2]);
MM[reg].sb[7] = SSATB(src.sw[3]);
return 0;
}
int opPACKUSWB_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].b[0] = USATB(dst.sw[0]);
MM[reg].b[1] = USATB(dst.sw[1]);
MM[reg].b[2] = USATB(dst.sw[2]);
MM[reg].b[3] = USATB(dst.sw[3]);
MM[reg].b[4] = USATB(src.sw[0]);
MM[reg].b[5] = USATB(src.sw[1]);
MM[reg].b[6] = USATB(src.sw[2]);
MM[reg].b[7] = USATB(src.sw[3]);
return 0;
}
int opPACKUSWB_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].b[0] = USATB(dst.sw[0]);
MM[reg].b[1] = USATB(dst.sw[1]);
MM[reg].b[2] = USATB(dst.sw[2]);
MM[reg].b[3] = USATB(dst.sw[3]);
MM[reg].b[4] = USATB(src.sw[0]);
MM[reg].b[5] = USATB(src.sw[1]);
MM[reg].b[6] = USATB(src.sw[2]);
MM[reg].b[7] = USATB(src.sw[3]);
return 0;
}
int opPACKSSDW_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].sw[0] = SSATW(dst.sl[0]);
MM[reg].sw[1] = SSATW(dst.sl[1]);
MM[reg].sw[2] = SSATW(src.sl[0]);
MM[reg].sw[3] = SSATW(src.sl[1]);
return 0;
}
int opPACKSSDW_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = MM[reg];
MM[reg].sw[0] = SSATW(dst.sl[0]);
MM[reg].sw[1] = SSATW(dst.sl[1]);
MM[reg].sw[2] = SSATW(src.sl[0]);
MM[reg].sw[3] = SSATW(src.sl[1]);
return 0;
}

452
src/x86_ops_mmx_shift.h Normal file
View file

@ -0,0 +1,452 @@
#define MMX_GETSHIFT() \
if (mod == 3) \
{ \
shift = MM[rm].b[0]; \
cycles--; \
} \
else \
{ \
shift = readmemb(easeg, eaaddr); if (abrt) return 0; \
cycles -= 2; \
}
int opPSxxW_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLW*/
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] >>= shift;
MM[reg].w[1] >>= shift;
MM[reg].w[2] >>= shift;
MM[reg].w[3] >>= shift;
}
break;
case 0x20: /*PSRAW*/
if (shift > 15)
shift = 15;
MM[reg].sw[0] >>= shift;
MM[reg].sw[1] >>= shift;
MM[reg].sw[2] >>= shift;
MM[reg].sw[3] >>= shift;
break;
case 0x30: /*PSLLW*/
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] <<= shift;
MM[reg].w[1] <<= shift;
MM[reg].w[2] <<= shift;
MM[reg].w[3] <<= shift;
}
break;
default:
pclog("Bad PSxxW (0F 71) instruction %02X\n", op);
pc = oldpc;
x86illegal();
return 0;
}
cycles--;
return 0;
}
int opPSLLW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] <<= shift;
MM[reg].w[1] <<= shift;
MM[reg].w[2] <<= shift;
MM[reg].w[3] <<= shift;
}
return 0;
}
int opPSLLW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] <<= shift;
MM[reg].w[1] <<= shift;
MM[reg].w[2] <<= shift;
MM[reg].w[3] <<= shift;
}
return 0;
}
int opPSRLW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] >>= shift;
MM[reg].w[1] >>= shift;
MM[reg].w[2] >>= shift;
MM[reg].w[3] >>= shift;
}
return 0;
}
int opPSRLW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
MM[reg].q = 0;
else
{
MM[reg].w[0] >>= shift;
MM[reg].w[1] >>= shift;
MM[reg].w[2] >>= shift;
MM[reg].w[3] >>= shift;
}
return 0;
}
int opPSRAW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
shift = 15;
MM[reg].sw[0] >>= shift;
MM[reg].sw[1] >>= shift;
MM[reg].sw[2] >>= shift;
MM[reg].sw[3] >>= shift;
return 0;
}
int opPSRAW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
shift = 15;
MM[reg].sw[0] >>= shift;
MM[reg].sw[1] >>= shift;
MM[reg].sw[2] >>= shift;
MM[reg].sw[3] >>= shift;
return 0;
}
int opPSxxD_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLD*/
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] >>= shift;
MM[reg].l[1] >>= shift;
}
break;
case 0x20: /*PSRAD*/
if (shift > 31)
shift = 31;
MM[reg].sl[0] >>= shift;
MM[reg].sl[1] >>= shift;
break;
case 0x30: /*PSLLD*/
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] <<= shift;
MM[reg].l[1] <<= shift;
}
break;
default:
pclog("Bad PSxxD (0F 72) instruction %02X\n", op);
pc = oldpc;
x86illegal();
return 0;
}
cycles--;
return 0;
}
int opPSLLD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] <<= shift;
MM[reg].l[1] <<= shift;
}
return 0;
}
int opPSLLD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] <<= shift;
MM[reg].l[1] <<= shift;
}
return 0;
}
int opPSRLD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] >>= shift;
MM[reg].l[1] >>= shift;
}
return 0;
}
int opPSRLD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
MM[reg].q = 0;
else
{
MM[reg].l[0] >>= shift;
MM[reg].l[1] >>= shift;
}
return 0;
}
int opPSRAD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
shift = 31;
MM[reg].sl[0] >>= shift;
MM[reg].sl[1] >>= shift;
return 0;
}
int opPSRAD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
shift = 31;
MM[reg].sl[0] >>= shift;
MM[reg].sl[1] >>= shift;
return 0;
}
int opPSxxQ_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLW*/
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q >>= shift;
break;
case 0x20: /*PSRAW*/
if (shift > 63)
shift = 63;
MM[reg].sq >>= shift;
break;
case 0x30: /*PSLLW*/
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q <<= shift;
break;
default:
pclog("Bad PSxxQ (0F 73) instruction %02X\n", op);
pc = oldpc;
x86illegal();
return 0;
}
cycles--;
return 0;
}
int opPSLLQ_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q <<= shift;
return 0;
}
int opPSLLQ_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q <<= shift;
return 0;
}
int opPSRLQ_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q >>= shift;
return 0;
}
int opPSRLQ_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
MM[reg].q = 0;
else
MM[reg].q >>= shift;
return 0;
}

View file

@ -2394,7 +2394,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
cr3=new_cr3;
pclog("TS New CR3 %08X\n",cr3);
// pclog("TS New CR3 %08X\n",cr3);
flushmmucache();

205
src/x87.c
View file

@ -60,6 +60,8 @@ static inline uint32_t geteal()
double ST[8];
MMX_REG MM[8];
int ismmx = 0;
uint16_t npxs,npxc,tag;
int TOP;
@ -90,6 +92,19 @@ int TOP;
dst = src1 / (double)src2; \
} while (0)
void x87_set_mmx()
{
TOP = 0;
tag = 0;
ismmx = 1;
}
void x87_emms()
{
tag = 0xffff;
ismmx = 0;
}
void x87_checkexceptions()
{
}
@ -100,15 +115,31 @@ void x87_reset()
void x87_dumpregs()
{
pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]);
if (ismmx)
{
pclog("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", MM[0].q, MM[1].q, MM[2].q, MM[3].q);
pclog("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", MM[4].q, MM[5].q, MM[6].q, MM[7].q);
}
else
{
pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]);
}
pclog("Status = %04X Control = %04X Tag = %04X\n",npxs,npxc,tag);
}
void x87_print()
{
pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP&7],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t TOP=%i CR=%04X SR=%04X TAG=%04X\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7], TOP, npxc, npxs, tag);
if (ismmx)
{
pclog("\tMM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\t", MM[0].q, MM[1].q, MM[2].q, MM[3].q);
pclog("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", MM[4].q, MM[5].q, MM[6].q, MM[7].q);
}
else
{
pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP&7],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t TOP=%i CR=%04X SR=%04X TAG=%04X\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7], TOP, npxc, npxs, tag);
}
}
void x87_push(double i)
@ -215,6 +246,20 @@ void x87_st80(double d)
writememw(easeg,eaaddr+8,test.begin);
}
void x87_ldmmx(MMX_REG *r)
{
r->l[0] = readmeml(easeg, eaaddr);
r->l[1] = readmeml(easeg, eaaddr + 4);
r->w[4] = readmemw(easeg, eaaddr + 8);
}
void x87_stmmx(MMX_REG r)
{
writememl(easeg, eaaddr, r.l[0]);
writememl(easeg, eaaddr + 4, r.l[1]);
writememw(easeg, eaaddr + 8, 0xffff);
}
void x87_d8()
{
union
@ -545,7 +590,7 @@ void x87_d9()
cycles-=7;
return;
case 3: /*FSTP single-precision*/
if (fplog) pclog("FSTPs %08X:%08X\n", easeg, eaaddr);
if (fplog) pclog("FSTPs %08X:%08X %f\n", easeg, eaaddr, ST(0));
ts.s=(float)ST(0);
seteal(ts.i); if (abrt) { pclog("FSTP sp abort\n"); return; }
// if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i);
@ -969,7 +1014,6 @@ void x87_dd()
cycles-=8;
return;
case 4: /*FRSTOR*/
if (fplog) pclog("FRSTOR %08X:%08X\n", easeg, eaaddr);
switch ((cr0&1)|(op32&0x100))
{
case 0x000: /*16-bit real mode*/
@ -989,23 +1033,33 @@ void x87_dd()
eaaddr+=28;
break;
}
ST(0)=x87_ld80(); eaaddr+=10;
ST(1)=x87_ld80(); eaaddr+=10;
ST(2)=x87_ld80(); eaaddr+=10;
ST(3)=x87_ld80(); eaaddr+=10;
ST(4)=x87_ld80(); eaaddr+=10;
ST(5)=x87_ld80(); eaaddr+=10;
ST(6)=x87_ld80(); eaaddr+=10;
ST(7)=x87_ld80();
x87_ldmmx(&MM[0]); ST(0)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[1]); ST(1)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[2]); ST(2)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[3]); ST(3)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[4]); ST(4)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[5]); ST(5)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[6]); ST(6)=x87_ld80(); eaaddr += 10;
x87_ldmmx(&MM[7]); ST(7)=x87_ld80();
ismmx = 0;
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
something like this is needed*/
if (MM[0].w == 0xffff && MM[1].w == 0xffff && MM[2].w == 0xffff && MM[3].w == 0xffff &&
MM[4].w == 0xffff && MM[5].w == 0xffff && MM[6].w == 0xffff && MM[7].w == 0xffff &&
!TOP && !tag)
ismmx = 1;
cycles-=(cr0&1)?34:44;
if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, eaaddr, ismmx, TOP, tag);
/* pclog("new TOP %i\n", TOP);
pclog("%04X %04X %04X %f %f %f %f %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/
return;
case 6: /*FSAVE*/
if (fplog) pclog("FSAVE %08X:%08X\n", easeg, eaaddr);
if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, eaaddr, ismmx);
npxs = (npxs & ~(7 << 11)) | (TOP << 11);
/* pclog("old TOP %i %04X\n", TOP, npxs);
pclog("%04X %04X %04X %f %f %f %f %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/
switch ((cr0&1)|(op32&0x100))
{
case 0x000: /*16-bit real mode*/
@ -1015,14 +1069,28 @@ void x87_dd()
writememw(easeg,eaaddr+6,x87_pc_off);
writememw(easeg,eaaddr+10,x87_op_off);
eaaddr+=14;
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
if (ismmx)
{
x87_stmmx(MM[0]); eaaddr+=10;
x87_stmmx(MM[1]); eaaddr+=10;
x87_stmmx(MM[2]); eaaddr+=10;
x87_stmmx(MM[3]); eaaddr+=10;
x87_stmmx(MM[4]); eaaddr+=10;
x87_stmmx(MM[5]); eaaddr+=10;
x87_stmmx(MM[6]); eaaddr+=10;
x87_stmmx(MM[7]);
}
else
{
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
}
break;
case 0x001: /*16-bit protected mode*/
writememw(easeg,eaaddr,npxc);
@ -1033,14 +1101,28 @@ void x87_dd()
writememw(easeg,eaaddr+10,x87_op_off);
writememw(easeg,eaaddr+12,x87_op_seg);
eaaddr+=14;
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
if (ismmx)
{
x87_stmmx(MM[0]); eaaddr+=10;
x87_stmmx(MM[1]); eaaddr+=10;
x87_stmmx(MM[2]); eaaddr+=10;
x87_stmmx(MM[3]); eaaddr+=10;
x87_stmmx(MM[4]); eaaddr+=10;
x87_stmmx(MM[5]); eaaddr+=10;
x87_stmmx(MM[6]); eaaddr+=10;
x87_stmmx(MM[7]);
}
else
{
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
}
break;
case 0x100: /*32-bit real mode*/
writememw(easeg,eaaddr,npxc);
@ -1050,14 +1132,28 @@ void x87_dd()
writememw(easeg,eaaddr+20,x87_op_off);
writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12);
eaaddr+=28;
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
if (ismmx)
{
x87_stmmx(MM[0]); eaaddr+=10;
x87_stmmx(MM[1]); eaaddr+=10;
x87_stmmx(MM[2]); eaaddr+=10;
x87_stmmx(MM[3]); eaaddr+=10;
x87_stmmx(MM[4]); eaaddr+=10;
x87_stmmx(MM[5]); eaaddr+=10;
x87_stmmx(MM[6]); eaaddr+=10;
x87_stmmx(MM[7]);
}
else
{
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
}
break;
case 0x101: /*32-bit protected mode*/
writememw(easeg,eaaddr,npxc);
@ -1068,14 +1164,28 @@ void x87_dd()
writememl(easeg,eaaddr+20,x87_op_off);
writememl(easeg,eaaddr+24,x87_op_seg);
eaaddr+=28;
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
if (ismmx)
{
x87_stmmx(MM[0]); eaaddr+=10;
x87_stmmx(MM[1]); eaaddr+=10;
x87_stmmx(MM[2]); eaaddr+=10;
x87_stmmx(MM[3]); eaaddr+=10;
x87_stmmx(MM[4]); eaaddr+=10;
x87_stmmx(MM[5]); eaaddr+=10;
x87_stmmx(MM[6]); eaaddr+=10;
x87_stmmx(MM[7]);
}
else
{
x87_st80(ST(0)); eaaddr+=10;
x87_st80(ST(1)); eaaddr+=10;
x87_st80(ST(2)); eaaddr+=10;
x87_st80(ST(3)); eaaddr+=10;
x87_st80(ST(4)); eaaddr+=10;
x87_st80(ST(5)); eaaddr+=10;
x87_st80(ST(6)); eaaddr+=10;
x87_st80(ST(7));
}
break;
}
cycles-=(cr0&1)?56:67;
@ -1293,3 +1403,4 @@ void x87_df()
// fatal("Bad x87 DF opcode %i %02X\n",reg,rmdat32&0xFF);
x86illegal();
}

View file

@ -1,3 +1,20 @@
uint32_t x87_pc_off,x87_op_off;
uint16_t x87_pc_seg,x87_op_seg;
extern uint32_t op32;
typedef union MMX_REG
{
uint64_t q;
int64_t sq;
uint32_t l[2];
int32_t sl[2];
uint16_t w[5];
int16_t sw[4];
uint8_t b[8];
int8_t sb[8];
} MMX_REG;
extern MMX_REG MM[8];
void x87_set_mmx();
void x87_emms();