Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: unittest/AssemblerX8632/XmmArith.cpp

Issue 1224173006: Adds the x86-64 assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments; make format Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « unittest/AssemblerX8632/X87.cpp ('k') | unittest/AssemblerX8664/ControlFlow.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: unittest/AssemblerX8632/XmmArith.cpp
diff --git a/unittest/AssemblerX8632/XmmArith.cpp b/unittest/AssemblerX8632/XmmArith.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..45ff3a97a1474a3d739201ad18631abf5a62849c
--- /dev/null
+++ b/unittest/AssemblerX8632/XmmArith.cpp
@@ -0,0 +1,1816 @@
+//===- subzero/unittest/AssemblerX8632/XmmArith.cpp -----------------------===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "AssemblerX8632/TestUtil.h"
+
+namespace Ice {
+namespace X8632 {
+namespace Test {
+namespace {
+
+TEST_F(AssemblerX8632Test, 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, XmmRegister::Encoded_Reg_##Dst, \
+ dwordAddress(T0)); \
+ __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Src, \
+ dwordAddress(T1)); \
+ __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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, XmmRegister::Encoded_Reg_##Dst, \
+ dwordAddress(T0)); \
+ __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##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)
+
+ TestArithSS(32, xmm0, xmm1, xmm2);
+ TestArithSS(32, xmm1, xmm2, xmm3);
+ TestArithSS(32, xmm2, xmm3, xmm4);
+ TestArithSS(32, xmm3, xmm4, xmm5);
+ TestArithSS(32, xmm4, xmm5, xmm6);
+ TestArithSS(32, xmm5, xmm6, xmm7);
+ TestArithSS(32, xmm6, xmm7, xmm0);
+ TestArithSS(32, xmm7, xmm0, xmm1);
+
+ TestArithSS(64, xmm0, xmm1, xmm2);
+ TestArithSS(64, xmm1, xmm2, xmm3);
+ TestArithSS(64, xmm2, xmm3, xmm4);
+ TestArithSS(64, xmm3, xmm4, xmm5);
+ TestArithSS(64, xmm4, xmm5, xmm6);
+ TestArithSS(64, xmm5, xmm6, xmm7);
+ TestArithSS(64, xmm6, xmm7, xmm0);
+ TestArithSS(64, xmm7, xmm0, xmm1);
+
+#undef TestArithSS
+#undef TestArithSSXmmAddr
+#undef TestArithSSXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestPArith
+#undef TestPArithSize
+#undef TestPAndnXmmAddr
+#undef TestPAndnXmmXmm
+#undef TestPArithXmmImm
+#undef TestPArithXmmAddr
+#undef TestPArithXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, ArithPS) {
+#define TestArithPSXmmXmm(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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(XmmRegister::Encoded_Reg_##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(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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##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(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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##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(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), addps, +, float); \
+ TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), addps, +, float); \
+ TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), subps, -, float); \
+ TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), subps, -, float); \
+ TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
+ TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
+ TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), divps, /, float); \
+ TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), divps, /, float); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), andps, &, float); \
+ TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), andps, &, float); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), andpd, &, \
+ double); \
+ TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), andpd, &, \
+ double); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), orps, |, float); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), orpd, |, \
+ double); \
+ TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), minps, float); \
+ TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), maxps, float); \
+ TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), minpd, double); \
+ TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxpd, double); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
+ (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
+ TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
+ (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
+ TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorpd, ^, \
+ double); \
+ TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), xorpd, ^, \
+ double); \
+ } while (0)
+
+#if 0
+
+#endif
+
+ TestArithPS(xmm0, xmm1);
+ TestArithPS(xmm1, xmm2);
+ TestArithPS(xmm2, xmm3);
+ TestArithPS(xmm3, xmm4);
+ TestArithPS(xmm4, xmm5);
+ TestArithPS(xmm5, xmm6);
+ TestArithPS(xmm6, xmm7);
+ TestArithPS(xmm7, xmm0);
+
+#undef TestArithPs
+#undef TestMinMaxPS
+#undef TestArithPSXmmXmmUntyped
+#undef TestArithPSXmmAddr
+#undef TestArithPSXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##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, xmm1);
+
+#undef TestBlending
+#undef TestBlendingXmmAddr
+#undef TestBlendingXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, Cmpps) {
+#define TestCmppsXmmXmm(Dst, Src, C, Op) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Src ", " #Dst ", " #C ", " #Op ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
+ const uint32_t T1 = allocateDqword(); \
+ const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
+ \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
+ Cond::Cmpps_##C); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, V0); \
+ test.setDqwordTo(T1, V1); \
+ test.run(); \
+ \
+ ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
+ ; \
+ reset(); \
+ } while (0)
+
+#define TestCmppsXmmAddr(Dst, C, Op) \
+ do { \
+ static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
+ const uint32_t T1 = allocateDqword(); \
+ const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
+ \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \
+ Cond::Cmpps_##C); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, V0); \
+ test.setDqwordTo(T1, V1); \
+ test.run(); \
+ \
+ ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
+ ; \
+ reset(); \
+ } while (0)
+
+#define TestCmppsOrdUnordXmmXmm(Dst, Src, C) \
+ 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
+ Cond::Cmpps_##C); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, V0); \
+ test.setDqwordTo(T1, V1); \
+ test.run(); \
+ \
+ ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
+ ; \
+ reset(); \
+ } while (0)
+
+#define TestCmppsOrdUnordXmmAddr(Dst, C) \
+ 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \
+ Cond::Cmpps_##C); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, V0); \
+ test.setDqwordTo(T1, V1); \
+ test.run(); \
+ \
+ ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
+ ; \
+ reset(); \
+ } while (0)
+
+#define TestCmpps(Dst, Src) \
+ do { \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
+ TestCmppsOrdUnordXmmAddr(Dst, unord); \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsXmmXmm(Dst, Src, eq, == ); \
+ TestCmppsXmmAddr(Dst, eq, == ); \
+ TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
+ TestCmppsOrdUnordXmmAddr(Dst, unord); \
+ } while (0)
+
+ TestCmpps(xmm0, xmm1);
+ TestCmpps(xmm1, xmm2);
+ TestCmpps(xmm2, xmm3);
+ TestCmpps(xmm3, xmm4);
+ TestCmpps(xmm4, xmm5);
+ TestCmpps(xmm5, xmm6);
+ TestCmpps(xmm6, xmm7);
+ TestCmpps(xmm7, xmm0);
+
+#undef TestCmpps
+#undef TestCmppsOrdUnordXmmAddr
+#undef TestCmppsOrdUnordXmmXmm
+#undef TestCmppsXmmAddr
+#undef TestCmppsXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(XmmRegister::Encoded_Reg_##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);
+
+#undef TestImpl
+#undef TestImplSingle
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestImpl
+#undef TestImplSingle
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestImpl
+#undef TestImplSingleXmmXmmUntyped
+#undef TestImplSingleXmmAddr
+#undef TestImplSingleXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Dst ", " #GPR ", cvt" #Inst ", f" #Size ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
+ Immediate(Inst##Size##SrcValue)); \
+ __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
+ GPRRegister::Encoded_Reg_##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, Size) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #GPR ", " #Src ", cvt" #Inst ", f" #Size ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
+ Immediate(Inst##Size##DstValue)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
+ __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \
+ XmmRegister::Encoded_Reg_##Src); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, Inst##Size##SrcValue); \
+ test.run(); \
+ \
+ ASSERT_EQ(static_cast<uint32_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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##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) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ const uint32_t T1 = allocateDword(); \
+ \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
+ 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, Size) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #GPR ", Addr, cvt" #Inst ", f" #Size ")"; \
+ const uint32_t T0 = allocateDqword(); \
+ \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
+ Immediate(Inst##Size##DstValue)); \
+ __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \
+ dwordAddress(T0)); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDqwordTo(T0, Inst##Size##SrcValue); \
+ test.run(); \
+ \
+ ASSERT_EQ(static_cast<uint32_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); \
+ TestImplSXmmAddr(Dst, si2ss, Size); \
+ TestImplSRegXmm(GPR, Src, tss2si, Size); \
+ TestImplSRegAddr(GPR, tss2si, 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, eax);
+ TestImpl(xmm1, xmm2, ebx);
+ TestImpl(xmm2, xmm3, ecx);
+ TestImpl(xmm3, xmm4, edx);
+ TestImpl(xmm4, xmm5, esi);
+ TestImpl(xmm5, xmm6, edi);
+ TestImpl(xmm6, xmm7, eax);
+ TestImpl(xmm7, xmm0, ebx);
+
+#undef TestImpl
+#undef TestImplSize
+#undef TestImplSRegAddr
+#undef TestImplSXmmAddr
+#undef TestImplPXmmAddr
+#undef TestImplSRegXmm
+#undef TestImplSXmmReg
+#undef TestImplPXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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 = AssemblerX8632::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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
+ __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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 = AssemblerX8632::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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
+ __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestImpl
+#undef TestImplSize
+#undef TestImplCond
+#undef TestImplXmmAddr
+#undef TestImplXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
+ __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
+ __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestSqrtss
+#undef TestSqrtssSize
+#undef TestSqrtssXmmAddr
+#undef TestSqrtssXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestInsertps
+#undef TestInsertpsXmmXmmAddr
+#undef TestInsertpsXmmXmmImm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, Immediate(Value1)); \
+ __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
+ GPRRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##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, eax);
+ TestPinsr(xmm1, ebx);
+ TestPinsr(xmm2, ecx);
+ TestPinsr(xmm3, edx);
+ TestPinsr(xmm4, esi);
+ TestPinsr(xmm5, edi);
+ TestPinsr(xmm6, eax);
+ TestPinsr(xmm7, ebx);
+
+#undef TestPinsr
+#undef TestPinsrSize
+#undef TestPinsrXmmAddrImm
+#undef TestPinsrXmmGPRImm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
+ __ pextr(IceType_i##Size, GPRRegister::Encoded_Reg_##GPR, \
+ XmmRegister::Encoded_Reg_##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(eax, xmm0);
+ TestPextr(ebx, xmm1);
+ TestPextr(ecx, xmm2);
+ TestPextr(edx, xmm3);
+ TestPextr(esi, xmm4);
+ TestPextr(edi, xmm5);
+ TestPextr(eax, xmm6);
+ TestPextr(ebx, xmm7);
+
+#undef TestPextr
+#undef TestPextrSize
+#undef TestPextrXmmGPRImm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
+ XmmRegister::Encoded_Reg_##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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##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, xmm0);
+
+#undef TestPcmp
+#undef TestPcmpSize
+#undef TestPcmpValues
+#undef TestPcmpXmmAddr
+#undef TestPcmpXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, 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(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
+ __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
+ __ roundsd(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
+ AssemblerX8632::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, xmm0);
+
+#undef TestRoundsd
+#undef TestRoundsdXmmXmm
+}
+
+TEST_F(AssemblerX8632Test, Set1ps) {
+#define TestImpl(Xmm, Src, Imm) \
+ do { \
+ __ set1ps(XmmRegister::Encoded_Reg_##Xmm, GPRRegister::Encoded_Reg_##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, ebx, 1);
+ TestImpl(xmm1, ecx, 2);
+ TestImpl(xmm2, edx, 3);
+ TestImpl(xmm3, esi, 4);
+ TestImpl(xmm4, edi, 5);
+ TestImpl(xmm5, eax, 6);
+ TestImpl(xmm6, ebx, 7);
+ TestImpl(xmm7, ecx, 8);
+
+#undef TestImpl
+}
+
+} // end of anonymous namespace
+} // end of namespace Test
+} // end of namespace X8632
+} // end of namespace Ice
« no previous file with comments | « unittest/AssemblerX8632/X87.cpp ('k') | unittest/AssemblerX8664/ControlFlow.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698