| OLD | NEW |
| (Empty) | |
| 1 //===- subzero/unittest/AssemblerX8632/XmmArith.cpp -----------------------===// |
| 2 // |
| 3 // The Subzero Code Generator |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 #include "AssemblerX8632/TestUtil.h" |
| 10 |
| 11 namespace Ice { |
| 12 namespace X8632 { |
| 13 namespace Test { |
| 14 namespace { |
| 15 |
| 16 TEST_F(AssemblerX8632Test, ArithSS) { |
| 17 #define TestArithSSXmmXmm(FloatSize, Src, Value0, Dst, Value1, Inst, Op) \ |
| 18 do { \ |
| 19 static_assert(FloatSize == 32 || FloatSize == 64, \ |
| 20 "Invalid fp size " #FloatSize); \ |
| 21 static constexpr char TestString[] = \ |
| 22 "(" #FloatSize ", " #Src ", " #Value0 ", " #Dst ", " #Value1 \ |
| 23 ", " #Inst ", " #Op ")"; \ |
| 24 static constexpr bool IsDouble = FloatSize == 64; \ |
| 25 using Type = std::conditional<IsDouble, double, float>::type; \ |
| 26 const uint32_t T0 = allocateQword(); \ |
| 27 const Type V0 = Value0; \ |
| 28 const uint32_t T1 = allocateQword(); \ |
| 29 const Type V1 = Value1; \ |
| 30 \ |
| 31 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \ |
| 32 dwordAddress(T0)); \ |
| 33 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Src, \ |
| 34 dwordAddress(T1)); \ |
| 35 __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \ |
| 36 XmmRegister::Encoded_Reg_##Src); \ |
| 37 \ |
| 38 AssembledTest test = assemble(); \ |
| 39 if (IsDouble) { \ |
| 40 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 41 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 42 } else { \ |
| 43 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 44 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 45 } \ |
| 46 \ |
| 47 test.run(); \ |
| 48 \ |
| 49 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \ |
| 50 reset(); \ |
| 51 } while (0) |
| 52 |
| 53 #define TestArithSSXmmAddr(FloatSize, Value0, Dst, Value1, Inst, Op) \ |
| 54 do { \ |
| 55 static_assert(FloatSize == 32 || FloatSize == 64, \ |
| 56 "Invalid fp size " #FloatSize); \ |
| 57 static constexpr char TestString[] = \ |
| 58 "(" #FloatSize ", Addr, " #Value0 ", " #Dst ", " #Value1 ", " #Inst \ |
| 59 ", " #Op ")"; \ |
| 60 static constexpr bool IsDouble = FloatSize == 64; \ |
| 61 using Type = std::conditional<IsDouble, double, float>::type; \ |
| 62 const uint32_t T0 = allocateQword(); \ |
| 63 const Type V0 = Value0; \ |
| 64 const uint32_t T1 = allocateQword(); \ |
| 65 const Type V1 = Value1; \ |
| 66 \ |
| 67 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \ |
| 68 dwordAddress(T0)); \ |
| 69 __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \ |
| 70 dwordAddress(T1)); \ |
| 71 \ |
| 72 AssembledTest test = assemble(); \ |
| 73 if (IsDouble) { \ |
| 74 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 75 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 76 } else { \ |
| 77 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 78 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 79 } \ |
| 80 \ |
| 81 test.run(); \ |
| 82 \ |
| 83 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \ |
| 84 reset(); \ |
| 85 } while (0) |
| 86 |
| 87 #define TestArithSS(FloatSize, Src, Dst0, Dst1) \ |
| 88 do { \ |
| 89 TestArithSSXmmXmm(FloatSize, Src, 1.0, Dst0, 10.0, addss, +); \ |
| 90 TestArithSSXmmAddr(FloatSize, 2.0, Dst1, 20.0, addss, +); \ |
| 91 TestArithSSXmmXmm(FloatSize, Src, 3.0, Dst0, 30.0, subss, -); \ |
| 92 TestArithSSXmmAddr(FloatSize, 4.0, Dst1, 40.0, subss, -); \ |
| 93 TestArithSSXmmXmm(FloatSize, Src, 5.0, Dst0, 50.0, mulss, *); \ |
| 94 TestArithSSXmmAddr(FloatSize, 6.0, Dst1, 60.0, mulss, *); \ |
| 95 TestArithSSXmmXmm(FloatSize, Src, 7.0, Dst0, 70.0, divss, / ); \ |
| 96 TestArithSSXmmAddr(FloatSize, 8.0, Dst1, 80.0, divss, / ); \ |
| 97 } while (0) |
| 98 |
| 99 TestArithSS(32, xmm0, xmm1, xmm2); |
| 100 TestArithSS(32, xmm1, xmm2, xmm3); |
| 101 TestArithSS(32, xmm2, xmm3, xmm4); |
| 102 TestArithSS(32, xmm3, xmm4, xmm5); |
| 103 TestArithSS(32, xmm4, xmm5, xmm6); |
| 104 TestArithSS(32, xmm5, xmm6, xmm7); |
| 105 TestArithSS(32, xmm6, xmm7, xmm0); |
| 106 TestArithSS(32, xmm7, xmm0, xmm1); |
| 107 |
| 108 TestArithSS(64, xmm0, xmm1, xmm2); |
| 109 TestArithSS(64, xmm1, xmm2, xmm3); |
| 110 TestArithSS(64, xmm2, xmm3, xmm4); |
| 111 TestArithSS(64, xmm3, xmm4, xmm5); |
| 112 TestArithSS(64, xmm4, xmm5, xmm6); |
| 113 TestArithSS(64, xmm5, xmm6, xmm7); |
| 114 TestArithSS(64, xmm6, xmm7, xmm0); |
| 115 TestArithSS(64, xmm7, xmm0, xmm1); |
| 116 |
| 117 #undef TestArithSS |
| 118 #undef TestArithSSXmmAddr |
| 119 #undef TestArithSSXmmXmm |
| 120 } |
| 121 |
| 122 TEST_F(AssemblerX8632Test, PArith) { |
| 123 #define TestPArithXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type, Size) \ |
| 124 do { \ |
| 125 static constexpr char TestString[] = \ |
| 126 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \ |
| 127 ", " #Type ", " #Size ")"; \ |
| 128 const uint32_t T0 = allocateDqword(); \ |
| 129 const Dqword V0 Value0; \ |
| 130 \ |
| 131 const uint32_t T1 = allocateDqword(); \ |
| 132 const Dqword V1 Value1; \ |
| 133 \ |
| 134 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 135 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 136 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 137 XmmRegister::Encoded_Reg_##Src); \ |
| 138 \ |
| 139 AssembledTest test = assemble(); \ |
| 140 test.setDqwordTo(T0, V0); \ |
| 141 test.setDqwordTo(T1, V1); \ |
| 142 test.run(); \ |
| 143 \ |
| 144 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \ |
| 145 << TestString; \ |
| 146 reset(); \ |
| 147 } while (0) |
| 148 |
| 149 #define TestPArithXmmAddr(Dst, Value0, Value1, Inst, Op, Type, Size) \ |
| 150 do { \ |
| 151 static constexpr char TestString[] = \ |
| 152 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \ |
| 153 ", " #Type ", " #Size ")"; \ |
| 154 const uint32_t T0 = allocateDqword(); \ |
| 155 const Dqword V0 Value0; \ |
| 156 \ |
| 157 const uint32_t T1 = allocateDqword(); \ |
| 158 const Dqword V1 Value1; \ |
| 159 \ |
| 160 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 161 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 162 dwordAddress(T1)); \ |
| 163 \ |
| 164 AssembledTest test = assemble(); \ |
| 165 test.setDqwordTo(T0, V0); \ |
| 166 test.setDqwordTo(T1, V1); \ |
| 167 test.run(); \ |
| 168 \ |
| 169 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \ |
| 170 << TestString; \ |
| 171 reset(); \ |
| 172 } while (0) |
| 173 |
| 174 #define TestPArithXmmImm(Dst, Value0, Imm, Inst, Op, Type, Size) \ |
| 175 do { \ |
| 176 static constexpr char TestString[] = \ |
| 177 "(" #Dst ", " #Value0 ", " #Imm ", " #Inst ", " #Op ", " #Type \ |
| 178 ", " #Size ")"; \ |
| 179 const uint32_t T0 = allocateDqword(); \ |
| 180 const Dqword V0 Value0; \ |
| 181 \ |
| 182 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 183 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, Immediate(Imm)); \ |
| 184 \ |
| 185 AssembledTest test = assemble(); \ |
| 186 test.setDqwordTo(T0, V0); \ |
| 187 test.run(); \ |
| 188 \ |
| 189 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op Imm, test.Dst<Dqword>()) \ |
| 190 << TestString; \ |
| 191 reset(); \ |
| 192 } while (0) |
| 193 |
| 194 #define TestPAndnXmmXmm(Dst, Value0, Src, Value1, Type, Size) \ |
| 195 do { \ |
| 196 static constexpr char TestString[] = \ |
| 197 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", pandn, " #Type \ |
| 198 ", " #Size ")"; \ |
| 199 const uint32_t T0 = allocateDqword(); \ |
| 200 const Dqword V0 Value0; \ |
| 201 \ |
| 202 const uint32_t T1 = allocateDqword(); \ |
| 203 const Dqword V1 Value1; \ |
| 204 \ |
| 205 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 206 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 207 __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 208 XmmRegister::Encoded_Reg_##Src); \ |
| 209 \ |
| 210 AssembledTest test = assemble(); \ |
| 211 test.setDqwordTo(T0, V0); \ |
| 212 test.setDqwordTo(T1, V1); \ |
| 213 test.run(); \ |
| 214 \ |
| 215 ASSERT_EQ(~(packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \ |
| 216 << TestString; \ |
| 217 reset(); \ |
| 218 } while (0) |
| 219 |
| 220 #define TestPAndnXmmAddr(Dst, Value0, Value1, Type, Size) \ |
| 221 do { \ |
| 222 static constexpr char TestString[] = \ |
| 223 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", pandn, " #Type ", " #Size \ |
| 224 ")"; \ |
| 225 const uint32_t T0 = allocateDqword(); \ |
| 226 const Dqword V0 Value0; \ |
| 227 \ |
| 228 const uint32_t T1 = allocateDqword(); \ |
| 229 const Dqword V1 Value1; \ |
| 230 \ |
| 231 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 232 __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 233 dwordAddress(T1)); \ |
| 234 \ |
| 235 AssembledTest test = assemble(); \ |
| 236 test.setDqwordTo(T0, V0); \ |
| 237 test.setDqwordTo(T1, V1); \ |
| 238 test.run(); \ |
| 239 \ |
| 240 ASSERT_EQ((~packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \ |
| 241 << TestString; \ |
| 242 reset(); \ |
| 243 } while (0) |
| 244 |
| 245 #define TestPArithSize(Dst, Src, Size) \ |
| 246 do { \ |
| 247 static_assert(Size == 8 || Size == 16 || Size == 32, "Invalid size."); \ |
| 248 if (Size != 8) { \ |
| 249 TestPArithXmmXmm( \ |
| 250 Dst, \ |
| 251 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 252 Src, (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \ |
| 253 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \ |
| 254 uint64_t(0x8080404002020101ull)), \ |
| 255 (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \ |
| 256 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 257 uint64_t(0x8080404002020101ull)), \ |
| 258 3u, psra, >>, int, Size); \ |
| 259 TestPArithXmmXmm( \ |
| 260 Dst, \ |
| 261 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 262 Src, (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \ |
| 263 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \ |
| 264 uint64_t(0x8080404002020101ull)), \ |
| 265 (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \ |
| 266 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 267 uint64_t(0x8080404002020101ull)), \ |
| 268 3u, psrl, >>, uint, Size); \ |
| 269 TestPArithXmmXmm( \ |
| 270 Dst, \ |
| 271 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 272 Src, (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \ |
| 273 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \ |
| 274 uint64_t(0x8080404002020101ull)), \ |
| 275 (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \ |
| 276 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 277 uint64_t(0x8080404002020101ull)), \ |
| 278 3u, psll, <<, uint, Size); \ |
| 279 \ |
| 280 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 281 uint64_t(0x8080404002020101ull)), \ |
| 282 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 283 uint64_t(0x0123456789ABCDEull)), \ |
| 284 pmull, *, int, Size); \ |
| 285 TestPArithXmmAddr( \ |
| 286 Dst, \ |
| 287 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 288 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 289 pmull, *, int, Size); \ |
| 290 if (Size != 16) { \ |
| 291 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 292 uint64_t(0x8080404002020101ull)), \ |
| 293 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 294 uint64_t(0x0123456789ABCDEull)), \ |
| 295 pmuludq, *, uint, Size); \ |
| 296 TestPArithXmmAddr( \ |
| 297 Dst, (uint64_t(0x8040201008040201ull), \ |
| 298 uint64_t(0x8080404002020101ull)), \ |
| 299 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 300 pmuludq, *, uint, Size); \ |
| 301 } \ |
| 302 } \ |
| 303 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 304 uint64_t(0x8080404002020101ull)), \ |
| 305 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 306 uint64_t(0x0123456789ABCDEull)), \ |
| 307 padd, +, int, Size); \ |
| 308 TestPArithXmmAddr( \ |
| 309 Dst, \ |
| 310 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 311 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 312 padd, +, int, Size); \ |
| 313 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 314 uint64_t(0x8080404002020101ull)), \ |
| 315 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 316 uint64_t(0x0123456789ABCDEull)), \ |
| 317 psub, -, int, Size); \ |
| 318 TestPArithXmmAddr( \ |
| 319 Dst, \ |
| 320 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 321 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 322 psub, -, int, Size); \ |
| 323 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 324 uint64_t(0x8080404002020101ull)), \ |
| 325 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 326 uint64_t(0x0123456789ABCDEull)), \ |
| 327 pand, &, int, Size); \ |
| 328 TestPArithXmmAddr( \ |
| 329 Dst, \ |
| 330 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 331 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 332 pand, &, int, Size); \ |
| 333 \ |
| 334 TestPAndnXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 335 uint64_t(0x8080404002020101ull)), \ |
| 336 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 337 uint64_t(0x0123456789ABCDEull)), \ |
| 338 int, Size); \ |
| 339 TestPAndnXmmAddr( \ |
| 340 Dst, \ |
| 341 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 342 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 343 int, Size); \ |
| 344 \ |
| 345 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 346 uint64_t(0x8080404002020101ull)), \ |
| 347 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 348 uint64_t(0x0123456789ABCDEull)), \ |
| 349 por, |, int, Size); \ |
| 350 TestPArithXmmAddr( \ |
| 351 Dst, \ |
| 352 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 353 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 354 por, |, int, Size); \ |
| 355 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \ |
| 356 uint64_t(0x8080404002020101ull)), \ |
| 357 Src, (uint64_t(0xFFFFFFFF00000000ull), \ |
| 358 uint64_t(0x0123456789ABCDEull)), \ |
| 359 pxor, ^, int, Size); \ |
| 360 TestPArithXmmAddr( \ |
| 361 Dst, \ |
| 362 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \ |
| 363 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \ |
| 364 pxor, ^, int, Size); \ |
| 365 } while (0) |
| 366 |
| 367 #define TestPArith(Src, Dst) \ |
| 368 do { \ |
| 369 TestPArithSize(Src, Dst, 8); \ |
| 370 TestPArithSize(Src, Dst, 16); \ |
| 371 TestPArithSize(Src, Dst, 32); \ |
| 372 } while (0) |
| 373 |
| 374 TestPArith(xmm0, xmm1); |
| 375 TestPArith(xmm1, xmm2); |
| 376 TestPArith(xmm2, xmm3); |
| 377 TestPArith(xmm3, xmm4); |
| 378 TestPArith(xmm4, xmm5); |
| 379 TestPArith(xmm5, xmm6); |
| 380 TestPArith(xmm6, xmm7); |
| 381 TestPArith(xmm7, xmm0); |
| 382 |
| 383 #undef TestPArith |
| 384 #undef TestPArithSize |
| 385 #undef TestPAndnXmmAddr |
| 386 #undef TestPAndnXmmXmm |
| 387 #undef TestPArithXmmImm |
| 388 #undef TestPArithXmmAddr |
| 389 #undef TestPArithXmmXmm |
| 390 } |
| 391 |
| 392 TEST_F(AssemblerX8632Test, ArithPS) { |
| 393 #define TestArithPSXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type) \ |
| 394 do { \ |
| 395 static constexpr char TestString[] = \ |
| 396 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \ |
| 397 ", " #Type ")"; \ |
| 398 const uint32_t T0 = allocateDqword(); \ |
| 399 const Dqword V0 Value0; \ |
| 400 const uint32_t T1 = allocateDqword(); \ |
| 401 const Dqword V1 Value1; \ |
| 402 \ |
| 403 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 404 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 405 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \ |
| 406 XmmRegister::Encoded_Reg_##Src); \ |
| 407 \ |
| 408 AssembledTest test = assemble(); \ |
| 409 test.setDqwordTo(T0, V0); \ |
| 410 test.setDqwordTo(T1, V1); \ |
| 411 test.run(); \ |
| 412 \ |
| 413 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 414 \ |
| 415 reset(); \ |
| 416 } while (0) |
| 417 |
| 418 #define TestArithPSXmmXmmUntyped(Dst, Value0, Src, Value1, Inst, Op, Type) \ |
| 419 do { \ |
| 420 static constexpr char TestString[] = \ |
| 421 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \ |
| 422 ", " #Type ")"; \ |
| 423 const uint32_t T0 = allocateDqword(); \ |
| 424 const Dqword V0 Value0; \ |
| 425 const uint32_t T1 = allocateDqword(); \ |
| 426 const Dqword V1 Value1; \ |
| 427 \ |
| 428 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 429 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 430 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 431 \ |
| 432 AssembledTest test = assemble(); \ |
| 433 test.setDqwordTo(T0, V0); \ |
| 434 test.setDqwordTo(T1, V1); \ |
| 435 test.run(); \ |
| 436 \ |
| 437 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 438 \ |
| 439 reset(); \ |
| 440 } while (0) |
| 441 |
| 442 #define TestArithPSXmmAddrUntyped(Dst, Value0, Value1, Inst, Op, Type) \ |
| 443 do { \ |
| 444 static constexpr char TestString[] = \ |
| 445 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \ |
| 446 ", " #Type ")"; \ |
| 447 const uint32_t T0 = allocateDqword(); \ |
| 448 const Dqword V0 Value0; \ |
| 449 const uint32_t T1 = allocateDqword(); \ |
| 450 const Dqword V1 Value1; \ |
| 451 \ |
| 452 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 453 __ Inst(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 454 \ |
| 455 AssembledTest test = assemble(); \ |
| 456 test.setDqwordTo(T0, V0); \ |
| 457 test.setDqwordTo(T1, V1); \ |
| 458 test.run(); \ |
| 459 \ |
| 460 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 461 \ |
| 462 reset(); \ |
| 463 } while (0) |
| 464 |
| 465 #define TestMinMaxPS(Dst, Value0, Src, Value1, Inst, Type) \ |
| 466 do { \ |
| 467 static constexpr char TestString[] = \ |
| 468 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Type \ |
| 469 ")"; \ |
| 470 const uint32_t T0 = allocateDqword(); \ |
| 471 const Dqword V0 Value0; \ |
| 472 const uint32_t T1 = allocateDqword(); \ |
| 473 const Dqword V1 Value1; \ |
| 474 \ |
| 475 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 476 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 477 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 478 \ |
| 479 AssembledTest test = assemble(); \ |
| 480 test.setDqwordTo(T0, V0); \ |
| 481 test.setDqwordTo(T1, V1); \ |
| 482 test.run(); \ |
| 483 \ |
| 484 ASSERT_EQ(packedAs<Type>(V0).Inst(V1), test.Dst<Dqword>()) << TestString; \ |
| 485 \ |
| 486 reset(); \ |
| 487 } while (0) |
| 488 |
| 489 #define TestArithPSXmmAddr(Dst, Value0, Value1, Inst, Op, Type) \ |
| 490 do { \ |
| 491 static constexpr char TestString[] = \ |
| 492 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \ |
| 493 ", " #Type ")"; \ |
| 494 const uint32_t T0 = allocateDqword(); \ |
| 495 const Dqword V0 Value0; \ |
| 496 const uint32_t T1 = allocateDqword(); \ |
| 497 const Dqword V1 Value1; \ |
| 498 \ |
| 499 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 500 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 501 \ |
| 502 AssembledTest test = assemble(); \ |
| 503 test.setDqwordTo(T0, V0); \ |
| 504 test.setDqwordTo(T1, V1); \ |
| 505 test.run(); \ |
| 506 \ |
| 507 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 508 \ |
| 509 reset(); \ |
| 510 } while (0) |
| 511 |
| 512 #define TestArithPS(Dst, Src) \ |
| 513 do { \ |
| 514 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 515 (0.55, 0.43, 0.23, 1.21), addps, +, float); \ |
| 516 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 517 (0.55, 0.43, 0.23, 1.21), addps, +, float); \ |
| 518 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 519 (0.55, 0.43, 0.23, 1.21), subps, -, float); \ |
| 520 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 521 (0.55, 0.43, 0.23, 1.21), subps, -, float); \ |
| 522 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 523 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \ |
| 524 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 525 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \ |
| 526 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 527 (0.55, 0.43, 0.23, 1.21), divps, /, float); \ |
| 528 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 529 (0.55, 0.43, 0.23, 1.21), divps, /, float); \ |
| 530 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 531 (0.55, 0.43, 0.23, 1.21), andps, &, float); \ |
| 532 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 533 (0.55, 0.43, 0.23, 1.21), andps, &, float); \ |
| 534 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), andpd, &, \ |
| 535 double); \ |
| 536 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), andpd, &, \ |
| 537 double); \ |
| 538 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 539 (0.55, 0.43, 0.23, 1.21), orps, |, float); \ |
| 540 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), orpd, |, \ |
| 541 double); \ |
| 542 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 543 (0.55, 0.43, 0.23, 1.21), minps, float); \ |
| 544 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 545 (0.55, 0.43, 0.23, 1.21), maxps, float); \ |
| 546 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), minpd, double); \ |
| 547 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxpd, double); \ |
| 548 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \ |
| 549 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \ |
| 550 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \ |
| 551 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \ |
| 552 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorpd, ^, \ |
| 553 double); \ |
| 554 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), xorpd, ^, \ |
| 555 double); \ |
| 556 } while (0) |
| 557 |
| 558 #if 0 |
| 559 |
| 560 #endif |
| 561 |
| 562 TestArithPS(xmm0, xmm1); |
| 563 TestArithPS(xmm1, xmm2); |
| 564 TestArithPS(xmm2, xmm3); |
| 565 TestArithPS(xmm3, xmm4); |
| 566 TestArithPS(xmm4, xmm5); |
| 567 TestArithPS(xmm5, xmm6); |
| 568 TestArithPS(xmm6, xmm7); |
| 569 TestArithPS(xmm7, xmm0); |
| 570 |
| 571 #undef TestArithPs |
| 572 #undef TestMinMaxPS |
| 573 #undef TestArithPSXmmXmmUntyped |
| 574 #undef TestArithPSXmmAddr |
| 575 #undef TestArithPSXmmXmm |
| 576 } |
| 577 |
| 578 TEST_F(AssemblerX8632Test, Blending) { |
| 579 using f32 = float; |
| 580 using i8 = uint8_t; |
| 581 |
| 582 #define TestBlendingXmmXmm(Dst, Value0, Src, Value1, M /*ask*/, Inst, Type) \ |
| 583 do { \ |
| 584 static constexpr char TestString[] = \ |
| 585 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #M ", " #Inst \ |
| 586 ", " #Type ")"; \ |
| 587 const uint32_t T0 = allocateDqword(); \ |
| 588 const Dqword V0 Value0; \ |
| 589 const uint32_t T1 = allocateDqword(); \ |
| 590 const Dqword V1 Value1; \ |
| 591 const uint32_t Mask = allocateDqword(); \ |
| 592 const Dqword MaskValue M; \ |
| 593 \ |
| 594 __ movups(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \ |
| 595 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 596 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 597 __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##Dst, \ |
| 598 XmmRegister::Encoded_Reg_##Src); \ |
| 599 \ |
| 600 AssembledTest test = assemble(); \ |
| 601 test.setDqwordTo(T0, V0); \ |
| 602 test.setDqwordTo(T1, V1); \ |
| 603 test.setDqwordTo(Mask, MaskValue); \ |
| 604 test.run(); \ |
| 605 \ |
| 606 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \ |
| 607 << TestString; \ |
| 608 reset(); \ |
| 609 } while (0) |
| 610 |
| 611 #define TestBlendingXmmAddr(Dst, Value0, Value1, M /*ask*/, Inst, Type) \ |
| 612 do { \ |
| 613 static constexpr char TestString[] = \ |
| 614 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #M ", " #Inst ", " #Type \ |
| 615 ")"; \ |
| 616 const uint32_t T0 = allocateDqword(); \ |
| 617 const Dqword V0 Value0; \ |
| 618 const uint32_t T1 = allocateDqword(); \ |
| 619 const Dqword V1 Value1; \ |
| 620 const uint32_t Mask = allocateDqword(); \ |
| 621 const Dqword MaskValue M; \ |
| 622 \ |
| 623 __ movups(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \ |
| 624 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 625 __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 626 \ |
| 627 AssembledTest test = assemble(); \ |
| 628 test.setDqwordTo(T0, V0); \ |
| 629 test.setDqwordTo(T1, V1); \ |
| 630 test.setDqwordTo(Mask, MaskValue); \ |
| 631 test.run(); \ |
| 632 \ |
| 633 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \ |
| 634 << TestString; \ |
| 635 reset(); \ |
| 636 } while (0) |
| 637 |
| 638 #define TestBlending(Src, Dst) \ |
| 639 do { \ |
| 640 TestBlendingXmmXmm( \ |
| 641 Dst, (1.0, 2.0, 1.0, 2.0), Src, (-1.0, -2.0, -1.0, -2.0), \ |
| 642 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \ |
| 643 blendvps, f32); \ |
| 644 TestBlendingXmmAddr( \ |
| 645 Dst, (1.0, 2.0, 1.0, 2.0), (-1.0, -2.0, -1.0, -2.0), \ |
| 646 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \ |
| 647 blendvps, f32); \ |
| 648 TestBlendingXmmXmm( \ |
| 649 Dst, \ |
| 650 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \ |
| 651 Src, \ |
| 652 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \ |
| 653 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \ |
| 654 pblendvb, i8); \ |
| 655 TestBlendingXmmAddr( \ |
| 656 Dst, \ |
| 657 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \ |
| 658 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \ |
| 659 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \ |
| 660 pblendvb, i8); \ |
| 661 } while (0) |
| 662 |
| 663 /* xmm0 is taken. It is the implicit mask . */ |
| 664 TestBlending(xmm1, xmm2); |
| 665 TestBlending(xmm2, xmm3); |
| 666 TestBlending(xmm3, xmm4); |
| 667 TestBlending(xmm4, xmm5); |
| 668 TestBlending(xmm5, xmm6); |
| 669 TestBlending(xmm6, xmm7); |
| 670 TestBlending(xmm7, xmm1); |
| 671 |
| 672 #undef TestBlending |
| 673 #undef TestBlendingXmmAddr |
| 674 #undef TestBlendingXmmXmm |
| 675 } |
| 676 |
| 677 TEST_F(AssemblerX8632Test, Cmpps) { |
| 678 #define TestCmppsXmmXmm(Dst, Src, C, Op) \ |
| 679 do { \ |
| 680 static constexpr char TestString[] = \ |
| 681 "(" #Src ", " #Dst ", " #C ", " #Op ")"; \ |
| 682 const uint32_t T0 = allocateDqword(); \ |
| 683 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \ |
| 684 const uint32_t T1 = allocateDqword(); \ |
| 685 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \ |
| 686 \ |
| 687 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 688 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 689 __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \ |
| 690 Cond::Cmpps_##C); \ |
| 691 \ |
| 692 AssembledTest test = assemble(); \ |
| 693 test.setDqwordTo(T0, V0); \ |
| 694 test.setDqwordTo(T1, V1); \ |
| 695 test.run(); \ |
| 696 \ |
| 697 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 698 ; \ |
| 699 reset(); \ |
| 700 } while (0) |
| 701 |
| 702 #define TestCmppsXmmAddr(Dst, C, Op) \ |
| 703 do { \ |
| 704 static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \ |
| 705 const uint32_t T0 = allocateDqword(); \ |
| 706 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \ |
| 707 const uint32_t T1 = allocateDqword(); \ |
| 708 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \ |
| 709 \ |
| 710 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 711 __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \ |
| 712 Cond::Cmpps_##C); \ |
| 713 \ |
| 714 AssembledTest test = assemble(); \ |
| 715 test.setDqwordTo(T0, V0); \ |
| 716 test.setDqwordTo(T1, V1); \ |
| 717 test.run(); \ |
| 718 \ |
| 719 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \ |
| 720 ; \ |
| 721 reset(); \ |
| 722 } while (0) |
| 723 |
| 724 #define TestCmppsOrdUnordXmmXmm(Dst, Src, C) \ |
| 725 do { \ |
| 726 static constexpr char TestString[] = "(" #Src ", " #Dst ", " #C ")"; \ |
| 727 const uint32_t T0 = allocateDqword(); \ |
| 728 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 729 std::numeric_limits<float>::quiet_NaN()); \ |
| 730 const uint32_t T1 = allocateDqword(); \ |
| 731 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \ |
| 732 std::numeric_limits<float>::quiet_NaN()); \ |
| 733 \ |
| 734 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 735 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 736 __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \ |
| 737 Cond::Cmpps_##C); \ |
| 738 \ |
| 739 AssembledTest test = assemble(); \ |
| 740 test.setDqwordTo(T0, V0); \ |
| 741 test.setDqwordTo(T1, V1); \ |
| 742 test.run(); \ |
| 743 \ |
| 744 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \ |
| 745 ; \ |
| 746 reset(); \ |
| 747 } while (0) |
| 748 |
| 749 #define TestCmppsOrdUnordXmmAddr(Dst, C) \ |
| 750 do { \ |
| 751 static constexpr char TestString[] = "(" #Dst ", " #C ")"; \ |
| 752 const uint32_t T0 = allocateDqword(); \ |
| 753 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 754 std::numeric_limits<float>::quiet_NaN()); \ |
| 755 const uint32_t T1 = allocateDqword(); \ |
| 756 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \ |
| 757 std::numeric_limits<float>::quiet_NaN()); \ |
| 758 \ |
| 759 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 760 __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \ |
| 761 Cond::Cmpps_##C); \ |
| 762 \ |
| 763 AssembledTest test = assemble(); \ |
| 764 test.setDqwordTo(T0, V0); \ |
| 765 test.setDqwordTo(T1, V1); \ |
| 766 test.run(); \ |
| 767 \ |
| 768 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \ |
| 769 ; \ |
| 770 reset(); \ |
| 771 } while (0) |
| 772 |
| 773 #define TestCmpps(Dst, Src) \ |
| 774 do { \ |
| 775 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 776 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 777 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 778 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 779 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 780 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 781 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \ |
| 782 TestCmppsOrdUnordXmmAddr(Dst, unord); \ |
| 783 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 784 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 785 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 786 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 787 TestCmppsXmmXmm(Dst, Src, eq, == ); \ |
| 788 TestCmppsXmmAddr(Dst, eq, == ); \ |
| 789 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \ |
| 790 TestCmppsOrdUnordXmmAddr(Dst, unord); \ |
| 791 } while (0) |
| 792 |
| 793 TestCmpps(xmm0, xmm1); |
| 794 TestCmpps(xmm1, xmm2); |
| 795 TestCmpps(xmm2, xmm3); |
| 796 TestCmpps(xmm3, xmm4); |
| 797 TestCmpps(xmm4, xmm5); |
| 798 TestCmpps(xmm5, xmm6); |
| 799 TestCmpps(xmm6, xmm7); |
| 800 TestCmpps(xmm7, xmm0); |
| 801 |
| 802 #undef TestCmpps |
| 803 #undef TestCmppsOrdUnordXmmAddr |
| 804 #undef TestCmppsOrdUnordXmmXmm |
| 805 #undef TestCmppsXmmAddr |
| 806 #undef TestCmppsXmmXmm |
| 807 } |
| 808 |
| 809 TEST_F(AssemblerX8632Test, Sqrtps_Rsqrtps_Reciprocalps_Sqrtpd) { |
| 810 #define TestImplSingle(Dst, Inst, Expect) \ |
| 811 do { \ |
| 812 static constexpr char TestString[] = "(" #Dst ", " #Inst ")"; \ |
| 813 const uint32_t T0 = allocateDqword(); \ |
| 814 const Dqword V0(1.0, 4.0, 20.0, 3.14); \ |
| 815 \ |
| 816 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 817 __ Inst(XmmRegister::Encoded_Reg_##Dst); \ |
| 818 \ |
| 819 AssembledTest test = assemble(); \ |
| 820 test.setDqwordTo(T0, V0); \ |
| 821 test.run(); \ |
| 822 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \ |
| 823 reset(); \ |
| 824 } while (0) |
| 825 |
| 826 #define TestImpl(Dst) \ |
| 827 do { \ |
| 828 TestImplSingle(Dst, sqrtps, (uint64_t(0x400000003F800000ull), \ |
| 829 uint64_t(0x3FE2D10B408F1BBDull))); \ |
| 830 TestImplSingle(Dst, rsqrtps, (uint64_t(0x3EFFF0003F7FF000ull), \ |
| 831 uint64_t(0x3F1078003E64F000ull))); \ |
| 832 TestImplSingle(Dst, reciprocalps, (uint64_t(0x3E7FF0003F7FF000ull), \ |
| 833 uint64_t(0x3EA310003D4CC000ull))); \ |
| 834 \ |
| 835 TestImplSingle(Dst, sqrtpd, (uint64_t(0x4036A09E9365F5F3ull), \ |
| 836 uint64_t(0x401C42FAE40282A8ull))); \ |
| 837 } while (0) |
| 838 |
| 839 TestImpl(xmm0); |
| 840 TestImpl(xmm1); |
| 841 TestImpl(xmm2); |
| 842 TestImpl(xmm3); |
| 843 TestImpl(xmm4); |
| 844 TestImpl(xmm5); |
| 845 TestImpl(xmm6); |
| 846 TestImpl(xmm7); |
| 847 |
| 848 #undef TestImpl |
| 849 #undef TestImplSingle |
| 850 } |
| 851 |
| 852 TEST_F(AssemblerX8632Test, Unpck) { |
| 853 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), |
| 854 uint64_t(0xCCCCCCCCDDDDDDDDull)); |
| 855 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), |
| 856 uint64_t(0x9999999988888888ull)); |
| 857 |
| 858 const Dqword unpcklpsExpected(uint64_t(0xFFFFFFFFBBBBBBBBull), |
| 859 uint64_t(0xEEEEEEEEAAAAAAAAull)); |
| 860 const Dqword unpcklpdExpected(uint64_t(0xAAAAAAAABBBBBBBBull), |
| 861 uint64_t(0xEEEEEEEEFFFFFFFFull)); |
| 862 const Dqword unpckhpsExpected(uint64_t(0x88888888DDDDDDDDull), |
| 863 uint64_t(0x99999999CCCCCCCCull)); |
| 864 const Dqword unpckhpdExpected(uint64_t(0xCCCCCCCCDDDDDDDDull), |
| 865 uint64_t(0x9999999988888888ull)); |
| 866 |
| 867 #define TestImplSingle(Dst, Src, Inst) \ |
| 868 do { \ |
| 869 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ |
| 870 const uint32_t T0 = allocateDqword(); \ |
| 871 const uint32_t T1 = allocateDqword(); \ |
| 872 \ |
| 873 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 874 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 875 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 876 \ |
| 877 AssembledTest test = assemble(); \ |
| 878 test.setDqwordTo(T0, V0); \ |
| 879 test.setDqwordTo(T1, V1); \ |
| 880 test.run(); \ |
| 881 \ |
| 882 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \ |
| 883 reset(); \ |
| 884 } while (0) |
| 885 |
| 886 #define TestImpl(Dst, Src) \ |
| 887 do { \ |
| 888 TestImplSingle(Dst, Src, unpcklps); \ |
| 889 TestImplSingle(Dst, Src, unpcklpd); \ |
| 890 TestImplSingle(Dst, Src, unpckhps); \ |
| 891 TestImplSingle(Dst, Src, unpckhpd); \ |
| 892 } while (0) |
| 893 |
| 894 TestImpl(xmm0, xmm1); |
| 895 TestImpl(xmm1, xmm2); |
| 896 TestImpl(xmm2, xmm3); |
| 897 TestImpl(xmm3, xmm4); |
| 898 TestImpl(xmm4, xmm5); |
| 899 TestImpl(xmm5, xmm6); |
| 900 TestImpl(xmm6, xmm7); |
| 901 TestImpl(xmm7, xmm0); |
| 902 |
| 903 #undef TestImpl |
| 904 #undef TestImplSingle |
| 905 } |
| 906 |
| 907 TEST_F(AssemblerX8632Test, Shufp) { |
| 908 const Dqword V0(uint64_t(0x1111111122222222ull), |
| 909 uint64_t(0x5555555577777777ull)); |
| 910 const Dqword V1(uint64_t(0xAAAAAAAABBBBBBBBull), |
| 911 uint64_t(0xCCCCCCCCDDDDDDDDull)); |
| 912 |
| 913 const uint8_t pshufdImm = 0x63; |
| 914 const Dqword pshufdExpected(uint64_t(0xBBBBBBBBCCCCCCCCull), |
| 915 uint64_t(0xAAAAAAAADDDDDDDDull)); |
| 916 |
| 917 const uint8_t shufpsImm = 0xf9; |
| 918 const Dqword shufpsExpected(uint64_t(0x7777777711111111ull), |
| 919 uint64_t(0xCCCCCCCCCCCCCCCCull)); |
| 920 |
| 921 #define TestImplSingleXmmXmm(Dst, Src, Inst) \ |
| 922 do { \ |
| 923 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ |
| 924 const uint32_t T0 = allocateDqword(); \ |
| 925 const uint32_t T1 = allocateDqword(); \ |
| 926 \ |
| 927 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 928 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 929 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \ |
| 930 XmmRegister::Encoded_Reg_##Src, Immediate(Inst##Imm)); \ |
| 931 \ |
| 932 AssembledTest test = assemble(); \ |
| 933 test.setDqwordTo(T0, V0); \ |
| 934 test.setDqwordTo(T1, V1); \ |
| 935 test.run(); \ |
| 936 \ |
| 937 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \ |
| 938 reset(); \ |
| 939 } while (0) |
| 940 |
| 941 #define TestImplSingleXmmAddr(Dst, Inst) \ |
| 942 do { \ |
| 943 static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \ |
| 944 const uint32_t T0 = allocateDqword(); \ |
| 945 const uint32_t T1 = allocateDqword(); \ |
| 946 \ |
| 947 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 948 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \ |
| 949 Immediate(Inst##Imm)); \ |
| 950 \ |
| 951 AssembledTest test = assemble(); \ |
| 952 test.setDqwordTo(T0, V0); \ |
| 953 test.setDqwordTo(T1, V1); \ |
| 954 test.run(); \ |
| 955 \ |
| 956 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \ |
| 957 reset(); \ |
| 958 } while (0) |
| 959 |
| 960 #define TestImplSingleXmmXmmUntyped(Dst, Src, Inst) \ |
| 961 do { \ |
| 962 static constexpr char TestString[] = \ |
| 963 "(" #Dst ", " #Src ", " #Inst ", Untyped)"; \ |
| 964 const uint32_t T0 = allocateDqword(); \ |
| 965 const uint32_t T1 = allocateDqword(); \ |
| 966 \ |
| 967 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 968 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 969 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \ |
| 970 Immediate(Inst##Imm)); \ |
| 971 \ |
| 972 AssembledTest test = assemble(); \ |
| 973 test.setDqwordTo(T0, V0); \ |
| 974 test.setDqwordTo(T1, V1); \ |
| 975 test.run(); \ |
| 976 \ |
| 977 ASSERT_EQ(Inst##UntypedExpected, test.Dst<Dqword>()) << TestString; \ |
| 978 reset(); \ |
| 979 } while (0) |
| 980 |
| 981 #define TestImpl(Dst, Src) \ |
| 982 do { \ |
| 983 TestImplSingleXmmXmm(Dst, Src, pshufd); \ |
| 984 TestImplSingleXmmAddr(Dst, pshufd); \ |
| 985 TestImplSingleXmmXmm(Dst, Src, shufps); \ |
| 986 TestImplSingleXmmAddr(Dst, shufps); \ |
| 987 } while (0) |
| 988 |
| 989 TestImpl(xmm0, xmm1); |
| 990 TestImpl(xmm1, xmm2); |
| 991 TestImpl(xmm2, xmm3); |
| 992 TestImpl(xmm3, xmm4); |
| 993 TestImpl(xmm4, xmm5); |
| 994 TestImpl(xmm5, xmm6); |
| 995 TestImpl(xmm6, xmm7); |
| 996 TestImpl(xmm7, xmm0); |
| 997 |
| 998 #undef TestImpl |
| 999 #undef TestImplSingleXmmXmmUntyped |
| 1000 #undef TestImplSingleXmmAddr |
| 1001 #undef TestImplSingleXmmXmm |
| 1002 } |
| 1003 |
| 1004 TEST_F(AssemblerX8632Test, Cvt) { |
| 1005 const Dqword dq2ps32DstValue(-1.0f, -1.0f, -1.0f, -1.0f); |
| 1006 const Dqword dq2ps32SrcValue(-5, 3, 100, 200); |
| 1007 const Dqword dq2ps32Expected(-5.0f, 3.0f, 100.0, 200.0); |
| 1008 |
| 1009 const Dqword dq2ps64DstValue(0.0f, 0.0f, -1.0f, -1.0f); |
| 1010 const Dqword dq2ps64SrcValue(-5, 3, 100, 200); |
| 1011 const Dqword dq2ps64Expected(-5.0f, 3.0f, 100.0, 200.0); |
| 1012 |
| 1013 const Dqword tps2dq32DstValue(-1.0f, -1.0f, -1.0f, -1.0f); |
| 1014 const Dqword tps2dq32SrcValue(-5.0f, 3.0f, 100.0, 200.0); |
| 1015 const Dqword tps2dq32Expected(-5, 3, 100, 200); |
| 1016 |
| 1017 const Dqword tps2dq64DstValue(-1.0f, -1.0f, -1.0f, -1.0f); |
| 1018 const Dqword tps2dq64SrcValue(-5.0f, 3.0f, 100.0, 200.0); |
| 1019 const Dqword tps2dq64Expected(-5, 3, 100, 200); |
| 1020 |
| 1021 const Dqword si2ss32DstValue(-1.0f, -1.0f, -1.0f, -1.0f); |
| 1022 const int32_t si2ss32SrcValue = 5; |
| 1023 const Dqword si2ss32Expected(5.0f, -1.0f, -1.0f, -1.0f); |
| 1024 |
| 1025 const Dqword si2ss64DstValue(-1.0, -1.0); |
| 1026 const int32_t si2ss64SrcValue = 5; |
| 1027 const Dqword si2ss64Expected(5.0, -1.0); |
| 1028 |
| 1029 const int32_t tss2si32DstValue = 0xF00F0FF0; |
| 1030 const Dqword tss2si32SrcValue(-5.0f, -1.0f, -1.0f, -1.0f); |
| 1031 const int32_t tss2si32Expected = -5; |
| 1032 |
| 1033 const int32_t tss2si64DstValue = 0xF00F0FF0; |
| 1034 const Dqword tss2si64SrcValue(-5.0, -1.0); |
| 1035 const int32_t tss2si64Expected = -5; |
| 1036 |
| 1037 const Dqword float2float32DstValue(-1.0, -1.0); |
| 1038 const Dqword float2float32SrcValue(-5.0, 3, 100, 200); |
| 1039 const Dqword float2float32Expected(-5.0, -1.0); |
| 1040 |
| 1041 const Dqword float2float64DstValue(-1.0, -1.0, -1.0, -1.0); |
| 1042 const Dqword float2float64SrcValue(-5.0, 3.0); |
| 1043 const Dqword float2float64Expected(-5.0, -1.0, -1.0, -1.0); |
| 1044 |
| 1045 #define TestImplPXmmXmm(Dst, Src, Inst, Size) \ |
| 1046 do { \ |
| 1047 static constexpr char TestString[] = \ |
| 1048 "(" #Dst ", " #Src ", cvt" #Inst ", f" #Size ")"; \ |
| 1049 const uint32_t T0 = allocateDqword(); \ |
| 1050 const uint32_t T1 = allocateDqword(); \ |
| 1051 \ |
| 1052 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1053 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 1054 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1055 XmmRegister::Encoded_Reg_##Src); \ |
| 1056 \ |
| 1057 AssembledTest test = assemble(); \ |
| 1058 test.setDqwordTo(T0, Inst##Size##DstValue); \ |
| 1059 test.setDqwordTo(T1, Inst##Size##SrcValue); \ |
| 1060 test.run(); \ |
| 1061 \ |
| 1062 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \ |
| 1063 reset(); \ |
| 1064 } while (0) |
| 1065 |
| 1066 #define TestImplSXmmReg(Dst, GPR, Inst, Size) \ |
| 1067 do { \ |
| 1068 static constexpr char TestString[] = \ |
| 1069 "(" #Dst ", " #GPR ", cvt" #Inst ", f" #Size ")"; \ |
| 1070 const uint32_t T0 = allocateDqword(); \ |
| 1071 \ |
| 1072 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1073 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \ |
| 1074 Immediate(Inst##Size##SrcValue)); \ |
| 1075 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1076 GPRRegister::Encoded_Reg_##GPR); \ |
| 1077 \ |
| 1078 AssembledTest test = assemble(); \ |
| 1079 test.setDqwordTo(T0, Inst##Size##DstValue); \ |
| 1080 test.run(); \ |
| 1081 \ |
| 1082 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \ |
| 1083 reset(); \ |
| 1084 } while (0) |
| 1085 |
| 1086 #define TestImplSRegXmm(GPR, Src, Inst, Size) \ |
| 1087 do { \ |
| 1088 static constexpr char TestString[] = \ |
| 1089 "(" #GPR ", " #Src ", cvt" #Inst ", f" #Size ")"; \ |
| 1090 const uint32_t T0 = allocateDqword(); \ |
| 1091 \ |
| 1092 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \ |
| 1093 Immediate(Inst##Size##DstValue)); \ |
| 1094 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 1095 __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \ |
| 1096 XmmRegister::Encoded_Reg_##Src); \ |
| 1097 \ |
| 1098 AssembledTest test = assemble(); \ |
| 1099 test.setDqwordTo(T0, Inst##Size##SrcValue); \ |
| 1100 test.run(); \ |
| 1101 \ |
| 1102 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \ |
| 1103 << TestString; \ |
| 1104 reset(); \ |
| 1105 } while (0) |
| 1106 |
| 1107 #define TestImplPXmmAddr(Dst, Inst, Size) \ |
| 1108 do { \ |
| 1109 static constexpr char TestString[] = \ |
| 1110 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \ |
| 1111 const uint32_t T0 = allocateDqword(); \ |
| 1112 const uint32_t T1 = allocateDqword(); \ |
| 1113 \ |
| 1114 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1115 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1116 dwordAddress(T1)); \ |
| 1117 \ |
| 1118 AssembledTest test = assemble(); \ |
| 1119 test.setDqwordTo(T0, Inst##Size##DstValue); \ |
| 1120 test.setDqwordTo(T1, Inst##Size##SrcValue); \ |
| 1121 test.run(); \ |
| 1122 \ |
| 1123 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \ |
| 1124 reset(); \ |
| 1125 } while (0) |
| 1126 |
| 1127 #define TestImplSXmmAddr(Dst, Inst, Size) \ |
| 1128 do { \ |
| 1129 static constexpr char TestString[] = \ |
| 1130 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \ |
| 1131 const uint32_t T0 = allocateDqword(); \ |
| 1132 const uint32_t T1 = allocateDword(); \ |
| 1133 \ |
| 1134 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1135 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1136 dwordAddress(T1)); \ |
| 1137 \ |
| 1138 AssembledTest test = assemble(); \ |
| 1139 test.setDqwordTo(T0, Inst##Size##DstValue); \ |
| 1140 test.setDwordTo(T1, Inst##Size##SrcValue); \ |
| 1141 test.run(); \ |
| 1142 \ |
| 1143 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \ |
| 1144 reset(); \ |
| 1145 } while (0) |
| 1146 |
| 1147 #define TestImplSRegAddr(GPR, Inst, Size) \ |
| 1148 do { \ |
| 1149 static constexpr char TestString[] = \ |
| 1150 "(" #GPR ", Addr, cvt" #Inst ", f" #Size ")"; \ |
| 1151 const uint32_t T0 = allocateDqword(); \ |
| 1152 \ |
| 1153 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \ |
| 1154 Immediate(Inst##Size##DstValue)); \ |
| 1155 __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \ |
| 1156 dwordAddress(T0)); \ |
| 1157 \ |
| 1158 AssembledTest test = assemble(); \ |
| 1159 test.setDqwordTo(T0, Inst##Size##SrcValue); \ |
| 1160 test.run(); \ |
| 1161 \ |
| 1162 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \ |
| 1163 << TestString; \ |
| 1164 reset(); \ |
| 1165 } while (0) |
| 1166 |
| 1167 #define TestImplSize(Dst, Src, GPR, Size) \ |
| 1168 do { \ |
| 1169 TestImplPXmmXmm(Dst, Src, dq2ps, Size); \ |
| 1170 TestImplPXmmAddr(Src, dq2ps, Size); \ |
| 1171 TestImplPXmmXmm(Dst, Src, tps2dq, Size); \ |
| 1172 TestImplPXmmAddr(Src, tps2dq, Size); \ |
| 1173 TestImplSXmmReg(Dst, GPR, si2ss, Size); \ |
| 1174 TestImplSXmmAddr(Dst, si2ss, Size); \ |
| 1175 TestImplSRegXmm(GPR, Src, tss2si, Size); \ |
| 1176 TestImplSRegAddr(GPR, tss2si, Size); \ |
| 1177 TestImplPXmmXmm(Dst, Src, float2float, Size); \ |
| 1178 TestImplPXmmAddr(Src, float2float, Size); \ |
| 1179 } while (0) |
| 1180 |
| 1181 #define TestImpl(Dst, Src, GPR) \ |
| 1182 do { \ |
| 1183 TestImplSize(Dst, Src, GPR, 32); \ |
| 1184 TestImplSize(Dst, Src, GPR, 64); \ |
| 1185 } while (0) |
| 1186 |
| 1187 TestImpl(xmm0, xmm1, eax); |
| 1188 TestImpl(xmm1, xmm2, ebx); |
| 1189 TestImpl(xmm2, xmm3, ecx); |
| 1190 TestImpl(xmm3, xmm4, edx); |
| 1191 TestImpl(xmm4, xmm5, esi); |
| 1192 TestImpl(xmm5, xmm6, edi); |
| 1193 TestImpl(xmm6, xmm7, eax); |
| 1194 TestImpl(xmm7, xmm0, ebx); |
| 1195 |
| 1196 #undef TestImpl |
| 1197 #undef TestImplSize |
| 1198 #undef TestImplSRegAddr |
| 1199 #undef TestImplSXmmAddr |
| 1200 #undef TestImplPXmmAddr |
| 1201 #undef TestImplSRegXmm |
| 1202 #undef TestImplSXmmReg |
| 1203 #undef TestImplPXmmXmm |
| 1204 } |
| 1205 |
| 1206 TEST_F(AssemblerX8632Test, Ucomiss) { |
| 1207 static constexpr float qnan32 = std::numeric_limits<float>::quiet_NaN(); |
| 1208 static constexpr double qnan64 = std::numeric_limits<float>::quiet_NaN(); |
| 1209 |
| 1210 Dqword test32DstValue(0.0, qnan32, qnan32, qnan32); |
| 1211 Dqword test32SrcValue(0.0, qnan32, qnan32, qnan32); |
| 1212 |
| 1213 Dqword test64DstValue(0.0, qnan64); |
| 1214 Dqword test64SrcValue(0.0, qnan64); |
| 1215 |
| 1216 #define TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, \ |
| 1217 BOther) \ |
| 1218 do { \ |
| 1219 static constexpr char NearBranch = AssemblerX8632::kNearJump; \ |
| 1220 static constexpr char TestString[] = \ |
| 1221 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #CompType \ |
| 1222 ", " #BParity ", " #BOther ")"; \ |
| 1223 const uint32_t T0 = allocateDqword(); \ |
| 1224 test##Size##DstValue.F##Size[0] = Value0; \ |
| 1225 const uint32_t T1 = allocateDqword(); \ |
| 1226 test##Size##SrcValue.F##Size[0] = Value1; \ |
| 1227 const uint32_t ImmIfTrue = 0xBEEF; \ |
| 1228 const uint32_t ImmIfFalse = 0xC0FFE; \ |
| 1229 \ |
| 1230 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1231 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 1232 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \ |
| 1233 __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1234 XmmRegister::Encoded_Reg_##Src); \ |
| 1235 Label Done; \ |
| 1236 __ j(Cond::Br_##BParity, &Done, NearBranch); \ |
| 1237 __ j(Cond::Br_##BOther, &Done, NearBranch); \ |
| 1238 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \ |
| 1239 __ bind(&Done); \ |
| 1240 \ |
| 1241 AssembledTest test = assemble(); \ |
| 1242 test.setDqwordTo(T0, test##Size##DstValue); \ |
| 1243 test.setDqwordTo(T1, test##Size##SrcValue); \ |
| 1244 test.run(); \ |
| 1245 \ |
| 1246 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \ |
| 1247 reset(); \ |
| 1248 } while (0) |
| 1249 |
| 1250 #define TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther) \ |
| 1251 do { \ |
| 1252 static constexpr char NearBranch = AssemblerX8632::kNearJump; \ |
| 1253 static constexpr char TestString[] = \ |
| 1254 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #CompType \ |
| 1255 ", " #BParity ", " #BOther ")"; \ |
| 1256 const uint32_t T0 = allocateDqword(); \ |
| 1257 test##Size##DstValue.F##Size[0] = Value0; \ |
| 1258 const uint32_t T1 = allocateDqword(); \ |
| 1259 test##Size##SrcValue.F##Size[0] = Value1; \ |
| 1260 const uint32_t ImmIfTrue = 0xBEEF; \ |
| 1261 const uint32_t ImmIfFalse = 0xC0FFE; \ |
| 1262 \ |
| 1263 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1264 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \ |
| 1265 __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1266 dwordAddress(T1)); \ |
| 1267 Label Done; \ |
| 1268 __ j(Cond::Br_##BParity, &Done, NearBranch); \ |
| 1269 __ j(Cond::Br_##BOther, &Done, NearBranch); \ |
| 1270 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \ |
| 1271 __ bind(&Done); \ |
| 1272 \ |
| 1273 AssembledTest test = assemble(); \ |
| 1274 test.setDqwordTo(T0, test##Size##DstValue); \ |
| 1275 test.setDqwordTo(T1, test##Size##SrcValue); \ |
| 1276 test.run(); \ |
| 1277 \ |
| 1278 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \ |
| 1279 reset(); \ |
| 1280 } while (0) |
| 1281 |
| 1282 #define TestImplCond(Dst, Value0, Src, Value1, Size, CompType, BParity, \ |
| 1283 BOther) \ |
| 1284 do { \ |
| 1285 TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, BOther); \ |
| 1286 TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther); \ |
| 1287 } while (0) |
| 1288 |
| 1289 #define TestImplSize(Dst, Src, Size) \ |
| 1290 do { \ |
| 1291 TestImplCond(Dst, 1.0, Src, 1.0, Size, isEq, p, ne); \ |
| 1292 TestImplCond(Dst, 1.0, Src, 2.0, Size, isNe, p, e); \ |
| 1293 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLe, p, a); \ |
| 1294 TestImplCond(Dst, 1.0, Src, 1.0, Size, isLe, p, a); \ |
| 1295 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLt, p, ae); \ |
| 1296 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGe, p, b); \ |
| 1297 TestImplCond(Dst, 1.0, Src, 1.0, Size, isGe, p, b); \ |
| 1298 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGt, p, be); \ |
| 1299 TestImplCond(Dst, qnan##Size, Src, 1.0, Size, isUnord, np, o); \ |
| 1300 TestImplCond(Dst, 1.0, Src, qnan##Size, Size, isUnord, np, s); \ |
| 1301 TestImplCond(Dst, qnan##Size, Src, qnan##Size, Size, isUnord, np, s); \ |
| 1302 } while (0) |
| 1303 |
| 1304 #define TestImpl(Dst, Src) \ |
| 1305 do { \ |
| 1306 TestImplSize(Dst, Src, 32); \ |
| 1307 TestImplSize(Dst, Src, 64); \ |
| 1308 } while (0) |
| 1309 |
| 1310 TestImpl(xmm0, xmm1); |
| 1311 TestImpl(xmm1, xmm2); |
| 1312 TestImpl(xmm2, xmm3); |
| 1313 TestImpl(xmm3, xmm4); |
| 1314 TestImpl(xmm4, xmm5); |
| 1315 TestImpl(xmm5, xmm6); |
| 1316 TestImpl(xmm6, xmm7); |
| 1317 TestImpl(xmm7, xmm0); |
| 1318 |
| 1319 #undef TestImpl |
| 1320 #undef TestImplSize |
| 1321 #undef TestImplCond |
| 1322 #undef TestImplXmmAddr |
| 1323 #undef TestImplXmmXmm |
| 1324 } |
| 1325 |
| 1326 TEST_F(AssemblerX8632Test, Sqrtss) { |
| 1327 Dqword test32SrcValue(-100.0, -100.0, -100.0, -100.0); |
| 1328 Dqword test32DstValue(-1.0, -1.0, -1.0, -1.0); |
| 1329 |
| 1330 Dqword test64SrcValue(-100.0, -100.0); |
| 1331 Dqword test64DstValue(-1.0, -1.0); |
| 1332 |
| 1333 #define TestSqrtssXmmXmm(Dst, Src, Value1, Result, Size) \ |
| 1334 do { \ |
| 1335 static constexpr char TestString[] = \ |
| 1336 "(" #Dst ", " #Src ", " #Value1 ", " #Result ", " #Size ")"; \ |
| 1337 const uint32_t T0 = allocateDqword(); \ |
| 1338 test##Size##SrcValue.F##Size[0] = Value1; \ |
| 1339 const uint32_t T1 = allocateDqword(); \ |
| 1340 \ |
| 1341 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 1342 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 1343 __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1344 XmmRegister::Encoded_Reg_##Src); \ |
| 1345 \ |
| 1346 AssembledTest test = assemble(); \ |
| 1347 test.setDqwordTo(T0, test##Size##SrcValue); \ |
| 1348 test.setDqwordTo(T1, test##Size##DstValue); \ |
| 1349 test.run(); \ |
| 1350 \ |
| 1351 Dqword Expected = test##Size##DstValue; \ |
| 1352 Expected.F##Size[0] = Result; \ |
| 1353 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1354 reset(); \ |
| 1355 } while (0) |
| 1356 |
| 1357 #define TestSqrtssXmmAddr(Dst, Value1, Result, Size) \ |
| 1358 do { \ |
| 1359 static constexpr char TestString[] = \ |
| 1360 "(" #Dst ", Addr, " #Value1 ", " #Result ", " #Size ")"; \ |
| 1361 const uint32_t T0 = allocateDqword(); \ |
| 1362 test##Size##SrcValue.F##Size[0] = Value1; \ |
| 1363 const uint32_t T1 = allocateDqword(); \ |
| 1364 \ |
| 1365 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 1366 __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1367 dwordAddress(T0)); \ |
| 1368 \ |
| 1369 AssembledTest test = assemble(); \ |
| 1370 test.setDqwordTo(T0, test##Size##SrcValue); \ |
| 1371 test.setDqwordTo(T1, test##Size##DstValue); \ |
| 1372 test.run(); \ |
| 1373 \ |
| 1374 Dqword Expected = test##Size##DstValue; \ |
| 1375 Expected.F##Size[0] = Result; \ |
| 1376 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1377 reset(); \ |
| 1378 } while (0) |
| 1379 |
| 1380 #define TestSqrtssSize(Dst, Src, Size) \ |
| 1381 do { \ |
| 1382 TestSqrtssXmmXmm(Dst, Src, 4.0, 2.0, Size); \ |
| 1383 TestSqrtssXmmAddr(Dst, 4.0, 2.0, Size); \ |
| 1384 TestSqrtssXmmXmm(Dst, Src, 9.0, 3.0, Size); \ |
| 1385 TestSqrtssXmmAddr(Dst, 9.0, 3.0, Size); \ |
| 1386 TestSqrtssXmmXmm(Dst, Src, 100.0, 10.0, Size); \ |
| 1387 TestSqrtssXmmAddr(Dst, 100.0, 10.0, Size); \ |
| 1388 } while (0) |
| 1389 |
| 1390 #define TestSqrtss(Dst, Src) \ |
| 1391 do { \ |
| 1392 TestSqrtssSize(Dst, Src, 32); \ |
| 1393 TestSqrtssSize(Dst, Src, 64); \ |
| 1394 } while (0) |
| 1395 |
| 1396 TestSqrtss(xmm0, xmm1); |
| 1397 TestSqrtss(xmm1, xmm2); |
| 1398 TestSqrtss(xmm2, xmm3); |
| 1399 TestSqrtss(xmm3, xmm4); |
| 1400 TestSqrtss(xmm4, xmm5); |
| 1401 TestSqrtss(xmm5, xmm6); |
| 1402 TestSqrtss(xmm6, xmm7); |
| 1403 TestSqrtss(xmm7, xmm0); |
| 1404 |
| 1405 #undef TestSqrtss |
| 1406 #undef TestSqrtssSize |
| 1407 #undef TestSqrtssXmmAddr |
| 1408 #undef TestSqrtssXmmXmm |
| 1409 } |
| 1410 |
| 1411 TEST_F(AssemblerX8632Test, Insertps) { |
| 1412 #define TestInsertpsXmmXmmImm(Dst, Value0, Src, Value1, Imm, Expected) \ |
| 1413 do { \ |
| 1414 static constexpr char TestString[] = \ |
| 1415 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Imm ", " #Expected \ |
| 1416 ")"; \ |
| 1417 const uint32_t T0 = allocateDqword(); \ |
| 1418 const Dqword V0 Value0; \ |
| 1419 const uint32_t T1 = allocateDqword(); \ |
| 1420 const Dqword V1 Value1; \ |
| 1421 \ |
| 1422 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1423 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 1424 __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##Dst, \ |
| 1425 XmmRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 1426 \ |
| 1427 AssembledTest test = assemble(); \ |
| 1428 test.setDqwordTo(T0, V0); \ |
| 1429 test.setDqwordTo(T1, V1); \ |
| 1430 test.run(); \ |
| 1431 \ |
| 1432 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \ |
| 1433 reset(); \ |
| 1434 } while (0) |
| 1435 |
| 1436 #define TestInsertpsXmmAddrImm(Dst, Value0, Value1, Imm, Expected) \ |
| 1437 do { \ |
| 1438 static constexpr char TestString[] = \ |
| 1439 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Expected ")"; \ |
| 1440 const uint32_t T0 = allocateDqword(); \ |
| 1441 const Dqword V0 Value0; \ |
| 1442 const uint32_t T1 = allocateDqword(); \ |
| 1443 const Dqword V1 Value1; \ |
| 1444 \ |
| 1445 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1446 __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##Dst, \ |
| 1447 dwordAddress(T1), Immediate(Imm)); \ |
| 1448 \ |
| 1449 AssembledTest test = assemble(); \ |
| 1450 test.setDqwordTo(T0, V0); \ |
| 1451 test.setDqwordTo(T1, V1); \ |
| 1452 test.run(); \ |
| 1453 \ |
| 1454 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \ |
| 1455 reset(); \ |
| 1456 } while (0) |
| 1457 |
| 1458 #define TestInsertps(Dst, Src) \ |
| 1459 do { \ |
| 1460 TestInsertpsXmmXmmImm( \ |
| 1461 Dst, (uint64_t(-1), uint64_t(-1)), Src, \ |
| 1462 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \ |
| 1463 0x99, \ |
| 1464 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x00000000FFFFFFFFull))); \ |
| 1465 TestInsertpsXmmAddrImm( \ |
| 1466 Dst, (uint64_t(-1), uint64_t(-1)), \ |
| 1467 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \ |
| 1468 0x99, \ |
| 1469 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x00000000FFFFFFFFull))); \ |
| 1470 TestInsertpsXmmXmmImm( \ |
| 1471 Dst, (uint64_t(-1), uint64_t(-1)), Src, \ |
| 1472 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \ |
| 1473 0x9D, \ |
| 1474 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x0000000000000000ull))); \ |
| 1475 TestInsertpsXmmAddrImm( \ |
| 1476 Dst, (uint64_t(-1), uint64_t(-1)), \ |
| 1477 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \ |
| 1478 0x9D, \ |
| 1479 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x0000000000000000ull))); \ |
| 1480 } while (0) |
| 1481 |
| 1482 TestInsertps(xmm0, xmm1); |
| 1483 TestInsertps(xmm1, xmm2); |
| 1484 TestInsertps(xmm2, xmm3); |
| 1485 TestInsertps(xmm3, xmm4); |
| 1486 TestInsertps(xmm4, xmm5); |
| 1487 TestInsertps(xmm5, xmm6); |
| 1488 TestInsertps(xmm6, xmm7); |
| 1489 TestInsertps(xmm7, xmm0); |
| 1490 |
| 1491 #undef TestInsertps |
| 1492 #undef TestInsertpsXmmXmmAddr |
| 1493 #undef TestInsertpsXmmXmmImm |
| 1494 } |
| 1495 |
| 1496 TEST_F(AssemblerX8632Test, Pinsr) { |
| 1497 static constexpr uint8_t Mask32 = 0x03; |
| 1498 static constexpr uint8_t Mask16 = 0x07; |
| 1499 static constexpr uint8_t Mask8 = 0x0F; |
| 1500 |
| 1501 #define TestPinsrXmmGPRImm(Dst, Value0, GPR, Value1, Imm, Size) \ |
| 1502 do { \ |
| 1503 static constexpr char TestString[] = \ |
| 1504 "(" #Dst ", " #Value0 ", " #GPR ", " #Value1 ", " #Imm ", " #Size ")"; \ |
| 1505 const uint32_t T0 = allocateDqword(); \ |
| 1506 const Dqword V0 Value0; \ |
| 1507 \ |
| 1508 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1509 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, Immediate(Value1)); \ |
| 1510 __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1511 GPRRegister::Encoded_Reg_##GPR, Immediate(Imm)); \ |
| 1512 \ |
| 1513 AssembledTest test = assemble(); \ |
| 1514 test.setDqwordTo(T0, V0); \ |
| 1515 test.run(); \ |
| 1516 \ |
| 1517 constexpr uint8_t sel = (Imm)&Mask##Size; \ |
| 1518 Dqword Expected = V0; \ |
| 1519 Expected.U##Size[sel] = Value1; \ |
| 1520 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1521 reset(); \ |
| 1522 } while (0) |
| 1523 |
| 1524 #define TestPinsrXmmAddrImm(Dst, Value0, Value1, Imm, Size) \ |
| 1525 do { \ |
| 1526 static constexpr char TestString[] = \ |
| 1527 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Size ")"; \ |
| 1528 const uint32_t T0 = allocateDqword(); \ |
| 1529 const Dqword V0 Value0; \ |
| 1530 const uint32_t T1 = allocateDword(); \ |
| 1531 const uint32_t V1 = Value1; \ |
| 1532 \ |
| 1533 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1534 __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1535 dwordAddress(T1), Immediate(Imm)); \ |
| 1536 \ |
| 1537 AssembledTest test = assemble(); \ |
| 1538 test.setDqwordTo(T0, V0); \ |
| 1539 test.setDwordTo(T1, V1); \ |
| 1540 test.run(); \ |
| 1541 \ |
| 1542 constexpr uint8_t sel = (Imm)&Mask##Size; \ |
| 1543 Dqword Expected = V0; \ |
| 1544 Expected.U##Size[sel] = Value1; \ |
| 1545 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1546 reset(); \ |
| 1547 } while (0) |
| 1548 |
| 1549 #define TestPinsrSize(Dst, GPR, Value1, Imm, Size) \ |
| 1550 do { \ |
| 1551 TestPinsrXmmGPRImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 1552 uint64_t(0xFFFFFFFFDDDDDDDDull)), \ |
| 1553 GPR, Value1, Imm, Size); \ |
| 1554 TestPinsrXmmAddrImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 1555 uint64_t(0xFFFFFFFFDDDDDDDDull)), \ |
| 1556 Value1, Imm, Size); \ |
| 1557 } while (0) |
| 1558 |
| 1559 #define TestPinsr(Src, Dst) \ |
| 1560 do { \ |
| 1561 TestPinsrSize(Src, Dst, 0xEE, 0x03, 8); \ |
| 1562 TestPinsrSize(Src, Dst, 0xFFEE, 0x03, 16); \ |
| 1563 TestPinsrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \ |
| 1564 } while (0) |
| 1565 |
| 1566 TestPinsr(xmm0, eax); |
| 1567 TestPinsr(xmm1, ebx); |
| 1568 TestPinsr(xmm2, ecx); |
| 1569 TestPinsr(xmm3, edx); |
| 1570 TestPinsr(xmm4, esi); |
| 1571 TestPinsr(xmm5, edi); |
| 1572 TestPinsr(xmm6, eax); |
| 1573 TestPinsr(xmm7, ebx); |
| 1574 |
| 1575 #undef TestPinsr |
| 1576 #undef TestPinsrSize |
| 1577 #undef TestPinsrXmmAddrImm |
| 1578 #undef TestPinsrXmmGPRImm |
| 1579 } |
| 1580 |
| 1581 TEST_F(AssemblerX8632Test, Pextr) { |
| 1582 static constexpr uint8_t Mask32 = 0x03; |
| 1583 static constexpr uint8_t Mask16 = 0x07; |
| 1584 static constexpr uint8_t Mask8 = 0x0F; |
| 1585 |
| 1586 #define TestPextrGPRXmmImm(GPR, Src, Value1, Imm, Size) \ |
| 1587 do { \ |
| 1588 static constexpr char TestString[] = \ |
| 1589 "(" #GPR ", " #Src ", " #Value1 ", " #Imm ", " #Size ")"; \ |
| 1590 const uint32_t T0 = allocateDqword(); \ |
| 1591 const Dqword V0 Value1; \ |
| 1592 \ |
| 1593 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 1594 __ pextr(IceType_i##Size, GPRRegister::Encoded_Reg_##GPR, \ |
| 1595 XmmRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 1596 \ |
| 1597 AssembledTest test = assemble(); \ |
| 1598 test.setDqwordTo(T0, V0); \ |
| 1599 test.run(); \ |
| 1600 \ |
| 1601 constexpr uint8_t sel = (Imm)&Mask##Size; \ |
| 1602 ASSERT_EQ(V0.U##Size[sel], test.GPR()) << TestString; \ |
| 1603 reset(); \ |
| 1604 } while (0) |
| 1605 |
| 1606 #define TestPextrSize(GPR, Src, Value1, Imm, Size) \ |
| 1607 do { \ |
| 1608 TestPextrGPRXmmImm(GPR, Src, (uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 1609 uint64_t(0xFFFFFFFFDDDDDDDDull)), \ |
| 1610 Imm, Size); \ |
| 1611 } while (0) |
| 1612 |
| 1613 #define TestPextr(Src, Dst) \ |
| 1614 do { \ |
| 1615 TestPextrSize(Src, Dst, 0xEE, 0x03, 8); \ |
| 1616 TestPextrSize(Src, Dst, 0xFFEE, 0x03, 16); \ |
| 1617 TestPextrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \ |
| 1618 } while (0) |
| 1619 |
| 1620 TestPextr(eax, xmm0); |
| 1621 TestPextr(ebx, xmm1); |
| 1622 TestPextr(ecx, xmm2); |
| 1623 TestPextr(edx, xmm3); |
| 1624 TestPextr(esi, xmm4); |
| 1625 TestPextr(edi, xmm5); |
| 1626 TestPextr(eax, xmm6); |
| 1627 TestPextr(ebx, xmm7); |
| 1628 |
| 1629 #undef TestPextr |
| 1630 #undef TestPextrSize |
| 1631 #undef TestPextrXmmGPRImm |
| 1632 } |
| 1633 |
| 1634 TEST_F(AssemblerX8632Test, Pcmpeq_Pcmpgt) { |
| 1635 #define TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, Inst, Op) \ |
| 1636 do { \ |
| 1637 static constexpr char TestString[] = \ |
| 1638 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #Op ")"; \ |
| 1639 const uint32_t T0 = allocateDqword(); \ |
| 1640 const Dqword V0 Value0; \ |
| 1641 const uint32_t T1 = allocateDqword(); \ |
| 1642 const Dqword V1 Value1; \ |
| 1643 \ |
| 1644 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1645 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 1646 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1647 XmmRegister::Encoded_Reg_##Src); \ |
| 1648 \ |
| 1649 AssembledTest test = assemble(); \ |
| 1650 test.setDqwordTo(T0, V0); \ |
| 1651 test.setDqwordTo(T1, V1); \ |
| 1652 test.run(); \ |
| 1653 \ |
| 1654 Dqword Expected(uint64_t(0), uint64_t(0)); \ |
| 1655 static constexpr uint8_t ArraySize = \ |
| 1656 sizeof(Dqword) / sizeof(uint##Size##_t); \ |
| 1657 for (uint8_t i = 0; i < ArraySize; ++i) { \ |
| 1658 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \ |
| 1659 } \ |
| 1660 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1661 reset(); \ |
| 1662 } while (0) |
| 1663 |
| 1664 #define TestPcmpXmmAddr(Dst, Value0, Value1, Size, Inst, Op) \ |
| 1665 do { \ |
| 1666 static constexpr char TestString[] = \ |
| 1667 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #Op ")"; \ |
| 1668 const uint32_t T0 = allocateDqword(); \ |
| 1669 const Dqword V0 Value0; \ |
| 1670 const uint32_t T1 = allocateDqword(); \ |
| 1671 const Dqword V1 Value1; \ |
| 1672 \ |
| 1673 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1674 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \ |
| 1675 dwordAddress(T1)); \ |
| 1676 \ |
| 1677 AssembledTest test = assemble(); \ |
| 1678 test.setDqwordTo(T0, V0); \ |
| 1679 test.setDqwordTo(T1, V1); \ |
| 1680 test.run(); \ |
| 1681 \ |
| 1682 Dqword Expected(uint64_t(0), uint64_t(0)); \ |
| 1683 static constexpr uint8_t ArraySize = \ |
| 1684 sizeof(Dqword) / sizeof(uint##Size##_t); \ |
| 1685 for (uint8_t i = 0; i < ArraySize; ++i) { \ |
| 1686 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \ |
| 1687 } \ |
| 1688 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1689 reset(); \ |
| 1690 } while (0) |
| 1691 |
| 1692 #define TestPcmpValues(Dst, Value0, Src, Value1, Size) \ |
| 1693 do { \ |
| 1694 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpeq, == ); \ |
| 1695 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpeq, == ); \ |
| 1696 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpgt, < ); \ |
| 1697 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpgt, < ); \ |
| 1698 } while (0) |
| 1699 |
| 1700 #define TestPcmpSize(Dst, Src, Size) \ |
| 1701 do { \ |
| 1702 TestPcmpValues(Dst, (uint64_t(0x8888888888888888ull), \ |
| 1703 uint64_t(0x0000000000000000ull)), \ |
| 1704 Src, (uint64_t(0x0000008800008800ull), \ |
| 1705 uint64_t(0xFFFFFFFFFFFFFFFFull)), \ |
| 1706 Size); \ |
| 1707 TestPcmpValues(Dst, (uint64_t(0x123567ABAB55DE01ull), \ |
| 1708 uint64_t(0x12345abcde12345Aull)), \ |
| 1709 Src, (uint64_t(0x0000008800008800ull), \ |
| 1710 uint64_t(0xAABBCCDD1234321Aull)), \ |
| 1711 Size); \ |
| 1712 } while (0) |
| 1713 |
| 1714 #define TestPcmp(Dst, Src) \ |
| 1715 do { \ |
| 1716 TestPcmpSize(xmm0, xmm1, 8); \ |
| 1717 TestPcmpSize(xmm0, xmm1, 16); \ |
| 1718 TestPcmpSize(xmm0, xmm1, 32); \ |
| 1719 } while (0) |
| 1720 |
| 1721 TestPcmp(xmm0, xmm1); |
| 1722 TestPcmp(xmm1, xmm2); |
| 1723 TestPcmp(xmm2, xmm3); |
| 1724 TestPcmp(xmm3, xmm4); |
| 1725 TestPcmp(xmm4, xmm5); |
| 1726 TestPcmp(xmm5, xmm6); |
| 1727 TestPcmp(xmm6, xmm7); |
| 1728 TestPcmp(xmm7, xmm0); |
| 1729 |
| 1730 #undef TestPcmp |
| 1731 #undef TestPcmpSize |
| 1732 #undef TestPcmpValues |
| 1733 #undef TestPcmpXmmAddr |
| 1734 #undef TestPcmpXmmXmm |
| 1735 } |
| 1736 |
| 1737 TEST_F(AssemblerX8632Test, Roundsd) { |
| 1738 #define TestRoundsdXmmXmm(Dst, Src, Mode, Input, RN) \ |
| 1739 do { \ |
| 1740 static constexpr char TestString[] = \ |
| 1741 "(" #Dst ", " #Src ", " #Mode ", " #Input ", " #RN ")"; \ |
| 1742 const uint32_t T0 = allocateDqword(); \ |
| 1743 const Dqword V0(-3.0, -3.0); \ |
| 1744 const uint32_t T1 = allocateDqword(); \ |
| 1745 const Dqword V1(double(Input), -123.4); \ |
| 1746 \ |
| 1747 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 1748 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 1749 __ roundsd(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \ |
| 1750 AssemblerX8632::k##Mode); \ |
| 1751 \ |
| 1752 AssembledTest test = assemble(); \ |
| 1753 test.setDqwordTo(T0, V0); \ |
| 1754 test.setDqwordTo(T1, V1); \ |
| 1755 test.run(); \ |
| 1756 \ |
| 1757 const Dqword Expected(double(RN), -3.0); \ |
| 1758 EXPECT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1759 reset(); \ |
| 1760 } while (0) |
| 1761 |
| 1762 #define TestRoundsd(Dst, Src) \ |
| 1763 do { \ |
| 1764 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.51, 6); \ |
| 1765 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.49, 5); \ |
| 1766 TestRoundsdXmmXmm(Dst, Src, RoundDown, 5.51, 5); \ |
| 1767 TestRoundsdXmmXmm(Dst, Src, RoundUp, 5.49, 6); \ |
| 1768 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.49, 5); \ |
| 1769 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.51, 5); \ |
| 1770 } while (0) |
| 1771 |
| 1772 TestRoundsd(xmm0, xmm1); |
| 1773 TestRoundsd(xmm1, xmm2); |
| 1774 TestRoundsd(xmm2, xmm3); |
| 1775 TestRoundsd(xmm3, xmm4); |
| 1776 TestRoundsd(xmm4, xmm5); |
| 1777 TestRoundsd(xmm5, xmm6); |
| 1778 TestRoundsd(xmm6, xmm7); |
| 1779 TestRoundsd(xmm7, xmm0); |
| 1780 |
| 1781 #undef TestRoundsd |
| 1782 #undef TestRoundsdXmmXmm |
| 1783 } |
| 1784 |
| 1785 TEST_F(AssemblerX8632Test, Set1ps) { |
| 1786 #define TestImpl(Xmm, Src, Imm) \ |
| 1787 do { \ |
| 1788 __ set1ps(XmmRegister::Encoded_Reg_##Xmm, GPRRegister::Encoded_Reg_##Src, \ |
| 1789 Immediate(Imm)); \ |
| 1790 \ |
| 1791 AssembledTest test = assemble(); \ |
| 1792 test.run(); \ |
| 1793 \ |
| 1794 const Dqword Expected((uint64_t(Imm) << 32) | uint32_t(Imm), \ |
| 1795 (uint64_t(Imm) << 32) | uint32_t(Imm)); \ |
| 1796 ASSERT_EQ(Expected, test.Xmm<Dqword>()) \ |
| 1797 << "(" #Xmm ", " #Src ", " #Imm ")"; \ |
| 1798 reset(); \ |
| 1799 } while (0) |
| 1800 |
| 1801 TestImpl(xmm0, ebx, 1); |
| 1802 TestImpl(xmm1, ecx, 2); |
| 1803 TestImpl(xmm2, edx, 3); |
| 1804 TestImpl(xmm3, esi, 4); |
| 1805 TestImpl(xmm4, edi, 5); |
| 1806 TestImpl(xmm5, eax, 6); |
| 1807 TestImpl(xmm6, ebx, 7); |
| 1808 TestImpl(xmm7, ecx, 8); |
| 1809 |
| 1810 #undef TestImpl |
| 1811 } |
| 1812 |
| 1813 } // end of anonymous namespace |
| 1814 } // end of namespace Test |
| 1815 } // end of namespace X8632 |
| 1816 } // end of namespace Ice |
| OLD | NEW |