1 //===- subzero/unittest/AssemblerX8664/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 "AssemblerX8664/TestUtil.h" 10 11 namespace Ice { 12 namespace X8664 { 13 namespace Test { 14 namespace { 15 16 TEST_F(AssemblerX8664Test, MovRegImm) { 17 static constexpr uint32_t Mask8 = 0x000000FF; 18 static constexpr uint32_t Mask16 = 0x0000FFFF; 19 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 20 21 #define MovRegImm(Reg, Suffix, Size) \ 22 do { \ 23 static constexpr char TestString[] = "(" #Reg ", " #Size ")"; \ 24 static constexpr uint32_t Value = (0xABCD7645) & Mask##Size; \ 25 static constexpr uint32_t Marker = 0xBEEFFEEB; \ 26 __ mov(IceType_i32, Encoded_GPR_##Reg##q(), Immediate(Marker)); \ 27 __ mov(IceType_i##Size, Encoded_GPR_##Reg##Suffix(), Immediate(Value)); \ 28 \ 29 AssembledTest test = assemble(); \ 30 test.run(); \ 31 \ 32 ASSERT_EQ(Value, test.Reg##Suffix()) << TestString; \ 33 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.Reg##d()) << TestString; \ 34 reset(); \ 35 } while (0) 36 37 #define TestImpl(Reg) \ 38 do { \ 39 MovRegImm(Reg, l, 8); \ 40 MovRegImm(Reg, w, 16); \ 41 MovRegImm(Reg, d, 32); \ 42 /* MovRegImm64 not implemented */ \ 43 } while (0) 44 45 TestImpl(r1); 46 TestImpl(r2); 47 TestImpl(r3); 48 TestImpl(r4); 49 TestImpl(r5); 50 TestImpl(r6); 51 TestImpl(r7); 52 TestImpl(r8); 53 TestImpl(r10); 54 TestImpl(r11); 55 TestImpl(r12); 56 TestImpl(r13); 57 TestImpl(r14); 58 TestImpl(r15); 59 60 #undef TestImpl 61 #undef MovRegImm 62 } 63 64 TEST_F(AssemblerX8664Test, MovMemImm) { 65 const uint32_t T0 = allocateDword(); 66 constexpr uint32_t ExpectedT0 = 0x00111100ul; 67 const uint32_t T1 = allocateDword(); 68 constexpr uint32_t ExpectedT1 = 0x00222200ul; 69 const uint32_t T2 = allocateDword(); 70 constexpr uint32_t ExpectedT2 = 0x03333000ul; 71 const uint32_t T3 = allocateDword(); 72 constexpr uint32_t ExpectedT3 = 0x00444400ul; 73 74 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); 75 __ mov(IceType_i16, dwordAddress(T1), Immediate(ExpectedT1)); 76 __ mov(IceType_i8, dwordAddress(T2), Immediate(ExpectedT2)); 77 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); 78 79 AssembledTest test = assemble(); 80 test.run(); 81 EXPECT_EQ(0ul, test.eax()); 82 EXPECT_EQ(0ul, test.ebx()); 83 EXPECT_EQ(0ul, test.ecx()); 84 EXPECT_EQ(0ul, test.edx()); 85 EXPECT_EQ(0ul, test.edi()); 86 EXPECT_EQ(0ul, test.esi()); 87 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); 88 EXPECT_EQ(ExpectedT1 & 0xFFFF, test.contentsOfDword(T1)); 89 EXPECT_EQ(ExpectedT2 & 0xFF, test.contentsOfDword(T2)); 90 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); 91 } 92 93 TEST_F(AssemblerX8664Test, MovMemReg) { 94 static constexpr uint64_t Mask8 = 0x00000000000000FF; 95 static constexpr uint64_t Mask16 = 0x000000000000FFFF; 96 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFF; 97 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFF; 98 99 #define TestMemReg(Src, Size) \ 100 do { \ 101 static constexpr char TestString[] = "(" #Src ", " #Size ")"; \ 102 static constexpr uint32_t Value = 0x1a4d567e & Mask##Size; \ 103 static constexpr uint64_t Marker = 0xD0DA33EEBEEFFEEB; \ 104 const uint32_t T0 = allocateQword(); \ 105 \ 106 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \ 107 __ mov(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \ 108 \ 109 AssembledTest test = assemble(); \ 110 test.setQwordTo(T0, Marker); \ 111 test.run(); \ 112 \ 113 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.contentsOfQword(T0)) \ 114 << TestString; \ 115 reset(); \ 116 } while (0) 117 118 #define TestImpl(Src) \ 119 do { \ 120 TestMemReg(Src, 8); \ 121 TestMemReg(Src, 16); \ 122 TestMemReg(Src, 32); \ 123 TestMemReg(Src, 64); \ 124 } while (0) 125 126 TestImpl(r1); 127 TestImpl(r2); 128 TestImpl(r3); 129 TestImpl(r4); 130 TestImpl(r5); 131 TestImpl(r6); 132 TestImpl(r7); 133 TestImpl(r8); 134 TestImpl(r10); 135 TestImpl(r11); 136 TestImpl(r12); 137 TestImpl(r13); 138 TestImpl(r14); 139 TestImpl(r15); 140 141 #undef TestImpl 142 #undef TestMemReg 143 } 144 145 TEST_F(AssemblerX8664Test, MovRegReg) { 146 static constexpr uint64_t Mask8 = 0x00000000000000FFull; 147 static constexpr uint64_t Mask16 = 0x000000000000FFFFull; 148 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull; 149 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull; 150 151 static constexpr uint64_t MaskResult8 = 0x00000000000000FFull; 152 static constexpr uint64_t MaskResult16 = 0x000000000000FFFFull; 153 static constexpr uint64_t MaskResult32 = 0xFFFFFFFFFFFFFFFFull; 154 static constexpr uint64_t MaskResult64 = 0xFFFFFFFFFFFFFFFFull; 155 156 #define TestRegReg(Dst, Src, Suffix, Size) \ 157 do { \ 158 static constexpr char TestString[] = \ 159 "(" #Dst ", " #Src ", " #Suffix ", " #Size ")"; \ 160 const uint8_t T0 = allocateQword(); \ 161 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \ 162 const uint8_t T1 = allocateQword(); \ 163 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \ 164 \ 165 __ mov(IceType_i64, Encoded_GPR_##Src(), dwordAddress(T0)); \ 166 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \ 167 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \ 168 \ 169 AssembledTest test = assemble(); \ 170 test.setQwordTo(T0, Value); \ 171 test.setQwordTo(T1, Marker); \ 172 test.run(); \ 173 \ 174 ASSERT_EQ((Marker & ~MaskResult##Size) | Value, test.Dst()) << TestString; \ 175 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \ 176 reset(); \ 177 } while (0) 178 179 #define TestImpl(Dst, Src) \ 180 do { \ 181 TestRegReg(Dst, Src, l, 8); \ 182 TestRegReg(Dst, Src, w, 16); \ 183 TestRegReg(Dst, Src, d, 32); \ 184 TestRegReg(Dst, Src, q, 64); \ 185 } while (0) 186 187 TestImpl(r1, r2); 188 TestImpl(r2, r3); 189 TestImpl(r3, r4); 190 TestImpl(r4, r5); 191 TestImpl(r5, r6); 192 TestImpl(r6, r7); 193 TestImpl(r7, r8); 194 TestImpl(r8, r10); 195 TestImpl(r10, r11); 196 TestImpl(r11, r12); 197 TestImpl(r12, r13); 198 TestImpl(r13, r14); 199 TestImpl(r14, r15); 200 TestImpl(r15, r1); 201 202 #undef TestImpl 203 #undef TestRegReg 204 } 205 206 TEST_F(AssemblerX8664Test, MovRegMem) { 207 static constexpr uint64_t Mask8 = 0x00000000000000FFull; 208 static constexpr uint64_t Mask16 = 0x000000000000FFFFull; 209 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull; 210 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull; 211 212 static constexpr uint64_t MaskResult8 = ~0x00000000000000FFull; 213 static constexpr uint64_t MaskResult16 = ~0x000000000000FFFFull; 214 static constexpr uint64_t MaskResult32 = ~0xFFFFFFFFFFFFFFFFull; 215 static constexpr uint64_t MaskResult64 = ~0xFFFFFFFFFFFFFFFFull; 216 217 #define TestRegAddr(Dst, Suffix, Size) \ 218 do { \ 219 static constexpr char TestString[] = \ 220 "(" #Dst ", Addr, " #Suffix ", " #Size ")"; \ 221 const uint8_t T0 = allocateQword(); \ 222 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \ 223 const uint8_t T1 = allocateQword(); \ 224 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \ 225 \ 226 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \ 227 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \ 228 \ 229 AssembledTest test = assemble(); \ 230 test.setQwordTo(T0, Value); \ 231 test.setQwordTo(T1, Marker); \ 232 test.run(); \ 233 \ 234 ASSERT_EQ((Marker & MaskResult##Size) | Value, test.Dst()) << TestString; \ 235 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \ 236 reset(); \ 237 } while (0) 238 239 #define TestImpl(Dst) \ 240 do { \ 241 TestRegAddr(Dst, l, 8); \ 242 TestRegAddr(Dst, w, 16); \ 243 TestRegAddr(Dst, d, 32); \ 244 TestRegAddr(Dst, q, 64); \ 245 } while (0) 246 247 TestImpl(r1); 248 TestImpl(r2); 249 TestImpl(r3); 250 TestImpl(r4); 251 TestImpl(r5); 252 TestImpl(r6); 253 TestImpl(r7); 254 TestImpl(r8); 255 TestImpl(r10); 256 TestImpl(r11); 257 TestImpl(r12); 258 TestImpl(r13); 259 TestImpl(r14); 260 TestImpl(r15); 261 262 #undef TestImpl 263 #undef TestRegAddr 264 } 265 266 TEST_F(AssemblerX8664Test, Movabs) { 267 #define TestImplValue(Dst, Value) \ 268 do { \ 269 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \ 270 uint64_t V = (Value); \ 271 __ movabs(Encoded_GPR_##Dst##q(), V); \ 272 \ 273 AssembledTest test = assemble(); \ 274 \ 275 test.run(); \ 276 \ 277 ASSERT_EQ(V, test.DST()) << TestString; \ 278 } while (0) 279 280 #define TestImpl(Dst) \ 281 do { \ 282 for (uint64_t V = {0, 1, 0xFFFFFFull, 0x80000000ull, \ 283 0xFFFFFFFFFFFFFFFFull}) { \ 284 TestImpl(Dst, V); \ 285 } \ 286 } while (0) 287 288 #undef TestImpl 289 #undef TestImplValue 290 } 291 292 TEST_F(AssemblerX8664Test, Movzx) { 293 static constexpr uint32_t Mask8 = 0x000000FF; 294 static constexpr uint32_t Mask16 = 0x0000FFFF; 295 296 #define TestImplRegReg(Dst, Src, Suffix, Size) \ 297 do { \ 298 const uint32_t T0 = allocateDqword(); \ 299 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ 300 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \ 301 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ 302 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \ 303 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), \ 304 Encoded_GPR_##Src##Suffix()); \ 305 AssembledTest test = assemble(); \ 306 test.setQwordTo(T0, V0); \ 307 test.run(); \ 308 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")"; \ 309 reset(); \ 310 } while (0) 311 312 #define TestImplRegAddr(Dst, Suffix, Size) \ 313 do { \ 314 const uint32_t T0 = allocateDqword(); \ 315 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ 316 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \ 317 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \ 318 \ 319 AssembledTest test = assemble(); \ 320 test.setQwordTo(T0, (V0 & ~Mask##Size) | Value); \ 321 test.run(); \ 322 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")"; \ 323 reset(); \ 324 } while (0) 325 326 #define TestImpl(Dst, Src) \ 327 do { \ 328 TestImplRegReg(Dst, Src, l, 8); \ 329 TestImplRegAddr(Dst, l, 8); \ 330 TestImplRegReg(Dst, Src, w, 16); \ 331 TestImplRegAddr(Dst, w, 16); \ 332 } while (0) 333 334 TestImpl(r1, r2); 335 TestImpl(r2, r3); 336 TestImpl(r3, r4); 337 TestImpl(r4, r5); 338 TestImpl(r5, r6); 339 TestImpl(r6, r7); 340 TestImpl(r7, r8); 341 TestImpl(r8, r10); 342 TestImpl(r10, r11); 343 TestImpl(r11, r12); 344 TestImpl(r12, r13); 345 TestImpl(r13, r14); 346 TestImpl(r14, r15); 347 TestImpl(r15, r1); 348 349 #undef TestImpl 350 #undef TestImplRegAddr 351 #undef TestImplRegReg 352 } 353 354 TEST_F(AssemblerX8664Test, Movsx) { 355 static constexpr uint64_t Mask8 = 0x000000FF; 356 static constexpr uint64_t Mask16 = 0x0000FFFF; 357 static constexpr uint64_t Mask32 = 0xFFFFFFFF; 358 359 #define TestImplRegReg(Dst, Src, Suffix, Size) \ 360 do { \ 361 const uint32_t T0 = allocateDqword(); \ 362 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ 363 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \ 364 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ 365 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \ 366 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), \ 367 Encoded_GPR_##Src##Suffix()); \ 368 AssembledTest test = assemble(); \ 369 test.setQwordTo(T0, V0); \ 370 test.run(); \ 371 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \ 372 << "(" #Dst ", " #Src ", " #Size ")"; \ 373 reset(); \ 374 } while (0) 375 376 #define TestImplRegAddr(Dst, Suffix, Size) \ 377 do { \ 378 const uint32_t T0 = allocateDqword(); \ 379 static constexpr uint64_t V0 = 0xC0BEBEEF & Mask##Size; \ 380 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \ 381 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \ 382 \ 383 AssembledTest test = assemble(); \ 384 test.setQwordTo(T0, V0); \ 385 test.run(); \ 386 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \ 387 << "(" #Dst ", Addr, " #Size ")"; \ 388 reset(); \ 389 } while (0) 390 391 #define TestImpl(Dst, Src) \ 392 do { \ 393 TestImplRegReg(Dst, Src, l, 8); \ 394 TestImplRegAddr(Dst, l, 8); \ 395 TestImplRegReg(Dst, Src, w, 16); \ 396 TestImplRegAddr(Dst, w, 16); \ 397 TestImplRegReg(Dst, Src, w, 32); \ 398 TestImplRegAddr(Dst, w, 32); \ 399 } while (0) 400 401 TestImpl(r1, r2); 402 TestImpl(r2, r3); 403 TestImpl(r3, r4); 404 TestImpl(r4, r5); 405 TestImpl(r5, r6); 406 TestImpl(r6, r7); 407 TestImpl(r7, r8); 408 TestImpl(r8, r10); 409 TestImpl(r10, r11); 410 TestImpl(r11, r12); 411 TestImpl(r12, r13); 412 TestImpl(r13, r14); 413 TestImpl(r14, r15); 414 TestImpl(r15, r1); 415 416 #undef TestImpl 417 #undef TestImplRegAddr 418 #undef TestImplRegReg 419 } 420 421 TEST_F(AssemblerX8664Test, Cmov) { 422 #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \ 423 do { \ 424 static constexpr char TestString[] = \ 425 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \ 426 ", " #Value1 ")"; \ 427 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \ 428 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \ 429 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \ 430 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \ 431 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \ 432 Encoded_GPR_##Src1()); \ 433 \ 434 AssembledTest test = assemble(); \ 435 test.run(); \ 436 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \ 437 \ 438 reset(); \ 439 } while (0) 440 441 #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1) \ 442 do { \ 443 static constexpr char TestString[] = \ 444 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 \ 445 ", Addr, " #Value1 ")"; \ 446 const uint32_t T0 = allocateDword(); \ 447 const uint32_t V0 = Value1; \ 448 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \ 449 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \ 450 __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0)); \ 451 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \ 452 dwordAddress(T0)); \ 453 \ 454 AssembledTest test = assemble(); \ 455 test.setDwordTo(T0, V0); \ 456 test.run(); \ 457 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \ 458 \ 459 reset(); \ 460 } while (0) 461 462 #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \ 463 do { \ 464 TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1); \ 465 TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1); \ 466 } while (0) 467 468 #define TestImpl(Dest, Src0, Src1) \ 469 do { \ 470 TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 471 TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \ 472 TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \ 473 TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 474 TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \ 475 TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 476 TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 477 TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 478 TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \ 479 TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \ 480 TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 481 TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \ 482 TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ 483 TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 484 TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 485 TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 486 TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ 487 TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 488 TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 489 TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 490 TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 491 TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 492 TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ 493 TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 494 TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 495 TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 496 TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ 497 TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ 498 TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ 499 TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ 500 } while (0) 501 502 TestImpl(r1, r2, r3); 503 504 #undef TestImpl 505 #undef TestValue 506 #undef TestRegAddr 507 #undef TestRegReg 508 } 509 510 TEST_F(AssemblerX8664LowLevelTest, RepMovsb) { 511 __ rep_movsb(); 512 513 static constexpr uint32_t ByteCount = 2; 514 static constexpr uint8_t Prefix = 0xF3; 515 static constexpr uint8_t Opcode = 0xA4; 516 517 ASSERT_EQ(ByteCount, codeBytesSize()); 518 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode); 519 } 520 521 TEST_F(AssemblerX8664Test, MovssXmmAddr) { 522 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \ 523 do { \ 524 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 525 "Invalid fp length #FloatLength"); \ 526 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 527 \ 528 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ 529 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 530 const uint32_t T0 = allocateQword(); \ 531 const Type V0 = Value; \ 532 \ 533 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \ 534 \ 535 AssembledTest test = assemble(); \ 536 if (IsDouble) { \ 537 test.setQwordTo(T0, static_cast<double>(V0)); \ 538 } else { \ 539 test.setDwordTo(T0, static_cast<float>(V0)); \ 540 } \ 541 test.run(); \ 542 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ 543 << Value; \ 544 reset(); \ 545 } while (0) 546 547 #define TestMovssXmmAddr(FloatLength) \ 548 do { \ 549 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 550 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 551 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \ 552 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \ 553 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \ 554 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \ 555 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \ 556 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \ 557 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \ 558 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \ 559 TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value); \ 560 TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value); \ 561 TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value); \ 562 TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value); \ 563 TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value); \ 564 TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value); \ 565 TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value); \ 566 TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value); \ 567 } \ 568 } while (0) 569 570 TestMovssXmmAddr(32); 571 TestMovssXmmAddr(64); 572 573 #undef TestMovssXmmAddr 574 #undef TestMovssXmmAddrType 575 } 576 577 TEST_F(AssemblerX8664Test, MovssAddrXmm) { 578 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \ 579 do { \ 580 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 581 "Invalid fp length #FloatLength"); \ 582 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 583 \ 584 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ 585 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 586 const uint32_t T0 = allocateQword(); \ 587 const Type V0 = Value; \ 588 const uint32_t T1 = allocateQword(); \ 589 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ 590 "f" #FloatLength " does not have quiet nan."); \ 591 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ 592 \ 593 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \ 594 \ 595 AssembledTest test = assemble(); \ 596 if (IsDouble) { \ 597 test.setQwordTo(T0, static_cast<double>(V0)); \ 598 test.setQwordTo(T1, static_cast<double>(V1)); \ 599 } else { \ 600 test.setDwordTo(T0, static_cast<float>(V0)); \ 601 test.setDwordTo(T1, static_cast<float>(V1)); \ 602 } \ 603 test.run(); \ 604 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ 605 << Value; \ 606 reset(); \ 607 } while (0) 608 609 #define TestMovssAddrXmm(FloatLength) \ 610 do { \ 611 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 612 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 613 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \ 614 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \ 615 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \ 616 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \ 617 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \ 618 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \ 619 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \ 620 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \ 621 TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value); \ 622 TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value); \ 623 TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value); \ 624 TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value); \ 625 TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value); \ 626 TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value); \ 627 TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value); \ 628 TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value); \ 629 } \ 630 } while (0) 631 632 TestMovssAddrXmm(32); 633 TestMovssAddrXmm(64); 634 635 #undef TestMovssAddrXmm 636 #undef TestMovssAddrXmmType 637 } 638 639 TEST_F(AssemblerX8664Test, MovssXmmXmm) { 640 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \ 641 do { \ 642 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ 643 "Invalid fp length #FloatLength"); \ 644 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 645 \ 646 static constexpr char TestString[] = \ 647 "(" #FloatLength ", " #Src ", " #Dst ")"; \ 648 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ 649 const uint32_t T0 = allocateQword(); \ 650 const Type V0 = Value; \ 651 const uint32_t T1 = allocateQword(); \ 652 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ 653 "f" #FloatLength " does not have quiet nan."); \ 654 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ 655 \ 656 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0)); \ 657 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 658 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), \ 659 Encoded_Xmm_##Src()); \ 660 \ 661 AssembledTest test = assemble(); \ 662 if (IsDouble) { \ 663 test.setQwordTo(T0, static_cast<double>(V0)); \ 664 test.setQwordTo(T1, static_cast<double>(V1)); \ 665 } else { \ 666 test.setDwordTo(T0, static_cast<float>(V0)); \ 667 test.setDwordTo(T1, static_cast<float>(V1)); \ 668 } \ 669 test.run(); \ 670 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \ 671 << Value; \ 672 reset(); \ 673 } while (0) 674 675 #define TestMovssXmmXmm(FloatLength) \ 676 do { \ 677 using Type = std::conditional<FloatLength == 32, float, double>::type; \ 678 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ 679 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \ 680 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \ 681 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \ 682 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \ 683 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \ 684 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \ 685 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \ 686 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value); \ 687 TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value); \ 688 TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value); \ 689 TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value); \ 690 TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value); \ 691 TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value); \ 692 TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value); \ 693 TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value); \ 694 TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value); \ 695 } \ 696 } while (0) 697 698 TestMovssXmmXmm(32); 699 TestMovssXmmXmm(64); 700 701 #undef TestMovssXmmXmm 702 #undef TestMovssXmmXmmType 703 } 704 705 TEST_F(AssemblerX8664Test, MovdToXmm) { 706 #define TestMovdXmmReg32(Src, Dst, Value) \ 707 do { \ 708 assert(((Value)&0xFFFFFFFF) == (Value)); \ 709 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 710 const uint32_t T0 = allocateQword(); \ 711 const uint64_t V0 = 0xFFFFFFFF00000000ull; \ 712 \ 713 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \ 714 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 715 __ movd(IceType_i32, Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \ 716 \ 717 AssembledTest test = assemble(); \ 718 \ 719 test.setQwordTo(T0, V0); \ 720 test.run(); \ 721 \ 722 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 723 << Value; \ 724 reset(); \ 725 } while (0) 726 727 #define TestMovdXmmReg64(Src, Dst, Value) \ 728 do { \ 729 assert(((Value)&0xFFFFFFFF) == (Value)); \ 730 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 731 const uint32_t T0 = allocateQword(); \ 732 const uint64_t V0 = 0xFFFFFFFF00000000ull; \ 733 const uint64_t Expected = (static_cast<uint64_t>(Value) << 32) | (Value); \ 734 \ 735 __ movabs(Encoded_GPR_##Src(), Expected); \ 736 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 737 __ movd(IceType_i64, Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \ 738 \ 739 AssembledTest test = assemble(); \ 740 \ 741 test.setQwordTo(T0, V0); \ 742 test.run(); \ 743 \ 744 ASSERT_EQ(Expected, test.Dst<uint64_t>()) << TestString << " value is " \ 745 << Value; \ 746 reset(); \ 747 } while (0) 748 749 #define TestMovdXmmReg(Src, Dst, Value) \ 750 do { \ 751 TestMovdXmmReg32(Src, Dst, Value); \ 752 TestMovdXmmReg64(Src, Dst, Value); \ 753 } while (0) 754 755 #define TestMovdXmmAddr32(Dst, Value) \ 756 do { \ 757 assert(((Value)&0xFFFFFFFF) == (Value)); \ 758 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 759 const uint32_t T0 = allocateQword(); \ 760 const uint32_t V0 = Value; \ 761 const uint32_t T1 = allocateQword(); \ 762 const uint64_t V1 = 0xFFFFFFFF00000000ull; \ 763 \ 764 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 765 __ movd(IceType_i32, Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 766 \ 767 AssembledTest test = assemble(); \ 768 \ 769 test.setDwordTo(T0, V0); \ 770 test.setQwordTo(T1, V1); \ 771 test.run(); \ 772 \ 773 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 774 << Value; \ 775 reset(); \ 776 } while (0) 777 778 #define TestMovdXmmAddr64(Dst, Value) \ 779 do { \ 780 assert(((Value)&0xFFFFFFFF) == (Value)); \ 781 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 782 const uint32_t T0 = allocateQword(); \ 783 const uint32_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value); \ 784 const uint32_t T1 = allocateQword(); \ 785 const uint64_t V1 = 0xFFFFFFFF00000000ull; \ 786 \ 787 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 788 __ movd(IceType_i64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 789 \ 790 AssembledTest test = assemble(); \ 791 \ 792 test.setDwordTo(T0, V0); \ 793 test.setQwordTo(T1, V1); \ 794 test.run(); \ 795 \ 796 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 797 << Value; \ 798 reset(); \ 799 } while (0) 800 801 #define TestMovdXmmAddr(Dst, Value) \ 802 do { \ 803 TestMovdXmmAddr32(Dst, Value); \ 804 TestMovdXmmAddr64(Dst, Value); \ 805 } while (0) 806 807 #define TestMovd(Dst) \ 808 do { \ 809 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ 810 TestMovdXmmReg(r1, Dst, Value); \ 811 TestMovdXmmReg(r2, Dst, Value); \ 812 TestMovdXmmReg(r3, Dst, Value); \ 813 TestMovdXmmReg(r4, Dst, Value); \ 814 TestMovdXmmReg(r5, Dst, Value); \ 815 TestMovdXmmReg(r6, Dst, Value); \ 816 TestMovdXmmReg(r7, Dst, Value); \ 817 TestMovdXmmReg(r8, Dst, Value); \ 818 TestMovdXmmReg(r10, Dst, Value); \ 819 TestMovdXmmReg(r11, Dst, Value); \ 820 TestMovdXmmReg(r12, Dst, Value); \ 821 TestMovdXmmReg(r13, Dst, Value); \ 822 TestMovdXmmReg(r14, Dst, Value); \ 823 TestMovdXmmReg(r15, Dst, Value); \ 824 TestMovdXmmAddr(Dst, Value); \ 825 } \ 826 } while (0) 827 828 TestMovd(xmm0); 829 TestMovd(xmm1); 830 TestMovd(xmm2); 831 TestMovd(xmm3); 832 TestMovd(xmm4); 833 TestMovd(xmm5); 834 TestMovd(xmm6); 835 TestMovd(xmm7); 836 TestMovd(xmm8); 837 TestMovd(xmm9); 838 TestMovd(xmm10); 839 TestMovd(xmm11); 840 TestMovd(xmm12); 841 TestMovd(xmm13); 842 TestMovd(xmm14); 843 TestMovd(xmm15); 844 845 #undef TestMovd 846 #undef TestMovdXmmAddr 847 #undef TestMovdXmmAddr64 848 #undef TestMovdXmmAddr32 849 #undef TestMovdXmmReg 850 #undef TestMovdXmmReg64 851 #undef TestMovdXmmReg32 852 } 853 854 TEST_F(AssemblerX8664Test, MovdFromXmm) { 855 #define TestMovdRegXmm32(Src, Dst, Value) \ 856 do { \ 857 assert(((Value)&0xFFFFFFFF) == (Value)); \ 858 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 859 const uint32_t T0 = allocateDword(); \ 860 const uint32_t V0 = Value; \ 861 \ 862 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ 863 __ movd(IceType_i32, Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \ 864 \ 865 AssembledTest test = assemble(); \ 866 \ 867 test.setDwordTo(T0, V0); \ 868 test.run(); \ 869 \ 870 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \ 871 << Value; \ 872 reset(); \ 873 } while (0) 874 875 #define TestMovdRegXmm64(Src, Dst, Value) \ 876 do { \ 877 assert(((Value)&0xFFFFFFFF) == (Value)); \ 878 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 879 const uint32_t T0 = allocateDword(); \ 880 const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value); \ 881 \ 882 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ 883 __ movd(IceType_i64, Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \ 884 \ 885 AssembledTest test = assemble(); \ 886 \ 887 test.setQwordTo(T0, V0); \ 888 test.run(); \ 889 \ 890 ASSERT_EQ(V0, test.contentsOfQword(T0)) << TestString << " value is " \ 891 << Value; \ 892 reset(); \ 893 } while (0) 894 895 #define TestMovdRegXmm(Src, Dst, Value) \ 896 do { \ 897 TestMovdRegXmm32(Src, Dst, Value); \ 898 TestMovdRegXmm64(Src, Dst, Value); \ 899 } while (0) 900 901 #define TestMovdAddrXmm32(Src, Value) \ 902 do { \ 903 assert(((Value)&0xFFFFFFFF) == (Value)); \ 904 static constexpr char TestString[] = "(" #Src ", Addr)"; \ 905 const uint32_t T0 = allocateDword(); \ 906 const uint32_t V0 = Value; \ 907 const uint32_t T1 = allocateDword(); \ 908 const uint32_t V1 = ~(Value); \ 909 \ 910 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ 911 __ movd(IceType_i32, dwordAddress(T1), Encoded_Xmm_##Src()); \ 912 \ 913 AssembledTest test = assemble(); \ 914 \ 915 test.setDwordTo(T0, V0); \ 916 test.setDwordTo(T1, V1); \ 917 test.run(); \ 918 \ 919 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \ 920 << Value; \ 921 reset(); \ 922 } while (0) 923 924 #define TestMovdAddrXmm64(Src, Value) \ 925 do { \ 926 assert(((Value)&0xFFFFFFFF) == (Value)); \ 927 static constexpr char TestString[] = "(" #Src ", Addr)"; \ 928 const uint32_t T0 = allocateQword(); \ 929 const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | Value; \ 930 const uint32_t T1 = allocateQword(); \ 931 const uint64_t V1 = ~V0; \ 932 \ 933 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ 934 __ movd(IceType_i64, dwordAddress(T1), Encoded_Xmm_##Src()); \ 935 \ 936 AssembledTest test = assemble(); \ 937 \ 938 test.setQwordTo(T0, V0); \ 939 test.setQwordTo(T1, V1); \ 940 test.run(); \ 941 \ 942 ASSERT_EQ(V0, test.contentsOfQword(T1)) << TestString << " value is " \ 943 << Value; \ 944 reset(); \ 945 } while (0) 946 947 #define TestMovdAddrXmm(Src, Value) \ 948 do { \ 949 TestMovdAddrXmm32(Src, Value); \ 950 TestMovdAddrXmm64(Src, Value); \ 951 } while (0) 952 953 #define TestMovd(Src) \ 954 do { \ 955 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ 956 TestMovdRegXmm(Src, r1, Value); \ 957 TestMovdRegXmm(Src, r2, Value); \ 958 TestMovdRegXmm(Src, r3, Value); \ 959 TestMovdRegXmm(Src, r4, Value); \ 960 TestMovdRegXmm(Src, r5, Value); \ 961 TestMovdRegXmm(Src, r6, Value); \ 962 TestMovdRegXmm(Src, r7, Value); \ 963 TestMovdRegXmm(Src, r8, Value); \ 964 TestMovdRegXmm(Src, r10, Value); \ 965 TestMovdRegXmm(Src, r11, Value); \ 966 TestMovdRegXmm(Src, r12, Value); \ 967 TestMovdRegXmm(Src, r13, Value); \ 968 TestMovdRegXmm(Src, r14, Value); \ 969 TestMovdRegXmm(Src, r15, Value); \ 970 TestMovdAddrXmm(Src, Value); \ 971 } \ 972 } while (0) 973 974 TestMovd(xmm0); 975 TestMovd(xmm1); 976 TestMovd(xmm2); 977 TestMovd(xmm3); 978 TestMovd(xmm4); 979 TestMovd(xmm5); 980 TestMovd(xmm6); 981 TestMovd(xmm7); 982 TestMovd(xmm8); 983 TestMovd(xmm9); 984 TestMovd(xmm10); 985 TestMovd(xmm11); 986 TestMovd(xmm12); 987 TestMovd(xmm13); 988 TestMovd(xmm14); 989 TestMovd(xmm15); 990 991 #undef TestMovd 992 #undef TestMovdAddrXmm 993 #undef TestMovdAddrXmm64 994 #undef TestMovdAddrXmm32 995 #undef TestMovdRegXmm 996 #undef TestMovdRegXmm64 997 #undef TestMovdRegXmm32 998 } 999 1000 TEST_F(AssemblerX8664Test, MovqXmmAddr) { 1001 #define TestMovd(Dst, Value) \ 1002 do { \ 1003 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 1004 const uint32_t T0 = allocateQword(); \ 1005 const uint64_t V0 = Value; \ 1006 const uint32_t T1 = allocateQword(); \ 1007 const uint64_t V1 = ~(Value); \ 1008 \ 1009 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 1010 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 1011 \ 1012 AssembledTest test = assemble(); \ 1013 \ 1014 test.setQwordTo(T0, V0); \ 1015 test.setQwordTo(T1, V1); \ 1016 test.run(); \ 1017 \ 1018 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 1019 << Value; \ 1020 reset(); \ 1021 } while (0) 1022 1023 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 1024 TestMovd(xmm0, Value); 1025 TestMovd(xmm1, Value); 1026 TestMovd(xmm2, Value); 1027 TestMovd(xmm3, Value); 1028 TestMovd(xmm4, Value); 1029 TestMovd(xmm5, Value); 1030 TestMovd(xmm6, Value); 1031 TestMovd(xmm7, Value); 1032 TestMovd(xmm8, Value); 1033 TestMovd(xmm9, Value); 1034 TestMovd(xmm10, Value); 1035 TestMovd(xmm11, Value); 1036 TestMovd(xmm12, Value); 1037 TestMovd(xmm13, Value); 1038 TestMovd(xmm14, Value); 1039 TestMovd(xmm15, Value); 1040 } 1041 1042 #undef TestMovd 1043 } 1044 1045 TEST_F(AssemblerX8664Test, MovqAddrXmm) { 1046 #define TestMovd(Dst, Value) \ 1047 do { \ 1048 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ 1049 const uint32_t T0 = allocateQword(); \ 1050 const uint64_t V0 = Value; \ 1051 const uint32_t T1 = allocateQword(); \ 1052 const uint64_t V1 = ~(Value); \ 1053 \ 1054 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 1055 __ movq(dwordAddress(T1), Encoded_Xmm_##Dst()); \ 1056 \ 1057 AssembledTest test = assemble(); \ 1058 \ 1059 test.setQwordTo(T0, V0); \ 1060 test.setQwordTo(T1, V1); \ 1061 test.run(); \ 1062 \ 1063 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 1064 << Value; \ 1065 reset(); \ 1066 } while (0) 1067 1068 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 1069 TestMovd(xmm0, Value); 1070 TestMovd(xmm1, Value); 1071 TestMovd(xmm2, Value); 1072 TestMovd(xmm3, Value); 1073 TestMovd(xmm4, Value); 1074 TestMovd(xmm5, Value); 1075 TestMovd(xmm6, Value); 1076 TestMovd(xmm7, Value); 1077 TestMovd(xmm8, Value); 1078 TestMovd(xmm9, Value); 1079 TestMovd(xmm10, Value); 1080 TestMovd(xmm11, Value); 1081 TestMovd(xmm12, Value); 1082 TestMovd(xmm13, Value); 1083 TestMovd(xmm14, Value); 1084 TestMovd(xmm15, Value); 1085 } 1086 1087 #undef TestMovd 1088 } 1089 1090 TEST_F(AssemblerX8664Test, MovqXmmXmm) { 1091 #define TestMovd(Src, Dst, Value) \ 1092 do { \ 1093 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ 1094 const uint32_t T0 = allocateQword(); \ 1095 const uint64_t V0 = Value; \ 1096 const uint32_t T1 = allocateQword(); \ 1097 const uint64_t V1 = ~(Value); \ 1098 \ 1099 __ movq(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1100 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 1101 __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ 1102 \ 1103 AssembledTest test = assemble(); \ 1104 \ 1105 test.setQwordTo(T0, V0); \ 1106 test.setQwordTo(T1, V1); \ 1107 test.run(); \ 1108 \ 1109 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ 1110 << Value; \ 1111 reset(); \ 1112 } while (0) 1113 1114 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { 1115 TestMovd(xmm0, xmm1, Value); 1116 TestMovd(xmm1, xmm2, Value); 1117 TestMovd(xmm2, xmm3, Value); 1118 TestMovd(xmm3, xmm4, Value); 1119 TestMovd(xmm4, xmm5, Value); 1120 TestMovd(xmm5, xmm6, Value); 1121 TestMovd(xmm6, xmm7, Value); 1122 TestMovd(xmm7, xmm8, Value); 1123 TestMovd(xmm8, xmm9, Value); 1124 TestMovd(xmm9, xmm10, Value); 1125 TestMovd(xmm10, xmm11, Value); 1126 TestMovd(xmm11, xmm12, Value); 1127 TestMovd(xmm12, xmm13, Value); 1128 TestMovd(xmm13, xmm14, Value); 1129 TestMovd(xmm14, xmm15, Value); 1130 TestMovd(xmm15, xmm0, Value); 1131 } 1132 1133 #undef TestMovd 1134 } 1135 1136 TEST_F(AssemblerX8664Test, MovupsXmmAddr) { 1137 #define TestMovups(Dst) \ 1138 do { \ 1139 static constexpr char TestString[] = "(" #Dst ")"; \ 1140 const uint32_t T0 = allocateDqword(); \ 1141 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 1142 std::numeric_limits<float>::infinity()); \ 1143 \ 1144 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 1145 \ 1146 AssembledTest test = assemble(); \ 1147 test.setDqwordTo(T0, V0); \ 1148 test.run(); \ 1149 \ 1150 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 1151 reset(); \ 1152 } while (0) 1153 1154 TestMovups(xmm0); 1155 TestMovups(xmm1); 1156 TestMovups(xmm2); 1157 TestMovups(xmm3); 1158 TestMovups(xmm4); 1159 TestMovups(xmm5); 1160 TestMovups(xmm6); 1161 TestMovups(xmm7); 1162 TestMovups(xmm8); 1163 TestMovups(xmm9); 1164 TestMovups(xmm10); 1165 TestMovups(xmm11); 1166 TestMovups(xmm12); 1167 TestMovups(xmm13); 1168 TestMovups(xmm14); 1169 TestMovups(xmm15); 1170 1171 #undef TestMovups 1172 } 1173 1174 TEST_F(AssemblerX8664Test, MovupsAddrXmm) { 1175 #define TestMovups(Src) \ 1176 do { \ 1177 static constexpr char TestString[] = "(" #Src ")"; \ 1178 const uint32_t T0 = allocateDqword(); \ 1179 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 1180 std::numeric_limits<float>::infinity()); \ 1181 const uint32_t T1 = allocateDqword(); \ 1182 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 1183 \ 1184 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1185 __ movups(dwordAddress(T1), Encoded_Xmm_##Src()); \ 1186 \ 1187 AssembledTest test = assemble(); \ 1188 test.setDqwordTo(T0, V0); \ 1189 test.setDqwordTo(T1, V1); \ 1190 test.run(); \ 1191 \ 1192 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \ 1193 reset(); \ 1194 } while (0) 1195 1196 TestMovups(xmm0); 1197 TestMovups(xmm1); 1198 TestMovups(xmm2); 1199 TestMovups(xmm3); 1200 TestMovups(xmm4); 1201 TestMovups(xmm5); 1202 TestMovups(xmm6); 1203 TestMovups(xmm7); 1204 TestMovups(xmm8); 1205 TestMovups(xmm9); 1206 TestMovups(xmm10); 1207 TestMovups(xmm11); 1208 TestMovups(xmm12); 1209 TestMovups(xmm13); 1210 TestMovups(xmm14); 1211 TestMovups(xmm15); 1212 1213 #undef TestMovups 1214 } 1215 1216 TEST_F(AssemblerX8664Test, MovupsXmmXmm) { 1217 #define TestMovups(Dst, Src) \ 1218 do { \ 1219 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ 1220 const uint32_t T0 = allocateDqword(); \ 1221 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 1222 std::numeric_limits<float>::infinity()); \ 1223 const uint32_t T1 = allocateDqword(); \ 1224 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 1225 \ 1226 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1227 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 1228 __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ 1229 \ 1230 AssembledTest test = assemble(); \ 1231 test.setDqwordTo(T0, V0); \ 1232 test.setDqwordTo(T1, V1); \ 1233 test.run(); \ 1234 \ 1235 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 1236 reset(); \ 1237 } while (0) 1238 1239 TestMovups(xmm0, xmm1); 1240 TestMovups(xmm1, xmm2); 1241 TestMovups(xmm2, xmm3); 1242 TestMovups(xmm3, xmm4); 1243 TestMovups(xmm4, xmm5); 1244 TestMovups(xmm5, xmm6); 1245 TestMovups(xmm6, xmm7); 1246 TestMovups(xmm7, xmm8); 1247 TestMovups(xmm8, xmm9); 1248 TestMovups(xmm9, xmm10); 1249 TestMovups(xmm10, xmm11); 1250 TestMovups(xmm11, xmm12); 1251 TestMovups(xmm12, xmm13); 1252 TestMovups(xmm13, xmm14); 1253 TestMovups(xmm14, xmm15); 1254 TestMovups(xmm15, xmm0); 1255 1256 #undef TestMovups 1257 } 1258 1259 TEST_F(AssemblerX8664Test, MovapsXmmXmm) { 1260 #define TestMovaps(Dst, Src) \ 1261 do { \ 1262 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ 1263 const uint32_t T0 = allocateDqword(); \ 1264 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ 1265 std::numeric_limits<float>::infinity()); \ 1266 const uint32_t T1 = allocateDqword(); \ 1267 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ 1268 \ 1269 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1270 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 1271 __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ 1272 \ 1273 AssembledTest test = assemble(); \ 1274 test.setDqwordTo(T0, V0); \ 1275 test.setDqwordTo(T1, V1); \ 1276 test.run(); \ 1277 \ 1278 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ 1279 reset(); \ 1280 } while (0) 1281 1282 TestMovaps(xmm0, xmm1); 1283 TestMovaps(xmm1, xmm2); 1284 TestMovaps(xmm2, xmm3); 1285 TestMovaps(xmm3, xmm4); 1286 TestMovaps(xmm4, xmm5); 1287 TestMovaps(xmm5, xmm6); 1288 TestMovaps(xmm6, xmm7); 1289 TestMovaps(xmm7, xmm8); 1290 TestMovaps(xmm8, xmm9); 1291 TestMovaps(xmm9, xmm10); 1292 TestMovaps(xmm10, xmm11); 1293 TestMovaps(xmm11, xmm12); 1294 TestMovaps(xmm12, xmm13); 1295 TestMovaps(xmm13, xmm14); 1296 TestMovaps(xmm14, xmm15); 1297 TestMovaps(xmm15, xmm0); 1298 1299 #undef TestMovaps 1300 } 1301 1302 TEST_F(AssemblerX8664Test, Movhlps_Movlhps) { 1303 #define TestImplSingle(Dst, Src, Inst, Expect) \ 1304 do { \ 1305 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ 1306 const uint32_t T0 = allocateDqword(); \ 1307 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \ 1308 uint64_t(0xCCCCCCCCDDDDDDDDull)); \ 1309 const uint32_t T1 = allocateDqword(); \ 1310 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \ 1311 uint64_t(0x9999999988888888ull)); \ 1312 \ 1313 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ 1314 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \ 1315 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ 1316 \ 1317 AssembledTest test = assemble(); \ 1318 test.setDqwordTo(T0, V0); \ 1319 test.setDqwordTo(T1, V1); \ 1320 test.run(); \ 1321 \ 1322 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \ 1323 reset(); \ 1324 } while (0) 1325 1326 #define TestImpl(Dst, Src) \ 1327 do { \ 1328 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \ 1329 uint64_t(0xCCCCCCCCDDDDDDDDull))); \ 1330 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \ 1331 uint64_t(0xEEEEEEEEFFFFFFFFull))); \ 1332 } while (0) 1333 1334 TestImpl(xmm0, xmm1); 1335 TestImpl(xmm1, xmm2); 1336 TestImpl(xmm2, xmm3); 1337 TestImpl(xmm3, xmm4); 1338 TestImpl(xmm4, xmm5); 1339 TestImpl(xmm5, xmm6); 1340 TestImpl(xmm6, xmm7); 1341 TestImpl(xmm7, xmm8); 1342 TestImpl(xmm8, xmm9); 1343 TestImpl(xmm9, xmm10); 1344 TestImpl(xmm10, xmm11); 1345 TestImpl(xmm11, xmm12); 1346 TestImpl(xmm12, xmm13); 1347 TestImpl(xmm13, xmm14); 1348 TestImpl(xmm14, xmm15); 1349 TestImpl(xmm15, xmm0); 1350 1351 #undef TestImpl 1352 #undef TestImplSingle 1353 } 1354 1355 TEST_F(AssemblerX8664Test, Movmsk) { 1356 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \ 1357 do { \ 1358 static constexpr char TestString[] = \ 1359 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \ 1360 const uint32_t T0 = allocateDqword(); \ 1361 const Dqword V0 Value1; \ 1362 \ 1363 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1364 __ Inst(IceType_v4f32, Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \ 1365 \ 1366 AssembledTest test = assemble(); \ 1367 test.setDqwordTo(T0, V0); \ 1368 test.run(); \ 1369 \ 1370 ASSERT_EQ(Expected, test.GPR()) << TestString; \ 1371 reset(); \ 1372 } while (0) 1373 1374 #define TestMovmsk(GPR, Src) \ 1375 do { \ 1376 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmsk); \ 1377 } while (0) 1378 1379 TestMovmsk(r1, xmm0); 1380 TestMovmsk(r2, xmm1); 1381 TestMovmsk(r3, xmm2); 1382 TestMovmsk(r4, xmm3); 1383 TestMovmsk(r5, xmm4); 1384 TestMovmsk(r6, xmm5); 1385 TestMovmsk(r7, xmm6); 1386 TestMovmsk(r8, xmm7); 1387 TestMovmsk(r10, xmm8); 1388 TestMovmsk(r11, xmm9); 1389 TestMovmsk(r12, xmm10); 1390 TestMovmsk(r13, xmm11); 1391 TestMovmsk(r14, xmm12); 1392 TestMovmsk(r15, xmm13); 1393 TestMovmsk(r1, xmm14); 1394 TestMovmsk(r2, xmm15); 1395 1396 #undef TestMovmskGPRXmm 1397 #undef TestMovmsk 1398 } 1399 1400 TEST_F(AssemblerX8664Test, Pmovsxdq) { 1401 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \ 1402 do { \ 1403 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \ 1404 const uint32_t T0 = allocateDqword(); \ 1405 const Dqword V0 Value1; \ 1406 const uint32_t T1 = allocateDqword(); \ 1407 const Dqword V1(uint64_t(0), uint64_t(0)); \ 1408 \ 1409 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ 1410 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ 1411 __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ 1412 \ 1413 AssembledTest test = assemble(); \ 1414 test.setDqwordTo(T0, V0); \ 1415 test.setDqwordTo(T1, V1); \ 1416 test.run(); \ 1417 \ 1418 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \ 1419 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ 1420 reset(); \ 1421 } while (0) 1422 1423 #define TestPmovsxdq(Dst, Src) \ 1424 do { \ 1425 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \ 1426 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1427 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \ 1428 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1429 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \ 1430 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1431 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \ 1432 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ 1433 } while (0) 1434 1435 TestPmovsxdq(xmm0, xmm1); 1436 TestPmovsxdq(xmm1, xmm2); 1437 TestPmovsxdq(xmm2, xmm3); 1438 TestPmovsxdq(xmm3, xmm4); 1439 TestPmovsxdq(xmm4, xmm5); 1440 TestPmovsxdq(xmm5, xmm6); 1441 TestPmovsxdq(xmm6, xmm7); 1442 TestPmovsxdq(xmm7, xmm8); 1443 TestPmovsxdq(xmm8, xmm9); 1444 TestPmovsxdq(xmm9, xmm10); 1445 TestPmovsxdq(xmm10, xmm11); 1446 TestPmovsxdq(xmm11, xmm12); 1447 TestPmovsxdq(xmm12, xmm13); 1448 TestPmovsxdq(xmm13, xmm14); 1449 TestPmovsxdq(xmm14, xmm15); 1450 TestPmovsxdq(xmm15, xmm0); 1451 1452 #undef TestPmovsxdq 1453 #undef TestPmovsxdqXmmXmm 1454 } 1455 1456 } // end of anonymous namespace 1457 } // end of namespace Test 1458 } // end of namespace X8664 1459 } // end of namespace Ice 1460