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 #ifdef __linux__ 89 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) { 90 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2))); 91 } 92 #endif 93 94 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value, 95 size_t Offset) { 96 return AllOf(OpcodeIs(Opcode), 97 ElementsAre(IsReg(X86::RSP), IsImm(1), IsReg(0), IsImm(Offset), 98 IsReg(0), IsImm(Value))); 99 } 100 101 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) { 102 return AllOf(OpcodeIs(Opcode), 103 ElementsAre(IsReg(Reg), IsReg(X86::RSP), IsImm(1), IsReg(0), 104 IsImm(0), IsReg(0))); 105 } 106 107 Matcher<MCInst> IsStackAllocate(unsigned Size) { 108 return AllOf(OpcodeIs(X86::SUB64ri8), 109 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size))); 110 } 111 112 Matcher<MCInst> IsStackDeallocate(unsigned Size) { 113 return AllOf(OpcodeIs(X86::ADD64ri8), 114 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size))); 115 } 116 117 constexpr const char kTriple[] = "x86_64-unknown-linux"; 118 119 class X86TargetTest : public ::testing::Test { 120 protected: 121 X86TargetTest(const char *Features) 122 : State(cantFail(LLVMState::Create(kTriple, "core2", Features))) {} 123 124 static void SetUpTestCase() { 125 LLVMInitializeX86TargetInfo(); 126 LLVMInitializeX86Target(); 127 LLVMInitializeX86TargetMC(); 128 InitializeX86ExegesisTarget(); 129 } 130 131 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) { 132 return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg, 133 Value); 134 } 135 136 const Instruction &getInstr(unsigned OpCode) { 137 return State.getIC().getInstr(OpCode); 138 } 139 140 LLVMState State; 141 }; 142 143 class X86Core2TargetTest : public X86TargetTest { 144 public: 145 X86Core2TargetTest() : X86TargetTest("") {} 146 }; 147 148 class X86Core2AvxTargetTest : public X86TargetTest { 149 public: 150 X86Core2AvxTargetTest() : X86TargetTest("+avx") {} 151 }; 152 153 class X86Core2Avx512TargetTest : public X86TargetTest { 154 public: 155 X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {} 156 }; 157 158 class X86Core2Avx512DQTargetTest : public X86TargetTest { 159 public: 160 X86Core2Avx512DQTargetTest() : X86TargetTest("+avx512dq") {} 161 }; 162 163 class X86Core2Avx512BWTargetTest : public X86TargetTest { 164 public: 165 X86Core2Avx512BWTargetTest() : X86TargetTest("+avx512bw") {} 166 }; 167 168 class X86Core2Avx512DQBWTargetTest : public X86TargetTest { 169 public: 170 X86Core2Avx512DQBWTargetTest() : X86TargetTest("+avx512dq,+avx512bw") {} 171 }; 172 173 TEST_F(X86Core2TargetTest, NoHighByteRegs) { 174 EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH)); 175 } 176 177 TEST_F(X86Core2TargetTest, SetFlags) { 178 const unsigned Reg = X86::EFLAGS; 179 EXPECT_THAT(setRegTo(Reg, APInt(64, 0x1111222233334444ULL)), 180 ElementsAre(IsStackAllocate(8), 181 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 182 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 183 OpcodeIs(X86::POPF64))); 184 } 185 186 TEST_F(X86Core2TargetTest, SetRegToGR8Value) { 187 const uint8_t Value = 0xFFU; 188 const unsigned Reg = X86::AL; 189 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)), 190 ElementsAre(IsMovImmediate(X86::MOV8ri, Reg, Value))); 191 } 192 193 TEST_F(X86Core2TargetTest, SetRegToGR16Value) { 194 const uint16_t Value = 0xFFFFU; 195 const unsigned Reg = X86::BX; 196 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)), 197 ElementsAre(IsMovImmediate(X86::MOV16ri, Reg, Value))); 198 } 199 200 TEST_F(X86Core2TargetTest, SetRegToGR32Value) { 201 const uint32_t Value = 0x7FFFFU; 202 const unsigned Reg = X86::ECX; 203 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)), 204 ElementsAre(IsMovImmediate(X86::MOV32ri, Reg, Value))); 205 } 206 207 TEST_F(X86Core2TargetTest, SetRegToGR64Value) { 208 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL; 209 const unsigned Reg = X86::RDX; 210 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)), 211 ElementsAre(IsMovImmediate(X86::MOV64ri, Reg, Value))); 212 } 213 214 TEST_F(X86Core2TargetTest, SetRegToVR64Value) { 215 EXPECT_THAT(setRegTo(X86::MM0, APInt(64, 0x1111222233334444ULL)), 216 ElementsAre(IsStackAllocate(8), 217 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 218 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 219 IsMovValueFromStack(X86::MMX_MOVQ64rm, X86::MM0), 220 IsStackDeallocate(8))); 221 } 222 223 TEST_F(X86Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) { 224 EXPECT_THAT( 225 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)), 226 ElementsAre(IsStackAllocate(16), 227 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 228 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 229 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 230 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 231 IsMovValueFromStack(X86::MOVDQUrm, X86::XMM0), 232 IsStackDeallocate(16))); 233 } 234 235 TEST_F(X86Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) { 236 EXPECT_THAT( 237 setRegTo(X86::XMM0, 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::VMOVDQUrm, X86::XMM0), 244 IsStackDeallocate(16))); 245 } 246 247 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) { 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::VMOVDQU32Z128rm, 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, SetRegToVR256Value_Use_VMOVDQU32Z256rm) { 278 const char ValueStr[] = 279 "1111111122222222333333334444444455555555666666667777777788888888"; 280 EXPECT_THAT( 281 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)), 282 ElementsAreArray({IsStackAllocate(32), 283 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 284 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 285 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 286 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 287 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 288 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 289 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 290 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 291 IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM0), 292 IsStackDeallocate(32)})); 293 } 294 295 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) { 296 const char ValueStr[] = 297 "1111111122222222333333334444444455555555666666667777777788888888" 298 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000"; 299 EXPECT_THAT( 300 setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)), 301 ElementsAreArray({IsStackAllocate(64), 302 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0), 303 IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4), 304 IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8), 305 IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12), 306 IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16), 307 IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20), 308 IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24), 309 IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28), 310 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32), 311 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36), 312 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40), 313 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44), 314 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48), 315 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52), 316 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56), 317 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60), 318 IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0), 319 IsStackDeallocate(64)})); 320 } 321 322 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_16Bits) { 323 const uint16_t Value = 0xABCDU; 324 const unsigned Reg = X86::K0; 325 const unsigned RegBitWidth = 16; 326 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 327 ElementsAre(IsStackAllocate(2), 328 IsMovValueToStack(X86::MOV16mi, Value, 0), 329 IsMovValueFromStack(X86::KMOVWkm, Reg), 330 IsStackDeallocate(2))); 331 } 332 333 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_16Bits) { 334 const uint16_t Value = 0xABCDU; 335 const unsigned Reg = X86::K0; 336 const unsigned RegBitWidth = 16; 337 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 338 ElementsAre(IsStackAllocate(2), 339 IsMovValueToStack(X86::MOV16mi, Value, 0), 340 IsMovValueFromStack(X86::KMOVWkm, Reg), 341 IsStackDeallocate(2))); 342 } 343 344 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_16Bits) { 345 const uint16_t Value = 0xABCDU; 346 const unsigned Reg = X86::K0; 347 const unsigned RegBitWidth = 16; 348 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 349 ElementsAre(IsStackAllocate(RegBitWidth / 8), 350 IsMovValueToStack(X86::MOV16mi, Value, 0), 351 IsMovValueFromStack(X86::KMOVWkm, Reg), 352 IsStackDeallocate(RegBitWidth / 8))); 353 } 354 355 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) { 356 const uint16_t Value = 0xABCDU; 357 const unsigned Reg = X86::K0; 358 const unsigned RegBitWidth = 16; 359 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 360 ElementsAre(IsStackAllocate(RegBitWidth / 8), 361 IsMovValueToStack(X86::MOV16mi, Value, 0), 362 IsMovValueFromStack(X86::KMOVWkm, Reg), 363 IsStackDeallocate(RegBitWidth / 8))); 364 } 365 366 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) { 367 const uint8_t Value = 0xABU; 368 const unsigned Reg = X86::K0; 369 const unsigned RegBitWidth = 8; 370 EXPECT_THAT( 371 setRegTo(Reg, APInt(RegBitWidth, Value)), 372 ElementsAre(IsStackAllocate(2), 373 IsMovValueToStack( 374 X86::MOV16mi, 375 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 376 IsMovValueFromStack(X86::KMOVWkm, Reg), 377 IsStackDeallocate(2))); 378 } 379 380 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) { 381 const uint8_t Value = 0xABU; 382 const unsigned Reg = X86::K0; 383 const unsigned RegBitWidth = 8; 384 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 385 ElementsAre(IsStackAllocate(RegBitWidth / 8), 386 IsMovValueToStack(X86::MOV8mi, Value, 0), 387 IsMovValueFromStack(X86::KMOVBkm, Reg), 388 IsStackDeallocate(RegBitWidth / 8))); 389 } 390 391 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) { 392 const uint8_t Value = 0xABU; 393 const unsigned Reg = X86::K0; 394 const unsigned RegBitWidth = 8; 395 EXPECT_THAT( 396 setRegTo(Reg, APInt(RegBitWidth, Value)), 397 ElementsAre(IsStackAllocate(2), 398 IsMovValueToStack( 399 X86::MOV16mi, 400 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 401 IsMovValueFromStack(X86::KMOVWkm, Reg), 402 IsStackDeallocate(2))); 403 } 404 405 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) { 406 const uint8_t Value = 0xABU; 407 const unsigned Reg = X86::K0; 408 const unsigned RegBitWidth = 8; 409 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 410 ElementsAre(IsStackAllocate(RegBitWidth / 8), 411 IsMovValueToStack(X86::MOV8mi, Value, 0), 412 IsMovValueFromStack(X86::KMOVBkm, Reg), 413 IsStackDeallocate(RegBitWidth / 8))); 414 } 415 416 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) { 417 const uint32_t Value = 0xABCDCABDU; 418 const unsigned Reg = X86::K0; 419 const unsigned RegBitWidth = 32; 420 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 421 } 422 423 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) { 424 const uint32_t Value = 0xABCDCABDU; 425 const unsigned Reg = X86::K0; 426 const unsigned RegBitWidth = 32; 427 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 428 } 429 430 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_32Bits) { 431 const uint32_t Value = 0xABCDCABDU; 432 const unsigned Reg = X86::K0; 433 const unsigned RegBitWidth = 32; 434 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 435 ElementsAre(IsStackAllocate(RegBitWidth / 8), 436 IsMovValueToStack(X86::MOV32mi, Value, 0), 437 IsMovValueFromStack(X86::KMOVDkm, Reg), 438 IsStackDeallocate(RegBitWidth / 8))); 439 } 440 441 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) { 442 const uint32_t Value = 0xABCDCABDU; 443 const unsigned Reg = X86::K0; 444 const unsigned RegBitWidth = 32; 445 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 446 ElementsAre(IsStackAllocate(RegBitWidth / 8), 447 IsMovValueToStack(X86::MOV32mi, Value, 0), 448 IsMovValueFromStack(X86::KMOVDkm, Reg), 449 IsStackDeallocate(RegBitWidth / 8))); 450 } 451 452 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) { 453 const uint64_t Value = 0xABCDABCDCABDCABDU; 454 const unsigned Reg = X86::K0; 455 const unsigned RegBitWidth = 64; 456 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 457 } 458 459 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) { 460 const uint64_t Value = 0xABCDABCDCABDCABDU; 461 const unsigned Reg = X86::K0; 462 const unsigned RegBitWidth = 64; 463 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 464 } 465 466 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) { 467 const uint64_t Value = 0xABCDABCDCABDCABDUL; 468 const unsigned Reg = X86::K0; 469 const unsigned RegBitWidth = 64; 470 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 471 ElementsAre(IsStackAllocate(RegBitWidth / 8), 472 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 473 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 474 IsMovValueFromStack(X86::KMOVQkm, Reg), 475 IsStackDeallocate(RegBitWidth / 8))); 476 } 477 478 TEST_F(X86Core2Avx512DQBWTargetTest, 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)), 483 ElementsAre(IsStackAllocate(RegBitWidth / 8), 484 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 485 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 486 IsMovValueFromStack(X86::KMOVQkm, Reg), 487 IsStackDeallocate(RegBitWidth / 8))); 488 } 489 490 // Note: We always put 80 bits on the stack independently of the size of the 491 // value. This uses a bit more space but makes the code simpler. 492 493 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) { 494 EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)), 495 ElementsAre(IsStackAllocate(10), 496 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 497 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 498 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 499 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 500 } 501 502 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) { 503 const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1); 504 EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)), 505 ElementsAre(IsStackAllocate(10), 506 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 507 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 508 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 509 OpcodeIs(X86::LD_F80m), CopySt0ToSt1, 510 IsStackDeallocate(10))); 511 } 512 513 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) { 514 EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)), 515 ElementsAre(IsStackAllocate(10), 516 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 517 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 518 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 519 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 520 } 521 522 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) { 523 EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)), 524 ElementsAre(IsStackAllocate(10), 525 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 526 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 527 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 528 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 529 } 530 531 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) { 532 EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)), 533 ElementsAre(IsStackAllocate(10), 534 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 535 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 536 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 537 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 538 } 539 540 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) { 541 EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)), 542 ElementsAre(IsStackAllocate(10), 543 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 544 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 545 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 546 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 547 } 548 549 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) { 550 EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)), 551 ElementsAre(IsStackAllocate(10), 552 IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0), 553 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 554 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 555 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 556 } 557 558 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) { 559 const Instruction &I = getInstr(X86::ADD64rm); 560 InstructionTemplate IT(&I); 561 constexpr const int kOffset = 42; 562 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 563 // Memory is operands 2-6. 564 EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI)); 565 EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1)); 566 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0)); 567 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset)); 568 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 569 } 570 571 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) { 572 const Instruction &I = getInstr(X86::VGATHERDPSZ128rm); 573 InstructionTemplate IT(&I); 574 constexpr const int kOffset = 42; 575 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 576 // Memory is operands 4-8. 577 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI)); 578 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1)); 579 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 580 EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset)); 581 EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0)); 582 } 583 584 TEST_F(X86Core2TargetTest, AllowAsBackToBack) { 585 EXPECT_TRUE( 586 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr))); 587 EXPECT_FALSE( 588 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r))); 589 } 590 591 #ifdef __linux__ 592 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) { 593 std::vector<MCInst> GeneratedCode; 594 State.getExegesisTarget().generateLowerMunmap(GeneratedCode); 595 EXPECT_THAT(GeneratedCode, 596 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0), 597 OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri), 598 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32), 599 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 600 OpcodeIs(X86::SYSCALL))); 601 } 602 603 #ifdef __arm__ 604 static constexpr const intptr_t VAddressSpaceCeiling = 0xC0000000; 605 #else 606 static constexpr const intptr_t VAddressSpaceCeiling = 0x0000800000000000; 607 #endif 608 609 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) { 610 std::vector<MCInst> GeneratedCode; 611 State.getExegesisTarget().generateUpperMunmap(GeneratedCode); 612 EXPECT_THAT( 613 GeneratedCode, 614 ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr), 615 OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri), 616 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32), 617 IsMovImmediate(X86::MOV64ri, X86::RSI, 618 VAddressSpaceCeiling - getpagesize()), 619 OpcodeIs(X86::SUB64rr), 620 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 621 OpcodeIs(X86::SYSCALL)})); 622 } 623 624 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) { 625 EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127), 626 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127), 627 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit), 628 OpcodeIs(X86::SYSCALL))); 629 } 630 631 // Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is 632 // not available, simplfy define it as MAP_FIXED which performs the same 633 // function but does not guarantee existing mappings won't get clobbered. 634 #ifndef MAP_FIXED_NOREPLACE 635 #define MAP_FIXED_NOREPLACE MAP_FIXED 636 #endif 637 638 // Some 32-bit architectures don't have mmap and define mmap2 instead. The only 639 // difference between the two syscalls is that mmap2's offset parameter is in 640 // terms 4096 byte offsets rather than individual bytes, so for our purposes 641 // they are effectively the same as all ofsets here are set to 0. 642 #if defined(SYS_mmap2) && !defined(SYS_mmap) 643 #define SYS_mmap SYS_mmap2 644 #endif 645 646 TEST_F(X86Core2TargetTest, GenerateMmapTest) { 647 EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000), 648 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000), 649 IsMovImmediate(X86::MOV64ri, X86::RSI, 4096), 650 IsMovImmediate(X86::MOV64ri, X86::RDX, 651 PROT_READ | PROT_WRITE), 652 IsMovImmediate(X86::MOV64ri, X86::R10, 653 MAP_SHARED | MAP_FIXED_NOREPLACE), 654 IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000), 655 OpcodeIs(X86::MOV32rm), 656 IsMovImmediate(X86::MOV64ri, X86::R9, 0), 657 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 658 OpcodeIs(X86::SYSCALL))); 659 } 660 661 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) { 662 std::vector<MCInst> GeneratedCode; 663 State.getExegesisTarget().generateMmapAuxMem(GeneratedCode); 664 EXPECT_THAT( 665 GeneratedCode, 666 ElementsAre( 667 IsMovImmediate( 668 X86::MOV64ri, X86::RDI, 669 State.getExegesisTarget().getAuxiliaryMemoryStartAddress()), 670 IsMovImmediate(X86::MOV64ri, X86::RSI, 671 SubprocessMemory::AuxiliaryMemorySize), 672 IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE), 673 IsMovImmediate(X86::MOV64ri, X86::R10, 674 MAP_SHARED | MAP_FIXED_NOREPLACE), 675 OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0), 676 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 677 OpcodeIs(X86::SYSCALL))); 678 } 679 680 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) { 681 std::vector<MCInst> GeneratedCode; 682 State.getExegesisTarget().moveArgumentRegisters(GeneratedCode); 683 EXPECT_THAT(GeneratedCode, 684 ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI), 685 IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI))); 686 } 687 #endif // __linux__ 688 689 } // namespace 690 } // namespace exegesis 691 } // namespace llvm 692