1 //===-- TargetTest.cpp -----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Target.h" 10 11 #include <cassert> 12 #include <memory> 13 14 #include "MCTargetDesc/X86MCTargetDesc.h" 15 #include "MmapUtils.h" 16 #include "SubprocessMemory.h" 17 #include "TestBase.h" 18 #include "llvm/MC/TargetRegistry.h" 19 #include "llvm/Support/TargetSelect.h" 20 #include "gmock/gmock.h" 21 #include "gtest/gtest.h" 22 23 #include "llvm/MC/MCInstPrinter.h" 24 25 #ifdef __linux__ 26 #include <sys/mman.h> 27 #include <sys/syscall.h> 28 #endif // __linux__ 29 30 namespace llvm { 31 32 bool operator==(const MCOperand &a, const MCOperand &b) { 33 if (a.isImm() && b.isImm()) 34 return a.getImm() == b.getImm(); 35 if (a.isReg() && b.isReg()) 36 return a.getReg() == b.getReg(); 37 return false; 38 } 39 40 bool operator==(const MCInst &a, const MCInst &b) { 41 if (a.getOpcode() != b.getOpcode()) 42 return false; 43 if (a.getNumOperands() != b.getNumOperands()) 44 return false; 45 for (unsigned I = 0; I < a.getNumOperands(); ++I) { 46 if (!(a.getOperand(I) == b.getOperand(I))) 47 return false; 48 } 49 return true; 50 } 51 52 } // namespace llvm 53 54 namespace llvm { 55 namespace exegesis { 56 57 void InitializeX86ExegesisTarget(); 58 59 namespace { 60 61 using testing::AllOf; 62 using testing::ElementsAre; 63 using testing::ElementsAreArray; 64 using testing::Eq; 65 using testing::IsEmpty; 66 using testing::Matcher; 67 using testing::Property; 68 69 Matcher<MCOperand> IsImm(int64_t Value) { 70 return AllOf(Property(&MCOperand::isImm, Eq(true)), 71 Property(&MCOperand::getImm, Eq(Value))); 72 } 73 74 Matcher<MCOperand> IsReg(unsigned Reg) { 75 return AllOf(Property(&MCOperand::isReg, Eq(true)), 76 Property(&MCOperand::getReg, Eq(Reg))); 77 } 78 79 Matcher<MCInst> OpcodeIs(unsigned Opcode) { 80 return Property(&MCInst::getOpcode, Eq(Opcode)); 81 } 82 83 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) { 84 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value))); 85 } 86 87 #ifdef __linux__ 88 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) { 89 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2))); 90 } 91 #endif 92 93 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value, 94 size_t Offset) { 95 return AllOf(OpcodeIs(Opcode), 96 ElementsAre(IsReg(X86::RSP), IsImm(1), IsReg(0), IsImm(Offset), 97 IsReg(0), IsImm(Value))); 98 } 99 100 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) { 101 return AllOf(OpcodeIs(Opcode), 102 ElementsAre(IsReg(Reg), IsReg(X86::RSP), IsImm(1), IsReg(0), 103 IsImm(0), IsReg(0))); 104 } 105 106 Matcher<MCInst> IsStackAllocate(unsigned Size) { 107 return AllOf(OpcodeIs(X86::SUB64ri8), 108 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size))); 109 } 110 111 Matcher<MCInst> IsStackDeallocate(unsigned Size) { 112 return AllOf(OpcodeIs(X86::ADD64ri8), 113 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size))); 114 } 115 116 class X86TargetTest : public X86TestBase { 117 protected: 118 X86TargetTest(const char *Features) : X86TestBase("core2", Features) {} 119 120 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) { 121 return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg, 122 Value); 123 } 124 125 const Instruction &getInstr(unsigned OpCode) { 126 return State.getIC().getInstr(OpCode); 127 } 128 }; 129 130 class X86Core2TargetTest : public X86TargetTest { 131 public: 132 X86Core2TargetTest() : X86TargetTest("") {} 133 }; 134 135 class X86Core2AvxTargetTest : public X86TargetTest { 136 public: 137 X86Core2AvxTargetTest() : X86TargetTest("+avx") {} 138 }; 139 140 class X86Core2Avx512TargetTest : public X86TargetTest { 141 public: 142 X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {} 143 }; 144 145 class X86Core2Avx512DQTargetTest : public X86TargetTest { 146 public: 147 X86Core2Avx512DQTargetTest() : X86TargetTest("+avx512dq") {} 148 }; 149 150 class X86Core2Avx512BWTargetTest : public X86TargetTest { 151 public: 152 X86Core2Avx512BWTargetTest() : X86TargetTest("+avx512bw") {} 153 }; 154 155 class X86Core2Avx512DQBWTargetTest : public X86TargetTest { 156 public: 157 X86Core2Avx512DQBWTargetTest() : X86TargetTest("+avx512dq,+avx512bw") {} 158 }; 159 160 TEST_F(X86Core2TargetTest, NoHighByteRegs) { 161 EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH)); 162 } 163 164 TEST_F(X86Core2TargetTest, SetFlags) { 165 const unsigned Reg = X86::EFLAGS; 166 EXPECT_THAT(setRegTo(Reg, APInt(64, 0x1111222233334444ULL)), 167 ElementsAre(IsStackAllocate(8), 168 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 169 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 170 OpcodeIs(X86::POPF64))); 171 } 172 173 TEST_F(X86Core2TargetTest, SetRegToGR8Value) { 174 const uint8_t Value = 0xFFU; 175 const unsigned Reg = X86::AL; 176 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)), 177 ElementsAre(IsMovImmediate(X86::MOV8ri, Reg, Value))); 178 } 179 180 TEST_F(X86Core2TargetTest, SetRegToGR16Value) { 181 const uint16_t Value = 0xFFFFU; 182 const unsigned Reg = X86::BX; 183 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)), 184 ElementsAre(IsMovImmediate(X86::MOV16ri, Reg, Value))); 185 } 186 187 TEST_F(X86Core2TargetTest, SetRegToGR32Value) { 188 const uint32_t Value = 0x7FFFFU; 189 const unsigned Reg = X86::ECX; 190 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)), 191 ElementsAre(IsMovImmediate(X86::MOV32ri, Reg, Value))); 192 } 193 194 TEST_F(X86Core2TargetTest, SetRegToGR64Value) { 195 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL; 196 const unsigned Reg = X86::RDX; 197 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)), 198 ElementsAre(IsMovImmediate(X86::MOV64ri, Reg, Value))); 199 } 200 201 TEST_F(X86Core2TargetTest, SetRegToVR64Value) { 202 EXPECT_THAT(setRegTo(X86::MM0, APInt(64, 0x1111222233334444ULL)), 203 ElementsAre(IsStackAllocate(8), 204 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 205 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 206 IsMovValueFromStack(X86::MMX_MOVQ64rm, X86::MM0), 207 IsStackDeallocate(8))); 208 } 209 210 TEST_F(X86Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) { 211 EXPECT_THAT( 212 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)), 213 ElementsAre(IsStackAllocate(16), 214 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 215 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 216 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 217 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 218 IsMovValueFromStack(X86::MOVDQUrm, X86::XMM0), 219 IsStackDeallocate(16))); 220 } 221 222 TEST_F(X86Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) { 223 EXPECT_THAT( 224 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)), 225 ElementsAre(IsStackAllocate(16), 226 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 227 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 228 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 229 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 230 IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0), 231 IsStackDeallocate(16))); 232 } 233 234 TEST_F(X86Core2Avx512TargetTest, 235 SetRegToVR128ValueHighXMM_Use_VMOVDQU32Z128rm) { 236 EXPECT_THAT( 237 setRegTo(X86::XMM16, APInt(128, "11112222333344445555666677778888", 16)), 238 ElementsAre(IsStackAllocate(16), 239 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 240 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 241 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 242 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 243 IsMovValueFromStack(X86::VMOVDQU32Z128rm, X86::XMM16), 244 IsStackDeallocate(16))); 245 } 246 247 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128ValueLowXMM_Use_VMOVDQUrm) { 248 EXPECT_THAT( 249 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)), 250 ElementsAre(IsStackAllocate(16), 251 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 252 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 253 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 254 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 255 IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0), 256 IsStackDeallocate(16))); 257 } 258 259 TEST_F(X86Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) { 260 const char ValueStr[] = 261 "1111111122222222333333334444444455555555666666667777777788888888"; 262 EXPECT_THAT( 263 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)), 264 ElementsAreArray({IsStackAllocate(32), 265 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 266 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 267 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 268 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 269 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 270 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 271 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 272 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 273 IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0), 274 IsStackDeallocate(32)})); 275 } 276 277 TEST_F(X86Core2Avx512TargetTest, 278 SetRegToVR256ValueHighYMM_Use_VMOVDQU32Z256rm) { 279 const char ValueStr[] = 280 "1111111122222222333333334444444455555555666666667777777788888888"; 281 EXPECT_THAT( 282 setRegTo(X86::YMM16, APInt(256, ValueStr, 16)), 283 ElementsAreArray({IsStackAllocate(32), 284 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 285 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 286 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 287 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 288 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 289 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 290 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 291 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 292 IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM16), 293 IsStackDeallocate(32)})); 294 } 295 296 TEST_F(X86Core2Avx512TargetTest, SetRegToVR256ValueLowYMM_Use_VMOVDQUYrm) { 297 const char ValueStr[] = 298 "1111111122222222333333334444444455555555666666667777777788888888"; 299 EXPECT_THAT( 300 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)), 301 ElementsAreArray({IsStackAllocate(32), 302 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 303 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 304 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 305 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 306 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 307 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 308 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 309 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 310 IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0), 311 IsStackDeallocate(32)})); 312 } 313 314 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) { 315 const char ValueStr[] = 316 "1111111122222222333333334444444455555555666666667777777788888888" 317 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000"; 318 EXPECT_THAT( 319 setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)), 320 ElementsAreArray({IsStackAllocate(64), 321 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0), 322 IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4), 323 IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8), 324 IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12), 325 IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16), 326 IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20), 327 IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24), 328 IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28), 329 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32), 330 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36), 331 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40), 332 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44), 333 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48), 334 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52), 335 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56), 336 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60), 337 IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0), 338 IsStackDeallocate(64)})); 339 } 340 341 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_16Bits) { 342 const uint16_t Value = 0xABCDU; 343 const unsigned Reg = X86::K0; 344 const unsigned RegBitWidth = 16; 345 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 346 ElementsAre(IsStackAllocate(2), 347 IsMovValueToStack(X86::MOV16mi, Value, 0), 348 IsMovValueFromStack(X86::KMOVWkm, Reg), 349 IsStackDeallocate(2))); 350 } 351 352 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_16Bits) { 353 const uint16_t Value = 0xABCDU; 354 const unsigned Reg = X86::K0; 355 const unsigned RegBitWidth = 16; 356 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 357 ElementsAre(IsStackAllocate(2), 358 IsMovValueToStack(X86::MOV16mi, Value, 0), 359 IsMovValueFromStack(X86::KMOVWkm, Reg), 360 IsStackDeallocate(2))); 361 } 362 363 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_16Bits) { 364 const uint16_t Value = 0xABCDU; 365 const unsigned Reg = X86::K0; 366 const unsigned RegBitWidth = 16; 367 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 368 ElementsAre(IsStackAllocate(RegBitWidth / 8), 369 IsMovValueToStack(X86::MOV16mi, Value, 0), 370 IsMovValueFromStack(X86::KMOVWkm, Reg), 371 IsStackDeallocate(RegBitWidth / 8))); 372 } 373 374 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) { 375 const uint16_t Value = 0xABCDU; 376 const unsigned Reg = X86::K0; 377 const unsigned RegBitWidth = 16; 378 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 379 ElementsAre(IsStackAllocate(RegBitWidth / 8), 380 IsMovValueToStack(X86::MOV16mi, Value, 0), 381 IsMovValueFromStack(X86::KMOVWkm, Reg), 382 IsStackDeallocate(RegBitWidth / 8))); 383 } 384 385 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) { 386 const uint8_t Value = 0xABU; 387 const unsigned Reg = X86::K0; 388 const unsigned RegBitWidth = 8; 389 EXPECT_THAT( 390 setRegTo(Reg, APInt(RegBitWidth, Value)), 391 ElementsAre(IsStackAllocate(2), 392 IsMovValueToStack( 393 X86::MOV16mi, 394 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 395 IsMovValueFromStack(X86::KMOVWkm, Reg), 396 IsStackDeallocate(2))); 397 } 398 399 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) { 400 const uint8_t Value = 0xABU; 401 const unsigned Reg = X86::K0; 402 const unsigned RegBitWidth = 8; 403 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 404 ElementsAre(IsStackAllocate(RegBitWidth / 8), 405 IsMovValueToStack(X86::MOV8mi, Value, 0), 406 IsMovValueFromStack(X86::KMOVBkm, Reg), 407 IsStackDeallocate(RegBitWidth / 8))); 408 } 409 410 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) { 411 const uint8_t Value = 0xABU; 412 const unsigned Reg = X86::K0; 413 const unsigned RegBitWidth = 8; 414 EXPECT_THAT( 415 setRegTo(Reg, APInt(RegBitWidth, Value)), 416 ElementsAre(IsStackAllocate(2), 417 IsMovValueToStack( 418 X86::MOV16mi, 419 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 420 IsMovValueFromStack(X86::KMOVWkm, Reg), 421 IsStackDeallocate(2))); 422 } 423 424 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) { 425 const uint8_t Value = 0xABU; 426 const unsigned Reg = X86::K0; 427 const unsigned RegBitWidth = 8; 428 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 429 ElementsAre(IsStackAllocate(RegBitWidth / 8), 430 IsMovValueToStack(X86::MOV8mi, Value, 0), 431 IsMovValueFromStack(X86::KMOVBkm, Reg), 432 IsStackDeallocate(RegBitWidth / 8))); 433 } 434 435 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) { 436 const uint32_t Value = 0xABCDCABDU; 437 const unsigned Reg = X86::K0; 438 const unsigned RegBitWidth = 32; 439 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 440 } 441 442 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) { 443 const uint32_t Value = 0xABCDCABDU; 444 const unsigned Reg = X86::K0; 445 const unsigned RegBitWidth = 32; 446 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 447 } 448 449 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_32Bits) { 450 const uint32_t Value = 0xABCDCABDU; 451 const unsigned Reg = X86::K0; 452 const unsigned RegBitWidth = 32; 453 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 454 ElementsAre(IsStackAllocate(RegBitWidth / 8), 455 IsMovValueToStack(X86::MOV32mi, Value, 0), 456 IsMovValueFromStack(X86::KMOVDkm, Reg), 457 IsStackDeallocate(RegBitWidth / 8))); 458 } 459 460 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) { 461 const uint32_t Value = 0xABCDCABDU; 462 const unsigned Reg = X86::K0; 463 const unsigned RegBitWidth = 32; 464 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 465 ElementsAre(IsStackAllocate(RegBitWidth / 8), 466 IsMovValueToStack(X86::MOV32mi, Value, 0), 467 IsMovValueFromStack(X86::KMOVDkm, Reg), 468 IsStackDeallocate(RegBitWidth / 8))); 469 } 470 471 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) { 472 const uint64_t Value = 0xABCDABCDCABDCABDU; 473 const unsigned Reg = X86::K0; 474 const unsigned RegBitWidth = 64; 475 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 476 } 477 478 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) { 479 const uint64_t Value = 0xABCDABCDCABDCABDU; 480 const unsigned Reg = X86::K0; 481 const unsigned RegBitWidth = 64; 482 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 483 } 484 485 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) { 486 const uint64_t Value = 0xABCDABCDCABDCABDUL; 487 const unsigned Reg = X86::K0; 488 const unsigned RegBitWidth = 64; 489 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 490 ElementsAre(IsStackAllocate(RegBitWidth / 8), 491 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 492 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 493 IsMovValueFromStack(X86::KMOVQkm, Reg), 494 IsStackDeallocate(RegBitWidth / 8))); 495 } 496 497 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_64Bits) { 498 const uint64_t Value = 0xABCDABCDCABDCABDU; 499 const unsigned Reg = X86::K0; 500 const unsigned RegBitWidth = 64; 501 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 502 ElementsAre(IsStackAllocate(RegBitWidth / 8), 503 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 504 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 505 IsMovValueFromStack(X86::KMOVQkm, Reg), 506 IsStackDeallocate(RegBitWidth / 8))); 507 } 508 509 // Note: We always put 80 bits on the stack independently of the size of the 510 // value. This uses a bit more space but makes the code simpler. 511 512 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) { 513 EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)), 514 ElementsAre(IsStackAllocate(10), 515 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 516 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 517 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 518 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 519 } 520 521 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) { 522 const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1); 523 EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)), 524 ElementsAre(IsStackAllocate(10), 525 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 526 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 527 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 528 OpcodeIs(X86::LD_F80m), CopySt0ToSt1, 529 IsStackDeallocate(10))); 530 } 531 532 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) { 533 EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)), 534 ElementsAre(IsStackAllocate(10), 535 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 536 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 537 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 538 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 539 } 540 541 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) { 542 EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)), 543 ElementsAre(IsStackAllocate(10), 544 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 545 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 546 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 547 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 548 } 549 550 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) { 551 EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)), 552 ElementsAre(IsStackAllocate(10), 553 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 554 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 555 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 556 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 557 } 558 559 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) { 560 EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)), 561 ElementsAre(IsStackAllocate(10), 562 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 563 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 564 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 565 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 566 } 567 568 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) { 569 EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)), 570 ElementsAre(IsStackAllocate(10), 571 IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0), 572 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 573 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 574 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 575 } 576 577 TEST_F(X86Core2TargetTest, SetRegToDf1) { 578 EXPECT_THAT(setRegTo(X86::DF, APInt(1, 1)), ElementsAre(OpcodeIs(X86::STD))); 579 } 580 581 TEST_F(X86Core2TargetTest, SetRegToDf0) { 582 EXPECT_THAT(setRegTo(X86::DF, APInt(1, 0)), ElementsAre(OpcodeIs(X86::CLD))); 583 } 584 585 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) { 586 const Instruction &I = getInstr(X86::ADD64rm); 587 InstructionTemplate IT(&I); 588 constexpr const int kOffset = 42; 589 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 590 // Memory is operands 2-6. 591 EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI)); 592 EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1)); 593 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0)); 594 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset)); 595 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 596 } 597 598 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) { 599 const Instruction &I = getInstr(X86::VGATHERDPSZ128rm); 600 InstructionTemplate IT(&I); 601 constexpr const int kOffset = 42; 602 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 603 // Memory is operands 4-8. 604 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI)); 605 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1)); 606 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 607 EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset)); 608 EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0)); 609 } 610 611 TEST_F(X86Core2TargetTest, AllowAsBackToBack) { 612 EXPECT_TRUE( 613 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr))); 614 EXPECT_FALSE( 615 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r))); 616 } 617 618 #ifdef __linux__ 619 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) { 620 std::vector<MCInst> GeneratedCode; 621 State.getExegesisTarget().generateLowerMunmap(GeneratedCode); 622 EXPECT_THAT(GeneratedCode, 623 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0), 624 OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri), 625 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32), 626 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 627 OpcodeIs(X86::SYSCALL))); 628 } 629 630 #ifdef __arm__ 631 static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000; 632 #else 633 static constexpr const uintptr_t VAddressSpaceCeiling = 0x0000800000000000; 634 #endif 635 636 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) { 637 std::vector<MCInst> GeneratedCode; 638 State.getExegesisTarget().generateUpperMunmap(GeneratedCode); 639 EXPECT_THAT( 640 GeneratedCode, 641 ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr), 642 OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri), 643 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32), 644 IsMovImmediate(X86::MOV64ri, X86::RSI, 645 VAddressSpaceCeiling - getpagesize()), 646 OpcodeIs(X86::SUB64rr), 647 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 648 OpcodeIs(X86::SYSCALL)})); 649 } 650 651 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) { 652 EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127), 653 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127), 654 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit), 655 OpcodeIs(X86::SYSCALL))); 656 } 657 658 TEST_F(X86Core2TargetTest, GenerateMmapTest) { 659 EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000), 660 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000), 661 IsMovImmediate(X86::MOV64ri, X86::RSI, 4096), 662 IsMovImmediate(X86::MOV64ri, X86::RDX, 663 PROT_READ | PROT_WRITE), 664 IsMovImmediate(X86::MOV64ri, X86::R10, 665 MAP_SHARED | MAP_FIXED_NOREPLACE), 666 IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000), 667 OpcodeIs(X86::MOV32rm), 668 IsMovImmediate(X86::MOV64ri, X86::R9, 0), 669 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 670 OpcodeIs(X86::SYSCALL))); 671 } 672 673 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) { 674 std::vector<MCInst> GeneratedCode; 675 State.getExegesisTarget().generateMmapAuxMem(GeneratedCode); 676 EXPECT_THAT( 677 GeneratedCode, 678 ElementsAre( 679 IsMovImmediate( 680 X86::MOV64ri, X86::RDI, 681 State.getExegesisTarget().getAuxiliaryMemoryStartAddress()), 682 IsMovImmediate(X86::MOV64ri, X86::RSI, 683 SubprocessMemory::AuxiliaryMemorySize), 684 IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE), 685 IsMovImmediate(X86::MOV64ri, X86::R10, 686 MAP_SHARED | MAP_FIXED_NOREPLACE), 687 OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0), 688 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 689 OpcodeIs(X86::SYSCALL))); 690 } 691 692 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) { 693 std::vector<MCInst> GeneratedCode; 694 State.getExegesisTarget().moveArgumentRegisters(GeneratedCode); 695 EXPECT_THAT(GeneratedCode, 696 ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI), 697 IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI))); 698 } 699 #endif // __linux__ 700 701 } // namespace 702 } // namespace exegesis 703 } // namespace llvm 704