1//===- subzero/unittest/AssemblerX8632/DataMov.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 11namespace Ice { 12namespace X8632 { 13namespace Test { 14namespace { 15 16TEST_F(AssemblerX8632Test, MovRegImm) { 17 constexpr uint32_t ExpectedEax = 0x000000FFul; 18 constexpr uint32_t ExpectedEbx = 0x0000FF00ul; 19 constexpr uint32_t ExpectedEcx = 0x00FF0000ul; 20 constexpr uint32_t ExpectedEdx = 0xFF000000ul; 21 constexpr uint32_t ExpectedEdi = 0x6AAA0006ul; 22 constexpr uint32_t ExpectedEsi = 0x6000AAA6ul; 23 24 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedEax)); 25 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedEbx)); 26 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedEcx)); 27 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedEdx)); 28 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedEdi)); 29 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedEsi)); 30 31 AssembledTest test = assemble(); 32 test.run(); 33 EXPECT_EQ(ExpectedEax, test.eax()); 34 EXPECT_EQ(ExpectedEbx, test.ebx()); 35 EXPECT_EQ(ExpectedEcx, test.ecx()); 36 EXPECT_EQ(ExpectedEdx, test.edx()); 37 EXPECT_EQ(ExpectedEdi, test.edi()); 38 EXPECT_EQ(ExpectedEsi, test.esi()); 39} 40 41TEST_F(AssemblerX8632Test, MovMemImm) { 42 const uint32_t T0 = allocateDword(); 43 constexpr uint32_t ExpectedT0 = 0x00111100ul; 44 const uint32_t T1 = allocateDword(); 45 constexpr uint32_t ExpectedT1 = 0x00222200ul; 46 const uint32_t T2 = allocateDword(); 47 constexpr uint32_t ExpectedT2 = 0x03333000ul; 48 const uint32_t T3 = allocateDword(); 49 constexpr uint32_t ExpectedT3 = 0x00444400ul; 50 51 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); 52 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1)); 53 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2)); 54 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); 55 56 AssembledTest test = assemble(); 57 test.run(); 58 EXPECT_EQ(0ul, test.eax()); 59 EXPECT_EQ(0ul, test.ebx()); 60 EXPECT_EQ(0ul, test.ecx()); 61 EXPECT_EQ(0ul, test.edx()); 62 EXPECT_EQ(0ul, test.edi()); 63 EXPECT_EQ(0ul, test.esi()); 64 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); 65 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1)); 66 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2)); 67 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); 68} 69 70TEST_F(AssemblerX8632Test, MovMemReg) { 71 const uint32_t T0 = allocateDword(); 72 constexpr uint32_t ExpectedT0 = 0x00111100ul; 73 const uint32_t T1 = allocateDword(); 74 constexpr uint32_t ExpectedT1 = 0x00222200ul; 75 const uint32_t T2 = allocateDword(); 76 constexpr uint32_t ExpectedT2 = 0x00333300ul; 77 const uint32_t T3 = allocateDword(); 78 constexpr uint32_t ExpectedT3 = 0x00444400ul; 79 const uint32_t T4 = allocateDword(); 80 constexpr uint32_t ExpectedT4 = 0x00555500ul; 81 const uint32_t T5 = allocateDword(); 82 constexpr uint32_t ExpectedT5 = 0x00666600ul; 83 84 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedT0)); 85 __ mov(IceType_i32, dwordAddress(T0), GPRRegister::Encoded_Reg_eax); 86 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedT1)); 87 __ mov(IceType_i32, dwordAddress(T1), GPRRegister::Encoded_Reg_ebx); 88 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedT2)); 89 __ mov(IceType_i32, dwordAddress(T2), GPRRegister::Encoded_Reg_ecx); 90 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedT3)); 91 __ mov(IceType_i32, dwordAddress(T3), GPRRegister::Encoded_Reg_edx); 92 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedT4)); 93 __ mov(IceType_i32, dwordAddress(T4), GPRRegister::Encoded_Reg_edi); 94 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedT5)); 95 __ mov(IceType_i32, dwordAddress(T5), GPRRegister::Encoded_Reg_esi); 96 97 AssembledTest test = assemble(); 98 test.run(); 99 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); 100 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1)); 101 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2)); 102 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); 103 EXPECT_EQ(ExpectedT4, test.contentsOfDword(T4)); 104 EXPECT_EQ(ExpectedT5, test.contentsOfDword(T5)); 105} 106 107TEST_F(AssemblerX8632Test, MovRegReg) { 108 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x20)); 109 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, 110 GPRRegister::Encoded_Reg_eax); 111 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, 112 GPRRegister::Encoded_Reg_ebx); 113 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, 114 GPRRegister::Encoded_Reg_ecx); 115 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, 116 GPRRegister::Encoded_Reg_edx); 117 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, 118 GPRRegister::Encoded_Reg_edi); 119 120 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x55000000ul)); 121 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, 122 GPRRegister::Encoded_Reg_esi); 123 124 AssembledTest test = assemble(); 125 test.run(); 126 EXPECT_EQ(0x55000000ul, test.eax()); 127 EXPECT_EQ(0x20ul, test.ebx()); 128 EXPECT_EQ(0x20ul, test.ecx()); 129 EXPECT_EQ(0x20ul, test.edx()); 130 EXPECT_EQ(0x20ul, test.edi()); 131 EXPECT_EQ(0x55000000ul, test.esi()); 132} 133 134TEST_F(AssemblerX8632Test, MovRegMem) { 135 const uint32_t T0 = allocateDword(); 136 constexpr uint32_t ExpectedT0 = 0x00111100ul; 137 const uint32_t T1 = allocateDword(); 138 constexpr uint32_t ExpectedT1 = 0x00222200ul; 139 const uint32_t T2 = allocateDword(); 140 constexpr uint32_t ExpectedT2 = 0x00333300ul; 141 const uint32_t T3 = allocateDword(); 142 constexpr uint32_t ExpectedT3 = 0x00444400ul; 143 const uint32_t T4 = allocateDword(); 144 constexpr uint32_t ExpectedT4 = 0x00555500ul; 145 const uint32_t T5 = allocateDword(); 146 constexpr uint32_t ExpectedT5 = 0x00666600ul; 147 148 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); 149 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, dwordAddress(T0)); 150 151 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1)); 152 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, dwordAddress(T1)); 153 154 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2)); 155 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, dwordAddress(T2)); 156 157 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); 158 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, dwordAddress(T3)); 159 160 __ mov(IceType_i32, dwordAddress(T4), Immediate(ExpectedT4)); 161 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, dwordAddress(T4)); 162 163 __ mov(IceType_i32, dwordAddress(T5), Immediate(ExpectedT5)); 164 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, dwordAddress(T5)); 165 166 AssembledTest test = assemble(); 167 test.run(); 168 EXPECT_EQ(ExpectedT0, test.eax()); 169 EXPECT_EQ(ExpectedT1, test.ebx()); 170 EXPECT_EQ(ExpectedT2, test.ecx()); 171 EXPECT_EQ(ExpectedT3, test.edx()); 172 EXPECT_EQ(ExpectedT4, test.edi()); 173 EXPECT_EQ(ExpectedT5, test.esi()); 174} 175 176TEST_F(AssemblerX8632Test, Movzx) { 177#define TestMovzx8bitWithRegDest(Src, Dst, Imm) \ 178 do { \ 179 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ 180 __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ 181 __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, \ 182 GPRRegister::Encoded_Reg_##Src); \ 183 AssembledTest test = assemble(); \ 184 test.run(); \ 185 ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")"; \ 186 reset(); \ 187 } while (0) 188 189#define TestMovzx16bitWithRegDest(Src, Dst, Imm) \ 190 do { \ 191 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ 192 __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ 193 __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, \ 194 GPRRegister::Encoded_Reg_##Src); \ 195 AssembledTest test = assemble(); \ 196 test.run(); \ 197 ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")"; \ 198 reset(); \ 199 } while (0) 200 201#define TestMovzx8bitWithAddrSrc(Dst, Imm) \ 202 do { \ 203 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ 204 const uint32_t T0 = allocateDword(); \ 205 const uint32_t V0 = Imm; \ 206 __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 207 AssembledTest test = assemble(); \ 208 test.setDwordTo(T0, V0); \ 209 test.run(); \ 210 ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")"; \ 211 reset(); \ 212 } while (0) 213 214#define TestMovzx16bitWithAddrSrc(Dst, Imm) \ 215 do { \ 216 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ 217 const uint32_t T0 = allocateDword(); \ 218 const uint32_t V0 = Imm; \ 219 __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 220 AssembledTest test = assemble(); \ 221 test.setDwordTo(T0, V0); \ 222 test.run(); \ 223 ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")"; \ 224 reset(); \ 225 } while (0) 226 227#define TestMovzx(Dst) \ 228 do { \ 229 TestMovzx8bitWithRegDest(eax, Dst, 0x81u); \ 230 TestMovzx8bitWithRegDest(ebx, Dst, 0x82u); \ 231 TestMovzx8bitWithRegDest(ecx, Dst, 0x83u); \ 232 TestMovzx8bitWithRegDest(edx, Dst, 0x84u); \ 233 /* esi is encoded as dh */ \ 234 TestMovzx8bitWithRegDest(esi, Dst, 0x85u); \ 235 /* edi is encoded as bh */ \ 236 TestMovzx8bitWithRegDest(edi, Dst, 0x86u); \ 237 /* ebp is encoded as ch */ \ 238 TestMovzx8bitWithRegDest(ebp, Dst, 0x87u); \ 239 /* esp is encoded as ah */ \ 240 TestMovzx8bitWithRegDest(esp, Dst, 0x88u); \ 241 TestMovzx8bitWithAddrSrc(Dst, 0x8Fu); \ 242 \ 243 TestMovzx16bitWithRegDest(eax, Dst, 0x8118u); \ 244 TestMovzx16bitWithRegDest(ebx, Dst, 0x8228u); \ 245 TestMovzx16bitWithRegDest(ecx, Dst, 0x8338u); \ 246 TestMovzx16bitWithRegDest(edx, Dst, 0x8448u); \ 247 TestMovzx16bitWithAddrSrc(Dst, 0x8FF8u); \ 248 } while (0) 249 250 TestMovzx(eax); 251 TestMovzx(ebx); 252 TestMovzx(ecx); 253 TestMovzx(edx); 254 TestMovzx(esi); 255 TestMovzx(edi); 256 257#undef TestMovzx 258#undef TestMovzx16bitWithAddrDest 259#undef TestMovzx8bitWithAddrDest 260#undef TestMovzx16bitWithRegDest 261#undef TestMovzx8bitWithRegDest 262} 263 264TEST_F(AssemblerX8632Test, Movsx) { 265#define TestMovsx8bitWithRegDest(Src, Dst, Imm) \ 266 do { \ 267 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ 268 __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ 269 __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, \ 270 GPRRegister::Encoded_Reg_##Src); \ 271 AssembledTest test = assemble(); \ 272 test.run(); \ 273 ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst()) \ 274 << "(" #Src ", " #Dst ", " #Imm ")"; \ 275 reset(); \ 276 } while (0) 277 278#define TestMovsx16bitWithRegDest(Src, Dst, Imm) \ 279 do { \ 280 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ 281 __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ 282 __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, \ 283 GPRRegister::Encoded_Reg_##Src); \ 284 AssembledTest test = assemble(); \ 285 test.run(); \ 286 ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst()) \ 287 << "(" #Src ", " #Dst ", " #Imm ")"; \ 288 reset(); \ 289 } while (0) 290 291#define TestMovsx8bitWithAddrSrc(Dst, Imm) \ 292 do { \ 293 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ 294 const uint32_t T0 = allocateDword(); \ 295 const uint32_t V0 = Imm; \ 296 __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 297 AssembledTest test = assemble(); \ 298 test.setDwordTo(T0, V0); \ 299 test.run(); \ 300 ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst()) \ 301 << "(Addr, " #Dst ", " #Imm ")"; \ 302 reset(); \ 303 } while (0) 304 305#define TestMovsx16bitWithAddrSrc(Dst, Imm) \ 306 do { \ 307 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ 308 const uint32_t T0 = allocateDword(); \ 309 const uint32_t V0 = Imm; \ 310 __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 311 AssembledTest test = assemble(); \ 312 test.setDwordTo(T0, V0); \ 313 test.run(); \ 314 ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst()) \ 315 << "(Addr, " #Dst ", " #Imm ")"; \ 316 reset(); \ 317 } while (0) 318 319#define TestMovsx(Dst) \ 320 do { \ 321 TestMovsx8bitWithRegDest(eax, Dst, 0x81u); \ 322 TestMovsx8bitWithRegDest(ebx, Dst, 0x82u); \ 323 TestMovsx8bitWithRegDest(ecx, Dst, 0x83u); \ 324 TestMovsx8bitWithRegDest(edx, Dst, 0x84u); \ 325 /* esi is encoded as dh */ \ 326 TestMovsx8bitWithRegDest(esi, Dst, 0x85u); \ 327 /* edi is encoded as bh */ \ 328 TestMovsx8bitWithRegDest(edi, Dst, 0x86u); \ 329 /* ebp is encoded as ch */ \ 330 TestMovsx8bitWithRegDest(ebp, Dst, 0x87u); \ 331 /* esp is encoded as ah */ \ 332 TestMovsx8bitWithRegDest(esp, Dst, 0x88u); \ 333 TestMovsx8bitWithAddrSrc(Dst, 0x8Fu); \ 334 \ 335 TestMovsx16bitWithRegDest(eax, Dst, 0x8118u); \ 336 TestMovsx16bitWithRegDest(ebx, Dst, 0x8228u); \ 337 TestMovsx16bitWithRegDest(ecx, Dst, 0x8338u); \ 338 TestMovsx16bitWithRegDest(edx, Dst, 0x8448u); \ 339 TestMovsx16bitWithAddrSrc(Dst, 0x8FF8u); \ 340 } while (0) 341 342 TestMovsx(eax); 343 TestMovsx(ebx); 344 TestMovsx(ecx); 345 TestMovsx(edx); 346 TestMovsx(esi); 347 TestMovsx(edi); 348 349#undef TestMovsx 350#undef TestMovsx16bitWithAddrDest 351#undef TestMovsx8bitWithAddrDest 352#undef TestMovsx16bitWithRegDest 353#undef TestMovsx8bitWithRegDest 354} 355 356TEST_F(AssemblerX8632LowLevelTest, RepMovsb) { 357 __ rep_movsb(); 358 359 static constexpr uint32_t ByteCount = 2; 360 static constexpr uint8_t Prefix = 0xF3; 361 static constexpr uint8_t Opcode = 0xA4; 362 363 ASSERT_EQ(ByteCount, codeBytesSize()); 364 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode); 365} 366 367TEST_F(AssemblerX8632Test, MovssXmmAddr) { 368#define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \ 369 do { \ 370 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 371 "Invalid fp length #FloatLength"); \ 372 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 373 \ 374 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ 375 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 376 const uint32_t T0 = allocateQword(); \ 377 const Type V0 = Value; \ 378 \ 379 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm, \ 380 dwordAddress(T0)); \ 381 \ 382 AssembledTest test = assemble(); \ 383 if (IsDouble) { \ 384 test.setQwordTo(T0, static_cast<double>(V0)); \ 385 } else { \ 386 test.setDwordTo(T0, static_cast<float>(V0)); \ 387 } \ 388 test.run(); \ 389 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ 390 << Value; \ 391 reset(); \ 392 } while (0) 393 394#define TestMovssXmmAddr(FloatLength) \ 395 do { \ 396 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 397 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 398 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \ 399 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \ 400 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \ 401 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \ 402 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \ 403 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \ 404 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \ 405 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \ 406 } \ 407 } while (0) 408 409 TestMovssXmmAddr(32); 410 TestMovssXmmAddr(64); 411 412#undef TestMovssXmmAddr 413#undef TestMovssXmmAddrType 414} 415 416TEST_F(AssemblerX8632Test, MovssAddrXmm) { 417#define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \ 418 do { \ 419 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 420 "Invalid fp length #FloatLength"); \ 421 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 422 \ 423 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ 424 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 425 const uint32_t T0 = allocateQword(); \ 426 const Type V0 = Value; \ 427 const uint32_t T1 = allocateQword(); \ 428 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ 429 "f" #FloatLength " does not have quiet nan."); \ 430 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ 431 \ 432 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm, \ 433 dwordAddress(T0)); \ 434 \ 435 AssembledTest test = assemble(); \ 436 if (IsDouble) { \ 437 test.setQwordTo(T0, static_cast<double>(V0)); \ 438 test.setQwordTo(T1, static_cast<double>(V1)); \ 439 } else { \ 440 test.setDwordTo(T0, static_cast<float>(V0)); \ 441 test.setDwordTo(T1, static_cast<float>(V1)); \ 442 } \ 443 test.run(); \ 444 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ 445 << Value; \ 446 reset(); \ 447 } while (0) 448 449#define TestMovssAddrXmm(FloatLength) \ 450 do { \ 451 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 452 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 453 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \ 454 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \ 455 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \ 456 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \ 457 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \ 458 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \ 459 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \ 460 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \ 461 } \ 462 } while (0) 463 464 TestMovssAddrXmm(32); 465 TestMovssAddrXmm(64); 466 467#undef TestMovssAddrXmm 468#undef TestMovssAddrXmmType 469} 470 471TEST_F(AssemblerX8632Test, MovssXmmXmm) { 472#define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \ 473 do { \ 474 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 475 "Invalid fp length #FloatLength"); \ 476 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 477 \ 478 static constexpr char TestString[] = \ 479 "(" #FloatLength ", " #Src ", " #Dst ")"; \ 480 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 481 const uint32_t T0 = allocateQword(); \ 482 const Type V0 = Value; \ 483 const uint32_t T1 = allocateQword(); \ 484 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ 485 "f" #FloatLength " does not have quiet nan."); \ 486 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ 487 \ 488 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Src, \ 489 dwordAddress(T0)); \ 490 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst, \ 491 dwordAddress(T1)); \ 492 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst, \ 493 XmmRegister::Encoded_Reg_##Src); \ 494 \ 495 AssembledTest test = assemble(); \ 496 if (IsDouble) { \ 497 test.setQwordTo(T0, static_cast<double>(V0)); \ 498 test.setQwordTo(T1, static_cast<double>(V1)); \ 499 } else { \ 500 test.setDwordTo(T0, static_cast<float>(V0)); \ 501 test.setDwordTo(T1, static_cast<float>(V1)); \ 502 } \ 503 test.run(); \ 504 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \ 505 << Value; \ 506 reset(); \ 507 } while (0) 508 509#define TestMovssXmmXmm(FloatLength) \ 510 do { \ 511 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 512 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 513 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \ 514 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \ 515 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \ 516 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \ 517 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \ 518 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \ 519 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \ 520 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm0, Value); \ 521 } \ 522 } while (0) 523 524 TestMovssXmmXmm(32); 525 TestMovssXmmXmm(64); 526 527#undef TestMovssXmmXmm 528#undef TestMovssXmmXmmType 529} 530 531TEST_F(AssemblerX8632Test, MovdToXmm) { 532#define TestMovdXmmReg(Src, Dst, Value) \ 533 do { \ 534 assert(((Value)&0xFFFFFFFF) == (Value)); \ 535 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 536 const uint32_t T0 = allocateQword(); \ 537 const uint64_t V0 = 0xFFFFFFFF00000000ull; \ 538 \ 539 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src, Immediate(Value)); \ 540 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 541 __ movd(IceType_i32, XmmRegister::Encoded_Reg_##Dst, \ 542 GPRRegister::Encoded_Reg_##Src); \ 543 \ 544 AssembledTest test = assemble(); \ 545 \ 546 test.setQwordTo(T0, V0); \ 547 test.run(); \ 548 \ 549 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 550 << Value; \ 551 reset(); \ 552 } while (0) 553 554#define TestMovdXmmAddr(Dst, Value) \ 555 do { \ 556 assert(((Value)&0xFFFFFFFF) == (Value)); \ 557 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 558 const uint32_t T0 = allocateQword(); \ 559 const uint32_t V0 = Value; \ 560 const uint32_t T1 = allocateQword(); \ 561 const uint64_t V1 = 0xFFFFFFFF00000000ull; \ 562 \ 563 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 564 __ movd(IceType_i32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 565 \ 566 AssembledTest test = assemble(); \ 567 \ 568 test.setDwordTo(T0, V0); \ 569 test.setQwordTo(T1, V1); \ 570 test.run(); \ 571 \ 572 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 573 << Value; \ 574 reset(); \ 575 } while (0) 576 577#define TestMovd(Dst) \ 578 do { \ 579 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ 580 TestMovdXmmReg(eax, Dst, Value); \ 581 TestMovdXmmReg(ebx, Dst, Value); \ 582 TestMovdXmmReg(ecx, Dst, Value); \ 583 TestMovdXmmReg(edx, Dst, Value); \ 584 TestMovdXmmReg(esi, Dst, Value); \ 585 TestMovdXmmReg(edi, Dst, Value); \ 586 TestMovdXmmAddr(Dst, Value); \ 587 } \ 588 } while (0) 589 590 TestMovd(xmm0); 591 TestMovd(xmm1); 592 TestMovd(xmm2); 593 TestMovd(xmm3); 594 TestMovd(xmm4); 595 TestMovd(xmm5); 596 TestMovd(xmm6); 597 TestMovd(xmm7); 598 599#undef TestMovdXmmAddr 600#undef TestMovdXmmReg 601#undef TestMovd 602} 603 604TEST_F(AssemblerX8632Test, MovdFromXmm) { 605#define TestMovdRegXmm(Src, Dst, Value) \ 606 do { \ 607 assert(((Value)&0xFFFFFFFF) == (Value)); \ 608 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 609 const uint32_t T0 = allocateDword(); \ 610 const uint32_t V0 = Value; \ 611 \ 612 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 613 __ movd(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 614 XmmRegister::Encoded_Reg_##Src); \ 615 \ 616 AssembledTest test = assemble(); \ 617 \ 618 test.setDwordTo(T0, V0); \ 619 test.run(); \ 620 \ 621 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \ 622 << Value; \ 623 reset(); \ 624 } while (0) 625 626#define TestMovdAddrXmm(Src, Value) \ 627 do { \ 628 assert(((Value)&0xFFFFFFFF) == (Value)); \ 629 static constexpr char TestString[] = "(" #Src ", Addr)"; \ 630 const uint32_t T0 = allocateDword(); \ 631 const uint32_t V0 = Value; \ 632 const uint32_t T1 = allocateDword(); \ 633 const uint32_t V1 = ~(Value); \ 634 \ 635 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 636 __ movd(IceType_i32, dwordAddress(T1), XmmRegister::Encoded_Reg_##Src); \ 637 \ 638 AssembledTest test = assemble(); \ 639 \ 640 test.setDwordTo(T0, V0); \ 641 test.setDwordTo(T1, V1); \ 642 test.run(); \ 643 \ 644 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \ 645 << Value; \ 646 reset(); \ 647 } while (0) 648 649#define TestMovd(Src) \ 650 do { \ 651 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ 652 TestMovdRegXmm(Src, eax, Value); \ 653 TestMovdRegXmm(Src, ebx, Value); \ 654 TestMovdRegXmm(Src, ecx, Value); \ 655 TestMovdRegXmm(Src, edx, Value); \ 656 TestMovdRegXmm(Src, esi, Value); \ 657 TestMovdRegXmm(Src, edi, Value); \ 658 TestMovdAddrXmm(Src, Value); \ 659 } \ 660 } while (0) 661 662 TestMovd(xmm0); 663 TestMovd(xmm1); 664 TestMovd(xmm2); 665 TestMovd(xmm3); 666 TestMovd(xmm4); 667 TestMovd(xmm5); 668 TestMovd(xmm6); 669 TestMovd(xmm7); 670 671#undef TestMovdAddrXmm 672#undef TestMovdRegXmm 673#undef TestMovd 674} 675 676TEST_F(AssemblerX8632Test, MovqXmmAddr) { 677#define TestMovd(Dst, Value) \ 678 do { \ 679 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 680 const uint32_t T0 = allocateQword(); \ 681 const uint64_t V0 = Value; \ 682 const uint32_t T1 = allocateQword(); \ 683 const uint64_t V1 = ~(Value); \ 684 \ 685 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 686 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 687 \ 688 AssembledTest test = assemble(); \ 689 \ 690 test.setQwordTo(T0, V0); \ 691 test.setQwordTo(T1, V1); \ 692 test.run(); \ 693 \ 694 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 695 << Value; \ 696 reset(); \ 697 } while (0) 698 699 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 700 TestMovd(xmm0, Value); 701 TestMovd(xmm1, Value); 702 TestMovd(xmm2, Value); 703 TestMovd(xmm3, Value); 704 TestMovd(xmm4, Value); 705 TestMovd(xmm5, Value); 706 TestMovd(xmm6, Value); 707 TestMovd(xmm7, Value); 708 } 709 710#undef TestMovd 711} 712 713TEST_F(AssemblerX8632Test, MovqAddrXmm) { 714#define TestMovd(Dst, Value) \ 715 do { \ 716 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 717 const uint32_t T0 = allocateQword(); \ 718 const uint64_t V0 = Value; \ 719 const uint32_t T1 = allocateQword(); \ 720 const uint64_t V1 = ~(Value); \ 721 \ 722 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 723 __ movq(dwordAddress(T1), XmmRegister::Encoded_Reg_##Dst); \ 724 \ 725 AssembledTest test = assemble(); \ 726 \ 727 test.setQwordTo(T0, V0); \ 728 test.setQwordTo(T1, V1); \ 729 test.run(); \ 730 \ 731 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 732 << Value; \ 733 reset(); \ 734 } while (0) 735 736 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 737 TestMovd(xmm0, Value); 738 TestMovd(xmm1, Value); 739 TestMovd(xmm2, Value); 740 TestMovd(xmm3, Value); 741 TestMovd(xmm4, Value); 742 TestMovd(xmm5, Value); 743 TestMovd(xmm6, Value); 744 TestMovd(xmm7, Value); 745 } 746 747#undef TestMovd 748} 749 750TEST_F(AssemblerX8632Test, MovqXmmXmm) { 751#define TestMovd(Src, Dst, Value) \ 752 do { \ 753 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 754 const uint32_t T0 = allocateQword(); \ 755 const uint64_t V0 = Value; \ 756 const uint32_t T1 = allocateQword(); \ 757 const uint64_t V1 = ~(Value); \ 758 \ 759 __ movq(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 760 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 761 __ movq(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ 762 \ 763 AssembledTest test = assemble(); \ 764 \ 765 test.setQwordTo(T0, V0); \ 766 test.setQwordTo(T1, V1); \ 767 test.run(); \ 768 \ 769 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 770 << Value; \ 771 reset(); \ 772 } while (0) 773 774 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 775 TestMovd(xmm0, xmm1, Value); 776 TestMovd(xmm1, xmm2, Value); 777 TestMovd(xmm2, xmm3, Value); 778 TestMovd(xmm3, xmm4, Value); 779 TestMovd(xmm4, xmm5, Value); 780 TestMovd(xmm5, xmm6, Value); 781 TestMovd(xmm6, xmm7, Value); 782 TestMovd(xmm7, xmm0, Value); 783 } 784 785#undef TestMovd 786} 787 788TEST_F(AssemblerX8632Test, MovupsXmmAddr) { 789#define TestMovups(Dst) \ 790 do { \ 791 static constexpr char TestString[] = "(" #Dst ")"; \ 792 const uint32_t T0 = allocateDqword(); \ 793 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 794 std::numeric_limits<float>::infinity()); \ 795 \ 796 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 797 \ 798 AssembledTest test = assemble(); \ 799 test.setDqwordTo(T0, V0); \ 800 test.run(); \ 801 \ 802 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 803 reset(); \ 804 } while (0) 805 806 TestMovups(xmm0); 807 TestMovups(xmm1); 808 TestMovups(xmm2); 809 TestMovups(xmm3); 810 TestMovups(xmm4); 811 TestMovups(xmm5); 812 TestMovups(xmm6); 813 TestMovups(xmm7); 814 815#undef TestMovups 816} 817 818TEST_F(AssemblerX8632Test, MovupsAddrXmm) { 819#define TestMovups(Src) \ 820 do { \ 821 static constexpr char TestString[] = "(" #Src ")"; \ 822 const uint32_t T0 = allocateDqword(); \ 823 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 824 std::numeric_limits<float>::infinity()); \ 825 const uint32_t T1 = allocateDqword(); \ 826 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 827 \ 828 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 829 __ movups(dwordAddress(T1), XmmRegister::Encoded_Reg_##Src); \ 830 \ 831 AssembledTest test = assemble(); \ 832 test.setDqwordTo(T0, V0); \ 833 test.setDqwordTo(T1, V1); \ 834 test.run(); \ 835 \ 836 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \ 837 reset(); \ 838 } while (0) 839 840 TestMovups(xmm0); 841 TestMovups(xmm1); 842 TestMovups(xmm2); 843 TestMovups(xmm3); 844 TestMovups(xmm4); 845 TestMovups(xmm5); 846 TestMovups(xmm6); 847 TestMovups(xmm7); 848 849#undef TestMovups 850} 851 852TEST_F(AssemblerX8632Test, MovupsXmmXmm) { 853#define TestMovups(Dst, Src) \ 854 do { \ 855 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ 856 const uint32_t T0 = allocateDqword(); \ 857 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 858 std::numeric_limits<float>::infinity()); \ 859 const uint32_t T1 = allocateDqword(); \ 860 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 861 \ 862 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 863 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 864 __ movups(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ 865 \ 866 AssembledTest test = assemble(); \ 867 test.setDqwordTo(T0, V0); \ 868 test.setDqwordTo(T1, V1); \ 869 test.run(); \ 870 \ 871 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 872 reset(); \ 873 } while (0) 874 875 TestMovups(xmm0, xmm1); 876 TestMovups(xmm1, xmm2); 877 TestMovups(xmm2, xmm3); 878 TestMovups(xmm3, xmm4); 879 TestMovups(xmm4, xmm5); 880 TestMovups(xmm5, xmm6); 881 TestMovups(xmm6, xmm7); 882 TestMovups(xmm7, xmm0); 883 884#undef TestMovups 885} 886 887TEST_F(AssemblerX8632Test, MovapsXmmXmm) { 888#define TestMovaps(Dst, Src) \ 889 do { \ 890 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ 891 const uint32_t T0 = allocateDqword(); \ 892 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 893 std::numeric_limits<float>::infinity()); \ 894 const uint32_t T1 = allocateDqword(); \ 895 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 896 \ 897 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 898 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 899 __ movaps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ 900 \ 901 AssembledTest test = assemble(); \ 902 test.setDqwordTo(T0, V0); \ 903 test.setDqwordTo(T1, V1); \ 904 test.run(); \ 905 \ 906 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 907 reset(); \ 908 } while (0) 909 910 TestMovaps(xmm0, xmm1); 911 TestMovaps(xmm1, xmm2); 912 TestMovaps(xmm2, xmm3); 913 TestMovaps(xmm3, xmm4); 914 TestMovaps(xmm4, xmm5); 915 TestMovaps(xmm5, xmm6); 916 TestMovaps(xmm6, xmm7); 917 TestMovaps(xmm7, xmm0); 918 919#undef TestMovaps 920} 921 922TEST_F(AssemblerX8632Test, Movhlps_Movlhps) { 923#define TestImplSingle(Dst, Src, Inst, Expect) \ 924 do { \ 925 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ 926 const uint32_t T0 = allocateDqword(); \ 927 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \ 928 uint64_t(0xCCCCCCCCDDDDDDDDull)); \ 929 const uint32_t T1 = allocateDqword(); \ 930 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \ 931 uint64_t(0x9999999988888888ull)); \ 932 \ 933 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ 934 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ 935 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ 936 \ 937 AssembledTest test = assemble(); \ 938 test.setDqwordTo(T0, V0); \ 939 test.setDqwordTo(T1, V1); \ 940 test.run(); \ 941 \ 942 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \ 943 reset(); \ 944 } while (0) 945 946#define TestImpl(Dst, Src) \ 947 do { \ 948 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \ 949 uint64_t(0xCCCCCCCCDDDDDDDDull))); \ 950 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \ 951 uint64_t(0xEEEEEEEEFFFFFFFFull))); \ 952 } while (0) 953 954 TestImpl(xmm0, xmm1); 955 TestImpl(xmm1, xmm2); 956 TestImpl(xmm2, xmm3); 957 TestImpl(xmm3, xmm4); 958 TestImpl(xmm4, xmm5); 959 TestImpl(xmm5, xmm6); 960 TestImpl(xmm6, xmm7); 961 TestImpl(xmm7, xmm0); 962 963#undef TestImpl 964#undef TestImplSingle 965} 966 967TEST_F(AssemblerX8632Test, Movmsk) { 968#define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \ 969 do { \ 970 static constexpr char TestString[] = \ 971 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \ 972 const uint32_t T0 = allocateDqword(); \ 973 const Dqword V0 Value1; \ 974 \ 975 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 976 __ Inst(IceType_v4f32, GPRRegister::Encoded_Reg_##GPR, \ 977 XmmRegister::Encoded_Reg_##Src); \ 978 \ 979 AssembledTest test = assemble(); \ 980 test.setDqwordTo(T0, V0); \ 981 test.run(); \ 982 \ 983 ASSERT_EQ(Expected, test.GPR()) << TestString; \ 984 reset(); \ 985 } while (0) 986 987#define TestMovmsk(GPR, Src) \ 988 do { \ 989 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmsk); \ 990 } while (0) 991 992 TestMovmsk(eax, xmm0); 993 TestMovmsk(ebx, xmm1); 994 TestMovmsk(ecx, xmm2); 995 TestMovmsk(edx, xmm3); 996 TestMovmsk(esi, xmm4); 997 TestMovmsk(edi, xmm5); 998 TestMovmsk(eax, xmm6); 999 TestMovmsk(ebx, xmm7); 1000 1001#undef TestMovmskGPRXmm 1002#undef TestMovmsk 1003} 1004 1005TEST_F(AssemblerX8632Test, Pmovsxdq) { 1006#define TestPmovsxdqXmmXmm(Dst, Src, Value1) \ 1007 do { \ 1008 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \ 1009 const uint32_t T0 = allocateDqword(); \ 1010 const Dqword V0 Value1; \ 1011 const uint32_t T1 = allocateDqword(); \ 1012 const Dqword V1(uint64_t(0), uint64_t(0)); \ 1013 \ 1014 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ 1015 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ 1016 __ pmovsxdq(XmmRegister::Encoded_Reg_##Dst, \ 1017 XmmRegister::Encoded_Reg_##Src); \ 1018 \ 1019 AssembledTest test = assemble(); \ 1020 test.setDqwordTo(T0, V0); \ 1021 test.setDqwordTo(T1, V1); \ 1022 test.run(); \ 1023 \ 1024 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \ 1025 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ 1026 reset(); \ 1027 } while (0) 1028 1029#define TestPmovsxdq(Dst, Src) \ 1030 do { \ 1031 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \ 1032 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1033 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \ 1034 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1035 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \ 1036 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1037 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \ 1038 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1039 } while (0) 1040 1041 TestPmovsxdq(xmm0, xmm1); 1042 TestPmovsxdq(xmm1, xmm2); 1043 TestPmovsxdq(xmm2, xmm3); 1044 TestPmovsxdq(xmm3, xmm4); 1045 TestPmovsxdq(xmm4, xmm5); 1046 TestPmovsxdq(xmm5, xmm6); 1047 TestPmovsxdq(xmm6, xmm7); 1048 TestPmovsxdq(xmm7, xmm0); 1049 1050#undef TestPmovsxdq 1051#undef TestPmovsxdqXmmXmm 1052} 1053 1054TEST_F(AssemblerX8632Test, CmovRegReg) { 1055#define TestCmovRegReg(C, Src0, Value0, Src1, Value1, Dest, IsTrue) \ 1056 do { \ 1057 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ 1058 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1)); \ 1059 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0)); \ 1060 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, \ 1061 GPRRegister::Encoded_Reg_##Src1); \ 1062 __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest, \ 1063 GPRRegister::Encoded_Reg_##Src1); \ 1064 \ 1065 AssembledTest test = assemble(); \ 1066 test.run(); \ 1067 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) \ 1068 << "(" #C ", " #Src0 ", " #Value0 ", " #Src1 ", " #Value1 ", " #Dest \ 1069 ", " #IsTrue ")"; \ 1070 \ 1071 reset(); \ 1072 } while (0) 1073 1074 TestCmovRegReg(o, eax, 0x80000000u, ebx, 0x1u, ecx, 1u); 1075 TestCmovRegReg(o, eax, 0x1u, ebx, 0x10000000u, ecx, 0u); 1076 1077 TestCmovRegReg(no, ebx, 0x1u, ecx, 0x10000000u, edx, 1u); 1078 TestCmovRegReg(no, ebx, 0x80000000u, ecx, 0x1u, edx, 0u); 1079 1080 TestCmovRegReg(b, ecx, 0x1, edx, 0x80000000u, eax, 1u); 1081 TestCmovRegReg(b, ecx, 0x80000000u, edx, 0x1u, eax, 0u); 1082 1083 TestCmovRegReg(ae, edx, 0x80000000u, edi, 0x1u, ebx, 1u); 1084 TestCmovRegReg(ae, edx, 0x1u, edi, 0x80000000u, ebx, 0u); 1085 1086 TestCmovRegReg(e, edi, 0x1u, esi, 0x1u, ecx, 1u); 1087 TestCmovRegReg(e, edi, 0x1u, esi, 0x11111u, ecx, 0u); 1088 1089 TestCmovRegReg(ne, esi, 0x80000000u, eax, 0x1u, edx, 1u); 1090 TestCmovRegReg(ne, esi, 0x1u, eax, 0x1u, edx, 0u); 1091 1092 TestCmovRegReg(be, eax, 0x1u, ebx, 0x80000000u, eax, 1u); 1093 TestCmovRegReg(be, eax, 0x80000000u, ebx, 0x1u, eax, 0u); 1094 1095 TestCmovRegReg(a, ebx, 0x80000000u, ecx, 0x1u, ebx, 1u); 1096 TestCmovRegReg(a, ebx, 0x1u, ecx, 0x80000000u, ebx, 0u); 1097 1098 TestCmovRegReg(s, ecx, 0x1u, edx, 0x80000000u, ecx, 1u); 1099 TestCmovRegReg(s, ecx, 0x80000000u, edx, 0x1u, ecx, 0u); 1100 1101 TestCmovRegReg(ns, edx, 0x80000000u, edi, 0x1u, ecx, 1u); 1102 TestCmovRegReg(ns, edx, 0x1u, edi, 0x80000000u, ecx, 0u); 1103 1104 TestCmovRegReg(p, edi, 0x80000000u, esi, 0x1u, edx, 1u); 1105 TestCmovRegReg(p, edi, 0x1u, esi, 0x80000000u, edx, 0u); 1106 1107 TestCmovRegReg(np, esi, 0x1u, edi, 0x80000000u, eax, 1u); 1108 TestCmovRegReg(np, esi, 0x80000000u, edi, 0x1u, eax, 0u); 1109 1110 TestCmovRegReg(l, edi, 0x80000000u, eax, 0x1u, ebx, 1u); 1111 TestCmovRegReg(l, edi, 0x1u, eax, 0x80000000u, ebx, 0u); 1112 1113 TestCmovRegReg(ge, eax, 0x1u, ebx, 0x80000000u, ecx, 1u); 1114 TestCmovRegReg(ge, eax, 0x80000000u, ebx, 0x1u, ecx, 0u); 1115 1116 TestCmovRegReg(le, ebx, 0x80000000u, ecx, 0x1u, edx, 1u); 1117 TestCmovRegReg(le, ebx, 0x1u, ecx, 0x80000000u, edx, 0u); 1118 1119#undef TestCmovRegReg 1120} 1121 1122TEST_F(AssemblerX8632Test, CmovRegAddr) { 1123#define TestCmovRegAddr(C, Src0, Value0, Value1, Dest, IsTrue) \ 1124 do { \ 1125 const uint32_t T0 = allocateDword(); \ 1126 const uint32_t V0 = Value1; \ 1127 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ 1128 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0)); \ 1129 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, dwordAddress(T0)); \ 1130 __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest, \ 1131 dwordAddress(T0)); \ 1132 \ 1133 AssembledTest test = assemble(); \ 1134 test.setDwordTo(T0, V0); \ 1135 test.run(); \ 1136 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) \ 1137 << "(" #C ", " #Src0 ", " #Value0 ", " #Value1 ", " #Dest ", " #IsTrue \ 1138 ")"; \ 1139 \ 1140 reset(); \ 1141 } while (0) 1142 1143 TestCmovRegAddr(o, eax, 0x80000000u, 0x1u, ecx, 1u); 1144 TestCmovRegAddr(o, eax, 0x1u, 0x10000000u, ecx, 0u); 1145 1146 TestCmovRegAddr(no, ebx, 0x1u, 0x10000000u, edx, 1u); 1147 TestCmovRegAddr(no, ebx, 0x80000000u, 0x1u, edx, 0u); 1148 1149 TestCmovRegAddr(b, ecx, 0x1, 0x80000000u, eax, 1u); 1150 TestCmovRegAddr(b, ecx, 0x80000000u, 0x1u, eax, 0u); 1151 1152 TestCmovRegAddr(ae, edx, 0x80000000u, 0x1u, ebx, 1u); 1153 TestCmovRegAddr(ae, edx, 0x1u, 0x80000000u, ebx, 0u); 1154 1155 TestCmovRegAddr(e, edi, 0x1u, 0x1u, ecx, 1u); 1156 TestCmovRegAddr(e, edi, 0x1u, 0x11111u, ecx, 0u); 1157 1158 TestCmovRegAddr(ne, esi, 0x80000000u, 0x1u, edx, 1u); 1159 TestCmovRegAddr(ne, esi, 0x1u, 0x1u, edx, 0u); 1160 1161 TestCmovRegAddr(be, eax, 0x1u, 0x80000000u, eax, 1u); 1162 TestCmovRegAddr(be, eax, 0x80000000u, 0x1u, eax, 0u); 1163 1164 TestCmovRegAddr(a, ebx, 0x80000000u, 0x1u, ebx, 1u); 1165 TestCmovRegAddr(a, ebx, 0x1u, 0x80000000u, ebx, 0u); 1166 1167 TestCmovRegAddr(s, ecx, 0x1u, 0x80000000u, ecx, 1u); 1168 TestCmovRegAddr(s, ecx, 0x80000000u, 0x1u, ecx, 0u); 1169 1170 TestCmovRegAddr(ns, edx, 0x80000000u, 0x1u, ecx, 1u); 1171 TestCmovRegAddr(ns, edx, 0x1u, 0x80000000u, ecx, 0u); 1172 1173 TestCmovRegAddr(p, edi, 0x80000000u, 0x1u, edx, 1u); 1174 TestCmovRegAddr(p, edi, 0x1u, 0x80000000u, edx, 0u); 1175 1176 TestCmovRegAddr(np, esi, 0x1u, 0x80000000u, eax, 1u); 1177 TestCmovRegAddr(np, esi, 0x80000000u, 0x1u, eax, 0u); 1178 1179 TestCmovRegAddr(l, edi, 0x80000000u, 0x1u, ebx, 1u); 1180 TestCmovRegAddr(l, edi, 0x1u, 0x80000000u, ebx, 0u); 1181 1182 TestCmovRegAddr(ge, eax, 0x1u, 0x80000000u, ecx, 1u); 1183 TestCmovRegAddr(ge, eax, 0x80000000u, 0x1u, ecx, 0u); 1184 1185 TestCmovRegAddr(le, ebx, 0x80000000u, 0x1u, edx, 1u); 1186 TestCmovRegAddr(le, ebx, 0x1u, 0x80000000u, edx, 0u); 1187 1188#undef TestCmovRegAddr 1189} 1190 1191} // end of anonymous namespace 1192} // end of namespace Test 1193} // end of namespace X8632 1194} // end of namespace Ice 1195