diff options
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/X86/Target.cpp')
-rw-r--r-- | llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 26a54591fb0..591edd2afae 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -8,7 +8,10 @@ //===----------------------------------------------------------------------===// #include "../Target.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "X86.h" +#include "X86RegisterInfo.h" +#include "llvm/MC/MCInstBuilder.h" namespace exegesis { @@ -22,9 +25,88 @@ class ExegesisX86Target : public ExegesisTarget { // PM.add(llvm::createX86FloatingPointStackifierPass()); } + std::vector<llvm::MCInst> + setRegToConstant(const unsigned Reg) const override { + // FIXME: Handle FP stack: + // llvm::X86::RFP32RegClass + // llvm::X86::RFP64RegClass + // llvm::X86::RFP80RegClass + if (llvm::X86::GR8RegClass.contains(Reg)) { + return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)}; + } + if (llvm::X86::GR16RegClass.contains(Reg)) { + return {llvm::MCInstBuilder(llvm::X86::MOV16ri).addReg(Reg).addImm(1)}; + } + if (llvm::X86::GR32RegClass.contains(Reg)) { + return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)}; + } + if (llvm::X86::GR64RegClass.contains(Reg)) { + return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)}; + } + if (llvm::X86::VR128XRegClass.contains(Reg)) { + return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm); + } + if (llvm::X86::VR256XRegClass.contains(Reg)) { + return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm); + } + if (llvm::X86::VR512RegClass.contains(Reg)) { + return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU64Zrm); + } + return {}; + } + bool matchesArch(llvm::Triple::ArchType Arch) const override { return Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86; } + +private: + // setRegToConstant() specialized for a vector register of size + // `RegSizeBytes`. `RMOpcode` is the opcode used to do a memory -> vector + // register load. + static std::vector<llvm::MCInst> + setVectorRegToConstant(const unsigned Reg, const unsigned RegSizeBytes, + const unsigned RMOpcode) { + // There is no instruction to directly set XMM, go through memory. + // Since vector values can be interpreted as integers of various sizes (8 + // to 64 bits) as well as floats and double, so we chose an immediate + // value that has set bits for all byte values and is a normal float/ + // double. 0x40404040 is ~32.5 when interpreted as a double and ~3.0f when + // interpreted as a float. + constexpr const uint64_t kImmValue = 0x40404040ull; + std::vector<llvm::MCInst> Result; + // Allocate scratch memory on the stack. + Result.push_back(llvm::MCInstBuilder(llvm::X86::SUB64ri8) + .addReg(llvm::X86::RSP) + .addReg(llvm::X86::RSP) + .addImm(RegSizeBytes)); + // Fill scratch memory. + for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += 4) { + Result.push_back(llvm::MCInstBuilder(llvm::X86::MOV32mi) + // Address = ESP + .addReg(llvm::X86::RSP) // BaseReg + .addImm(1) // ScaleAmt + .addReg(0) // IndexReg + .addImm(Disp) // Disp + .addReg(0) // Segment + // Immediate. + .addImm(kImmValue)); + } + // Load Reg from scratch memory. + Result.push_back(llvm::MCInstBuilder(RMOpcode) + .addReg(Reg) + // Address = ESP + .addReg(llvm::X86::RSP) // BaseReg + .addImm(1) // ScaleAmt + .addReg(0) // IndexReg + .addImm(0) // Disp + .addReg(0)); // Segment + // Release scratch memory. + Result.push_back(llvm::MCInstBuilder(llvm::X86::ADD64ri8) + .addReg(llvm::X86::RSP) + .addReg(llvm::X86::RSP) + .addImm(RegSizeBytes)); + return Result; + } }; } // namespace |