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