| OLD | NEW |
| (Empty) | |
| 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, Movzx) { |
| 267 static constexpr uint32_t Mask8 = 0x000000FF; |
| 268 static constexpr uint32_t Mask16 = 0x0000FFFF; |
| 269 |
| 270 #define TestImplRegReg(Dst, Src, Suffix, Size) \ |
| 271 do { \ |
| 272 const uint32_t T0 = allocateDqword(); \ |
| 273 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ |
| 274 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \ |
| 275 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ |
| 276 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \ |
| 277 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), \ |
| 278 Encoded_GPR_##Src##Suffix()); \ |
| 279 AssembledTest test = assemble(); \ |
| 280 test.setQwordTo(T0, V0); \ |
| 281 test.run(); \ |
| 282 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")"; \ |
| 283 reset(); \ |
| 284 } while (0) |
| 285 |
| 286 #define TestImplRegAddr(Dst, Suffix, Size) \ |
| 287 do { \ |
| 288 const uint32_t T0 = allocateDqword(); \ |
| 289 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ |
| 290 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \ |
| 291 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \ |
| 292 \ |
| 293 AssembledTest test = assemble(); \ |
| 294 test.setQwordTo(T0, (V0 & ~Mask##Size) | Value); \ |
| 295 test.run(); \ |
| 296 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")"; \ |
| 297 reset(); \ |
| 298 } while (0) |
| 299 |
| 300 #define TestImpl(Dst, Src) \ |
| 301 do { \ |
| 302 TestImplRegReg(Dst, Src, l, 8); \ |
| 303 TestImplRegAddr(Dst, l, 8); \ |
| 304 TestImplRegReg(Dst, Src, w, 16); \ |
| 305 TestImplRegAddr(Dst, w, 16); \ |
| 306 } while (0) |
| 307 |
| 308 TestImpl(r1, r2); |
| 309 TestImpl(r2, r3); |
| 310 TestImpl(r3, r4); |
| 311 TestImpl(r4, r5); |
| 312 TestImpl(r5, r6); |
| 313 TestImpl(r6, r7); |
| 314 TestImpl(r7, r8); |
| 315 TestImpl(r8, r10); |
| 316 TestImpl(r10, r11); |
| 317 TestImpl(r11, r12); |
| 318 TestImpl(r12, r13); |
| 319 TestImpl(r13, r14); |
| 320 TestImpl(r14, r15); |
| 321 TestImpl(r15, r1); |
| 322 |
| 323 #undef TestImpl |
| 324 #undef TestImplRegAddr |
| 325 #undef TestImplRegReg |
| 326 } |
| 327 |
| 328 TEST_F(AssemblerX8664Test, Movsx) { |
| 329 static constexpr uint64_t Mask8 = 0x000000FF; |
| 330 static constexpr uint64_t Mask16 = 0x0000FFFF; |
| 331 static constexpr uint64_t Mask32 = 0xFFFFFFFF; |
| 332 |
| 333 #define TestImplRegReg(Dst, Src, Suffix, Size) \ |
| 334 do { \ |
| 335 const uint32_t T0 = allocateDqword(); \ |
| 336 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \ |
| 337 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \ |
| 338 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ |
| 339 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \ |
| 340 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), \ |
| 341 Encoded_GPR_##Src##Suffix()); \ |
| 342 AssembledTest test = assemble(); \ |
| 343 test.setQwordTo(T0, V0); \ |
| 344 test.run(); \ |
| 345 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \ |
| 346 << "(" #Dst ", " #Src ", " #Size ")"; \ |
| 347 reset(); \ |
| 348 } while (0) |
| 349 |
| 350 #define TestImplRegAddr(Dst, Suffix, Size) \ |
| 351 do { \ |
| 352 const uint32_t T0 = allocateDqword(); \ |
| 353 static constexpr uint64_t V0 = 0xC0BEBEEF & Mask##Size; \ |
| 354 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \ |
| 355 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \ |
| 356 \ |
| 357 AssembledTest test = assemble(); \ |
| 358 test.setQwordTo(T0, V0); \ |
| 359 test.run(); \ |
| 360 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \ |
| 361 << "(" #Dst ", Addr, " #Size ")"; \ |
| 362 reset(); \ |
| 363 } while (0) |
| 364 |
| 365 #define TestImpl(Dst, Src) \ |
| 366 do { \ |
| 367 TestImplRegReg(Dst, Src, l, 8); \ |
| 368 TestImplRegAddr(Dst, l, 8); \ |
| 369 TestImplRegReg(Dst, Src, w, 16); \ |
| 370 TestImplRegAddr(Dst, w, 16); \ |
| 371 TestImplRegReg(Dst, Src, w, 32); \ |
| 372 TestImplRegAddr(Dst, w, 32); \ |
| 373 } while (0) |
| 374 |
| 375 TestImpl(r1, r2); |
| 376 TestImpl(r2, r3); |
| 377 TestImpl(r3, r4); |
| 378 TestImpl(r4, r5); |
| 379 TestImpl(r5, r6); |
| 380 TestImpl(r6, r7); |
| 381 TestImpl(r7, r8); |
| 382 TestImpl(r8, r10); |
| 383 TestImpl(r10, r11); |
| 384 TestImpl(r11, r12); |
| 385 TestImpl(r12, r13); |
| 386 TestImpl(r13, r14); |
| 387 TestImpl(r14, r15); |
| 388 TestImpl(r15, r1); |
| 389 |
| 390 #undef TestImpl |
| 391 #undef TestImplRegAddr |
| 392 #undef TestImplRegReg |
| 393 } |
| 394 |
| 395 TEST_F(AssemblerX8664Test, Cmov) { |
| 396 #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \ |
| 397 do { \ |
| 398 static constexpr char TestString[] = \ |
| 399 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \ |
| 400 ", " #Value1 ")"; \ |
| 401 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \ |
| 402 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \ |
| 403 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \ |
| 404 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \ |
| 405 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \ |
| 406 Encoded_GPR_##Src1()); \ |
| 407 \ |
| 408 AssembledTest test = assemble(); \ |
| 409 test.run(); \ |
| 410 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \ |
| 411 \ |
| 412 reset(); \ |
| 413 } while (0) |
| 414 |
| 415 #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1) \ |
| 416 do { \ |
| 417 static constexpr char TestString[] = \ |
| 418 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 \ |
| 419 ", Addr, " #Value1 ")"; \ |
| 420 const uint32_t T0 = allocateDword(); \ |
| 421 const uint32_t V0 = Value1; \ |
| 422 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \ |
| 423 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \ |
| 424 __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0)); \ |
| 425 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \ |
| 426 dwordAddress(T0)); \ |
| 427 \ |
| 428 AssembledTest test = assemble(); \ |
| 429 test.setDwordTo(T0, V0); \ |
| 430 test.run(); \ |
| 431 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \ |
| 432 \ |
| 433 reset(); \ |
| 434 } while (0) |
| 435 |
| 436 #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \ |
| 437 do { \ |
| 438 TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1); \ |
| 439 TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1); \ |
| 440 } while (0) |
| 441 |
| 442 #define TestImpl(Dest, Src0, Src1) \ |
| 443 do { \ |
| 444 TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 445 TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \ |
| 446 TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \ |
| 447 TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 448 TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \ |
| 449 TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 450 TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 451 TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 452 TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \ |
| 453 TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \ |
| 454 TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 455 TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \ |
| 456 TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 457 TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 458 TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 459 TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 460 TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 461 TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 462 TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 463 TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 464 TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 465 TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 466 TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 467 TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 468 TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 469 TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 470 TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 471 TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 472 TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \ |
| 473 TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \ |
| 474 } while (0) |
| 475 |
| 476 TestImpl(r1, r2, r3); |
| 477 |
| 478 #undef TestImpl |
| 479 #undef TestValue |
| 480 #undef TestRegAddr |
| 481 #undef TestRegReg |
| 482 } |
| 483 |
| 484 TEST_F(AssemblerX8664LowLevelTest, RepMovsb) { |
| 485 __ rep_movsb(); |
| 486 |
| 487 static constexpr uint32_t ByteCount = 2; |
| 488 static constexpr uint8_t Prefix = 0xF3; |
| 489 static constexpr uint8_t Opcode = 0xA4; |
| 490 |
| 491 ASSERT_EQ(ByteCount, codeBytesSize()); |
| 492 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode); |
| 493 } |
| 494 |
| 495 TEST_F(AssemblerX8664Test, MovssXmmAddr) { |
| 496 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \ |
| 497 do { \ |
| 498 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 499 "Invalid fp length #FloatLength"); \ |
| 500 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 501 \ |
| 502 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ |
| 503 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 504 const uint32_t T0 = allocateQword(); \ |
| 505 const Type V0 = Value; \ |
| 506 \ |
| 507 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \ |
| 508 \ |
| 509 AssembledTest test = assemble(); \ |
| 510 if (IsDouble) { \ |
| 511 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 512 } else { \ |
| 513 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 514 } \ |
| 515 test.run(); \ |
| 516 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ |
| 517 << Value; \ |
| 518 reset(); \ |
| 519 } while (0) |
| 520 |
| 521 #define TestMovssXmmAddr(FloatLength) \ |
| 522 do { \ |
| 523 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 524 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 525 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \ |
| 526 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \ |
| 527 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \ |
| 528 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \ |
| 529 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \ |
| 530 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \ |
| 531 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \ |
| 532 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \ |
| 533 TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value); \ |
| 534 TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value); \ |
| 535 TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value); \ |
| 536 TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value); \ |
| 537 TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value); \ |
| 538 TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value); \ |
| 539 TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value); \ |
| 540 TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value); \ |
| 541 } \ |
| 542 } while (0) |
| 543 |
| 544 TestMovssXmmAddr(32); |
| 545 TestMovssXmmAddr(64); |
| 546 |
| 547 #undef TestMovssXmmAddr |
| 548 #undef TestMovssXmmAddrType |
| 549 } |
| 550 |
| 551 TEST_F(AssemblerX8664Test, MovssAddrXmm) { |
| 552 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \ |
| 553 do { \ |
| 554 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 555 "Invalid fp length #FloatLength"); \ |
| 556 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 557 \ |
| 558 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ |
| 559 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 560 const uint32_t T0 = allocateQword(); \ |
| 561 const Type V0 = Value; \ |
| 562 const uint32_t T1 = allocateQword(); \ |
| 563 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ |
| 564 "f" #FloatLength " does not have quiet nan."); \ |
| 565 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ |
| 566 \ |
| 567 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \ |
| 568 \ |
| 569 AssembledTest test = assemble(); \ |
| 570 if (IsDouble) { \ |
| 571 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 572 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 573 } else { \ |
| 574 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 575 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 576 } \ |
| 577 test.run(); \ |
| 578 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ |
| 579 << Value; \ |
| 580 reset(); \ |
| 581 } while (0) |
| 582 |
| 583 #define TestMovssAddrXmm(FloatLength) \ |
| 584 do { \ |
| 585 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 586 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 587 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \ |
| 588 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \ |
| 589 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \ |
| 590 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \ |
| 591 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \ |
| 592 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \ |
| 593 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \ |
| 594 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \ |
| 595 TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value); \ |
| 596 TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value); \ |
| 597 TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value); \ |
| 598 TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value); \ |
| 599 TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value); \ |
| 600 TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value); \ |
| 601 TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value); \ |
| 602 TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value); \ |
| 603 } \ |
| 604 } while (0) |
| 605 |
| 606 TestMovssAddrXmm(32); |
| 607 TestMovssAddrXmm(64); |
| 608 |
| 609 #undef TestMovssAddrXmm |
| 610 #undef TestMovssAddrXmmType |
| 611 } |
| 612 |
| 613 TEST_F(AssemblerX8664Test, MovssXmmXmm) { |
| 614 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \ |
| 615 do { \ |
| 616 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 617 "Invalid fp length #FloatLength"); \ |
| 618 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 619 \ |
| 620 static constexpr char TestString[] = \ |
| 621 "(" #FloatLength ", " #Src ", " #Dst ")"; \ |
| 622 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 623 const uint32_t T0 = allocateQword(); \ |
| 624 const Type V0 = Value; \ |
| 625 const uint32_t T1 = allocateQword(); \ |
| 626 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ |
| 627 "f" #FloatLength " does not have quiet nan."); \ |
| 628 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ |
| 629 \ |
| 630 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 631 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 632 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), \ |
| 633 Encoded_Xmm_##Src()); \ |
| 634 \ |
| 635 AssembledTest test = assemble(); \ |
| 636 if (IsDouble) { \ |
| 637 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 638 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 639 } else { \ |
| 640 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 641 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 642 } \ |
| 643 test.run(); \ |
| 644 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \ |
| 645 << Value; \ |
| 646 reset(); \ |
| 647 } while (0) |
| 648 |
| 649 #define TestMovssXmmXmm(FloatLength) \ |
| 650 do { \ |
| 651 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 652 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 653 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \ |
| 654 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \ |
| 655 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \ |
| 656 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \ |
| 657 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \ |
| 658 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \ |
| 659 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \ |
| 660 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value); \ |
| 661 TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value); \ |
| 662 TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value); \ |
| 663 TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value); \ |
| 664 TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value); \ |
| 665 TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value); \ |
| 666 TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value); \ |
| 667 TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value); \ |
| 668 TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value); \ |
| 669 } \ |
| 670 } while (0) |
| 671 |
| 672 TestMovssXmmXmm(32); |
| 673 TestMovssXmmXmm(64); |
| 674 |
| 675 #undef TestMovssXmmXmm |
| 676 #undef TestMovssXmmXmmType |
| 677 } |
| 678 |
| 679 TEST_F(AssemblerX8664Test, MovdToXmm) { |
| 680 #define TestMovdXmmReg(Src, Dst, Value) \ |
| 681 do { \ |
| 682 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 683 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 684 const uint32_t T0 = allocateQword(); \ |
| 685 const uint64_t V0 = 0xFFFFFFFF00000000ull; \ |
| 686 \ |
| 687 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \ |
| 688 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 689 __ movd(Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \ |
| 690 \ |
| 691 AssembledTest test = assemble(); \ |
| 692 \ |
| 693 test.setQwordTo(T0, V0); \ |
| 694 test.run(); \ |
| 695 \ |
| 696 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 697 << Value; \ |
| 698 reset(); \ |
| 699 } while (0) |
| 700 |
| 701 #define TestMovdXmmAddr(Dst, Value) \ |
| 702 do { \ |
| 703 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 704 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 705 const uint32_t T0 = allocateQword(); \ |
| 706 const uint32_t V0 = Value; \ |
| 707 const uint32_t T1 = allocateQword(); \ |
| 708 const uint64_t V1 = 0xFFFFFFFF00000000ull; \ |
| 709 \ |
| 710 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 711 __ movd(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 712 \ |
| 713 AssembledTest test = assemble(); \ |
| 714 \ |
| 715 test.setDwordTo(T0, V0); \ |
| 716 test.setQwordTo(T1, V1); \ |
| 717 test.run(); \ |
| 718 \ |
| 719 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 720 << Value; \ |
| 721 reset(); \ |
| 722 } while (0) |
| 723 |
| 724 #define TestMovd(Dst) \ |
| 725 do { \ |
| 726 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ |
| 727 TestMovdXmmReg(r1, Dst, Value); \ |
| 728 TestMovdXmmReg(r2, Dst, Value); \ |
| 729 TestMovdXmmReg(r3, Dst, Value); \ |
| 730 TestMovdXmmReg(r4, Dst, Value); \ |
| 731 TestMovdXmmReg(r5, Dst, Value); \ |
| 732 TestMovdXmmReg(r6, Dst, Value); \ |
| 733 TestMovdXmmReg(r7, Dst, Value); \ |
| 734 TestMovdXmmReg(r8, Dst, Value); \ |
| 735 TestMovdXmmReg(r10, Dst, Value); \ |
| 736 TestMovdXmmReg(r11, Dst, Value); \ |
| 737 TestMovdXmmReg(r12, Dst, Value); \ |
| 738 TestMovdXmmReg(r13, Dst, Value); \ |
| 739 TestMovdXmmReg(r14, Dst, Value); \ |
| 740 TestMovdXmmReg(r15, Dst, Value); \ |
| 741 TestMovdXmmAddr(Dst, Value); \ |
| 742 } \ |
| 743 } while (0) |
| 744 |
| 745 TestMovd(xmm0); |
| 746 TestMovd(xmm1); |
| 747 TestMovd(xmm2); |
| 748 TestMovd(xmm3); |
| 749 TestMovd(xmm4); |
| 750 TestMovd(xmm5); |
| 751 TestMovd(xmm6); |
| 752 TestMovd(xmm7); |
| 753 TestMovd(xmm8); |
| 754 TestMovd(xmm9); |
| 755 TestMovd(xmm10); |
| 756 TestMovd(xmm11); |
| 757 TestMovd(xmm12); |
| 758 TestMovd(xmm13); |
| 759 TestMovd(xmm14); |
| 760 TestMovd(xmm15); |
| 761 |
| 762 #undef TestMovdXmmAddr |
| 763 #undef TestMovdXmmReg |
| 764 #undef TestMovd |
| 765 } |
| 766 |
| 767 TEST_F(AssemblerX8664Test, MovdFromXmm) { |
| 768 #define TestMovdRegXmm(Src, Dst, Value) \ |
| 769 do { \ |
| 770 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 771 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 772 const uint32_t T0 = allocateDword(); \ |
| 773 const uint32_t V0 = Value; \ |
| 774 \ |
| 775 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 776 __ movd(Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \ |
| 777 \ |
| 778 AssembledTest test = assemble(); \ |
| 779 \ |
| 780 test.setDwordTo(T0, V0); \ |
| 781 test.run(); \ |
| 782 \ |
| 783 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \ |
| 784 << Value; \ |
| 785 reset(); \ |
| 786 } while (0) |
| 787 |
| 788 #define TestMovdAddrXmm(Src, Value) \ |
| 789 do { \ |
| 790 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 791 static constexpr char TestString[] = "(" #Src ", Addr)"; \ |
| 792 const uint32_t T0 = allocateDword(); \ |
| 793 const uint32_t V0 = Value; \ |
| 794 const uint32_t T1 = allocateDword(); \ |
| 795 const uint32_t V1 = ~(Value); \ |
| 796 \ |
| 797 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 798 __ movd(dwordAddress(T1), Encoded_Xmm_##Src()); \ |
| 799 \ |
| 800 AssembledTest test = assemble(); \ |
| 801 \ |
| 802 test.setDwordTo(T0, V0); \ |
| 803 test.setDwordTo(T1, V1); \ |
| 804 test.run(); \ |
| 805 \ |
| 806 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \ |
| 807 << Value; \ |
| 808 reset(); \ |
| 809 } while (0) |
| 810 |
| 811 #define TestMovd(Src) \ |
| 812 do { \ |
| 813 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ |
| 814 TestMovdRegXmm(Src, r1, Value); \ |
| 815 TestMovdRegXmm(Src, r2, Value); \ |
| 816 TestMovdRegXmm(Src, r3, Value); \ |
| 817 TestMovdRegXmm(Src, r4, Value); \ |
| 818 TestMovdRegXmm(Src, r5, Value); \ |
| 819 TestMovdRegXmm(Src, r6, Value); \ |
| 820 TestMovdRegXmm(Src, r7, Value); \ |
| 821 TestMovdRegXmm(Src, r8, Value); \ |
| 822 TestMovdRegXmm(Src, r10, Value); \ |
| 823 TestMovdRegXmm(Src, r11, Value); \ |
| 824 TestMovdRegXmm(Src, r12, Value); \ |
| 825 TestMovdRegXmm(Src, r13, Value); \ |
| 826 TestMovdRegXmm(Src, r14, Value); \ |
| 827 TestMovdRegXmm(Src, r15, Value); \ |
| 828 TestMovdAddrXmm(Src, Value); \ |
| 829 } \ |
| 830 } while (0) |
| 831 |
| 832 TestMovd(xmm0); |
| 833 TestMovd(xmm1); |
| 834 TestMovd(xmm2); |
| 835 TestMovd(xmm3); |
| 836 TestMovd(xmm4); |
| 837 TestMovd(xmm5); |
| 838 TestMovd(xmm6); |
| 839 TestMovd(xmm7); |
| 840 TestMovd(xmm8); |
| 841 TestMovd(xmm9); |
| 842 TestMovd(xmm10); |
| 843 TestMovd(xmm11); |
| 844 TestMovd(xmm12); |
| 845 TestMovd(xmm13); |
| 846 TestMovd(xmm14); |
| 847 TestMovd(xmm15); |
| 848 |
| 849 #undef TestMovdAddrXmm |
| 850 #undef TestMovdRegXmm |
| 851 #undef TestMovd |
| 852 } |
| 853 |
| 854 TEST_F(AssemblerX8664Test, MovqXmmAddr) { |
| 855 #define TestMovd(Dst, Value) \ |
| 856 do { \ |
| 857 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 858 const uint32_t T0 = allocateQword(); \ |
| 859 const uint64_t V0 = Value; \ |
| 860 const uint32_t T1 = allocateQword(); \ |
| 861 const uint64_t V1 = ~(Value); \ |
| 862 \ |
| 863 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 864 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 865 \ |
| 866 AssembledTest test = assemble(); \ |
| 867 \ |
| 868 test.setQwordTo(T0, V0); \ |
| 869 test.setQwordTo(T1, V1); \ |
| 870 test.run(); \ |
| 871 \ |
| 872 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 873 << Value; \ |
| 874 reset(); \ |
| 875 } while (0) |
| 876 |
| 877 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 878 TestMovd(xmm0, Value); |
| 879 TestMovd(xmm1, Value); |
| 880 TestMovd(xmm2, Value); |
| 881 TestMovd(xmm3, Value); |
| 882 TestMovd(xmm4, Value); |
| 883 TestMovd(xmm5, Value); |
| 884 TestMovd(xmm6, Value); |
| 885 TestMovd(xmm7, Value); |
| 886 TestMovd(xmm8, Value); |
| 887 TestMovd(xmm9, Value); |
| 888 TestMovd(xmm10, Value); |
| 889 TestMovd(xmm11, Value); |
| 890 TestMovd(xmm12, Value); |
| 891 TestMovd(xmm13, Value); |
| 892 TestMovd(xmm14, Value); |
| 893 TestMovd(xmm15, Value); |
| 894 } |
| 895 |
| 896 #undef TestMovd |
| 897 } |
| 898 |
| 899 TEST_F(AssemblerX8664Test, MovqAddrXmm) { |
| 900 #define TestMovd(Dst, Value) \ |
| 901 do { \ |
| 902 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 903 const uint32_t T0 = allocateQword(); \ |
| 904 const uint64_t V0 = Value; \ |
| 905 const uint32_t T1 = allocateQword(); \ |
| 906 const uint64_t V1 = ~(Value); \ |
| 907 \ |
| 908 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 909 __ movq(dwordAddress(T1), Encoded_Xmm_##Dst()); \ |
| 910 \ |
| 911 AssembledTest test = assemble(); \ |
| 912 \ |
| 913 test.setQwordTo(T0, V0); \ |
| 914 test.setQwordTo(T1, V1); \ |
| 915 test.run(); \ |
| 916 \ |
| 917 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 918 << Value; \ |
| 919 reset(); \ |
| 920 } while (0) |
| 921 |
| 922 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 923 TestMovd(xmm0, Value); |
| 924 TestMovd(xmm1, Value); |
| 925 TestMovd(xmm2, Value); |
| 926 TestMovd(xmm3, Value); |
| 927 TestMovd(xmm4, Value); |
| 928 TestMovd(xmm5, Value); |
| 929 TestMovd(xmm6, Value); |
| 930 TestMovd(xmm7, Value); |
| 931 TestMovd(xmm8, Value); |
| 932 TestMovd(xmm9, Value); |
| 933 TestMovd(xmm10, Value); |
| 934 TestMovd(xmm11, Value); |
| 935 TestMovd(xmm12, Value); |
| 936 TestMovd(xmm13, Value); |
| 937 TestMovd(xmm14, Value); |
| 938 TestMovd(xmm15, Value); |
| 939 } |
| 940 |
| 941 #undef TestMovd |
| 942 } |
| 943 |
| 944 TEST_F(AssemblerX8664Test, MovqXmmXmm) { |
| 945 #define TestMovd(Src, Dst, Value) \ |
| 946 do { \ |
| 947 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 948 const uint32_t T0 = allocateQword(); \ |
| 949 const uint64_t V0 = Value; \ |
| 950 const uint32_t T1 = allocateQword(); \ |
| 951 const uint64_t V1 = ~(Value); \ |
| 952 \ |
| 953 __ movq(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 954 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 955 __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ |
| 956 \ |
| 957 AssembledTest test = assemble(); \ |
| 958 \ |
| 959 test.setQwordTo(T0, V0); \ |
| 960 test.setQwordTo(T1, V1); \ |
| 961 test.run(); \ |
| 962 \ |
| 963 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 964 << Value; \ |
| 965 reset(); \ |
| 966 } while (0) |
| 967 |
| 968 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 969 TestMovd(xmm0, xmm1, Value); |
| 970 TestMovd(xmm1, xmm2, Value); |
| 971 TestMovd(xmm2, xmm3, Value); |
| 972 TestMovd(xmm3, xmm4, Value); |
| 973 TestMovd(xmm4, xmm5, Value); |
| 974 TestMovd(xmm5, xmm6, Value); |
| 975 TestMovd(xmm6, xmm7, Value); |
| 976 TestMovd(xmm7, xmm8, Value); |
| 977 TestMovd(xmm8, xmm9, Value); |
| 978 TestMovd(xmm9, xmm10, Value); |
| 979 TestMovd(xmm10, xmm11, Value); |
| 980 TestMovd(xmm11, xmm12, Value); |
| 981 TestMovd(xmm12, xmm13, Value); |
| 982 TestMovd(xmm13, xmm14, Value); |
| 983 TestMovd(xmm14, xmm15, Value); |
| 984 TestMovd(xmm15, xmm0, Value); |
| 985 } |
| 986 |
| 987 #undef TestMovd |
| 988 } |
| 989 |
| 990 TEST_F(AssemblerX8664Test, MovupsXmmAddr) { |
| 991 #define TestMovups(Dst) \ |
| 992 do { \ |
| 993 static constexpr char TestString[] = "(" #Dst ")"; \ |
| 994 const uint32_t T0 = allocateDqword(); \ |
| 995 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 996 std::numeric_limits<float>::infinity()); \ |
| 997 \ |
| 998 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 999 \ |
| 1000 AssembledTest test = assemble(); \ |
| 1001 test.setDqwordTo(T0, V0); \ |
| 1002 test.run(); \ |
| 1003 \ |
| 1004 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 1005 reset(); \ |
| 1006 } while (0) |
| 1007 |
| 1008 TestMovups(xmm0); |
| 1009 TestMovups(xmm1); |
| 1010 TestMovups(xmm2); |
| 1011 TestMovups(xmm3); |
| 1012 TestMovups(xmm4); |
| 1013 TestMovups(xmm5); |
| 1014 TestMovups(xmm6); |
| 1015 TestMovups(xmm7); |
| 1016 TestMovups(xmm8); |
| 1017 TestMovups(xmm9); |
| 1018 TestMovups(xmm10); |
| 1019 TestMovups(xmm11); |
| 1020 TestMovups(xmm12); |
| 1021 TestMovups(xmm13); |
| 1022 TestMovups(xmm14); |
| 1023 TestMovups(xmm15); |
| 1024 |
| 1025 #undef TestMovups |
| 1026 } |
| 1027 |
| 1028 TEST_F(AssemblerX8664Test, MovupsAddrXmm) { |
| 1029 #define TestMovups(Src) \ |
| 1030 do { \ |
| 1031 static constexpr char TestString[] = "(" #Src ")"; \ |
| 1032 const uint32_t T0 = allocateDqword(); \ |
| 1033 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 1034 std::numeric_limits<float>::infinity()); \ |
| 1035 const uint32_t T1 = allocateDqword(); \ |
| 1036 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 1037 \ |
| 1038 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 1039 __ movups(dwordAddress(T1), Encoded_Xmm_##Src()); \ |
| 1040 \ |
| 1041 AssembledTest test = assemble(); \ |
| 1042 test.setDqwordTo(T0, V0); \ |
| 1043 test.setDqwordTo(T1, V1); \ |
| 1044 test.run(); \ |
| 1045 \ |
| 1046 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \ |
| 1047 reset(); \ |
| 1048 } while (0) |
| 1049 |
| 1050 TestMovups(xmm0); |
| 1051 TestMovups(xmm1); |
| 1052 TestMovups(xmm2); |
| 1053 TestMovups(xmm3); |
| 1054 TestMovups(xmm4); |
| 1055 TestMovups(xmm5); |
| 1056 TestMovups(xmm6); |
| 1057 TestMovups(xmm7); |
| 1058 TestMovups(xmm8); |
| 1059 TestMovups(xmm9); |
| 1060 TestMovups(xmm10); |
| 1061 TestMovups(xmm11); |
| 1062 TestMovups(xmm12); |
| 1063 TestMovups(xmm13); |
| 1064 TestMovups(xmm14); |
| 1065 TestMovups(xmm15); |
| 1066 |
| 1067 #undef TestMovups |
| 1068 } |
| 1069 |
| 1070 TEST_F(AssemblerX8664Test, MovupsXmmXmm) { |
| 1071 #define TestMovups(Dst, Src) \ |
| 1072 do { \ |
| 1073 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ |
| 1074 const uint32_t T0 = allocateDqword(); \ |
| 1075 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 1076 std::numeric_limits<float>::infinity()); \ |
| 1077 const uint32_t T1 = allocateDqword(); \ |
| 1078 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 1079 \ |
| 1080 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 1081 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 1082 __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ |
| 1083 \ |
| 1084 AssembledTest test = assemble(); \ |
| 1085 test.setDqwordTo(T0, V0); \ |
| 1086 test.setDqwordTo(T1, V1); \ |
| 1087 test.run(); \ |
| 1088 \ |
| 1089 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 1090 reset(); \ |
| 1091 } while (0) |
| 1092 |
| 1093 TestMovups(xmm0, xmm1); |
| 1094 TestMovups(xmm1, xmm2); |
| 1095 TestMovups(xmm2, xmm3); |
| 1096 TestMovups(xmm3, xmm4); |
| 1097 TestMovups(xmm4, xmm5); |
| 1098 TestMovups(xmm5, xmm6); |
| 1099 TestMovups(xmm6, xmm7); |
| 1100 TestMovups(xmm7, xmm8); |
| 1101 TestMovups(xmm8, xmm9); |
| 1102 TestMovups(xmm9, xmm10); |
| 1103 TestMovups(xmm10, xmm11); |
| 1104 TestMovups(xmm11, xmm12); |
| 1105 TestMovups(xmm12, xmm13); |
| 1106 TestMovups(xmm13, xmm14); |
| 1107 TestMovups(xmm14, xmm15); |
| 1108 TestMovups(xmm15, xmm0); |
| 1109 |
| 1110 #undef TestMovups |
| 1111 } |
| 1112 |
| 1113 TEST_F(AssemblerX8664Test, MovapsXmmXmm) { |
| 1114 #define TestMovaps(Dst, Src) \ |
| 1115 do { \ |
| 1116 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ |
| 1117 const uint32_t T0 = allocateDqword(); \ |
| 1118 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 1119 std::numeric_limits<float>::infinity()); \ |
| 1120 const uint32_t T1 = allocateDqword(); \ |
| 1121 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 1122 \ |
| 1123 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 1124 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 1125 __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ |
| 1126 \ |
| 1127 AssembledTest test = assemble(); \ |
| 1128 test.setDqwordTo(T0, V0); \ |
| 1129 test.setDqwordTo(T1, V1); \ |
| 1130 test.run(); \ |
| 1131 \ |
| 1132 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 1133 reset(); \ |
| 1134 } while (0) |
| 1135 |
| 1136 TestMovaps(xmm0, xmm1); |
| 1137 TestMovaps(xmm1, xmm2); |
| 1138 TestMovaps(xmm2, xmm3); |
| 1139 TestMovaps(xmm3, xmm4); |
| 1140 TestMovaps(xmm4, xmm5); |
| 1141 TestMovaps(xmm5, xmm6); |
| 1142 TestMovaps(xmm6, xmm7); |
| 1143 TestMovaps(xmm7, xmm8); |
| 1144 TestMovaps(xmm8, xmm9); |
| 1145 TestMovaps(xmm9, xmm10); |
| 1146 TestMovaps(xmm10, xmm11); |
| 1147 TestMovaps(xmm11, xmm12); |
| 1148 TestMovaps(xmm12, xmm13); |
| 1149 TestMovaps(xmm13, xmm14); |
| 1150 TestMovaps(xmm14, xmm15); |
| 1151 TestMovaps(xmm15, xmm0); |
| 1152 |
| 1153 #undef TestMovaps |
| 1154 } |
| 1155 |
| 1156 TEST_F(AssemblerX8664Test, Movhlps_Movlhps) { |
| 1157 #define TestImplSingle(Dst, Src, Inst, Expect) \ |
| 1158 do { \ |
| 1159 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ |
| 1160 const uint32_t T0 = allocateDqword(); \ |
| 1161 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 1162 uint64_t(0xCCCCCCCCDDDDDDDDull)); \ |
| 1163 const uint32_t T1 = allocateDqword(); \ |
| 1164 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \ |
| 1165 uint64_t(0x9999999988888888ull)); \ |
| 1166 \ |
| 1167 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \ |
| 1168 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \ |
| 1169 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ |
| 1170 \ |
| 1171 AssembledTest test = assemble(); \ |
| 1172 test.setDqwordTo(T0, V0); \ |
| 1173 test.setDqwordTo(T1, V1); \ |
| 1174 test.run(); \ |
| 1175 \ |
| 1176 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \ |
| 1177 reset(); \ |
| 1178 } while (0) |
| 1179 |
| 1180 #define TestImpl(Dst, Src) \ |
| 1181 do { \ |
| 1182 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \ |
| 1183 uint64_t(0xCCCCCCCCDDDDDDDDull))); \ |
| 1184 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 1185 uint64_t(0xEEEEEEEEFFFFFFFFull))); \ |
| 1186 } while (0) |
| 1187 |
| 1188 TestImpl(xmm0, xmm1); |
| 1189 TestImpl(xmm1, xmm2); |
| 1190 TestImpl(xmm2, xmm3); |
| 1191 TestImpl(xmm3, xmm4); |
| 1192 TestImpl(xmm4, xmm5); |
| 1193 TestImpl(xmm5, xmm6); |
| 1194 TestImpl(xmm6, xmm7); |
| 1195 TestImpl(xmm7, xmm8); |
| 1196 TestImpl(xmm8, xmm9); |
| 1197 TestImpl(xmm9, xmm10); |
| 1198 TestImpl(xmm10, xmm11); |
| 1199 TestImpl(xmm11, xmm12); |
| 1200 TestImpl(xmm12, xmm13); |
| 1201 TestImpl(xmm13, xmm14); |
| 1202 TestImpl(xmm14, xmm15); |
| 1203 TestImpl(xmm15, xmm0); |
| 1204 |
| 1205 #undef TestImpl |
| 1206 #undef TestImplSingle |
| 1207 } |
| 1208 |
| 1209 TEST_F(AssemblerX8664Test, Movmsk) { |
| 1210 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \ |
| 1211 do { \ |
| 1212 static constexpr char TestString[] = \ |
| 1213 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \ |
| 1214 const uint32_t T0 = allocateDqword(); \ |
| 1215 const Dqword V0 Value1; \ |
| 1216 \ |
| 1217 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 1218 __ Inst(Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \ |
| 1219 \ |
| 1220 AssembledTest test = assemble(); \ |
| 1221 test.setDqwordTo(T0, V0); \ |
| 1222 test.run(); \ |
| 1223 \ |
| 1224 ASSERT_EQ(Expected, test.GPR()) << TestString; \ |
| 1225 reset(); \ |
| 1226 } while (0) |
| 1227 |
| 1228 #define TestMovmsk(GPR, Src) \ |
| 1229 do { \ |
| 1230 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmskps); \ |
| 1231 TestMovmskGPRXmm(GPR, Src, (1.0, -1.0), 0x02ul, movmskpd); \ |
| 1232 } while (0) |
| 1233 |
| 1234 TestMovmsk(r1, xmm0); |
| 1235 TestMovmsk(r2, xmm1); |
| 1236 TestMovmsk(r3, xmm2); |
| 1237 TestMovmsk(r4, xmm3); |
| 1238 TestMovmsk(r5, xmm4); |
| 1239 TestMovmsk(r6, xmm5); |
| 1240 TestMovmsk(r7, xmm6); |
| 1241 TestMovmsk(r8, xmm7); |
| 1242 TestMovmsk(r10, xmm8); |
| 1243 TestMovmsk(r11, xmm9); |
| 1244 TestMovmsk(r12, xmm10); |
| 1245 TestMovmsk(r13, xmm11); |
| 1246 TestMovmsk(r14, xmm12); |
| 1247 TestMovmsk(r15, xmm13); |
| 1248 TestMovmsk(r1, xmm14); |
| 1249 TestMovmsk(r2, xmm15); |
| 1250 |
| 1251 #undef TestMovmskGPRXmm |
| 1252 #undef TestMovmsk |
| 1253 } |
| 1254 |
| 1255 TEST_F(AssemblerX8664Test, Pmovsxdq) { |
| 1256 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \ |
| 1257 do { \ |
| 1258 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \ |
| 1259 const uint32_t T0 = allocateDqword(); \ |
| 1260 const Dqword V0 Value1; \ |
| 1261 const uint32_t T1 = allocateDqword(); \ |
| 1262 const Dqword V1(uint64_t(0), uint64_t(0)); \ |
| 1263 \ |
| 1264 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \ |
| 1265 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \ |
| 1266 __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \ |
| 1267 \ |
| 1268 AssembledTest test = assemble(); \ |
| 1269 test.setDqwordTo(T0, V0); \ |
| 1270 test.setDqwordTo(T1, V1); \ |
| 1271 test.run(); \ |
| 1272 \ |
| 1273 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \ |
| 1274 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1275 reset(); \ |
| 1276 } while (0) |
| 1277 |
| 1278 #define TestPmovsxdq(Dst, Src) \ |
| 1279 do { \ |
| 1280 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \ |
| 1281 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1282 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \ |
| 1283 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1284 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \ |
| 1285 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1286 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \ |
| 1287 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1288 } while (0) |
| 1289 |
| 1290 TestPmovsxdq(xmm0, xmm1); |
| 1291 TestPmovsxdq(xmm1, xmm2); |
| 1292 TestPmovsxdq(xmm2, xmm3); |
| 1293 TestPmovsxdq(xmm3, xmm4); |
| 1294 TestPmovsxdq(xmm4, xmm5); |
| 1295 TestPmovsxdq(xmm5, xmm6); |
| 1296 TestPmovsxdq(xmm6, xmm7); |
| 1297 TestPmovsxdq(xmm7, xmm8); |
| 1298 TestPmovsxdq(xmm8, xmm9); |
| 1299 TestPmovsxdq(xmm9, xmm10); |
| 1300 TestPmovsxdq(xmm10, xmm11); |
| 1301 TestPmovsxdq(xmm11, xmm12); |
| 1302 TestPmovsxdq(xmm12, xmm13); |
| 1303 TestPmovsxdq(xmm13, xmm14); |
| 1304 TestPmovsxdq(xmm14, xmm15); |
| 1305 TestPmovsxdq(xmm15, xmm0); |
| 1306 |
| 1307 #undef TestPmovsxdq |
| 1308 #undef TestPmovsxdqXmmXmm |
| 1309 } |
| 1310 |
| 1311 } // end of anonymous namespace |
| 1312 } // end of namespace Test |
| 1313 } // end of namespace X8664 |
| 1314 } // end of namespace Ice |
| OLD | NEW |