6 #include "MCTargetDesc/X86MCTargetDesc.h"
7 #include "llvm/Support/TargetRegistry.h"
8 #include "llvm/Support/TargetSelect.h"
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
12 #include "llvm/MC/MCInstPrinter.h"
16 bool operator==(const MCOperand
&a
, const MCOperand
&b
) {
17 if (a
.isImm() && b
.isImm())
18 return a
.getImm() == b
.getImm();
19 if (a
.isReg() && b
.isReg())
20 return a
.getReg() == b
.getReg();
24 bool operator==(const MCInst
&a
, const MCInst
&b
) {
25 if (a
.getOpcode() != b
.getOpcode())
27 if (a
.getNumOperands() != b
.getNumOperands())
29 for (unsigned I
= 0; I
< a
.getNumOperands(); ++I
) {
30 if (!(a
.getOperand(I
) == b
.getOperand(I
)))
40 void InitializeX86ExegesisTarget();
45 using testing::ElementsAre
;
46 using testing::ElementsAreArray
;
49 using testing::Matcher
;
50 using testing::NotNull
;
51 using testing::Property
;
52 using testing::SizeIs
;
56 using llvm::MCInstBuilder
;
57 using llvm::MCOperand
;
59 Matcher
<MCOperand
> IsImm(int64_t Value
) {
60 return AllOf(Property(&MCOperand::isImm
, Eq(true)),
61 Property(&MCOperand::getImm
, Eq(Value
)));
64 Matcher
<MCOperand
> IsReg(unsigned Reg
) {
65 return AllOf(Property(&MCOperand::isReg
, Eq(true)),
66 Property(&MCOperand::getReg
, Eq(Reg
)));
69 Matcher
<MCInst
> OpcodeIs(unsigned Opcode
) {
70 return Property(&MCInst::getOpcode
, Eq(Opcode
));
73 Matcher
<MCInst
> IsMovImmediate(unsigned Opcode
, int64_t Reg
, int64_t Value
) {
74 return AllOf(OpcodeIs(Opcode
), ElementsAre(IsReg(Reg
), IsImm(Value
)));
77 Matcher
<MCInst
> IsMovValueToStack(unsigned Opcode
, int64_t Value
,
79 return AllOf(OpcodeIs(Opcode
),
80 ElementsAre(IsReg(llvm::X86::RSP
), IsImm(1), IsReg(0),
81 IsImm(Offset
), IsReg(0), IsImm(Value
)));
84 Matcher
<MCInst
> IsMovValueFromStack(unsigned Opcode
, unsigned Reg
) {
85 return AllOf(OpcodeIs(Opcode
),
86 ElementsAre(IsReg(Reg
), IsReg(llvm::X86::RSP
), IsImm(1),
87 IsReg(0), IsImm(0), IsReg(0)));
90 Matcher
<MCInst
> IsStackAllocate(unsigned Size
) {
92 OpcodeIs(llvm::X86::SUB64ri8
),
93 ElementsAre(IsReg(llvm::X86::RSP
), IsReg(llvm::X86::RSP
), IsImm(Size
)));
96 Matcher
<MCInst
> IsStackDeallocate(unsigned Size
) {
98 OpcodeIs(llvm::X86::ADD64ri8
),
99 ElementsAre(IsReg(llvm::X86::RSP
), IsReg(llvm::X86::RSP
), IsImm(Size
)));
102 constexpr const char kTriple
[] = "x86_64-unknown-linux";
103 constexpr const char kFeaturesEmpty
[] = "";
104 constexpr const char kFeaturesAvx
[] = "+avx";
105 constexpr const char kFeaturesAvx512VL
[] = "+avx512vl";
106 constexpr const char kCpuCore2
[] = "core2";
108 template <const char *CPU
, const char *Features
>
109 class X86TargetTest
: public ::testing::Test
{
112 : ExegesisTarget_(ExegesisTarget::lookup(llvm::Triple(kTriple
))) {
113 EXPECT_THAT(ExegesisTarget_
, NotNull());
115 Target_
= llvm::TargetRegistry::lookupTarget(kTriple
, error
);
116 EXPECT_THAT(Target_
, NotNull());
117 STI_
.reset(Target_
->createMCSubtargetInfo(kTriple
, kCpuCore2
, Features
));
120 static void SetUpTestCase() {
121 LLVMInitializeX86TargetInfo();
122 LLVMInitializeX86Target();
123 LLVMInitializeX86TargetMC();
124 InitializeX86ExegesisTarget();
127 std::vector
<MCInst
> setRegTo(unsigned Reg
, const APInt
&Value
) {
128 return ExegesisTarget_
->setRegTo(*STI_
, Reg
, Value
);
131 const llvm::Target
*Target_
;
132 const ExegesisTarget
*const ExegesisTarget_
;
133 std::unique_ptr
<llvm::MCSubtargetInfo
> STI_
;
136 using Core2TargetTest
= X86TargetTest
<kCpuCore2
, kFeaturesEmpty
>;
137 using Core2AvxTargetTest
= X86TargetTest
<kCpuCore2
, kFeaturesAvx
>;
138 using Core2Avx512TargetTest
= X86TargetTest
<kCpuCore2
, kFeaturesAvx512VL
>;
140 TEST_F(Core2TargetTest
, SetFlags
) {
141 const unsigned Reg
= llvm::X86::EFLAGS
;
143 setRegTo(Reg
, APInt(64, 0x1111222233334444ULL
)),
144 ElementsAre(IsStackAllocate(8),
145 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 0),
146 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 4),
147 OpcodeIs(llvm::X86::POPF64
)));
150 TEST_F(Core2TargetTest
, SetRegToGR8Value
) {
151 const uint8_t Value
= 0xFFU
;
152 const unsigned Reg
= llvm::X86::AL
;
153 EXPECT_THAT(setRegTo(Reg
, APInt(8, Value
)),
154 ElementsAre(IsMovImmediate(llvm::X86::MOV8ri
, Reg
, Value
)));
157 TEST_F(Core2TargetTest
, SetRegToGR16Value
) {
158 const uint16_t Value
= 0xFFFFU
;
159 const unsigned Reg
= llvm::X86::BX
;
160 EXPECT_THAT(setRegTo(Reg
, APInt(16, Value
)),
161 ElementsAre(IsMovImmediate(llvm::X86::MOV16ri
, Reg
, Value
)));
164 TEST_F(Core2TargetTest
, SetRegToGR32Value
) {
165 const uint32_t Value
= 0x7FFFFU
;
166 const unsigned Reg
= llvm::X86::ECX
;
167 EXPECT_THAT(setRegTo(Reg
, APInt(32, Value
)),
168 ElementsAre(IsMovImmediate(llvm::X86::MOV32ri
, Reg
, Value
)));
171 TEST_F(Core2TargetTest
, SetRegToGR64Value
) {
172 const uint64_t Value
= 0x7FFFFFFFFFFFFFFFULL
;
173 const unsigned Reg
= llvm::X86::RDX
;
174 EXPECT_THAT(setRegTo(Reg
, APInt(64, Value
)),
175 ElementsAre(IsMovImmediate(llvm::X86::MOV64ri
, Reg
, Value
)));
178 TEST_F(Core2TargetTest
, SetRegToVR64Value
) {
180 setRegTo(llvm::X86::MM0
, APInt(64, 0x1111222233334444ULL
)),
181 ElementsAre(IsStackAllocate(8),
182 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 0),
183 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 4),
184 IsMovValueFromStack(llvm::X86::MMX_MOVQ64rm
, llvm::X86::MM0
),
185 IsStackDeallocate(8)));
188 TEST_F(Core2TargetTest
, SetRegToVR128Value_Use_MOVDQUrm
) {
190 setRegTo(llvm::X86::XMM0
,
191 APInt(128, "11112222333344445555666677778888", 16)),
192 ElementsAre(IsStackAllocate(16),
193 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77778888UL
, 0),
194 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55556666UL
, 4),
195 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 8),
196 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 12),
197 IsMovValueFromStack(llvm::X86::MOVDQUrm
, llvm::X86::XMM0
),
198 IsStackDeallocate(16)));
201 TEST_F(Core2AvxTargetTest
, SetRegToVR128Value_Use_VMOVDQUrm
) {
203 setRegTo(llvm::X86::XMM0
,
204 APInt(128, "11112222333344445555666677778888", 16)),
205 ElementsAre(IsStackAllocate(16),
206 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77778888UL
, 0),
207 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55556666UL
, 4),
208 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 8),
209 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 12),
210 IsMovValueFromStack(llvm::X86::VMOVDQUrm
, llvm::X86::XMM0
),
211 IsStackDeallocate(16)));
214 TEST_F(Core2Avx512TargetTest
, SetRegToVR128Value_Use_VMOVDQU32Z128rm
) {
216 setRegTo(llvm::X86::XMM0
,
217 APInt(128, "11112222333344445555666677778888", 16)),
220 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77778888UL
, 0),
221 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55556666UL
, 4),
222 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 8),
223 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 12),
224 IsMovValueFromStack(llvm::X86::VMOVDQU32Z128rm
, llvm::X86::XMM0
),
225 IsStackDeallocate(16)));
228 TEST_F(Core2AvxTargetTest
, SetRegToVR256Value_Use_VMOVDQUYrm
) {
229 const char ValueStr
[] =
230 "1111111122222222333333334444444455555555666666667777777788888888";
231 EXPECT_THAT(setRegTo(llvm::X86::YMM0
, APInt(256, ValueStr
, 16)),
233 {IsStackAllocate(32),
234 IsMovValueToStack(llvm::X86::MOV32mi
, 0x88888888UL
, 0),
235 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77777777UL
, 4),
236 IsMovValueToStack(llvm::X86::MOV32mi
, 0x66666666UL
, 8),
237 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55555555UL
, 12),
238 IsMovValueToStack(llvm::X86::MOV32mi
, 0x44444444UL
, 16),
239 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33333333UL
, 20),
240 IsMovValueToStack(llvm::X86::MOV32mi
, 0x22222222UL
, 24),
241 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11111111UL
, 28),
242 IsMovValueFromStack(llvm::X86::VMOVDQUYrm
, llvm::X86::YMM0
),
243 IsStackDeallocate(32)}));
246 TEST_F(Core2Avx512TargetTest
, SetRegToVR256Value_Use_VMOVDQU32Z256rm
) {
247 const char ValueStr
[] =
248 "1111111122222222333333334444444455555555666666667777777788888888";
250 setRegTo(llvm::X86::YMM0
, APInt(256, ValueStr
, 16)),
252 {IsStackAllocate(32),
253 IsMovValueToStack(llvm::X86::MOV32mi
, 0x88888888UL
, 0),
254 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77777777UL
, 4),
255 IsMovValueToStack(llvm::X86::MOV32mi
, 0x66666666UL
, 8),
256 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55555555UL
, 12),
257 IsMovValueToStack(llvm::X86::MOV32mi
, 0x44444444UL
, 16),
258 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33333333UL
, 20),
259 IsMovValueToStack(llvm::X86::MOV32mi
, 0x22222222UL
, 24),
260 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11111111UL
, 28),
261 IsMovValueFromStack(llvm::X86::VMOVDQU32Z256rm
, llvm::X86::YMM0
),
262 IsStackDeallocate(32)}));
265 TEST_F(Core2Avx512TargetTest
, SetRegToVR512Value
) {
266 const char ValueStr
[] =
267 "1111111122222222333333334444444455555555666666667777777788888888"
268 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
270 setRegTo(llvm::X86::ZMM0
, APInt(512, ValueStr
, 16)),
272 {IsStackAllocate(64),
273 IsMovValueToStack(llvm::X86::MOV32mi
, 0x00000000UL
, 0),
274 IsMovValueToStack(llvm::X86::MOV32mi
, 0xFFFFFFFFUL
, 4),
275 IsMovValueToStack(llvm::X86::MOV32mi
, 0xEEEEEEEEUL
, 8),
276 IsMovValueToStack(llvm::X86::MOV32mi
, 0xDDDDDDDDUL
, 12),
277 IsMovValueToStack(llvm::X86::MOV32mi
, 0xCCCCCCCCUL
, 16),
278 IsMovValueToStack(llvm::X86::MOV32mi
, 0xBBBBBBBBUL
, 20),
279 IsMovValueToStack(llvm::X86::MOV32mi
, 0xAAAAAAAAUL
, 24),
280 IsMovValueToStack(llvm::X86::MOV32mi
, 0x99999999UL
, 28),
281 IsMovValueToStack(llvm::X86::MOV32mi
, 0x88888888UL
, 32),
282 IsMovValueToStack(llvm::X86::MOV32mi
, 0x77777777UL
, 36),
283 IsMovValueToStack(llvm::X86::MOV32mi
, 0x66666666UL
, 40),
284 IsMovValueToStack(llvm::X86::MOV32mi
, 0x55555555UL
, 44),
285 IsMovValueToStack(llvm::X86::MOV32mi
, 0x44444444UL
, 48),
286 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33333333UL
, 52),
287 IsMovValueToStack(llvm::X86::MOV32mi
, 0x22222222UL
, 56),
288 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11111111UL
, 60),
289 IsMovValueFromStack(llvm::X86::VMOVDQU32Zrm
, llvm::X86::ZMM0
),
290 IsStackDeallocate(64)}));
293 TEST_F(Core2TargetTest
, SetRegToST0_32Bits
) {
295 setRegTo(llvm::X86::ST0
, APInt(32, 0x11112222ULL
)),
296 ElementsAre(IsStackAllocate(4),
297 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 0),
298 OpcodeIs(llvm::X86::LD_F32m
), IsStackDeallocate(4)));
301 TEST_F(Core2TargetTest
, SetRegToST1_32Bits
) {
302 const MCInst CopySt0ToSt1
=
303 llvm::MCInstBuilder(llvm::X86::ST_Frr
).addReg(llvm::X86::ST1
);
305 setRegTo(llvm::X86::ST1
, APInt(32, 0x11112222ULL
)),
306 ElementsAre(IsStackAllocate(4),
307 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 0),
308 OpcodeIs(llvm::X86::LD_F32m
), CopySt0ToSt1
,
309 IsStackDeallocate(4)));
312 TEST_F(Core2TargetTest
, SetRegToST0_64Bits
) {
314 setRegTo(llvm::X86::ST0
, APInt(64, 0x1111222233334444ULL
)),
315 ElementsAre(IsStackAllocate(8),
316 IsMovValueToStack(llvm::X86::MOV32mi
, 0x33334444UL
, 0),
317 IsMovValueToStack(llvm::X86::MOV32mi
, 0x11112222UL
, 4),
318 OpcodeIs(llvm::X86::LD_F64m
), IsStackDeallocate(8)));
321 TEST_F(Core2TargetTest
, SetRegToST0_80Bits
) {
323 setRegTo(llvm::X86::ST0
, APInt(80, "11112222333344445555", 16)),
324 ElementsAre(IsStackAllocate(10),
325 IsMovValueToStack(llvm::X86::MOV32mi
, 0x44445555UL
, 0),
326 IsMovValueToStack(llvm::X86::MOV32mi
, 0x22223333UL
, 4),
327 IsMovValueToStack(llvm::X86::MOV16mi
, 0x1111UL
, 8),
328 OpcodeIs(llvm::X86::LD_F80m
), IsStackDeallocate(10)));
332 } // namespace exegesis