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 "llvm/MC/TargetRegistry.h" 18 #include "llvm/Support/TargetSelect.h" 19 #include "gmock/gmock.h" 20 #include "gtest/gtest.h" 21 22 #include "llvm/MC/MCInstPrinter.h" 23 24 #ifdef __linux__ 25 #include <sys/mman.h> 26 #include <sys/syscall.h> 27 #endif // __linux__ 28 29 namespace llvm { 30 31 bool operator==(const MCOperand &a, const MCOperand &b) { 32 if (a.isImm() && b.isImm()) 33 return a.getImm() == b.getImm(); 34 if (a.isReg() && b.isReg()) 35 return a.getReg() == b.getReg(); 36 return false; 37 } 38 39 bool operator==(const MCInst &a, const MCInst &b) { 40 if (a.getOpcode() != b.getOpcode()) 41 return false; 42 if (a.getNumOperands() != b.getNumOperands()) 43 return false; 44 for (unsigned I = 0; I < a.getNumOperands(); ++I) { 45 if (!(a.getOperand(I) == b.getOperand(I))) 46 return false; 47 } 48 return true; 49 } 50 51 } // namespace llvm 52 53 namespace llvm { 54 namespace exegesis { 55 56 void InitializeX86ExegesisTarget(); 57 58 namespace { 59 60 using testing::AllOf; 61 using testing::ElementsAre; 62 using testing::ElementsAreArray; 63 using testing::Eq; 64 using testing::IsEmpty; 65 using testing::Matcher; 66 using testing::Property; 67 68 Matcher<MCOperand> IsImm(int64_t Value) { 69 return AllOf(Property(&MCOperand::isImm, Eq(true)), 70 Property(&MCOperand::getImm, Eq(Value))); 71 } 72 73 Matcher<MCOperand> IsReg(unsigned Reg) { 74 return AllOf(Property(&MCOperand::isReg, Eq(true)), 75 Property(&MCOperand::getReg, Eq(Reg))); 76 } 77 78 Matcher<MCInst> OpcodeIs(unsigned Opcode) { 79 return Property(&MCInst::getOpcode, Eq(Opcode)); 80 } 81 82 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) { 83 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value))); 84 } 85 86 #ifdef __linux__ 87 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) { 88 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2))); 89 } 90 #endif 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, 246 SetRegToVR128ValueHighXMM_Use_VMOVDQU32Z128rm) { 247 EXPECT_THAT( 248 setRegTo(X86::XMM16, APInt(128, "11112222333344445555666677778888", 16)), 249 ElementsAre(IsStackAllocate(16), 250 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 251 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 252 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 253 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 254 IsMovValueFromStack(X86::VMOVDQU32Z128rm, X86::XMM16), 255 IsStackDeallocate(16))); 256 } 257 258 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128ValueLowXMM_Use_VMOVDQUrm) { 259 EXPECT_THAT( 260 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)), 261 ElementsAre(IsStackAllocate(16), 262 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0), 263 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4), 264 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8), 265 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12), 266 IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0), 267 IsStackDeallocate(16))); 268 } 269 270 TEST_F(X86Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) { 271 const char ValueStr[] = 272 "1111111122222222333333334444444455555555666666667777777788888888"; 273 EXPECT_THAT( 274 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)), 275 ElementsAreArray({IsStackAllocate(32), 276 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 277 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 278 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 279 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 280 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 281 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 282 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 283 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 284 IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0), 285 IsStackDeallocate(32)})); 286 } 287 288 TEST_F(X86Core2Avx512TargetTest, 289 SetRegToVR256ValueHighYMM_Use_VMOVDQU32Z256rm) { 290 const char ValueStr[] = 291 "1111111122222222333333334444444455555555666666667777777788888888"; 292 EXPECT_THAT( 293 setRegTo(X86::YMM16, APInt(256, ValueStr, 16)), 294 ElementsAreArray({IsStackAllocate(32), 295 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 296 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 297 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 298 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 299 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 300 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 301 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 302 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 303 IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM16), 304 IsStackDeallocate(32)})); 305 } 306 307 TEST_F(X86Core2Avx512TargetTest, SetRegToVR256ValueLowYMM_Use_VMOVDQUYrm) { 308 const char ValueStr[] = 309 "1111111122222222333333334444444455555555666666667777777788888888"; 310 EXPECT_THAT( 311 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)), 312 ElementsAreArray({IsStackAllocate(32), 313 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0), 314 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4), 315 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8), 316 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12), 317 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16), 318 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20), 319 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24), 320 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28), 321 IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0), 322 IsStackDeallocate(32)})); 323 } 324 325 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) { 326 const char ValueStr[] = 327 "1111111122222222333333334444444455555555666666667777777788888888" 328 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000"; 329 EXPECT_THAT( 330 setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)), 331 ElementsAreArray({IsStackAllocate(64), 332 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0), 333 IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4), 334 IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8), 335 IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12), 336 IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16), 337 IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20), 338 IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24), 339 IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28), 340 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32), 341 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36), 342 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40), 343 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44), 344 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48), 345 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52), 346 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56), 347 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60), 348 IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0), 349 IsStackDeallocate(64)})); 350 } 351 352 TEST_F(X86Core2Avx512TargetTest, 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(X86Core2Avx512DQTargetTest, 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(2), 369 IsMovValueToStack(X86::MOV16mi, Value, 0), 370 IsMovValueFromStack(X86::KMOVWkm, Reg), 371 IsStackDeallocate(2))); 372 } 373 374 TEST_F(X86Core2Avx512BWTargetTest, 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(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) { 386 const uint16_t Value = 0xABCDU; 387 const unsigned Reg = X86::K0; 388 const unsigned RegBitWidth = 16; 389 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 390 ElementsAre(IsStackAllocate(RegBitWidth / 8), 391 IsMovValueToStack(X86::MOV16mi, Value, 0), 392 IsMovValueFromStack(X86::KMOVWkm, Reg), 393 IsStackDeallocate(RegBitWidth / 8))); 394 } 395 396 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) { 397 const uint8_t Value = 0xABU; 398 const unsigned Reg = X86::K0; 399 const unsigned RegBitWidth = 8; 400 EXPECT_THAT( 401 setRegTo(Reg, APInt(RegBitWidth, Value)), 402 ElementsAre(IsStackAllocate(2), 403 IsMovValueToStack( 404 X86::MOV16mi, 405 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 406 IsMovValueFromStack(X86::KMOVWkm, Reg), 407 IsStackDeallocate(2))); 408 } 409 410 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) { 411 const uint8_t Value = 0xABU; 412 const unsigned Reg = X86::K0; 413 const unsigned RegBitWidth = 8; 414 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 415 ElementsAre(IsStackAllocate(RegBitWidth / 8), 416 IsMovValueToStack(X86::MOV8mi, Value, 0), 417 IsMovValueFromStack(X86::KMOVBkm, Reg), 418 IsStackDeallocate(RegBitWidth / 8))); 419 } 420 421 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) { 422 const uint8_t Value = 0xABU; 423 const unsigned Reg = X86::K0; 424 const unsigned RegBitWidth = 8; 425 EXPECT_THAT( 426 setRegTo(Reg, APInt(RegBitWidth, Value)), 427 ElementsAre(IsStackAllocate(2), 428 IsMovValueToStack( 429 X86::MOV16mi, 430 APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0), 431 IsMovValueFromStack(X86::KMOVWkm, Reg), 432 IsStackDeallocate(2))); 433 } 434 435 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) { 436 const uint8_t Value = 0xABU; 437 const unsigned Reg = X86::K0; 438 const unsigned RegBitWidth = 8; 439 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 440 ElementsAre(IsStackAllocate(RegBitWidth / 8), 441 IsMovValueToStack(X86::MOV8mi, Value, 0), 442 IsMovValueFromStack(X86::KMOVBkm, Reg), 443 IsStackDeallocate(RegBitWidth / 8))); 444 } 445 446 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) { 447 const uint32_t Value = 0xABCDCABDU; 448 const unsigned Reg = X86::K0; 449 const unsigned RegBitWidth = 32; 450 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 451 } 452 453 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) { 454 const uint32_t Value = 0xABCDCABDU; 455 const unsigned Reg = X86::K0; 456 const unsigned RegBitWidth = 32; 457 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 458 } 459 460 TEST_F(X86Core2Avx512BWTargetTest, 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(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) { 472 const uint32_t Value = 0xABCDCABDU; 473 const unsigned Reg = X86::K0; 474 const unsigned RegBitWidth = 32; 475 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 476 ElementsAre(IsStackAllocate(RegBitWidth / 8), 477 IsMovValueToStack(X86::MOV32mi, Value, 0), 478 IsMovValueFromStack(X86::KMOVDkm, Reg), 479 IsStackDeallocate(RegBitWidth / 8))); 480 } 481 482 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) { 483 const uint64_t Value = 0xABCDABCDCABDCABDU; 484 const unsigned Reg = X86::K0; 485 const unsigned RegBitWidth = 64; 486 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 487 } 488 489 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) { 490 const uint64_t Value = 0xABCDABCDCABDCABDU; 491 const unsigned Reg = X86::K0; 492 const unsigned RegBitWidth = 64; 493 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty()); 494 } 495 496 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) { 497 const uint64_t Value = 0xABCDABCDCABDCABDUL; 498 const unsigned Reg = X86::K0; 499 const unsigned RegBitWidth = 64; 500 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 501 ElementsAre(IsStackAllocate(RegBitWidth / 8), 502 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 503 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 504 IsMovValueFromStack(X86::KMOVQkm, Reg), 505 IsStackDeallocate(RegBitWidth / 8))); 506 } 507 508 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_64Bits) { 509 const uint64_t Value = 0xABCDABCDCABDCABDU; 510 const unsigned Reg = X86::K0; 511 const unsigned RegBitWidth = 64; 512 EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), 513 ElementsAre(IsStackAllocate(RegBitWidth / 8), 514 IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0), 515 IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4), 516 IsMovValueFromStack(X86::KMOVQkm, Reg), 517 IsStackDeallocate(RegBitWidth / 8))); 518 } 519 520 // Note: We always put 80 bits on the stack independently of the size of the 521 // value. This uses a bit more space but makes the code simpler. 522 523 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) { 524 EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)), 525 ElementsAre(IsStackAllocate(10), 526 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 527 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 528 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 529 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 530 } 531 532 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) { 533 const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1); 534 EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)), 535 ElementsAre(IsStackAllocate(10), 536 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 537 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 538 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 539 OpcodeIs(X86::LD_F80m), CopySt0ToSt1, 540 IsStackDeallocate(10))); 541 } 542 543 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) { 544 EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)), 545 ElementsAre(IsStackAllocate(10), 546 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0), 547 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4), 548 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 549 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 550 } 551 552 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) { 553 EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)), 554 ElementsAre(IsStackAllocate(10), 555 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 556 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 557 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 558 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10))); 559 } 560 561 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) { 562 EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)), 563 ElementsAre(IsStackAllocate(10), 564 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0), 565 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4), 566 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8), 567 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 568 } 569 570 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) { 571 EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)), 572 ElementsAre(IsStackAllocate(10), 573 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0), 574 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 575 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 576 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 577 } 578 579 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) { 580 EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)), 581 ElementsAre(IsStackAllocate(10), 582 IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0), 583 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4), 584 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8), 585 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10))); 586 } 587 588 TEST_F(X86Core2TargetTest, SetRegToDf1) { 589 EXPECT_THAT(setRegTo(X86::DF, APInt(1, 1)), ElementsAre(OpcodeIs(X86::STD))); 590 } 591 592 TEST_F(X86Core2TargetTest, SetRegToDf0) { 593 EXPECT_THAT(setRegTo(X86::DF, APInt(1, 0)), ElementsAre(OpcodeIs(X86::CLD))); 594 } 595 596 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) { 597 const Instruction &I = getInstr(X86::ADD64rm); 598 InstructionTemplate IT(&I); 599 constexpr const int kOffset = 42; 600 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 601 // Memory is operands 2-6. 602 EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI)); 603 EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1)); 604 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0)); 605 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset)); 606 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 607 } 608 609 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) { 610 const Instruction &I = getInstr(X86::VGATHERDPSZ128rm); 611 InstructionTemplate IT(&I); 612 constexpr const int kOffset = 42; 613 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset); 614 // Memory is operands 4-8. 615 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI)); 616 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1)); 617 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0)); 618 EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset)); 619 EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0)); 620 } 621 622 TEST_F(X86Core2TargetTest, AllowAsBackToBack) { 623 EXPECT_TRUE( 624 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr))); 625 EXPECT_FALSE( 626 State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r))); 627 } 628 629 #ifdef __linux__ 630 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) { 631 std::vector<MCInst> GeneratedCode; 632 State.getExegesisTarget().generateLowerMunmap(GeneratedCode); 633 EXPECT_THAT(GeneratedCode, 634 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0), 635 OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri), 636 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32), 637 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 638 OpcodeIs(X86::SYSCALL))); 639 } 640 641 #ifdef __arm__ 642 static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000; 643 #else 644 static constexpr const uintptr_t VAddressSpaceCeiling = 0x0000800000000000; 645 #endif 646 647 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) { 648 std::vector<MCInst> GeneratedCode; 649 State.getExegesisTarget().generateUpperMunmap(GeneratedCode); 650 EXPECT_THAT( 651 GeneratedCode, 652 ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr), 653 OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri), 654 OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32), 655 IsMovImmediate(X86::MOV64ri, X86::RSI, 656 VAddressSpaceCeiling - getpagesize()), 657 OpcodeIs(X86::SUB64rr), 658 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap), 659 OpcodeIs(X86::SYSCALL)})); 660 } 661 662 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) { 663 EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127), 664 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127), 665 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit), 666 OpcodeIs(X86::SYSCALL))); 667 } 668 669 TEST_F(X86Core2TargetTest, GenerateMmapTest) { 670 EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000), 671 ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000), 672 IsMovImmediate(X86::MOV64ri, X86::RSI, 4096), 673 IsMovImmediate(X86::MOV64ri, X86::RDX, 674 PROT_READ | PROT_WRITE), 675 IsMovImmediate(X86::MOV64ri, X86::R10, 676 MAP_SHARED | MAP_FIXED_NOREPLACE), 677 IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000), 678 OpcodeIs(X86::MOV32rm), 679 IsMovImmediate(X86::MOV64ri, X86::R9, 0), 680 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 681 OpcodeIs(X86::SYSCALL))); 682 } 683 684 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) { 685 std::vector<MCInst> GeneratedCode; 686 State.getExegesisTarget().generateMmapAuxMem(GeneratedCode); 687 EXPECT_THAT( 688 GeneratedCode, 689 ElementsAre( 690 IsMovImmediate( 691 X86::MOV64ri, X86::RDI, 692 State.getExegesisTarget().getAuxiliaryMemoryStartAddress()), 693 IsMovImmediate(X86::MOV64ri, X86::RSI, 694 SubprocessMemory::AuxiliaryMemorySize), 695 IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE), 696 IsMovImmediate(X86::MOV64ri, X86::R10, 697 MAP_SHARED | MAP_FIXED_NOREPLACE), 698 OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0), 699 IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap), 700 OpcodeIs(X86::SYSCALL))); 701 } 702 703 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) { 704 std::vector<MCInst> GeneratedCode; 705 State.getExegesisTarget().moveArgumentRegisters(GeneratedCode); 706 EXPECT_THAT(GeneratedCode, 707 ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI), 708 IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI))); 709 } 710 #endif // __linux__ 711 712 } // namespace 713 } // namespace exegesis 714 } // namespace llvm 715