2003-05-26 23:30:33 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2010-02-26 01:04:31 +03:00
|
|
|
// $Id: sse_pfp.cc,v 1.63 2010-02-25 22:04:31 sshwarts Exp $
|
2005-03-19 23:44:01 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2003-05-26 23:30:33 +04:00
|
|
|
//
|
2009-10-15 00:45:29 +04:00
|
|
|
// Copyright (c) 2003-2009 Stanislav Shwartsman
|
2007-03-24 00:27:13 +03:00
|
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
2003-05-26 23:30:33 +04:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
2009-01-16 21:18:59 +03:00
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
|
2003-05-26 23:30:33 +04:00
|
|
|
//
|
2007-11-18 02:28:33 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
#define NEED_CPU_REG_SHORTCUTS 1
|
|
|
|
#include "bochs.h"
|
2006-03-07 01:03:16 +03:00
|
|
|
#include "cpu.h"
|
2003-05-26 23:30:33 +04:00
|
|
|
#define LOG_THIS BX_CPU_THIS_PTR
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
#include "fpu/softfloat-specialize.h"
|
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
void BX_CPU_C::check_exceptionsSSE(int exceptions_flags)
|
|
|
|
{
|
2009-06-21 00:39:51 +04:00
|
|
|
exceptions_flags &= MXCSR_EXCEPTIONS;
|
2003-05-26 23:30:33 +04:00
|
|
|
int unmasked = ~(MXCSR.get_exceptions_masks()) & exceptions_flags;
|
|
|
|
MXCSR.set_exceptions(exceptions_flags);
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (unmasked)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
if(BX_CPU_THIS_PTR cr4.get_OSXMMEXCPT())
|
|
|
|
exception(BX_XM_EXCEPTION, 0, 0);
|
|
|
|
else
|
|
|
|
exception(BX_UD_EXCEPTION, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-14 20:50:27 +04:00
|
|
|
BX_CPP_INLINE void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mxcsr)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
status.float_exception_flags = 0; // clear exceptions before execution
|
|
|
|
status.float_nan_handling_mode = float_first_operand_nan;
|
|
|
|
status.float_rounding_mode = mxcsr.get_rounding_mode();
|
|
|
|
// if underflow is masked and FUZ is 1, set it to 1, else to 0
|
2008-02-03 00:46:54 +03:00
|
|
|
status.flush_underflow_to_zero =
|
2003-05-26 23:30:33 +04:00
|
|
|
(mxcsr.get_flush_masked_underflow() && mxcsr.get_UM()) ? 1 : 0;
|
2009-06-05 21:48:55 +04:00
|
|
|
status.float_exception_masks = mxcsr.get_exceptions_masks();
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Comparison predicate for CMPSS/CMPPS instructions */
|
|
|
|
static float32_compare_method compare32[4] = {
|
2008-02-03 00:46:54 +03:00
|
|
|
float32_eq,
|
|
|
|
float32_lt,
|
|
|
|
float32_le,
|
2003-05-26 23:30:33 +04:00
|
|
|
float32_unordered
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Comparison predicate for CMPSD/CMPPD instructions */
|
|
|
|
static float64_compare_method compare64[4] = {
|
2008-02-03 00:46:54 +03:00
|
|
|
float64_eq,
|
|
|
|
float64_lt,
|
|
|
|
float64_le,
|
2003-05-26 23:30:33 +04:00
|
|
|
float64_unordered
|
|
|
|
};
|
2007-04-19 20:12:21 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 2A
|
|
|
|
* Convert two 32bit signed integers from MMX/MEM to two single precision FP
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #P
|
|
|
|
*/
|
2009-08-22 15:47:42 +04:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqR(bxInstruction_c *i)
|
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
|
|
|
|
|
|
|
BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
|
|
|
|
|
|
|
result.xmm32u(0) = int32_to_float32(MMXUD0(op), status_word);
|
|
|
|
result.xmm32u(1) = int32_to_float32(MMXUD1(op), status_word);
|
|
|
|
|
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result.xmm64u(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqM(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedMmxRegister op;
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
2009-08-22 15:47:42 +04:00
|
|
|
// do not cause transition to MMX state if no MMX register touched
|
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
|
|
|
MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
result.xmm32u(0) = int32_to_float32(MMXUD0(op), status_word);
|
|
|
|
result.xmm32u(1) = int32_to_float32(MMXUD1(op), status_word);
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result.xmm64u(0));
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 2A
|
|
|
|
* Convert two 32bit signed integers from MMX/MEM to two double precision FP
|
|
|
|
* Possible floating point exceptions: -
|
|
|
|
*/
|
2009-08-22 15:47:42 +04:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PD_VpdQqR(bxInstruction_c *i)
|
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
|
|
|
|
|
|
|
BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
|
|
|
|
|
|
|
|
result.xmm64u(0) = int32_to_float64(MMXUD0(op));
|
|
|
|
result.xmm64u(1) = int32_to_float64(MMXUD1(op));
|
|
|
|
|
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PD_VpdQqM(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedMmxRegister op;
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
2009-08-22 15:47:42 +04:00
|
|
|
// do not cause transition to MMX state if no MMX register touched
|
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
|
|
|
MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
result.xmm64u(0) = int32_to_float64(MMXUD0(op));
|
|
|
|
result.xmm64u(1) = int32_to_float64(MMXUD1(op));
|
|
|
|
|
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 2A
|
|
|
|
* Convert one 32bit signed integer to one double precision FP
|
|
|
|
* Possible floating point exceptions: -
|
|
|
|
*/
|
2009-08-22 15:47:42 +04:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEdR(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 result;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2009-08-22 15:47:42 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size */
|
|
|
|
result = int64_to_float64(BX_READ_64BIT_REG(i->rm()), status_word);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
result = int32_to_float64(BX_READ_32BIT_REG(i->rm()));
|
|
|
|
|
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEdM(bxInstruction_c *i)
|
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
|
|
|
float64 result;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-08-22 15:47:42 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
|
|
|
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
if (i->os64L()) /* 64 bit operand size */
|
|
|
|
{
|
|
|
|
Bit64u op = read_virtual_qword_64(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = int64_to_float64(op, status_word);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
2009-08-22 15:47:42 +04:00
|
|
|
Bit32u op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = int32_to_float64(op);
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 2A
|
|
|
|
* Convert one 32bit signed integer to one single precision FP
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #P
|
|
|
|
*/
|
2009-08-22 15:47:42 +04:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEdR(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 result;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2009-08-22 15:47:42 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size */
|
|
|
|
result = int64_to_float32(BX_READ_64BIT_REG(i->rm()), status_word);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
result = int32_to_float32(BX_READ_32BIT_REG(i->rm()), status_word);
|
|
|
|
|
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), result);
|
|
|
|
}
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-08-22 15:47:42 +04:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEdM(bxInstruction_c *i)
|
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
|
|
|
float32 result;
|
|
|
|
|
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
|
|
|
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
if (i->os64L()) /* 64 bit operand size */
|
|
|
|
{
|
|
|
|
Bit64u op = read_virtual_qword_64(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = int64_to_float32(op, status_word);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
2009-08-22 15:47:42 +04:00
|
|
|
Bit32u op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = int32_to_float32(op, status_word);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 2C
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two single precision FP numbers to two signed doubleword integers
|
2003-05-26 23:30:33 +04:00
|
|
|
* in MMX using truncation if the conversion is inexact
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2PI_PqWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
2008-10-08 14:51:38 +04:00
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
Bit64u op;
|
|
|
|
BxPackedMmxRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 r0 = (float32)(op & 0xFFFFFFFF);
|
|
|
|
float32 r1 = (float32)(op >> 32);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
r0 = float32_denormal_to_zero(r0);
|
|
|
|
r1 = float32_denormal_to_zero(r1);
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
MMXUD0(result) = float32_to_int32_round_to_zero(r0, status_word);
|
|
|
|
MMXUD1(result) = float32_to_int32_round_to_zero(r1, status_word);
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2009-08-20 23:53:05 +04:00
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_MMX_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 2C
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two double precision FP numbers to two signed doubleword integers
|
2003-05-26 23:30:33 +04:00
|
|
|
* in MMX using truncation if the conversion is inexact
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2PI_PqWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
2008-10-08 14:51:38 +04:00
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
BxPackedXmmRegister op;
|
|
|
|
BxPackedMmxRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
MMXUD0(result) = float64_to_int32_round_to_zero(op.xmm64u(0), status_word);
|
|
|
|
MMXUD1(result) = float64_to_int32_round_to_zero(op.xmm64u(1), status_word);
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2009-08-20 23:53:05 +04:00
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_MMX_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 2C
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert one double precision FP number to doubleword integer using
|
2003-05-26 23:30:33 +04:00
|
|
|
* truncation if the conversion is inexact
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSD2SI_GdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float64_denormal_to_zero(op);
|
2007-04-19 22:50:57 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2003-05-26 23:30:33 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size mode */
|
|
|
|
{
|
|
|
|
Bit64u result = float64_to_int64_round_to_zero(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->nnn(), result);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Bit32u result = float64_to_int32_round_to_zero(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-01-27 01:12:05 +03:00
|
|
|
BX_WRITE_32BIT_REGZ(i->nnn(), result);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 2C
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert one single precision FP number to doubleword integer using
|
2003-05-26 23:30:33 +04:00
|
|
|
* truncation if the conversion is inexact
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSS2SI_GdWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float32_denormal_to_zero(op);
|
2007-04-19 22:50:57 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2003-05-26 23:30:33 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size mode */
|
|
|
|
{
|
|
|
|
Bit64u result = float32_to_int64_round_to_zero(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->nnn(), result);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Bit32u result = float32_to_int32_round_to_zero(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-01-27 01:12:05 +03:00
|
|
|
BX_WRITE_32BIT_REGZ(i->nnn(), result);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Opcode: 0F 2D
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two single precision FP numbers to two signed doubleword integers
|
|
|
|
* in MMX register. When a conversion is inexact, the value returned is
|
2003-05-26 23:30:33 +04:00
|
|
|
* rounded according to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PI_PqWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
2008-10-08 14:51:38 +04:00
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
Bit64u op;
|
|
|
|
BxPackedMmxRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 r0 = (float32)(op & 0xFFFFFFFF);
|
|
|
|
float32 r1 = (float32)(op >> 32);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
r0 = float32_denormal_to_zero(r0);
|
|
|
|
r1 = float32_denormal_to_zero(r1);
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
MMXUD0(result) = float32_to_int32(r0, status_word);
|
|
|
|
MMXUD1(result) = float32_to_int32(r1, status_word);
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2009-08-20 23:53:05 +04:00
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_MMX_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 2D
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two double precision FP numbers to two signed doubleword integers
|
|
|
|
* in MMX register. When a conversion is inexact, the value returned is
|
2003-05-26 23:30:33 +04:00
|
|
|
* rounded according to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PI_PqWpd(bxInstruction_c *i)
|
2008-02-03 00:46:54 +03:00
|
|
|
{
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
2008-10-08 14:51:38 +04:00
|
|
|
|
|
|
|
/* check floating point status word for a pending FPU exceptions */
|
|
|
|
FPU_check_pending_exceptions();
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
BxPackedXmmRegister op;
|
|
|
|
BxPackedMmxRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
MMXUD0(result) = float64_to_int32(op.xmm64u(0), status_word);
|
|
|
|
MMXUD1(result) = float64_to_int32(op.xmm64u(1), status_word);
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2009-08-20 23:53:05 +04:00
|
|
|
prepareFPU2MMX(); /* cause FPU2MMX state transition */
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_MMX_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 2D
|
|
|
|
* Convert one double precision FP number to doubleword integer
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SI_GdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float64_denormal_to_zero(op);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2003-05-26 23:30:33 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size mode */
|
|
|
|
{
|
|
|
|
Bit64u result = float64_to_int64(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->nnn(), result);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Bit32u result = float64_to_int32(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-01-27 01:12:05 +03:00
|
|
|
BX_WRITE_32BIT_REGZ(i->nnn(), result);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Opcode: F3 0F 2D
|
|
|
|
* Convert one single precision FP number to doubleword integer.
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SI_GdWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float32_denormal_to_zero(op);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2003-05-26 23:30:33 +04:00
|
|
|
if (i->os64L()) /* 64 bit operand size mode */
|
|
|
|
{
|
|
|
|
Bit64u result = float32_to_int64(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->nnn(), result);
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Bit32u result = float32_to_int32(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-01-27 01:12:05 +03:00
|
|
|
BX_WRITE_32BIT_REGZ(i->nnn(), result);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5A
|
|
|
|
* Convert two single precision FP numbers to two double precision FP numbers
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PD_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
Bit64u op;
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 r0 = (float32)(op & 0xFFFFFFFF);
|
|
|
|
float32 r1 = (float32)(op >> 32);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
r0 = float32_denormal_to_zero(r0);
|
|
|
|
r1 = float32_denormal_to_zero(r1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-12-23 20:21:28 +03:00
|
|
|
result.xmm64u(0) = float32_to_float64(r0, status_word);
|
|
|
|
result.xmm64u(1) = float32_to_float64(r1, status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5A
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two double precision FP numbers to two single precision FP.
|
2003-05-26 23:30:33 +04:00
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PS_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
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 {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
result.xmm32u(0) = float64_to_float32(op.xmm64u(0), status_word);
|
|
|
|
result.xmm32u(1) = float64_to_float32(op.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
result.xmm64u(1) = 0;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 5A
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert one double precision FP number to one single precision FP.
|
2003-05-26 23:30:33 +04:00
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SS_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op;
|
|
|
|
float32 result;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float64_denormal_to_zero(op);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = float64_to_float32(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5A
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert one single precision FP number to one double precision FP.
|
2003-05-26 23:30:33 +04:00
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SD_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op;
|
|
|
|
float64 result;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float32_denormal_to_zero(op);
|
2003-05-26 23:30:33 +04:00
|
|
|
result = float32_to_float64(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5B
|
|
|
|
* Convert four signed integers to four single precision FP numbers.
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTDQ2PS_VpsWdq(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
BxPackedXmmRegister op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
op.xmm32u(0) = int32_to_float32(op.xmm32u(0), status_word);
|
|
|
|
op.xmm32u(1) = int32_to_float32(op.xmm32u(1), status_word);
|
|
|
|
op.xmm32u(2) = int32_to_float32(op.xmm32u(2), status_word);
|
|
|
|
op.xmm32u(3) = int32_to_float32(op.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-27 20:23:29 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5B
|
|
|
|
* Convert four single precision FP to four doubleword integers.
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2DQ_VdqWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
BxPackedXmmRegister op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm32u(0) = float32_denormal_to_zero(op.xmm32u(0));
|
|
|
|
op.xmm32u(1) = float32_denormal_to_zero(op.xmm32u(1));
|
|
|
|
op.xmm32u(2) = float32_denormal_to_zero(op.xmm32u(2));
|
|
|
|
op.xmm32u(3) = float32_denormal_to_zero(op.xmm32u(3));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
op.xmm32u(0) = float32_to_int32(op.xmm32u(0), status_word);
|
|
|
|
op.xmm32u(1) = float32_to_int32(op.xmm32u(1), status_word);
|
|
|
|
op.xmm32u(2) = float32_to_int32(op.xmm32u(2), status_word);
|
|
|
|
op.xmm32u(3) = float32_to_int32(op.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-27 20:23:29 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5B
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert four single precision FP to four doubleword integers using
|
2003-05-26 23:30:33 +04:00
|
|
|
* truncation if the conversion is inexact.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2DQ_VdqWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
BxPackedXmmRegister op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm32u(0) = float32_denormal_to_zero(op.xmm32u(0));
|
|
|
|
op.xmm32u(1) = float32_denormal_to_zero(op.xmm32u(1));
|
|
|
|
op.xmm32u(2) = float32_denormal_to_zero(op.xmm32u(2));
|
|
|
|
op.xmm32u(3) = float32_denormal_to_zero(op.xmm32u(3));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
2007-09-27 20:23:29 +04:00
|
|
|
op.xmm32u(0) = float32_to_int32_round_to_zero(op.xmm32u(0), status_word);
|
|
|
|
op.xmm32u(1) = float32_to_int32_round_to_zero(op.xmm32u(1), status_word);
|
|
|
|
op.xmm32u(2) = float32_to_int32_round_to_zero(op.xmm32u(2), status_word);
|
|
|
|
op.xmm32u(3) = float32_to_int32_round_to_zero(op.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-27 20:23:29 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F E6
|
2008-02-03 00:46:54 +03:00
|
|
|
* Convert two double precision FP to two signed doubleword integers using
|
2003-05-26 23:30:33 +04:00
|
|
|
* truncation if the conversion is inexact.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2DQ_VqWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
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 {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
result.xmm32u(0) = float64_to_int32_round_to_zero(op.xmm64u(0), status_word);
|
|
|
|
result.xmm32u(1) = float64_to_int32_round_to_zero(op.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
result.xmm64u(1) = 0;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F E6
|
|
|
|
* Convert two double precision FP to two signed doubleword integers.
|
|
|
|
* When a conversion is inexact, the value returned is rounded according
|
|
|
|
* to rounding control bits in MXCSR register.
|
|
|
|
* Possible floating point exceptions: #I, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2DQ_VqWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
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 {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2007-04-19 22:50:57 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2007-04-19 22:50:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
result.xmm32u(0) = float64_to_int32(op.xmm64u(0), status_word);
|
|
|
|
result.xmm32u(1) = float64_to_int32(op.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
result.xmm64u(1) = 0;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F E6
|
|
|
|
* Convert two 32bit signed integers from XMM/MEM to two double precision FP
|
|
|
|
* Possible floating point exceptions: -
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTDQ2PD_VpdWq(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
Bit64u op;
|
|
|
|
BxPackedXmmRegister result;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
Bit32u r0 = (Bit32u)(op & 0xFFFFFFFF);
|
|
|
|
Bit32u r1 = (Bit32u)(op >> 32);
|
|
|
|
|
|
|
|
result.xmm64u(0) = int32_to_float64(r0);
|
|
|
|
result.xmm64u(1) = int32_to_float64(r1);
|
|
|
|
|
|
|
|
BX_WRITE_XMM_REG(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 2E
|
|
|
|
* Compare two single precision FP numbers and set EFLAGS accordintly.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float32_compare_quiet(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2004-06-18 18:11:11 +04:00
|
|
|
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 2E
|
|
|
|
* Compare two double precision FP numbers and set EFLAGS accordintly.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float64_compare_quiet(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2004-06-18 18:11:11 +04:00
|
|
|
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 2F
|
|
|
|
* Compare two single precision FP numbers and set EFLAGS accordintly.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float32_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2004-06-18 18:11:11 +04:00
|
|
|
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 2F
|
|
|
|
* Compare two double precision FP numbers and set EFLAGS accordintly.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float64_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2004-06-18 18:11:11 +04:00
|
|
|
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 51
|
|
|
|
* Square Root packed single precision.
|
|
|
|
* Possible floating point exceptions: #I, #D, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
BxPackedXmmRegister op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm32u(0) = float32_denormal_to_zero(op.xmm32u(0));
|
|
|
|
op.xmm32u(1) = float32_denormal_to_zero(op.xmm32u(1));
|
|
|
|
op.xmm32u(2) = float32_denormal_to_zero(op.xmm32u(2));
|
|
|
|
op.xmm32u(3) = float32_denormal_to_zero(op.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
op.xmm32u(0) = float32_sqrt(op.xmm32u(0), status_word);
|
|
|
|
op.xmm32u(1) = float32_sqrt(op.xmm32u(1), status_word);
|
|
|
|
op.xmm32u(2) = float32_sqrt(op.xmm32u(2), status_word);
|
|
|
|
op.xmm32u(3) = float32_sqrt(op.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 23:09:52 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 51
|
|
|
|
* Square Root packed double precision.
|
|
|
|
* Possible floating point exceptions: #I, #D, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
BxPackedXmmRegister op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
op.xmm64u(0) = float64_sqrt(op.xmm64u(0), status_word);
|
|
|
|
op.xmm64u(1) = float64_sqrt(op.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 23:09:52 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 51
|
|
|
|
* Square Root scalar double precision.
|
|
|
|
* Possible floating point exceptions: #I, #D, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
float64 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float64_denormal_to_zero(op);
|
2007-04-19 23:09:52 +04:00
|
|
|
op = float64_sqrt(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 23:09:52 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 51
|
|
|
|
* Square Root scalar single precision.
|
|
|
|
* Possible floating point exceptions: #I, #D, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 23:09:52 +04:00
|
|
|
float32 op;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float32_denormal_to_zero(op);
|
2007-04-19 23:09:52 +04:00
|
|
|
op = float32_sqrt(op, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 23:09:52 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 58
|
|
|
|
* Add packed single precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = float32_add(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
op1.xmm32u(1) = float32_add(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(2) = float32_add(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
op1.xmm32u(3) = float32_add(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 58
|
|
|
|
* Add packed double precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = float64_add(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
op1.xmm64u(1) = float64_add(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 58
|
|
|
|
* Add the lower double precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float64_add(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 58
|
|
|
|
* Add the lower single precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float32_add(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 59
|
|
|
|
* Multiply packed single precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MULPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = float32_mul(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
op1.xmm32u(1) = float32_mul(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(2) = float32_mul(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
op1.xmm32u(3) = float32_mul(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 59
|
|
|
|
* Multiply packed double precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MULPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = float64_mul(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
op1.xmm64u(1) = float64_mul(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 59
|
|
|
|
* Multiply the lower double precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MULSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float64_mul(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 59
|
|
|
|
* Multiply the lower single precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MULSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float32_mul(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5C
|
|
|
|
* Subtract packed single precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = float32_sub(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
op1.xmm32u(1) = float32_sub(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(2) = float32_sub(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
op1.xmm32u(3) = float32_sub(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5C
|
|
|
|
* Subtract packed double precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = float64_sub(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
op1.xmm64u(1) = float64_sub(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 5C
|
|
|
|
* Subtract the lower double precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float64_sub(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5C
|
|
|
|
* Subtract the lower single precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float32_sub(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5D
|
|
|
|
* Calculate the minimum single precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MINPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = float32_compare(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = (rc == float_relation_less) ? op1.xmm32u(0) : op2.xmm32u(0);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(1) = (rc == float_relation_less) ? op1.xmm32u(1) : op2.xmm32u(1);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(2) = (rc == float_relation_less) ? op1.xmm32u(2) : op2.xmm32u(2);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(3) = (rc == float_relation_less) ? op1.xmm32u(3) : op2.xmm32u(3);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5D
|
|
|
|
* Calculate the minimum double precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MINPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int rc;
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = float64_compare(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = (rc == float_relation_less) ? op1.xmm64u(0) : op2.xmm64u(0);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float64_compare(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(1) = (rc == float_relation_less) ? op1.xmm64u(1) : op2.xmm64u(1);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 5D
|
|
|
|
* Calculate the minimum scalar double precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MINSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float64_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-02-03 00:46:54 +03:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(),
|
2003-05-26 23:30:33 +04:00
|
|
|
(rc == float_relation_less) ? op1 : op2);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5D
|
|
|
|
* Calculate the minimum scalar single precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MINSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float32_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-02-03 00:46:54 +03:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(),
|
2003-05-26 23:30:33 +04:00
|
|
|
(rc == float_relation_less) ? op1 : op2);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5E
|
|
|
|
* Divide packed single precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #Z, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = float32_div(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
op1.xmm32u(1) = float32_div(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(2) = float32_div(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
op1.xmm32u(3) = float32_div(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5E
|
|
|
|
* Divide packed double precision FP numbers from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #Z, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = float64_div(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
op1.xmm64u(1) = float64_div(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 5E
|
|
|
|
* Divide the lower double precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #Z, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float64_div(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5E
|
|
|
|
* Divide the lower single precision FP number from XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #Z, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1 = float32_div(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F 5F
|
|
|
|
* Calculate the maximum single precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXPS_VpsWps(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = float32_compare(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = (rc == float_relation_greater) ? op1.xmm32u(0) : op2.xmm32u(0);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(1) = (rc == float_relation_greater) ? op1.xmm32u(1) : op2.xmm32u(1);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(2) = (rc == float_relation_greater) ? op1.xmm32u(2) : op2.xmm32u(2);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float32_compare(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(3) = (rc == float_relation_greater) ? op1.xmm32u(3) : op2.xmm32u(3);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F 5F
|
|
|
|
* Calculate the maximum double precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXPD_VpdWpd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int rc;
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = float64_compare(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = (rc == float_relation_greater) ? op1.xmm64u(0) : op2.xmm64u(0);
|
2003-05-26 23:30:33 +04:00
|
|
|
rc = float64_compare(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(1) = (rc == float_relation_greater) ? op1.xmm64u(1) : op2.xmm64u(1);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F 5F
|
|
|
|
* Calculate the maximum scalar double precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXSD_VsdWsd(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float64_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-02-03 00:46:54 +03:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(),
|
2003-05-26 23:30:33 +04:00
|
|
|
(rc == float_relation_greater) ? op1 : op2);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F 5F
|
|
|
|
* Calculate the maxumim scalar single precision FP between XMM2/MEM to XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXSS_VssWss(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = float32_compare(op1, op2, status_word);
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-02-03 00:46:54 +03:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(),
|
2003-05-26 23:30:33 +04:00
|
|
|
(rc == float_relation_greater) ? op1 : op2);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* Opcode: 66 0F 7C
|
|
|
|
* Add horizontally packed double precision FP in XMM2/MEM from XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HADDPD_VpdWpd(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
op1.xmm64u(0) = float64_add(op1.xmm64u(0), op1.xmm64u(1), status_word);
|
|
|
|
op1.xmm64u(1) = float64_add(op2.xmm64u(0), op2.xmm64u(1), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* Opcode: F2 0F 7C
|
|
|
|
* Add horizontally packed single precision FP in XMM2/MEM from XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HADDPS_VpsWps(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
op1.xmm32u(0) = float32_add(op1.xmm32u(0), op1.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(1) = float32_add(op1.xmm32u(2), op1.xmm32u(3), status_word);
|
|
|
|
op1.xmm32u(2) = float32_add(op2.xmm32u(0), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(3) = float32_add(op2.xmm32u(2), op2.xmm32u(3), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* Opcode: 66 0F 7D
|
|
|
|
* Subtract horizontally packed double precision FP in XMM2/MEM from XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HSUBPD_VpdWpd(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
op1.xmm64u(0) = float64_sub(op1.xmm64u(0), op1.xmm64u(1), status_word);
|
|
|
|
op1.xmm64u(1) = float64_sub(op2.xmm64u(0), op2.xmm64u(1), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* Opcode: F2 0F 7D
|
|
|
|
* Subtract horizontally packed single precision FP in XMM2/MEM from XMM1.
|
|
|
|
* Possible floating point exceptions: #I, #D, #O, #U, #P
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HSUBPS_VpsWps(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
op1.xmm32u(0) = float32_sub(op1.xmm32u(0), op1.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(1) = float32_sub(op1.xmm32u(2), op1.xmm32u(3), status_word);
|
|
|
|
op1.xmm32u(2) = float32_sub(op2.xmm32u(0), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(3) = float32_sub(op2.xmm32u(2), op2.xmm32u(3), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 0F C2
|
|
|
|
* Compare packed single precision FP values using Ib as comparison predicate.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPS_VpsWpsIb(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int ib = i->Ib();
|
|
|
|
|
2006-02-22 23:20:21 +03:00
|
|
|
/* mask used bits, ignore reserved */
|
|
|
|
if (ib > 7) {
|
|
|
|
BX_ERROR(("CMPPS_VpsWpsIb: unrecognized predicate %u", i->Ib()));
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
ib &= 7;
|
2006-02-22 23:20:21 +03:00
|
|
|
|
2003-05-26 23:30:33 +04:00
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if(ib < 4)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(0) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(0), op2.xmm32u(0), status) ? 0xFFFFFFFF : 0;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(1) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(1), op2.xmm32u(1), status) ? 0xFFFFFFFF : 0;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(2) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(2), op2.xmm32u(2), status) ? 0xFFFFFFFF : 0;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(3) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(3), op2.xmm32u(3), status) ? 0xFFFFFFFF : 0;
|
|
|
|
}
|
2006-02-22 23:20:21 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
ib -= 4;
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(0) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(0), op2.xmm32u(0), status) ? 0 : 0xFFFFFFFF;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(1) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(1), op2.xmm32u(1), status) ? 0 : 0xFFFFFFFF;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(2) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(2), op2.xmm32u(2), status) ? 0 : 0xFFFFFFFF;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm32u(3) =
|
2003-05-26 23:30:33 +04:00
|
|
|
compare32[ib](op1.xmm32u(3), op2.xmm32u(3), status) ? 0 : 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: 66 0F C2
|
|
|
|
* Compare packed double precision FP values using Ib as comparison predicate.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPD_VpdWpdIb(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int ib = i->Ib();
|
|
|
|
|
2006-02-22 23:20:21 +03:00
|
|
|
/* mask used bits, ignore reserved */
|
|
|
|
if (ib > 7) {
|
|
|
|
BX_ERROR(("CMPPD_VpdWpdIb: unrecognized predicate %u", i->Ib()));
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
ib &= 7;
|
2006-02-22 23:20:21 +03:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if(ib < 4)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm64u(0) = compare64[ib](op1.xmm64u(0), op2.xmm64u(0), status) ?
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0;
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm64u(1) = compare64[ib](op1.xmm64u(1), op2.xmm64u(1), status) ?
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0;
|
|
|
|
}
|
2006-02-22 23:20:21 +03:00
|
|
|
else
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
ib -= 4;
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm64u(0) = compare64[ib](op1.xmm64u(0), op2.xmm64u(0), status) ?
|
2003-05-26 23:30:33 +04:00
|
|
|
0 : BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
2008-02-03 00:46:54 +03:00
|
|
|
op1.xmm64u(1) = compare64[ib](op1.xmm64u(1), op2.xmm64u(1), status) ?
|
2003-05-26 23:30:33 +04:00
|
|
|
0 : BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F2 0F C2
|
|
|
|
* Compare double precision FP values using Ib as comparison predicate.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD_VsdWsdIb(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->nnn()), op2, result = 0;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_qword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int ib = i->Ib();
|
|
|
|
|
2006-02-22 23:20:21 +03:00
|
|
|
/* mask used bits, ignore reserved */
|
|
|
|
if (ib > 7) {
|
|
|
|
BX_ERROR(("CMPSD_VsdWsdIb: unrecognized predicate %u", i->Ib()));
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
ib &= 7;
|
2006-02-22 23:20:21 +03:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float64_denormal_to_zero(op1);
|
|
|
|
op2 = float64_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ib < 4) {
|
|
|
|
if(compare64[ib](op1, op2, status_word)) {
|
|
|
|
result = BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
|
|
|
} else {
|
|
|
|
result = 0;
|
|
|
|
}
|
2006-02-22 23:20:21 +03:00
|
|
|
} else {
|
2003-05-26 23:30:33 +04:00
|
|
|
if(compare64[ib-4](op1, op2, status_word)) {
|
|
|
|
result = 0;
|
|
|
|
} else {
|
|
|
|
result = BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), result);
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-05-26 23:30:33 +04:00
|
|
|
* Opcode: F3 0F C2
|
|
|
|
* Compare single precision FP values using Ib as comparison predicate.
|
|
|
|
* Possible floating point exceptions: #I, #D
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSS_VssWssIb(bxInstruction_c *i)
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-04-19 20:12:21 +04:00
|
|
|
float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->nnn()), op2, result = 0;
|
2003-05-26 23:30:33 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-05-26 23:30:33 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op2 = read_virtual_dword(i->seg(), eaddr);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-05-26 23:30:33 +04:00
|
|
|
int ib = i->Ib();
|
|
|
|
|
2006-02-22 23:20:21 +03:00
|
|
|
/* mask used bits, ignore reserved */
|
|
|
|
if (ib > 7) {
|
|
|
|
BX_ERROR(("CMPSS_VssWssIb: unrecognized predicate %u", i->Ib()));
|
|
|
|
}
|
2008-02-03 00:46:54 +03:00
|
|
|
ib &= 7;
|
2006-02-22 23:20:21 +03:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-05-26 23:30:33 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1 = float32_denormal_to_zero(op1);
|
|
|
|
op2 = float32_denormal_to_zero(op2);
|
2003-05-26 23:30:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ib < 4) {
|
|
|
|
if(compare32[ib](op1, op2, status_word)) {
|
|
|
|
result = 0xFFFFFFFF;
|
|
|
|
} else {
|
|
|
|
result = 0;
|
|
|
|
}
|
2006-02-22 23:20:21 +03:00
|
|
|
} else {
|
2003-05-26 23:30:33 +04:00
|
|
|
if(compare32[ib-4](op1, op2, status_word)) {
|
|
|
|
result = 0;
|
|
|
|
} else {
|
|
|
|
result = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2003-05-26 23:30:33 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), result);
|
|
|
|
}
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* 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
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSUBPD_VpdWpd(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
if (MXCSR.get_DAZ())
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm64u(0) = float64_sub(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
op1.xmm64u(1) = float64_add(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/*
|
2003-08-30 01:20:52 +04:00
|
|
|
* 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
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSUBPS_VpsWps(bxInstruction_c *i)
|
2003-08-30 01:20:52 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2;
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2003-08-30 01:20:52 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2004-06-18 18:11:11 +04:00
|
|
|
float_status_t status_word;
|
2003-11-07 23:53:27 +03:00
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2005-11-27 00:36:51 +03:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
|
|
|
|
2007-09-21 02:55:03 +04:00
|
|
|
op1.xmm32u(0) = float32_sub(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
op1.xmm32u(1) = float32_add(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
op1.xmm32u(2) = float32_sub(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
op1.xmm32u(3) = float32_add(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
2003-08-30 01:20:52 +04:00
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-09-21 02:55:03 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
2003-08-30 01:20:52 +04:00
|
|
|
}
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
/* 66 0F 3A 08 */
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPS_VpsWpsIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op;
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-20 18:10:44 +04:00
|
|
|
Bit8u control = i->Ib();
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// override MXCSR rounding mode with control coming from imm8
|
|
|
|
if ((control & 0x4) == 0)
|
|
|
|
status_word.float_rounding_mode = control & 0x3;
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm32u(0) = float32_denormal_to_zero(op.xmm32u(0));
|
|
|
|
op.xmm32u(1) = float32_denormal_to_zero(op.xmm32u(1));
|
|
|
|
op.xmm32u(2) = float32_denormal_to_zero(op.xmm32u(2));
|
|
|
|
op.xmm32u(3) = float32_denormal_to_zero(op.xmm32u(3));
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
2009-05-21 15:44:59 +04:00
|
|
|
op.xmm32u(0) = float32_round_to_int(op.xmm32u(0), status_word);
|
|
|
|
op.xmm32u(1) = float32_round_to_int(op.xmm32u(1), status_word);
|
|
|
|
op.xmm32u(2) = float32_round_to_int(op.xmm32u(2), status_word);
|
|
|
|
op.xmm32u(3) = float32_round_to_int(op.xmm32u(3), status_word);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// ignore precision exception result
|
|
|
|
if (control & 0x8)
|
|
|
|
status_word.float_exception_flags &= ~float_flag_inexact;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 66 0F 3A 09 */
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPD_VpdWpdIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
2008-04-20 18:10:44 +04:00
|
|
|
BxPackedXmmRegister op;
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-20 18:10:44 +04:00
|
|
|
Bit8u control = i->Ib();
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// override MXCSR rounding mode with control coming from imm8
|
|
|
|
if ((control & 0x4) == 0)
|
|
|
|
status_word.float_rounding_mode = control & 0x3;
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op.xmm64u(0) = float64_denormal_to_zero(op.xmm64u(0));
|
|
|
|
op.xmm64u(1) = float64_denormal_to_zero(op.xmm64u(1));
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
2009-05-21 15:44:59 +04:00
|
|
|
op.xmm64u(0) = float64_round_to_int(op.xmm64u(0), status_word);
|
|
|
|
op.xmm64u(1) = float64_round_to_int(op.xmm64u(1), status_word);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// ignore precision exception result
|
|
|
|
if (control & 0x8)
|
|
|
|
status_word.float_exception_flags &= ~float_flag_inexact;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 66 0F 3A 0A */
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSS_VssWssIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
float32 op;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_DWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_dword(i->seg(), eaddr);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-20 18:10:44 +04:00
|
|
|
Bit8u control = i->Ib();
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// override MXCSR rounding mode with control coming from imm8
|
|
|
|
if ((control & 0x4) == 0)
|
|
|
|
status_word.float_rounding_mode = control & 0x3;
|
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float32_denormal_to_zero(op);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
2009-05-21 15:44:59 +04:00
|
|
|
op = float32_round_to_int(op, status_word);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// ignore precision exception result
|
|
|
|
if (control & 0x8)
|
|
|
|
status_word.float_exception_flags &= ~float_flag_inexact;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_DWORD(i->nnn(), op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 66 0F 3A 0B */
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSD_VsdWsdIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
float64 op;
|
|
|
|
|
|
|
|
/* op is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op = BX_READ_XMM_REG_LO_QWORD(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
op = read_virtual_qword(i->seg(), eaddr);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
2008-04-20 18:10:44 +04:00
|
|
|
Bit8u control = i->Ib();
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// override MXCSR rounding mode with control coming from imm8
|
|
|
|
if ((control & 0x4) == 0)
|
|
|
|
status_word.float_rounding_mode = control & 0x3;
|
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
if (MXCSR.get_DAZ()) op = float64_denormal_to_zero(op);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
2009-05-21 15:44:59 +04:00
|
|
|
op = float64_round_to_int(op, status_word);
|
2007-04-19 20:12:21 +04:00
|
|
|
|
|
|
|
// ignore precision exception result
|
|
|
|
if (control & 0x8)
|
|
|
|
status_word.float_exception_flags &= ~float_flag_inexact;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2008-04-20 18:10:44 +04:00
|
|
|
BX_WRITE_XMM_REG_LO_QWORD(i->nnn(), op);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
2008-02-03 00:46:54 +03:00
|
|
|
/* Opcode: 66 0F 3A 40
|
2007-04-19 20:12:21 +04:00
|
|
|
* Selectively multiply packed SP floating-point values from xmm1 with
|
2008-02-03 00:46:54 +03:00
|
|
|
* packed SP floating-point values from xmm2, add and selectively
|
2007-04-19 20:12:21 +04:00
|
|
|
* store the packed SP floating-point values or zero values to xmm1
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPS_VpsWpsIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, tmp;
|
|
|
|
Bit8u mask = i->Ib();
|
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm32u(0) = float32_denormal_to_zero(op1.xmm32u(0));
|
|
|
|
op1.xmm32u(1) = float32_denormal_to_zero(op1.xmm32u(1));
|
|
|
|
op1.xmm32u(2) = float32_denormal_to_zero(op1.xmm32u(2));
|
|
|
|
op1.xmm32u(3) = float32_denormal_to_zero(op1.xmm32u(3));
|
2007-04-19 20:12:21 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm32u(0) = float32_denormal_to_zero(op2.xmm32u(0));
|
|
|
|
op2.xmm32u(1) = float32_denormal_to_zero(op2.xmm32u(1));
|
|
|
|
op2.xmm32u(2) = float32_denormal_to_zero(op2.xmm32u(2));
|
|
|
|
op2.xmm32u(3) = float32_denormal_to_zero(op2.xmm32u(3));
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp.xmm64u(0) = tmp.xmm64u(1) = 0;
|
|
|
|
|
|
|
|
if (mask & 0x10)
|
|
|
|
tmp.xmm32u(0) = float32_mul(op1.xmm32u(0), op2.xmm32u(0), status_word);
|
|
|
|
if (mask & 0x20)
|
|
|
|
tmp.xmm32u(1) = float32_mul(op1.xmm32u(1), op2.xmm32u(1), status_word);
|
|
|
|
if (mask & 0x40)
|
|
|
|
tmp.xmm32u(2) = float32_mul(op1.xmm32u(2), op2.xmm32u(2), status_word);
|
|
|
|
if (mask & 0x80)
|
|
|
|
tmp.xmm32u(3) = float32_mul(op1.xmm32u(3), op2.xmm32u(3), status_word);
|
|
|
|
|
|
|
|
float32 r1 = float32_add(tmp.xmm32u(0), tmp.xmm32u(1), status_word);
|
|
|
|
float32 r2 = float32_add(tmp.xmm32u(2), tmp.xmm32u(3), status_word);
|
|
|
|
float32 r = float32_add(r1, r2, status_word);
|
|
|
|
|
|
|
|
op1.xmm64u(0) = op1.xmm64u(1) = 0;
|
|
|
|
|
|
|
|
if (mask & 0x01) op1.xmm32u(0) = r;
|
|
|
|
if (mask & 0x02) op1.xmm32u(1) = r;
|
|
|
|
if (mask & 0x04) op1.xmm32u(2) = r;
|
|
|
|
if (mask & 0x08) op1.xmm32u(3) = r;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 20:12:21 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Opcode: 66 0F 3A 41
|
|
|
|
* Selectively multiply packed DP floating-point values from xmm1 with
|
2008-02-03 00:46:54 +03:00
|
|
|
* packed DP floating-point values from xmm2, add and selectively
|
2007-04-19 20:12:21 +04:00
|
|
|
* store the packed DP floating-point values or zero values to xmm1
|
|
|
|
*/
|
2008-03-23 00:29:41 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPD_VpdWpdIb(bxInstruction_c *i)
|
2007-04-19 20:12:21 +04:00
|
|
|
{
|
|
|
|
BX_CPU_THIS_PTR prepareSSE();
|
|
|
|
|
|
|
|
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, tmp;
|
|
|
|
Bit8u mask = i->Ib();
|
|
|
|
|
|
|
|
/* op2 is a register or memory reference */
|
|
|
|
if (i->modC0()) {
|
|
|
|
op2 = BX_READ_XMM_REG(i->rm());
|
|
|
|
}
|
|
|
|
else {
|
2008-08-08 13:22:49 +04:00
|
|
|
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
2007-04-19 20:12:21 +04:00
|
|
|
/* pointer, segment address pair */
|
2008-08-08 13:22:49 +04:00
|
|
|
readVirtualDQwordAligned(i->seg(), eaddr, (Bit8u *) &op2);
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
float_status_t status_word;
|
|
|
|
mxcsr_to_softfloat_status_word(status_word, MXCSR);
|
|
|
|
|
|
|
|
if (MXCSR.get_DAZ()) {
|
2008-04-05 00:03:27 +04:00
|
|
|
op1.xmm64u(0) = float64_denormal_to_zero(op1.xmm64u(0));
|
|
|
|
op1.xmm64u(1) = float64_denormal_to_zero(op1.xmm64u(1));
|
2007-04-19 20:12:21 +04:00
|
|
|
|
2008-04-05 00:03:27 +04:00
|
|
|
op2.xmm64u(0) = float64_denormal_to_zero(op2.xmm64u(0));
|
|
|
|
op2.xmm64u(1) = float64_denormal_to_zero(op2.xmm64u(1));
|
2007-04-19 20:12:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp.xmm64u(0) = tmp.xmm64u(1) = 0;
|
|
|
|
|
|
|
|
if (mask & 0x10)
|
|
|
|
tmp.xmm64u(0) = float64_mul(op1.xmm64u(0), op2.xmm64u(0), status_word);
|
|
|
|
if (mask & 0x20)
|
|
|
|
tmp.xmm64u(1) = float64_mul(op1.xmm64u(1), op2.xmm64u(1), status_word);
|
|
|
|
|
|
|
|
float64 result = float64_add(tmp.xmm64u(0), tmp.xmm64u(1), status_word);
|
|
|
|
|
|
|
|
op1.xmm64u(0) = op1.xmm64u(1) = 0;
|
|
|
|
|
|
|
|
if (mask & 0x01) op1.xmm64u(0) = result;
|
|
|
|
if (mask & 0x02) op1.xmm64u(1) = result;
|
|
|
|
|
2009-05-29 00:18:34 +04:00
|
|
|
check_exceptionsSSE(status_word.float_exception_flags);
|
2007-04-19 20:12:21 +04:00
|
|
|
BX_WRITE_XMM_REG(i->nnn(), op1);
|
|
|
|
}
|