//===- subzero/unittest/AssemblerX8664/XmmArith.cpp -----------------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AssemblerX8664/TestUtil.h"
namespace Ice {
namespace X8664 {
namespace Test {
namespace {
TEST_F(AssemblerX8664Test, ArithSS) {
#define TestArithSSXmmXmm(FloatSize, Src, Value0, Dst, Value1, Inst, Op) \
do { \
static_assert(FloatSize == 32 || FloatSize == 64, \
"Invalid fp size " #FloatSize); \
static constexpr char TestString[] = \
"(" #FloatSize ", " #Src ", " #Value0 ", " #Dst ", " #Value1 \
", " #Inst ", " #Op ")"; \
static constexpr bool IsDouble = FloatSize == 64; \
using Type = std::conditional<IsDouble, double, float>::type; \
const uint32_t T0 = allocateQword(); \
const Type V0 = Value0; \
const uint32_t T1 = allocateQword(); \
const Type V1 = Value1; \
\
__ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movss(IceType_f##FloatSize, Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
if (IsDouble) { \
test.setQwordTo(T0, static_cast<double>(V0)); \
test.setQwordTo(T1, static_cast<double>(V1)); \
} else { \
test.setDwordTo(T0, static_cast<float>(V0)); \
test.setDwordTo(T1, static_cast<float>(V1)); \
} \
\
test.run(); \
\
ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
reset(); \
} while (0)
#define TestArithSSXmmAddr(FloatSize, Value0, Dst, Value1, Inst, Op) \
do { \
static_assert(FloatSize == 32 || FloatSize == 64, \
"Invalid fp size " #FloatSize); \
static constexpr char TestString[] = \
"(" #FloatSize ", Addr, " #Value0 ", " #Dst ", " #Value1 ", " #Inst \
", " #Op ")"; \
static constexpr bool IsDouble = FloatSize == 64; \
using Type = std::conditional<IsDouble, double, float>::type; \
const uint32_t T0 = allocateQword(); \
const Type V0 = Value0; \
const uint32_t T1 = allocateQword(); \
const Type V1 = Value1; \
\
__ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
if (IsDouble) { \
test.setQwordTo(T0, static_cast<double>(V0)); \
test.setQwordTo(T1, static_cast<double>(V1)); \
} else { \
test.setDwordTo(T0, static_cast<float>(V0)); \
test.setDwordTo(T1, static_cast<float>(V1)); \
} \
\
test.run(); \
\
ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
reset(); \
} while (0)
#define TestArithSS(FloatSize, Src, Dst0, Dst1) \
do { \
TestArithSSXmmXmm(FloatSize, Src, 1.0, Dst0, 10.0, addss, +); \
TestArithSSXmmAddr(FloatSize, 2.0, Dst1, 20.0, addss, +); \
TestArithSSXmmXmm(FloatSize, Src, 3.0, Dst0, 30.0, subss, -); \
TestArithSSXmmAddr(FloatSize, 4.0, Dst1, 40.0, subss, -); \
TestArithSSXmmXmm(FloatSize, Src, 5.0, Dst0, 50.0, mulss, *); \
TestArithSSXmmAddr(FloatSize, 6.0, Dst1, 60.0, mulss, *); \
TestArithSSXmmXmm(FloatSize, Src, 7.0, Dst0, 70.0, divss, / ); \
TestArithSSXmmAddr(FloatSize, 8.0, Dst1, 80.0, divss, / ); \
} while (0)
#define TestImpl(Src, Dst0, Dst1) \
do { \
TestArithSS(32, Src, Dst0, Dst1); \
TestArithSS(64, Src, Dst0, Dst1); \
} while (0)
TestImpl(xmm0, xmm1, xmm2);
TestImpl(xmm1, xmm2, xmm3);
TestImpl(xmm2, xmm3, xmm4);
TestImpl(xmm3, xmm4, xmm5);
TestImpl(xmm4, xmm5, xmm6);
TestImpl(xmm5, xmm6, xmm7);
TestImpl(xmm6, xmm7, xmm8);
TestImpl(xmm7, xmm8, xmm9);
TestImpl(xmm8, xmm9, xmm10);
TestImpl(xmm9, xmm10, xmm11);
TestImpl(xmm10, xmm11, xmm12);
TestImpl(xmm11, xmm12, xmm13);
TestImpl(xmm12, xmm13, xmm14);
TestImpl(xmm13, xmm14, xmm15);
TestImpl(xmm14, xmm15, xmm0);
TestImpl(xmm15, xmm0, xmm1);
#undef TestImpl
#undef TestArithSS
#undef TestArithSSXmmAddr
#undef TestArithSSXmmXmm
}
TEST_F(AssemblerX8664Test, PArith) {
#define TestPArithXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
", " #Type ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestPArithXmmAddr(Dst, Value0, Value1, Inst, Op, Type, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
", " #Type ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestPArithXmmImm(Dst, Value0, Imm, Inst, Op, Type, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Imm ", " #Inst ", " #Op ", " #Type \
", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.run(); \
\
ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op Imm, test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestPAndnXmmXmm(Dst, Value0, Src, Value1, Type, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", pandn, " #Type \
", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(~(packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestPAndnXmmAddr(Dst, Value0, Value1, Type, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", pandn, " #Type ", " #Size \
")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ((~packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestPArithSize(Dst, Src, Size) \
do { \
static_assert(Size == 8 || Size == 16 || Size == 32, "Invalid size."); \
if (Size != 8) { \
TestPArithXmmXmm( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
(uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
3u, psra, >>, int, Size); \
TestPArithXmmXmm( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
(uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
3u, psrl, >>, uint, Size); \
TestPArithXmmXmm( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
(uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
3u, psll, <<, uint, Size); \
\
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
pmull, *, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
pmull, *, int, Size); \
if (Size != 16) { \
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
pmuludq, *, uint, Size); \
TestPArithXmmAddr( \
Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
pmuludq, *, uint, Size); \
} \
} \
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
padd, +, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
padd, +, int, Size); \
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
psub, -, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
psub, -, int, Size); \
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
pand, &, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
pand, &, int, Size); \
\
TestPAndnXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
int, Size); \
TestPAndnXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
int, Size); \
\
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
por, |, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
por, |, int, Size); \
TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
uint64_t(0x8080404002020101ull)), \
Src, (uint64_t(0xFFFFFFFF00000000ull), \
uint64_t(0x0123456789ABCDEull)), \
pxor, ^, int, Size); \
TestPArithXmmAddr( \
Dst, \
(uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
(uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
pxor, ^, int, Size); \
} while (0)
#define TestPArith(Src, Dst) \
do { \
TestPArithSize(Src, Dst, 8); \
TestPArithSize(Src, Dst, 16); \
TestPArithSize(Src, Dst, 32); \
} while (0)
TestPArith(xmm0, xmm1);
TestPArith(xmm1, xmm2);
TestPArith(xmm2, xmm3);
TestPArith(xmm3, xmm4);
TestPArith(xmm4, xmm5);
TestPArith(xmm5, xmm6);
TestPArith(xmm6, xmm7);
TestPArith(xmm7, xmm8);
TestPArith(xmm8, xmm9);
TestPArith(xmm9, xmm10);
TestPArith(xmm10, xmm11);
TestPArith(xmm11, xmm12);
TestPArith(xmm12, xmm13);
TestPArith(xmm13, xmm14);
TestPArith(xmm14, xmm15);
TestPArith(xmm15, xmm0);
#undef TestPArith
#undef TestPArithSize
#undef TestPAndnXmmAddr
#undef TestPAndnXmmXmm
#undef TestPArithXmmImm
#undef TestPArithXmmAddr
#undef TestPArithXmmXmm
}
TEST_F(AssemblerX8664Test, ArithPS) {
#define TestArithPSXmmXmm(FloatSize, Dst, Value0, Src, Value1, Inst, Op, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
", " #Type ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
\
reset(); \
} while (0)
#define TestArithPSXmmXmmUntyped(Dst, Value0, Src, Value1, Inst, Op, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
", " #Type ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
\
reset(); \
} while (0)
#define TestArithPSXmmAddrUntyped(Dst, Value0, Value1, Inst, Op, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
", " #Type ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
\
reset(); \
} while (0)
#define TestMinMaxPS(FloatSize, Dst, Value0, Src, Value1, Inst, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Type \
")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0).Inst(V1), test.Dst<Dqword>()) << TestString; \
\
reset(); \
} while (0)
#define TestArithPSXmmAddr(FloatSize, Dst, Value0, Value1, Inst, Op, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
", " #Type ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
\
reset(); \
} while (0)
#define TestArithPS(Dst, Src) \
do { \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), addps, +, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), addps, +, float); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), subps, -, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), subps, -, float); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), mulps, *, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), mulps, *, float); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), divps, /, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), divps, /, float); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), andps, &, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), andps, &, float); \
TestArithPSXmmXmm(64, Dst, (1.0, -1000.0), Src, (0.55, 1.21), andps, &, \
double); \
TestArithPSXmmAddr(64, Dst, (1.0, -1000.0), (0.55, 1.21), andps, &, \
double); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), orps, |, float); \
TestArithPSXmmXmm(64, Dst, (1.0, -1000.0), Src, (0.55, 1.21), orps, |, \
double); \
TestMinMaxPS(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), minps, float); \
TestMinMaxPS(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), maxps, float); \
TestMinMaxPS(64, Dst, (1.0, -1000.0), Src, (0.55, 1.21), minps, double); \
TestMinMaxPS(64, Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxps, double); \
TestArithPSXmmXmm(32, Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
(0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
TestArithPSXmmAddr(32, Dst, (1.0, 100.0, -1000.0, 20.0), \
(0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
TestArithPSXmmXmm(64, Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorps, ^, \
double); \
TestArithPSXmmAddr(64, Dst, (1.0, -1000.0), (0.55, 1.21), xorps, ^, \
double); \
} while (0)
TestArithPS(xmm0, xmm1);
TestArithPS(xmm1, xmm2);
TestArithPS(xmm2, xmm3);
TestArithPS(xmm3, xmm4);
TestArithPS(xmm4, xmm5);
TestArithPS(xmm5, xmm6);
TestArithPS(xmm6, xmm7);
TestArithPS(xmm7, xmm8);
TestArithPS(xmm8, xmm9);
TestArithPS(xmm9, xmm10);
TestArithPS(xmm10, xmm11);
TestArithPS(xmm11, xmm12);
TestArithPS(xmm12, xmm13);
TestArithPS(xmm13, xmm14);
TestArithPS(xmm14, xmm15);
TestArithPS(xmm15, xmm0);
#undef TestArithPs
#undef TestMinMaxPS
#undef TestArithPSXmmXmmUntyped
#undef TestArithPSXmmAddr
#undef TestArithPSXmmXmm
}
TEST_F(AssemblerX8664Test, Blending) {
using f32 = float;
using i8 = uint8_t;
#define TestBlendingXmmXmm(Dst, Value0, Src, Value1, M /*ask*/, Inst, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #M ", " #Inst \
", " #Type ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
const uint32_t Mask = allocateDqword(); \
const Dqword MaskValue M; \
\
__ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_##Type, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.setDqwordTo(Mask, MaskValue); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestBlendingXmmAddr(Dst, Value0, Value1, M /*ask*/, Inst, Type) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #M ", " #Inst ", " #Type \
")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
const uint32_t Mask = allocateDqword(); \
const Dqword MaskValue M; \
\
__ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_##Type, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.setDqwordTo(Mask, MaskValue); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
<< TestString; \
reset(); \
} while (0)
#define TestBlending(Src, Dst) \
do { \
TestBlendingXmmXmm( \
Dst, (1.0, 2.0, 1.0, 2.0), Src, (-1.0, -2.0, -1.0, -2.0), \
(uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
blendvps, f32); \
TestBlendingXmmAddr( \
Dst, (1.0, 2.0, 1.0, 2.0), (-1.0, -2.0, -1.0, -2.0), \
(uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
blendvps, f32); \
TestBlendingXmmXmm( \
Dst, \
(uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
Src, \
(uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
(uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
pblendvb, i8); \
TestBlendingXmmAddr( \
Dst, \
(uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
(uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
(uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
pblendvb, i8); \
} while (0)
/* xmm0 is taken. It is the implicit mask . */
TestBlending(xmm1, xmm2);
TestBlending(xmm2, xmm3);
TestBlending(xmm3, xmm4);
TestBlending(xmm4, xmm5);
TestBlending(xmm5, xmm6);
TestBlending(xmm6, xmm7);
TestBlending(xmm7, xmm8);
TestBlending(xmm8, xmm9);
TestBlending(xmm9, xmm10);
TestBlending(xmm10, xmm11);
TestBlending(xmm11, xmm12);
TestBlending(xmm12, xmm13);
TestBlending(xmm13, xmm14);
TestBlending(xmm14, xmm15);
TestBlending(xmm15, xmm1);
#undef TestBlending
#undef TestBlendingXmmAddr
#undef TestBlendingXmmXmm
}
TEST_F(AssemblerX8664Test, Cmpps) {
#define TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, C, Op, Type) \
do { \
static constexpr char TestString[] = \
"(" #Src ", " #Dst ", " #C ", " #Op ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ cmpps(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
Cond::Cmpps_##C); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
; \
reset(); \
} while (0)
#define TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, C, Op, Type) \
do { \
static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ cmpps(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1), \
Cond::Cmpps_##C); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
; \
reset(); \
} while (0)
#define TestCmppsOrdUnordXmmXmm(FloatSize, Dst, Value0, Src, Value1, C, Type) \
do { \
static constexpr char TestString[] = "(" #Src ", " #Dst ", " #C ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
std::numeric_limits<float>::quiet_NaN()); \
const uint32_t T1 = allocateDqword(); \
const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
std::numeric_limits<float>::quiet_NaN()); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ cmpps(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
Cond::Cmpps_##C); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
; \
reset(); \
} while (0)
#define TestCmppsOrdUnordXmmAddr(FloatSize, Dst, Value0, Value1, C, Type) \
do { \
static constexpr char TestString[] = "(" #Dst ", " #C ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
std::numeric_limits<float>::quiet_NaN()); \
const uint32_t T1 = allocateDqword(); \
const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
std::numeric_limits<float>::quiet_NaN()); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ cmpps(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1), \
Cond::Cmpps_##C); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(packedAs<Type>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
; \
reset(); \
} while (0)
#define TestCmpps(FloatSize, Dst, Value0, Src, Value1, Type) \
do { \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
TestCmppsOrdUnordXmmXmm(FloatSize, Dst, Value0, Src, Value1, unord, Type); \
TestCmppsOrdUnordXmmAddr(FloatSize, Dst, Value0, Value1, unord, Type); \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
TestCmppsXmmXmm(FloatSize, Dst, Value0, Src, Value1, eq, ==, Type); \
TestCmppsXmmAddr(FloatSize, Dst, Value0, Value1, eq, ==, Type); \
if (FloatSize == 32) { \
TestCmppsOrdUnordXmmXmm( \
32, Dst, (1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
std::numeric_limits<float>::quiet_NaN()), \
Src, (1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
std::numeric_limits<float>::quiet_NaN()), \
unord, Type); \
TestCmppsOrdUnordXmmAddr( \
32, Dst, (1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
std::numeric_limits<float>::quiet_NaN()), \
(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
std::numeric_limits<float>::quiet_NaN()), \
unord, Type); \
} else { \
TestCmppsOrdUnordXmmXmm(64, Dst, \
(1.0, std::numeric_limits<double>::quiet_NaN()), \
Src, (std::numeric_limits<double>::quiet_NaN(), \
std::numeric_limits<double>::quiet_NaN()), \
unord, Type); \
TestCmppsOrdUnordXmmXmm(64, Dst, (1.0, 1.0), Src, \
(1.0, std::numeric_limits<double>::quiet_NaN()), \
unord, Type); \
TestCmppsOrdUnordXmmAddr( \
64, Dst, (1.0, std::numeric_limits<double>::quiet_NaN()), \
(std::numeric_limits<double>::quiet_NaN(), \
std::numeric_limits<double>::quiet_NaN()), \
unord, Type); \
TestCmppsOrdUnordXmmAddr( \
64, Dst, (1.0, 1.0), \
(1.0, std::numeric_limits<double>::quiet_NaN()), unord, Type); \
} \
} while (0)
#define TestCmppsSize(FloatSize, Value0, Value1, Type) \
do { \
TestCmpps(FloatSize, xmm0, Value0, xmm1, Value1, Type); \
TestCmpps(FloatSize, xmm1, Value0, xmm2, Value1, Type); \
TestCmpps(FloatSize, xmm2, Value0, xmm3, Value1, Type); \
TestCmpps(FloatSize, xmm3, Value0, xmm4, Value1, Type); \
TestCmpps(FloatSize, xmm4, Value0, xmm5, Value1, Type); \
TestCmpps(FloatSize, xmm5, Value0, xmm6, Value1, Type); \
TestCmpps(FloatSize, xmm6, Value0, xmm7, Value1, Type); \
TestCmpps(FloatSize, xmm7, Value0, xmm8, Value1, Type); \
TestCmpps(FloatSize, xmm8, Value0, xmm9, Value1, Type); \
TestCmpps(FloatSize, xmm9, Value0, xmm10, Value1, Type); \
TestCmpps(FloatSize, xmm10, Value0, xmm11, Value1, Type); \
TestCmpps(FloatSize, xmm11, Value0, xmm12, Value1, Type); \
TestCmpps(FloatSize, xmm12, Value0, xmm13, Value1, Type); \
TestCmpps(FloatSize, xmm13, Value0, xmm14, Value1, Type); \
TestCmpps(FloatSize, xmm14, Value0, xmm15, Value1, Type); \
TestCmpps(FloatSize, xmm15, Value0, xmm0, Value1, Type); \
} while (0)
TestCmppsSize(32, (-1.0, 1.0, 3.14, 1024.5), (-1.0, 1.0, 3.14, 1024.5),
float);
TestCmppsSize(64, (1.0, -1000.0), (1.0, -1000.0), double);
#undef TestCmpps
#undef TestCmppsOrdUnordXmmAddr
#undef TestCmppsOrdUnordXmmXmm
#undef TestCmppsXmmAddr
#undef TestCmppsXmmXmm
}
TEST_F(AssemblerX8664Test, Sqrtps_Rsqrtps_Reciprocalps_Sqrtpd) {
#define TestImplSingle(Dst, Inst, Expect) \
do { \
static constexpr char TestString[] = "(" #Dst ", " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0(1.0, 4.0, 20.0, 3.14); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(Encoded_Xmm_##Dst()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.run(); \
ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst) \
do { \
TestImplSingle(Dst, sqrtps, (uint64_t(0x400000003F800000ull), \
uint64_t(0x3FE2D10B408F1BBDull))); \
TestImplSingle(Dst, rsqrtps, (uint64_t(0x3EFFF0003F7FF000ull), \
uint64_t(0x3F1078003E64F000ull))); \
TestImplSingle(Dst, reciprocalps, (uint64_t(0x3E7FF0003F7FF000ull), \
uint64_t(0x3EA310003D4CC000ull))); \
\
TestImplSingle(Dst, sqrtpd, (uint64_t(0x4036A09E9365F5F3ull), \
uint64_t(0x401C42FAE40282A8ull))); \
} while (0)
TestImpl(xmm0);
TestImpl(xmm1);
TestImpl(xmm2);
TestImpl(xmm3);
TestImpl(xmm4);
TestImpl(xmm5);
TestImpl(xmm6);
TestImpl(xmm7);
TestImpl(xmm8);
TestImpl(xmm9);
TestImpl(xmm10);
TestImpl(xmm11);
TestImpl(xmm12);
TestImpl(xmm13);
TestImpl(xmm14);
TestImpl(xmm15);
#undef TestImpl
#undef TestImplSingle
}
TEST_F(AssemblerX8664Test, Unpck) {
const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),
uint64_t(0xCCCCCCCCDDDDDDDDull));
const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),
uint64_t(0x9999999988888888ull));
const Dqword unpcklpsExpected(uint64_t(0xFFFFFFFFBBBBBBBBull),
uint64_t(0xEEEEEEEEAAAAAAAAull));
const Dqword unpcklpdExpected(uint64_t(0xAAAAAAAABBBBBBBBull),
uint64_t(0xEEEEEEEEFFFFFFFFull));
const Dqword unpckhpsExpected(uint64_t(0x88888888DDDDDDDDull),
uint64_t(0x99999999CCCCCCCCull));
const Dqword unpckhpdExpected(uint64_t(0xCCCCCCCCDDDDDDDDull),
uint64_t(0x9999999988888888ull));
#define TestImplSingle(Dst, Src, Inst) \
do { \
static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplSingle(Dst, Src, unpcklps); \
TestImplSingle(Dst, Src, unpcklpd); \
TestImplSingle(Dst, Src, unpckhps); \
TestImplSingle(Dst, Src, unpckhpd); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm8);
TestImpl(xmm8, xmm9);
TestImpl(xmm9, xmm10);
TestImpl(xmm10, xmm11);
TestImpl(xmm11, xmm12);
TestImpl(xmm12, xmm13);
TestImpl(xmm13, xmm14);
TestImpl(xmm14, xmm15);
TestImpl(xmm15, xmm0);
#undef TestImpl
#undef TestImplSingle
}
TEST_F(AssemblerX8664Test, Shufp) {
const Dqword V0(uint64_t(0x1111111122222222ull),
uint64_t(0x5555555577777777ull));
const Dqword V1(uint64_t(0xAAAAAAAABBBBBBBBull),
uint64_t(0xCCCCCCCCDDDDDDDDull));
const uint8_t pshufdImm = 0x63;
const Dqword pshufdExpected(uint64_t(0xBBBBBBBBCCCCCCCCull),
uint64_t(0xAAAAAAAADDDDDDDDull));
const uint8_t shufpsImm = 0xf9;
const Dqword shufpsExpected(uint64_t(0x7777777711111111ull),
uint64_t(0xCCCCCCCCCCCCCCCCull));
#define TestImplSingleXmmXmm(Dst, Src, Inst) \
do { \
static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
Immediate(Inst##Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSingleXmmAddr(Dst, Inst) \
do { \
static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
Immediate(Inst##Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSingleXmmXmmUntyped(Dst, Src, Inst) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Inst ", Untyped)"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Immediate(Inst##Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Inst##UntypedExpected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplSingleXmmXmm(Dst, Src, pshufd); \
TestImplSingleXmmAddr(Dst, pshufd); \
TestImplSingleXmmXmm(Dst, Src, shufps); \
TestImplSingleXmmAddr(Dst, shufps); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm8);
TestImpl(xmm8, xmm9);
TestImpl(xmm9, xmm10);
TestImpl(xmm10, xmm11);
TestImpl(xmm11, xmm12);
TestImpl(xmm12, xmm13);
TestImpl(xmm13, xmm14);
TestImpl(xmm14, xmm15);
TestImpl(xmm15, xmm0);
#undef TestImpl
#undef TestImplSingleXmmXmmUntyped
#undef TestImplSingleXmmAddr
#undef TestImplSingleXmmXmm
}
TEST_F(AssemblerX8664Test, Punpckl) {
const Dqword V0_v4i32(uint64_t(0x1111111122222222ull),
uint64_t(0x5555555577777777ull));
const Dqword V1_v4i32(uint64_t(0xAAAAAAAABBBBBBBBull),
uint64_t(0xCCCCCCCCDDDDDDDDull));
const Dqword Expected_v4i32(uint64_t(0xBBBBBBBB22222222ull),
uint64_t(0xAAAAAAAA11111111ull));
const Dqword V0_v8i16(uint64_t(0x1111222233334444ull),
uint64_t(0x5555666677778888ull));
const Dqword V1_v8i16(uint64_t(0xAAAABBBBCCCCDDDDull),
uint64_t(0xEEEEFFFF00009999ull));
const Dqword Expected_v8i16(uint64_t(0xCCCC3333DDDD4444ull),
uint64_t(0xAAAA1111BBBB2222ull));
const Dqword V0_v16i8(uint64_t(0x1122334455667788ull),
uint64_t(0x99AABBCCDDEEFF00ull));
const Dqword V1_v16i8(uint64_t(0xFFEEDDCCBBAA9900ull),
uint64_t(0xBAADF00DFEEDFACEull));
const Dqword Expected_v16i8(uint64_t(0xBB55AA6699770088ull),
uint64_t(0xFF11EE22DD33CC44ull));
#define TestImplXmmXmm(Dst, Src, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, \
XmmRegister::Encoded_Reg_##Src); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplXmmAddr(Dst, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplXmmXmm(Dst, Src, punpckl, v4i32); \
TestImplXmmAddr(Dst, punpckl, v4i32); \
TestImplXmmXmm(Dst, Src, punpckl, v8i16); \
TestImplXmmAddr(Dst, punpckl, v8i16); \
TestImplXmmXmm(Dst, Src, punpckl, v16i8); \
TestImplXmmAddr(Dst, punpckl, v16i8); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm0);
#undef TestImpl
#undef TestImplXmmAddr
#undef TestImplXmmXmm
}
TEST_F(AssemblerX8664Test, Packss) {
const Dqword V0_v4i32(uint64_t(0x0001000000001234ull),
uint64_t(0x7FFFFFFF80000000ull));
const Dqword V1_v4i32(uint64_t(0xFFFFFFFEFFFFFFFFull),
uint64_t(0x0000800100007FFEull));
const Dqword Expected_v4i32(uint64_t(0x7FFF80007FFF1234ull),
uint64_t(0x7FFF7FFEFFFEFFFFull));
const Dqword V0_v8i16(uint64_t(0x0001000000120034ull),
uint64_t(0xFFFEFFFF7FFF8000ull));
const Dqword V1_v8i16(uint64_t(0x00057FF80081007Eull),
uint64_t(0x0088007700660055ull));
const Dqword Expected_v8i16(uint64_t(0xFEFF7F8001001234ull),
uint64_t(0x7F776655057F7F7Eull));
#define TestImplXmmXmm(Dst, Src, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, \
XmmRegister::Encoded_Reg_##Src); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplXmmAddr(Dst, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplXmmXmm(Dst, Src, packss, v4i32); \
TestImplXmmAddr(Dst, packss, v4i32); \
TestImplXmmXmm(Dst, Src, packss, v8i16); \
TestImplXmmAddr(Dst, packss, v8i16); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm0);
#undef TestImpl
#undef TestImplXmmAddr
#undef TestImplXmmXmm
}
TEST_F(AssemblerX8664Test, Packus) {
const Dqword V0_v4i32(uint64_t(0x0001000000001234ull),
uint64_t(0x7FFFFFFF80000000ull));
const Dqword V1_v4i32(uint64_t(0xFFFFFFFEFFFFFFFFull),
uint64_t(0x0000800100007FFEull));
const Dqword Expected_v4i32(uint64_t(0xFFFF0000FFFF1234ull),
uint64_t(0x80017FFE00000000ull));
const Dqword V0_v8i16(uint64_t(0x0001000000120034ull),
uint64_t(0xFFFEFFFF7FFF8000ull));
const Dqword V1_v8i16(uint64_t(0x00057FF80081007Eull),
uint64_t(0x0088007700660055ull));
const Dqword Expected_v8i16(uint64_t(0x0000FF0001001234ull),
uint64_t(0x8877665505FF817Eull));
#define TestImplXmmXmm(Dst, Src, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, \
XmmRegister::Encoded_Reg_##Src); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplXmmAddr(Dst, Inst, Ty) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, " #Inst ", " #Ty ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ Inst(IceType_##Ty, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0_##Ty); \
test.setDqwordTo(T1, V1_##Ty); \
test.run(); \
\
ASSERT_EQ(Expected_##Ty, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplXmmXmm(Dst, Src, packus, v4i32); \
TestImplXmmAddr(Dst, packus, v4i32); \
TestImplXmmXmm(Dst, Src, packus, v8i16); \
TestImplXmmAddr(Dst, packus, v8i16); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm0);
#undef TestImpl
#undef TestImplXmmAddr
#undef TestImplXmmXmm
}
TEST_F(AssemblerX8664Test, Pshufb) {
const Dqword V0(uint64_t(0x1122334455667788ull),
uint64_t(0x99aabbccddeeff32ull));
const Dqword V1(uint64_t(0x0204050380060708ull),
uint64_t(0x010306080a8b0c0dull));
const Dqword Expected(uint64_t(0x6644335500221132ull),
uint64_t(0x77552232ee00ccbbull));
#define TestImplXmmXmm(Dst, Src, Inst) \
do { \
static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
__ Inst(IceType_void, XmmRegister::Encoded_Reg_##Dst, \
XmmRegister::Encoded_Reg_##Src); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplXmmAddr(Dst, Inst) \
do { \
static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
__ Inst(IceType_void, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplXmmXmm(Dst, Src, pshufb); \
TestImplXmmAddr(Dst, pshufb); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm8);
TestImpl(xmm8, xmm9);
TestImpl(xmm9, xmm10);
TestImpl(xmm10, xmm11);
TestImpl(xmm11, xmm12);
TestImpl(xmm12, xmm13);
TestImpl(xmm13, xmm14);
TestImpl(xmm14, xmm15);
TestImpl(xmm15, xmm0);
#undef TestImpl
#undef TestImplXmmAddr
#undef TestImplXmmXmm
}
TEST_F(AssemblerX8664Test, Cvt) {
const Dqword dq2ps32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
const Dqword dq2ps32SrcValue(-5, 3, 100, 200);
const Dqword dq2ps32Expected(-5.0f, 3.0f, 100.0, 200.0);
const Dqword dq2ps64DstValue(0.0f, 0.0f, -1.0f, -1.0f);
const Dqword dq2ps64SrcValue(-5, 3, 100, 200);
const Dqword dq2ps64Expected(-5.0f, 3.0f, 100.0, 200.0);
const Dqword tps2dq32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
const Dqword tps2dq32SrcValue(-5.0f, 3.0f, 100.0, 200.0);
const Dqword tps2dq32Expected(-5, 3, 100, 200);
const Dqword tps2dq64DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
const Dqword tps2dq64SrcValue(-5.0f, 3.0f, 100.0, 200.0);
const Dqword tps2dq64Expected(-5, 3, 100, 200);
const Dqword si2ss32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
const int32_t si2ss32SrcValue = 5;
const Dqword si2ss32Expected(5.0f, -1.0f, -1.0f, -1.0f);
const Dqword si2ss64DstValue(-1.0, -1.0);
const int32_t si2ss64SrcValue = 5;
const Dqword si2ss64Expected(5.0, -1.0);
const int32_t tss2si32DstValue = 0xF00F0FF0;
const Dqword tss2si32SrcValue(-5.0f, -1.0f, -1.0f, -1.0f);
const int32_t tss2si32Expected = -5;
const int32_t tss2si64DstValue = 0xF00F0FF0;
const Dqword tss2si64SrcValue(-5.0, -1.0);
const int32_t tss2si64Expected = -5;
const Dqword float2float32DstValue(-1.0, -1.0);
const Dqword float2float32SrcValue(-5.0, 3, 100, 200);
const Dqword float2float32Expected(-5.0, -1.0);
const Dqword float2float64DstValue(-1.0, -1.0, -1.0, -1.0);
const Dqword float2float64SrcValue(-5.0, 3.0);
const Dqword float2float64Expected(-5.0, -1.0, -1.0, -1.0);
#define TestImplPXmmXmm(Dst, Src, Inst, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", cvt" #Inst ", f" #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##DstValue); \
test.setDqwordTo(T1, Inst##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSXmmReg(Dst, GPR, Inst, Size, IntType) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #GPR ", cvt" #Inst ", " #IntType ", f" #Size ")"; \
const uint32_t T0 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##SrcValue)); \
__ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), IntType, \
Encoded_GPR_##GPR()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##DstValue); \
test.run(); \
\
ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSRegXmm(GPR, Src, Inst, IntSize, Size) \
do { \
static constexpr char TestString[] = \
"(" #GPR ", " #Src ", cvt" #Inst ", " #IntSize ", f" #Size ")"; \
const uint32_t T0 = allocateDqword(); \
\
__ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
__ cvt##Inst(IceType_i##IntSize, Encoded_GPR_##GPR(), IceType_f##Size, \
Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(static_cast<uint##IntSize##_t>(Inst##Size##Expected), \
test.GPR()) \
<< TestString; \
reset(); \
} while (0)
#define TestImplPXmmAddr(Dst, Inst, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##DstValue); \
test.setDqwordTo(T1, Inst##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSXmmAddr(Dst, Inst, Size, IntType) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, cvt" #Inst ", f" #Size ", " #IntType ")"; \
const uint32_t T0 = allocateDqword(); \
const uint32_t T1 = allocateDword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), IntType, \
dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##DstValue); \
test.setDwordTo(T1, Inst##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestImplSRegAddr(GPR, Inst, IntSize, Size) \
do { \
static constexpr char TestString[] = \
"(" #GPR ", Addr, cvt" #Inst ", f" #Size ", " #IntSize ")"; \
const uint32_t T0 = allocateDqword(); \
\
__ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
__ cvt##Inst(IceType_i##IntSize, Encoded_GPR_##GPR(), IceType_f##Size, \
dwordAddress(T0)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, Inst##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(static_cast<uint##IntSize##_t>(Inst##Size##Expected), \
test.GPR()) \
<< TestString; \
reset(); \
} while (0)
#define TestImplSize(Dst, Src, GPR, Size) \
do { \
TestImplPXmmXmm(Dst, Src, dq2ps, Size); \
TestImplPXmmAddr(Src, dq2ps, Size); \
TestImplPXmmXmm(Dst, Src, tps2dq, Size); \
TestImplPXmmAddr(Src, tps2dq, Size); \
TestImplSXmmReg(Dst, GPR, si2ss, Size, IceType_i32); \
TestImplSXmmReg(Dst, GPR, si2ss, Size, IceType_i64); \
TestImplSXmmAddr(Dst, si2ss, Size, IceType_i32); \
TestImplSXmmAddr(Dst, si2ss, Size, IceType_i64); \
TestImplSRegXmm(GPR, Src, tss2si, 32, Size); \
TestImplSRegXmm(GPR, Src, tss2si, 64, Size); \
TestImplSRegAddr(GPR, tss2si, 32, Size); \
TestImplSRegAddr(GPR, tss2si, 64, Size); \
TestImplPXmmXmm(Dst, Src, float2float, Size); \
TestImplPXmmAddr(Src, float2float, Size); \
} while (0)
#define TestImpl(Dst, Src, GPR) \
do { \
TestImplSize(Dst, Src, GPR, 32); \
TestImplSize(Dst, Src, GPR, 64); \
} while (0)
TestImpl(xmm0, xmm1, r1);
TestImpl(xmm1, xmm2, r2);
TestImpl(xmm2, xmm3, r3);
TestImpl(xmm3, xmm4, r4);
TestImpl(xmm4, xmm5, r5);
TestImpl(xmm5, xmm6, r6);
TestImpl(xmm6, xmm7, r7);
TestImpl(xmm7, xmm8, r8);
TestImpl(xmm8, xmm9, r10);
TestImpl(xmm9, xmm10, r11);
TestImpl(xmm10, xmm11, r12);
TestImpl(xmm11, xmm12, r13);
TestImpl(xmm12, xmm13, r14);
TestImpl(xmm13, xmm14, r15);
TestImpl(xmm14, xmm15, r1);
TestImpl(xmm15, xmm0, r2);
#undef TestImpl
#undef TestImplSize
#undef TestImplSRegAddr
#undef TestImplSXmmAddr
#undef TestImplPXmmAddr
#undef TestImplSRegXmm
#undef TestImplSXmmReg
#undef TestImplPXmmXmm
}
TEST_F(AssemblerX8664Test, Ucomiss) {
static constexpr float qnan32 = std::numeric_limits<float>::quiet_NaN();
static constexpr double qnan64 = std::numeric_limits<float>::quiet_NaN();
Dqword test32DstValue(0.0, qnan32, qnan32, qnan32);
Dqword test32SrcValue(0.0, qnan32, qnan32, qnan32);
Dqword test64DstValue(0.0, qnan64);
Dqword test64SrcValue(0.0, qnan64);
#define TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, \
BOther) \
do { \
static constexpr char NearBranch = AssemblerX8664::kNearJump; \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #CompType \
", " #BParity ", " #BOther ")"; \
const uint32_t T0 = allocateDqword(); \
test##Size##DstValue.F##Size[0] = Value0; \
const uint32_t T1 = allocateDqword(); \
test##Size##SrcValue.F##Size[0] = Value1; \
const uint32_t ImmIfTrue = 0xBEEF; \
const uint32_t ImmIfFalse = 0xC0FFE; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
__ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
Label Done; \
__ j(Cond::Br_##BParity, &Done, NearBranch); \
__ j(Cond::Br_##BOther, &Done, NearBranch); \
__ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
__ bind(&Done); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, test##Size##DstValue); \
test.setDqwordTo(T1, test##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
reset(); \
} while (0)
#define TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther) \
do { \
static constexpr char NearBranch = AssemblerX8664::kNearJump; \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #CompType \
", " #BParity ", " #BOther ")"; \
const uint32_t T0 = allocateDqword(); \
test##Size##DstValue.F##Size[0] = Value0; \
const uint32_t T1 = allocateDqword(); \
test##Size##SrcValue.F##Size[0] = Value1; \
const uint32_t ImmIfTrue = 0xBEEF; \
const uint32_t ImmIfFalse = 0xC0FFE; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
__ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
Label Done; \
__ j(Cond::Br_##BParity, &Done, NearBranch); \
__ j(Cond::Br_##BOther, &Done, NearBranch); \
__ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
__ bind(&Done); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, test##Size##DstValue); \
test.setDqwordTo(T1, test##Size##SrcValue); \
test.run(); \
\
ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
reset(); \
} while (0)
#define TestImplCond(Dst, Value0, Src, Value1, Size, CompType, BParity, \
BOther) \
do { \
TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, BOther); \
TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther); \
} while (0)
#define TestImplSize(Dst, Src, Size) \
do { \
TestImplCond(Dst, 1.0, Src, 1.0, Size, isEq, p, ne); \
TestImplCond(Dst, 1.0, Src, 2.0, Size, isNe, p, e); \
TestImplCond(Dst, 1.0, Src, 2.0, Size, isLe, p, a); \
TestImplCond(Dst, 1.0, Src, 1.0, Size, isLe, p, a); \
TestImplCond(Dst, 1.0, Src, 2.0, Size, isLt, p, ae); \
TestImplCond(Dst, 2.0, Src, 1.0, Size, isGe, p, b); \
TestImplCond(Dst, 1.0, Src, 1.0, Size, isGe, p, b); \
TestImplCond(Dst, 2.0, Src, 1.0, Size, isGt, p, be); \
TestImplCond(Dst, qnan##Size, Src, 1.0, Size, isUnord, np, o); \
TestImplCond(Dst, 1.0, Src, qnan##Size, Size, isUnord, np, s); \
TestImplCond(Dst, qnan##Size, Src, qnan##Size, Size, isUnord, np, s); \
} while (0)
#define TestImpl(Dst, Src) \
do { \
TestImplSize(Dst, Src, 32); \
TestImplSize(Dst, Src, 64); \
} while (0)
TestImpl(xmm0, xmm1);
TestImpl(xmm1, xmm2);
TestImpl(xmm2, xmm3);
TestImpl(xmm3, xmm4);
TestImpl(xmm4, xmm5);
TestImpl(xmm5, xmm6);
TestImpl(xmm6, xmm7);
TestImpl(xmm7, xmm8);
TestImpl(xmm8, xmm9);
TestImpl(xmm9, xmm10);
TestImpl(xmm10, xmm11);
TestImpl(xmm11, xmm12);
TestImpl(xmm12, xmm13);
TestImpl(xmm13, xmm14);
TestImpl(xmm14, xmm15);
TestImpl(xmm15, xmm0);
#undef TestImpl
#undef TestImplSize
#undef TestImplCond
#undef TestImplXmmAddr
#undef TestImplXmmXmm
}
TEST_F(AssemblerX8664Test, Sqrtss) {
Dqword test32SrcValue(-100.0, -100.0, -100.0, -100.0);
Dqword test32DstValue(-1.0, -1.0, -1.0, -1.0);
Dqword test64SrcValue(-100.0, -100.0);
Dqword test64DstValue(-1.0, -1.0);
#define TestSqrtssXmmXmm(Dst, Src, Value1, Result, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Value1 ", " #Result ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
test##Size##SrcValue.F##Size[0] = Value1; \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
__ sqrt(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, test##Size##SrcValue); \
test.setDqwordTo(T1, test##Size##DstValue); \
test.run(); \
\
Dqword Expected = test##Size##DstValue; \
Expected.F##Size[0] = Result; \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestSqrtssXmmAddr(Dst, Value1, Result, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", Addr, " #Value1 ", " #Result ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
test##Size##SrcValue.F##Size[0] = Value1; \
const uint32_t T1 = allocateDqword(); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
__ sqrt(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, test##Size##SrcValue); \
test.setDqwordTo(T1, test##Size##DstValue); \
test.run(); \
\
Dqword Expected = test##Size##DstValue; \
Expected.F##Size[0] = Result; \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestSqrtssSize(Dst, Src, Size) \
do { \
TestSqrtssXmmXmm(Dst, Src, 4.0, 2.0, Size); \
TestSqrtssXmmAddr(Dst, 4.0, 2.0, Size); \
TestSqrtssXmmXmm(Dst, Src, 9.0, 3.0, Size); \
TestSqrtssXmmAddr(Dst, 9.0, 3.0, Size); \
TestSqrtssXmmXmm(Dst, Src, 100.0, 10.0, Size); \
TestSqrtssXmmAddr(Dst, 100.0, 10.0, Size); \
} while (0)
#define TestSqrtss(Dst, Src) \
do { \
TestSqrtssSize(Dst, Src, 32); \
TestSqrtssSize(Dst, Src, 64); \
} while (0)
TestSqrtss(xmm0, xmm1);
TestSqrtss(xmm1, xmm2);
TestSqrtss(xmm2, xmm3);
TestSqrtss(xmm3, xmm4);
TestSqrtss(xmm4, xmm5);
TestSqrtss(xmm5, xmm6);
TestSqrtss(xmm6, xmm7);
TestSqrtss(xmm7, xmm8);
TestSqrtss(xmm8, xmm9);
TestSqrtss(xmm9, xmm10);
TestSqrtss(xmm10, xmm11);
TestSqrtss(xmm11, xmm12);
TestSqrtss(xmm12, xmm13);
TestSqrtss(xmm13, xmm14);
TestSqrtss(xmm14, xmm15);
TestSqrtss(xmm15, xmm0);
#undef TestSqrtss
#undef TestSqrtssSize
#undef TestSqrtssXmmAddr
#undef TestSqrtssXmmXmm
}
TEST_F(AssemblerX8664Test, Insertps) {
#define TestInsertpsXmmXmmImm(Dst, Value0, Src, Value1, Imm, Expected) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Imm ", " #Expected \
")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestInsertpsXmmAddrImm(Dst, Value0, Value1, Imm, Expected) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Expected ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestInsertps(Dst, Src) \
do { \
TestInsertpsXmmXmmImm( \
Dst, (uint64_t(-1), uint64_t(-1)), Src, \
(uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
0x99, \
(uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
TestInsertpsXmmAddrImm( \
Dst, (uint64_t(-1), uint64_t(-1)), \
(uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
0x99, \
(uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
TestInsertpsXmmXmmImm( \
Dst, (uint64_t(-1), uint64_t(-1)), Src, \
(uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
0x9D, \
(uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x0000000000000000ull))); \
TestInsertpsXmmAddrImm( \
Dst, (uint64_t(-1), uint64_t(-1)), \
(uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
0x9D, \
(uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x0000000000000000ull))); \
} while (0)
TestInsertps(xmm0, xmm1);
TestInsertps(xmm1, xmm2);
TestInsertps(xmm2, xmm3);
TestInsertps(xmm3, xmm4);
TestInsertps(xmm4, xmm5);
TestInsertps(xmm5, xmm6);
TestInsertps(xmm6, xmm7);
TestInsertps(xmm7, xmm8);
TestInsertps(xmm8, xmm9);
TestInsertps(xmm9, xmm10);
TestInsertps(xmm10, xmm11);
TestInsertps(xmm11, xmm12);
TestInsertps(xmm12, xmm13);
TestInsertps(xmm13, xmm14);
TestInsertps(xmm14, xmm15);
TestInsertps(xmm15, xmm0);
#undef TestInsertps
#undef TestInsertpsXmmXmmAddr
#undef TestInsertpsXmmXmmImm
}
TEST_F(AssemblerX8664Test, Pinsr) {
static constexpr uint8_t Mask32 = 0x03;
static constexpr uint8_t Mask16 = 0x07;
static constexpr uint8_t Mask8 = 0x0F;
#define TestPinsrXmmGPRImm(Dst, Value0, GPR, Value1, Imm, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #GPR ", " #Value1 ", " #Imm ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Value1)); \
__ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_GPR_##GPR(), \
Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.run(); \
\
constexpr uint8_t sel = (Imm)&Mask##Size; \
Dqword Expected = V0; \
Expected.U##Size[sel] = Value1; \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestPinsrXmmAddrImm(Dst, Value0, Value1, Imm, Size) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDword(); \
const uint32_t V1 = Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1), \
Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDwordTo(T1, V1); \
test.run(); \
\
constexpr uint8_t sel = (Imm)&Mask##Size; \
Dqword Expected = V0; \
Expected.U##Size[sel] = Value1; \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestPinsrSize(Dst, GPR, Value1, Imm, Size) \
do { \
TestPinsrXmmGPRImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
uint64_t(0xFFFFFFFFDDDDDDDDull)), \
GPR, Value1, Imm, Size); \
TestPinsrXmmAddrImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
uint64_t(0xFFFFFFFFDDDDDDDDull)), \
Value1, Imm, Size); \
} while (0)
#define TestPinsr(Src, Dst) \
do { \
TestPinsrSize(Src, Dst, 0xEE, 0x03, 8); \
TestPinsrSize(Src, Dst, 0xFFEE, 0x03, 16); \
TestPinsrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
} while (0)
TestPinsr(xmm0, r1);
TestPinsr(xmm1, r2);
TestPinsr(xmm2, r3);
TestPinsr(xmm3, r4);
TestPinsr(xmm4, r5);
TestPinsr(xmm5, r6);
TestPinsr(xmm6, r7);
TestPinsr(xmm7, r8);
TestPinsr(xmm8, r10);
TestPinsr(xmm9, r11);
TestPinsr(xmm10, r12);
TestPinsr(xmm11, r13);
TestPinsr(xmm12, r14);
TestPinsr(xmm13, r15);
TestPinsr(xmm14, r1);
TestPinsr(xmm15, r2);
#undef TestPinsr
#undef TestPinsrSize
#undef TestPinsrXmmAddrImm
#undef TestPinsrXmmGPRImm
}
TEST_F(AssemblerX8664Test, Pextr) {
static constexpr uint8_t Mask32 = 0x03;
static constexpr uint8_t Mask16 = 0x07;
static constexpr uint8_t Mask8 = 0x0F;
#define TestPextrGPRXmmImm(GPR, Src, Value1, Imm, Size) \
do { \
static constexpr char TestString[] = \
"(" #GPR ", " #Src ", " #Value1 ", " #Imm ", " #Size ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value1; \
\
__ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
__ pextr(IceType_i##Size, Encoded_GPR_##GPR(), Encoded_Xmm_##Src(), \
Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.run(); \
\
constexpr uint8_t sel = (Imm)&Mask##Size; \
ASSERT_EQ(V0.U##Size[sel], test.GPR()) << TestString; \
reset(); \
} while (0)
#define TestPextrSize(GPR, Src, Value1, Imm, Size) \
do { \
TestPextrGPRXmmImm(GPR, Src, (uint64_t(0xAAAAAAAABBBBBBBBull), \
uint64_t(0xFFFFFFFFDDDDDDDDull)), \
Imm, Size); \
} while (0)
#define TestPextr(Src, Dst) \
do { \
TestPextrSize(Src, Dst, 0xEE, 0x03, 8); \
TestPextrSize(Src, Dst, 0xFFEE, 0x03, 16); \
TestPextrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
} while (0)
TestPextr(r1, xmm0);
TestPextr(r2, xmm1);
TestPextr(r3, xmm2);
TestPextr(r4, xmm3);
TestPextr(r5, xmm4);
TestPextr(r6, xmm5);
TestPextr(r7, xmm6);
TestPextr(r8, xmm7);
TestPextr(r10, xmm8);
TestPextr(r11, xmm9);
TestPextr(r12, xmm10);
TestPextr(r13, xmm11);
TestPextr(r14, xmm12);
TestPextr(r15, xmm13);
TestPextr(r1, xmm14);
TestPextr(r2, xmm15);
#undef TestPextr
#undef TestPextrSize
#undef TestPextrXmmGPRImm
}
TEST_F(AssemblerX8664Test, Pcmpeq_Pcmpgt) {
#define TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, Inst, Op) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #Op ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
Dqword Expected(uint64_t(0), uint64_t(0)); \
static constexpr uint8_t ArraySize = \
sizeof(Dqword) / sizeof(uint##Size##_t); \
for (uint8_t i = 0; i < ArraySize; ++i) { \
Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
} \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestPcmpXmmAddr(Dst, Value0, Value1, Size, Inst, Op) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #Op ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0 Value0; \
const uint32_t T1 = allocateDqword(); \
const Dqword V1 Value1; \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
Dqword Expected(uint64_t(0), uint64_t(0)); \
static constexpr uint8_t ArraySize = \
sizeof(Dqword) / sizeof(uint##Size##_t); \
for (uint8_t i = 0; i < ArraySize; ++i) { \
Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
} \
ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestPcmpValues(Dst, Value0, Src, Value1, Size) \
do { \
TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpeq, == ); \
TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpeq, == ); \
TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpgt, < ); \
TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpgt, < ); \
} while (0)
#define TestPcmpSize(Dst, Src, Size) \
do { \
TestPcmpValues(Dst, (uint64_t(0x8888888888888888ull), \
uint64_t(0x0000000000000000ull)), \
Src, (uint64_t(0x0000008800008800ull), \
uint64_t(0xFFFFFFFFFFFFFFFFull)), \
Size); \
TestPcmpValues(Dst, (uint64_t(0x123567ABAB55DE01ull), \
uint64_t(0x12345abcde12345Aull)), \
Src, (uint64_t(0x0000008800008800ull), \
uint64_t(0xAABBCCDD1234321Aull)), \
Size); \
} while (0)
#define TestPcmp(Dst, Src) \
do { \
TestPcmpSize(xmm0, xmm1, 8); \
TestPcmpSize(xmm0, xmm1, 16); \
TestPcmpSize(xmm0, xmm1, 32); \
} while (0)
TestPcmp(xmm0, xmm1);
TestPcmp(xmm1, xmm2);
TestPcmp(xmm2, xmm3);
TestPcmp(xmm3, xmm4);
TestPcmp(xmm4, xmm5);
TestPcmp(xmm5, xmm6);
TestPcmp(xmm6, xmm7);
TestPcmp(xmm7, xmm8);
TestPcmp(xmm8, xmm9);
TestPcmp(xmm9, xmm10);
TestPcmp(xmm10, xmm11);
TestPcmp(xmm11, xmm12);
TestPcmp(xmm12, xmm13);
TestPcmp(xmm13, xmm14);
TestPcmp(xmm14, xmm15);
TestPcmp(xmm15, xmm0);
#undef TestPcmp
#undef TestPcmpSize
#undef TestPcmpValues
#undef TestPcmpXmmAddr
#undef TestPcmpXmmXmm
}
TEST_F(AssemblerX8664Test, Roundsd) {
#define TestRoundsdXmmXmm(Dst, Src, Mode, Input, RN) \
do { \
static constexpr char TestString[] = \
"(" #Dst ", " #Src ", " #Mode ", " #Input ", " #RN ")"; \
const uint32_t T0 = allocateDqword(); \
const Dqword V0(-3.0, -3.0); \
const uint32_t T1 = allocateDqword(); \
const Dqword V1(double(Input), -123.4); \
\
__ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
__ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
__ round(IceType_f64, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
Immediate(AssemblerX8664::k##Mode)); \
\
AssembledTest test = assemble(); \
test.setDqwordTo(T0, V0); \
test.setDqwordTo(T1, V1); \
test.run(); \
\
const Dqword Expected(double(RN), -3.0); \
EXPECT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
reset(); \
} while (0)
#define TestRoundsd(Dst, Src) \
do { \
TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.51, 6); \
TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.49, 5); \
TestRoundsdXmmXmm(Dst, Src, RoundDown, 5.51, 5); \
TestRoundsdXmmXmm(Dst, Src, RoundUp, 5.49, 6); \
TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.49, 5); \
TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.51, 5); \
} while (0)
TestRoundsd(xmm0, xmm1);
TestRoundsd(xmm1, xmm2);
TestRoundsd(xmm2, xmm3);
TestRoundsd(xmm3, xmm4);
TestRoundsd(xmm4, xmm5);
TestRoundsd(xmm5, xmm6);
TestRoundsd(xmm6, xmm7);
TestRoundsd(xmm7, xmm8);
TestRoundsd(xmm8, xmm9);
TestRoundsd(xmm9, xmm10);
TestRoundsd(xmm10, xmm11);
TestRoundsd(xmm11, xmm12);
TestRoundsd(xmm12, xmm13);
TestRoundsd(xmm13, xmm14);
TestRoundsd(xmm14, xmm15);
TestRoundsd(xmm15, xmm0);
#undef TestRoundsd
#undef TestRoundsdXmmXmm
}
TEST_F(AssemblerX8664Test, Set1ps) {
#define TestImpl(Xmm, Src, Imm) \
do { \
__ set1ps(Encoded_Xmm_##Xmm(), Encoded_GPR_##Src(), Immediate(Imm)); \
\
AssembledTest test = assemble(); \
test.run(); \
\
const Dqword Expected((uint64_t(Imm) << 32) | uint32_t(Imm), \
(uint64_t(Imm) << 32) | uint32_t(Imm)); \
ASSERT_EQ(Expected, test.Xmm<Dqword>()) \
<< "(" #Xmm ", " #Src ", " #Imm ")"; \
reset(); \
} while (0)
TestImpl(xmm0, r1, 1);
TestImpl(xmm1, r2, 12);
TestImpl(xmm2, r3, 22);
TestImpl(xmm3, r4, 54);
TestImpl(xmm4, r5, 80);
TestImpl(xmm5, r6, 32);
TestImpl(xmm6, r7, 55);
TestImpl(xmm7, r8, 44);
TestImpl(xmm8, r10, 10);
TestImpl(xmm9, r11, 155);
TestImpl(xmm10, r12, 165);
TestImpl(xmm11, r13, 170);
TestImpl(xmm12, r14, 200);
TestImpl(xmm13, r15, 124);
TestImpl(xmm14, r1, 101);
TestImpl(xmm15, r2, 166);
#undef TestImpl
}
} // end of anonymous namespace
} // end of namespace Test
} // end of namespace X8664
} // end of namespace Ice