OLD | NEW |
---|---|
1 //===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- C++ -*--===// | 1 //===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- C++ -*--===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// \brief This file defines the InstX86Base template class, as well as the | 11 /// \brief This file defines the InstX86Base template class, as well as the |
12 /// generic X86 Instruction class hierarchy. | 12 /// generic X86 Instruction class hierarchy. |
13 /// | 13 /// |
14 /// Only X86 instructions common across all/most X86 targets should be defined | 14 /// Only X86 instructions common across all/most X86 targets should be defined |
15 /// here, with target-specific instructions declared in the target's traits. | 15 /// here, with target-specific instructions declared in the target's traits. |
16 /// | 16 /// |
17 //===----------------------------------------------------------------------===// | 17 //===----------------------------------------------------------------------===// |
18 | 18 |
19 #ifndef SUBZERO_SRC_ICEINSTX86BASE_H | 19 #ifndef SUBZERO_SRC_ICEINSTX86BASE_H |
20 #define SUBZERO_SRC_ICEINSTX86BASE_H | 20 #define SUBZERO_SRC_ICEINSTX86BASE_H |
21 | 21 |
22 #include "IceDefs.h" | 22 #include "IceDefs.h" |
23 #include "IceInst.h" | 23 #include "IceInst.h" |
24 #include "IceOperand.h" | 24 #include "IceOperand.h" |
25 | 25 |
26 namespace Ice { | 26 namespace Ice { |
27 | 27 |
28 namespace X86Internal { | 28 #ifndef X86NAMESPACE |
29 | 29 #error "You must define the X86 Target namespace." |
30 template <class Machine> struct MachineTraits; | 30 #endif |
31 | 31 |
32 template <class Machine> class InstX86Base : public InstTarget { | 32 namespace X86NAMESPACE { |
33 InstX86Base<Machine>() = delete; | 33 |
John
2015/12/30 22:07:52
The diff seems worse than it is because of changes
| |
34 InstX86Base<Machine>(const InstX86Base &) = delete; | 34 template <typename TraitsType> struct InstImpl { |
35 InstX86Base &operator=(const InstX86Base &) = delete; | 35 using Traits = TraitsType; |
36 | 36 using Assembler = typename Traits::Assembler; |
37 public: | 37 using AssemblerLabel = typename Assembler::Label; |
38 using Traits = MachineTraits<Machine>; | 38 using AssemblerImmediate = typename Assembler::Immediate; |
39 using X86TargetLowering = typename Traits::TargetLowering; | 39 using TargetLowering = typename Traits::TargetLowering; |
40 | 40 using Address = typename Traits::Address; |
41 enum InstKindX86 { | 41 using X86Operand = typename Traits::X86Operand; |
42 k__Start = Inst::Target, | 42 using X86OperandMem = typename Traits::X86OperandMem; |
43 Adc, | 43 using VariableSplit = typename Traits::VariableSplit; |
44 AdcRMW, | 44 |
45 Add, | 45 using GPRRegister = typename Traits::RegisterSet::GPRRegister; |
46 AddRMW, | 46 using RegisterSet = typename Traits::RegisterSet; |
47 Addps, | 47 using XmmRegister = typename Traits::RegisterSet::XmmRegister; |
48 Addss, | 48 |
49 And, | 49 using Cond = typename Traits::Cond; |
50 Andnps, | 50 using BrCond = typename Traits::Cond::BrCond; |
51 Andps, | 51 using CmppsCond = typename Traits::Cond::CmppsCond; |
52 AndRMW, | 52 |
53 Blendvps, | 53 template <typename SReg_t, typename DReg_t> |
54 Br, | 54 using CastEmitterRegOp = |
55 Bsf, | 55 typename Traits::Assembler::template CastEmitterRegOp<SReg_t, DReg_t>; |
56 Bsr, | 56 template <typename SReg_t, typename DReg_t> |
57 Bswap, | 57 using ThreeOpImmEmitter = |
58 Call, | 58 typename Traits::Assembler::template ThreeOpImmEmitter<SReg_t, DReg_t>; |
59 Cbwdq, | 59 using GPREmitterAddrOp = typename Traits::Assembler::GPREmitterAddrOp; |
60 Cmov, | 60 using GPREmitterRegOp = typename Traits::Assembler::GPREmitterRegOp; |
61 Cmpps, | 61 using GPREmitterShiftD = typename Traits::Assembler::GPREmitterShiftD; |
62 Cmpxchg, | 62 using GPREmitterShiftOp = typename Traits::Assembler::GPREmitterShiftOp; |
63 Cmpxchg8b, | 63 using GPREmitterOneOp = typename Traits::Assembler::GPREmitterOneOp; |
64 Cvt, | 64 using XmmEmitterRegOp = typename Traits::Assembler::XmmEmitterRegOp; |
65 Div, | 65 using XmmEmitterShiftOp = typename Traits::Assembler::XmmEmitterShiftOp; |
66 Divps, | 66 using XmmEmitterMovOps = typename Traits::Assembler::XmmEmitterMovOps; |
67 Divss, | 67 |
68 FakeRMW, | 68 class InstX86Base : public InstTarget { |
69 Fld, | 69 InstX86Base() = delete; |
70 Fstp, | 70 InstX86Base(const InstX86Base &) = delete; |
71 Icmp, | 71 InstX86Base &operator=(const InstX86Base &) = delete; |
72 Idiv, | 72 |
73 Imul, | 73 public: |
74 ImulImm, | 74 enum InstKindX86 { |
75 Insertps, | 75 k__Start = Inst::Target, |
76 Jmp, | 76 Adc, |
77 Label, | 77 AdcRMW, |
78 Lea, | 78 Add, |
79 Load, | 79 AddRMW, |
80 Mfence, | 80 Addps, |
81 Minss, | 81 Addss, |
82 Maxss, | 82 And, |
83 Mov, | 83 Andnps, |
84 Movd, | 84 Andps, |
85 Movp, | 85 AndRMW, |
86 Movq, | 86 Blendvps, |
87 MovssRegs, | 87 Br, |
88 Movsx, | 88 Bsf, |
89 Movzx, | 89 Bsr, |
90 Mul, | 90 Bswap, |
91 Mulps, | 91 Call, |
92 Mulss, | 92 Cbwdq, |
93 Neg, | 93 Cmov, |
94 Nop, | 94 Cmpps, |
95 Or, | 95 Cmpxchg, |
96 Orps, | 96 Cmpxchg8b, |
97 OrRMW, | 97 Cvt, |
98 Padd, | 98 Div, |
99 Pand, | 99 Divps, |
100 Pandn, | 100 Divss, |
101 Pblendvb, | 101 FakeRMW, |
102 Pcmpeq, | 102 Fld, |
103 Pcmpgt, | 103 Fstp, |
104 Pextr, | 104 Icmp, |
105 Pinsr, | 105 Idiv, |
106 Pmull, | 106 Imul, |
107 Pmuludq, | 107 ImulImm, |
108 Pop, | 108 Insertps, |
109 Por, | 109 Jmp, |
110 Pshufd, | 110 Label, |
111 Psll, | 111 Lea, |
112 Psra, | 112 Load, |
113 Psrl, | 113 Mfence, |
114 Psub, | 114 Minss, |
115 Push, | 115 Maxss, |
116 Pxor, | 116 Mov, |
117 Ret, | 117 Movd, |
118 Rol, | 118 Movp, |
119 Sar, | 119 Movq, |
120 Sbb, | 120 MovssRegs, |
121 SbbRMW, | 121 Movsx, |
122 Setcc, | 122 Movzx, |
123 Shl, | 123 Mul, |
124 Shld, | 124 Mulps, |
125 Shr, | 125 Mulss, |
126 Shrd, | 126 Neg, |
127 Shufps, | 127 Nop, |
128 Sqrtss, | 128 Or, |
129 Store, | 129 Orps, |
130 StoreP, | 130 OrRMW, |
131 StoreQ, | 131 Padd, |
132 Sub, | 132 Pand, |
133 SubRMW, | 133 Pandn, |
134 Subps, | 134 Pblendvb, |
135 Subss, | 135 Pcmpeq, |
136 Test, | 136 Pcmpgt, |
137 Ucomiss, | 137 Pextr, |
138 UD2, | 138 Pinsr, |
139 Xadd, | 139 Pmull, |
140 Xchg, | 140 Pmuludq, |
141 Xor, | 141 Pop, |
142 Xorps, | 142 Por, |
143 XorRMW, | 143 Pshufd, |
144 | 144 Psll, |
145 /// Intel Architecture Code Analyzer markers. These are not executable so | 145 Psra, |
146 /// must only be used for analysis. | 146 Psrl, |
147 IacaStart, | 147 Psub, |
148 IacaEnd | 148 Push, |
149 }; | 149 Pxor, |
150 | 150 Ret, |
151 enum SseSuffix { None, Packed, Scalar, Integral }; | 151 Rol, |
152 | 152 Sar, |
153 static const char *getWidthString(Type Ty); | 153 Sbb, |
154 static const char *getFldString(Type Ty); | 154 SbbRMW, |
155 static typename Traits::Cond::BrCond | 155 Setcc, |
156 getOppositeCondition(typename Traits::Cond::BrCond Cond); | 156 Shl, |
157 void dump(const Cfg *Func) const override; | 157 Shld, |
158 | 158 Shr, |
159 // Shared emit routines for common forms of instructions. | 159 Shrd, |
160 void emitTwoAddress(const Cfg *Func, const char *Opcode, | 160 Shufps, |
161 const char *Suffix = "") const; | 161 Sqrtss, |
162 | 162 Store, |
163 StoreP, | |
164 StoreQ, | |
165 Sub, | |
166 SubRMW, | |
167 Subps, | |
168 Subss, | |
169 Test, | |
170 Ucomiss, | |
171 UD2, | |
172 Xadd, | |
173 Xchg, | |
174 Xor, | |
175 Xorps, | |
176 XorRMW, | |
177 | |
178 /// Intel Architecture Code Analyzer markers. These are not executable so | |
179 /// must only be used for analysis. | |
180 IacaStart, | |
181 IacaEnd | |
182 }; | |
183 | |
184 enum SseSuffix { None, Packed, Scalar, Integral }; | |
185 | |
186 static const char *getWidthString(Type Ty); | |
187 static const char *getFldString(Type Ty); | |
188 static BrCond getOppositeCondition(BrCond Cond); | |
189 void dump(const Cfg *Func) const override; | |
190 | |
191 // Shared emit routines for common forms of instructions. | |
192 void emitTwoAddress(const Cfg *Func, const char *Opcode, | |
193 const char *Suffix = "") const; | |
194 | |
195 static TargetLowering *getTarget(const Cfg *Func) { | |
196 return static_cast<TargetLowering *>(Func->getTarget()); | |
197 } | |
198 | |
199 protected: | |
200 InstX86Base(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, Variable *Dest) | |
201 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | |
202 | |
203 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | |
204 return Inst->getKind() == static_cast<InstKind>(MyKind); | |
205 } | |
206 // Most instructions that operate on vector arguments require vector memory | |
207 // operands to be fully aligned (16-byte alignment for PNaCl vector types). | |
208 // The stack frame layout and call ABI ensure proper alignment for stack | |
209 // operands, but memory operands (originating from load/store bitcode | |
210 // instructions) only have element-size alignment guarantees. This function | |
211 // validates that none of the operands is a memory operand of vector type, | |
212 // calling report_fatal_error() if one is found. This function should be | |
213 // called during emission, and maybe also in the ctor (as long as that fits | |
214 // the lowering style). | |
215 void validateVectorAddrMode() const { | |
216 if (this->getDest()) | |
Jim Stichnoth
2016/01/03 18:20:02
It looks like the "this->" in this method can be r
| |
217 this->validateVectorAddrModeOpnd(this->getDest()); | |
218 for (SizeT i = 0; i < this->getSrcSize(); ++i) { | |
219 this->validateVectorAddrModeOpnd(this->getSrc(i)); | |
220 } | |
221 } | |
222 | |
223 private: | |
224 static void validateVectorAddrModeOpnd(const Operand *Opnd) { | |
225 if (llvm::isa<X86OperandMem>(Opnd) && isVectorType(Opnd->getType())) { | |
226 llvm::report_fatal_error("Possible misaligned vector memory operation"); | |
227 } | |
228 } | |
229 }; | |
230 | |
231 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | |
232 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it | |
233 /// still needs to be lowered to some actual RMW instruction. | |
234 /// | |
235 /// If A is some memory address, D is some data value to apply, and OP is an | |
236 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | |
237 class InstX86FakeRMW final : public InstX86Base { | |
238 InstX86FakeRMW() = delete; | |
239 InstX86FakeRMW(const InstX86FakeRMW &) = delete; | |
240 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | |
241 | |
242 public: | |
243 static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | |
244 Variable *Beacon, InstArithmetic::OpKind Op, | |
245 uint32_t Align = 1) { | |
246 // TODO(stichnot): Stop ignoring alignment specification. | |
247 (void)Align; | |
248 return new (Func->allocate<InstX86FakeRMW>()) | |
249 InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | |
250 } | |
251 Operand *getAddr() const { return this->getSrc(1); } | |
252 Operand *getData() const { return this->getSrc(0); } | |
253 InstArithmetic::OpKind getOp() const { return Op; } | |
254 Variable *getBeacon() const { | |
255 return llvm::cast<Variable>(this->getSrc(2)); | |
256 } | |
257 void dump(const Cfg *Func) const override; | |
258 static bool classof(const Inst *Inst) { | |
259 return InstX86Base::isClassof(Inst, InstX86Base::FakeRMW); | |
260 } | |
261 | |
262 private: | |
263 InstArithmetic::OpKind Op; | |
264 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | |
265 InstArithmetic::OpKind Op, Variable *Beacon); | |
266 }; | |
267 | |
268 /// InstX86Label represents an intra-block label that is the target of an | |
269 /// intra-block branch. The offset between the label and the branch must be | |
270 /// fit into one byte (considered "near"). These are used for lowering i1 | |
271 /// calculations, Select instructions, and 64-bit compares on a 32-bit | |
272 /// architecture, without basic block splitting. Basic block splitting is not | |
273 /// so desirable for several reasons, one of which is the impact on decisions | |
274 /// based on whether a variable's live range spans multiple basic blocks. | |
275 /// | |
276 /// Intra-block control flow must be used with caution. Consider the sequence | |
277 /// for "c = (a >= b ? x : y)". | |
278 /// cmp a, b | |
279 /// br lt, L1 | |
280 /// mov c, x | |
281 /// jmp L2 | |
282 /// L1: | |
283 /// mov c, y | |
284 /// L2: | |
285 /// | |
286 /// Labels L1 and L2 are intra-block labels. Without knowledge of the | |
287 /// intra-block control flow, liveness analysis will determine the "mov c, x" | |
288 /// instruction to be dead. One way to prevent this is to insert a | |
289 /// "FakeUse(c)" instruction anywhere between the two "mov c, ..." | |
290 /// instructions, e.g.: | |
291 /// | |
292 /// cmp a, b | |
293 /// br lt, L1 | |
294 /// mov c, x | |
295 /// jmp L2 | |
296 /// FakeUse(c) | |
297 /// L1: | |
298 /// mov c, y | |
299 /// L2: | |
300 /// | |
301 /// The down-side is that "mov c, x" can never be dead-code eliminated even if | |
302 /// there are no uses of c. As unlikely as this situation is, it may be | |
303 /// prevented by running dead code elimination before lowering. | |
304 class InstX86Label final : public InstX86Base { | |
305 InstX86Label() = delete; | |
306 InstX86Label(const InstX86Label &) = delete; | |
307 InstX86Label &operator=(const InstX86Label &) = delete; | |
308 | |
309 public: | |
310 static InstX86Label *create(Cfg *Func, TargetLowering *Target) { | |
311 return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | |
312 } | |
313 uint32_t getEmitInstCount() const override { return 0; } | |
314 IceString getName(const Cfg *Func) const; | |
315 SizeT getNumber() const { return Number; } | |
316 void emit(const Cfg *Func) const override; | |
317 void emitIAS(const Cfg *Func) const override; | |
318 void dump(const Cfg *Func) const override; | |
319 | |
320 private: | |
321 InstX86Label(Cfg *Func, TargetLowering *Target); | |
322 | |
323 SizeT Number; // used for unique label generation. | |
324 }; | |
325 | |
326 /// Conditional and unconditional branch instruction. | |
327 class InstX86Br final : public InstX86Base { | |
328 InstX86Br() = delete; | |
329 InstX86Br(const InstX86Br &) = delete; | |
330 InstX86Br &operator=(const InstX86Br &) = delete; | |
331 | |
332 public: | |
333 enum Mode { Near, Far }; | |
334 | |
335 /// Create a conditional branch to a node. | |
336 static InstX86Br *create(Cfg *Func, CfgNode *TargetTrue, | |
337 CfgNode *TargetFalse, BrCond Condition, | |
338 Mode Kind) { | |
339 assert(Condition != Cond::Br_None); | |
340 constexpr InstX86Label *NoLabel = nullptr; | |
341 return new (Func->allocate<InstX86Br>()) | |
342 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | |
343 } | |
344 /// Create an unconditional branch to a node. | |
345 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | |
346 constexpr CfgNode *NoCondTarget = nullptr; | |
347 constexpr InstX86Label *NoLabel = nullptr; | |
348 return new (Func->allocate<InstX86Br>()) | |
349 InstX86Br(Func, NoCondTarget, Target, NoLabel, Cond::Br_None, Kind); | |
350 } | |
351 /// Create a non-terminator conditional branch to a node, with a fallthrough | |
352 /// to the next instruction in the current node. This is used for switch | |
353 /// lowering. | |
354 static InstX86Br *create(Cfg *Func, CfgNode *Target, BrCond Condition, | |
355 Mode Kind) { | |
356 assert(Condition != Cond::Br_None); | |
357 constexpr CfgNode *NoUncondTarget = nullptr; | |
358 constexpr InstX86Label *NoLabel = nullptr; | |
359 return new (Func->allocate<InstX86Br>()) | |
360 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | |
361 } | |
362 /// Create a conditional intra-block branch (or unconditional, if | |
363 /// Condition==Br_None) to a label in the current block. | |
364 static InstX86Br *create(Cfg *Func, InstX86Label *Label, BrCond Condition, | |
365 Mode Kind) { | |
366 constexpr CfgNode *NoCondTarget = nullptr; | |
367 constexpr CfgNode *NoUncondTarget = nullptr; | |
368 return new (Func->allocate<InstX86Br>()) | |
369 InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | |
370 } | |
371 const CfgNode *getTargetTrue() const { return TargetTrue; } | |
372 const CfgNode *getTargetFalse() const { return TargetFalse; } | |
373 bool isNear() const { return Kind == Near; } | |
374 bool optimizeBranch(const CfgNode *NextNode); | |
375 uint32_t getEmitInstCount() const override { | |
376 uint32_t Sum = 0; | |
377 if (Label) | |
378 ++Sum; | |
379 if (getTargetTrue()) | |
380 ++Sum; | |
381 if (getTargetFalse()) | |
382 ++Sum; | |
383 return Sum; | |
384 } | |
385 bool isUnconditionalBranch() const override { | |
386 return !Label && Condition == Cond::Br_None; | |
387 } | |
388 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | |
389 void emit(const Cfg *Func) const override; | |
390 void emitIAS(const Cfg *Func) const override; | |
391 void dump(const Cfg *Func) const override; | |
392 static bool classof(const Inst *Inst) { | |
393 return InstX86Base::isClassof(Inst, InstX86Base::Br); | |
394 } | |
395 | |
396 private: | |
397 InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | |
398 const InstX86Label *Label, BrCond Condition, Mode Kind); | |
399 | |
400 BrCond Condition; | |
401 const CfgNode *TargetTrue; | |
402 const CfgNode *TargetFalse; | |
403 const InstX86Label *Label; // Intra-block branch target | |
404 const Mode Kind; | |
405 }; | |
406 | |
407 /// Jump to a target outside this function, such as tailcall, nacljump, | |
408 /// naclret, unreachable. This is different from a Branch instruction in that | |
409 /// there is no intra-function control flow to represent. | |
410 class InstX86Jmp final : public InstX86Base { | |
411 InstX86Jmp() = delete; | |
412 InstX86Jmp(const InstX86Jmp &) = delete; | |
413 InstX86Jmp &operator=(const InstX86Jmp &) = delete; | |
414 | |
415 public: | |
416 static InstX86Jmp *create(Cfg *Func, Operand *Target) { | |
417 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | |
418 } | |
419 Operand *getJmpTarget() const { return this->getSrc(0); } | |
420 void emit(const Cfg *Func) const override; | |
421 void emitIAS(const Cfg *Func) const override; | |
422 void dump(const Cfg *Func) const override; | |
423 static bool classof(const Inst *Inst) { | |
424 return InstX86Base::isClassof(Inst, InstX86Base::Jmp); | |
425 } | |
426 | |
427 private: | |
428 InstX86Jmp(Cfg *Func, Operand *Target); | |
429 }; | |
430 | |
431 /// Call instruction. Arguments should have already been pushed. | |
432 class InstX86Call final : public InstX86Base { | |
433 InstX86Call() = delete; | |
434 InstX86Call(const InstX86Call &) = delete; | |
435 InstX86Call &operator=(const InstX86Call &) = delete; | |
436 | |
437 public: | |
438 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | |
439 return new (Func->allocate<InstX86Call>()) | |
440 InstX86Call(Func, Dest, CallTarget); | |
441 } | |
442 Operand *getCallTarget() const { return this->getSrc(0); } | |
443 void emit(const Cfg *Func) const override; | |
444 void emitIAS(const Cfg *Func) const override; | |
445 void dump(const Cfg *Func) const override; | |
446 static bool classof(const Inst *Inst) { | |
447 return InstX86Base::isClassof(Inst, InstX86Base::Call); | |
448 } | |
449 | |
450 private: | |
451 InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | |
452 }; | |
453 | |
454 /// Emit a one-operand (GPR) instruction. | |
455 static void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | |
456 const GPREmitterOneOp &Emitter); | |
457 | |
458 static void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, | |
459 const Operand *Op1, | |
460 const GPREmitterAddrOp &Emitter); | |
461 | |
462 static void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | |
463 const Operand *Src, | |
464 const GPREmitterShiftOp &Emitter); | |
465 | |
466 static void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const Address &Addr, | |
467 const Operand *Src, | |
468 const GPREmitterAddrOp &Emitter); | |
469 | |
470 static void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | |
471 const Operand *Src, | |
472 const XmmEmitterRegOp &Emitter); | |
473 | |
474 static void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, | |
475 const Operand *Src1Op, | |
476 const Operand *Src2Op, | |
477 const GPREmitterShiftD &Emitter); | |
478 | |
479 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
480 SReg_t (*srcEnc)(int32_t)> | |
481 static void emitIASCastRegOp(const Cfg *Func, Type DestTy, | |
482 const Variable *Dest, Type SrcTy, | |
483 const Operand *Src, | |
484 const CastEmitterRegOp<DReg_t, SReg_t> &Emitter); | |
485 | |
486 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
487 SReg_t (*srcEnc)(int32_t)> | |
163 static void | 488 static void |
164 emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 489 emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, const Variable *Dest, |
165 const Operand *Src, | 490 const Operand *Src0, const Operand *Src1, |
166 const typename Traits::Assembler::GPREmitterShiftOp &Emitter); | 491 const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter); |
167 | 492 |
168 static X86TargetLowering *getTarget(const Cfg *Func) { | 493 static void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, |
169 return static_cast<X86TargetLowering *>(Func->getTarget()); | 494 const Operand *Src, |
170 } | 495 const XmmEmitterMovOps Emitter); |
171 | 496 |
172 protected: | 497 static void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
173 InstX86Base<Machine>(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, | 498 const Cfg *Func); |
174 Variable *Dest) | 499 |
175 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 500 static void emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, |
176 | 501 const XmmEmitterRegOp &Emitter); |
177 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | 502 |
178 return Inst->getKind() == static_cast<InstKind>(MyKind); | 503 static void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
179 } | 504 const Operand *Src, |
180 // Most instructions that operate on vector arguments require vector memory | 505 const XmmEmitterShiftOp &Emitter); |
181 // operands to be fully aligned (16-byte alignment for PNaCl vector types). | 506 |
182 // The stack frame layout and call ABI ensure proper alignment for stack | 507 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable |
183 // operands, but memory operands (originating from load/store bitcode | 508 /// that's guaranteed to be a register. |
184 // instructions) only have element-size alignment guarantees. This function | 509 template <bool VarCanBeByte = true, bool SrcCanBeByte = true> |
185 // validates that none of the operands is a memory operand of vector type, | 510 static void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, |
186 // calling report_fatal_error() if one is found. This function should be | 511 const Operand *Src, |
187 // called during emission, and maybe also in the ctor (as long as that fits | 512 const GPREmitterRegOp &Emitter); |
188 // the lowering style). | 513 |
189 void validateVectorAddrMode() const { | 514 /// Instructions of the form x := op(x). |
190 if (this->getDest()) | 515 template <typename InstX86Base::InstKindX86 K> |
191 this->validateVectorAddrModeOpnd(this->getDest()); | 516 class InstX86BaseInplaceopGPR : public InstX86Base { |
192 for (SizeT i = 0; i < this->getSrcSize(); ++i) { | 517 InstX86BaseInplaceopGPR() = delete; |
193 this->validateVectorAddrModeOpnd(this->getSrc(i)); | 518 InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; |
194 } | 519 InstX86BaseInplaceopGPR & |
195 } | 520 operator=(const InstX86BaseInplaceopGPR &) = delete; |
196 | 521 |
197 private: | 522 public: |
198 static void validateVectorAddrModeOpnd(const Operand *Opnd) { | 523 using Base = InstX86BaseInplaceopGPR<K>; |
199 if (llvm::isa<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && | 524 |
200 isVectorType(Opnd->getType())) { | 525 void emit(const Cfg *Func) const override { |
201 llvm::report_fatal_error("Possible misaligned vector memory operation"); | 526 if (!BuildDefs::dump()) |
202 } | 527 return; |
203 } | 528 Ostream &Str = Func->getContext()->getStrEmit(); |
204 }; | 529 assert(this->getSrcSize() == 1); |
205 | 530 Str << "\t" << Opcode << "\t"; |
206 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | 531 this->getSrc(0)->emit(Func); |
207 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it still | 532 } |
208 /// needs to be lowered to some actual RMW instruction. | 533 void emitIAS(const Cfg *Func) const override { |
209 /// | 534 assert(this->getSrcSize() == 1); |
210 /// If A is some memory address, D is some data value to apply, and OP is an | 535 const Variable *Var = this->getDest(); |
211 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | 536 Type Ty = Var->getType(); |
212 template <class Machine> | 537 emitIASOpTyGPR(Func, Ty, Var, Emitter); |
213 class InstX86FakeRMW final : public InstX86Base<Machine> { | 538 } |
214 InstX86FakeRMW() = delete; | 539 void dump(const Cfg *Func) const override { |
215 InstX86FakeRMW(const InstX86FakeRMW &) = delete; | 540 if (!BuildDefs::dump()) |
216 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | 541 return; |
217 | 542 Ostream &Str = Func->getContext()->getStrDump(); |
218 public: | 543 this->dumpDest(Func); |
219 static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | 544 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
220 Variable *Beacon, InstArithmetic::OpKind Op, | 545 this->dumpSources(Func); |
221 uint32_t Align = 1) { | 546 } |
222 // TODO(stichnot): Stop ignoring alignment specification. | 547 static bool classof(const Inst *Inst) { |
223 (void)Align; | 548 return InstX86Base::isClassof(Inst, InstX86Base::K); |
224 return new (Func->allocate<InstX86FakeRMW>()) | 549 } |
225 InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | 550 |
226 } | 551 protected: |
227 Operand *getAddr() const { return this->getSrc(1); } | 552 InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) |
228 Operand *getData() const { return this->getSrc(0); } | 553 : InstX86Base(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |
229 InstArithmetic::OpKind getOp() const { return Op; } | 554 this->addSource(SrcDest); |
230 Variable *getBeacon() const { return llvm::cast<Variable>(this->getSrc(2)); } | 555 } |
231 void dump(const Cfg *Func) const override; | 556 |
232 static bool classof(const Inst *Inst) { | 557 private: |
233 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::FakeRMW); | 558 static const char *Opcode; |
234 } | 559 static const GPREmitterOneOp Emitter; |
235 | 560 }; |
236 private: | 561 |
237 InstArithmetic::OpKind Op; | 562 /// Instructions of the form x := op(y). |
238 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 563 template <typename InstX86Base::InstKindX86 K> |
239 InstArithmetic::OpKind Op, Variable *Beacon); | 564 class InstX86BaseUnaryopGPR : public InstX86Base { |
240 }; | 565 InstX86BaseUnaryopGPR() = delete; |
241 | 566 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; |
242 /// InstX86Label represents an intra-block label that is the target of an | 567 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; |
243 /// intra-block branch. The offset between the label and the branch must be fit | 568 |
244 /// into one byte (considered "near"). These are used for lowering i1 | 569 public: |
245 /// calculations, Select instructions, and 64-bit compares on a 32-bit | 570 using Base = InstX86BaseUnaryopGPR<K>; |
246 /// architecture, without basic block splitting. Basic block splitting is not so | 571 |
247 /// desirable for several reasons, one of which is the impact on decisions based | 572 void emit(const Cfg *Func) const override { |
248 /// on whether a variable's live range spans multiple basic blocks. | 573 if (!BuildDefs::dump()) |
249 /// | 574 return; |
250 /// Intra-block control flow must be used with caution. Consider the sequence | 575 Ostream &Str = Func->getContext()->getStrEmit(); |
251 /// for "c = (a >= b ? x : y)". | 576 assert(this->getSrcSize() == 1); |
252 /// cmp a, b | 577 Type SrcTy = this->getSrc(0)->getType(); |
253 /// br lt, L1 | 578 Type DestTy = this->getDest()->getType(); |
254 /// mov c, x | 579 Str << "\t" << Opcode << this->getWidthString(SrcTy); |
255 /// jmp L2 | 580 // Movsx and movzx need both the source and dest type width letter to |
256 /// L1: | 581 // define the operation. The other unary operations have the same source |
257 /// mov c, y | 582 // and dest type and as a result need only one letter. |
258 /// L2: | 583 if (SrcTy != DestTy) |
259 /// | 584 Str << this->getWidthString(DestTy); |
260 /// Labels L1 and L2 are intra-block labels. Without knowledge of the | 585 Str << "\t"; |
261 /// intra-block control flow, liveness analysis will determine the "mov c, x" | 586 this->getSrc(0)->emit(Func); |
262 /// instruction to be dead. One way to prevent this is to insert a "FakeUse(c)" | 587 Str << ", "; |
263 /// instruction anywhere between the two "mov c, ..." instructions, e.g.: | 588 this->getDest()->emit(Func); |
264 /// | 589 } |
265 /// cmp a, b | 590 void emitIAS(const Cfg *Func) const override { |
266 /// br lt, L1 | 591 assert(this->getSrcSize() == 1); |
267 /// mov c, x | 592 const Variable *Var = this->getDest(); |
268 /// jmp L2 | 593 Type Ty = Var->getType(); |
269 /// FakeUse(c) | 594 const Operand *Src = this->getSrc(0); |
270 /// L1: | 595 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); |
271 /// mov c, y | 596 } |
272 /// L2: | 597 void dump(const Cfg *Func) const override { |
273 /// | 598 if (!BuildDefs::dump()) |
274 /// The down-side is that "mov c, x" can never be dead-code eliminated even if | 599 return; |
275 /// there are no uses of c. As unlikely as this situation is, it may be | 600 Ostream &Str = Func->getContext()->getStrDump(); |
276 /// prevented by running dead code elimination before lowering. | 601 this->dumpDest(Func); |
277 template <class Machine> | 602 Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; |
278 class InstX86Label final : public InstX86Base<Machine> { | 603 this->dumpSources(Func); |
279 InstX86Label() = delete; | 604 } |
280 InstX86Label(const InstX86Label &) = delete; | 605 static bool classof(const Inst *Inst) { |
281 InstX86Label &operator=(const InstX86Label &) = delete; | 606 return InstX86Base::isClassof(Inst, InstX86Base::K); |
282 | 607 } |
283 public: | 608 |
284 static InstX86Label * | 609 protected: |
285 create(Cfg *Func, | 610 InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |
286 typename InstX86Base<Machine>::Traits::TargetLowering *Target) { | 611 : InstX86Base(Func, K, 1, Dest) { |
287 return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | 612 this->addSource(Src); |
288 } | 613 } |
289 uint32_t getEmitInstCount() const override { return 0; } | 614 |
290 IceString getName(const Cfg *Func) const; | 615 static const char *Opcode; |
291 SizeT getNumber() const { return Number; } | 616 static const GPREmitterRegOp Emitter; |
292 void emit(const Cfg *Func) const override; | 617 }; |
293 void emitIAS(const Cfg *Func) const override; | 618 |
294 void dump(const Cfg *Func) const override; | 619 template <typename InstX86Base::InstKindX86 K> |
295 | 620 class InstX86BaseUnaryopXmm : public InstX86Base { |
296 private: | 621 InstX86BaseUnaryopXmm() = delete; |
297 InstX86Label(Cfg *Func, | 622 InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; |
298 typename InstX86Base<Machine>::Traits::TargetLowering *Target); | 623 InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; |
299 | 624 |
300 SizeT Number; // used for unique label generation. | 625 public: |
301 }; | 626 using Base = InstX86BaseUnaryopXmm<K>; |
302 | 627 |
303 /// Conditional and unconditional branch instruction. | 628 void emit(const Cfg *Func) const override { |
304 template <class Machine> class InstX86Br final : public InstX86Base<Machine> { | 629 if (!BuildDefs::dump()) |
305 InstX86Br() = delete; | 630 return; |
306 InstX86Br(const InstX86Br &) = delete; | 631 Ostream &Str = Func->getContext()->getStrEmit(); |
307 InstX86Br &operator=(const InstX86Br &) = delete; | 632 assert(this->getSrcSize() == 1); |
308 | 633 Str << "\t" << Opcode << "\t"; |
309 public: | 634 this->getSrc(0)->emit(Func); |
310 enum Mode { Near, Far }; | 635 Str << ", "; |
311 | 636 this->getDest()->emit(Func); |
312 /// Create a conditional branch to a node. | 637 } |
313 static InstX86Br * | 638 void emitIAS(const Cfg *Func) const override { |
314 create(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, | 639 Type Ty = this->getDest()->getType(); |
315 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 640 assert(this->getSrcSize() == 1); |
316 Mode Kind) { | 641 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(0), Emitter); |
317 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 642 } |
318 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 643 void dump(const Cfg *Func) const override { |
319 return new (Func->allocate<InstX86Br>()) | 644 if (!BuildDefs::dump()) |
320 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | 645 return; |
321 } | 646 Ostream &Str = Func->getContext()->getStrDump(); |
322 /// Create an unconditional branch to a node. | 647 this->dumpDest(Func); |
323 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | 648 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
324 constexpr CfgNode *NoCondTarget = nullptr; | 649 this->dumpSources(Func); |
325 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 650 } |
326 return new (Func->allocate<InstX86Br>()) | 651 static bool classof(const Inst *Inst) { |
327 InstX86Br(Func, NoCondTarget, Target, NoLabel, | 652 return InstX86Base::isClassof(Inst, InstX86Base::K); |
328 InstX86Base<Machine>::Traits::Cond::Br_None, Kind); | 653 } |
329 } | 654 |
330 /// Create a non-terminator conditional branch to a node, with a fallthrough | 655 protected: |
331 /// to the next instruction in the current node. This is used for switch | 656 InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) |
332 /// lowering. | 657 : InstX86Base(Func, K, 1, Dest) { |
333 static InstX86Br * | 658 this->addSource(Src); |
334 create(Cfg *Func, CfgNode *Target, | 659 } |
335 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 660 |
336 Mode Kind) { | 661 static const char *Opcode; |
337 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 662 static const XmmEmitterRegOp Emitter; |
338 constexpr CfgNode *NoUncondTarget = nullptr; | 663 }; |
339 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 664 |
340 return new (Func->allocate<InstX86Br>()) | 665 template <typename InstX86Base::InstKindX86 K> |
341 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | 666 class InstX86BaseBinopGPRShift : public InstX86Base { |
342 } | 667 InstX86BaseBinopGPRShift() = delete; |
343 /// Create a conditional intra-block branch (or unconditional, if | 668 InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; |
344 /// Condition==Br_None) to a label in the current block. | 669 InstX86BaseBinopGPRShift & |
345 static InstX86Br * | 670 operator=(const InstX86BaseBinopGPRShift &) = delete; |
346 create(Cfg *Func, InstX86Label<Machine> *Label, | 671 |
347 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 672 public: |
348 Mode Kind) { | 673 using Base = InstX86BaseBinopGPRShift<K>; |
349 constexpr CfgNode *NoCondTarget = nullptr; | 674 |
350 constexpr CfgNode *NoUncondTarget = nullptr; | 675 void emit(const Cfg *Func) const override { |
351 return new (Func->allocate<InstX86Br>()) | 676 if (!BuildDefs::dump()) |
352 InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | 677 return; |
353 } | |
354 const CfgNode *getTargetTrue() const { return TargetTrue; } | |
355 const CfgNode *getTargetFalse() const { return TargetFalse; } | |
356 bool isNear() const { return Kind == Near; } | |
357 bool optimizeBranch(const CfgNode *NextNode); | |
358 uint32_t getEmitInstCount() const override { | |
359 uint32_t Sum = 0; | |
360 if (Label) | |
361 ++Sum; | |
362 if (getTargetTrue()) | |
363 ++Sum; | |
364 if (getTargetFalse()) | |
365 ++Sum; | |
366 return Sum; | |
367 } | |
368 bool isUnconditionalBranch() const override { | |
369 return !Label && Condition == InstX86Base<Machine>::Traits::Cond::Br_None; | |
370 } | |
371 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | |
372 void emit(const Cfg *Func) const override; | |
373 void emitIAS(const Cfg *Func) const override; | |
374 void dump(const Cfg *Func) const override; | |
375 static bool classof(const Inst *Inst) { | |
376 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Br); | |
377 } | |
378 | |
379 private: | |
380 InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | |
381 const InstX86Label<Machine> *Label, | |
382 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | |
383 Mode Kind); | |
384 | |
385 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | |
386 const CfgNode *TargetTrue; | |
387 const CfgNode *TargetFalse; | |
388 const InstX86Label<Machine> *Label; // Intra-block branch target | |
389 const Mode Kind; | |
390 }; | |
391 | |
392 /// Jump to a target outside this function, such as tailcall, nacljump, naclret, | |
393 /// unreachable. This is different from a Branch instruction in that there is no | |
394 /// intra-function control flow to represent. | |
395 template <class Machine> class InstX86Jmp final : public InstX86Base<Machine> { | |
396 InstX86Jmp() = delete; | |
397 InstX86Jmp(const InstX86Jmp &) = delete; | |
398 InstX86Jmp &operator=(const InstX86Jmp &) = delete; | |
399 | |
400 public: | |
401 static InstX86Jmp *create(Cfg *Func, Operand *Target) { | |
402 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | |
403 } | |
404 Operand *getJmpTarget() const { return this->getSrc(0); } | |
405 void emit(const Cfg *Func) const override; | |
406 void emitIAS(const Cfg *Func) const override; | |
407 void dump(const Cfg *Func) const override; | |
408 static bool classof(const Inst *Inst) { | |
409 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Jmp); | |
410 } | |
411 | |
412 private: | |
413 InstX86Jmp(Cfg *Func, Operand *Target); | |
414 }; | |
415 | |
416 /// Call instruction. Arguments should have already been pushed. | |
417 template <class Machine> class InstX86Call final : public InstX86Base<Machine> { | |
418 InstX86Call() = delete; | |
419 InstX86Call(const InstX86Call &) = delete; | |
420 InstX86Call &operator=(const InstX86Call &) = delete; | |
421 | |
422 public: | |
423 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | |
424 return new (Func->allocate<InstX86Call>()) | |
425 InstX86Call(Func, Dest, CallTarget); | |
426 } | |
427 Operand *getCallTarget() const { return this->getSrc(0); } | |
428 void emit(const Cfg *Func) const override; | |
429 void emitIAS(const Cfg *Func) const override; | |
430 void dump(const Cfg *Func) const override; | |
431 static bool classof(const Inst *Inst) { | |
432 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Call); | |
433 } | |
434 | |
435 private: | |
436 InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | |
437 }; | |
438 | |
439 /// Emit a one-operand (GPR) instruction. | |
440 template <class Machine> | |
441 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | |
442 const typename InstX86Base< | |
443 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter); | |
444 | |
445 template <class Machine> | |
446 void emitIASAsAddrOpTyGPR( | |
447 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, | |
448 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp | |
449 &Emitter); | |
450 | |
451 /// Instructions of the form x := op(x). | |
452 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
453 class InstX86BaseInplaceopGPR : public InstX86Base<Machine> { | |
454 InstX86BaseInplaceopGPR() = delete; | |
455 InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; | |
456 InstX86BaseInplaceopGPR &operator=(const InstX86BaseInplaceopGPR &) = delete; | |
457 | |
458 public: | |
459 using Base = InstX86BaseInplaceopGPR<Machine, K>; | |
460 | |
461 void emit(const Cfg *Func) const override { | |
462 if (!BuildDefs::dump()) | |
463 return; | |
464 Ostream &Str = Func->getContext()->getStrEmit(); | |
465 assert(this->getSrcSize() == 1); | |
466 Str << "\t" << Opcode << "\t"; | |
467 this->getSrc(0)->emit(Func); | |
468 } | |
469 void emitIAS(const Cfg *Func) const override { | |
470 assert(this->getSrcSize() == 1); | |
471 const Variable *Var = this->getDest(); | |
472 Type Ty = Var->getType(); | |
473 emitIASOpTyGPR<Machine>(Func, Ty, Var, Emitter); | |
474 } | |
475 void dump(const Cfg *Func) const override { | |
476 if (!BuildDefs::dump()) | |
477 return; | |
478 Ostream &Str = Func->getContext()->getStrDump(); | |
479 this->dumpDest(Func); | |
480 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
481 this->dumpSources(Func); | |
482 } | |
483 static bool classof(const Inst *Inst) { | |
484 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
485 } | |
486 | |
487 protected: | |
488 InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) | |
489 : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | |
490 this->addSource(SrcDest); | |
491 } | |
492 | |
493 private: | |
494 static const char *Opcode; | |
495 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp | |
496 Emitter; | |
497 }; | |
498 | |
499 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable | |
500 /// that's guaranteed to be a register. | |
501 template <class Machine, bool VarCanBeByte = true, bool SrcCanBeByte = true> | |
502 void emitIASRegOpTyGPR( | |
503 const Cfg *Func, Type Ty, const Variable *Dst, const Operand *Src, | |
504 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
505 &Emitter); | |
506 | |
507 /// Instructions of the form x := op(y). | |
508 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
509 class InstX86BaseUnaryopGPR : public InstX86Base<Machine> { | |
510 InstX86BaseUnaryopGPR() = delete; | |
511 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; | |
512 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; | |
513 | |
514 public: | |
515 using Base = InstX86BaseUnaryopGPR<Machine, K>; | |
516 | |
517 void emit(const Cfg *Func) const override { | |
518 if (!BuildDefs::dump()) | |
519 return; | |
520 Ostream &Str = Func->getContext()->getStrEmit(); | |
521 assert(this->getSrcSize() == 1); | |
522 Type SrcTy = this->getSrc(0)->getType(); | |
523 Type DestTy = this->getDest()->getType(); | |
524 Str << "\t" << Opcode << this->getWidthString(SrcTy); | |
525 // Movsx and movzx need both the source and dest type width letter to | |
526 // define the operation. The other unary operations have the same source | |
527 // and dest type and as a result need only one letter. | |
528 if (SrcTy != DestTy) | |
529 Str << this->getWidthString(DestTy); | |
530 Str << "\t"; | |
531 this->getSrc(0)->emit(Func); | |
532 Str << ", "; | |
533 this->getDest()->emit(Func); | |
534 } | |
535 void emitIAS(const Cfg *Func) const override { | |
536 assert(this->getSrcSize() == 1); | |
537 const Variable *Var = this->getDest(); | |
538 Type Ty = Var->getType(); | |
539 const Operand *Src = this->getSrc(0); | |
540 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter); | |
541 } | |
542 void dump(const Cfg *Func) const override { | |
543 if (!BuildDefs::dump()) | |
544 return; | |
545 Ostream &Str = Func->getContext()->getStrDump(); | |
546 this->dumpDest(Func); | |
547 Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; | |
548 this->dumpSources(Func); | |
549 } | |
550 static bool classof(const Inst *Inst) { | |
551 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
552 } | |
553 | |
554 protected: | |
555 InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | |
556 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
557 this->addSource(Src); | |
558 } | |
559 | |
560 static const char *Opcode; | |
561 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
562 Emitter; | |
563 }; | |
564 | |
565 template <class Machine> | |
566 void emitIASRegOpTyXMM( | |
567 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | |
568 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | |
569 &Emitter); | |
570 | |
571 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
572 class InstX86BaseUnaryopXmm : public InstX86Base<Machine> { | |
573 InstX86BaseUnaryopXmm() = delete; | |
574 InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; | |
575 InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; | |
576 | |
577 public: | |
578 using Base = InstX86BaseUnaryopXmm<Machine, K>; | |
579 | |
580 void emit(const Cfg *Func) const override { | |
581 if (!BuildDefs::dump()) | |
582 return; | |
583 Ostream &Str = Func->getContext()->getStrEmit(); | |
584 assert(this->getSrcSize() == 1); | |
585 Str << "\t" << Opcode << "\t"; | |
586 this->getSrc(0)->emit(Func); | |
587 Str << ", "; | |
588 this->getDest()->emit(Func); | |
589 } | |
590 void emitIAS(const Cfg *Func) const override { | |
591 Type Ty = this->getDest()->getType(); | |
592 assert(this->getSrcSize() == 1); | |
593 emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(0), | |
594 Emitter); | |
595 } | |
596 void dump(const Cfg *Func) const override { | |
597 if (!BuildDefs::dump()) | |
598 return; | |
599 Ostream &Str = Func->getContext()->getStrDump(); | |
600 this->dumpDest(Func); | |
601 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
602 this->dumpSources(Func); | |
603 } | |
604 static bool classof(const Inst *Inst) { | |
605 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
606 } | |
607 | |
608 protected: | |
609 InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) | |
610 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
611 this->addSource(Src); | |
612 } | |
613 | |
614 static const char *Opcode; | |
615 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | |
616 Emitter; | |
617 }; | |
618 | |
619 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
620 class InstX86BaseBinopGPRShift : public InstX86Base<Machine> { | |
621 InstX86BaseBinopGPRShift() = delete; | |
622 InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; | |
623 InstX86BaseBinopGPRShift & | |
624 operator=(const InstX86BaseBinopGPRShift &) = delete; | |
625 | |
626 public: | |
627 using Base = InstX86BaseBinopGPRShift<Machine, K>; | |
628 | |
629 void emit(const Cfg *Func) const override { | |
630 if (!BuildDefs::dump()) | |
631 return; | |
632 this->emitTwoAddress(Func, Opcode); | |
633 } | |
634 void emitIAS(const Cfg *Func) const override { | |
635 Type Ty = this->getDest()->getType(); | |
636 assert(this->getSrcSize() == 2); | |
637 this->emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
638 } | |
639 void dump(const Cfg *Func) const override { | |
640 if (!BuildDefs::dump()) | |
641 return; | |
642 Ostream &Str = Func->getContext()->getStrDump(); | |
643 this->dumpDest(Func); | |
644 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
645 this->dumpSources(Func); | |
646 } | |
647 static bool classof(const Inst *Inst) { | |
648 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
649 } | |
650 | |
651 protected: | |
652 InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | |
653 : InstX86Base<Machine>(Func, K, 2, Dest) { | |
654 this->addSource(Dest); | |
655 this->addSource(Source); | |
656 } | |
657 | |
658 static const char *Opcode; | |
659 static const typename InstX86Base< | |
660 Machine>::Traits::Assembler::GPREmitterShiftOp Emitter; | |
661 }; | |
662 | |
663 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
664 class InstX86BaseBinopGPR : public InstX86Base<Machine> { | |
665 InstX86BaseBinopGPR() = delete; | |
666 InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | |
667 InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | |
668 | |
669 public: | |
670 using Base = InstX86BaseBinopGPR<Machine, K>; | |
671 | |
672 void emit(const Cfg *Func) const override { | |
673 if (!BuildDefs::dump()) | |
674 return; | |
675 this->emitTwoAddress(Func, Opcode); | |
676 } | |
677 void emitIAS(const Cfg *Func) const override { | |
678 Type Ty = this->getDest()->getType(); | |
679 assert(this->getSrcSize() == 2); | |
680 emitIASRegOpTyGPR<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | |
681 Emitter); | |
682 } | |
683 void dump(const Cfg *Func) const override { | |
684 if (!BuildDefs::dump()) | |
685 return; | |
686 Ostream &Str = Func->getContext()->getStrDump(); | |
687 this->dumpDest(Func); | |
688 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
689 this->dumpSources(Func); | |
690 } | |
691 static bool classof(const Inst *Inst) { | |
692 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
693 } | |
694 | |
695 protected: | |
696 InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | |
697 : InstX86Base<Machine>(Func, K, 2, Dest) { | |
698 this->addSource(Dest); | |
699 this->addSource(Source); | |
700 } | |
701 | |
702 static const char *Opcode; | |
703 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
704 Emitter; | |
705 }; | |
706 | |
707 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
708 class InstX86BaseBinopRMW : public InstX86Base<Machine> { | |
709 InstX86BaseBinopRMW() = delete; | |
710 InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | |
711 InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | |
712 | |
713 public: | |
714 using Base = InstX86BaseBinopRMW<Machine, K>; | |
715 | |
716 void emit(const Cfg *Func) const override { | |
717 if (!BuildDefs::dump()) | |
718 return; | |
719 this->emitTwoAddress(Func, Opcode); | |
720 } | |
721 void emitIAS(const Cfg *Func) const override { | |
722 Type Ty = this->getSrc(0)->getType(); | |
723 assert(this->getSrcSize() == 2); | |
724 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, this->getSrc(0), this->getSrc(1), | |
725 Emitter); | |
726 } | |
727 void dump(const Cfg *Func) const override { | |
728 if (!BuildDefs::dump()) | |
729 return; | |
730 Ostream &Str = Func->getContext()->getStrDump(); | |
731 Str << Opcode << "." << this->getSrc(0)->getType() << " "; | |
732 this->dumpSources(Func); | |
733 } | |
734 static bool classof(const Inst *Inst) { | |
735 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
736 } | |
737 | |
738 protected: | |
739 InstX86BaseBinopRMW( | |
740 Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
741 Operand *Src1) | |
742 : InstX86Base<Machine>(Func, K, 2, nullptr) { | |
743 this->addSource(DestSrc0); | |
744 this->addSource(Src1); | |
745 } | |
746 | |
747 static const char *Opcode; | |
748 static const typename InstX86Base< | |
749 Machine>::Traits::Assembler::GPREmitterAddrOp Emitter; | |
750 }; | |
751 | |
752 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | |
753 bool NeedsElementType, | |
754 typename InstX86Base<Machine>::SseSuffix Suffix> | |
755 class InstX86BaseBinopXmm : public InstX86Base<Machine> { | |
756 InstX86BaseBinopXmm() = delete; | |
757 InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | |
758 InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | |
759 | |
760 public: | |
761 using Base = InstX86BaseBinopXmm<Machine, K, NeedsElementType, Suffix>; | |
762 | |
763 void emit(const Cfg *Func) const override { | |
764 if (!BuildDefs::dump()) | |
765 return; | |
766 this->validateVectorAddrMode(); | |
767 switch (Suffix) { | |
768 case InstX86Base<Machine>::SseSuffix::None: | |
769 this->emitTwoAddress(Func, Opcode); | 678 this->emitTwoAddress(Func, Opcode); |
770 break; | 679 } |
771 case InstX86Base<Machine>::SseSuffix::Packed: { | 680 void emitIAS(const Cfg *Func) const override { |
681 Type Ty = this->getDest()->getType(); | |
682 assert(this->getSrcSize() == 2); | |
683 emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
684 } | |
685 void dump(const Cfg *Func) const override { | |
686 if (!BuildDefs::dump()) | |
687 return; | |
688 Ostream &Str = Func->getContext()->getStrDump(); | |
689 this->dumpDest(Func); | |
690 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
691 this->dumpSources(Func); | |
692 } | |
693 static bool classof(const Inst *Inst) { | |
694 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
695 } | |
696 | |
697 protected: | |
698 InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | |
699 : InstX86Base(Func, K, 2, Dest) { | |
700 this->addSource(Dest); | |
701 this->addSource(Source); | |
702 } | |
703 | |
704 static const char *Opcode; | |
705 static const GPREmitterShiftOp Emitter; | |
706 }; | |
707 | |
708 template <typename InstX86Base::InstKindX86 K> | |
709 class InstX86BaseBinopGPR : public InstX86Base { | |
710 InstX86BaseBinopGPR() = delete; | |
711 InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | |
712 InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | |
713 | |
714 public: | |
715 using Base = InstX86BaseBinopGPR<K>; | |
716 | |
717 void emit(const Cfg *Func) const override { | |
718 if (!BuildDefs::dump()) | |
719 return; | |
720 this->emitTwoAddress(Func, Opcode); | |
721 } | |
722 void emitIAS(const Cfg *Func) const override { | |
723 Type Ty = this->getDest()->getType(); | |
724 assert(this->getSrcSize() == 2); | |
725 emitIASRegOpTyGPR(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
726 } | |
727 void dump(const Cfg *Func) const override { | |
728 if (!BuildDefs::dump()) | |
729 return; | |
730 Ostream &Str = Func->getContext()->getStrDump(); | |
731 this->dumpDest(Func); | |
732 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
733 this->dumpSources(Func); | |
734 } | |
735 static bool classof(const Inst *Inst) { | |
736 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
737 } | |
738 | |
739 protected: | |
740 InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | |
741 : InstX86Base(Func, K, 2, Dest) { | |
742 this->addSource(Dest); | |
743 this->addSource(Source); | |
744 } | |
745 | |
746 static const char *Opcode; | |
747 static const GPREmitterRegOp Emitter; | |
748 }; | |
749 | |
750 template <typename InstX86Base::InstKindX86 K> | |
751 class InstX86BaseBinopRMW : public InstX86Base { | |
752 InstX86BaseBinopRMW() = delete; | |
753 InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | |
754 InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | |
755 | |
756 public: | |
757 using Base = InstX86BaseBinopRMW<K>; | |
758 | |
759 void emit(const Cfg *Func) const override { | |
760 if (!BuildDefs::dump()) | |
761 return; | |
762 this->emitTwoAddress(Func, Opcode); | |
763 } | |
764 void emitIAS(const Cfg *Func) const override { | |
765 Type Ty = this->getSrc(0)->getType(); | |
766 assert(this->getSrcSize() == 2); | |
767 emitIASAsAddrOpTyGPR(Func, Ty, this->getSrc(0), this->getSrc(1), Emitter); | |
768 } | |
769 void dump(const Cfg *Func) const override { | |
770 if (!BuildDefs::dump()) | |
771 return; | |
772 Ostream &Str = Func->getContext()->getStrDump(); | |
773 Str << Opcode << "." << this->getSrc(0)->getType() << " "; | |
774 this->dumpSources(Func); | |
775 } | |
776 static bool classof(const Inst *Inst) { | |
777 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
778 } | |
779 | |
780 protected: | |
781 InstX86BaseBinopRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
782 : InstX86Base(Func, K, 2, nullptr) { | |
783 this->addSource(DestSrc0); | |
784 this->addSource(Src1); | |
785 } | |
786 | |
787 static const char *Opcode; | |
788 static const GPREmitterAddrOp Emitter; | |
789 }; | |
790 | |
791 template <typename InstX86Base::InstKindX86 K, bool NeedsElementType, | |
792 typename InstX86Base::SseSuffix Suffix> | |
793 class InstX86BaseBinopXmm : public InstX86Base { | |
794 InstX86BaseBinopXmm() = delete; | |
795 InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | |
796 InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | |
797 | |
798 public: | |
799 using Base = InstX86BaseBinopXmm<K, NeedsElementType, Suffix>; | |
800 | |
801 void emit(const Cfg *Func) const override { | |
802 if (!BuildDefs::dump()) | |
803 return; | |
804 this->validateVectorAddrMode(); | |
805 switch (Suffix) { | |
806 case InstX86Base::SseSuffix::None: | |
807 this->emitTwoAddress(Func, Opcode); | |
808 break; | |
809 case InstX86Base::SseSuffix::Packed: { | |
810 const Type DestTy = this->getDest()->getType(); | |
811 this->emitTwoAddress(Func, this->Opcode, | |
812 Traits::TypeAttributes[DestTy].PdPsString); | |
813 } break; | |
814 case InstX86Base::SseSuffix::Scalar: { | |
815 const Type DestTy = this->getDest()->getType(); | |
816 this->emitTwoAddress(Func, this->Opcode, | |
817 Traits::TypeAttributes[DestTy].SdSsString); | |
818 } break; | |
819 case InstX86Base::SseSuffix::Integral: { | |
820 const Type DestTy = this->getDest()->getType(); | |
821 this->emitTwoAddress(Func, this->Opcode, | |
822 Traits::TypeAttributes[DestTy].PackString); | |
823 } break; | |
824 } | |
825 } | |
826 void emitIAS(const Cfg *Func) const override { | |
827 this->validateVectorAddrMode(); | |
828 Type Ty = this->getDest()->getType(); | |
829 if (NeedsElementType) | |
830 Ty = typeElementType(Ty); | |
831 assert(this->getSrcSize() == 2); | |
832 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
833 } | |
834 void dump(const Cfg *Func) const override { | |
835 if (!BuildDefs::dump()) | |
836 return; | |
837 Ostream &Str = Func->getContext()->getStrDump(); | |
838 this->dumpDest(Func); | |
839 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
840 this->dumpSources(Func); | |
841 } | |
842 static bool classof(const Inst *Inst) { | |
843 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
844 } | |
845 | |
846 protected: | |
847 InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | |
848 : InstX86Base(Func, K, 2, Dest) { | |
849 this->addSource(Dest); | |
850 this->addSource(Source); | |
851 } | |
852 | |
853 static const char *Opcode; | |
854 static const XmmEmitterRegOp Emitter; | |
855 }; | |
856 | |
857 template <typename InstX86Base::InstKindX86 K, bool AllowAllTypes = false> | |
858 class InstX86BaseBinopXmmShift : public InstX86Base { | |
859 InstX86BaseBinopXmmShift() = delete; | |
860 InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | |
861 InstX86BaseBinopXmmShift & | |
862 operator=(const InstX86BaseBinopXmmShift &) = delete; | |
863 | |
864 public: | |
865 using Base = InstX86BaseBinopXmmShift<K, AllowAllTypes>; | |
866 | |
867 void emit(const Cfg *Func) const override { | |
868 if (!BuildDefs::dump()) | |
869 return; | |
870 this->validateVectorAddrMode(); | |
871 // Shift operations are always integral, and hence always need a suffix. | |
772 const Type DestTy = this->getDest()->getType(); | 872 const Type DestTy = this->getDest()->getType(); |
773 this->emitTwoAddress( | 873 this->emitTwoAddress(Func, this->Opcode, |
774 Func, this->Opcode, | 874 Traits::TypeAttributes[DestTy].PackString); |
775 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PdPsString); | 875 } |
776 } break; | 876 void emitIAS(const Cfg *Func) const override { |
777 case InstX86Base<Machine>::SseSuffix::Scalar: { | 877 this->validateVectorAddrMode(); |
778 const Type DestTy = this->getDest()->getType(); | 878 Type Ty = this->getDest()->getType(); |
779 this->emitTwoAddress( | 879 assert(AllowAllTypes || isVectorType(Ty)); |
780 Func, this->Opcode, | 880 Type ElementTy = typeElementType(Ty); |
781 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].SdSsString); | 881 assert(this->getSrcSize() == 2); |
782 } break; | 882 emitIASXmmShift(Func, ElementTy, this->getDest(), this->getSrc(1), |
783 case InstX86Base<Machine>::SseSuffix::Integral: { | 883 Emitter); |
784 const Type DestTy = this->getDest()->getType(); | 884 } |
785 this->emitTwoAddress( | 885 void dump(const Cfg *Func) const override { |
786 Func, this->Opcode, | 886 if (!BuildDefs::dump()) |
787 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 887 return; |
788 } break; | 888 Ostream &Str = Func->getContext()->getStrDump(); |
789 } | 889 this->dumpDest(Func); |
790 } | 890 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
791 void emitIAS(const Cfg *Func) const override { | 891 this->dumpSources(Func); |
792 this->validateVectorAddrMode(); | 892 } |
793 Type Ty = this->getDest()->getType(); | 893 static bool classof(const Inst *Inst) { |
794 if (NeedsElementType) | 894 return InstX86Base::isClassof(Inst, InstX86Base::K); |
795 Ty = typeElementType(Ty); | 895 } |
796 assert(this->getSrcSize() == 2); | 896 |
797 emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | 897 protected: |
798 Emitter); | 898 InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) |
799 } | 899 : InstX86Base(Func, K, 2, Dest) { |
800 void dump(const Cfg *Func) const override { | 900 this->addSource(Dest); |
801 if (!BuildDefs::dump()) | 901 this->addSource(Source); |
802 return; | 902 } |
803 Ostream &Str = Func->getContext()->getStrDump(); | 903 |
804 this->dumpDest(Func); | 904 static const char *Opcode; |
805 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 905 static const XmmEmitterShiftOp Emitter; |
806 this->dumpSources(Func); | 906 }; |
807 } | 907 |
808 static bool classof(const Inst *Inst) { | 908 template <typename InstX86Base::InstKindX86 K> |
809 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 909 class InstX86BaseTernop : public InstX86Base { |
810 } | 910 InstX86BaseTernop() = delete; |
811 | 911 InstX86BaseTernop(const InstX86BaseTernop &) = delete; |
812 protected: | 912 InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; |
813 InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | 913 |
814 : InstX86Base<Machine>(Func, K, 2, Dest) { | 914 public: |
815 this->addSource(Dest); | 915 using Base = InstX86BaseTernop<K>; |
816 this->addSource(Source); | 916 |
817 } | 917 void emit(const Cfg *Func) const override { |
818 | 918 if (!BuildDefs::dump()) |
819 static const char *Opcode; | 919 return; |
820 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | 920 Ostream &Str = Func->getContext()->getStrEmit(); |
821 Emitter; | 921 assert(this->getSrcSize() == 3); |
822 }; | 922 Str << "\t" << Opcode << "\t"; |
823 | 923 this->getSrc(2)->emit(Func); |
824 template <class Machine> | 924 Str << ", "; |
825 void emitIASXmmShift( | 925 this->getSrc(1)->emit(Func); |
826 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | 926 Str << ", "; |
827 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp | 927 this->getDest()->emit(Func); |
828 &Emitter); | 928 } |
829 | 929 void dump(const Cfg *Func) const override { |
830 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | 930 if (!BuildDefs::dump()) |
831 bool AllowAllTypes = false> | 931 return; |
832 class InstX86BaseBinopXmmShift : public InstX86Base<Machine> { | 932 Ostream &Str = Func->getContext()->getStrDump(); |
833 InstX86BaseBinopXmmShift() = delete; | 933 this->dumpDest(Func); |
834 InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | 934 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
835 InstX86BaseBinopXmmShift & | 935 this->dumpSources(Func); |
836 operator=(const InstX86BaseBinopXmmShift &) = delete; | 936 } |
837 | 937 static bool classof(const Inst *Inst) { |
838 public: | 938 return InstX86Base::isClassof(Inst, InstX86Base::K); |
839 using Base = InstX86BaseBinopXmmShift<Machine, K, AllowAllTypes>; | 939 } |
840 | 940 |
841 void emit(const Cfg *Func) const override { | 941 protected: |
842 if (!BuildDefs::dump()) | 942 InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, |
843 return; | 943 Operand *Source2) |
844 this->validateVectorAddrMode(); | 944 : InstX86Base(Func, K, 3, Dest) { |
845 // Shift operations are always integral, and hence always need a suffix. | 945 this->addSource(Dest); |
846 const Type DestTy = this->getDest()->getType(); | 946 this->addSource(Source1); |
847 this->emitTwoAddress( | 947 this->addSource(Source2); |
848 Func, this->Opcode, | 948 } |
849 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 949 |
850 } | 950 static const char *Opcode; |
851 void emitIAS(const Cfg *Func) const override { | 951 }; |
852 this->validateVectorAddrMode(); | 952 |
853 Type Ty = this->getDest()->getType(); | 953 // Instructions of the form x := y op z |
854 assert(AllowAllTypes || isVectorType(Ty)); | 954 template <typename InstX86Base::InstKindX86 K> |
855 Type ElementTy = typeElementType(Ty); | 955 class InstX86BaseThreeAddressop : public InstX86Base { |
856 assert(this->getSrcSize() == 2); | 956 InstX86BaseThreeAddressop() = delete; |
857 emitIASXmmShift<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1), | 957 InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; |
858 Emitter); | 958 InstX86BaseThreeAddressop & |
859 } | 959 operator=(const InstX86BaseThreeAddressop &) = delete; |
860 void dump(const Cfg *Func) const override { | 960 |
861 if (!BuildDefs::dump()) | 961 public: |
862 return; | 962 using Base = InstX86BaseThreeAddressop<K>; |
863 Ostream &Str = Func->getContext()->getStrDump(); | 963 |
864 this->dumpDest(Func); | 964 void emit(const Cfg *Func) const override { |
865 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 965 if (!BuildDefs::dump()) |
866 this->dumpSources(Func); | 966 return; |
867 } | 967 Ostream &Str = Func->getContext()->getStrEmit(); |
868 static bool classof(const Inst *Inst) { | 968 assert(this->getSrcSize() == 2); |
869 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 969 Str << "\t" << Opcode << "\t"; |
870 } | 970 this->getSrc(1)->emit(Func); |
871 | 971 Str << ", "; |
872 protected: | 972 this->getSrc(0)->emit(Func); |
873 InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) | 973 Str << ", "; |
874 : InstX86Base<Machine>(Func, K, 2, Dest) { | 974 this->getDest()->emit(Func); |
875 this->addSource(Dest); | 975 } |
876 this->addSource(Source); | 976 void dump(const Cfg *Func) const override { |
877 } | 977 if (!BuildDefs::dump()) |
878 | 978 return; |
879 static const char *Opcode; | 979 Ostream &Str = Func->getContext()->getStrDump(); |
880 static const typename InstX86Base< | 980 this->dumpDest(Func); |
881 Machine>::Traits::Assembler::XmmEmitterShiftOp Emitter; | 981 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
882 }; | 982 this->dumpSources(Func); |
883 | 983 } |
884 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 984 static bool classof(const Inst *Inst) { |
885 class InstX86BaseTernop : public InstX86Base<Machine> { | 985 return InstX86Base::isClassof(Inst, InstX86Base::K); |
886 InstX86BaseTernop() = delete; | 986 } |
887 InstX86BaseTernop(const InstX86BaseTernop &) = delete; | 987 |
888 InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; | 988 protected: |
889 | 989 InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, |
890 public: | 990 Operand *Source1) |
891 using Base = InstX86BaseTernop<Machine, K>; | 991 : InstX86Base(Func, K, 2, Dest) { |
892 | 992 this->addSource(Source0); |
893 void emit(const Cfg *Func) const override { | 993 this->addSource(Source1); |
894 if (!BuildDefs::dump()) | 994 } |
895 return; | 995 |
896 Ostream &Str = Func->getContext()->getStrEmit(); | 996 static const char *Opcode; |
897 assert(this->getSrcSize() == 3); | 997 }; |
898 Str << "\t" << Opcode << "\t"; | 998 |
899 this->getSrc(2)->emit(Func); | 999 /// Base class for assignment instructions |
900 Str << ", "; | 1000 template <typename InstX86Base::InstKindX86 K> |
901 this->getSrc(1)->emit(Func); | 1001 class InstX86BaseMovlike : public InstX86Base { |
902 Str << ", "; | 1002 InstX86BaseMovlike() = delete; |
903 this->getDest()->emit(Func); | 1003 InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; |
904 } | 1004 InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; |
905 void dump(const Cfg *Func) const override { | 1005 |
906 if (!BuildDefs::dump()) | 1006 public: |
907 return; | 1007 using Base = InstX86BaseMovlike<K>; |
908 Ostream &Str = Func->getContext()->getStrDump(); | 1008 |
909 this->dumpDest(Func); | 1009 bool isRedundantAssign() const override { |
910 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 1010 if (const auto *SrcVar = |
911 this->dumpSources(Func); | 1011 llvm::dyn_cast<const Variable>(this->getSrc(0))) { |
912 } | 1012 if (SrcVar->hasReg() && this->Dest->hasReg()) { |
913 static bool classof(const Inst *Inst) { | 1013 // An assignment between physical registers is considered redundant if |
914 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 1014 // they have the same base register and the same encoding. E.g.: |
915 } | 1015 // mov cl, ecx ==> redundant |
916 | 1016 // mov ch, ecx ==> not redundant due to different encodings |
917 protected: | 1017 // mov ch, ebp ==> not redundant due to different base registers |
918 InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, | 1018 // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting |
1019 // is handled by Inst86Zext. | |
1020 const int32_t SrcReg = SrcVar->getRegNum(); | |
1021 const int32_t DestReg = this->Dest->getRegNum(); | |
1022 return (Traits::getEncoding(SrcReg) == | |
1023 Traits::getEncoding(DestReg)) && | |
1024 (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg)); | |
1025 } | |
1026 } | |
1027 return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | |
1028 } | |
1029 bool isVarAssign() const override { | |
1030 return llvm::isa<Variable>(this->getSrc(0)); | |
1031 } | |
1032 void dump(const Cfg *Func) const override { | |
1033 if (!BuildDefs::dump()) | |
1034 return; | |
1035 Ostream &Str = Func->getContext()->getStrDump(); | |
1036 Str << Opcode << "." << this->getDest()->getType() << " "; | |
1037 this->dumpDest(Func); | |
1038 Str << ", "; | |
1039 this->dumpSources(Func); | |
1040 } | |
1041 static bool classof(const Inst *Inst) { | |
1042 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
1043 } | |
1044 | |
1045 protected: | |
1046 InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | |
1047 : InstX86Base(Func, K, 1, Dest) { | |
1048 this->addSource(Source); | |
1049 // For an integer assignment, make sure it's either a same-type assignment | |
1050 // or a truncation. | |
1051 assert(!isScalarIntegerType(Dest->getType()) || | |
1052 (typeWidthInBytes(Dest->getType()) <= | |
1053 typeWidthInBytes(Source->getType()))); | |
1054 } | |
1055 | |
1056 static const char *Opcode; | |
1057 }; | |
1058 | |
1059 class InstX86Bswap : public InstX86BaseInplaceopGPR<InstX86Base::Bswap> { | |
1060 public: | |
1061 static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | |
1062 return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | |
1063 } | |
1064 | |
1065 private: | |
1066 InstX86Bswap(Cfg *Func, Operand *SrcDest) | |
1067 : InstX86BaseInplaceopGPR<InstX86Base::Bswap>(Func, SrcDest) {} | |
1068 }; | |
1069 | |
1070 class InstX86Neg : public InstX86BaseInplaceopGPR<InstX86Base::Neg> { | |
1071 public: | |
1072 static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | |
1073 return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | |
1074 } | |
1075 | |
1076 private: | |
1077 InstX86Neg(Cfg *Func, Operand *SrcDest) | |
1078 : InstX86BaseInplaceopGPR<InstX86Base::Neg>(Func, SrcDest) {} | |
1079 }; | |
1080 | |
1081 class InstX86Bsf : public InstX86BaseUnaryopGPR<InstX86Base::Bsf> { | |
1082 public: | |
1083 static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1084 return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | |
1085 } | |
1086 | |
1087 private: | |
1088 InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | |
1089 : InstX86BaseUnaryopGPR<InstX86Base::Bsf>(Func, Dest, Src) {} | |
1090 }; | |
1091 | |
1092 class InstX86Bsr : public InstX86BaseUnaryopGPR<InstX86Base::Bsr> { | |
1093 public: | |
1094 static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1095 return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | |
1096 } | |
1097 | |
1098 private: | |
1099 InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | |
1100 : InstX86BaseUnaryopGPR<InstX86Base::Bsr>(Func, Dest, Src) {} | |
1101 }; | |
1102 | |
1103 class InstX86Lea : public InstX86BaseUnaryopGPR<InstX86Base::Lea> { | |
1104 public: | |
1105 static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1106 return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | |
1107 } | |
1108 | |
1109 void emit(const Cfg *Func) const override; | |
1110 | |
1111 private: | |
1112 InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | |
1113 : InstX86BaseUnaryopGPR<InstX86Base::Lea>(Func, Dest, Src) {} | |
1114 }; | |
1115 | |
1116 // Cbwdq instruction - wrapper for cbw, cwd, and cdq | |
1117 class InstX86Cbwdq : public InstX86BaseUnaryopGPR<InstX86Base::Cbwdq> { | |
1118 public: | |
1119 static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1120 return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | |
1121 } | |
1122 | |
1123 void emit(const Cfg *Func) const override; | |
1124 void emitIAS(const Cfg *Func) const override; | |
1125 | |
1126 private: | |
1127 InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | |
1128 : InstX86BaseUnaryopGPR<InstX86Base::Cbwdq>(Func, Dest, Src) {} | |
1129 }; | |
1130 | |
1131 class InstX86Movsx : public InstX86BaseUnaryopGPR<InstX86Base::Movsx> { | |
1132 public: | |
1133 static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1134 assert(typeWidthInBytes(Dest->getType()) > | |
1135 typeWidthInBytes(Src->getType())); | |
1136 return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | |
1137 } | |
1138 | |
1139 void emitIAS(const Cfg *Func) const override; | |
1140 | |
1141 private: | |
1142 InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | |
1143 : InstX86BaseUnaryopGPR<InstX86Base::Movsx>(Func, Dest, Src) {} | |
1144 }; | |
1145 | |
1146 class InstX86Movzx : public InstX86BaseUnaryopGPR<InstX86Base::Movzx> { | |
1147 public: | |
1148 static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1149 assert(typeWidthInBytes(Dest->getType()) > | |
1150 typeWidthInBytes(Src->getType())); | |
1151 return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | |
1152 } | |
1153 | |
1154 void emit(const Cfg *Func) const override; | |
1155 | |
1156 void emitIAS(const Cfg *Func) const override; | |
1157 | |
1158 private: | |
1159 InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | |
1160 : InstX86BaseUnaryopGPR<InstX86Base::Movzx>(Func, Dest, Src) {} | |
1161 }; | |
1162 | |
1163 class InstX86Movd : public InstX86BaseUnaryopXmm<InstX86Base::Movd> { | |
1164 public: | |
1165 static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1166 return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | |
1167 } | |
1168 | |
1169 void emit(const Cfg *Func) const override; | |
1170 | |
1171 void emitIAS(const Cfg *Func) const override; | |
1172 | |
1173 private: | |
1174 InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | |
1175 : InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {} | |
1176 }; | |
1177 | |
1178 class InstX86Sqrtss : public InstX86BaseUnaryopXmm<InstX86Base::Sqrtss> { | |
1179 public: | |
1180 static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1181 return new (Func->allocate<InstX86Sqrtss>()) | |
1182 InstX86Sqrtss(Func, Dest, Src); | |
1183 } | |
1184 | |
1185 virtual void emit(const Cfg *Func) const override; | |
1186 | |
1187 private: | |
1188 InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | |
1189 : InstX86BaseUnaryopXmm<InstX86Base::Sqrtss>(Func, Dest, Src) {} | |
1190 }; | |
1191 | |
1192 /// Move/assignment instruction - wrapper for mov/movss/movsd. | |
1193 class InstX86Mov : public InstX86BaseMovlike<InstX86Base::Mov> { | |
1194 public: | |
1195 static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1196 assert(!isScalarIntegerType(Dest->getType()) || | |
1197 (typeWidthInBytes(Dest->getType()) <= | |
1198 typeWidthInBytes(Source->getType()))); | |
1199 return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | |
1200 } | |
1201 | |
1202 void emit(const Cfg *Func) const override; | |
1203 void emitIAS(const Cfg *Func) const override; | |
1204 | |
1205 private: | |
1206 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
1207 : InstX86BaseMovlike<InstX86Base::Mov>(Func, Dest, Source) {} | |
1208 }; | |
1209 | |
1210 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | |
1211 /// registers. | |
1212 class InstX86Movp : public InstX86BaseMovlike<InstX86Base::Movp> { | |
1213 public: | |
1214 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1215 return new (Func->allocate<InstX86Movp>()) | |
1216 InstX86Movp(Func, Dest, Source); | |
1217 } | |
1218 | |
1219 void emit(const Cfg *Func) const override; | |
1220 void emitIAS(const Cfg *Func) const override; | |
1221 | |
1222 private: | |
1223 InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | |
1224 : InstX86BaseMovlike<InstX86Base::Movp>(Func, Dest, Source) {} | |
1225 }; | |
1226 | |
1227 /// Movq - copy between XMM registers, or mem64 and XMM registers. | |
1228 class InstX86Movq : public InstX86BaseMovlike<InstX86Base::Movq> { | |
1229 public: | |
1230 static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1231 return new (Func->allocate<InstX86Movq>()) | |
1232 InstX86Movq(Func, Dest, Source); | |
1233 } | |
1234 | |
1235 void emit(const Cfg *Func) const override; | |
1236 void emitIAS(const Cfg *Func) const override; | |
1237 | |
1238 private: | |
1239 InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | |
1240 : InstX86BaseMovlike<InstX86Base::Movq>(Func, Dest, Source) {} | |
1241 }; | |
1242 | |
1243 class InstX86Add : public InstX86BaseBinopGPR<InstX86Base::Add> { | |
1244 public: | |
1245 static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1246 return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | |
1247 } | |
1248 | |
1249 private: | |
1250 InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | |
1251 : InstX86BaseBinopGPR<InstX86Base::Add>(Func, Dest, Source) {} | |
1252 }; | |
1253 | |
1254 class InstX86AddRMW : public InstX86BaseBinopRMW<InstX86Base::AddRMW> { | |
1255 public: | |
1256 static InstX86AddRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1257 Operand *Src1) { | |
1258 return new (Func->allocate<InstX86AddRMW>()) | |
1259 InstX86AddRMW(Func, DestSrc0, Src1); | |
1260 } | |
1261 | |
1262 private: | |
1263 InstX86AddRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1264 : InstX86BaseBinopRMW<InstX86Base::AddRMW>(Func, DestSrc0, Src1) {} | |
1265 }; | |
1266 | |
1267 class InstX86Addps | |
1268 : public InstX86BaseBinopXmm<InstX86Base::Addps, true, | |
1269 InstX86Base::SseSuffix::Packed> { | |
1270 public: | |
1271 static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1272 return new (Func->allocate<InstX86Addps>()) | |
1273 InstX86Addps(Func, Dest, Source); | |
1274 } | |
1275 | |
1276 private: | |
1277 InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | |
1278 : InstX86BaseBinopXmm<InstX86Base::Addps, true, | |
1279 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1280 Source) {} | |
1281 }; | |
1282 | |
1283 class InstX86Adc : public InstX86BaseBinopGPR<InstX86Base::Adc> { | |
1284 public: | |
1285 static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1286 return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | |
1287 } | |
1288 | |
1289 private: | |
1290 InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | |
1291 : InstX86BaseBinopGPR<InstX86Base::Adc>(Func, Dest, Source) {} | |
1292 }; | |
1293 | |
1294 class InstX86AdcRMW : public InstX86BaseBinopRMW<InstX86Base::AdcRMW> { | |
1295 public: | |
1296 static InstX86AdcRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1297 Operand *Src1) { | |
1298 return new (Func->allocate<InstX86AdcRMW>()) | |
1299 InstX86AdcRMW(Func, DestSrc0, Src1); | |
1300 } | |
1301 | |
1302 private: | |
1303 InstX86AdcRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1304 : InstX86BaseBinopRMW<InstX86Base::AdcRMW>(Func, DestSrc0, Src1) {} | |
1305 }; | |
1306 | |
1307 class InstX86Addss | |
1308 : public InstX86BaseBinopXmm<InstX86Base::Addss, false, | |
1309 InstX86Base::SseSuffix::Scalar> { | |
1310 public: | |
1311 static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1312 return new (Func->allocate<InstX86Addss>()) | |
1313 InstX86Addss(Func, Dest, Source); | |
1314 } | |
1315 | |
1316 private: | |
1317 InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | |
1318 : InstX86BaseBinopXmm<InstX86Base::Addss, false, | |
1319 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1320 Source) {} | |
1321 }; | |
1322 | |
1323 class InstX86Padd | |
1324 : public InstX86BaseBinopXmm<InstX86Base::Padd, true, | |
1325 InstX86Base::SseSuffix::Integral> { | |
1326 public: | |
1327 static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1328 return new (Func->allocate<InstX86Padd>()) | |
1329 InstX86Padd(Func, Dest, Source); | |
1330 } | |
1331 | |
1332 private: | |
1333 InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | |
1334 : InstX86BaseBinopXmm<InstX86Base::Padd, true, | |
1335 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
1336 Source) {} | |
1337 }; | |
1338 | |
1339 class InstX86Sub : public InstX86BaseBinopGPR<InstX86Base::Sub> { | |
1340 public: | |
1341 static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1342 return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | |
1343 } | |
1344 | |
1345 private: | |
1346 InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | |
1347 : InstX86BaseBinopGPR<InstX86Base::Sub>(Func, Dest, Source) {} | |
1348 }; | |
1349 | |
1350 class InstX86SubRMW : public InstX86BaseBinopRMW<InstX86Base::SubRMW> { | |
1351 public: | |
1352 static InstX86SubRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1353 Operand *Src1) { | |
1354 return new (Func->allocate<InstX86SubRMW>()) | |
1355 InstX86SubRMW(Func, DestSrc0, Src1); | |
1356 } | |
1357 | |
1358 private: | |
1359 InstX86SubRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1360 : InstX86BaseBinopRMW<InstX86Base::SubRMW>(Func, DestSrc0, Src1) {} | |
1361 }; | |
1362 | |
1363 class InstX86Subps | |
1364 : public InstX86BaseBinopXmm<InstX86Base::Subps, true, | |
1365 InstX86Base::SseSuffix::Packed> { | |
1366 public: | |
1367 static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1368 return new (Func->allocate<InstX86Subps>()) | |
1369 InstX86Subps(Func, Dest, Source); | |
1370 } | |
1371 | |
1372 private: | |
1373 InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | |
1374 : InstX86BaseBinopXmm<InstX86Base::Subps, true, | |
1375 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1376 Source) {} | |
1377 }; | |
1378 | |
1379 class InstX86Subss | |
1380 : public InstX86BaseBinopXmm<InstX86Base::Subss, false, | |
1381 InstX86Base::SseSuffix::Scalar> { | |
1382 public: | |
1383 static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1384 return new (Func->allocate<InstX86Subss>()) | |
1385 InstX86Subss(Func, Dest, Source); | |
1386 } | |
1387 | |
1388 private: | |
1389 InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | |
1390 : InstX86BaseBinopXmm<InstX86Base::Subss, false, | |
1391 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1392 Source) {} | |
1393 }; | |
1394 | |
1395 class InstX86Sbb : public InstX86BaseBinopGPR<InstX86Base::Sbb> { | |
1396 public: | |
1397 static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1398 return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | |
1399 } | |
1400 | |
1401 private: | |
1402 InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | |
1403 : InstX86BaseBinopGPR<InstX86Base::Sbb>(Func, Dest, Source) {} | |
1404 }; | |
1405 | |
1406 class InstX86SbbRMW : public InstX86BaseBinopRMW<InstX86Base::SbbRMW> { | |
1407 public: | |
1408 static InstX86SbbRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1409 Operand *Src1) { | |
1410 return new (Func->allocate<InstX86SbbRMW>()) | |
1411 InstX86SbbRMW(Func, DestSrc0, Src1); | |
1412 } | |
1413 | |
1414 private: | |
1415 InstX86SbbRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1416 : InstX86BaseBinopRMW<InstX86Base::SbbRMW>(Func, DestSrc0, Src1) {} | |
1417 }; | |
1418 | |
1419 class InstX86Psub | |
1420 : public InstX86BaseBinopXmm<InstX86Base::Psub, true, | |
1421 InstX86Base::SseSuffix::Integral> { | |
1422 public: | |
1423 static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1424 return new (Func->allocate<InstX86Psub>()) | |
1425 InstX86Psub(Func, Dest, Source); | |
1426 } | |
1427 | |
1428 private: | |
1429 InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | |
1430 : InstX86BaseBinopXmm<InstX86Base::Psub, true, | |
1431 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
1432 Source) {} | |
1433 }; | |
1434 | |
1435 class InstX86And : public InstX86BaseBinopGPR<InstX86Base::And> { | |
1436 public: | |
1437 static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1438 return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | |
1439 } | |
1440 | |
1441 private: | |
1442 InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | |
1443 : InstX86BaseBinopGPR<InstX86Base::And>(Func, Dest, Source) {} | |
1444 }; | |
1445 | |
1446 class InstX86Andnps | |
1447 : public InstX86BaseBinopXmm<InstX86Base::Andnps, true, | |
1448 InstX86Base::SseSuffix::Packed> { | |
1449 public: | |
1450 static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1451 return new (Func->allocate<InstX86Andnps>()) | |
1452 InstX86Andnps(Func, Dest, Source); | |
1453 } | |
1454 | |
1455 private: | |
1456 InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | |
1457 : InstX86BaseBinopXmm<InstX86Base::Andnps, true, | |
1458 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1459 Source) {} | |
1460 }; | |
1461 | |
1462 class InstX86Andps | |
1463 : public InstX86BaseBinopXmm<InstX86Base::Andps, true, | |
1464 InstX86Base::SseSuffix::Packed> { | |
1465 public: | |
1466 static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1467 return new (Func->allocate<InstX86Andps>()) | |
1468 InstX86Andps(Func, Dest, Source); | |
1469 } | |
1470 | |
1471 private: | |
1472 InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | |
1473 : InstX86BaseBinopXmm<InstX86Base::Andps, true, | |
1474 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1475 Source) {} | |
1476 }; | |
1477 | |
1478 class InstX86AndRMW : public InstX86BaseBinopRMW<InstX86Base::AndRMW> { | |
1479 public: | |
1480 static InstX86AndRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1481 Operand *Src1) { | |
1482 return new (Func->allocate<InstX86AndRMW>()) | |
1483 InstX86AndRMW(Func, DestSrc0, Src1); | |
1484 } | |
1485 | |
1486 private: | |
1487 InstX86AndRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1488 : InstX86BaseBinopRMW<InstX86Base::AndRMW>(Func, DestSrc0, Src1) {} | |
1489 }; | |
1490 | |
1491 class InstX86Pand : public InstX86BaseBinopXmm<InstX86Base::Pand, false, | |
1492 InstX86Base::SseSuffix::None> { | |
1493 public: | |
1494 static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1495 return new (Func->allocate<InstX86Pand>()) | |
1496 InstX86Pand(Func, Dest, Source); | |
1497 } | |
1498 | |
1499 private: | |
1500 InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | |
1501 : InstX86BaseBinopXmm<InstX86Base::Pand, false, | |
1502 InstX86Base::SseSuffix::None>(Func, Dest, | |
1503 Source) {} | |
1504 }; | |
1505 | |
1506 class InstX86Pandn | |
1507 : public InstX86BaseBinopXmm<InstX86Base::Pandn, false, | |
1508 InstX86Base::SseSuffix::None> { | |
1509 public: | |
1510 static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1511 return new (Func->allocate<InstX86Pandn>()) | |
1512 InstX86Pandn(Func, Dest, Source); | |
1513 } | |
1514 | |
1515 private: | |
1516 InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | |
1517 : InstX86BaseBinopXmm<InstX86Base::Pandn, false, | |
1518 InstX86Base::SseSuffix::None>(Func, Dest, | |
1519 Source) {} | |
1520 }; | |
1521 | |
1522 class InstX86Maxss | |
1523 : public InstX86BaseBinopXmm<InstX86Base::Maxss, true, | |
1524 InstX86Base::SseSuffix::Scalar> { | |
1525 public: | |
1526 static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1527 return new (Func->allocate<InstX86Maxss>()) | |
1528 InstX86Maxss(Func, Dest, Source); | |
1529 } | |
1530 | |
1531 private: | |
1532 InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | |
1533 : InstX86BaseBinopXmm<InstX86Base::Maxss, true, | |
1534 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1535 Source) {} | |
1536 }; | |
1537 | |
1538 class InstX86Minss | |
1539 : public InstX86BaseBinopXmm<InstX86Base::Minss, true, | |
1540 InstX86Base::SseSuffix::Scalar> { | |
1541 public: | |
1542 static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1543 return new (Func->allocate<InstX86Minss>()) | |
1544 InstX86Minss(Func, Dest, Source); | |
1545 } | |
1546 | |
1547 private: | |
1548 InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | |
1549 : InstX86BaseBinopXmm<InstX86Base::Minss, true, | |
1550 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1551 Source) {} | |
1552 }; | |
1553 | |
1554 class InstX86Or : public InstX86BaseBinopGPR<InstX86Base::Or> { | |
1555 public: | |
1556 static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1557 return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | |
1558 } | |
1559 | |
1560 private: | |
1561 InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | |
1562 : InstX86BaseBinopGPR<InstX86Base::Or>(Func, Dest, Source) {} | |
1563 }; | |
1564 | |
1565 class InstX86Orps | |
1566 : public InstX86BaseBinopXmm<InstX86Base::Orps, true, | |
1567 InstX86Base::SseSuffix::Packed> { | |
1568 public: | |
1569 static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1570 return new (Func->allocate<InstX86Orps>()) | |
1571 InstX86Orps(Func, Dest, Source); | |
1572 } | |
1573 | |
1574 private: | |
1575 InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | |
1576 : InstX86BaseBinopXmm<InstX86Base::Orps, true, | |
1577 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1578 Source) {} | |
1579 }; | |
1580 | |
1581 class InstX86OrRMW : public InstX86BaseBinopRMW<InstX86Base::OrRMW> { | |
1582 public: | |
1583 static InstX86OrRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1584 Operand *Src1) { | |
1585 return new (Func->allocate<InstX86OrRMW>()) | |
1586 InstX86OrRMW(Func, DestSrc0, Src1); | |
1587 } | |
1588 | |
1589 private: | |
1590 InstX86OrRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1591 : InstX86BaseBinopRMW<InstX86Base::OrRMW>(Func, DestSrc0, Src1) {} | |
1592 }; | |
1593 | |
1594 class InstX86Por : public InstX86BaseBinopXmm<InstX86Base::Por, false, | |
1595 InstX86Base::SseSuffix::None> { | |
1596 public: | |
1597 static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1598 return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | |
1599 } | |
1600 | |
1601 private: | |
1602 InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | |
1603 : InstX86BaseBinopXmm<InstX86Base::Por, false, | |
1604 InstX86Base::SseSuffix::None>(Func, Dest, | |
1605 Source) {} | |
1606 }; | |
1607 | |
1608 class InstX86Xor : public InstX86BaseBinopGPR<InstX86Base::Xor> { | |
1609 public: | |
1610 static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1611 return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | |
1612 } | |
1613 | |
1614 private: | |
1615 InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | |
1616 : InstX86BaseBinopGPR<InstX86Base::Xor>(Func, Dest, Source) {} | |
1617 }; | |
1618 | |
1619 class InstX86Xorps | |
1620 : public InstX86BaseBinopXmm<InstX86Base::Xorps, true, | |
1621 InstX86Base::SseSuffix::Packed> { | |
1622 public: | |
1623 static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1624 return new (Func->allocate<InstX86Xorps>()) | |
1625 InstX86Xorps(Func, Dest, Source); | |
1626 } | |
1627 | |
1628 private: | |
1629 InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | |
1630 : InstX86BaseBinopXmm<InstX86Base::Xorps, true, | |
1631 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1632 Source) {} | |
1633 }; | |
1634 | |
1635 class InstX86XorRMW : public InstX86BaseBinopRMW<InstX86Base::XorRMW> { | |
1636 public: | |
1637 static InstX86XorRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
1638 Operand *Src1) { | |
1639 return new (Func->allocate<InstX86XorRMW>()) | |
1640 InstX86XorRMW(Func, DestSrc0, Src1); | |
1641 } | |
1642 | |
1643 private: | |
1644 InstX86XorRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
1645 : InstX86BaseBinopRMW<InstX86Base::XorRMW>(Func, DestSrc0, Src1) {} | |
1646 }; | |
1647 | |
1648 class InstX86Pxor : public InstX86BaseBinopXmm<InstX86Base::Pxor, false, | |
1649 InstX86Base::SseSuffix::None> { | |
1650 public: | |
1651 static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1652 return new (Func->allocate<InstX86Pxor>()) | |
1653 InstX86Pxor(Func, Dest, Source); | |
1654 } | |
1655 | |
1656 private: | |
1657 InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | |
1658 : InstX86BaseBinopXmm<InstX86Base::Pxor, false, | |
1659 InstX86Base::SseSuffix::None>(Func, Dest, | |
1660 Source) {} | |
1661 }; | |
1662 | |
1663 class InstX86Imul : public InstX86BaseBinopGPR<InstX86Base::Imul> { | |
1664 public: | |
1665 static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1666 return new (Func->allocate<InstX86Imul>()) | |
1667 InstX86Imul(Func, Dest, Source); | |
1668 } | |
1669 | |
1670 void emit(const Cfg *Func) const override; | |
1671 void emitIAS(const Cfg *Func) const override; | |
1672 | |
1673 private: | |
1674 InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | |
1675 : InstX86BaseBinopGPR<InstX86Base::Imul>(Func, Dest, Source) {} | |
1676 }; | |
1677 | |
1678 class InstX86ImulImm | |
1679 : public InstX86BaseThreeAddressop<InstX86Base::ImulImm> { | |
1680 public: | |
1681 static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | |
1682 Operand *Source1) { | |
1683 return new (Func->allocate<InstX86ImulImm>()) | |
1684 InstX86ImulImm(Func, Dest, Source0, Source1); | |
1685 } | |
1686 | |
1687 void emit(const Cfg *Func) const override; | |
1688 void emitIAS(const Cfg *Func) const override; | |
1689 | |
1690 private: | |
1691 InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, | |
1692 Operand *Source1) | |
1693 : InstX86BaseThreeAddressop<InstX86Base::ImulImm>(Func, Dest, Source0, | |
1694 Source1) {} | |
1695 }; | |
1696 | |
1697 class InstX86Mulps | |
1698 : public InstX86BaseBinopXmm<InstX86Base::Mulps, true, | |
1699 InstX86Base::SseSuffix::Packed> { | |
1700 public: | |
1701 static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1702 return new (Func->allocate<InstX86Mulps>()) | |
1703 InstX86Mulps(Func, Dest, Source); | |
1704 } | |
1705 | |
1706 private: | |
1707 InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | |
1708 : InstX86BaseBinopXmm<InstX86Base::Mulps, true, | |
1709 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1710 Source) {} | |
1711 }; | |
1712 | |
1713 class InstX86Mulss | |
1714 : public InstX86BaseBinopXmm<InstX86Base::Mulss, false, | |
1715 InstX86Base::SseSuffix::Scalar> { | |
1716 public: | |
1717 static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1718 return new (Func->allocate<InstX86Mulss>()) | |
1719 InstX86Mulss(Func, Dest, Source); | |
1720 } | |
1721 | |
1722 private: | |
1723 InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | |
1724 : InstX86BaseBinopXmm<InstX86Base::Mulss, false, | |
1725 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1726 Source) {} | |
1727 }; | |
1728 | |
1729 class InstX86Pmull | |
1730 : public InstX86BaseBinopXmm<InstX86Base::Pmull, true, | |
1731 InstX86Base::SseSuffix::Integral> { | |
1732 public: | |
1733 static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1734 bool TypesAreValid = | |
1735 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | |
1736 auto *Target = InstX86Base::getTarget(Func); | |
1737 bool InstructionSetIsValid = | |
1738 Dest->getType() == IceType_v8i16 || | |
1739 Target->getInstructionSet() >= Traits::SSE4_1; | |
1740 (void)TypesAreValid; | |
1741 (void)InstructionSetIsValid; | |
1742 assert(TypesAreValid); | |
1743 assert(InstructionSetIsValid); | |
1744 return new (Func->allocate<InstX86Pmull>()) | |
1745 InstX86Pmull(Func, Dest, Source); | |
1746 } | |
1747 | |
1748 private: | |
1749 InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | |
1750 : InstX86BaseBinopXmm<InstX86Base::Pmull, true, | |
1751 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
1752 Source) {} | |
1753 }; | |
1754 | |
1755 class InstX86Pmuludq | |
1756 : public InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | |
1757 InstX86Base::SseSuffix::None> { | |
1758 public: | |
1759 static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1760 assert(Dest->getType() == IceType_v4i32 && | |
1761 Source->getType() == IceType_v4i32); | |
1762 return new (Func->allocate<InstX86Pmuludq>()) | |
1763 InstX86Pmuludq(Func, Dest, Source); | |
1764 } | |
1765 | |
1766 private: | |
1767 InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | |
1768 : InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | |
1769 InstX86Base::SseSuffix::None>(Func, Dest, | |
1770 Source) {} | |
1771 }; | |
1772 | |
1773 class InstX86Divps | |
1774 : public InstX86BaseBinopXmm<InstX86Base::Divps, true, | |
1775 InstX86Base::SseSuffix::Packed> { | |
1776 public: | |
1777 static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1778 return new (Func->allocate<InstX86Divps>()) | |
1779 InstX86Divps(Func, Dest, Source); | |
1780 } | |
1781 | |
1782 private: | |
1783 InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | |
1784 : InstX86BaseBinopXmm<InstX86Base::Divps, true, | |
1785 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
1786 Source) {} | |
1787 }; | |
1788 | |
1789 class InstX86Divss | |
1790 : public InstX86BaseBinopXmm<InstX86Base::Divss, false, | |
1791 InstX86Base::SseSuffix::Scalar> { | |
1792 public: | |
1793 static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1794 return new (Func->allocate<InstX86Divss>()) | |
1795 InstX86Divss(Func, Dest, Source); | |
1796 } | |
1797 | |
1798 private: | |
1799 InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | |
1800 : InstX86BaseBinopXmm<InstX86Base::Divss, false, | |
1801 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
1802 Source) {} | |
1803 }; | |
1804 | |
1805 class InstX86Rol : public InstX86BaseBinopGPRShift<InstX86Base::Rol> { | |
1806 public: | |
1807 static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1808 return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | |
1809 } | |
1810 | |
1811 private: | |
1812 InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | |
1813 : InstX86BaseBinopGPRShift<InstX86Base::Rol>(Func, Dest, Source) {} | |
1814 }; | |
1815 | |
1816 class InstX86Shl : public InstX86BaseBinopGPRShift<InstX86Base::Shl> { | |
1817 public: | |
1818 static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1819 return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | |
1820 } | |
1821 | |
1822 private: | |
1823 InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | |
1824 : InstX86BaseBinopGPRShift<InstX86Base::Shl>(Func, Dest, Source) {} | |
1825 }; | |
1826 | |
1827 class InstX86Psll : public InstX86BaseBinopXmmShift<InstX86Base::Psll> { | |
1828 public: | |
1829 static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1830 assert( | |
1831 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | |
1832 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
1833 return new (Func->allocate<InstX86Psll>()) | |
1834 InstX86Psll(Func, Dest, Source); | |
1835 } | |
1836 | |
1837 private: | |
1838 InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | |
1839 : InstX86BaseBinopXmmShift<InstX86Base::Psll>(Func, Dest, Source) {} | |
1840 }; | |
1841 | |
1842 class InstX86Psrl : public InstX86BaseBinopXmmShift<InstX86Base::Psrl, true> { | |
1843 public: | |
1844 static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1845 return new (Func->allocate<InstX86Psrl>()) | |
1846 InstX86Psrl(Func, Dest, Source); | |
1847 } | |
1848 | |
1849 private: | |
1850 InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | |
1851 : InstX86BaseBinopXmmShift<InstX86Base::Psrl, true>(Func, Dest, | |
1852 Source) {} | |
1853 }; | |
1854 | |
1855 class InstX86Shr : public InstX86BaseBinopGPRShift<InstX86Base::Shr> { | |
1856 public: | |
1857 static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1858 return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | |
1859 } | |
1860 | |
1861 private: | |
1862 InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | |
1863 : InstX86BaseBinopGPRShift<InstX86Base::Shr>(Func, Dest, Source) {} | |
1864 }; | |
1865 | |
1866 class InstX86Sar : public InstX86BaseBinopGPRShift<InstX86Base::Sar> { | |
1867 public: | |
1868 static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1869 return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | |
1870 } | |
1871 | |
1872 private: | |
1873 InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | |
1874 : InstX86BaseBinopGPRShift<InstX86Base::Sar>(Func, Dest, Source) {} | |
1875 }; | |
1876 | |
1877 class InstX86Psra : public InstX86BaseBinopXmmShift<InstX86Base::Psra> { | |
1878 public: | |
1879 static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1880 assert( | |
1881 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | |
1882 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
1883 return new (Func->allocate<InstX86Psra>()) | |
1884 InstX86Psra(Func, Dest, Source); | |
1885 } | |
1886 | |
1887 private: | |
1888 InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | |
1889 : InstX86BaseBinopXmmShift<InstX86Base::Psra>(Func, Dest, Source) {} | |
1890 }; | |
1891 | |
1892 class InstX86Pcmpeq | |
1893 : public InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | |
1894 InstX86Base::SseSuffix::Integral> { | |
1895 public: | |
1896 static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1897 return new (Func->allocate<InstX86Pcmpeq>()) | |
1898 InstX86Pcmpeq(Func, Dest, Source); | |
1899 } | |
1900 | |
1901 private: | |
1902 InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | |
1903 : InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | |
1904 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
1905 Source) {} | |
1906 }; | |
1907 | |
1908 class InstX86Pcmpgt | |
1909 : public InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | |
1910 InstX86Base::SseSuffix::Integral> { | |
1911 public: | |
1912 static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1913 return new (Func->allocate<InstX86Pcmpgt>()) | |
1914 InstX86Pcmpgt(Func, Dest, Source); | |
1915 } | |
1916 | |
1917 private: | |
1918 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | |
1919 : InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | |
1920 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
1921 Source) {} | |
1922 }; | |
1923 | |
1924 /// movss is only a binary operation when the source and dest operands are | |
1925 /// both registers (the high bits of dest are left untouched). In other cases, | |
1926 /// it behaves like a copy (mov-like) operation (and the high bits of dest are | |
1927 /// cleared). InstX86Movss will assert that both its source and dest operands | |
1928 /// are registers, so the lowering code should use _mov instead of _movss in | |
1929 /// cases where a copy operation is intended. | |
1930 class InstX86MovssRegs | |
1931 : public InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | |
1932 InstX86Base::SseSuffix::None> { | |
1933 public: | |
1934 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, | |
1935 Operand *Source) { | |
1936 return new (Func->allocate<InstX86MovssRegs>()) | |
1937 InstX86MovssRegs(Func, Dest, Source); | |
1938 } | |
1939 | |
1940 void emitIAS(const Cfg *Func) const override; | |
1941 | |
1942 private: | |
1943 InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | |
1944 : InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | |
1945 InstX86Base::SseSuffix::None>(Func, Dest, | |
1946 Source) {} | |
1947 }; | |
1948 | |
1949 class InstX86Idiv : public InstX86BaseTernop<InstX86Base::Idiv> { | |
1950 public: | |
1951 static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
1952 Operand *Source2) { | |
1953 return new (Func->allocate<InstX86Idiv>()) | |
1954 InstX86Idiv(Func, Dest, Source1, Source2); | |
1955 } | |
1956 | |
1957 void emit(const Cfg *Func) const override; | |
1958 void emitIAS(const Cfg *Func) const override; | |
1959 | |
1960 private: | |
1961 InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
1962 : InstX86BaseTernop<InstX86Base::Idiv>(Func, Dest, Source1, Source2) {} | |
1963 }; | |
1964 | |
1965 class InstX86Div : public InstX86BaseTernop<InstX86Base::Div> { | |
1966 public: | |
1967 static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
1968 Operand *Source2) { | |
1969 return new (Func->allocate<InstX86Div>()) | |
1970 InstX86Div(Func, Dest, Source1, Source2); | |
1971 } | |
1972 | |
1973 void emit(const Cfg *Func) const override; | |
1974 void emitIAS(const Cfg *Func) const override; | |
1975 | |
1976 private: | |
1977 InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
1978 : InstX86BaseTernop<InstX86Base::Div>(Func, Dest, Source1, Source2) {} | |
1979 }; | |
1980 | |
1981 class InstX86Insertps : public InstX86BaseTernop<InstX86Base::Insertps> { | |
1982 public: | |
1983 static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
1984 Operand *Source2) { | |
1985 return new (Func->allocate<InstX86Insertps>()) | |
1986 InstX86Insertps(Func, Dest, Source1, Source2); | |
1987 } | |
1988 | |
1989 void emitIAS(const Cfg *Func) const override; | |
1990 | |
1991 private: | |
1992 InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, | |
919 Operand *Source2) | 1993 Operand *Source2) |
920 : InstX86Base<Machine>(Func, K, 3, Dest) { | 1994 : InstX86BaseTernop<InstX86Base::Insertps>(Func, Dest, Source1, |
921 this->addSource(Dest); | 1995 Source2) {} |
922 this->addSource(Source1); | 1996 }; |
923 this->addSource(Source2); | 1997 |
924 } | 1998 class InstX86Pinsr : public InstX86BaseTernop<InstX86Base::Pinsr> { |
925 | 1999 public: |
926 static const char *Opcode; | 2000 static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, |
927 }; | 2001 Operand *Source2) { |
928 | 2002 // pinsrb and pinsrd are SSE4.1 instructions. |
929 // Instructions of the form x := y op z | 2003 assert( |
930 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 2004 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || |
931 class InstX86BaseThreeAddressop : public InstX86Base<Machine> { | 2005 InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1); |
932 InstX86BaseThreeAddressop() = delete; | 2006 return new (Func->allocate<InstX86Pinsr>()) |
933 InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; | 2007 InstX86Pinsr(Func, Dest, Source1, Source2); |
934 InstX86BaseThreeAddressop & | 2008 } |
935 operator=(const InstX86BaseThreeAddressop &) = delete; | 2009 |
936 | 2010 void emit(const Cfg *Func) const override; |
937 public: | 2011 void emitIAS(const Cfg *Func) const override; |
938 using Base = InstX86BaseThreeAddressop<Machine, K>; | 2012 |
939 | 2013 private: |
940 void emit(const Cfg *Func) const override { | 2014 InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
941 if (!BuildDefs::dump()) | 2015 : InstX86BaseTernop<InstX86Base::Pinsr>(Func, Dest, Source1, Source2) {} |
942 return; | 2016 }; |
943 Ostream &Str = Func->getContext()->getStrEmit(); | 2017 |
944 assert(this->getSrcSize() == 2); | 2018 class InstX86Shufps : public InstX86BaseTernop<InstX86Base::Shufps> { |
945 Str << "\t" << Opcode << "\t"; | 2019 public: |
946 this->getSrc(1)->emit(Func); | 2020 static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, |
947 Str << ", "; | 2021 Operand *Source2) { |
948 this->getSrc(0)->emit(Func); | 2022 return new (Func->allocate<InstX86Shufps>()) |
949 Str << ", "; | 2023 InstX86Shufps(Func, Dest, Source1, Source2); |
950 this->getDest()->emit(Func); | 2024 } |
951 } | 2025 |
952 void dump(const Cfg *Func) const override { | 2026 void emitIAS(const Cfg *Func) const override; |
953 if (!BuildDefs::dump()) | 2027 |
954 return; | 2028 private: |
955 Ostream &Str = Func->getContext()->getStrDump(); | 2029 InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
956 this->dumpDest(Func); | 2030 : InstX86BaseTernop<InstX86Base::Shufps>(Func, Dest, Source1, Source2) { |
957 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 2031 } |
958 this->dumpSources(Func); | 2032 }; |
959 } | 2033 |
960 static bool classof(const Inst *Inst) { | 2034 class InstX86Blendvps : public InstX86BaseTernop<InstX86Base::Blendvps> { |
961 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 2035 public: |
962 } | 2036 static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, |
963 | 2037 Operand *Source2) { |
964 protected: | 2038 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= |
965 InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, | 2039 Traits::SSE4_1); |
966 Operand *Source1) | 2040 return new (Func->allocate<InstX86Blendvps>()) |
967 : InstX86Base<Machine>(Func, K, 2, Dest) { | 2041 InstX86Blendvps(Func, Dest, Source1, Source2); |
968 this->addSource(Source0); | 2042 } |
969 this->addSource(Source1); | 2043 |
970 } | 2044 void emit(const Cfg *Func) const override; |
971 | 2045 void emitIAS(const Cfg *Fund) const override; |
972 static const char *Opcode; | 2046 |
973 }; | 2047 private: |
974 | 2048 InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, |
975 /// Base class for assignment instructions | 2049 Operand *Source2) |
976 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 2050 : InstX86BaseTernop<InstX86Base::Blendvps>(Func, Dest, Source1, |
977 class InstX86BaseMovlike : public InstX86Base<Machine> { | 2051 Source2) {} |
978 InstX86BaseMovlike() = delete; | 2052 }; |
979 InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; | 2053 |
980 InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; | 2054 class InstX86Pblendvb : public InstX86BaseTernop<InstX86Base::Pblendvb> { |
981 | 2055 public: |
982 public: | 2056 static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, |
983 using Base = InstX86BaseMovlike<Machine, K>; | 2057 Operand *Source2) { |
984 | 2058 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= |
985 bool isRedundantAssign() const override { | 2059 Traits::SSE4_1); |
986 if (const auto *SrcVar = llvm::dyn_cast<const Variable>(this->getSrc(0))) { | 2060 return new (Func->allocate<InstX86Pblendvb>()) |
987 if (SrcVar->hasReg() && this->Dest->hasReg()) { | 2061 InstX86Pblendvb(Func, Dest, Source1, Source2); |
988 // An assignment between physical registers is considered redundant if | 2062 } |
989 // they have the same base register and the same encoding. E.g.: | 2063 |
990 // mov cl, ecx ==> redundant | 2064 void emit(const Cfg *Func) const override; |
991 // mov ch, ecx ==> not redundant due to different encodings | 2065 void emitIAS(const Cfg *Func) const override; |
992 // mov ch, ebp ==> not redundant due to different base registers | 2066 |
993 // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting | 2067 private: |
994 // is handled by Inst86Zext. | 2068 InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, |
995 const int32_t SrcReg = SrcVar->getRegNum(); | 2069 Operand *Source2) |
996 const int32_t DestReg = this->Dest->getRegNum(); | 2070 : InstX86BaseTernop<InstX86Base::Pblendvb>(Func, Dest, Source1, |
997 return (InstX86Base<Machine>::Traits::getEncoding(SrcReg) == | 2071 Source2) {} |
998 InstX86Base<Machine>::Traits::getEncoding(DestReg)) && | 2072 }; |
999 (InstX86Base<Machine>::Traits::getBaseReg(SrcReg) == | 2073 |
1000 InstX86Base<Machine>::Traits::getBaseReg(DestReg)); | 2074 class InstX86Pextr : public InstX86BaseThreeAddressop<InstX86Base::Pextr> { |
1001 } | 2075 public: |
1002 } | 2076 static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, |
1003 return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | |
1004 } | |
1005 bool isVarAssign() const override { | |
1006 return llvm::isa<Variable>(this->getSrc(0)); | |
1007 } | |
1008 void dump(const Cfg *Func) const override { | |
1009 if (!BuildDefs::dump()) | |
1010 return; | |
1011 Ostream &Str = Func->getContext()->getStrDump(); | |
1012 Str << Opcode << "." << this->getDest()->getType() << " "; | |
1013 this->dumpDest(Func); | |
1014 Str << ", "; | |
1015 this->dumpSources(Func); | |
1016 } | |
1017 static bool classof(const Inst *Inst) { | |
1018 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
1019 } | |
1020 | |
1021 protected: | |
1022 InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | |
1023 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
1024 this->addSource(Source); | |
1025 // For an integer assignment, make sure it's either a same-type assignment | |
1026 // or a truncation. | |
1027 assert(!isScalarIntegerType(Dest->getType()) || | |
1028 (typeWidthInBytes(Dest->getType()) <= | |
1029 typeWidthInBytes(Source->getType()))); | |
1030 } | |
1031 | |
1032 static const char *Opcode; | |
1033 }; | |
1034 | |
1035 template <class Machine> | |
1036 class InstX86Bswap | |
1037 : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap> { | |
1038 public: | |
1039 static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | |
1040 return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | |
1041 } | |
1042 | |
1043 private: | |
1044 InstX86Bswap(Cfg *Func, Operand *SrcDest) | |
1045 : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap>(Func, | |
1046 SrcDest) { | |
1047 } | |
1048 }; | |
1049 | |
1050 template <class Machine> | |
1051 class InstX86Neg | |
1052 : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg> { | |
1053 public: | |
1054 static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | |
1055 return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | |
1056 } | |
1057 | |
1058 private: | |
1059 InstX86Neg(Cfg *Func, Operand *SrcDest) | |
1060 : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg>(Func, | |
1061 SrcDest) {} | |
1062 }; | |
1063 | |
1064 template <class Machine> | |
1065 class InstX86Bsf | |
1066 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf> { | |
1067 public: | |
1068 static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1069 return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | |
1070 } | |
1071 | |
1072 private: | |
1073 InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | |
1074 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf>(Func, Dest, | |
1075 Src) {} | |
1076 }; | |
1077 | |
1078 template <class Machine> | |
1079 class InstX86Bsr | |
1080 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr> { | |
1081 public: | |
1082 static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1083 return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | |
1084 } | |
1085 | |
1086 private: | |
1087 InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | |
1088 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr>(Func, Dest, | |
1089 Src) {} | |
1090 }; | |
1091 | |
1092 template <class Machine> | |
1093 class InstX86Lea | |
1094 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea> { | |
1095 public: | |
1096 static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1097 return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | |
1098 } | |
1099 | |
1100 void emit(const Cfg *Func) const override; | |
1101 | |
1102 private: | |
1103 InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | |
1104 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea>(Func, Dest, | |
1105 Src) {} | |
1106 }; | |
1107 | |
1108 // Cbwdq instruction - wrapper for cbw, cwd, and cdq | |
1109 template <class Machine> | |
1110 class InstX86Cbwdq | |
1111 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq> { | |
1112 public: | |
1113 static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1114 return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | |
1115 } | |
1116 | |
1117 void emit(const Cfg *Func) const override; | |
1118 void emitIAS(const Cfg *Func) const override; | |
1119 | |
1120 private: | |
1121 InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | |
1122 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq>(Func, Dest, | |
1123 Src) {} | |
1124 }; | |
1125 | |
1126 template <class Machine> | |
1127 class InstX86Movsx | |
1128 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx> { | |
1129 public: | |
1130 static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1131 assert(typeWidthInBytes(Dest->getType()) > | |
1132 typeWidthInBytes(Src->getType())); | |
1133 return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | |
1134 } | |
1135 | |
1136 void emitIAS(const Cfg *Func) const override; | |
1137 | |
1138 private: | |
1139 InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | |
1140 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx>(Func, Dest, | |
1141 Src) {} | |
1142 }; | |
1143 | |
1144 template <class Machine> | |
1145 class InstX86Movzx | |
1146 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx> { | |
1147 public: | |
1148 static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1149 assert(typeWidthInBytes(Dest->getType()) > | |
1150 typeWidthInBytes(Src->getType())); | |
1151 return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | |
1152 } | |
1153 | |
1154 void emit(const Cfg *Func) const override; | |
1155 | |
1156 void emitIAS(const Cfg *Func) const override; | |
1157 | |
1158 private: | |
1159 InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | |
1160 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>(Func, Dest, | |
1161 Src) {} | |
1162 }; | |
1163 | |
1164 template <class Machine> | |
1165 class InstX86Movd | |
1166 : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd> { | |
1167 public: | |
1168 static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1169 return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | |
1170 } | |
1171 | |
1172 void emit(const Cfg *Func) const override; | |
1173 | |
1174 void emitIAS(const Cfg *Func) const override; | |
1175 | |
1176 private: | |
1177 InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | |
1178 : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>(Func, Dest, | |
1179 Src) {} | |
1180 }; | |
1181 | |
1182 template <class Machine> | |
1183 class InstX86Sqrtss | |
1184 : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss> { | |
1185 public: | |
1186 static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
1187 return new (Func->allocate<InstX86Sqrtss>()) InstX86Sqrtss(Func, Dest, Src); | |
1188 } | |
1189 | |
1190 virtual void emit(const Cfg *Func) const override; | |
1191 | |
1192 private: | |
1193 InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | |
1194 : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss>(Func, Dest, | |
1195 Src) {} | |
1196 }; | |
1197 | |
1198 /// Move/assignment instruction - wrapper for mov/movss/movsd. | |
1199 template <class Machine> | |
1200 class InstX86Mov | |
1201 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov> { | |
1202 public: | |
1203 static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1204 assert(!isScalarIntegerType(Dest->getType()) || | |
1205 (typeWidthInBytes(Dest->getType()) <= | |
1206 typeWidthInBytes(Source->getType()))); | |
1207 return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | |
1208 } | |
1209 | |
1210 void emit(const Cfg *Func) const override; | |
1211 void emitIAS(const Cfg *Func) const override; | |
1212 | |
1213 private: | |
1214 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
1215 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, | |
1216 Source) {} | |
1217 }; | |
1218 | |
1219 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | |
1220 /// registers. | |
1221 template <class Machine> | |
1222 class InstX86Movp | |
1223 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { | |
1224 public: | |
1225 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1226 return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); | |
1227 } | |
1228 | |
1229 void emit(const Cfg *Func) const override; | |
1230 void emitIAS(const Cfg *Func) const override; | |
1231 | |
1232 private: | |
1233 InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | |
1234 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp>(Func, Dest, | |
1235 Source) {} | |
1236 }; | |
1237 | |
1238 /// Movq - copy between XMM registers, or mem64 and XMM registers. | |
1239 template <class Machine> | |
1240 class InstX86Movq | |
1241 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq> { | |
1242 public: | |
1243 static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1244 return new (Func->allocate<InstX86Movq>()) InstX86Movq(Func, Dest, Source); | |
1245 } | |
1246 | |
1247 void emit(const Cfg *Func) const override; | |
1248 void emitIAS(const Cfg *Func) const override; | |
1249 | |
1250 private: | |
1251 InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | |
1252 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq>(Func, Dest, | |
1253 Source) {} | |
1254 }; | |
1255 | |
1256 template <class Machine> | |
1257 class InstX86Add | |
1258 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add> { | |
1259 public: | |
1260 static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1261 return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | |
1262 } | |
1263 | |
1264 private: | |
1265 InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | |
1266 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add>(Func, Dest, | |
1267 Source) {} | |
1268 }; | |
1269 | |
1270 template <class Machine> | |
1271 class InstX86AddRMW | |
1272 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW> { | |
1273 public: | |
1274 static InstX86AddRMW * | |
1275 create(Cfg *Func, | |
1276 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1277 Operand *Src1) { | |
1278 return new (Func->allocate<InstX86AddRMW>()) | |
1279 InstX86AddRMW(Func, DestSrc0, Src1); | |
1280 } | |
1281 | |
1282 private: | |
1283 InstX86AddRMW(Cfg *Func, | |
1284 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1285 Operand *Src1) | |
1286 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW>( | |
1287 Func, DestSrc0, Src1) {} | |
1288 }; | |
1289 | |
1290 template <class Machine> | |
1291 class InstX86Addps | |
1292 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | |
1293 InstX86Base<Machine>::SseSuffix::Packed> { | |
1294 public: | |
1295 static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1296 return new (Func->allocate<InstX86Addps>()) | |
1297 InstX86Addps(Func, Dest, Source); | |
1298 } | |
1299 | |
1300 private: | |
1301 InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | |
1302 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | |
1303 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1304 Source) {} | |
1305 }; | |
1306 | |
1307 template <class Machine> | |
1308 class InstX86Adc | |
1309 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc> { | |
1310 public: | |
1311 static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1312 return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | |
1313 } | |
1314 | |
1315 private: | |
1316 InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | |
1317 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc>(Func, Dest, | |
1318 Source) {} | |
1319 }; | |
1320 | |
1321 template <class Machine> | |
1322 class InstX86AdcRMW | |
1323 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW> { | |
1324 public: | |
1325 static InstX86AdcRMW * | |
1326 create(Cfg *Func, | |
1327 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1328 Operand *Src1) { | |
1329 return new (Func->allocate<InstX86AdcRMW>()) | |
1330 InstX86AdcRMW(Func, DestSrc0, Src1); | |
1331 } | |
1332 | |
1333 private: | |
1334 InstX86AdcRMW(Cfg *Func, | |
1335 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1336 Operand *Src1) | |
1337 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW>( | |
1338 Func, DestSrc0, Src1) {} | |
1339 }; | |
1340 | |
1341 template <class Machine> | |
1342 class InstX86Addss | |
1343 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | |
1344 InstX86Base<Machine>::SseSuffix::Scalar> { | |
1345 public: | |
1346 static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1347 return new (Func->allocate<InstX86Addss>()) | |
1348 InstX86Addss(Func, Dest, Source); | |
1349 } | |
1350 | |
1351 private: | |
1352 InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | |
1353 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | |
1354 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
1355 Source) {} | |
1356 }; | |
1357 | |
1358 template <class Machine> | |
1359 class InstX86Padd | |
1360 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | |
1361 InstX86Base<Machine>::SseSuffix::Integral> { | |
1362 public: | |
1363 static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1364 return new (Func->allocate<InstX86Padd>()) InstX86Padd(Func, Dest, Source); | |
1365 } | |
1366 | |
1367 private: | |
1368 InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | |
1369 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | |
1370 InstX86Base<Machine>::SseSuffix::Integral>( | |
1371 Func, Dest, Source) {} | |
1372 }; | |
1373 | |
1374 template <class Machine> | |
1375 class InstX86Sub | |
1376 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub> { | |
1377 public: | |
1378 static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1379 return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | |
1380 } | |
1381 | |
1382 private: | |
1383 InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | |
1384 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub>(Func, Dest, | |
1385 Source) {} | |
1386 }; | |
1387 | |
1388 template <class Machine> | |
1389 class InstX86SubRMW | |
1390 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW> { | |
1391 public: | |
1392 static InstX86SubRMW * | |
1393 create(Cfg *Func, | |
1394 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1395 Operand *Src1) { | |
1396 return new (Func->allocate<InstX86SubRMW>()) | |
1397 InstX86SubRMW(Func, DestSrc0, Src1); | |
1398 } | |
1399 | |
1400 private: | |
1401 InstX86SubRMW(Cfg *Func, | |
1402 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1403 Operand *Src1) | |
1404 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW>( | |
1405 Func, DestSrc0, Src1) {} | |
1406 }; | |
1407 | |
1408 template <class Machine> | |
1409 class InstX86Subps | |
1410 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | |
1411 InstX86Base<Machine>::SseSuffix::Packed> { | |
1412 public: | |
1413 static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1414 return new (Func->allocate<InstX86Subps>()) | |
1415 InstX86Subps(Func, Dest, Source); | |
1416 } | |
1417 | |
1418 private: | |
1419 InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | |
1420 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | |
1421 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1422 Source) {} | |
1423 }; | |
1424 | |
1425 template <class Machine> | |
1426 class InstX86Subss | |
1427 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | |
1428 InstX86Base<Machine>::SseSuffix::Scalar> { | |
1429 public: | |
1430 static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1431 return new (Func->allocate<InstX86Subss>()) | |
1432 InstX86Subss(Func, Dest, Source); | |
1433 } | |
1434 | |
1435 private: | |
1436 InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | |
1437 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | |
1438 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
1439 Source) {} | |
1440 }; | |
1441 | |
1442 template <class Machine> | |
1443 class InstX86Sbb | |
1444 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb> { | |
1445 public: | |
1446 static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1447 return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | |
1448 } | |
1449 | |
1450 private: | |
1451 InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | |
1452 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb>(Func, Dest, | |
1453 Source) {} | |
1454 }; | |
1455 | |
1456 template <class Machine> | |
1457 class InstX86SbbRMW | |
1458 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW> { | |
1459 public: | |
1460 static InstX86SbbRMW * | |
1461 create(Cfg *Func, | |
1462 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1463 Operand *Src1) { | |
1464 return new (Func->allocate<InstX86SbbRMW>()) | |
1465 InstX86SbbRMW(Func, DestSrc0, Src1); | |
1466 } | |
1467 | |
1468 private: | |
1469 InstX86SbbRMW(Cfg *Func, | |
1470 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1471 Operand *Src1) | |
1472 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW>( | |
1473 Func, DestSrc0, Src1) {} | |
1474 }; | |
1475 | |
1476 template <class Machine> | |
1477 class InstX86Psub | |
1478 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | |
1479 InstX86Base<Machine>::SseSuffix::Integral> { | |
1480 public: | |
1481 static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1482 return new (Func->allocate<InstX86Psub>()) InstX86Psub(Func, Dest, Source); | |
1483 } | |
1484 | |
1485 private: | |
1486 InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | |
1487 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | |
1488 InstX86Base<Machine>::SseSuffix::Integral>( | |
1489 Func, Dest, Source) {} | |
1490 }; | |
1491 | |
1492 template <class Machine> | |
1493 class InstX86And | |
1494 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And> { | |
1495 public: | |
1496 static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1497 return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | |
1498 } | |
1499 | |
1500 private: | |
1501 InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | |
1502 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And>(Func, Dest, | |
1503 Source) {} | |
1504 }; | |
1505 | |
1506 template <class Machine> | |
1507 class InstX86Andnps | |
1508 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | |
1509 InstX86Base<Machine>::SseSuffix::Packed> { | |
1510 public: | |
1511 static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1512 return new (Func->allocate<InstX86Andnps>()) | |
1513 InstX86Andnps(Func, Dest, Source); | |
1514 } | |
1515 | |
1516 private: | |
1517 InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | |
1518 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | |
1519 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1520 Source) {} | |
1521 }; | |
1522 | |
1523 template <class Machine> | |
1524 class InstX86Andps | |
1525 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | |
1526 InstX86Base<Machine>::SseSuffix::Packed> { | |
1527 public: | |
1528 static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1529 return new (Func->allocate<InstX86Andps>()) | |
1530 InstX86Andps(Func, Dest, Source); | |
1531 } | |
1532 | |
1533 private: | |
1534 InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | |
1535 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | |
1536 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1537 Source) {} | |
1538 }; | |
1539 | |
1540 template <class Machine> | |
1541 class InstX86AndRMW | |
1542 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW> { | |
1543 public: | |
1544 static InstX86AndRMW * | |
1545 create(Cfg *Func, | |
1546 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1547 Operand *Src1) { | |
1548 return new (Func->allocate<InstX86AndRMW>()) | |
1549 InstX86AndRMW(Func, DestSrc0, Src1); | |
1550 } | |
1551 | |
1552 private: | |
1553 InstX86AndRMW(Cfg *Func, | |
1554 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1555 Operand *Src1) | |
1556 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW>( | |
1557 Func, DestSrc0, Src1) {} | |
1558 }; | |
1559 | |
1560 template <class Machine> | |
1561 class InstX86Pand | |
1562 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | |
1563 InstX86Base<Machine>::SseSuffix::None> { | |
1564 public: | |
1565 static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1566 return new (Func->allocate<InstX86Pand>()) InstX86Pand(Func, Dest, Source); | |
1567 } | |
1568 | |
1569 private: | |
1570 InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | |
1571 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | |
1572 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
1573 Source) {} | |
1574 }; | |
1575 | |
1576 template <class Machine> | |
1577 class InstX86Pandn | |
1578 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | |
1579 InstX86Base<Machine>::SseSuffix::None> { | |
1580 public: | |
1581 static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1582 return new (Func->allocate<InstX86Pandn>()) | |
1583 InstX86Pandn(Func, Dest, Source); | |
1584 } | |
1585 | |
1586 private: | |
1587 InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | |
1588 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | |
1589 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
1590 Source) {} | |
1591 }; | |
1592 | |
1593 template <class Machine> | |
1594 class InstX86Maxss | |
1595 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | |
1596 InstX86Base<Machine>::SseSuffix::Scalar> { | |
1597 public: | |
1598 static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1599 return new (Func->allocate<InstX86Maxss>()) | |
1600 InstX86Maxss(Func, Dest, Source); | |
1601 } | |
1602 | |
1603 private: | |
1604 InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | |
1605 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | |
1606 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
1607 Source) {} | |
1608 }; | |
1609 | |
1610 template <class Machine> | |
1611 class InstX86Minss | |
1612 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | |
1613 InstX86Base<Machine>::SseSuffix::Scalar> { | |
1614 public: | |
1615 static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1616 return new (Func->allocate<InstX86Minss>()) | |
1617 InstX86Minss(Func, Dest, Source); | |
1618 } | |
1619 | |
1620 private: | |
1621 InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | |
1622 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | |
1623 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
1624 Source) {} | |
1625 }; | |
1626 | |
1627 template <class Machine> | |
1628 class InstX86Or | |
1629 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or> { | |
1630 public: | |
1631 static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1632 return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | |
1633 } | |
1634 | |
1635 private: | |
1636 InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | |
1637 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or>(Func, Dest, | |
1638 Source) {} | |
1639 }; | |
1640 | |
1641 template <class Machine> | |
1642 class InstX86Orps | |
1643 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | |
1644 InstX86Base<Machine>::SseSuffix::Packed> { | |
1645 public: | |
1646 static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1647 return new (Func->allocate<InstX86Orps>()) InstX86Orps(Func, Dest, Source); | |
1648 } | |
1649 | |
1650 private: | |
1651 InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | |
1652 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | |
1653 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1654 Source) {} | |
1655 }; | |
1656 | |
1657 template <class Machine> | |
1658 class InstX86OrRMW | |
1659 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW> { | |
1660 public: | |
1661 static InstX86OrRMW * | |
1662 create(Cfg *Func, | |
1663 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1664 Operand *Src1) { | |
1665 return new (Func->allocate<InstX86OrRMW>()) | |
1666 InstX86OrRMW(Func, DestSrc0, Src1); | |
1667 } | |
1668 | |
1669 private: | |
1670 InstX86OrRMW(Cfg *Func, | |
1671 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1672 Operand *Src1) | |
1673 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW>( | |
1674 Func, DestSrc0, Src1) {} | |
1675 }; | |
1676 | |
1677 template <class Machine> | |
1678 class InstX86Por | |
1679 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | |
1680 InstX86Base<Machine>::SseSuffix::None> { | |
1681 public: | |
1682 static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1683 return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | |
1684 } | |
1685 | |
1686 private: | |
1687 InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | |
1688 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | |
1689 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
1690 Source) {} | |
1691 }; | |
1692 | |
1693 template <class Machine> | |
1694 class InstX86Xor | |
1695 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor> { | |
1696 public: | |
1697 static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1698 return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | |
1699 } | |
1700 | |
1701 private: | |
1702 InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | |
1703 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor>(Func, Dest, | |
1704 Source) {} | |
1705 }; | |
1706 | |
1707 template <class Machine> | |
1708 class InstX86Xorps | |
1709 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | |
1710 InstX86Base<Machine>::SseSuffix::Packed> { | |
1711 public: | |
1712 static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1713 return new (Func->allocate<InstX86Xorps>()) | |
1714 InstX86Xorps(Func, Dest, Source); | |
1715 } | |
1716 | |
1717 private: | |
1718 InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | |
1719 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | |
1720 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1721 Source) {} | |
1722 }; | |
1723 | |
1724 template <class Machine> | |
1725 class InstX86XorRMW | |
1726 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW> { | |
1727 public: | |
1728 static InstX86XorRMW * | |
1729 create(Cfg *Func, | |
1730 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1731 Operand *Src1) { | |
1732 return new (Func->allocate<InstX86XorRMW>()) | |
1733 InstX86XorRMW(Func, DestSrc0, Src1); | |
1734 } | |
1735 | |
1736 private: | |
1737 InstX86XorRMW(Cfg *Func, | |
1738 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
1739 Operand *Src1) | |
1740 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW>( | |
1741 Func, DestSrc0, Src1) {} | |
1742 }; | |
1743 | |
1744 template <class Machine> | |
1745 class InstX86Pxor | |
1746 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | |
1747 InstX86Base<Machine>::SseSuffix::None> { | |
1748 public: | |
1749 static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1750 return new (Func->allocate<InstX86Pxor>()) InstX86Pxor(Func, Dest, Source); | |
1751 } | |
1752 | |
1753 private: | |
1754 InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | |
1755 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | |
1756 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
1757 Source) {} | |
1758 }; | |
1759 | |
1760 template <class Machine> | |
1761 class InstX86Imul | |
1762 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul> { | |
1763 public: | |
1764 static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1765 return new (Func->allocate<InstX86Imul>()) InstX86Imul(Func, Dest, Source); | |
1766 } | |
1767 | |
1768 void emit(const Cfg *Func) const override; | |
1769 void emitIAS(const Cfg *Func) const override; | |
1770 | |
1771 private: | |
1772 InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | |
1773 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul>(Func, Dest, | |
1774 Source) {} | |
1775 }; | |
1776 | |
1777 template <class Machine> | |
1778 class InstX86ImulImm | |
1779 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm> { | |
1780 public: | |
1781 static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | |
1782 Operand *Source1) { | 2077 Operand *Source1) { |
1783 return new (Func->allocate<InstX86ImulImm>()) | 2078 assert(Source0->getType() == IceType_v8i16 || |
1784 InstX86ImulImm(Func, Dest, Source0, Source1); | 2079 Source0->getType() == IceType_v8i1 || |
1785 } | 2080 InstX86Base::getTarget(Func)->getInstructionSet() >= |
1786 | 2081 Traits::SSE4_1); |
1787 void emit(const Cfg *Func) const override; | 2082 return new (Func->allocate<InstX86Pextr>()) |
1788 void emitIAS(const Cfg *Func) const override; | 2083 InstX86Pextr(Func, Dest, Source0, Source1); |
1789 | 2084 } |
1790 private: | 2085 |
1791 InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2086 void emit(const Cfg *Func) const override; |
1792 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm>( | 2087 void emitIAS(const Cfg *Func) const override; |
1793 Func, Dest, Source0, Source1) {} | 2088 |
1794 }; | 2089 private: |
1795 | 2090 InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) |
1796 template <class Machine> | 2091 : InstX86BaseThreeAddressop<InstX86Base::Pextr>(Func, Dest, Source0, |
1797 class InstX86Mulps | 2092 Source1) {} |
1798 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 2093 }; |
1799 InstX86Base<Machine>::SseSuffix::Packed> { | 2094 |
1800 public: | 2095 class InstX86Pshufd : public InstX86BaseThreeAddressop<InstX86Base::Pshufd> { |
1801 static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2096 public: |
1802 return new (Func->allocate<InstX86Mulps>()) | 2097 static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, |
1803 InstX86Mulps(Func, Dest, Source); | 2098 Operand *Source1) { |
1804 } | 2099 return new (Func->allocate<InstX86Pshufd>()) |
1805 | 2100 InstX86Pshufd(Func, Dest, Source0, Source1); |
1806 private: | 2101 } |
1807 InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | 2102 |
1808 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 2103 void emitIAS(const Cfg *Func) const override; |
1809 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 2104 |
1810 Source) {} | 2105 private: |
1811 }; | 2106 InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) |
1812 | 2107 : InstX86BaseThreeAddressop<InstX86Base::Pshufd>(Func, Dest, Source0, |
1813 template <class Machine> | 2108 Source1) {} |
1814 class InstX86Mulss | 2109 }; |
1815 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 2110 |
1816 InstX86Base<Machine>::SseSuffix::Scalar> { | 2111 /// Base class for a lockable x86-32 instruction (emits a locked prefix). |
1817 public: | 2112 class InstX86BaseLockable : public InstX86Base { |
1818 static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2113 InstX86BaseLockable() = delete; |
1819 return new (Func->allocate<InstX86Mulss>()) | 2114 InstX86BaseLockable(const InstX86BaseLockable &) = delete; |
1820 InstX86Mulss(Func, Dest, Source); | 2115 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; |
1821 } | 2116 |
1822 | 2117 protected: |
1823 private: | 2118 bool Locked; |
1824 InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | 2119 |
1825 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 2120 InstX86BaseLockable(Cfg *Func, typename InstX86Base::InstKindX86 Kind, |
1826 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 2121 SizeT Maxsrcs, Variable *Dest, bool Locked) |
1827 Source) {} | 2122 : InstX86Base(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |
1828 }; | 2123 // Assume that such instructions are used for Atomics and be careful with |
1829 | 2124 // optimizations. |
1830 template <class Machine> | 2125 this->HasSideEffects = Locked; |
1831 class InstX86Pmull | 2126 } |
1832 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | 2127 }; |
1833 InstX86Base<Machine>::SseSuffix::Integral> { | 2128 |
1834 public: | 2129 /// Mul instruction - unsigned multiply. |
1835 static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2130 class InstX86Mul final : public InstX86Base { |
1836 bool TypesAreValid = | 2131 InstX86Mul() = delete; |
1837 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | 2132 InstX86Mul(const InstX86Mul &) = delete; |
1838 auto *Target = InstX86Base<Machine>::getTarget(Func); | 2133 InstX86Mul &operator=(const InstX86Mul &) = delete; |
1839 bool InstructionSetIsValid = | 2134 |
1840 Dest->getType() == IceType_v8i16 || | 2135 public: |
1841 Target->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1; | 2136 static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, |
1842 (void)TypesAreValid; | |
1843 (void)InstructionSetIsValid; | |
1844 assert(TypesAreValid); | |
1845 assert(InstructionSetIsValid); | |
1846 return new (Func->allocate<InstX86Pmull>()) | |
1847 InstX86Pmull(Func, Dest, Source); | |
1848 } | |
1849 | |
1850 private: | |
1851 InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | |
1852 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | |
1853 InstX86Base<Machine>::SseSuffix::Integral>( | |
1854 Func, Dest, Source) {} | |
1855 }; | |
1856 | |
1857 template <class Machine> | |
1858 class InstX86Pmuludq | |
1859 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | |
1860 InstX86Base<Machine>::SseSuffix::None> { | |
1861 public: | |
1862 static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1863 assert(Dest->getType() == IceType_v4i32 && | |
1864 Source->getType() == IceType_v4i32); | |
1865 return new (Func->allocate<InstX86Pmuludq>()) | |
1866 InstX86Pmuludq(Func, Dest, Source); | |
1867 } | |
1868 | |
1869 private: | |
1870 InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | |
1871 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | |
1872 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
1873 Source) {} | |
1874 }; | |
1875 | |
1876 template <class Machine> | |
1877 class InstX86Divps | |
1878 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | |
1879 InstX86Base<Machine>::SseSuffix::Packed> { | |
1880 public: | |
1881 static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1882 return new (Func->allocate<InstX86Divps>()) | |
1883 InstX86Divps(Func, Dest, Source); | |
1884 } | |
1885 | |
1886 private: | |
1887 InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | |
1888 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | |
1889 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
1890 Source) {} | |
1891 }; | |
1892 | |
1893 template <class Machine> | |
1894 class InstX86Divss | |
1895 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | |
1896 InstX86Base<Machine>::SseSuffix::Scalar> { | |
1897 public: | |
1898 static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1899 return new (Func->allocate<InstX86Divss>()) | |
1900 InstX86Divss(Func, Dest, Source); | |
1901 } | |
1902 | |
1903 private: | |
1904 InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | |
1905 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | |
1906 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
1907 Source) {} | |
1908 }; | |
1909 | |
1910 template <class Machine> | |
1911 class InstX86Rol | |
1912 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol> { | |
1913 public: | |
1914 static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1915 return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | |
1916 } | |
1917 | |
1918 private: | |
1919 InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | |
1920 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol>(Func, Dest, | |
1921 Source) {} | |
1922 }; | |
1923 | |
1924 template <class Machine> | |
1925 class InstX86Shl | |
1926 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl> { | |
1927 public: | |
1928 static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1929 return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | |
1930 } | |
1931 | |
1932 private: | |
1933 InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | |
1934 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl>(Func, Dest, | |
1935 Source) {} | |
1936 }; | |
1937 | |
1938 template <class Machine> | |
1939 class InstX86Psll | |
1940 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll> { | |
1941 public: | |
1942 static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1943 assert(Dest->getType() == IceType_v8i16 || | |
1944 Dest->getType() == IceType_v8i1 || | |
1945 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
1946 return new (Func->allocate<InstX86Psll>()) InstX86Psll(Func, Dest, Source); | |
1947 } | |
1948 | |
1949 private: | |
1950 InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | |
1951 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll>( | |
1952 Func, Dest, Source) {} | |
1953 }; | |
1954 | |
1955 template <class Machine> | |
1956 class InstX86Psrl | |
1957 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, | |
1958 true> { | |
1959 public: | |
1960 static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1961 return new (Func->allocate<InstX86Psrl>()) InstX86Psrl(Func, Dest, Source); | |
1962 } | |
1963 | |
1964 private: | |
1965 InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | |
1966 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, true>( | |
1967 Func, Dest, Source) {} | |
1968 }; | |
1969 | |
1970 template <class Machine> | |
1971 class InstX86Shr | |
1972 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr> { | |
1973 public: | |
1974 static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1975 return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | |
1976 } | |
1977 | |
1978 private: | |
1979 InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | |
1980 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr>(Func, Dest, | |
1981 Source) {} | |
1982 }; | |
1983 | |
1984 template <class Machine> | |
1985 class InstX86Sar | |
1986 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar> { | |
1987 public: | |
1988 static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
1989 return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | |
1990 } | |
1991 | |
1992 private: | |
1993 InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | |
1994 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar>(Func, Dest, | |
1995 Source) {} | |
1996 }; | |
1997 | |
1998 template <class Machine> | |
1999 class InstX86Psra | |
2000 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra> { | |
2001 public: | |
2002 static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
2003 assert(Dest->getType() == IceType_v8i16 || | |
2004 Dest->getType() == IceType_v8i1 || | |
2005 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
2006 return new (Func->allocate<InstX86Psra>()) InstX86Psra(Func, Dest, Source); | |
2007 } | |
2008 | |
2009 private: | |
2010 InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | |
2011 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra>( | |
2012 Func, Dest, Source) {} | |
2013 }; | |
2014 | |
2015 template <class Machine> | |
2016 class InstX86Pcmpeq | |
2017 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | |
2018 InstX86Base<Machine>::SseSuffix::Integral> { | |
2019 public: | |
2020 static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
2021 return new (Func->allocate<InstX86Pcmpeq>()) | |
2022 InstX86Pcmpeq(Func, Dest, Source); | |
2023 } | |
2024 | |
2025 private: | |
2026 InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | |
2027 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | |
2028 InstX86Base<Machine>::SseSuffix::Integral>( | |
2029 Func, Dest, Source) {} | |
2030 }; | |
2031 | |
2032 template <class Machine> | |
2033 class InstX86Pcmpgt | |
2034 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | |
2035 InstX86Base<Machine>::SseSuffix::Integral> { | |
2036 public: | |
2037 static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
2038 return new (Func->allocate<InstX86Pcmpgt>()) | |
2039 InstX86Pcmpgt(Func, Dest, Source); | |
2040 } | |
2041 | |
2042 private: | |
2043 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | |
2044 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | |
2045 InstX86Base<Machine>::SseSuffix::Integral>( | |
2046 Func, Dest, Source) {} | |
2047 }; | |
2048 | |
2049 /// movss is only a binary operation when the source and dest operands are both | |
2050 /// registers (the high bits of dest are left untouched). In other cases, it | |
2051 /// behaves like a copy (mov-like) operation (and the high bits of dest are | |
2052 /// cleared). InstX86Movss will assert that both its source and dest operands | |
2053 /// are registers, so the lowering code should use _mov instead of _movss in | |
2054 /// cases where a copy operation is intended. | |
2055 template <class Machine> | |
2056 class InstX86MovssRegs | |
2057 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, | |
2058 false, InstX86Base<Machine>::SseSuffix::None> { | |
2059 public: | |
2060 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
2061 return new (Func->allocate<InstX86MovssRegs>()) | |
2062 InstX86MovssRegs(Func, Dest, Source); | |
2063 } | |
2064 | |
2065 void emitIAS(const Cfg *Func) const override; | |
2066 | |
2067 private: | |
2068 InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | |
2069 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, false, | |
2070 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
2071 Source) {} | |
2072 }; | |
2073 | |
2074 template <class Machine> | |
2075 class InstX86Idiv | |
2076 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv> { | |
2077 public: | |
2078 static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
2079 Operand *Source2) { | |
2080 return new (Func->allocate<InstX86Idiv>()) | |
2081 InstX86Idiv(Func, Dest, Source1, Source2); | |
2082 } | |
2083 | |
2084 void emit(const Cfg *Func) const override; | |
2085 void emitIAS(const Cfg *Func) const override; | |
2086 | |
2087 private: | |
2088 InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
2089 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv>( | |
2090 Func, Dest, Source1, Source2) {} | |
2091 }; | |
2092 | |
2093 template <class Machine> | |
2094 class InstX86Div | |
2095 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Div> { | |
2096 public: | |
2097 static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
2098 Operand *Source2) { | |
2099 return new (Func->allocate<InstX86Div>()) | |
2100 InstX86Div(Func, Dest, Source1, Source2); | |
2101 } | |
2102 | |
2103 void emit(const Cfg *Func) const override; | |
2104 void emitIAS(const Cfg *Func) const override; | |
2105 | |
2106 private: | |
2107 InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
2108 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Div>( | |
2109 Func, Dest, Source1, Source2) {} | |
2110 }; | |
2111 | |
2112 template <class Machine> | |
2113 class InstX86Insertps | |
2114 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps> { | |
2115 public: | |
2116 static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
2117 Operand *Source2) { | |
2118 return new (Func->allocate<InstX86Insertps>()) | |
2119 InstX86Insertps(Func, Dest, Source1, Source2); | |
2120 } | |
2121 | |
2122 void emitIAS(const Cfg *Func) const override; | |
2123 | |
2124 private: | |
2125 InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
2126 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps>( | |
2127 Func, Dest, Source1, Source2) {} | |
2128 }; | |
2129 | |
2130 template <class Machine> | |
2131 class InstX86Pinsr | |
2132 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr> { | |
2133 public: | |
2134 static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
2135 Operand *Source2) { | 2137 Operand *Source2) { |
2136 // pinsrb and pinsrd are SSE4.1 instructions. | 2138 return new (Func->allocate<InstX86Mul>()) |
2137 assert(Dest->getType() == IceType_v8i16 || | 2139 InstX86Mul(Func, Dest, Source1, Source2); |
2138 Dest->getType() == IceType_v8i1 || | 2140 } |
2139 InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2141 void emit(const Cfg *Func) const override; |
2140 InstX86Base<Machine>::Traits::SSE4_1); | 2142 void emitIAS(const Cfg *Func) const override; |
2141 return new (Func->allocate<InstX86Pinsr>()) | 2143 void dump(const Cfg *Func) const override; |
2142 InstX86Pinsr(Func, Dest, Source1, Source2); | 2144 static bool classof(const Inst *Inst) { |
2143 } | 2145 return InstX86Base::isClassof(Inst, InstX86Base::Mul); |
2144 | 2146 } |
2145 void emit(const Cfg *Func) const override; | 2147 |
2146 void emitIAS(const Cfg *Func) const override; | 2148 private: |
2147 | 2149 InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
2148 private: | 2150 }; |
2149 InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2151 |
2150 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr>( | 2152 /// Shld instruction - shift across a pair of operands. |
2151 Func, Dest, Source1, Source2) {} | 2153 class InstX86Shld final : public InstX86Base { |
2152 }; | 2154 InstX86Shld() = delete; |
2153 | 2155 InstX86Shld(const InstX86Shld &) = delete; |
2154 template <class Machine> | 2156 InstX86Shld &operator=(const InstX86Shld &) = delete; |
2155 class InstX86Shufps | 2157 |
2156 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps> { | 2158 public: |
2157 public: | 2159 static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, |
2158 static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
2159 Operand *Source2) { | 2160 Operand *Source2) { |
2160 return new (Func->allocate<InstX86Shufps>()) | 2161 return new (Func->allocate<InstX86Shld>()) |
2161 InstX86Shufps(Func, Dest, Source1, Source2); | 2162 InstX86Shld(Func, Dest, Source1, Source2); |
2162 } | 2163 } |
2163 | 2164 void emit(const Cfg *Func) const override; |
2164 void emitIAS(const Cfg *Func) const override; | 2165 void emitIAS(const Cfg *Func) const override; |
2165 | 2166 void dump(const Cfg *Func) const override; |
2166 private: | 2167 static bool classof(const Inst *Inst) { |
2167 InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2168 return InstX86Base::isClassof(Inst, InstX86Base::Shld); |
2168 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps>( | 2169 } |
2169 Func, Dest, Source1, Source2) {} | 2170 |
2170 }; | 2171 private: |
2171 | 2172 InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
2172 template <class Machine> | 2173 }; |
2173 class InstX86Blendvps | 2174 |
2174 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps> { | 2175 /// Shrd instruction - shift across a pair of operands. |
2175 public: | 2176 class InstX86Shrd final : public InstX86Base { |
2176 static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 2177 InstX86Shrd() = delete; |
2177 Operand *Source2) { | 2178 InstX86Shrd(const InstX86Shrd &) = delete; |
2178 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2179 InstX86Shrd &operator=(const InstX86Shrd &) = delete; |
2179 InstX86Base<Machine>::Traits::SSE4_1); | 2180 |
2180 return new (Func->allocate<InstX86Blendvps>()) | 2181 public: |
2181 InstX86Blendvps(Func, Dest, Source1, Source2); | 2182 static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, |
2182 } | 2183 Operand *Source2) { |
2183 | 2184 return new (Func->allocate<InstX86Shrd>()) |
2184 void emit(const Cfg *Func) const override; | 2185 InstX86Shrd(Func, Dest, Source1, Source2); |
2185 void emitIAS(const Cfg *Fund) const override; | 2186 } |
2186 | 2187 void emit(const Cfg *Func) const override; |
2187 private: | 2188 void emitIAS(const Cfg *Func) const override; |
2188 InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2189 void dump(const Cfg *Func) const override; |
2189 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps>( | 2190 static bool classof(const Inst *Inst) { |
2190 Func, Dest, Source1, Source2) {} | 2191 return InstX86Base::isClassof(Inst, InstX86Base::Shrd); |
2191 }; | 2192 } |
2192 | 2193 |
2193 template <class Machine> | 2194 private: |
2194 class InstX86Pblendvb | 2195 InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
2195 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb> { | 2196 }; |
2196 public: | 2197 |
2197 static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, | 2198 /// Conditional move instruction. |
2198 Operand *Source2) { | 2199 class InstX86Cmov final : public InstX86Base { |
2199 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2200 InstX86Cmov() = delete; |
2200 InstX86Base<Machine>::Traits::SSE4_1); | 2201 InstX86Cmov(const InstX86Cmov &) = delete; |
2201 return new (Func->allocate<InstX86Pblendvb>()) | 2202 InstX86Cmov &operator=(const InstX86Cmov &) = delete; |
2202 InstX86Pblendvb(Func, Dest, Source1, Source2); | 2203 |
2203 } | 2204 public: |
2204 | 2205 static InstX86Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, |
2205 void emit(const Cfg *Func) const override; | 2206 BrCond Cond) { |
2206 void emitIAS(const Cfg *Func) const override; | 2207 return new (Func->allocate<InstX86Cmov>()) |
2207 | 2208 InstX86Cmov(Func, Dest, Source, Cond); |
2208 private: | 2209 } |
2209 InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2210 void emit(const Cfg *Func) const override; |
2210 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb>( | 2211 void emitIAS(const Cfg *Func) const override; |
2211 Func, Dest, Source1, Source2) {} | 2212 void dump(const Cfg *Func) const override; |
2212 }; | 2213 static bool classof(const Inst *Inst) { |
2213 | 2214 return InstX86Base::isClassof(Inst, InstX86Base::Cmov); |
2214 template <class Machine> | 2215 } |
2215 class InstX86Pextr | 2216 |
2216 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr> { | 2217 private: |
2217 public: | 2218 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, BrCond Cond); |
2218 static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, | 2219 |
2219 Operand *Source1) { | 2220 BrCond Condition; |
2220 assert(Source0->getType() == IceType_v8i16 || | 2221 }; |
2221 Source0->getType() == IceType_v8i1 || | 2222 |
2222 InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2223 /// Cmpps instruction - compare packed singled-precision floating point values |
2223 InstX86Base<Machine>::Traits::SSE4_1); | 2224 class InstX86Cmpps final : public InstX86Base { |
2224 return new (Func->allocate<InstX86Pextr>()) | 2225 InstX86Cmpps() = delete; |
2225 InstX86Pextr(Func, Dest, Source0, Source1); | 2226 InstX86Cmpps(const InstX86Cmpps &) = delete; |
2226 } | 2227 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; |
2227 | 2228 |
2228 void emit(const Cfg *Func) const override; | 2229 public: |
2229 void emitIAS(const Cfg *Func) const override; | 2230 static InstX86Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, |
2230 | 2231 CmppsCond Condition) { |
2231 private: | 2232 return new (Func->allocate<InstX86Cmpps>()) |
2232 InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2233 InstX86Cmpps(Func, Dest, Source, Condition); |
2233 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr>( | 2234 } |
2234 Func, Dest, Source0, Source1) {} | 2235 void emit(const Cfg *Func) const override; |
2235 }; | 2236 void emitIAS(const Cfg *Func) const override; |
2236 | 2237 void dump(const Cfg *Func) const override; |
2237 template <class Machine> | 2238 static bool classof(const Inst *Inst) { |
2238 class InstX86Pshufd | 2239 return InstX86Base::isClassof(Inst, InstX86Base::Cmpps); |
2239 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd> { | 2240 } |
2240 public: | 2241 |
2241 static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, | 2242 private: |
2242 Operand *Source1) { | 2243 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, CmppsCond Cond); |
2243 return new (Func->allocate<InstX86Pshufd>()) | 2244 |
2244 InstX86Pshufd(Func, Dest, Source0, Source1); | 2245 CmppsCond Condition; |
2245 } | 2246 }; |
2246 | 2247 |
2247 void emitIAS(const Cfg *Func) const override; | 2248 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |
2248 | 2249 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If |
2249 private: | 2250 /// not, ZF is cleared and <dest> is copied to eax (or subregister). <dest> |
2250 InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2251 /// can be a register or memory, while <desired> must be a register. It is |
2251 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd>( | 2252 /// the user's responsibility to mark eax with a FakeDef. |
2252 Func, Dest, Source0, Source1) {} | 2253 class InstX86Cmpxchg final : public InstX86BaseLockable { |
2253 }; | 2254 InstX86Cmpxchg() = delete; |
2254 | 2255 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; |
2255 /// Base class for a lockable x86-32 instruction (emits a locked prefix). | 2256 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; |
2256 template <class Machine> | 2257 |
2257 class InstX86BaseLockable : public InstX86Base<Machine> { | 2258 public: |
2258 InstX86BaseLockable() = delete; | 2259 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
2259 InstX86BaseLockable(const InstX86BaseLockable &) = delete; | 2260 Variable *Desired, bool Locked) { |
2260 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; | 2261 return new (Func->allocate<InstX86Cmpxchg>()) |
2261 | 2262 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |
2262 protected: | 2263 } |
2263 bool Locked; | 2264 void emit(const Cfg *Func) const override; |
2264 | 2265 void emitIAS(const Cfg *Func) const override; |
2265 InstX86BaseLockable(Cfg *Func, | 2266 void dump(const Cfg *Func) const override; |
2266 typename InstX86Base<Machine>::InstKindX86 Kind, | 2267 static bool classof(const Inst *Inst) { |
2267 SizeT Maxsrcs, Variable *Dest, bool Locked) | 2268 return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg); |
2268 : InstX86Base<Machine>(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 2269 } |
2269 // Assume that such instructions are used for Atomics and be careful with | 2270 |
2270 // optimizations. | 2271 private: |
2271 this->HasSideEffects = Locked; | 2272 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
2272 } | 2273 Variable *Desired, bool Locked); |
2273 }; | 2274 }; |
2274 | 2275 |
2275 /// Mul instruction - unsigned multiply. | 2276 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals |
2276 template <class Machine> class InstX86Mul final : public InstX86Base<Machine> { | 2277 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF |
2277 InstX86Mul() = delete; | 2278 /// is cleared and <m64> is copied to edx:eax. The caller is responsible for |
2278 InstX86Mul(const InstX86Mul &) = delete; | 2279 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory |
2279 InstX86Mul &operator=(const InstX86Mul &) = delete; | 2280 /// operand. |
2280 | 2281 class InstX86Cmpxchg8b final : public InstX86BaseLockable { |
2281 public: | 2282 InstX86Cmpxchg8b() = delete; |
2282 static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2283 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; |
2283 Operand *Source2) { | 2284 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; |
2284 return new (Func->allocate<InstX86Mul>()) | 2285 |
2285 InstX86Mul(Func, Dest, Source1, Source2); | 2286 public: |
2286 } | 2287 static InstX86Cmpxchg8b *create(Cfg *Func, X86OperandMem *Dest, |
2287 void emit(const Cfg *Func) const override; | 2288 Variable *Edx, Variable *Eax, Variable *Ecx, |
2288 void emitIAS(const Cfg *Func) const override; | 2289 Variable *Ebx, bool Locked) { |
2289 void dump(const Cfg *Func) const override; | 2290 return new (Func->allocate<InstX86Cmpxchg8b>()) |
2290 static bool classof(const Inst *Inst) { | 2291 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |
2291 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mul); | 2292 } |
2292 } | 2293 void emit(const Cfg *Func) const override; |
2293 | 2294 void emitIAS(const Cfg *Func) const override; |
2294 private: | 2295 void dump(const Cfg *Func) const override; |
2295 InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2296 static bool classof(const Inst *Inst) { |
2296 }; | 2297 return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg8b); |
2297 | 2298 } |
2298 /// Shld instruction - shift across a pair of operands. | 2299 |
2299 template <class Machine> class InstX86Shld final : public InstX86Base<Machine> { | 2300 private: |
2300 InstX86Shld() = delete; | 2301 InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Dest, Variable *Edx, |
2301 InstX86Shld(const InstX86Shld &) = delete; | 2302 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |
2302 InstX86Shld &operator=(const InstX86Shld &) = delete; | 2303 }; |
2303 | 2304 |
2304 public: | 2305 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as |
2305 static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2306 /// appropriate. s=float, d=double, i=int. X and Y are determined from |
2306 Operand *Source2) { | 2307 /// dest/src types. Sign and zero extension on the integer operand needs to be |
2307 return new (Func->allocate<InstX86Shld>()) | 2308 /// done separately. |
2308 InstX86Shld(Func, Dest, Source1, Source2); | 2309 class InstX86Cvt final : public InstX86Base { |
2309 } | 2310 InstX86Cvt() = delete; |
2310 void emit(const Cfg *Func) const override; | 2311 InstX86Cvt(const InstX86Cvt &) = delete; |
2311 void emitIAS(const Cfg *Func) const override; | 2312 InstX86Cvt &operator=(const InstX86Cvt &) = delete; |
2312 void dump(const Cfg *Func) const override; | 2313 |
2313 static bool classof(const Inst *Inst) { | 2314 public: |
2314 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shld); | 2315 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |
2315 } | 2316 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, |
2316 | 2317 CvtVariant Variant) { |
2317 private: | 2318 return new (Func->allocate<InstX86Cvt>()) |
2318 InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2319 InstX86Cvt(Func, Dest, Source, Variant); |
2319 }; | 2320 } |
2320 | 2321 void emit(const Cfg *Func) const override; |
2321 /// Shrd instruction - shift across a pair of operands. | 2322 void emitIAS(const Cfg *Func) const override; |
2322 template <class Machine> class InstX86Shrd final : public InstX86Base<Machine> { | 2323 void dump(const Cfg *Func) const override; |
2323 InstX86Shrd() = delete; | 2324 static bool classof(const Inst *Inst) { |
2324 InstX86Shrd(const InstX86Shrd &) = delete; | 2325 return InstX86Base::isClassof(Inst, InstX86Base::Cvt); |
2325 InstX86Shrd &operator=(const InstX86Shrd &) = delete; | 2326 } |
2326 | 2327 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } |
2327 public: | 2328 |
2328 static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2329 private: |
2329 Operand *Source2) { | 2330 CvtVariant Variant; |
2330 return new (Func->allocate<InstX86Shrd>()) | 2331 InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); |
2331 InstX86Shrd(Func, Dest, Source1, Source2); | 2332 }; |
2332 } | 2333 |
2333 void emit(const Cfg *Func) const override; | 2334 /// cmp - Integer compare instruction. |
2334 void emitIAS(const Cfg *Func) const override; | 2335 class InstX86Icmp final : public InstX86Base { |
2335 void dump(const Cfg *Func) const override; | 2336 InstX86Icmp() = delete; |
2336 static bool classof(const Inst *Inst) { | 2337 InstX86Icmp(const InstX86Icmp &) = delete; |
2337 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shrd); | 2338 InstX86Icmp &operator=(const InstX86Icmp &) = delete; |
2338 } | 2339 |
2339 | 2340 public: |
2340 private: | 2341 static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
2341 InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2342 return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); |
2342 }; | 2343 } |
2343 | 2344 void emit(const Cfg *Func) const override; |
2344 /// Conditional move instruction. | 2345 void emitIAS(const Cfg *Func) const override; |
2345 template <class Machine> class InstX86Cmov final : public InstX86Base<Machine> { | 2346 void dump(const Cfg *Func) const override; |
2346 InstX86Cmov() = delete; | 2347 static bool classof(const Inst *Inst) { |
2347 InstX86Cmov(const InstX86Cmov &) = delete; | 2348 return InstX86Base::isClassof(Inst, InstX86Base::Icmp); |
2348 InstX86Cmov &operator=(const InstX86Cmov &) = delete; | 2349 } |
2349 | 2350 |
2350 public: | 2351 private: |
2351 static InstX86Cmov * | 2352 InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); |
2352 create(Cfg *Func, Variable *Dest, Operand *Source, | 2353 }; |
2353 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | 2354 |
2354 return new (Func->allocate<InstX86Cmov>()) | 2355 /// ucomiss/ucomisd - floating-point compare instruction. |
2355 InstX86Cmov(Func, Dest, Source, Cond); | 2356 class InstX86Ucomiss final : public InstX86Base { |
2356 } | 2357 InstX86Ucomiss() = delete; |
2357 void emit(const Cfg *Func) const override; | 2358 InstX86Ucomiss(const InstX86Ucomiss &) = delete; |
2358 void emitIAS(const Cfg *Func) const override; | 2359 InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; |
2359 void dump(const Cfg *Func) const override; | 2360 |
2360 static bool classof(const Inst *Inst) { | 2361 public: |
2361 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmov); | 2362 static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
2362 } | 2363 return new (Func->allocate<InstX86Ucomiss>()) |
2363 | 2364 InstX86Ucomiss(Func, Src1, Src2); |
2364 private: | 2365 } |
2365 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 2366 void emit(const Cfg *Func) const override; |
2366 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 2367 void emitIAS(const Cfg *Func) const override; |
2367 | 2368 void dump(const Cfg *Func) const override; |
2368 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 2369 static bool classof(const Inst *Inst) { |
2369 }; | 2370 return InstX86Base::isClassof(Inst, InstX86Base::Ucomiss); |
2370 | 2371 } |
2371 /// Cmpps instruction - compare packed singled-precision floating point values | 2372 |
2372 template <class Machine> | 2373 private: |
2373 class InstX86Cmpps final : public InstX86Base<Machine> { | 2374 InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); |
2374 InstX86Cmpps() = delete; | 2375 }; |
2375 InstX86Cmpps(const InstX86Cmpps &) = delete; | 2376 |
2376 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; | 2377 /// UD2 instruction. |
2377 | 2378 class InstX86UD2 final : public InstX86Base { |
2378 public: | 2379 InstX86UD2() = delete; |
2379 static InstX86Cmpps * | 2380 InstX86UD2(const InstX86UD2 &) = delete; |
2380 create(Cfg *Func, Variable *Dest, Operand *Source, | 2381 InstX86UD2 &operator=(const InstX86UD2 &) = delete; |
2381 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { | 2382 |
2382 return new (Func->allocate<InstX86Cmpps>()) | 2383 public: |
2383 InstX86Cmpps(Func, Dest, Source, Condition); | 2384 static InstX86UD2 *create(Cfg *Func) { |
2384 } | 2385 return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); |
2385 void emit(const Cfg *Func) const override; | 2386 } |
2386 void emitIAS(const Cfg *Func) const override; | 2387 void emit(const Cfg *Func) const override; |
2387 void dump(const Cfg *Func) const override; | 2388 void emitIAS(const Cfg *Func) const override; |
2388 static bool classof(const Inst *Inst) { | 2389 void dump(const Cfg *Func) const override; |
2389 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpps); | 2390 static bool classof(const Inst *Inst) { |
2390 } | 2391 return InstX86Base::isClassof(Inst, InstX86Base::UD2); |
2391 | 2392 } |
2392 private: | 2393 |
2393 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 2394 private: |
2394 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); | 2395 explicit InstX86UD2(Cfg *Func); |
2395 | 2396 }; |
2396 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; | 2397 |
2397 }; | 2398 /// Test instruction. |
2398 | 2399 class InstX86Test final : public InstX86Base { |
2399 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 2400 InstX86Test() = delete; |
2400 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If not, | 2401 InstX86Test(const InstX86Test &) = delete; |
2401 /// ZF is cleared and <dest> is copied to eax (or subregister). <dest> can be a | 2402 InstX86Test &operator=(const InstX86Test &) = delete; |
2402 /// register or memory, while <desired> must be a register. It is the user's | 2403 |
2403 /// responsibility to mark eax with a FakeDef. | 2404 public: |
2404 template <class Machine> | 2405 static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { |
2405 class InstX86Cmpxchg final : public InstX86BaseLockable<Machine> { | 2406 return new (Func->allocate<InstX86Test>()) |
2406 InstX86Cmpxchg() = delete; | 2407 InstX86Test(Func, Source1, Source2); |
2407 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; | 2408 } |
2408 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; | 2409 void emit(const Cfg *Func) const override; |
2409 | 2410 void emitIAS(const Cfg *Func) const override; |
2410 public: | 2411 void dump(const Cfg *Func) const override; |
2411 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2412 static bool classof(const Inst *Inst) { |
2412 Variable *Desired, bool Locked) { | 2413 return InstX86Base::isClassof(Inst, InstX86Base::Test); |
2413 return new (Func->allocate<InstX86Cmpxchg>()) | 2414 } |
2414 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 2415 |
2415 } | 2416 private: |
2416 void emit(const Cfg *Func) const override; | 2417 InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); |
2417 void emitIAS(const Cfg *Func) const override; | 2418 }; |
2418 void dump(const Cfg *Func) const override; | 2419 |
2419 static bool classof(const Inst *Inst) { | 2420 /// Mfence instruction. |
2420 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpxchg); | 2421 class InstX86Mfence final : public InstX86Base { |
2421 } | 2422 InstX86Mfence() = delete; |
2422 | 2423 InstX86Mfence(const InstX86Mfence &) = delete; |
2423 private: | 2424 InstX86Mfence &operator=(const InstX86Mfence &) = delete; |
2424 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2425 |
2425 Variable *Desired, bool Locked); | 2426 public: |
2426 }; | 2427 static InstX86Mfence *create(Cfg *Func) { |
2427 | 2428 return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); |
2428 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals | 2429 } |
2429 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF is | 2430 void emit(const Cfg *Func) const override; |
2430 /// cleared and <m64> is copied to edx:eax. The caller is responsible for | 2431 void emitIAS(const Cfg *Func) const override; |
2431 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory | 2432 void dump(const Cfg *Func) const override; |
2432 /// operand. | 2433 static bool classof(const Inst *Inst) { |
2433 template <class Machine> | 2434 return InstX86Base::isClassof(Inst, InstX86Base::Mfence); |
2434 class InstX86Cmpxchg8b final : public InstX86BaseLockable<Machine> { | 2435 } |
2435 InstX86Cmpxchg8b() = delete; | 2436 |
2436 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; | 2437 private: |
2437 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; | 2438 explicit InstX86Mfence(Cfg *Func); |
2438 | 2439 }; |
2439 public: | 2440 |
2440 static InstX86Cmpxchg8b * | 2441 /// This is essentially a "mov" instruction with anX86OperandMem operand |
2441 create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2442 /// instead of Variable as the destination. It's important for liveness that |
2442 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2443 /// there is no Dest operand. |
2443 bool Locked) { | 2444 class InstX86Store final : public InstX86Base { |
2444 return new (Func->allocate<InstX86Cmpxchg8b>()) | 2445 InstX86Store() = delete; |
2445 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 2446 InstX86Store(const InstX86Store &) = delete; |
2446 } | 2447 InstX86Store &operator=(const InstX86Store &) = delete; |
2447 void emit(const Cfg *Func) const override; | 2448 |
2448 void emitIAS(const Cfg *Func) const override; | 2449 public: |
2449 void dump(const Cfg *Func) const override; | 2450 static InstX86Store *create(Cfg *Func, Operand *Value, X86Operand *Mem) { |
2450 static bool classof(const Inst *Inst) { | 2451 return new (Func->allocate<InstX86Store>()) |
2451 return InstX86Base<Machine>::isClassof(Inst, | 2452 InstX86Store(Func, Value, Mem); |
2452 InstX86Base<Machine>::Cmpxchg8b); | 2453 } |
2453 } | 2454 void emit(const Cfg *Func) const override; |
2454 | 2455 void emitIAS(const Cfg *Func) const override; |
2455 private: | 2456 void dump(const Cfg *Func) const override; |
2456 InstX86Cmpxchg8b(Cfg *Func, | 2457 static bool classof(const Inst *Inst) { |
2457 typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2458 return InstX86Base::isClassof(Inst, InstX86Base::Store); |
2458 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2459 } |
2459 bool Locked); | 2460 |
2460 }; | 2461 private: |
2461 | 2462 InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem); |
2462 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as | 2463 }; |
2463 /// appropriate. s=float, d=double, i=int. X and Y are determined from dest/src | 2464 |
2464 /// types. Sign and zero extension on the integer operand needs to be done | 2465 /// This is essentially a vector "mov" instruction with an typename |
2465 /// separately. | 2466 /// X86OperandMem operand instead of Variable as the destination. It's |
2466 template <class Machine> class InstX86Cvt final : public InstX86Base<Machine> { | 2467 /// important for liveness that there is no Dest operand. The source must be |
2467 InstX86Cvt() = delete; | 2468 /// an Xmm register, since Dest is mem. |
2468 InstX86Cvt(const InstX86Cvt &) = delete; | 2469 class InstX86StoreP final : public InstX86Base { |
2469 InstX86Cvt &operator=(const InstX86Cvt &) = delete; | 2470 InstX86StoreP() = delete; |
2470 | 2471 InstX86StoreP(const InstX86StoreP &) = delete; |
2471 public: | 2472 InstX86StoreP &operator=(const InstX86StoreP &) = delete; |
2472 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 2473 |
2473 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 2474 public: |
2474 CvtVariant Variant) { | 2475 static InstX86StoreP *create(Cfg *Func, Variable *Value, |
2475 return new (Func->allocate<InstX86Cvt>()) | 2476 X86OperandMem *Mem) { |
2476 InstX86Cvt(Func, Dest, Source, Variant); | 2477 return new (Func->allocate<InstX86StoreP>()) |
2477 } | 2478 InstX86StoreP(Func, Value, Mem); |
2478 void emit(const Cfg *Func) const override; | 2479 } |
2479 void emitIAS(const Cfg *Func) const override; | 2480 void emit(const Cfg *Func) const override; |
2480 void dump(const Cfg *Func) const override; | 2481 void emitIAS(const Cfg *Func) const override; |
2481 static bool classof(const Inst *Inst) { | 2482 void dump(const Cfg *Func) const override; |
2482 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cvt); | 2483 static bool classof(const Inst *Inst) { |
2483 } | 2484 return InstX86Base::isClassof(Inst, InstX86Base::StoreP); |
2484 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } | 2485 } |
2485 | 2486 |
2486 private: | 2487 private: |
2487 CvtVariant Variant; | 2488 InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem); |
2488 InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); | 2489 }; |
2489 }; | 2490 |
2490 | 2491 class InstX86StoreQ final : public InstX86Base { |
2491 /// cmp - Integer compare instruction. | 2492 InstX86StoreQ() = delete; |
2492 template <class Machine> class InstX86Icmp final : public InstX86Base<Machine> { | 2493 InstX86StoreQ(const InstX86StoreQ &) = delete; |
2493 InstX86Icmp() = delete; | 2494 InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; |
2494 InstX86Icmp(const InstX86Icmp &) = delete; | 2495 |
2495 InstX86Icmp &operator=(const InstX86Icmp &) = delete; | 2496 public: |
2496 | 2497 static InstX86StoreQ *create(Cfg *Func, Variable *Value, |
2497 public: | 2498 X86OperandMem *Mem) { |
2498 static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 2499 return new (Func->allocate<InstX86StoreQ>()) |
2499 return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); | 2500 InstX86StoreQ(Func, Value, Mem); |
2500 } | 2501 } |
2501 void emit(const Cfg *Func) const override; | 2502 void emit(const Cfg *Func) const override; |
2502 void emitIAS(const Cfg *Func) const override; | 2503 void emitIAS(const Cfg *Func) const override; |
2503 void dump(const Cfg *Func) const override; | 2504 void dump(const Cfg *Func) const override; |
2504 static bool classof(const Inst *Inst) { | 2505 static bool classof(const Inst *Inst) { |
2505 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Icmp); | 2506 return InstX86Base::isClassof(Inst, InstX86Base::StoreQ); |
2506 } | 2507 } |
2507 | 2508 |
2508 private: | 2509 private: |
2509 InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); | 2510 InstX86StoreQ(Cfg *Func, Variable *Value, X86OperandMem *Mem); |
2510 }; | 2511 }; |
2511 | 2512 |
2512 /// ucomiss/ucomisd - floating-point compare instruction. | 2513 /// Nop instructions of varying length |
2513 template <class Machine> | 2514 class InstX86Nop final : public InstX86Base { |
2514 class InstX86Ucomiss final : public InstX86Base<Machine> { | 2515 InstX86Nop() = delete; |
2515 InstX86Ucomiss() = delete; | 2516 InstX86Nop(const InstX86Nop &) = delete; |
2516 InstX86Ucomiss(const InstX86Ucomiss &) = delete; | 2517 InstX86Nop &operator=(const InstX86Nop &) = delete; |
2517 InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; | 2518 |
2518 | 2519 public: |
2519 public: | 2520 // TODO: Replace with enum. |
2520 static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 2521 using NopVariant = unsigned; |
2521 return new (Func->allocate<InstX86Ucomiss>()) | 2522 |
2522 InstX86Ucomiss(Func, Src1, Src2); | 2523 static InstX86Nop *create(Cfg *Func, NopVariant Variant) { |
2523 } | 2524 return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); |
2524 void emit(const Cfg *Func) const override; | 2525 } |
2525 void emitIAS(const Cfg *Func) const override; | 2526 void emit(const Cfg *Func) const override; |
2526 void dump(const Cfg *Func) const override; | 2527 void emitIAS(const Cfg *Func) const override; |
2527 static bool classof(const Inst *Inst) { | 2528 void dump(const Cfg *Func) const override; |
2528 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ucomiss); | 2529 static bool classof(const Inst *Inst) { |
2529 } | 2530 return InstX86Base::isClassof(Inst, InstX86Base::Nop); |
2530 | 2531 } |
2531 private: | 2532 |
2532 InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); | 2533 private: |
2533 }; | 2534 InstX86Nop(Cfg *Func, SizeT Length); |
2534 | 2535 |
2535 /// UD2 instruction. | 2536 NopVariant Variant; |
2536 template <class Machine> class InstX86UD2 final : public InstX86Base<Machine> { | 2537 }; |
2537 InstX86UD2() = delete; | 2538 |
2538 InstX86UD2(const InstX86UD2 &) = delete; | 2539 /// Fld - load a value onto the x87 FP stack. |
2539 InstX86UD2 &operator=(const InstX86UD2 &) = delete; | 2540 class InstX86Fld final : public InstX86Base { |
2540 | 2541 InstX86Fld() = delete; |
2541 public: | 2542 InstX86Fld(const InstX86Fld &) = delete; |
2542 static InstX86UD2 *create(Cfg *Func) { | 2543 InstX86Fld &operator=(const InstX86Fld &) = delete; |
2543 return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); | 2544 |
2544 } | 2545 public: |
2545 void emit(const Cfg *Func) const override; | 2546 static InstX86Fld *create(Cfg *Func, Operand *Src) { |
2546 void emitIAS(const Cfg *Func) const override; | 2547 return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); |
2547 void dump(const Cfg *Func) const override; | 2548 } |
2548 static bool classof(const Inst *Inst) { | 2549 void emit(const Cfg *Func) const override; |
2549 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::UD2); | 2550 void emitIAS(const Cfg *Func) const override; |
2550 } | 2551 void dump(const Cfg *Func) const override; |
2551 | 2552 static bool classof(const Inst *Inst) { |
2552 private: | 2553 return InstX86Base::isClassof(Inst, InstX86Base::Fld); |
2553 explicit InstX86UD2(Cfg *Func); | 2554 } |
2554 }; | 2555 |
2555 | 2556 private: |
2556 /// Test instruction. | 2557 InstX86Fld(Cfg *Func, Operand *Src); |
2557 template <class Machine> class InstX86Test final : public InstX86Base<Machine> { | 2558 }; |
2558 InstX86Test() = delete; | 2559 |
2559 InstX86Test(const InstX86Test &) = delete; | 2560 /// Fstp - store x87 st(0) into memory and pop st(0). |
2560 InstX86Test &operator=(const InstX86Test &) = delete; | 2561 class InstX86Fstp final : public InstX86Base { |
2561 | 2562 InstX86Fstp() = delete; |
2562 public: | 2563 InstX86Fstp(const InstX86Fstp &) = delete; |
2563 static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { | 2564 InstX86Fstp &operator=(const InstX86Fstp &) = delete; |
2564 return new (Func->allocate<InstX86Test>()) | 2565 |
2565 InstX86Test(Func, Source1, Source2); | 2566 public: |
2566 } | 2567 static InstX86Fstp *create(Cfg *Func, Variable *Dest) { |
2567 void emit(const Cfg *Func) const override; | 2568 return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); |
2568 void emitIAS(const Cfg *Func) const override; | 2569 } |
2569 void dump(const Cfg *Func) const override; | 2570 void emit(const Cfg *Func) const override; |
2570 static bool classof(const Inst *Inst) { | 2571 void emitIAS(const Cfg *Func) const override; |
2571 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Test); | 2572 void dump(const Cfg *Func) const override; |
2572 } | 2573 static bool classof(const Inst *Inst) { |
2573 | 2574 return InstX86Base::isClassof(Inst, InstX86Base::Fstp); |
2574 private: | 2575 } |
2575 InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); | 2576 |
2576 }; | 2577 private: |
2577 | 2578 InstX86Fstp(Cfg *Func, Variable *Dest); |
2578 /// Mfence instruction. | 2579 }; |
2579 template <class Machine> | 2580 |
2580 class InstX86Mfence final : public InstX86Base<Machine> { | 2581 class InstX86Pop final : public InstX86Base { |
2581 InstX86Mfence() = delete; | 2582 InstX86Pop() = delete; |
2582 InstX86Mfence(const InstX86Mfence &) = delete; | 2583 InstX86Pop(const InstX86Pop &) = delete; |
2583 InstX86Mfence &operator=(const InstX86Mfence &) = delete; | 2584 InstX86Pop &operator=(const InstX86Pop &) = delete; |
2584 | 2585 |
2585 public: | 2586 public: |
2586 static InstX86Mfence *create(Cfg *Func) { | 2587 static InstX86Pop *create(Cfg *Func, Variable *Dest) { |
2587 return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); | 2588 return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); |
2588 } | 2589 } |
2589 void emit(const Cfg *Func) const override; | 2590 void emit(const Cfg *Func) const override; |
2590 void emitIAS(const Cfg *Func) const override; | 2591 void emitIAS(const Cfg *Func) const override; |
2591 void dump(const Cfg *Func) const override; | 2592 void dump(const Cfg *Func) const override; |
2592 static bool classof(const Inst *Inst) { | 2593 static bool classof(const Inst *Inst) { |
2593 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mfence); | 2594 return InstX86Base::isClassof(Inst, InstX86Base::Pop); |
2594 } | 2595 } |
2595 | 2596 |
2596 private: | 2597 private: |
2597 explicit InstX86Mfence(Cfg *Func); | 2598 InstX86Pop(Cfg *Func, Variable *Dest); |
2598 }; | 2599 }; |
2599 | 2600 |
2600 /// This is essentially a "mov" instruction with an | 2601 class InstX86Push final : public InstX86Base { |
2601 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 2602 InstX86Push() = delete; |
2602 /// the destination. It's important for liveness that there is no Dest operand. | 2603 InstX86Push(const InstX86Push &) = delete; |
2603 template <class Machine> | 2604 InstX86Push &operator=(const InstX86Push &) = delete; |
2604 class InstX86Store final : public InstX86Base<Machine> { | 2605 |
2605 InstX86Store() = delete; | 2606 public: |
2606 InstX86Store(const InstX86Store &) = delete; | 2607 static InstX86Push *create(Cfg *Func, Variable *Source) { |
2607 InstX86Store &operator=(const InstX86Store &) = delete; | 2608 return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); |
2608 | 2609 } |
2609 public: | 2610 void emit(const Cfg *Func) const override; |
2610 static InstX86Store * | 2611 void emitIAS(const Cfg *Func) const override; |
2611 create(Cfg *Func, Operand *Value, | 2612 void dump(const Cfg *Func) const override; |
2612 typename InstX86Base<Machine>::Traits::X86Operand *Mem) { | 2613 static bool classof(const Inst *Inst) { |
2613 return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); | 2614 return InstX86Base::isClassof(Inst, InstX86Base::Push); |
2614 } | 2615 } |
2615 void emit(const Cfg *Func) const override; | 2616 |
2616 void emitIAS(const Cfg *Func) const override; | 2617 private: |
2617 void dump(const Cfg *Func) const override; | 2618 InstX86Push(Cfg *Func, Variable *Source); |
2618 static bool classof(const Inst *Inst) { | 2619 }; |
2619 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Store); | 2620 |
2620 } | 2621 /// Ret instruction. Currently only supports the "ret" version that does not |
2621 | 2622 /// pop arguments. This instruction takes a Source operand (for non-void |
2622 private: | 2623 /// returning functions) for liveness analysis, though a FakeUse before the |
2623 InstX86Store(Cfg *Func, Operand *Value, | 2624 /// ret would do just as well. |
2624 typename InstX86Base<Machine>::Traits::X86Operand *Mem); | 2625 class InstX86Ret final : public InstX86Base { |
2625 }; | 2626 InstX86Ret() = delete; |
2626 | 2627 InstX86Ret(const InstX86Ret &) = delete; |
2627 /// This is essentially a vector "mov" instruction with an typename | 2628 InstX86Ret &operator=(const InstX86Ret &) = delete; |
2628 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 2629 |
2629 /// the destination. It's important for liveness that there is no Dest operand. | 2630 public: |
2630 /// The source must be an Xmm register, since Dest is mem. | 2631 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { |
2631 template <class Machine> | 2632 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); |
2632 class InstX86StoreP final : public InstX86Base<Machine> { | 2633 } |
2633 InstX86StoreP() = delete; | 2634 void emit(const Cfg *Func) const override; |
2634 InstX86StoreP(const InstX86StoreP &) = delete; | 2635 void emitIAS(const Cfg *Func) const override; |
2635 InstX86StoreP &operator=(const InstX86StoreP &) = delete; | 2636 void dump(const Cfg *Func) const override; |
2636 | 2637 static bool classof(const Inst *Inst) { |
2637 public: | 2638 return InstX86Base::isClassof(Inst, InstX86Base::Ret); |
2638 static InstX86StoreP * | 2639 } |
2639 create(Cfg *Func, Variable *Value, | 2640 |
2640 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 2641 private: |
2641 return new (Func->allocate<InstX86StoreP>()) | 2642 InstX86Ret(Cfg *Func, Variable *Source); |
2642 InstX86StoreP(Func, Value, Mem); | 2643 }; |
2643 } | 2644 |
2644 void emit(const Cfg *Func) const override; | 2645 /// Conditional set-byte instruction. |
2645 void emitIAS(const Cfg *Func) const override; | 2646 class InstX86Setcc final : public InstX86Base { |
2646 void dump(const Cfg *Func) const override; | 2647 InstX86Setcc() = delete; |
2647 static bool classof(const Inst *Inst) { | 2648 InstX86Setcc(const InstX86Cmov &) = delete; |
2648 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreP); | 2649 InstX86Setcc &operator=(const InstX86Setcc &) = delete; |
2649 } | 2650 |
2650 | 2651 public: |
2651 private: | 2652 static InstX86Setcc *create(Cfg *Func, Variable *Dest, BrCond Cond) { |
2652 InstX86StoreP(Cfg *Func, Variable *Value, | 2653 return new (Func->allocate<InstX86Setcc>()) |
2653 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 2654 InstX86Setcc(Func, Dest, Cond); |
2654 }; | 2655 } |
2655 | 2656 void emit(const Cfg *Func) const override; |
2656 template <class Machine> | 2657 void emitIAS(const Cfg *Func) const override; |
2657 class InstX86StoreQ final : public InstX86Base<Machine> { | 2658 void dump(const Cfg *Func) const override; |
2658 InstX86StoreQ() = delete; | 2659 static bool classof(const Inst *Inst) { |
2659 InstX86StoreQ(const InstX86StoreQ &) = delete; | 2660 return InstX86Base::isClassof(Inst, InstX86Base::Setcc); |
2660 InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; | 2661 } |
2661 | 2662 |
2662 public: | 2663 private: |
2663 static InstX86StoreQ * | 2664 InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond); |
2664 create(Cfg *Func, Variable *Value, | 2665 |
2665 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 2666 const BrCond Condition; |
2666 return new (Func->allocate<InstX86StoreQ>()) | 2667 }; |
2667 InstX86StoreQ(Func, Value, Mem); | 2668 |
2668 } | 2669 /// Exchanging Add instruction. Exchanges the first operand (destination |
2669 void emit(const Cfg *Func) const override; | 2670 /// operand) with the second operand (source operand), then loads the sum of |
2670 void emitIAS(const Cfg *Func) const override; | 2671 /// the two values into the destination operand. The destination may be a |
2671 void dump(const Cfg *Func) const override; | 2672 /// register or memory, while the source must be a register. |
2672 static bool classof(const Inst *Inst) { | 2673 /// |
2673 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreQ); | 2674 /// Both the dest and source are updated. The caller should then insert a |
2674 } | 2675 /// FakeDef to reflect the second udpate. |
2675 | 2676 class InstX86Xadd final : public InstX86BaseLockable { |
2676 private: | 2677 InstX86Xadd() = delete; |
2677 InstX86StoreQ(Cfg *Func, Variable *Value, | 2678 InstX86Xadd(const InstX86Xadd &) = delete; |
2678 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 2679 InstX86Xadd &operator=(const InstX86Xadd &) = delete; |
2679 }; | 2680 |
2680 | 2681 public: |
2681 /// Nop instructions of varying length | 2682 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
2682 template <class Machine> class InstX86Nop final : public InstX86Base<Machine> { | 2683 bool Locked) { |
2683 InstX86Nop() = delete; | 2684 return new (Func->allocate<InstX86Xadd>()) |
2684 InstX86Nop(const InstX86Nop &) = delete; | 2685 InstX86Xadd(Func, Dest, Source, Locked); |
2685 InstX86Nop &operator=(const InstX86Nop &) = delete; | 2686 } |
2686 | 2687 void emit(const Cfg *Func) const override; |
2687 public: | 2688 void emitIAS(const Cfg *Func) const override; |
2688 // TODO: Replace with enum. | 2689 void dump(const Cfg *Func) const override; |
2689 using NopVariant = unsigned; | 2690 static bool classof(const Inst *Inst) { |
2690 | 2691 return InstX86Base::isClassof(Inst, InstX86Base::Xadd); |
2691 static InstX86Nop *create(Cfg *Func, NopVariant Variant) { | 2692 } |
2692 return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); | 2693 |
2693 } | 2694 private: |
2694 void emit(const Cfg *Func) const override; | 2695 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
2695 void emitIAS(const Cfg *Func) const override; | 2696 }; |
2696 void dump(const Cfg *Func) const override; | 2697 |
2697 static bool classof(const Inst *Inst) { | 2698 /// Exchange instruction. Exchanges the first operand (destination operand) |
2698 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Nop); | 2699 /// with the second operand (source operand). At least one of the operands |
2699 } | 2700 /// must be a register (and the other can be reg or mem). Both the Dest and |
2700 | 2701 /// Source are updated. If there is a memory operand, then the instruction is |
2701 private: | 2702 /// automatically "locked" without the need for a lock prefix. |
2702 InstX86Nop(Cfg *Func, SizeT Length); | 2703 class InstX86Xchg final : public InstX86Base { |
2703 | 2704 InstX86Xchg() = delete; |
2704 NopVariant Variant; | 2705 InstX86Xchg(const InstX86Xchg &) = delete; |
2705 }; | 2706 InstX86Xchg &operator=(const InstX86Xchg &) = delete; |
2706 | 2707 |
2707 /// Fld - load a value onto the x87 FP stack. | 2708 public: |
2708 template <class Machine> class InstX86Fld final : public InstX86Base<Machine> { | 2709 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |
2709 InstX86Fld() = delete; | 2710 return new (Func->allocate<InstX86Xchg>()) |
2710 InstX86Fld(const InstX86Fld &) = delete; | 2711 InstX86Xchg(Func, Dest, Source); |
2711 InstX86Fld &operator=(const InstX86Fld &) = delete; | 2712 } |
2712 | 2713 void emit(const Cfg *Func) const override; |
2713 public: | 2714 void emitIAS(const Cfg *Func) const override; |
2714 static InstX86Fld *create(Cfg *Func, Operand *Src) { | 2715 void dump(const Cfg *Func) const override; |
2715 return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); | 2716 static bool classof(const Inst *Inst) { |
2716 } | 2717 return InstX86Base::isClassof(Inst, InstX86Base::Xchg); |
2717 void emit(const Cfg *Func) const override; | 2718 } |
2718 void emitIAS(const Cfg *Func) const override; | 2719 |
2719 void dump(const Cfg *Func) const override; | 2720 private: |
2720 static bool classof(const Inst *Inst) { | 2721 InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); |
2721 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fld); | 2722 }; |
2722 } | 2723 |
2723 | 2724 /// Start marker for the Intel Architecture Code Analyzer. This is not an |
2724 private: | 2725 /// executable instruction and must only be used for analysis. |
2725 InstX86Fld(Cfg *Func, Operand *Src); | 2726 class InstX86IacaStart final : public InstX86Base { |
2726 }; | 2727 InstX86IacaStart() = delete; |
2727 | 2728 InstX86IacaStart(const InstX86IacaStart &) = delete; |
2728 /// Fstp - store x87 st(0) into memory and pop st(0). | 2729 InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; |
2729 template <class Machine> class InstX86Fstp final : public InstX86Base<Machine> { | 2730 |
2730 InstX86Fstp() = delete; | 2731 public: |
2731 InstX86Fstp(const InstX86Fstp &) = delete; | 2732 static InstX86IacaStart *create(Cfg *Func) { |
2732 InstX86Fstp &operator=(const InstX86Fstp &) = delete; | 2733 return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); |
2733 | 2734 } |
2734 public: | 2735 void emit(const Cfg *Func) const override; |
2735 static InstX86Fstp *create(Cfg *Func, Variable *Dest) { | 2736 void emitIAS(const Cfg *Func) const override; |
2736 return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); | 2737 void dump(const Cfg *Func) const override; |
2737 } | 2738 static bool classof(const Inst *Inst) { |
2738 void emit(const Cfg *Func) const override; | 2739 return InstX86Base::isClassof(Inst, InstX86Base::IacaStart); |
2739 void emitIAS(const Cfg *Func) const override; | 2740 } |
2740 void dump(const Cfg *Func) const override; | 2741 |
2741 static bool classof(const Inst *Inst) { | 2742 private: |
2742 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fstp); | 2743 InstX86IacaStart(Cfg *Func); |
2743 } | 2744 }; |
2744 | 2745 |
2745 private: | 2746 /// End marker for the Intel Architecture Code Analyzer. This is not an |
2746 InstX86Fstp(Cfg *Func, Variable *Dest); | 2747 /// executable instruction and must only be used for analysis. |
2747 }; | 2748 class InstX86IacaEnd final : public InstX86Base { |
2748 | 2749 InstX86IacaEnd() = delete; |
2749 template <class Machine> class InstX86Pop final : public InstX86Base<Machine> { | 2750 InstX86IacaEnd(const InstX86IacaEnd &) = delete; |
2750 InstX86Pop() = delete; | 2751 InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; |
2751 InstX86Pop(const InstX86Pop &) = delete; | 2752 |
2752 InstX86Pop &operator=(const InstX86Pop &) = delete; | 2753 public: |
2753 | 2754 static InstX86IacaEnd *create(Cfg *Func) { |
2754 public: | 2755 return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); |
2755 static InstX86Pop *create(Cfg *Func, Variable *Dest) { | 2756 } |
2756 return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); | 2757 void emit(const Cfg *Func) const override; |
2757 } | 2758 void emitIAS(const Cfg *Func) const override; |
2758 void emit(const Cfg *Func) const override; | 2759 void dump(const Cfg *Func) const override; |
2759 void emitIAS(const Cfg *Func) const override; | 2760 static bool classof(const Inst *Inst) { |
2760 void dump(const Cfg *Func) const override; | 2761 return InstX86Base::isClassof(Inst, InstX86Base::IacaEnd); |
2761 static bool classof(const Inst *Inst) { | 2762 } |
2762 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Pop); | 2763 |
2763 } | 2764 private: |
2764 | 2765 InstX86IacaEnd(Cfg *Func); |
2765 private: | 2766 }; |
2766 InstX86Pop(Cfg *Func, Variable *Dest); | 2767 }; // struct InstImpl |
2767 }; | |
2768 | |
2769 template <class Machine> class InstX86Push final : public InstX86Base<Machine> { | |
2770 InstX86Push() = delete; | |
2771 InstX86Push(const InstX86Push &) = delete; | |
2772 InstX86Push &operator=(const InstX86Push &) = delete; | |
2773 | |
2774 public: | |
2775 static InstX86Push *create(Cfg *Func, Variable *Source) { | |
2776 return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); | |
2777 } | |
2778 void emit(const Cfg *Func) const override; | |
2779 void emitIAS(const Cfg *Func) const override; | |
2780 void dump(const Cfg *Func) const override; | |
2781 static bool classof(const Inst *Inst) { | |
2782 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Push); | |
2783 } | |
2784 | |
2785 private: | |
2786 InstX86Push(Cfg *Func, Variable *Source); | |
2787 }; | |
2788 | |
2789 /// Ret instruction. Currently only supports the "ret" version that does not pop | |
2790 /// arguments. This instruction takes a Source operand (for non-void returning | |
2791 /// functions) for liveness analysis, though a FakeUse before the ret would do | |
2792 /// just as well. | |
2793 template <class Machine> class InstX86Ret final : public InstX86Base<Machine> { | |
2794 InstX86Ret() = delete; | |
2795 InstX86Ret(const InstX86Ret &) = delete; | |
2796 InstX86Ret &operator=(const InstX86Ret &) = delete; | |
2797 | |
2798 public: | |
2799 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { | |
2800 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); | |
2801 } | |
2802 void emit(const Cfg *Func) const override; | |
2803 void emitIAS(const Cfg *Func) const override; | |
2804 void dump(const Cfg *Func) const override; | |
2805 static bool classof(const Inst *Inst) { | |
2806 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ret); | |
2807 } | |
2808 | |
2809 private: | |
2810 InstX86Ret(Cfg *Func, Variable *Source); | |
2811 }; | |
2812 | |
2813 /// Conditional set-byte instruction. | |
2814 template <class Machine> | |
2815 class InstX86Setcc final : public InstX86Base<Machine> { | |
2816 InstX86Setcc() = delete; | |
2817 InstX86Setcc(const InstX86Cmov<Machine> &) = delete; | |
2818 InstX86Setcc &operator=(const InstX86Setcc &) = delete; | |
2819 | |
2820 public: | |
2821 static InstX86Setcc * | |
2822 create(Cfg *Func, Variable *Dest, | |
2823 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | |
2824 return new (Func->allocate<InstX86Setcc>()) InstX86Setcc(Func, Dest, Cond); | |
2825 } | |
2826 void emit(const Cfg *Func) const override; | |
2827 void emitIAS(const Cfg *Func) const override; | |
2828 void dump(const Cfg *Func) const override; | |
2829 static bool classof(const Inst *Inst) { | |
2830 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Setcc); | |
2831 } | |
2832 | |
2833 private: | |
2834 InstX86Setcc(Cfg *Func, Variable *Dest, | |
2835 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | |
2836 | |
2837 const typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | |
2838 }; | |
2839 | |
2840 /// Exchanging Add instruction. Exchanges the first operand (destination | |
2841 /// operand) with the second operand (source operand), then loads the sum of the | |
2842 /// two values into the destination operand. The destination may be a register | |
2843 /// or memory, while the source must be a register. | |
2844 /// | |
2845 /// Both the dest and source are updated. The caller should then insert a | |
2846 /// FakeDef to reflect the second udpate. | |
2847 template <class Machine> | |
2848 class InstX86Xadd final : public InstX86BaseLockable<Machine> { | |
2849 InstX86Xadd() = delete; | |
2850 InstX86Xadd(const InstX86Xadd &) = delete; | |
2851 InstX86Xadd &operator=(const InstX86Xadd &) = delete; | |
2852 | |
2853 public: | |
2854 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | |
2855 bool Locked) { | |
2856 return new (Func->allocate<InstX86Xadd>()) | |
2857 InstX86Xadd(Func, Dest, Source, Locked); | |
2858 } | |
2859 void emit(const Cfg *Func) const override; | |
2860 void emitIAS(const Cfg *Func) const override; | |
2861 void dump(const Cfg *Func) const override; | |
2862 static bool classof(const Inst *Inst) { | |
2863 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xadd); | |
2864 } | |
2865 | |
2866 private: | |
2867 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | |
2868 }; | |
2869 | |
2870 /// Exchange instruction. Exchanges the first operand (destination operand) with | |
2871 /// the second operand (source operand). At least one of the operands must be a | |
2872 /// register (and the other can be reg or mem). Both the Dest and Source are | |
2873 /// updated. If there is a memory operand, then the instruction is automatically | |
2874 /// "locked" without the need for a lock prefix. | |
2875 template <class Machine> class InstX86Xchg final : public InstX86Base<Machine> { | |
2876 InstX86Xchg() = delete; | |
2877 InstX86Xchg(const InstX86Xchg &) = delete; | |
2878 InstX86Xchg &operator=(const InstX86Xchg &) = delete; | |
2879 | |
2880 public: | |
2881 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | |
2882 return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); | |
2883 } | |
2884 void emit(const Cfg *Func) const override; | |
2885 void emitIAS(const Cfg *Func) const override; | |
2886 void dump(const Cfg *Func) const override; | |
2887 static bool classof(const Inst *Inst) { | |
2888 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xchg); | |
2889 } | |
2890 | |
2891 private: | |
2892 InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); | |
2893 }; | |
2894 | |
2895 /// Start marker for the Intel Architecture Code Analyzer. This is not an | |
2896 /// executable instruction and must only be used for analysis. | |
2897 template <class Machine> | |
2898 class InstX86IacaStart final : public InstX86Base<Machine> { | |
2899 InstX86IacaStart() = delete; | |
2900 InstX86IacaStart(const InstX86IacaStart &) = delete; | |
2901 InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; | |
2902 | |
2903 public: | |
2904 static InstX86IacaStart *create(Cfg *Func) { | |
2905 return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); | |
2906 } | |
2907 void emit(const Cfg *Func) const override; | |
2908 void emitIAS(const Cfg *Func) const override; | |
2909 void dump(const Cfg *Func) const override; | |
2910 static bool classof(const Inst *Inst) { | |
2911 return InstX86Base<Machine>::isClassof(Inst, | |
2912 InstX86Base<Machine>::IacaStart); | |
2913 } | |
2914 | |
2915 private: | |
2916 InstX86IacaStart(Cfg *Func); | |
2917 }; | |
2918 | |
2919 /// End marker for the Intel Architecture Code Analyzer. This is not an | |
2920 /// executable instruction and must only be used for analysis. | |
2921 template <class Machine> | |
2922 class InstX86IacaEnd final : public InstX86Base<Machine> { | |
2923 InstX86IacaEnd() = delete; | |
2924 InstX86IacaEnd(const InstX86IacaEnd &) = delete; | |
2925 InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; | |
2926 | |
2927 public: | |
2928 static InstX86IacaEnd *create(Cfg *Func) { | |
2929 return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); | |
2930 } | |
2931 void emit(const Cfg *Func) const override; | |
2932 void emitIAS(const Cfg *Func) const override; | |
2933 void dump(const Cfg *Func) const override; | |
2934 static bool classof(const Inst *Inst) { | |
2935 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::IacaEnd); | |
2936 } | |
2937 | |
2938 private: | |
2939 InstX86IacaEnd(Cfg *Func); | |
2940 }; | |
2941 | 2768 |
2942 /// struct Insts is a template that can be used to instantiate all the X86 | 2769 /// struct Insts is a template that can be used to instantiate all the X86 |
2943 /// instructions for a target with a simple | 2770 /// instructions for a target with a simple |
2944 /// | 2771 /// |
2945 /// using Insts = ::Ice::X86Internal::Insts<TargeT>; | 2772 /// using Insts = ::Ice::X86NAMESPACE::Insts<TraitsType>; |
2946 template <class Machine> struct Insts { | 2773 template <typename TraitsType> struct Insts { |
2947 using FakeRMW = InstX86FakeRMW<Machine>; | 2774 using FakeRMW = typename InstImpl<TraitsType>::InstX86FakeRMW; |
2948 using Label = InstX86Label<Machine>; | 2775 using Label = typename InstImpl<TraitsType>::InstX86Label; |
2949 | 2776 |
2950 using Call = InstX86Call<Machine>; | 2777 using Call = typename InstImpl<TraitsType>::InstX86Call; |
2951 | 2778 |
2952 using Br = InstX86Br<Machine>; | 2779 using Br = typename InstImpl<TraitsType>::InstX86Br; |
2953 using Jmp = InstX86Jmp<Machine>; | 2780 using Jmp = typename InstImpl<TraitsType>::InstX86Jmp; |
2954 using Bswap = InstX86Bswap<Machine>; | 2781 using Bswap = typename InstImpl<TraitsType>::InstX86Bswap; |
2955 using Neg = InstX86Neg<Machine>; | 2782 using Neg = typename InstImpl<TraitsType>::InstX86Neg; |
2956 using Bsf = InstX86Bsf<Machine>; | 2783 using Bsf = typename InstImpl<TraitsType>::InstX86Bsf; |
2957 using Bsr = InstX86Bsr<Machine>; | 2784 using Bsr = typename InstImpl<TraitsType>::InstX86Bsr; |
2958 using Lea = InstX86Lea<Machine>; | 2785 using Lea = typename InstImpl<TraitsType>::InstX86Lea; |
2959 using Cbwdq = InstX86Cbwdq<Machine>; | 2786 using Cbwdq = typename InstImpl<TraitsType>::InstX86Cbwdq; |
2960 using Movsx = InstX86Movsx<Machine>; | 2787 using Movsx = typename InstImpl<TraitsType>::InstX86Movsx; |
2961 using Movzx = InstX86Movzx<Machine>; | 2788 using Movzx = typename InstImpl<TraitsType>::InstX86Movzx; |
2962 using Movd = InstX86Movd<Machine>; | 2789 using Movd = typename InstImpl<TraitsType>::InstX86Movd; |
2963 using Sqrtss = InstX86Sqrtss<Machine>; | 2790 using Sqrtss = typename InstImpl<TraitsType>::InstX86Sqrtss; |
2964 using Mov = InstX86Mov<Machine>; | 2791 using Mov = typename InstImpl<TraitsType>::InstX86Mov; |
2965 using Movp = InstX86Movp<Machine>; | 2792 using Movp = typename InstImpl<TraitsType>::InstX86Movp; |
2966 using Movq = InstX86Movq<Machine>; | 2793 using Movq = typename InstImpl<TraitsType>::InstX86Movq; |
2967 using Add = InstX86Add<Machine>; | 2794 using Add = typename InstImpl<TraitsType>::InstX86Add; |
2968 using AddRMW = InstX86AddRMW<Machine>; | 2795 using AddRMW = typename InstImpl<TraitsType>::InstX86AddRMW; |
2969 using Addps = InstX86Addps<Machine>; | 2796 using Addps = typename InstImpl<TraitsType>::InstX86Addps; |
2970 using Adc = InstX86Adc<Machine>; | 2797 using Adc = typename InstImpl<TraitsType>::InstX86Adc; |
2971 using AdcRMW = InstX86AdcRMW<Machine>; | 2798 using AdcRMW = typename InstImpl<TraitsType>::InstX86AdcRMW; |
2972 using Addss = InstX86Addss<Machine>; | 2799 using Addss = typename InstImpl<TraitsType>::InstX86Addss; |
2973 using Andnps = InstX86Andnps<Machine>; | 2800 using Andnps = typename InstImpl<TraitsType>::InstX86Andnps; |
2974 using Andps = InstX86Andps<Machine>; | 2801 using Andps = typename InstImpl<TraitsType>::InstX86Andps; |
2975 using Padd = InstX86Padd<Machine>; | 2802 using Padd = typename InstImpl<TraitsType>::InstX86Padd; |
2976 using Sub = InstX86Sub<Machine>; | 2803 using Sub = typename InstImpl<TraitsType>::InstX86Sub; |
2977 using SubRMW = InstX86SubRMW<Machine>; | 2804 using SubRMW = typename InstImpl<TraitsType>::InstX86SubRMW; |
2978 using Subps = InstX86Subps<Machine>; | 2805 using Subps = typename InstImpl<TraitsType>::InstX86Subps; |
2979 using Subss = InstX86Subss<Machine>; | 2806 using Subss = typename InstImpl<TraitsType>::InstX86Subss; |
2980 using Sbb = InstX86Sbb<Machine>; | 2807 using Sbb = typename InstImpl<TraitsType>::InstX86Sbb; |
2981 using SbbRMW = InstX86SbbRMW<Machine>; | 2808 using SbbRMW = typename InstImpl<TraitsType>::InstX86SbbRMW; |
2982 using Psub = InstX86Psub<Machine>; | 2809 using Psub = typename InstImpl<TraitsType>::InstX86Psub; |
2983 using And = InstX86And<Machine>; | 2810 using And = typename InstImpl<TraitsType>::InstX86And; |
2984 using AndRMW = InstX86AndRMW<Machine>; | 2811 using AndRMW = typename InstImpl<TraitsType>::InstX86AndRMW; |
2985 using Pand = InstX86Pand<Machine>; | 2812 using Pand = typename InstImpl<TraitsType>::InstX86Pand; |
2986 using Pandn = InstX86Pandn<Machine>; | 2813 using Pandn = typename InstImpl<TraitsType>::InstX86Pandn; |
2987 using Or = InstX86Or<Machine>; | 2814 using Or = typename InstImpl<TraitsType>::InstX86Or; |
2988 using Orps = InstX86Orps<Machine>; | 2815 using Orps = typename InstImpl<TraitsType>::InstX86Orps; |
2989 using OrRMW = InstX86OrRMW<Machine>; | 2816 using OrRMW = typename InstImpl<TraitsType>::InstX86OrRMW; |
2990 using Por = InstX86Por<Machine>; | 2817 using Por = typename InstImpl<TraitsType>::InstX86Por; |
2991 using Xor = InstX86Xor<Machine>; | 2818 using Xor = typename InstImpl<TraitsType>::InstX86Xor; |
2992 using Xorps = InstX86Xorps<Machine>; | 2819 using Xorps = typename InstImpl<TraitsType>::InstX86Xorps; |
2993 using XorRMW = InstX86XorRMW<Machine>; | 2820 using XorRMW = typename InstImpl<TraitsType>::InstX86XorRMW; |
2994 using Pxor = InstX86Pxor<Machine>; | 2821 using Pxor = typename InstImpl<TraitsType>::InstX86Pxor; |
2995 using Maxss = InstX86Maxss<Machine>; | 2822 using Maxss = typename InstImpl<TraitsType>::InstX86Maxss; |
2996 using Minss = InstX86Minss<Machine>; | 2823 using Minss = typename InstImpl<TraitsType>::InstX86Minss; |
2997 using Imul = InstX86Imul<Machine>; | 2824 using Imul = typename InstImpl<TraitsType>::InstX86Imul; |
2998 using ImulImm = InstX86ImulImm<Machine>; | 2825 using ImulImm = typename InstImpl<TraitsType>::InstX86ImulImm; |
2999 using Mulps = InstX86Mulps<Machine>; | 2826 using Mulps = typename InstImpl<TraitsType>::InstX86Mulps; |
3000 using Mulss = InstX86Mulss<Machine>; | 2827 using Mulss = typename InstImpl<TraitsType>::InstX86Mulss; |
3001 using Pmull = InstX86Pmull<Machine>; | 2828 using Pmull = typename InstImpl<TraitsType>::InstX86Pmull; |
3002 using Pmuludq = InstX86Pmuludq<Machine>; | 2829 using Pmuludq = typename InstImpl<TraitsType>::InstX86Pmuludq; |
3003 using Divps = InstX86Divps<Machine>; | 2830 using Divps = typename InstImpl<TraitsType>::InstX86Divps; |
3004 using Divss = InstX86Divss<Machine>; | 2831 using Divss = typename InstImpl<TraitsType>::InstX86Divss; |
3005 using Rol = InstX86Rol<Machine>; | 2832 using Rol = typename InstImpl<TraitsType>::InstX86Rol; |
3006 using Shl = InstX86Shl<Machine>; | 2833 using Shl = typename InstImpl<TraitsType>::InstX86Shl; |
3007 using Psll = InstX86Psll<Machine>; | 2834 using Psll = typename InstImpl<TraitsType>::InstX86Psll; |
3008 using Psrl = InstX86Psrl<Machine>; | 2835 using Psrl = typename InstImpl<TraitsType>::InstX86Psrl; |
3009 using Shr = InstX86Shr<Machine>; | 2836 using Shr = typename InstImpl<TraitsType>::InstX86Shr; |
3010 using Sar = InstX86Sar<Machine>; | 2837 using Sar = typename InstImpl<TraitsType>::InstX86Sar; |
3011 using Psra = InstX86Psra<Machine>; | 2838 using Psra = typename InstImpl<TraitsType>::InstX86Psra; |
3012 using Pcmpeq = InstX86Pcmpeq<Machine>; | 2839 using Pcmpeq = typename InstImpl<TraitsType>::InstX86Pcmpeq; |
3013 using Pcmpgt = InstX86Pcmpgt<Machine>; | 2840 using Pcmpgt = typename InstImpl<TraitsType>::InstX86Pcmpgt; |
3014 using MovssRegs = InstX86MovssRegs<Machine>; | 2841 using MovssRegs = typename InstImpl<TraitsType>::InstX86MovssRegs; |
3015 using Idiv = InstX86Idiv<Machine>; | 2842 using Idiv = typename InstImpl<TraitsType>::InstX86Idiv; |
3016 using Div = InstX86Div<Machine>; | 2843 using Div = typename InstImpl<TraitsType>::InstX86Div; |
3017 using Insertps = InstX86Insertps<Machine>; | 2844 using Insertps = typename InstImpl<TraitsType>::InstX86Insertps; |
3018 using Pinsr = InstX86Pinsr<Machine>; | 2845 using Pinsr = typename InstImpl<TraitsType>::InstX86Pinsr; |
3019 using Shufps = InstX86Shufps<Machine>; | 2846 using Shufps = typename InstImpl<TraitsType>::InstX86Shufps; |
3020 using Blendvps = InstX86Blendvps<Machine>; | 2847 using Blendvps = typename InstImpl<TraitsType>::InstX86Blendvps; |
3021 using Pblendvb = InstX86Pblendvb<Machine>; | 2848 using Pblendvb = typename InstImpl<TraitsType>::InstX86Pblendvb; |
3022 using Pextr = InstX86Pextr<Machine>; | 2849 using Pextr = typename InstImpl<TraitsType>::InstX86Pextr; |
3023 using Pshufd = InstX86Pshufd<Machine>; | 2850 using Pshufd = typename InstImpl<TraitsType>::InstX86Pshufd; |
3024 using Lockable = InstX86BaseLockable<Machine>; | 2851 using Lockable = typename InstImpl<TraitsType>::InstX86BaseLockable; |
3025 using Mul = InstX86Mul<Machine>; | 2852 using Mul = typename InstImpl<TraitsType>::InstX86Mul; |
3026 using Shld = InstX86Shld<Machine>; | 2853 using Shld = typename InstImpl<TraitsType>::InstX86Shld; |
3027 using Shrd = InstX86Shrd<Machine>; | 2854 using Shrd = typename InstImpl<TraitsType>::InstX86Shrd; |
3028 using Cmov = InstX86Cmov<Machine>; | 2855 using Cmov = typename InstImpl<TraitsType>::InstX86Cmov; |
3029 using Cmpps = InstX86Cmpps<Machine>; | 2856 using Cmpps = typename InstImpl<TraitsType>::InstX86Cmpps; |
3030 using Cmpxchg = InstX86Cmpxchg<Machine>; | 2857 using Cmpxchg = typename InstImpl<TraitsType>::InstX86Cmpxchg; |
3031 using Cmpxchg8b = InstX86Cmpxchg8b<Machine>; | 2858 using Cmpxchg8b = typename InstImpl<TraitsType>::InstX86Cmpxchg8b; |
3032 using Cvt = InstX86Cvt<Machine>; | 2859 using Cvt = typename InstImpl<TraitsType>::InstX86Cvt; |
3033 using Icmp = InstX86Icmp<Machine>; | 2860 using Icmp = typename InstImpl<TraitsType>::InstX86Icmp; |
3034 using Ucomiss = InstX86Ucomiss<Machine>; | 2861 using Ucomiss = typename InstImpl<TraitsType>::InstX86Ucomiss; |
3035 using UD2 = InstX86UD2<Machine>; | 2862 using UD2 = typename InstImpl<TraitsType>::InstX86UD2; |
3036 using Test = InstX86Test<Machine>; | 2863 using Test = typename InstImpl<TraitsType>::InstX86Test; |
3037 using Mfence = InstX86Mfence<Machine>; | 2864 using Mfence = typename InstImpl<TraitsType>::InstX86Mfence; |
3038 using Store = InstX86Store<Machine>; | 2865 using Store = typename InstImpl<TraitsType>::InstX86Store; |
3039 using StoreP = InstX86StoreP<Machine>; | 2866 using StoreP = typename InstImpl<TraitsType>::InstX86StoreP; |
3040 using StoreQ = InstX86StoreQ<Machine>; | 2867 using StoreQ = typename InstImpl<TraitsType>::InstX86StoreQ; |
3041 using Nop = InstX86Nop<Machine>; | 2868 using Nop = typename InstImpl<TraitsType>::InstX86Nop; |
3042 template <typename T = typename InstX86Base<Machine>::Traits> | 2869 template <typename T = typename InstImpl<TraitsType>::Traits> |
3043 using Fld = typename std::enable_if<T::UsesX87, InstX86Fld<Machine>>::type; | 2870 using Fld = |
3044 template <typename T = typename InstX86Base<Machine>::Traits> | 2871 typename std::enable_if<T::UsesX87, |
3045 using Fstp = typename std::enable_if<T::UsesX87, InstX86Fstp<Machine>>::type; | 2872 typename InstImpl<TraitsType>::InstX86Fld>::type; |
3046 using Pop = InstX86Pop<Machine>; | 2873 template <typename T = typename InstImpl<TraitsType>::Traits> |
3047 using Push = InstX86Push<Machine>; | 2874 using Fstp = |
3048 using Ret = InstX86Ret<Machine>; | 2875 typename std::enable_if<T::UsesX87, |
3049 using Setcc = InstX86Setcc<Machine>; | 2876 typename InstImpl<TraitsType>::InstX86Fstp>::type; |
3050 using Xadd = InstX86Xadd<Machine>; | 2877 using Pop = typename InstImpl<TraitsType>::InstX86Pop; |
3051 using Xchg = InstX86Xchg<Machine>; | 2878 using Push = typename InstImpl<TraitsType>::InstX86Push; |
3052 | 2879 using Ret = typename InstImpl<TraitsType>::InstX86Ret; |
3053 using IacaStart = InstX86IacaStart<Machine>; | 2880 using Setcc = typename InstImpl<TraitsType>::InstX86Setcc; |
3054 using IacaEnd = InstX86IacaEnd<Machine>; | 2881 using Xadd = typename InstImpl<TraitsType>::InstX86Xadd; |
2882 using Xchg = typename InstImpl<TraitsType>::InstX86Xchg; | |
2883 | |
2884 using IacaStart = typename InstImpl<TraitsType>::InstX86IacaStart; | |
2885 using IacaEnd = typename InstImpl<TraitsType>::InstX86IacaEnd; | |
3055 }; | 2886 }; |
3056 | 2887 |
3057 /// X86 Instructions have static data (particularly, opcodes and instruction | 2888 /// X86 Instructions have static data (particularly, opcodes and instruction |
3058 /// emitters). Each X86 target needs to define all of these, so this macro is | 2889 /// emitters). Each X86 target needs to define all of these, so this macro is |
3059 /// provided so that, if something changes, then all X86 targets will be updated | 2890 /// provided so that, if something changes, then all X86 targets will be updated |
3060 /// automatically. | 2891 /// automatically. |
3061 #define X86INSTS_DEFINE_STATIC_DATA(Machine) \ | 2892 #define X86INSTS_DEFINE_STATIC_DATA(X86NAMESPACE, TraitsType) \ |
3062 namespace Ice { \ | 2893 namespace Ice { \ |
3063 namespace X86Internal { \ | 2894 namespace X86NAMESPACE { \ |
3064 /* In-place ops */ \ | 2895 /* In-place ops */ \ |
3065 template <> const char *InstX86Bswap<Machine>::Base::Opcode = "bswap"; \ | 2896 template <> \ |
3066 template <> const char *InstX86Neg<Machine>::Base::Opcode = "neg"; \ | 2897 template <> \ |
2898 const char *InstImpl<TraitsType>::InstX86Bswap::Base::Opcode = "bswap"; \ | |
2899 template <> \ | |
2900 template <> \ | |
2901 const char *InstImpl<TraitsType>::InstX86Neg::Base::Opcode = "neg"; \ | |
3067 /* Unary ops */ \ | 2902 /* Unary ops */ \ |
3068 template <> const char *InstX86Bsf<Machine>::Base::Opcode = "bsf"; \ | 2903 template <> \ |
3069 template <> const char *InstX86Bsr<Machine>::Base::Opcode = "bsr"; \ | 2904 template <> \ |
3070 template <> const char *InstX86Lea<Machine>::Base::Opcode = "lea"; \ | 2905 const char *InstImpl<TraitsType>::InstX86Bsf::Base::Opcode = "bsf"; \ |
3071 template <> const char *InstX86Movd<Machine>::Base::Opcode = "movd"; \ | 2906 template <> \ |
3072 template <> const char *InstX86Movsx<Machine>::Base::Opcode = "movs"; \ | 2907 template <> \ |
3073 template <> const char *InstX86Movzx<Machine>::Base::Opcode = "movz"; \ | 2908 const char *InstImpl<TraitsType>::InstX86Bsr::Base::Opcode = "bsr"; \ |
3074 template <> const char *InstX86Sqrtss<Machine>::Base::Opcode = "sqrtss"; \ | 2909 template <> \ |
3075 template <> const char *InstX86Cbwdq<Machine>::Base::Opcode = "cbw/cwd/cdq"; \ | 2910 template <> \ |
2911 const char *InstImpl<TraitsType>::InstX86Lea::Base::Opcode = "lea"; \ | |
2912 template <> \ | |
2913 template <> \ | |
2914 const char *InstImpl<TraitsType>::InstX86Movd::Base::Opcode = "movd"; \ | |
2915 template <> \ | |
2916 template <> \ | |
2917 const char *InstImpl<TraitsType>::InstX86Movsx::Base::Opcode = "movs"; \ | |
2918 template <> \ | |
2919 template <> \ | |
2920 const char *InstImpl<TraitsType>::InstX86Movzx::Base::Opcode = "movz"; \ | |
2921 template <> \ | |
2922 template <> \ | |
2923 const char *InstImpl<TraitsType>::InstX86Sqrtss::Base::Opcode = "sqrtss"; \ | |
2924 template <> \ | |
2925 template <> \ | |
2926 const char *InstImpl<TraitsType>::InstX86Cbwdq::Base::Opcode = \ | |
2927 "cbw/cwd/cdq"; \ | |
3076 /* Mov-like ops */ \ | 2928 /* Mov-like ops */ \ |
3077 template <> const char *InstX86Mov<Machine>::Base::Opcode = "mov"; \ | 2929 template <> \ |
3078 template <> const char *InstX86Movp<Machine>::Base::Opcode = "movups"; \ | 2930 template <> \ |
3079 template <> const char *InstX86Movq<Machine>::Base::Opcode = "movq"; \ | 2931 const char *InstImpl<TraitsType>::InstX86Mov::Base::Opcode = "mov"; \ |
2932 template <> \ | |
2933 template <> \ | |
2934 const char *InstImpl<TraitsType>::InstX86Movp::Base::Opcode = "movups"; \ | |
2935 template <> \ | |
2936 template <> \ | |
2937 const char *InstImpl<TraitsType>::InstX86Movq::Base::Opcode = "movq"; \ | |
3080 /* Binary ops */ \ | 2938 /* Binary ops */ \ |
3081 template <> const char *InstX86Add<Machine>::Base::Opcode = "add"; \ | 2939 template <> \ |
3082 template <> const char *InstX86AddRMW<Machine>::Base::Opcode = "add"; \ | 2940 template <> \ |
3083 template <> const char *InstX86Addps<Machine>::Base::Opcode = "add"; \ | 2941 const char *InstImpl<TraitsType>::InstX86Add::Base::Opcode = "add"; \ |
3084 template <> const char *InstX86Adc<Machine>::Base::Opcode = "adc"; \ | 2942 template <> \ |
3085 template <> const char *InstX86AdcRMW<Machine>::Base::Opcode = "adc"; \ | 2943 template <> \ |
3086 template <> const char *InstX86Addss<Machine>::Base::Opcode = "add"; \ | 2944 const char *InstImpl<TraitsType>::InstX86AddRMW::Base::Opcode = "add"; \ |
3087 template <> const char *InstX86Andnps<Machine>::Base::Opcode = "andn"; \ | 2945 template <> \ |
3088 template <> const char *InstX86Andps<Machine>::Base::Opcode = "and"; \ | 2946 template <> \ |
3089 template <> const char *InstX86Maxss<Machine>::Base::Opcode = "max"; \ | 2947 const char *InstImpl<TraitsType>::InstX86Addps::Base::Opcode = "add"; \ |
3090 template <> const char *InstX86Minss<Machine>::Base::Opcode = "min"; \ | 2948 template <> \ |
3091 template <> const char *InstX86Padd<Machine>::Base::Opcode = "padd"; \ | 2949 template <> \ |
3092 template <> const char *InstX86Sub<Machine>::Base::Opcode = "sub"; \ | 2950 const char *InstImpl<TraitsType>::InstX86Adc::Base::Opcode = "adc"; \ |
3093 template <> const char *InstX86SubRMW<Machine>::Base::Opcode = "sub"; \ | 2951 template <> \ |
3094 template <> const char *InstX86Subps<Machine>::Base::Opcode = "sub"; \ | 2952 template <> \ |
3095 template <> const char *InstX86Subss<Machine>::Base::Opcode = "sub"; \ | 2953 const char *InstImpl<TraitsType>::InstX86AdcRMW::Base::Opcode = "adc"; \ |
3096 template <> const char *InstX86Sbb<Machine>::Base::Opcode = "sbb"; \ | 2954 template <> \ |
3097 template <> const char *InstX86SbbRMW<Machine>::Base::Opcode = "sbb"; \ | 2955 template <> \ |
3098 template <> const char *InstX86Psub<Machine>::Base::Opcode = "psub"; \ | 2956 const char *InstImpl<TraitsType>::InstX86Addss::Base::Opcode = "add"; \ |
3099 template <> const char *InstX86And<Machine>::Base::Opcode = "and"; \ | 2957 template <> \ |
3100 template <> const char *InstX86AndRMW<Machine>::Base::Opcode = "and"; \ | 2958 template <> \ |
3101 template <> const char *InstX86Pand<Machine>::Base::Opcode = "pand"; \ | 2959 const char *InstImpl<TraitsType>::InstX86Andnps::Base::Opcode = "andn"; \ |
3102 template <> const char *InstX86Pandn<Machine>::Base::Opcode = "pandn"; \ | 2960 template <> \ |
3103 template <> const char *InstX86Or<Machine>::Base::Opcode = "or"; \ | 2961 template <> \ |
3104 template <> const char *InstX86Orps<Machine>::Base::Opcode = "or"; \ | 2962 const char *InstImpl<TraitsType>::InstX86Andps::Base::Opcode = "and"; \ |
3105 template <> const char *InstX86OrRMW<Machine>::Base::Opcode = "or"; \ | 2963 template <> \ |
3106 template <> const char *InstX86Por<Machine>::Base::Opcode = "por"; \ | 2964 template <> \ |
3107 template <> const char *InstX86Xor<Machine>::Base::Opcode = "xor"; \ | 2965 const char *InstImpl<TraitsType>::InstX86Maxss::Base::Opcode = "max"; \ |
3108 template <> const char *InstX86Xorps<Machine>::Base::Opcode = "xor"; \ | 2966 template <> \ |
3109 template <> const char *InstX86XorRMW<Machine>::Base::Opcode = "xor"; \ | 2967 template <> \ |
3110 template <> const char *InstX86Pxor<Machine>::Base::Opcode = "pxor"; \ | 2968 const char *InstImpl<TraitsType>::InstX86Minss::Base::Opcode = "min"; \ |
3111 template <> const char *InstX86Imul<Machine>::Base::Opcode = "imul"; \ | 2969 template <> \ |
3112 template <> const char *InstX86ImulImm<Machine>::Base::Opcode = "imul"; \ | 2970 template <> \ |
3113 template <> const char *InstX86Mulps<Machine>::Base::Opcode = "mul"; \ | 2971 const char *InstImpl<TraitsType>::InstX86Padd::Base::Opcode = "padd"; \ |
3114 template <> const char *InstX86Mulss<Machine>::Base::Opcode = "mul"; \ | 2972 template <> \ |
3115 template <> const char *InstX86Pmull<Machine>::Base::Opcode = "pmull"; \ | 2973 template <> \ |
3116 template <> const char *InstX86Pmuludq<Machine>::Base::Opcode = "pmuludq"; \ | 2974 const char *InstImpl<TraitsType>::InstX86Sub::Base::Opcode = "sub"; \ |
3117 template <> const char *InstX86Div<Machine>::Base::Opcode = "div"; \ | 2975 template <> \ |
3118 template <> const char *InstX86Divps<Machine>::Base::Opcode = "div"; \ | 2976 template <> \ |
3119 template <> const char *InstX86Divss<Machine>::Base::Opcode = "div"; \ | 2977 const char *InstImpl<TraitsType>::InstX86SubRMW::Base::Opcode = "sub"; \ |
3120 template <> const char *InstX86Idiv<Machine>::Base::Opcode = "idiv"; \ | 2978 template <> \ |
3121 template <> const char *InstX86Rol<Machine>::Base::Opcode = "rol"; \ | 2979 template <> \ |
3122 template <> const char *InstX86Shl<Machine>::Base::Opcode = "shl"; \ | 2980 const char *InstImpl<TraitsType>::InstX86Subps::Base::Opcode = "sub"; \ |
3123 template <> const char *InstX86Psll<Machine>::Base::Opcode = "psll"; \ | 2981 template <> \ |
3124 template <> const char *InstX86Shr<Machine>::Base::Opcode = "shr"; \ | 2982 template <> \ |
3125 template <> const char *InstX86Sar<Machine>::Base::Opcode = "sar"; \ | 2983 const char *InstImpl<TraitsType>::InstX86Subss::Base::Opcode = "sub"; \ |
3126 template <> const char *InstX86Psra<Machine>::Base::Opcode = "psra"; \ | 2984 template <> \ |
3127 template <> const char *InstX86Psrl<Machine>::Base::Opcode = "psrl"; \ | 2985 template <> \ |
3128 template <> const char *InstX86Pcmpeq<Machine>::Base::Opcode = "pcmpeq"; \ | 2986 const char *InstImpl<TraitsType>::InstX86Sbb::Base::Opcode = "sbb"; \ |
3129 template <> const char *InstX86Pcmpgt<Machine>::Base::Opcode = "pcmpgt"; \ | 2987 template <> \ |
3130 template <> const char *InstX86MovssRegs<Machine>::Base::Opcode = "movss"; \ | 2988 template <> \ |
2989 const char *InstImpl<TraitsType>::InstX86SbbRMW::Base::Opcode = "sbb"; \ | |
2990 template <> \ | |
2991 template <> \ | |
2992 const char *InstImpl<TraitsType>::InstX86Psub::Base::Opcode = "psub"; \ | |
2993 template <> \ | |
2994 template <> \ | |
2995 const char *InstImpl<TraitsType>::InstX86And::Base::Opcode = "and"; \ | |
2996 template <> \ | |
2997 template <> \ | |
2998 const char *InstImpl<TraitsType>::InstX86AndRMW::Base::Opcode = "and"; \ | |
2999 template <> \ | |
3000 template <> \ | |
3001 const char *InstImpl<TraitsType>::InstX86Pand::Base::Opcode = "pand"; \ | |
3002 template <> \ | |
3003 template <> \ | |
3004 const char *InstImpl<TraitsType>::InstX86Pandn::Base::Opcode = "pandn"; \ | |
3005 template <> \ | |
3006 template <> \ | |
3007 const char *InstImpl<TraitsType>::InstX86Or::Base::Opcode = "or"; \ | |
3008 template <> \ | |
3009 template <> \ | |
3010 const char *InstImpl<TraitsType>::InstX86Orps::Base::Opcode = "or"; \ | |
3011 template <> \ | |
3012 template <> \ | |
3013 const char *InstImpl<TraitsType>::InstX86OrRMW::Base::Opcode = "or"; \ | |
3014 template <> \ | |
3015 template <> \ | |
3016 const char *InstImpl<TraitsType>::InstX86Por::Base::Opcode = "por"; \ | |
3017 template <> \ | |
3018 template <> \ | |
3019 const char *InstImpl<TraitsType>::InstX86Xor::Base::Opcode = "xor"; \ | |
3020 template <> \ | |
3021 template <> \ | |
3022 const char *InstImpl<TraitsType>::InstX86Xorps::Base::Opcode = "xor"; \ | |
3023 template <> \ | |
3024 template <> \ | |
3025 const char *InstImpl<TraitsType>::InstX86XorRMW::Base::Opcode = "xor"; \ | |
3026 template <> \ | |
3027 template <> \ | |
3028 const char *InstImpl<TraitsType>::InstX86Pxor::Base::Opcode = "pxor"; \ | |
3029 template <> \ | |
3030 template <> \ | |
3031 const char *InstImpl<TraitsType>::InstX86Imul::Base::Opcode = "imul"; \ | |
3032 template <> \ | |
3033 template <> \ | |
3034 const char *InstImpl<TraitsType>::InstX86ImulImm::Base::Opcode = "imul"; \ | |
3035 template <> \ | |
3036 template <> \ | |
3037 const char *InstImpl<TraitsType>::InstX86Mulps::Base::Opcode = "mul"; \ | |
3038 template <> \ | |
3039 template <> \ | |
3040 const char *InstImpl<TraitsType>::InstX86Mulss::Base::Opcode = "mul"; \ | |
3041 template <> \ | |
3042 template <> \ | |
3043 const char *InstImpl<TraitsType>::InstX86Pmull::Base::Opcode = "pmull"; \ | |
3044 template <> \ | |
3045 template <> \ | |
3046 const char *InstImpl<TraitsType>::InstX86Pmuludq::Base::Opcode = "pmuludq"; \ | |
3047 template <> \ | |
3048 template <> \ | |
3049 const char *InstImpl<TraitsType>::InstX86Div::Base::Opcode = "div"; \ | |
3050 template <> \ | |
3051 template <> \ | |
3052 const char *InstImpl<TraitsType>::InstX86Divps::Base::Opcode = "div"; \ | |
3053 template <> \ | |
3054 template <> \ | |
3055 const char *InstImpl<TraitsType>::InstX86Divss::Base::Opcode = "div"; \ | |
3056 template <> \ | |
3057 template <> \ | |
3058 const char *InstImpl<TraitsType>::InstX86Idiv::Base::Opcode = "idiv"; \ | |
3059 template <> \ | |
3060 template <> \ | |
3061 const char *InstImpl<TraitsType>::InstX86Rol::Base::Opcode = "rol"; \ | |
3062 template <> \ | |
3063 template <> \ | |
3064 const char *InstImpl<TraitsType>::InstX86Shl::Base::Opcode = "shl"; \ | |
3065 template <> \ | |
3066 template <> \ | |
3067 const char *InstImpl<TraitsType>::InstX86Psll::Base::Opcode = "psll"; \ | |
3068 template <> \ | |
3069 template <> \ | |
3070 const char *InstImpl<TraitsType>::InstX86Shr::Base::Opcode = "shr"; \ | |
3071 template <> \ | |
3072 template <> \ | |
3073 const char *InstImpl<TraitsType>::InstX86Sar::Base::Opcode = "sar"; \ | |
3074 template <> \ | |
3075 template <> \ | |
3076 const char *InstImpl<TraitsType>::InstX86Psra::Base::Opcode = "psra"; \ | |
3077 template <> \ | |
3078 template <> \ | |
3079 const char *InstImpl<TraitsType>::InstX86Psrl::Base::Opcode = "psrl"; \ | |
3080 template <> \ | |
3081 template <> \ | |
3082 const char *InstImpl<TraitsType>::InstX86Pcmpeq::Base::Opcode = "pcmpeq"; \ | |
3083 template <> \ | |
3084 template <> \ | |
3085 const char *InstImpl<TraitsType>::InstX86Pcmpgt::Base::Opcode = "pcmpgt"; \ | |
3086 template <> \ | |
3087 template <> \ | |
3088 const char *InstImpl<TraitsType>::InstX86MovssRegs::Base::Opcode = "movss"; \ | |
3131 /* Ternary ops */ \ | 3089 /* Ternary ops */ \ |
3132 template <> const char *InstX86Insertps<Machine>::Base::Opcode = "insertps"; \ | 3090 template <> \ |
3133 template <> const char *InstX86Shufps<Machine>::Base::Opcode = "shufps"; \ | 3091 template <> \ |
3134 template <> const char *InstX86Pinsr<Machine>::Base::Opcode = "pinsr"; \ | 3092 const char *InstImpl<TraitsType>::InstX86Insertps::Base::Opcode = \ |
3135 template <> const char *InstX86Blendvps<Machine>::Base::Opcode = "blendvps"; \ | 3093 "insertps"; \ |
3136 template <> const char *InstX86Pblendvb<Machine>::Base::Opcode = "pblendvb"; \ | 3094 template <> \ |
3095 template <> \ | |
3096 const char *InstImpl<TraitsType>::InstX86Shufps::Base::Opcode = "shufps"; \ | |
3097 template <> \ | |
3098 template <> \ | |
3099 const char *InstImpl<TraitsType>::InstX86Pinsr::Base::Opcode = "pinsr"; \ | |
3100 template <> \ | |
3101 template <> \ | |
3102 const char *InstImpl<TraitsType>::InstX86Blendvps::Base::Opcode = \ | |
3103 "blendvps"; \ | |
3104 template <> \ | |
3105 template <> \ | |
3106 const char *InstImpl<TraitsType>::InstX86Pblendvb::Base::Opcode = \ | |
3107 "pblendvb"; \ | |
3137 /* Three address ops */ \ | 3108 /* Three address ops */ \ |
3138 template <> const char *InstX86Pextr<Machine>::Base::Opcode = "pextr"; \ | 3109 template <> \ |
3139 template <> const char *InstX86Pshufd<Machine>::Base::Opcode = "pshufd"; \ | 3110 template <> \ |
3111 const char *InstImpl<TraitsType>::InstX86Pextr::Base::Opcode = "pextr"; \ | |
3112 template <> \ | |
3113 template <> \ | |
3114 const char *InstImpl<TraitsType>::InstX86Pshufd::Base::Opcode = "pshufd"; \ | |
3140 /* Inplace GPR ops */ \ | 3115 /* Inplace GPR ops */ \ |
3141 template <> \ | 3116 template <> \ |
3142 const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 3117 template <> \ |
3143 InstX86Bswap<Machine>::Base::Emitter = { \ | 3118 const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ |
3144 &InstX86Base<Machine>::Traits::Assembler::bswap, \ | 3119 InstImpl<TraitsType>::InstX86Bswap::Base::Emitter = { \ |
3120 &InstImpl<TraitsType>::Assembler::bswap, \ | |
3145 nullptr /* only a reg form exists */ \ | 3121 nullptr /* only a reg form exists */ \ |
3146 }; \ | 3122 }; \ |
3147 template <> \ | 3123 template <> \ |
3148 const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 3124 template <> \ |
3149 InstX86Neg<Machine>::Base::Emitter = { \ | 3125 const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ |
3150 &InstX86Base<Machine>::Traits::Assembler::neg, \ | 3126 InstImpl<TraitsType>::InstX86Neg::Base::Emitter = { \ |
3151 &InstX86Base<Machine>::Traits::Assembler::neg}; \ | 3127 &InstImpl<TraitsType>::Assembler::neg, \ |
3128 &InstImpl<TraitsType>::Assembler::neg}; \ | |
3152 \ | 3129 \ |
3153 /* Unary GPR ops */ \ | 3130 /* Unary GPR ops */ \ |
3131 template <> \ | |
3154 template <> /* uses specialized emitter. */ \ | 3132 template <> /* uses specialized emitter. */ \ |
3155 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3133 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3156 InstX86Cbwdq<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 3134 InstImpl<TraitsType>::InstX86Cbwdq::Base::Emitter = {nullptr, nullptr, \ |
3157 template <> \ | 3135 nullptr}; \ |
3158 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3136 template <> \ |
3159 InstX86Bsf<Machine>::Base::Emitter = { \ | 3137 template <> \ |
3160 &InstX86Base<Machine>::Traits::Assembler::bsf, \ | 3138 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3161 &InstX86Base<Machine>::Traits::Assembler::bsf, nullptr}; \ | 3139 InstImpl<TraitsType>::InstX86Bsf::Base::Emitter = { \ |
3162 template <> \ | 3140 &InstImpl<TraitsType>::Assembler::bsf, \ |
3163 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3141 &InstImpl<TraitsType>::Assembler::bsf, nullptr}; \ |
3164 InstX86Bsr<Machine>::Base::Emitter = { \ | 3142 template <> \ |
3165 &InstX86Base<Machine>::Traits::Assembler::bsr, \ | 3143 template <> \ |
3166 &InstX86Base<Machine>::Traits::Assembler::bsr, nullptr}; \ | 3144 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3167 template <> \ | 3145 InstImpl<TraitsType>::InstX86Bsr::Base::Emitter = { \ |
3168 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3146 &InstImpl<TraitsType>::Assembler::bsr, \ |
3169 InstX86Lea<Machine>::Base::Emitter = { \ | 3147 &InstImpl<TraitsType>::Assembler::bsr, nullptr}; \ |
3148 template <> \ | |
3149 template <> \ | |
3150 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | |
3151 InstImpl<TraitsType>::InstX86Lea::Base::Emitter = { \ | |
3170 /* reg/reg and reg/imm are illegal */ nullptr, \ | 3152 /* reg/reg and reg/imm are illegal */ nullptr, \ |
3171 &InstX86Base<Machine>::Traits::Assembler::lea, nullptr}; \ | 3153 &InstImpl<TraitsType>::Assembler::lea, nullptr}; \ |
3172 template <> \ | 3154 template <> \ |
3173 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3155 template <> \ |
3174 InstX86Movsx<Machine>::Base::Emitter = { \ | 3156 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3175 &InstX86Base<Machine>::Traits::Assembler::movsx, \ | 3157 InstImpl<TraitsType>::InstX86Movsx::Base::Emitter = { \ |
3176 &InstX86Base<Machine>::Traits::Assembler::movsx, nullptr}; \ | 3158 &InstImpl<TraitsType>::Assembler::movsx, \ |
3177 template <> \ | 3159 &InstImpl<TraitsType>::Assembler::movsx, nullptr}; \ |
3178 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3160 template <> \ |
3179 InstX86Movzx<Machine>::Base::Emitter = { \ | 3161 template <> \ |
3180 &InstX86Base<Machine>::Traits::Assembler::movzx, \ | 3162 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3181 &InstX86Base<Machine>::Traits::Assembler::movzx, nullptr}; \ | 3163 InstImpl<TraitsType>::InstX86Movzx::Base::Emitter = { \ |
3164 &InstImpl<TraitsType>::Assembler::movzx, \ | |
3165 &InstImpl<TraitsType>::Assembler::movzx, nullptr}; \ | |
3182 \ | 3166 \ |
3183 /* Unary XMM ops */ \ | 3167 /* Unary XMM ops */ \ |
3168 template <> \ | |
3184 template <> /* uses specialized emitter. */ \ | 3169 template <> /* uses specialized emitter. */ \ |
3185 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3170 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3186 InstX86Movd<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 3171 InstImpl<TraitsType>::InstX86Movd::Base::Emitter = {nullptr, nullptr}; \ |
3187 template <> \ | 3172 template <> \ |
3188 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3173 template <> \ |
3189 InstX86Sqrtss<Machine>::Base::Emitter = { \ | 3174 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3190 &InstX86Base<Machine>::Traits::Assembler::sqrtss, \ | 3175 InstImpl<TraitsType>::InstX86Sqrtss::Base::Emitter = { \ |
3191 &InstX86Base<Machine>::Traits::Assembler::sqrtss}; \ | 3176 &InstImpl<TraitsType>::Assembler::sqrtss, \ |
3177 &InstImpl<TraitsType>::Assembler::sqrtss}; \ | |
3192 \ | 3178 \ |
3193 /* Binary GPR ops */ \ | 3179 /* Binary GPR ops */ \ |
3180 template <> \ | |
3194 template <> /* uses specialized emitter. */ \ | 3181 template <> /* uses specialized emitter. */ \ |
3195 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3182 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3196 InstX86Imul<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 3183 InstImpl<TraitsType>::InstX86Imul::Base::Emitter = {nullptr, nullptr, \ |
3197 template <> \ | 3184 nullptr}; \ |
3198 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3185 template <> \ |
3199 InstX86Add<Machine>::Base::Emitter = { \ | 3186 template <> \ |
3200 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3187 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3201 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3188 InstImpl<TraitsType>::InstX86Add::Base::Emitter = { \ |
3202 &InstX86Base<Machine>::Traits::Assembler::add}; \ | 3189 &InstImpl<TraitsType>::Assembler::add, \ |
3203 template <> \ | 3190 &InstImpl<TraitsType>::Assembler::add, \ |
3204 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3191 &InstImpl<TraitsType>::Assembler::add}; \ |
3205 InstX86AddRMW<Machine>::Base::Emitter = { \ | 3192 template <> \ |
3206 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3193 template <> \ |
3207 &InstX86Base<Machine>::Traits::Assembler::add}; \ | 3194 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3208 template <> \ | 3195 InstImpl<TraitsType>::InstX86AddRMW::Base::Emitter = { \ |
3209 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3196 &InstImpl<TraitsType>::Assembler::add, \ |
3210 InstX86Adc<Machine>::Base::Emitter = { \ | 3197 &InstImpl<TraitsType>::Assembler::add}; \ |
3211 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3198 template <> \ |
3212 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3199 template <> \ |
3213 &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 3200 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3214 template <> \ | 3201 InstImpl<TraitsType>::InstX86Adc::Base::Emitter = { \ |
3215 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3202 &InstImpl<TraitsType>::Assembler::adc, \ |
3216 InstX86AdcRMW<Machine>::Base::Emitter = { \ | 3203 &InstImpl<TraitsType>::Assembler::adc, \ |
3217 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3204 &InstImpl<TraitsType>::Assembler::adc}; \ |
3218 &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 3205 template <> \ |
3219 template <> \ | 3206 template <> \ |
3220 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3207 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3221 InstX86And<Machine>::Base::Emitter = { \ | 3208 InstImpl<TraitsType>::InstX86AdcRMW::Base::Emitter = { \ |
3222 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3209 &InstImpl<TraitsType>::Assembler::adc, \ |
3223 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3210 &InstImpl<TraitsType>::Assembler::adc}; \ |
3224 &InstX86Base<Machine>::Traits::Assembler::And}; \ | 3211 template <> \ |
3225 template <> \ | 3212 template <> \ |
3226 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3213 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3227 InstX86AndRMW<Machine>::Base::Emitter = { \ | 3214 InstImpl<TraitsType>::InstX86And::Base::Emitter = { \ |
3228 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3215 &InstImpl<TraitsType>::Assembler::And, \ |
3229 &InstX86Base<Machine>::Traits::Assembler::And}; \ | 3216 &InstImpl<TraitsType>::Assembler::And, \ |
3230 template <> \ | 3217 &InstImpl<TraitsType>::Assembler::And}; \ |
3231 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3218 template <> \ |
3232 InstX86Or<Machine>::Base::Emitter = { \ | 3219 template <> \ |
3233 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3220 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3234 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3221 InstImpl<TraitsType>::InstX86AndRMW::Base::Emitter = { \ |
3235 &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 3222 &InstImpl<TraitsType>::Assembler::And, \ |
3236 template <> \ | 3223 &InstImpl<TraitsType>::Assembler::And}; \ |
3237 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3224 template <> \ |
3238 InstX86OrRMW<Machine>::Base::Emitter = { \ | 3225 template <> \ |
3239 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3226 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3240 &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 3227 InstImpl<TraitsType>::InstX86Or::Base::Emitter = { \ |
3241 template <> \ | 3228 &InstImpl<TraitsType>::Assembler::Or, \ |
3242 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3229 &InstImpl<TraitsType>::Assembler::Or, \ |
3243 InstX86Sbb<Machine>::Base::Emitter = { \ | 3230 &InstImpl<TraitsType>::Assembler::Or}; \ |
3244 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3231 template <> \ |
3245 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3232 template <> \ |
3246 &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 3233 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3247 template <> \ | 3234 InstImpl<TraitsType>::InstX86OrRMW::Base::Emitter = { \ |
3248 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3235 &InstImpl<TraitsType>::Assembler::Or, \ |
3249 InstX86SbbRMW<Machine>::Base::Emitter = { \ | 3236 &InstImpl<TraitsType>::Assembler::Or}; \ |
3250 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3237 template <> \ |
3251 &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 3238 template <> \ |
3252 template <> \ | 3239 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3253 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3240 InstImpl<TraitsType>::InstX86Sbb::Base::Emitter = { \ |
3254 InstX86Sub<Machine>::Base::Emitter = { \ | 3241 &InstImpl<TraitsType>::Assembler::sbb, \ |
3255 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3242 &InstImpl<TraitsType>::Assembler::sbb, \ |
3256 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3243 &InstImpl<TraitsType>::Assembler::sbb}; \ |
3257 &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 3244 template <> \ |
3258 template <> \ | 3245 template <> \ |
3259 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3246 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3260 InstX86SubRMW<Machine>::Base::Emitter = { \ | 3247 InstImpl<TraitsType>::InstX86SbbRMW::Base::Emitter = { \ |
3261 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3248 &InstImpl<TraitsType>::Assembler::sbb, \ |
3262 &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 3249 &InstImpl<TraitsType>::Assembler::sbb}; \ |
3263 template <> \ | 3250 template <> \ |
3264 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3251 template <> \ |
3265 InstX86Xor<Machine>::Base::Emitter = { \ | 3252 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
3266 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3253 InstImpl<TraitsType>::InstX86Sub::Base::Emitter = { \ |
3267 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3254 &InstImpl<TraitsType>::Assembler::sub, \ |
3268 &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 3255 &InstImpl<TraitsType>::Assembler::sub, \ |
3269 template <> \ | 3256 &InstImpl<TraitsType>::Assembler::sub}; \ |
3270 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3257 template <> \ |
3271 InstX86XorRMW<Machine>::Base::Emitter = { \ | 3258 template <> \ |
3272 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3259 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
3273 &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 3260 InstImpl<TraitsType>::InstX86SubRMW::Base::Emitter = { \ |
3261 &InstImpl<TraitsType>::Assembler::sub, \ | |
3262 &InstImpl<TraitsType>::Assembler::sub}; \ | |
3263 template <> \ | |
3264 template <> \ | |
3265 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | |
3266 InstImpl<TraitsType>::InstX86Xor::Base::Emitter = { \ | |
3267 &InstImpl<TraitsType>::Assembler::Xor, \ | |
3268 &InstImpl<TraitsType>::Assembler::Xor, \ | |
3269 &InstImpl<TraitsType>::Assembler::Xor}; \ | |
3270 template <> \ | |
3271 template <> \ | |
3272 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | |
3273 InstImpl<TraitsType>::InstX86XorRMW::Base::Emitter = { \ | |
3274 &InstImpl<TraitsType>::Assembler::Xor, \ | |
3275 &InstImpl<TraitsType>::Assembler::Xor}; \ | |
3274 \ | 3276 \ |
3275 /* Binary Shift GPR ops */ \ | 3277 /* Binary Shift GPR ops */ \ |
3276 template <> \ | 3278 template <> \ |
3277 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3279 template <> \ |
3278 InstX86Rol<Machine>::Base::Emitter = { \ | 3280 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
3279 &InstX86Base<Machine>::Traits::Assembler::rol, \ | 3281 InstImpl<TraitsType>::InstX86Rol::Base::Emitter = { \ |
3280 &InstX86Base<Machine>::Traits::Assembler::rol}; \ | 3282 &InstImpl<TraitsType>::Assembler::rol, \ |
3281 template <> \ | 3283 &InstImpl<TraitsType>::Assembler::rol}; \ |
3282 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3284 template <> \ |
3283 InstX86Sar<Machine>::Base::Emitter = { \ | 3285 template <> \ |
3284 &InstX86Base<Machine>::Traits::Assembler::sar, \ | 3286 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
3285 &InstX86Base<Machine>::Traits::Assembler::sar}; \ | 3287 InstImpl<TraitsType>::InstX86Sar::Base::Emitter = { \ |
3286 template <> \ | 3288 &InstImpl<TraitsType>::Assembler::sar, \ |
3287 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3289 &InstImpl<TraitsType>::Assembler::sar}; \ |
3288 InstX86Shl<Machine>::Base::Emitter = { \ | 3290 template <> \ |
3289 &InstX86Base<Machine>::Traits::Assembler::shl, \ | 3291 template <> \ |
3290 &InstX86Base<Machine>::Traits::Assembler::shl}; \ | 3292 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
3291 template <> \ | 3293 InstImpl<TraitsType>::InstX86Shl::Base::Emitter = { \ |
3292 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3294 &InstImpl<TraitsType>::Assembler::shl, \ |
3293 InstX86Shr<Machine>::Base::Emitter = { \ | 3295 &InstImpl<TraitsType>::Assembler::shl}; \ |
3294 &InstX86Base<Machine>::Traits::Assembler::shr, \ | 3296 template <> \ |
3295 &InstX86Base<Machine>::Traits::Assembler::shr}; \ | 3297 template <> \ |
3298 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | |
3299 InstImpl<TraitsType>::InstX86Shr::Base::Emitter = { \ | |
3300 &InstImpl<TraitsType>::Assembler::shr, \ | |
3301 &InstImpl<TraitsType>::Assembler::shr}; \ | |
3296 \ | 3302 \ |
3297 /* Binary XMM ops */ \ | 3303 /* Binary XMM ops */ \ |
3304 template <> \ | |
3298 template <> /* uses specialized emitter. */ \ | 3305 template <> /* uses specialized emitter. */ \ |
3299 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3306 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3300 InstX86MovssRegs<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 3307 InstImpl<TraitsType>::InstX86MovssRegs::Base::Emitter = {nullptr, \ |
3301 template <> \ | 3308 nullptr}; \ |
3302 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3309 template <> \ |
3303 InstX86Addss<Machine>::Base::Emitter = { \ | 3310 template <> \ |
3304 &InstX86Base<Machine>::Traits::Assembler::addss, \ | 3311 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3305 &InstX86Base<Machine>::Traits::Assembler::addss}; \ | 3312 InstImpl<TraitsType>::InstX86Addss::Base::Emitter = { \ |
3306 template <> \ | 3313 &InstImpl<TraitsType>::Assembler::addss, \ |
3307 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3314 &InstImpl<TraitsType>::Assembler::addss}; \ |
3308 InstX86Addps<Machine>::Base::Emitter = { \ | 3315 template <> \ |
3309 &InstX86Base<Machine>::Traits::Assembler::addps, \ | 3316 template <> \ |
3310 &InstX86Base<Machine>::Traits::Assembler::addps}; \ | 3317 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3311 template <> \ | 3318 InstImpl<TraitsType>::InstX86Addps::Base::Emitter = { \ |
3312 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3319 &InstImpl<TraitsType>::Assembler::addps, \ |
3313 InstX86Divss<Machine>::Base::Emitter = { \ | 3320 &InstImpl<TraitsType>::Assembler::addps}; \ |
3314 &InstX86Base<Machine>::Traits::Assembler::divss, \ | 3321 template <> \ |
3315 &InstX86Base<Machine>::Traits::Assembler::divss}; \ | 3322 template <> \ |
3316 template <> \ | 3323 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3317 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3324 InstImpl<TraitsType>::InstX86Divss::Base::Emitter = { \ |
3318 InstX86Divps<Machine>::Base::Emitter = { \ | 3325 &InstImpl<TraitsType>::Assembler::divss, \ |
3319 &InstX86Base<Machine>::Traits::Assembler::divps, \ | 3326 &InstImpl<TraitsType>::Assembler::divss}; \ |
3320 &InstX86Base<Machine>::Traits::Assembler::divps}; \ | 3327 template <> \ |
3321 template <> \ | 3328 template <> \ |
3322 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3329 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3323 InstX86Mulss<Machine>::Base::Emitter = { \ | 3330 InstImpl<TraitsType>::InstX86Divps::Base::Emitter = { \ |
3324 &InstX86Base<Machine>::Traits::Assembler::mulss, \ | 3331 &InstImpl<TraitsType>::Assembler::divps, \ |
3325 &InstX86Base<Machine>::Traits::Assembler::mulss}; \ | 3332 &InstImpl<TraitsType>::Assembler::divps}; \ |
3326 template <> \ | 3333 template <> \ |
3327 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3334 template <> \ |
3328 InstX86Mulps<Machine>::Base::Emitter = { \ | 3335 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3329 &InstX86Base<Machine>::Traits::Assembler::mulps, \ | 3336 InstImpl<TraitsType>::InstX86Mulss::Base::Emitter = { \ |
3330 &InstX86Base<Machine>::Traits::Assembler::mulps}; \ | 3337 &InstImpl<TraitsType>::Assembler::mulss, \ |
3331 template <> \ | 3338 &InstImpl<TraitsType>::Assembler::mulss}; \ |
3332 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3339 template <> \ |
3333 InstX86Padd<Machine>::Base::Emitter = { \ | 3340 template <> \ |
3334 &InstX86Base<Machine>::Traits::Assembler::padd, \ | 3341 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3335 &InstX86Base<Machine>::Traits::Assembler::padd}; \ | 3342 InstImpl<TraitsType>::InstX86Mulps::Base::Emitter = { \ |
3336 template <> \ | 3343 &InstImpl<TraitsType>::Assembler::mulps, \ |
3337 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3344 &InstImpl<TraitsType>::Assembler::mulps}; \ |
3338 InstX86Pand<Machine>::Base::Emitter = { \ | 3345 template <> \ |
3339 &InstX86Base<Machine>::Traits::Assembler::pand, \ | 3346 template <> \ |
3340 &InstX86Base<Machine>::Traits::Assembler::pand}; \ | 3347 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3341 template <> \ | 3348 InstImpl<TraitsType>::InstX86Padd::Base::Emitter = { \ |
3342 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3349 &InstImpl<TraitsType>::Assembler::padd, \ |
3343 InstX86Pandn<Machine>::Base::Emitter = { \ | 3350 &InstImpl<TraitsType>::Assembler::padd}; \ |
3344 &InstX86Base<Machine>::Traits::Assembler::pandn, \ | 3351 template <> \ |
3345 &InstX86Base<Machine>::Traits::Assembler::pandn}; \ | 3352 template <> \ |
3346 template <> \ | 3353 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3347 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3354 InstImpl<TraitsType>::InstX86Pand::Base::Emitter = { \ |
3348 InstX86Pcmpeq<Machine>::Base::Emitter = { \ | 3355 &InstImpl<TraitsType>::Assembler::pand, \ |
3349 &InstX86Base<Machine>::Traits::Assembler::pcmpeq, \ | 3356 &InstImpl<TraitsType>::Assembler::pand}; \ |
3350 &InstX86Base<Machine>::Traits::Assembler::pcmpeq}; \ | 3357 template <> \ |
3351 template <> \ | 3358 template <> \ |
3352 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3359 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3353 InstX86Pcmpgt<Machine>::Base::Emitter = { \ | 3360 InstImpl<TraitsType>::InstX86Pandn::Base::Emitter = { \ |
3354 &InstX86Base<Machine>::Traits::Assembler::pcmpgt, \ | 3361 &InstImpl<TraitsType>::Assembler::pandn, \ |
3355 &InstX86Base<Machine>::Traits::Assembler::pcmpgt}; \ | 3362 &InstImpl<TraitsType>::Assembler::pandn}; \ |
3356 template <> \ | 3363 template <> \ |
3357 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3364 template <> \ |
3358 InstX86Pmull<Machine>::Base::Emitter = { \ | 3365 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3359 &InstX86Base<Machine>::Traits::Assembler::pmull, \ | 3366 InstImpl<TraitsType>::InstX86Pcmpeq::Base::Emitter = { \ |
3360 &InstX86Base<Machine>::Traits::Assembler::pmull}; \ | 3367 &InstImpl<TraitsType>::Assembler::pcmpeq, \ |
3361 template <> \ | 3368 &InstImpl<TraitsType>::Assembler::pcmpeq}; \ |
3362 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3369 template <> \ |
3363 InstX86Pmuludq<Machine>::Base::Emitter = { \ | 3370 template <> \ |
3364 &InstX86Base<Machine>::Traits::Assembler::pmuludq, \ | 3371 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3365 &InstX86Base<Machine>::Traits::Assembler::pmuludq}; \ | 3372 InstImpl<TraitsType>::InstX86Pcmpgt::Base::Emitter = { \ |
3366 template <> \ | 3373 &InstImpl<TraitsType>::Assembler::pcmpgt, \ |
3367 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3374 &InstImpl<TraitsType>::Assembler::pcmpgt}; \ |
3368 InstX86Por<Machine>::Base::Emitter = { \ | 3375 template <> \ |
3369 &InstX86Base<Machine>::Traits::Assembler::por, \ | 3376 template <> \ |
3370 &InstX86Base<Machine>::Traits::Assembler::por}; \ | 3377 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3371 template <> \ | 3378 InstImpl<TraitsType>::InstX86Pmull::Base::Emitter = { \ |
3372 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3379 &InstImpl<TraitsType>::Assembler::pmull, \ |
3373 InstX86Psub<Machine>::Base::Emitter = { \ | 3380 &InstImpl<TraitsType>::Assembler::pmull}; \ |
3374 &InstX86Base<Machine>::Traits::Assembler::psub, \ | 3381 template <> \ |
3375 &InstX86Base<Machine>::Traits::Assembler::psub}; \ | 3382 template <> \ |
3376 template <> \ | 3383 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3377 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3384 InstImpl<TraitsType>::InstX86Pmuludq::Base::Emitter = { \ |
3378 InstX86Pxor<Machine>::Base::Emitter = { \ | 3385 &InstImpl<TraitsType>::Assembler::pmuludq, \ |
3379 &InstX86Base<Machine>::Traits::Assembler::pxor, \ | 3386 &InstImpl<TraitsType>::Assembler::pmuludq}; \ |
3380 &InstX86Base<Machine>::Traits::Assembler::pxor}; \ | 3387 template <> \ |
3381 template <> \ | 3388 template <> \ |
3382 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3389 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3383 InstX86Subss<Machine>::Base::Emitter = { \ | 3390 InstImpl<TraitsType>::InstX86Por::Base::Emitter = { \ |
3384 &InstX86Base<Machine>::Traits::Assembler::subss, \ | 3391 &InstImpl<TraitsType>::Assembler::por, \ |
3385 &InstX86Base<Machine>::Traits::Assembler::subss}; \ | 3392 &InstImpl<TraitsType>::Assembler::por}; \ |
3386 template <> \ | 3393 template <> \ |
3387 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3394 template <> \ |
3388 InstX86Subps<Machine>::Base::Emitter = { \ | 3395 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3389 &InstX86Base<Machine>::Traits::Assembler::subps, \ | 3396 InstImpl<TraitsType>::InstX86Psub::Base::Emitter = { \ |
3390 &InstX86Base<Machine>::Traits::Assembler::subps}; \ | 3397 &InstImpl<TraitsType>::Assembler::psub, \ |
3391 template <> \ | 3398 &InstImpl<TraitsType>::Assembler::psub}; \ |
3392 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3399 template <> \ |
3393 InstX86Andnps<Machine>::Base::Emitter = { \ | 3400 template <> \ |
3394 &InstX86Base<Machine>::Traits::Assembler::andnps, \ | 3401 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3395 &InstX86Base<Machine>::Traits::Assembler::andnps}; \ | 3402 InstImpl<TraitsType>::InstX86Pxor::Base::Emitter = { \ |
3396 template <> \ | 3403 &InstImpl<TraitsType>::Assembler::pxor, \ |
3397 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3404 &InstImpl<TraitsType>::Assembler::pxor}; \ |
3398 InstX86Andps<Machine>::Base::Emitter = { \ | 3405 template <> \ |
3399 &InstX86Base<Machine>::Traits::Assembler::andps, \ | 3406 template <> \ |
3400 &InstX86Base<Machine>::Traits::Assembler::andps}; \ | 3407 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3401 template <> \ | 3408 InstImpl<TraitsType>::InstX86Subss::Base::Emitter = { \ |
3402 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3409 &InstImpl<TraitsType>::Assembler::subss, \ |
3403 InstX86Maxss<Machine>::Base::Emitter = { \ | 3410 &InstImpl<TraitsType>::Assembler::subss}; \ |
3404 &InstX86Base<Machine>::Traits::Assembler::maxss, \ | 3411 template <> \ |
3405 &InstX86Base<Machine>::Traits::Assembler::maxss}; \ | 3412 template <> \ |
3406 template <> \ | 3413 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3407 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3414 InstImpl<TraitsType>::InstX86Subps::Base::Emitter = { \ |
3408 InstX86Minss<Machine>::Base::Emitter = { \ | 3415 &InstImpl<TraitsType>::Assembler::subps, \ |
3409 &InstX86Base<Machine>::Traits::Assembler::minss, \ | 3416 &InstImpl<TraitsType>::Assembler::subps}; \ |
3410 &InstX86Base<Machine>::Traits::Assembler::minss}; \ | 3417 template <> \ |
3411 template <> \ | 3418 template <> \ |
3412 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3419 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3413 InstX86Orps<Machine>::Base::Emitter = { \ | 3420 InstImpl<TraitsType>::InstX86Andnps::Base::Emitter = { \ |
3414 &InstX86Base<Machine>::Traits::Assembler::orps, \ | 3421 &InstImpl<TraitsType>::Assembler::andnps, \ |
3415 &InstX86Base<Machine>::Traits::Assembler::orps}; \ | 3422 &InstImpl<TraitsType>::Assembler::andnps}; \ |
3416 template <> \ | 3423 template <> \ |
3417 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3424 template <> \ |
3418 InstX86Xorps<Machine>::Base::Emitter = { \ | 3425 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
3419 &InstX86Base<Machine>::Traits::Assembler::xorps, \ | 3426 InstImpl<TraitsType>::InstX86Andps::Base::Emitter = { \ |
3420 &InstX86Base<Machine>::Traits::Assembler::xorps}; \ | 3427 &InstImpl<TraitsType>::Assembler::andps, \ |
3428 &InstImpl<TraitsType>::Assembler::andps}; \ | |
3429 template <> \ | |
3430 template <> \ | |
3431 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
3432 InstImpl<TraitsType>::InstX86Maxss::Base::Emitter = { \ | |
3433 &InstImpl<TraitsType>::Assembler::maxss, \ | |
3434 &InstImpl<TraitsType>::Assembler::maxss}; \ | |
3435 template <> \ | |
3436 template <> \ | |
3437 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
3438 InstImpl<TraitsType>::InstX86Minss::Base::Emitter = { \ | |
3439 &InstImpl<TraitsType>::Assembler::minss, \ | |
3440 &InstImpl<TraitsType>::Assembler::minss}; \ | |
3441 template <> \ | |
3442 template <> \ | |
3443 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
3444 InstImpl<TraitsType>::InstX86Orps::Base::Emitter = { \ | |
3445 &InstImpl<TraitsType>::Assembler::orps, \ | |
3446 &InstImpl<TraitsType>::Assembler::orps}; \ | |
3447 template <> \ | |
3448 template <> \ | |
3449 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
3450 InstImpl<TraitsType>::InstX86Xorps::Base::Emitter = { \ | |
3451 &InstImpl<TraitsType>::Assembler::xorps, \ | |
3452 &InstImpl<TraitsType>::Assembler::xorps}; \ | |
3421 \ | 3453 \ |
3422 /* Binary XMM Shift ops */ \ | 3454 /* Binary XMM Shift ops */ \ |
3423 template <> \ | 3455 template <> \ |
3424 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3456 template <> \ |
3425 InstX86Psll<Machine>::Base::Emitter = { \ | 3457 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
3426 &InstX86Base<Machine>::Traits::Assembler::psll, \ | 3458 InstImpl<TraitsType>::InstX86Psll::Base::Emitter = { \ |
3427 &InstX86Base<Machine>::Traits::Assembler::psll, \ | 3459 &InstImpl<TraitsType>::Assembler::psll, \ |
3428 &InstX86Base<Machine>::Traits::Assembler::psll}; \ | 3460 &InstImpl<TraitsType>::Assembler::psll, \ |
3429 template <> \ | 3461 &InstImpl<TraitsType>::Assembler::psll}; \ |
3430 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3462 template <> \ |
3431 InstX86Psra<Machine>::Base::Emitter = { \ | 3463 template <> \ |
3432 &InstX86Base<Machine>::Traits::Assembler::psra, \ | 3464 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
3433 &InstX86Base<Machine>::Traits::Assembler::psra, \ | 3465 InstImpl<TraitsType>::InstX86Psra::Base::Emitter = { \ |
3434 &InstX86Base<Machine>::Traits::Assembler::psra}; \ | 3466 &InstImpl<TraitsType>::Assembler::psra, \ |
3435 template <> \ | 3467 &InstImpl<TraitsType>::Assembler::psra, \ |
3436 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3468 &InstImpl<TraitsType>::Assembler::psra}; \ |
3437 InstX86Psrl<Machine>::Base::Emitter = { \ | 3469 template <> \ |
3438 &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 3470 template <> \ |
3439 &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 3471 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
3440 &InstX86Base<Machine>::Traits::Assembler::psrl}; \ | 3472 InstImpl<TraitsType>::InstX86Psrl::Base::Emitter = { \ |
3473 &InstImpl<TraitsType>::Assembler::psrl, \ | |
3474 &InstImpl<TraitsType>::Assembler::psrl, \ | |
3475 &InstImpl<TraitsType>::Assembler::psrl}; \ | |
3441 } \ | 3476 } \ |
3442 } | 3477 } |
3443 | 3478 |
3444 } // end of namespace X86Internal | 3479 } // end of namespace X86NAMESPACE |
3445 } // end of namespace Ice | 3480 } // end of namespace Ice |
3446 | 3481 |
3447 #include "IceInstX86BaseImpl.h" | 3482 #include "IceInstX86BaseImpl.h" |
3448 | 3483 |
3449 #endif // SUBZERO_SRC_ICEINSTX86BASE_H | 3484 #endif // SUBZERO_SRC_ICEINSTX86BASE_H |
OLD | NEW |