Added PNI new streaming extensions instructions

PNI could be enabled by setting BX_SUPPORT_PNI in config.h
After the feature will be fully validation I'll also add configure option.

The implemntation is ~complete. I've missed only three FPU new opcodes of FUSTTP instruction and MONITOR/WAIT instructions.

Enjoy ! ;)
This commit is contained in:
Stanislav Shwartsman 2003-08-29 21:20:52 +00:00
parent c2ea352a04
commit 7f570b0150
10 changed files with 536 additions and 90 deletions

View File

@ -34,6 +34,12 @@ Changes in 2.1 (July ??, 2003):
RSQRTSS_VssWss, RSQRTPS_VpsWps, RCPPS_VpsWps, RCPSS_VssWss
[+] Add emulation of SSE3 (PNI) instructions
Currently we have only 3 PNI opcodes still not implemented:
FISTTP m16int, FISTTP m32int, FISTTP m64int
[+] Fixed: Unallowed lock prefix cases must cause #UD exception
[+] Fixed FXSAVE/FXRSTOR instructions
@ -41,7 +47,7 @@ Changes in 2.1 (July ??, 2003):
[+] Fixed fetchdecode bug caused #UD in SYSENTER/SYSEXIT instructions
in 32bit mode.
[+] Fixed fetchdecode bug caused wrong decoding of opcodes containing
[+] Fixed fetchdecode64 bug caused wrong decoding of opcodes containing
BxImmediate_IvIw or BxImmediate_IwIb in x86-64.
[+] Hundreds of bugfixes in FPU emulation after checking of the emulation

View File

@ -708,6 +708,7 @@ typedef
#define BX_SUPPORT_3DNOW 0
#define BX_SUPPORT_SSE 0
#define BX_SUPPORT_DAZ 0
#define BX_SUPPORT_PNI 0
#define BX_SUPPORT_SEP 0
#define BX_SUPPORT_4MEG_PAGES 0
@ -764,6 +765,10 @@ typedef
#error "SSE cannot be compiled without FPU+MMX support"
#endif
#if (BX_SUPPORT_PNI && !BX_SUPPORT_SSE)
#error "PNI cannot be compiled without SSE support"
#endif
#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SEP)
#error SYSENTER/SYSEXIT only supported with CPU_LEVEL >= 6
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.144 2003-08-28 19:25:23 sshwarts Exp $
// $Id: cpu.h,v 1.145 2003-08-29 21:20:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -168,19 +168,16 @@
#define BX_READ_8BIT_REGx(index,extended) ((((index) < 4) || (extended)) ? \
(BX_CPU_THIS_PTR gen_reg[index].word.byte.rl) : \
(BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh))
#define BX_READ_16BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].word.rx)
#define BX_READ_32BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].dword.erx)
#define BX_READ_64BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].rrx)
#else
#define BX_READ_8BIT_REG(index) (((index) < 4) ? \
(BX_CPU_THIS_PTR gen_reg[index].word.byte.rl) : \
(BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh))
#define BX_READ_8BIT_REGx(index,ext) BX_READ_8BIT_REG(index)
#endif
#define BX_READ_16BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].word.rx)
#define BX_READ_32BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].dword.erx)
#endif
#define BX_READ_16BIT_BASE_REG(var, index) {\
var = *BX_CPU_THIS_PTR _16bit_base_reg[index];\
@ -191,6 +188,7 @@
}
#if BX_SUPPORT_X86_64
#define BX_WRITE_8BIT_REGx(index, extended, val) {\
if (((index) < 4) || (extended)) \
BX_CPU_THIS_PTR gen_reg[index].word.byte.rl = val; \
@ -231,6 +229,7 @@
#define BX_WRITE_32BIT_REGZ(index, val) {\
BX_CPU_THIS_PTR gen_reg[index].dword.erx = (Bit32u) val; \
}
#endif
#ifndef CPL
@ -2160,6 +2159,19 @@ union {
BX_SMF void PSLLDQ_WdqIb(bxInstruction_c *i);
/* SSE2 */
/* PNI */
BX_SMF void MOVDDUP_VpdWq(bxInstruction_c *i);
BX_SMF void MOVSLDUP_VpsWps(bxInstruction_c *i);
BX_SMF void MOVSHDUP_VpsWps(bxInstruction_c *i);
BX_SMF void HADDPD_VpdWpd(bxInstruction_c *i);
BX_SMF void HADDPS_VpsWps(bxInstruction_c *i);
BX_SMF void HSUBPD_VpdWpd(bxInstruction_c *i);
BX_SMF void HSUBPS_VpsWps(bxInstruction_c *i);
BX_SMF void ADDSUBPD_VpdWpd(bxInstruction_c *i);
BX_SMF void ADDSUBPS_VpsWps(bxInstruction_c *i);
BX_SMF void LDDQU_VdqMdq(bxInstruction_c *i);
/* PNI */
#if BX_SUPPORT_FPU
BX_SMF void fpu_execute(bxInstruction_c *i);
BX_SMF void fpu_init(void);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer32.cc,v 1.27 2003-08-17 18:15:04 akrisak Exp $
// $Id: ctrl_xfer32.cc,v 1.28 2003-08-29 21:20:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -592,7 +592,6 @@ done:
BX_CPU_C::IRET32(bxInstruction_c *i)
{
BailBigRSP("IRET32");
// Bit32u eip, ecs_raw, eflags;
invalidate_prefetch_q();
@ -619,19 +618,9 @@ BailBigRSP("IRET32");
goto done;
#endif
// BX_ERROR(("IRET32 called when you're not in vm8086 mode or protected mode."));
BX_ERROR(("IRET32 may not be implemented right."));
BX_PANIC(("Please report that you have found a test case for BX_CPU_C::IRET32."));
// pop_32(&eip);
// pop_32(&ecs_raw);
// pop_32(&eflags);
// load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) ecs_raw);
// EIP = eip;
//FIXME: this should do (eflags & 0x257FD5) | (EFLAGS | 0x1A0000)
// write_eflags(eflags, /* change IOPL? */ 1, /* change IF? */ 1, 0, 1);
done:
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.cc,v 1.57 2003-08-28 19:25:23 sshwarts Exp $
// $Id: fetchdecode.cc,v 1.58 2003-08-29 21:20:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -863,8 +863,8 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7c },
/* 0F 7D */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7d },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 80 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jw },
@ -947,7 +947,7 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F CD */ { 0, &BX_CPU_C::BSWAP_EBP },
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
/* 0F D0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd0 },
/* 0F D1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd1 },
/* 0F D2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd2 },
/* 0F D3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd3 },
@ -979,7 +979,7 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F ED */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fed },
/* 0F EE */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fee },
/* 0F EF */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fef },
/* 0F F0 */ { 0, &BX_CPU_C::BxError },
/* 0F F0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff0 },
/* 0F F1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff1 },
/* 0F F2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff2 },
/* 0F F3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff3 },
@ -1397,8 +1397,8 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7c },
/* 0F 7D */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7d },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 80 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jd },
@ -1481,7 +1481,7 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F CD */ { 0, &BX_CPU_C::BSWAP_EBP },
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
/* 0F D0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd0 },
/* 0F D1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd1 },
/* 0F D2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd2 },
/* 0F D3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd3 },
@ -1513,7 +1513,7 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F ED */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fed },
/* 0F EE */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fee },
/* 0F EF */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fef },
/* 0F F0 */ { 0, &BX_CPU_C::BxError },
/* 0F F0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff0 },
/* 0F F1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff1 },
/* 0F F2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff2 },
/* 0F F3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff3 },

View File

@ -379,10 +379,10 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f11[4] = {
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f12[4] = {
/* -- */ { 0, &BX_CPU_C::MOVLPS_VpsMq },
/* 66 */ { 0, &BX_CPU_C::MOVLPD_VsdMq },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::BxError }
/* -- */ { 0, &BX_CPU_C::MOVLPS_VpsMq },
/* 66 */ { 0, &BX_CPU_C::MOVLPD_VsdMq },
/* F2 */ { 0, &BX_CPU_C::MOVDDUP_VpdWq }, // PNI
/* F3 */ { 0, &BX_CPU_C::MOVSLDUP_VpsWps } // PNI
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f13[4] = {
@ -410,7 +410,7 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f16[4] = {
/* -- */ { 0, &BX_CPU_C::MOVHPS_VpsMq },
/* 66 */ { 0, &BX_CPU_C::MOVHPD_VsdMq },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::BxError }
/* F3 */ { 0, &BX_CPU_C::MOVSHDUP_VpsWps } // PNI
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f17[4] = {
@ -697,7 +697,7 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f6f[4] = {
/* -- */ { 0, &BX_CPU_C::MOVQ_PqQq },
/* 66 */ { 0, &BX_CPU_C::MOVDQA_VdqWdq },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::MOVDQU_VdqWdq },
/* F3 */ { 0, &BX_CPU_C::MOVDQU_VdqWdq }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f70[4] = {
@ -728,18 +728,32 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f76[4] = {
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7c[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::HADDPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::HADDPS_VpsWps }, // PNI
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7d[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::HSUBPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::HSUBPS_VpsWps }, // PNI
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7e[4] = {
/* -- */ { 0, &BX_CPU_C::MOVD_EdPd },
/* 66 */ { 0, &BX_CPU_C::MOVD_EdVd },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::MOVQ_VqWq },
/* F3 */ { 0, &BX_CPU_C::MOVQ_VqWq }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7f[4] = {
/* -- */ { 0, &BX_CPU_C::MOVQ_QqPq },
/* 66 */ { 0, &BX_CPU_C::MOVDQA_WdqVdq },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::MOVDQU_WdqVdq },
/* F3 */ { 0, &BX_CPU_C::MOVDQU_WdqVdq }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0fc2[4] = {
@ -777,6 +791,13 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0fc6[4] = {
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0fd0[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::ADDSUBPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::ADDSUBPS_VpsWps }, // PNI
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0fd1[4] = {
/* -- */ { 0, &BX_CPU_C::PSRLW_PqQq },
/* 66 */ { 0, &BX_CPU_C::PSRLW_VdqWdq },
@ -816,7 +837,7 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0fd6[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::MOVQ_WqVq },
/* F2 */ { 0, &BX_CPU_C::MOVDQ2Q_PqVRq },
/* F3 */ { 0, &BX_CPU_C::MOVQ2DQ_VdqQq },
/* F3 */ { 0, &BX_CPU_C::MOVQ2DQ_VdqQq }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0fd7[4] = {
@ -994,6 +1015,13 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0fef[4] = {
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0ff0[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::BxError },
/* F2 */ { 0, &BX_CPU_C::LDDQU_VdqMdq }, // PNI
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0ff1[4] = {
/* -- */ { 0, &BX_CPU_C::PSLLW_PqQq },
/* 66 */ { 0, &BX_CPU_C::PSLLW_VdqWdq },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode64.cc,v 1.55 2003-08-28 19:25:23 sshwarts Exp $
// $Id: fetchdecode64.cc,v 1.56 2003-08-29 21:20:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -954,10 +954,10 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 7C */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7c },
/* 0F 7D */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7d },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 80 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jq },
/* 0F 81 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jq },
/* 0F 82 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jq },
@ -1038,7 +1038,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F CD */ { 0, &BX_CPU_C::BSWAP_EBP },
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
/* 0F D0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd0 },
/* 0F D1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd1 },
/* 0F D2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd2 },
/* 0F D3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd3 },
@ -1070,7 +1070,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F ED */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fed },
/* 0F EE */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fee },
/* 0F EF */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fef },
/* 0F F0 */ { 0, &BX_CPU_C::BxError },
/* 0F F0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff0 },
/* 0F F1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff1 },
/* 0F F2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff2 },
/* 0F F3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff3 },
@ -1478,10 +1478,10 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 7C */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7c },
/* 0F 7D */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7d },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 80 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
/* 0F 81 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
/* 0F 82 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
@ -1562,7 +1562,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F CD */ { 0, &BX_CPU_C::BSWAP_EBP },
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
/* 0F D0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd0 },
/* 0F D1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd1 },
/* 0F D2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd2 },
/* 0F D3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd3 },
@ -1594,7 +1594,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F ED */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fed },
/* 0F EE */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fee },
/* 0F EF */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fef },
/* 0F F0 */ { 0, &BX_CPU_C::BxError },
/* 0F F0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff0 },
/* 0F F1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff1 },
/* 0F F2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff2 },
/* 0F F3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff3 },
@ -1999,10 +1999,10 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 7C */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7c },
/* 0F 7D */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7d },
/* 0F 7E */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7e },
/* 0F 7F */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0f7f },
/* 0F 80 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
/* 0F 81 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
/* 0F 82 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jq },
@ -2083,7 +2083,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F CD */ { 0, &BX_CPU_C::BSWAP_RBP },
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_RSI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_RDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
/* 0F D0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd0 },
/* 0F D1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd1 },
/* 0F D2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd2 },
/* 0F D3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fd3 },
@ -2115,7 +2115,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F ED */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fed },
/* 0F EE */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fee },
/* 0F EF */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fef },
/* 0F F0 */ { 0, &BX_CPU_C::BxError },
/* 0F F0 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff0 },
/* 0F F1 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff1 },
/* 0F F2 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff2 },
/* 0F F3 */ { BxAnother | BxPrefixSSE, NULL, BxOpcodeGroupSSE_0ff3 },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.73 2003-08-03 16:44:53 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.74 2003-08-29 21:20:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -73,7 +73,6 @@ BX_CPU_C::HLT(bxInstruction_c *i)
BX_PANIC(("HALT instruction encountered in the BIOS ROM"));
if (CPL!=0) {
// BX_INFO(("HLT(): CPL!=0"));
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
@ -889,11 +888,9 @@ BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
// Protected mode: #GP(0) if attempt to write a 1 to
// any reserved bit of CR4
BX_INFO(("MOV_CqRq: ignoring write to CR4 of 0x%08x",
val_64));
BX_INFO(("MOV_CqRq: ignoring write to CR4 of 0x%08x", val_64));
if (val_64) {
BX_INFO(("MOV_CqRq: (CR4) write of 0x%08x not supported!",
val_64));
BX_INFO(("MOV_CqRq: (CR4) write of 0x%08x not supported!", val_64));
}
// Only allow writes of 0 to CR4 for now.
// Writes to bits in CR4 should not be 1s as CPUID
@ -1343,7 +1340,7 @@ BX_PANIC(("LOADALL: handle CR0.val32"));
static inline Bit32u
get_std_cpuid_features()
{
unsigned features;
Bit32u features;
// EAX[3:0] Stepping ID
// EAX[7:4] Model: starts at 1
@ -1351,7 +1348,10 @@ get_std_cpuid_features()
// EAX[13:12] Type: 0=OEM,1=overdrive,2=dual cpu,3=reserved
// EAX[31:14] Reserved
// EBX: Reserved (0)
// ECX: Reserved (0)
// ECX: Feature Flags::Extended
// [0:0] PNI
// [3:3] MONITOR/MWAIT
// [7:7] Enchanced Intel Speedstep Technology
// EDX: Feature Flags
// [0:0] FPU on chip
// [1:1] VME: Virtual-8086 Mode enhancements
@ -1409,21 +1409,19 @@ get_std_cpuid_features()
#if BX_SUPPORT_4MEG_PAGES
features |= (1<<3); // Support Page-Size Extension (4M pages)
#endif
#if BX_SupportGlobalPages
features |= (1<<13); // Support Global pages.
#endif
#if BX_SupportPAE
features |= (1<<6); // Support PAE.
#endif
#if BX_SUPPORT_X86_64
features |= (1<<5); // AMD specific MSR's
features |= (1<<5); // AMD specific MSR's
#endif
#if BX_SUPPORT_SEP
features |= (1<<11); // SYSENTER/SYSEXIT
features |= (1<<11); // SYSENTER/SYSEXIT
#endif
return features;
@ -1476,15 +1474,15 @@ BX_CPU_C::CPUID(bxInstruction_c *i)
#elif BX_CPU_LEVEL == 5
family = 5;
model = 1; // Pentium (60,66)
model = 1; // Pentium (60,66)
stepping = 3; // ???
#elif BX_CPU_LEVEL == 6
family = 6;
#if BX_SUPPORT_X86_64
model = 2; // Hammer returns what?
model = 2; // Hammer returns what?
#else
model = 1; // Pentium Pro
model = 1; // Pentium Pro
#endif
stepping = 3; // ???
#else
@ -1493,6 +1491,9 @@ BX_CPU_C::CPUID(bxInstruction_c *i)
RAX = (family <<8) | (model<<4) | stepping;
RBX = RCX = 0; // reserved
#if BX_SUPPORT_PNI
RCX = 1; // report PNI
#endif
RDX = get_std_cpuid_features ();
break;
@ -1844,8 +1845,8 @@ BX_CPU_C::RDMSR(bxInstruction_c *i)
default:
#if BX_IGNORE_BAD_MSR
BX_ERROR(("RDMSR: Unknown register %#x", ECX));
return;
BX_ERROR(("RDMSR: Unknown register %#x", ECX));
return;
#else
BX_PANIC(("RDMSR: Unknown register %#x", ECX));
#endif
@ -1972,7 +1973,6 @@ BX_CPU_C::WRMSR(bxInstruction_c *i)
do_exception:
exception(BX_GP_EXCEPTION, 0, 0);
}
void
@ -2099,24 +2099,21 @@ BX_CPU_C::SYSEXIT (bxInstruction_c *i)
}
#if BX_SUPPORT_X86_64
void
BX_CPU_C::SWAPGS(bxInstruction_c *i)
void BX_CPU_C::SWAPGS(bxInstruction_c *i)
{
Bit64u temp_GS_base;
if(CPL != 0) {
if(CPL != 0)
exception(BX_GP_EXCEPTION, 0, 0);
}
temp_GS_base = MSR_GSBASE;
MSR_GSBASE = MSR_KERNELGSBASE;
MSR_KERNELGSBASE = temp_GS_base;
}
#endif
#if BX_X86_DEBUGGER
Bit32u
BX_CPU_C::hwdebug_compare(Bit32u laddr_0, unsigned size,
Bit32u BX_CPU_C::hwdebug_compare(Bit32u laddr_0, unsigned size,
unsigned opa, unsigned opb)
{
// Support x86 hardware debug facilities (DR0..DR7)

View File

@ -299,7 +299,6 @@ void BX_CPU_C::FXRSTOR(bxInstruction_c *i)
/* MOVUPS: 0F 10 */
/* MOVUPD: 66 0F 10 */
/* MOVDQU: F3 0F 6F */
void BX_CPU_C::MOVUPS_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -327,7 +326,6 @@ void BX_CPU_C::MOVUPS_VpsWps(bxInstruction_c *i)
/* MOVUPS: 0F 11 */
/* MOVUPD: 66 0F 11 */
/* MOVDQU: F3 0F 7F */
void BX_CPU_C::MOVUPS_WpsVps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -351,7 +349,6 @@ void BX_CPU_C::MOVUPS_WpsVps(bxInstruction_c *i)
/* MOVAPS: 0F 28 */
/* MOVAPD: 66 0F 28 */
/* MOVDQA: F3 0F 6F */
void BX_CPU_C::MOVAPS_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -379,7 +376,6 @@ void BX_CPU_C::MOVAPS_VpsWps(bxInstruction_c *i)
/* MOVAPS: 0F 29 */
/* MOVAPD: 66 0F 29 */
/* MOVDQA: F3 0F 7F */
void BX_CPU_C::MOVAPS_WpsVps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -525,7 +521,6 @@ void BX_CPU_C::MOVSD_WsdVsd(bxInstruction_c *i)
/* MOVLPS: 0F 12 */
/* MOVLPD: 66 0F 12 */
void BX_CPU_C::MOVLPS_VpsMq(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -549,9 +544,94 @@ void BX_CPU_C::MOVLPS_VpsMq(bxInstruction_c *i)
#endif
}
/* F2 0F 12 */
void BX_CPU_C::MOVDDUP_VpdWq(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
Bit64u val64;
BxPackedXmmRegister op;
if (i->modC0())
{
val64 = BX_READ_XMM_REG_LO_QWORD(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_qword(i->seg(), RMAddr(i), &val64);
}
op.xmm64u(0) = val64;
op.xmm64u(1) = val64;
/* now write result back to destination */
BX_WRITE_XMM_REG(i->nnn(), op);
#else
BX_INFO(("MOVDDUP_VpdWq: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/* F3 0F 12 */
void BX_CPU_C::MOVSLDUP_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op, result;
/* op is a register or memory reference */
if (i->modC0()) {
op = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op);
}
result.xmm32u(0) = op.xmm32u(0);
result.xmm32u(1) = op.xmm32u(0);
result.xmm32u(2) = op.xmm32u(2);
result.xmm32u(3) = op.xmm32u(2);
/* now write result back to destination */
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("MOVSLDUP_VpsWps: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/* F3 0F 16 */
void BX_CPU_C::MOVSHDUP_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op, result;
/* op is a register or memory reference */
if (i->modC0()) {
op = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op);
}
result.xmm32u(0) = op.xmm32u(1);
result.xmm32u(1) = op.xmm32u(1);
result.xmm32u(2) = op.xmm32u(3);
result.xmm32u(3) = op.xmm32u(3);
/* now write result back to destination */
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("MOVHLDUP_VpsWps: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/* MOVLPS: 0F 13 */
/* MOVLPD: 66 0F 13 */
void BX_CPU_C::MOVLPS_MqVps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -573,7 +653,6 @@ void BX_CPU_C::MOVLPS_MqVps(bxInstruction_c *i)
/* MOVHPS: 0F 16 */
/* MOVHPD: 66 0F 16 */
void BX_CPU_C::MOVHPS_VpsMq(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -599,7 +678,6 @@ void BX_CPU_C::MOVHPS_VpsMq(bxInstruction_c *i)
/* MOVHPS: 0F 17 */
/* MOVHPD: 66 0F 17 */
void BX_CPU_C::MOVHPS_MqVps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
@ -619,6 +697,31 @@ void BX_CPU_C::MOVHPS_MqVps(bxInstruction_c *i)
#endif
}
/* F2 0F F0 */
void BX_CPU_C::LDDQU_VdqMdq(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
/* source must be memory reference */
if (i->modC0()) {
BX_INFO(("LDDQU_VdqMdq: must be memory reference"));
UndefinedOpcode(i);
}
BxPackedXmmRegister op;
readVirtualDQword(i->seg(), RMAddr(i), (Bit8u *) &op);
/* now write result back to destination */
BX_WRITE_XMM_REG(i->nnn(), op);
#else
BX_INFO(("LDDQU_VdqMdq: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/* 66 0F F7 */
void BX_CPU_C::MASKMOVDQU_VdqVRdq(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 2
@ -1349,7 +1452,6 @@ void BX_CPU_C::MOVNTI_MdGd(bxInstruction_c *i)
/* MOVNTPS: 0F 2B */
/* MOVNTPD: 66 0F 2B */
/* MOVNTDQ: 66 0F E7 */
void BX_CPU_C::MOVNTPS_MdqVps(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1

View File

@ -2564,6 +2564,212 @@ void BX_CPU_C::MAXSS_VssWss(bxInstruction_c *i)
#endif
}
/*
* Opcode: 66 0F 7C
* Add horizontally packed double precision FP in XMM2/MEM from XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::HADDPD_VpdWpd(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
int rc;
if (MXCSR.get_DAZ())
{
op1.xmm64u(0) = handleDAZ(op1.xmm64u(0));
op1.xmm64u(1) = handleDAZ(op1.xmm64u(1));
op2.xmm64u(0) = handleDAZ(op2.xmm64u(0));
op2.xmm64u(1) = handleDAZ(op2.xmm64u(1));
}
result.xmm64u(0) =
float64_add(op1.xmm64u(0), op1.xmm64u(1), status_word);
result.xmm64u(1) =
float64_add(op2.xmm64u(1), op2.xmm64u(1), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HADDPD_VpdWpd: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/*
* Opcode: F2 0F 7C
* Add horizontally packed single precision FP in XMM2/MEM from XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::HADDPS_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
int rc;
if (MXCSR.get_DAZ()) {
op1.xmm32u(0) = handleDAZ(op1.xmm32u(0));
op1.xmm32u(1) = handleDAZ(op1.xmm32u(1));
op1.xmm32u(2) = handleDAZ(op1.xmm32u(2));
op1.xmm32u(3) = handleDAZ(op1.xmm32u(3));
op2.xmm32u(0) = handleDAZ(op2.xmm32u(0));
op2.xmm32u(1) = handleDAZ(op2.xmm32u(1));
op2.xmm32u(2) = handleDAZ(op2.xmm32u(2));
op2.xmm32u(3) = handleDAZ(op2.xmm32u(3));
}
result.xmm32u(0) =
float32_add(op1.xmm32u(0), op1.xmm32u(1), status_word);
result.xmm32u(1) =
float32_add(op1.xmm32u(2), op1.xmm32u(3), status_word);
result.xmm32u(2) =
float32_add(op2.xmm32u(0), op2.xmm32u(1), status_word);
result.xmm32u(3) =
float32_add(op2.xmm32u(2), op2.xmm32u(3), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HADDPS_VpsWps: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/*
* Opcode: 66 0F 7D
* Subtract horizontally packed double precision FP in XMM2/MEM from XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::HSUBPD_VpdWpd(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
int rc;
if (MXCSR.get_DAZ())
{
op1.xmm64u(0) = handleDAZ(op1.xmm64u(0));
op1.xmm64u(1) = handleDAZ(op1.xmm64u(1));
op2.xmm64u(0) = handleDAZ(op2.xmm64u(0));
op2.xmm64u(1) = handleDAZ(op2.xmm64u(1));
}
result.xmm64u(0) =
float64_sub(op1.xmm64u(0), op1.xmm64u(1), status_word);
result.xmm64u(1) =
float64_sub(op2.xmm64u(1), op2.xmm64u(1), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HSUBPD_VpdWpd: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/*
* Opcode: F2 0F 7D
* Subtract horizontally packed single precision FP in XMM2/MEM from XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::HSUBPS_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
int rc;
if (MXCSR.get_DAZ()) {
op1.xmm32u(0) = handleDAZ(op1.xmm32u(0));
op1.xmm32u(1) = handleDAZ(op1.xmm32u(1));
op1.xmm32u(2) = handleDAZ(op1.xmm32u(2));
op1.xmm32u(3) = handleDAZ(op1.xmm32u(3));
op2.xmm32u(0) = handleDAZ(op2.xmm32u(0));
op2.xmm32u(1) = handleDAZ(op2.xmm32u(1));
op2.xmm32u(2) = handleDAZ(op2.xmm32u(2));
op2.xmm32u(3) = handleDAZ(op2.xmm32u(3));
}
result.xmm32u(0) =
float32_sub(op1.xmm32u(0), op1.xmm32u(1), status_word);
result.xmm32u(1) =
float32_sub(op1.xmm32u(2), op1.xmm32u(3), status_word);
result.xmm32u(2) =
float32_sub(op2.xmm32u(0), op2.xmm32u(1), status_word);
result.xmm32u(3) =
float32_sub(op2.xmm32u(2), op2.xmm32u(3), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HSUBPS_VpsWps: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/*
* Opcode: 0F C2
* Compare packed single precision FP values using Ib as comparison predicate.
@ -2812,3 +3018,104 @@ void BX_CPU_C::CMPSS_VssWssIb(bxInstruction_c *i)
UndefinedOpcode(i);
#endif
}
/*
* Opcode: 66 0F D0
* Add/Subtract packed double precision FP numbers from XMM2/MEM to XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::ADDSUBPD_VpdWpd(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
if (MXCSR.get_DAZ())
{
op1.xmm64u(0) = handleDAZ(op1.xmm64u(0));
op1.xmm64u(1) = handleDAZ(op1.xmm64u(1));
op2.xmm64u(0) = handleDAZ(op2.xmm64u(0));
op2.xmm64u(1) = handleDAZ(op2.xmm64u(1));
}
result.xmm64u(0) =
float64_sub(op1.xmm64u(0), op2.xmm64u(0), status_word);
result.xmm64u(1) =
float64_add(op1.xmm64u(1), op2.xmm64u(1), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("ADDSUBPD_VpdWpd: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}
/*
* Opcode: F2 0F D0
* Add/Substract packed single precision FP numbers from XMM2/MEM to XMM1.
* Possible floating point exceptions: #I, #D, #O, #U, #P
*/
void BX_CPU_C::ADDSUBPS_VpsWps(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareSSE();
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result;
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_XMM_REG(i->rm());
}
else {
/* pointer, segment address pair */
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
softfloat_status_word_t status_word;
MXCSR_to_softfloat_status_word(status_word, MXCSR);
if (MXCSR.get_DAZ()) {
op1.xmm32u(0) = handleDAZ(op1.xmm32u(0));
op1.xmm32u(1) = handleDAZ(op1.xmm32u(1));
op1.xmm32u(2) = handleDAZ(op1.xmm32u(2));
op1.xmm32u(3) = handleDAZ(op1.xmm32u(3));
op2.xmm32u(0) = handleDAZ(op2.xmm32u(0));
op2.xmm32u(1) = handleDAZ(op2.xmm32u(1));
op2.xmm32u(2) = handleDAZ(op2.xmm32u(2));
op2.xmm32u(3) = handleDAZ(op2.xmm32u(3));
}
result.xmm32u(0) =
float32_sub(op1.xmm32u(0), op2.xmm32u(0), status_word);
result.xmm32u(1) =
float32_add(op1.xmm32u(1), op2.xmm32u(1), status_word);
result.xmm32u(2) =
float32_sub(op1.xmm32u(2), op2.xmm32u(2), status_word);
result.xmm32u(3) =
float32_add(op1.xmm32u(3), op2.xmm32u(3), status_word);
BX_CPU_THIS_PTR check_exceptionsSSE(status_word.float_exception_flags);
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("ADDSUBPS_VpsWps: required PNI, use --enable-pni option"));
UndefinedOpcode(i);
#endif
}