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

Side by Side Diff: src/IceInstX86Base.h

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

Powered by Google App Engine
This is Rietveld 408576698