Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: src/IceInstX86Base.h

Issue 1548363002: Subzero. Code organization. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698