blob: 591edd2afae58612e42107cc9f0a301e83105c93 [file] [log] [blame]
Clement Courbet44b4c542018-06-19 11:28:59 +00001//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "../Target.h"
10
Clement Courbeta51efc22018-06-25 13:12:02 +000011#include "MCTargetDesc/X86MCTargetDesc.h"
Clement Courbet6fd00e32018-06-20 11:54:35 +000012#include "X86.h"
Clement Courbeta51efc22018-06-25 13:12:02 +000013#include "X86RegisterInfo.h"
14#include "llvm/MC/MCInstBuilder.h"
Clement Courbet6fd00e32018-06-20 11:54:35 +000015
Clement Courbet44b4c542018-06-19 11:28:59 +000016namespace exegesis {
17
18namespace {
19
20class ExegesisX86Target : public ExegesisTarget {
Clement Courbet6fd00e32018-06-20 11:54:35 +000021 void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
22 // Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F.
23 // FIXME: Enable when the exegesis assembler no longer does
24 // Properties.reset(TracksLiveness);
25 // PM.add(llvm::createX86FloatingPointStackifierPass());
26 }
27
Clement Courbeta51efc22018-06-25 13:12:02 +000028 std::vector<llvm::MCInst>
29 setRegToConstant(const unsigned Reg) const override {
30 // FIXME: Handle FP stack:
31 // llvm::X86::RFP32RegClass
32 // llvm::X86::RFP64RegClass
33 // llvm::X86::RFP80RegClass
34 if (llvm::X86::GR8RegClass.contains(Reg)) {
35 return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)};
36 }
37 if (llvm::X86::GR16RegClass.contains(Reg)) {
38 return {llvm::MCInstBuilder(llvm::X86::MOV16ri).addReg(Reg).addImm(1)};
39 }
40 if (llvm::X86::GR32RegClass.contains(Reg)) {
41 return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)};
42 }
43 if (llvm::X86::GR64RegClass.contains(Reg)) {
44 return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)};
45 }
46 if (llvm::X86::VR128XRegClass.contains(Reg)) {
47 return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
48 }
49 if (llvm::X86::VR256XRegClass.contains(Reg)) {
50 return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm);
51 }
52 if (llvm::X86::VR512RegClass.contains(Reg)) {
53 return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU64Zrm);
54 }
55 return {};
56 }
57
Clement Courbet44b4c542018-06-19 11:28:59 +000058 bool matchesArch(llvm::Triple::ArchType Arch) const override {
59 return Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86;
60 }
Clement Courbeta51efc22018-06-25 13:12:02 +000061
62private:
63 // setRegToConstant() specialized for a vector register of size
64 // `RegSizeBytes`. `RMOpcode` is the opcode used to do a memory -> vector
65 // register load.
66 static std::vector<llvm::MCInst>
67 setVectorRegToConstant(const unsigned Reg, const unsigned RegSizeBytes,
68 const unsigned RMOpcode) {
69 // There is no instruction to directly set XMM, go through memory.
70 // Since vector values can be interpreted as integers of various sizes (8
71 // to 64 bits) as well as floats and double, so we chose an immediate
72 // value that has set bits for all byte values and is a normal float/
73 // double. 0x40404040 is ~32.5 when interpreted as a double and ~3.0f when
74 // interpreted as a float.
75 constexpr const uint64_t kImmValue = 0x40404040ull;
76 std::vector<llvm::MCInst> Result;
77 // Allocate scratch memory on the stack.
78 Result.push_back(llvm::MCInstBuilder(llvm::X86::SUB64ri8)
79 .addReg(llvm::X86::RSP)
80 .addReg(llvm::X86::RSP)
81 .addImm(RegSizeBytes));
82 // Fill scratch memory.
83 for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += 4) {
84 Result.push_back(llvm::MCInstBuilder(llvm::X86::MOV32mi)
85 // Address = ESP
86 .addReg(llvm::X86::RSP) // BaseReg
87 .addImm(1) // ScaleAmt
88 .addReg(0) // IndexReg
89 .addImm(Disp) // Disp
90 .addReg(0) // Segment
91 // Immediate.
92 .addImm(kImmValue));
93 }
94 // Load Reg from scratch memory.
95 Result.push_back(llvm::MCInstBuilder(RMOpcode)
96 .addReg(Reg)
97 // Address = ESP
98 .addReg(llvm::X86::RSP) // BaseReg
99 .addImm(1) // ScaleAmt
100 .addReg(0) // IndexReg
101 .addImm(0) // Disp
102 .addReg(0)); // Segment
103 // Release scratch memory.
104 Result.push_back(llvm::MCInstBuilder(llvm::X86::ADD64ri8)
105 .addReg(llvm::X86::RSP)
106 .addReg(llvm::X86::RSP)
107 .addImm(RegSizeBytes));
108 return Result;
109 }
Clement Courbet44b4c542018-06-19 11:28:59 +0000110};
111
112} // namespace
113
Clement Courbetcff2caa2018-06-25 11:22:23 +0000114static ExegesisTarget *getTheExegesisX86Target() {
Clement Courbet44b4c542018-06-19 11:28:59 +0000115 static ExegesisX86Target Target;
116 return &Target;
117}
118
119void InitializeX86ExegesisTarget() {
120 ExegesisTarget::registerTarget(getTheExegesisX86Target());
121}
122
Clement Courbetcff2caa2018-06-25 11:22:23 +0000123} // namespace exegesis