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

Side by Side Diff: src/IceInstX8632.h

Issue 1216933015: X8632 Templatization completed. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. 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
« no previous file with comments | « src/IceAssemblerX86Base.h ('k') | src/IceInstX8632.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceInstX8632.h - x86-32 machine instructions -*- C++ -*-===// 1 //===- subzero/src/IceInstX8632.h - x86-32 machine instructions -*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// This file declares the InstX8632 and OperandX8632 classes and 11 /// This file used to house all the X8632 instructions. Subzero has been
12 /// their subclasses. This represents the machine instructions and 12 /// modified to use templates for X86 instructions, so all those definitions are
13 /// operands used for x86-32 code selection. 13 /// are in IceInstX86Base.h
14 ///
15 /// When interacting with the X8632 target (which should only happen in the
16 /// X8632 TargetLowering) clients have should use the Ice::X8632::Traits::Insts
17 /// traits, which hides all the template verboseness behind a type alias.
18 ///
19 /// For example, to create an X8632 MOV Instruction, clients should do
20 ///
21 /// ::Ice::X8632::Traits::Insts::Mov::create
22 ///
23 /// In the future, this file might be used to declare X8632 specific
24 /// instructions (e.g., FLD, and FSTP.)
14 /// 25 ///
15 //===----------------------------------------------------------------------===// 26 //===----------------------------------------------------------------------===//
16 27
17 #ifndef SUBZERO_SRC_ICEINSTX8632_H 28 #ifndef SUBZERO_SRC_ICEINSTX8632_H
18 #define SUBZERO_SRC_ICEINSTX8632_H 29 #define SUBZERO_SRC_ICEINSTX8632_H
19 30
20 #include "IceAssemblerX8632.h"
21 #include "IceConditionCodesX8632.h"
22 #include "IceDefs.h" 31 #include "IceDefs.h"
23 #include "IceInst.h" 32 #include "IceInst.h"
24 #include "IceInstX8632.def" 33 #include "IceInstX86Base.h"
25 #include "IceOperand.h" 34 #include "IceOperand.h"
26 #include "IceTargetLoweringX8632Traits.h" 35 #include "IceTargetLoweringX8632Traits.h"
27 36
28 namespace Ice {
29
30 class TargetX8632;
31
32 /// OperandX8632 extends the Operand hierarchy. Its subclasses are
33 /// OperandX8632Mem and VariableSplit.
34 class OperandX8632 : public Operand {
35 OperandX8632() = delete;
36 OperandX8632(const OperandX8632 &) = delete;
37 OperandX8632 &operator=(const OperandX8632 &) = delete;
38
39 public:
40 enum OperandKindX8632 { k__Start = Operand::kTarget, kMem, kSplit };
41 using Operand::dump;
42 void dump(const Cfg *, Ostream &Str) const override {
43 if (BuildDefs::dump())
44 Str << "<OperandX8632>";
45 }
46
47 protected:
48 OperandX8632(OperandKindX8632 Kind, Type Ty)
49 : Operand(static_cast<OperandKind>(Kind), Ty) {}
50 };
51
52 /// OperandX8632Mem represents the m32 addressing mode, with optional
53 /// base and index registers, a constant offset, and a fixed shift
54 /// value for the index register.
55 class OperandX8632Mem : public OperandX8632 {
56 OperandX8632Mem() = delete;
57 OperandX8632Mem(const OperandX8632Mem &) = delete;
58 OperandX8632Mem &operator=(const OperandX8632Mem &) = delete;
59
60 public:
61 enum SegmentRegisters {
62 DefaultSegment = -1,
63 #define X(val, name, prefix) val,
64 SEG_REGX8632_TABLE
65 #undef X
66 SegReg_NUM
67 };
68 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base,
69 Constant *Offset, Variable *Index = nullptr,
70 uint16_t Shift = 0,
71 SegmentRegisters SegmentReg = DefaultSegment) {
72 return new (Func->allocate<OperandX8632Mem>())
73 OperandX8632Mem(Func, Ty, Base, Offset, Index, Shift, SegmentReg);
74 }
75 Variable *getBase() const { return Base; }
76 Constant *getOffset() const { return Offset; }
77 Variable *getIndex() const { return Index; }
78 uint16_t getShift() const { return Shift; }
79 SegmentRegisters getSegmentRegister() const { return SegmentReg; }
80 void emitSegmentOverride(X8632::AssemblerX8632 *Asm) const;
81 X8632::Traits::Address toAsmAddress(Assembler *Asm) const;
82 void emit(const Cfg *Func) const override;
83 using OperandX8632::dump;
84 void dump(const Cfg *Func, Ostream &Str) const override;
85
86 static bool classof(const Operand *Operand) {
87 return Operand->getKind() == static_cast<OperandKind>(kMem);
88 }
89
90 void setRandomized(bool R) { Randomized = R; }
91
92 bool getRandomized() const { return Randomized; }
93
94 private:
95 OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
96 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg);
97
98 Variable *Base;
99 Constant *Offset;
100 Variable *Index;
101 uint16_t Shift;
102 SegmentRegisters SegmentReg : 16;
103 /// A flag to show if this memory operand is a randomized one.
104 /// Randomized memory operands are generated in
105 /// TargetX8632::randomizeOrPoolImmediate()
106 bool Randomized;
107 };
108
109 /// VariableSplit is a way to treat an f64 memory location as a pair
110 /// of i32 locations (Low and High). This is needed for some cases
111 /// of the Bitcast instruction. Since it's not possible for integer
112 /// registers to access the XMM registers and vice versa, the
113 /// lowering forces the f64 to be spilled to the stack and then
114 /// accesses through the VariableSplit.
115 class VariableSplit : public OperandX8632 {
116 VariableSplit() = delete;
117 VariableSplit(const VariableSplit &) = delete;
118 VariableSplit &operator=(const VariableSplit &) = delete;
119
120 public:
121 enum Portion { Low, High };
122 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
123 return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part);
124 }
125 int32_t getOffset() const { return Part == High ? 4 : 0; }
126
127 X8632::Traits::Address toAsmAddress(const Cfg *Func) const;
128 void emit(const Cfg *Func) const override;
129 using OperandX8632::dump;
130 void dump(const Cfg *Func, Ostream &Str) const override;
131
132 static bool classof(const Operand *Operand) {
133 return Operand->getKind() == static_cast<OperandKind>(kSplit);
134 }
135
136 private:
137 VariableSplit(Cfg *Func, Variable *Var, Portion Part)
138 : OperandX8632(kSplit, IceType_i32), Var(Var), Part(Part) {
139 assert(Var->getType() == IceType_f64);
140 Vars = Func->allocateArrayOf<Variable *>(1);
141 Vars[0] = Var;
142 NumVars = 1;
143 }
144
145 Variable *Var;
146 Portion Part;
147 };
148
149 /// SpillVariable decorates a Variable by linking it to another
150 /// Variable. When stack frame offsets are computed, the SpillVariable
151 /// is given a distinct stack slot only if its linked Variable has a
152 /// register. If the linked Variable has a stack slot, then the
153 /// Variable and SpillVariable share that slot.
154 class SpillVariable : public Variable {
155 SpillVariable() = delete;
156 SpillVariable(const SpillVariable &) = delete;
157 SpillVariable &operator=(const SpillVariable &) = delete;
158
159 public:
160 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
161 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index);
162 }
163 const static OperandKind SpillVariableKind =
164 static_cast<OperandKind>(kVariable_Target);
165 static bool classof(const Operand *Operand) {
166 return Operand->getKind() == SpillVariableKind;
167 }
168 void setLinkedTo(Variable *Var) { LinkedTo = Var; }
169 Variable *getLinkedTo() const { return LinkedTo; }
170 // Inherit dump() and emit() from Variable.
171 private:
172 SpillVariable(Type Ty, SizeT Index)
173 : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
174 Variable *LinkedTo;
175 };
176
177 class InstX8632 : public InstTarget {
178 InstX8632() = delete;
179 InstX8632(const InstX8632 &) = delete;
180 InstX8632 &operator=(const InstX8632 &) = delete;
181
182 public:
183 enum InstKindX8632 {
184 k__Start = Inst::Target,
185 Adc,
186 AdcRMW,
187 Add,
188 AddRMW,
189 Addps,
190 Addss,
191 Adjuststack,
192 And,
193 AndRMW,
194 Blendvps,
195 Br,
196 Bsf,
197 Bsr,
198 Bswap,
199 Call,
200 Cbwdq,
201 Cmov,
202 Cmpps,
203 Cmpxchg,
204 Cmpxchg8b,
205 Cvt,
206 Div,
207 Divps,
208 Divss,
209 FakeRMW,
210 Fld,
211 Fstp,
212 Icmp,
213 Idiv,
214 Imul,
215 Insertps,
216 Jmp,
217 Label,
218 Lea,
219 Load,
220 Mfence,
221 Mov,
222 Movd,
223 Movp,
224 Movq,
225 MovssRegs,
226 Movsx,
227 Movzx,
228 Mul,
229 Mulps,
230 Mulss,
231 Neg,
232 Nop,
233 Or,
234 OrRMW,
235 Padd,
236 Pand,
237 Pandn,
238 Pblendvb,
239 Pcmpeq,
240 Pcmpgt,
241 Pextr,
242 Pinsr,
243 Pmull,
244 Pmuludq,
245 Pop,
246 Por,
247 Pshufd,
248 Psll,
249 Psra,
250 Psrl,
251 Psub,
252 Push,
253 Pxor,
254 Ret,
255 Rol,
256 Sar,
257 Sbb,
258 SbbRMW,
259 Setcc,
260 Shl,
261 Shld,
262 Shr,
263 Shrd,
264 Shufps,
265 Sqrtss,
266 Store,
267 StoreP,
268 StoreQ,
269 Sub,
270 SubRMW,
271 Subps,
272 Subss,
273 Test,
274 Ucomiss,
275 UD2,
276 Xadd,
277 Xchg,
278 Xor,
279 XorRMW
280 };
281
282 static const char *getWidthString(Type Ty);
283 static const char *getFldString(Type Ty);
284 static X8632::Traits::Cond::BrCond
285 getOppositeCondition(X8632::Traits::Cond::BrCond Cond);
286 void dump(const Cfg *Func) const override;
287
288 /// Shared emit routines for common forms of instructions.
289 /// See the definition of emitTwoAddress() for a description of
290 /// ShiftHack.
291 static void emitTwoAddress(const char *Opcode, const Inst *Inst,
292 const Cfg *Func, bool ShiftHack = false);
293
294 static void
295 emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
296 const Operand *Src,
297 const X8632::AssemblerX8632::GPREmitterShiftOp &Emitter);
298
299 protected:
300 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest)
301 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
302
303 static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) {
304 return Inst->getKind() == static_cast<InstKind>(MyKind);
305 }
306 /// Most instructions that operate on vector arguments require vector
307 /// memory operands to be fully aligned (16-byte alignment for PNaCl
308 /// vector types). The stack frame layout and call ABI ensure proper
309 /// alignment for stack operands, but memory operands (originating
310 /// from load/store bitcode instructions) only have element-size
311 /// alignment guarantees. This function validates that none of the
312 /// operands is a memory operand of vector type, calling
313 /// report_fatal_error() if one is found. This function should be
314 /// called during emission, and maybe also in the ctor (as long as
315 /// that fits the lowering style).
316 void validateVectorAddrMode() const {
317 if (getDest())
318 validateVectorAddrModeOpnd(getDest());
319 for (SizeT i = 0; i < getSrcSize(); ++i) {
320 validateVectorAddrModeOpnd(getSrc(i));
321 }
322 }
323
324 private:
325 static void validateVectorAddrModeOpnd(const Operand *Opnd) {
326 if (llvm::isa<OperandX8632Mem>(Opnd) && isVectorType(Opnd->getType())) {
327 llvm::report_fatal_error("Possible misaligned vector memory operation");
328 }
329 }
330 };
331
332 /// InstX8632FakeRMW represents a non-atomic read-modify-write operation on a
333 /// memory location. An InstX8632FakeRMW is a "fake" instruction in that it
334 /// still needs to be lowered to some actual RMW instruction.
335 ///
336 /// If A is some memory address, D is some data value to apply, and OP is an
337 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D
338 class InstX8632FakeRMW : public InstX8632 {
339 InstX8632FakeRMW() = delete;
340 InstX8632FakeRMW(const InstX8632FakeRMW &) = delete;
341 InstX8632FakeRMW &operator=(const InstX8632FakeRMW &) = delete;
342
343 public:
344 static InstX8632FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr,
345 Variable *Beacon, InstArithmetic::OpKind Op,
346 uint32_t Align = 1) {
347 // TODO(stichnot): Stop ignoring alignment specification.
348 (void)Align;
349 return new (Func->allocate<InstX8632FakeRMW>())
350 InstX8632FakeRMW(Func, Data, Addr, Op, Beacon);
351 }
352 Operand *getAddr() const { return getSrc(1); }
353 Operand *getData() const { return getSrc(0); }
354 InstArithmetic::OpKind getOp() const { return Op; }
355 Variable *getBeacon() const { return llvm::cast<Variable>(getSrc(2)); }
356 void dump(const Cfg *Func) const override;
357 static bool classof(const Inst *Inst) { return isClassof(Inst, FakeRMW); }
358
359 private:
360 InstArithmetic::OpKind Op;
361 InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
362 InstArithmetic::OpKind Op, Variable *Beacon);
363 };
364
365 /// InstX8632Label represents an intra-block label that is the target
366 /// of an intra-block branch. The offset between the label and the
367 /// branch must be fit into one byte (considered "near"). These are
368 /// used for lowering i1 calculations, Select instructions, and 64-bit
369 /// compares on a 32-bit architecture, without basic block splitting.
370 /// Basic block splitting is not so desirable for several reasons, one
371 /// of which is the impact on decisions based on whether a variable's
372 /// live range spans multiple basic blocks.
373 ///
374 /// Intra-block control flow must be used with caution. Consider the
375 /// sequence for "c = (a >= b ? x : y)".
376 /// cmp a, b
377 /// br lt, L1
378 /// mov c, x
379 /// jmp L2
380 /// L1:
381 /// mov c, y
382 /// L2:
383 ///
384 /// Labels L1 and L2 are intra-block labels. Without knowledge of the
385 /// intra-block control flow, liveness analysis will determine the "mov
386 /// c, x" instruction to be dead. One way to prevent this is to insert
387 /// a "FakeUse(c)" instruction anywhere between the two "mov c, ..."
388 /// instructions, e.g.:
389 ///
390 /// cmp a, b
391 /// br lt, L1
392 /// mov c, x
393 /// jmp L2
394 /// FakeUse(c)
395 /// L1:
396 /// mov c, y
397 /// L2:
398 ///
399 /// The down-side is that "mov c, x" can never be dead-code eliminated
400 /// even if there are no uses of c. As unlikely as this situation is,
401 /// it may be prevented by running dead code elimination before
402 /// lowering.
403 class InstX8632Label : public InstX8632 {
404 InstX8632Label() = delete;
405 InstX8632Label(const InstX8632Label &) = delete;
406 InstX8632Label &operator=(const InstX8632Label &) = delete;
407
408 public:
409 static InstX8632Label *create(Cfg *Func, TargetX8632 *Target) {
410 return new (Func->allocate<InstX8632Label>()) InstX8632Label(Func, Target);
411 }
412 uint32_t getEmitInstCount() const override { return 0; }
413 IceString getName(const Cfg *Func) const;
414 SizeT getNumber() const { return Number; }
415 void emit(const Cfg *Func) const override;
416 void emitIAS(const Cfg *Func) const override;
417 void dump(const Cfg *Func) const override;
418
419 private:
420 InstX8632Label(Cfg *Func, TargetX8632 *Target);
421
422 SizeT Number; /// used for unique label generation.
423 };
424
425 /// Conditional and unconditional branch instruction.
426 class InstX8632Br : public InstX8632 {
427 InstX8632Br() = delete;
428 InstX8632Br(const InstX8632Br &) = delete;
429 InstX8632Br &operator=(const InstX8632Br &) = delete;
430
431 public:
432 /// Create a conditional branch to a node.
433 static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
434 CfgNode *TargetFalse,
435 X8632::Traits::Cond::BrCond Condition) {
436 assert(Condition != X8632::Traits::Cond::Br_None);
437 const InstX8632Label *NoLabel = nullptr;
438 return new (Func->allocate<InstX8632Br>())
439 InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
440 }
441 /// Create an unconditional branch to a node.
442 static InstX8632Br *create(Cfg *Func, CfgNode *Target) {
443 const CfgNode *NoCondTarget = nullptr;
444 const InstX8632Label *NoLabel = nullptr;
445 return new (Func->allocate<InstX8632Br>()) InstX8632Br(
446 Func, NoCondTarget, Target, NoLabel, X8632::Traits::Cond::Br_None);
447 }
448 /// Create a non-terminator conditional branch to a node, with a
449 /// fallthrough to the next instruction in the current node. This is
450 /// used for switch lowering.
451 static InstX8632Br *create(Cfg *Func, CfgNode *Target,
452 X8632::Traits::Cond::BrCond Condition) {
453 assert(Condition != X8632::Traits::Cond::Br_None);
454 const CfgNode *NoUncondTarget = nullptr;
455 const InstX8632Label *NoLabel = nullptr;
456 return new (Func->allocate<InstX8632Br>())
457 InstX8632Br(Func, Target, NoUncondTarget, NoLabel, Condition);
458 }
459 /// Create a conditional intra-block branch (or unconditional, if
460 /// Condition==Br_None) to a label in the current block.
461 static InstX8632Br *create(Cfg *Func, InstX8632Label *Label,
462 X8632::Traits::Cond::BrCond Condition) {
463 const CfgNode *NoCondTarget = nullptr;
464 const CfgNode *NoUncondTarget = nullptr;
465 return new (Func->allocate<InstX8632Br>())
466 InstX8632Br(Func, NoCondTarget, NoUncondTarget, Label, Condition);
467 }
468 const CfgNode *getTargetTrue() const { return TargetTrue; }
469 const CfgNode *getTargetFalse() const { return TargetFalse; }
470 bool optimizeBranch(const CfgNode *NextNode);
471 uint32_t getEmitInstCount() const override {
472 uint32_t Sum = 0;
473 if (Label)
474 ++Sum;
475 if (getTargetTrue())
476 ++Sum;
477 if (getTargetFalse())
478 ++Sum;
479 return Sum;
480 }
481 bool isUnconditionalBranch() const override {
482 return !Label && Condition == X8632::Traits::Cond::Br_None;
483 }
484 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
485 void emit(const Cfg *Func) const override;
486 void emitIAS(const Cfg *Func) const override;
487 void dump(const Cfg *Func) const override;
488 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
489
490 private:
491 InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
492 const InstX8632Label *Label,
493 X8632::Traits::Cond::BrCond Condition);
494
495 X8632::Traits::Cond::BrCond Condition;
496 const CfgNode *TargetTrue;
497 const CfgNode *TargetFalse;
498 const InstX8632Label *Label; /// Intra-block branch target
499 };
500
501 /// Jump to a target outside this function, such as tailcall, nacljump,
502 /// naclret, unreachable. This is different from a Branch instruction
503 /// in that there is no intra-function control flow to represent.
504 class InstX8632Jmp : public InstX8632 {
505 InstX8632Jmp() = delete;
506 InstX8632Jmp(const InstX8632Jmp &) = delete;
507 InstX8632Jmp &operator=(const InstX8632Jmp &) = delete;
508
509 public:
510 static InstX8632Jmp *create(Cfg *Func, Operand *Target) {
511 return new (Func->allocate<InstX8632Jmp>()) InstX8632Jmp(Func, Target);
512 }
513 Operand *getJmpTarget() const { return getSrc(0); }
514 void emit(const Cfg *Func) const override;
515 void emitIAS(const Cfg *Func) const override;
516 void dump(const Cfg *Func) const override;
517 static bool classof(const Inst *Inst) { return isClassof(Inst, Jmp); }
518
519 private:
520 InstX8632Jmp(Cfg *Func, Operand *Target);
521 };
522
523 /// AdjustStack instruction - subtracts esp by the given amount and
524 /// updates the stack offset during code emission.
525 class InstX8632AdjustStack : public InstX8632 {
526 InstX8632AdjustStack() = delete;
527 InstX8632AdjustStack(const InstX8632AdjustStack &) = delete;
528 InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) = delete;
529
530 public:
531 static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) {
532 return new (Func->allocate<InstX8632AdjustStack>())
533 InstX8632AdjustStack(Func, Amount, Esp);
534 }
535 void emit(const Cfg *Func) const override;
536 void emitIAS(const Cfg *Func) const override;
537 void dump(const Cfg *Func) const override;
538 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
539
540 private:
541 InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp);
542 SizeT Amount;
543 };
544
545 /// Call instruction. Arguments should have already been pushed.
546 class InstX8632Call : public InstX8632 {
547 InstX8632Call() = delete;
548 InstX8632Call(const InstX8632Call &) = delete;
549 InstX8632Call &operator=(const InstX8632Call &) = delete;
550
551 public:
552 static InstX8632Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
553 return new (Func->allocate<InstX8632Call>())
554 InstX8632Call(Func, Dest, CallTarget);
555 }
556 Operand *getCallTarget() const { return getSrc(0); }
557 void emit(const Cfg *Func) const override;
558 void emitIAS(const Cfg *Func) const override;
559 void dump(const Cfg *Func) const override;
560 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
561
562 private:
563 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
564 };
565
566 /// Emit a one-operand (GPR) instruction.
567 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var,
568 const X8632::AssemblerX8632::GPREmitterOneOp &Emitter);
569 void emitIASAsAddrOpTyGPR(
570 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
571 const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter);
572
573 /// Instructions of the form x := op(x).
574 template <InstX8632::InstKindX8632 K>
575 class InstX8632InplaceopGPR : public InstX8632 {
576 InstX8632InplaceopGPR() = delete;
577 InstX8632InplaceopGPR(const InstX8632InplaceopGPR &) = delete;
578 InstX8632InplaceopGPR &operator=(const InstX8632InplaceopGPR &) = delete;
579
580 public:
581 static InstX8632InplaceopGPR *create(Cfg *Func, Operand *SrcDest) {
582 return new (Func->allocate<InstX8632InplaceopGPR>())
583 InstX8632InplaceopGPR(Func, SrcDest);
584 }
585 void emit(const Cfg *Func) const override {
586 if (!BuildDefs::dump())
587 return;
588 Ostream &Str = Func->getContext()->getStrEmit();
589 assert(getSrcSize() == 1);
590 Str << "\t" << Opcode << "\t";
591 getSrc(0)->emit(Func);
592 }
593 void emitIAS(const Cfg *Func) const override {
594 assert(getSrcSize() == 1);
595 const Variable *Var = getDest();
596 Type Ty = Var->getType();
597 emitIASOpTyGPR(Func, Ty, Var, Emitter);
598 }
599 void dump(const Cfg *Func) const override {
600 if (!BuildDefs::dump())
601 return;
602 Ostream &Str = Func->getContext()->getStrDump();
603 dumpDest(Func);
604 Str << " = " << Opcode << "." << getDest()->getType() << " ";
605 dumpSources(Func);
606 }
607 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
608
609 private:
610 InstX8632InplaceopGPR(Cfg *Func, Operand *SrcDest)
611 : InstX8632(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) {
612 addSource(SrcDest);
613 }
614
615 static const char *Opcode;
616 static const X8632::AssemblerX8632::GPREmitterOneOp Emitter;
617 };
618
619 /// Emit a two-operand (GPR) instruction, where the dest operand is a
620 /// Variable that's guaranteed to be a register.
621 template <bool VarCanBeByte = true, bool SrcCanBeByte = true>
622 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst,
623 const Operand *Src,
624 const X8632::AssemblerX8632::GPREmitterRegOp &Emitter);
625
626 /// Instructions of the form x := op(y).
627 template <InstX8632::InstKindX8632 K>
628 class InstX8632UnaryopGPR : public InstX8632 {
629 InstX8632UnaryopGPR() = delete;
630 InstX8632UnaryopGPR(const InstX8632UnaryopGPR &) = delete;
631 InstX8632UnaryopGPR &operator=(const InstX8632UnaryopGPR &) = delete;
632
633 public:
634 static InstX8632UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) {
635 return new (Func->allocate<InstX8632UnaryopGPR>())
636 InstX8632UnaryopGPR(Func, Dest, Src);
637 }
638 void emit(const Cfg *Func) const override {
639 if (!BuildDefs::dump())
640 return;
641 Ostream &Str = Func->getContext()->getStrEmit();
642 assert(getSrcSize() == 1);
643 Type SrcTy = getSrc(0)->getType();
644 Type DestTy = getDest()->getType();
645 Str << "\t" << Opcode << getWidthString(SrcTy);
646 // Movsx and movzx need both the source and dest type width letter
647 // to define the operation. The other unary operations have the
648 // same source and dest type and as a result need only one letter.
649 if (SrcTy != DestTy)
650 Str << getWidthString(DestTy);
651 Str << "\t";
652 getSrc(0)->emit(Func);
653 Str << ", ";
654 getDest()->emit(Func);
655 }
656 void emitIAS(const Cfg *Func) const override {
657 assert(getSrcSize() == 1);
658 const Variable *Var = getDest();
659 Type Ty = Var->getType();
660 const Operand *Src = getSrc(0);
661 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
662 }
663 void dump(const Cfg *Func) const override {
664 if (!BuildDefs::dump())
665 return;
666 Ostream &Str = Func->getContext()->getStrDump();
667 dumpDest(Func);
668 Str << " = " << Opcode << "." << getSrc(0)->getType() << " ";
669 dumpSources(Func);
670 }
671 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
672
673 private:
674 InstX8632UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src)
675 : InstX8632(Func, K, 1, Dest) {
676 addSource(Src);
677 }
678
679 static const char *Opcode;
680 static const X8632::AssemblerX8632::GPREmitterRegOp Emitter;
681 };
682
683 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
684 const Operand *Src,
685 const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter);
686
687 template <InstX8632::InstKindX8632 K>
688 class InstX8632UnaryopXmm : public InstX8632 {
689 InstX8632UnaryopXmm() = delete;
690 InstX8632UnaryopXmm(const InstX8632UnaryopXmm &) = delete;
691 InstX8632UnaryopXmm &operator=(const InstX8632UnaryopXmm &) = delete;
692
693 public:
694 static InstX8632UnaryopXmm *create(Cfg *Func, Variable *Dest, Operand *Src) {
695 return new (Func->allocate<InstX8632UnaryopXmm>())
696 InstX8632UnaryopXmm(Func, Dest, Src);
697 }
698 void emit(const Cfg *Func) const override {
699 if (!BuildDefs::dump())
700 return;
701 Ostream &Str = Func->getContext()->getStrEmit();
702 assert(getSrcSize() == 1);
703 Str << "\t" << Opcode << "\t";
704 getSrc(0)->emit(Func);
705 Str << ", ";
706 getDest()->emit(Func);
707 }
708 void emitIAS(const Cfg *Func) const override {
709 Type Ty = getDest()->getType();
710 assert(getSrcSize() == 1);
711 emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(0), Emitter);
712 }
713 void dump(const Cfg *Func) const override {
714 if (!BuildDefs::dump())
715 return;
716 Ostream &Str = Func->getContext()->getStrDump();
717 dumpDest(Func);
718 Str << " = " << Opcode << "." << getDest()->getType() << " ";
719 dumpSources(Func);
720 }
721 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
722
723 private:
724 InstX8632UnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src)
725 : InstX8632(Func, K, 1, Dest) {
726 addSource(Src);
727 }
728
729 static const char *Opcode;
730 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter;
731 };
732
733 template <InstX8632::InstKindX8632 K>
734 class InstX8632BinopGPRShift : public InstX8632 {
735 InstX8632BinopGPRShift() = delete;
736 InstX8632BinopGPRShift(const InstX8632BinopGPRShift &) = delete;
737 InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete;
738
739 public:
740 /// Create a binary-op GPR shift instruction.
741 static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest,
742 Operand *Source) {
743 return new (Func->allocate<InstX8632BinopGPRShift>())
744 InstX8632BinopGPRShift(Func, Dest, Source);
745 }
746 void emit(const Cfg *Func) const override {
747 if (!BuildDefs::dump())
748 return;
749 const bool ShiftHack = true;
750 emitTwoAddress(Opcode, this, Func, ShiftHack);
751 }
752 void emitIAS(const Cfg *Func) const override {
753 Type Ty = getDest()->getType();
754 assert(getSrcSize() == 2);
755 emitIASGPRShift(Func, Ty, getDest(), getSrc(1), Emitter);
756 }
757 void dump(const Cfg *Func) const override {
758 if (!BuildDefs::dump())
759 return;
760 Ostream &Str = Func->getContext()->getStrDump();
761 dumpDest(Func);
762 Str << " = " << Opcode << "." << getDest()->getType() << " ";
763 dumpSources(Func);
764 }
765 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
766
767 private:
768 InstX8632BinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source)
769 : InstX8632(Func, K, 2, Dest) {
770 addSource(Dest);
771 addSource(Source);
772 }
773
774 static const char *Opcode;
775 static const X8632::AssemblerX8632::GPREmitterShiftOp Emitter;
776 };
777
778 template <InstX8632::InstKindX8632 K>
779 class InstX8632BinopGPR : public InstX8632 {
780 InstX8632BinopGPR() = delete;
781 InstX8632BinopGPR(const InstX8632BinopGPR &) = delete;
782 InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete;
783
784 public:
785 /// Create an ordinary binary-op instruction like add or sub.
786 static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) {
787 return new (Func->allocate<InstX8632BinopGPR>())
788 InstX8632BinopGPR(Func, Dest, Source);
789 }
790 void emit(const Cfg *Func) const override {
791 if (!BuildDefs::dump())
792 return;
793 const bool ShiftHack = false;
794 emitTwoAddress(Opcode, this, Func, ShiftHack);
795 }
796 void emitIAS(const Cfg *Func) const override {
797 Type Ty = getDest()->getType();
798 assert(getSrcSize() == 2);
799 emitIASRegOpTyGPR(Func, Ty, getDest(), getSrc(1), Emitter);
800 }
801 void dump(const Cfg *Func) const override {
802 if (!BuildDefs::dump())
803 return;
804 Ostream &Str = Func->getContext()->getStrDump();
805 dumpDest(Func);
806 Str << " = " << Opcode << "." << getDest()->getType() << " ";
807 dumpSources(Func);
808 }
809 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
810
811 private:
812 InstX8632BinopGPR(Cfg *Func, Variable *Dest, Operand *Source)
813 : InstX8632(Func, K, 2, Dest) {
814 addSource(Dest);
815 addSource(Source);
816 }
817
818 static const char *Opcode;
819 static const X8632::AssemblerX8632::GPREmitterRegOp Emitter;
820 };
821
822 template <InstX8632::InstKindX8632 K>
823 class InstX8632BinopRMW : public InstX8632 {
824 InstX8632BinopRMW() = delete;
825 InstX8632BinopRMW(const InstX8632BinopRMW &) = delete;
826 InstX8632BinopRMW &operator=(const InstX8632BinopRMW &) = delete;
827
828 public:
829 /// Create an ordinary binary-op instruction like add or sub.
830 static InstX8632BinopRMW *create(Cfg *Func, OperandX8632Mem *DestSrc0,
831 Operand *Src1) {
832 return new (Func->allocate<InstX8632BinopRMW>())
833 InstX8632BinopRMW(Func, DestSrc0, Src1);
834 }
835 void emit(const Cfg *Func) const override {
836 if (!BuildDefs::dump())
837 return;
838 const bool ShiftHack = false;
839 emitTwoAddress(Opcode, this, Func, ShiftHack);
840 }
841 void emitIAS(const Cfg *Func) const override {
842 Type Ty = getSrc(0)->getType();
843 assert(getSrcSize() == 2);
844 emitIASAsAddrOpTyGPR(Func, Ty, getSrc(0), getSrc(1), Emitter);
845 }
846 void dump(const Cfg *Func) const override {
847 if (!BuildDefs::dump())
848 return;
849 Ostream &Str = Func->getContext()->getStrDump();
850 Str << Opcode << "." << getSrc(0)->getType() << " ";
851 dumpSources(Func);
852 }
853 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
854
855 private:
856 InstX8632BinopRMW(Cfg *Func, OperandX8632Mem *DestSrc0, Operand *Src1)
857 : InstX8632(Func, K, 2, nullptr) {
858 addSource(DestSrc0);
859 addSource(Src1);
860 }
861 static const char *Opcode;
862 static const X8632::AssemblerX8632::GPREmitterAddrOp Emitter;
863 };
864
865 template <InstX8632::InstKindX8632 K, bool NeedsElementType>
866 class InstX8632BinopXmm : public InstX8632 {
867 InstX8632BinopXmm() = delete;
868 InstX8632BinopXmm(const InstX8632BinopXmm &) = delete;
869 InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete;
870
871 public:
872 /// Create an XMM binary-op instruction like addss or addps.
873 static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) {
874 return new (Func->allocate<InstX8632BinopXmm>())
875 InstX8632BinopXmm(Func, Dest, Source);
876 }
877 void emit(const Cfg *Func) const override {
878 if (!BuildDefs::dump())
879 return;
880 validateVectorAddrMode();
881 const bool ShiftHack = false;
882 emitTwoAddress(Opcode, this, Func, ShiftHack);
883 }
884 void emitIAS(const Cfg *Func) const override {
885 validateVectorAddrMode();
886 Type Ty = getDest()->getType();
887 if (NeedsElementType)
888 Ty = typeElementType(Ty);
889 assert(getSrcSize() == 2);
890 emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(1), Emitter);
891 }
892 void dump(const Cfg *Func) const override {
893 if (!BuildDefs::dump())
894 return;
895 Ostream &Str = Func->getContext()->getStrDump();
896 dumpDest(Func);
897 Str << " = " << Opcode << "." << getDest()->getType() << " ";
898 dumpSources(Func);
899 }
900 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
901
902 private:
903 InstX8632BinopXmm(Cfg *Func, Variable *Dest, Operand *Source)
904 : InstX8632(Func, K, 2, Dest) {
905 addSource(Dest);
906 addSource(Source);
907 }
908
909 static const char *Opcode;
910 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter;
911 };
912
913 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
914 const Operand *Src,
915 const X8632::AssemblerX8632::XmmEmitterShiftOp &Emitter);
916
917 template <InstX8632::InstKindX8632 K, bool AllowAllTypes = false>
918 class InstX8632BinopXmmShift : public InstX8632 {
919 InstX8632BinopXmmShift() = delete;
920 InstX8632BinopXmmShift(const InstX8632BinopXmmShift &) = delete;
921 InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete;
922
923 public:
924 /// Create an XMM binary-op shift operation.
925 static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest,
926 Operand *Source) {
927 return new (Func->allocate<InstX8632BinopXmmShift>())
928 InstX8632BinopXmmShift(Func, Dest, Source);
929 }
930 void emit(const Cfg *Func) const override {
931 if (!BuildDefs::dump())
932 return;
933 validateVectorAddrMode();
934 const bool ShiftHack = false;
935 emitTwoAddress(Opcode, this, Func, ShiftHack);
936 }
937 void emitIAS(const Cfg *Func) const override {
938 validateVectorAddrMode();
939 Type Ty = getDest()->getType();
940 assert(AllowAllTypes || isVectorType(Ty));
941 Type ElementTy = typeElementType(Ty);
942 assert(getSrcSize() == 2);
943 emitIASXmmShift(Func, ElementTy, getDest(), getSrc(1), Emitter);
944 }
945 void dump(const Cfg *Func) const override {
946 if (!BuildDefs::dump())
947 return;
948 Ostream &Str = Func->getContext()->getStrDump();
949 dumpDest(Func);
950 Str << " = " << Opcode << "." << getDest()->getType() << " ";
951 dumpSources(Func);
952 }
953 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
954
955 private:
956 InstX8632BinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source)
957 : InstX8632(Func, K, 2, Dest) {
958 addSource(Dest);
959 addSource(Source);
960 }
961
962 static const char *Opcode;
963 static const X8632::AssemblerX8632::XmmEmitterShiftOp Emitter;
964 };
965
966 template <InstX8632::InstKindX8632 K> class InstX8632Ternop : public InstX8632 {
967 InstX8632Ternop() = delete;
968 InstX8632Ternop(const InstX8632Ternop &) = delete;
969 InstX8632Ternop &operator=(const InstX8632Ternop &) = delete;
970
971 public:
972 /// Create a ternary-op instruction like div or idiv.
973 static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1,
974 Operand *Source2) {
975 return new (Func->allocate<InstX8632Ternop>())
976 InstX8632Ternop(Func, Dest, Source1, Source2);
977 }
978 void emit(const Cfg *Func) const override {
979 if (!BuildDefs::dump())
980 return;
981 Ostream &Str = Func->getContext()->getStrEmit();
982 assert(getSrcSize() == 3);
983 Str << "\t" << Opcode << "\t";
984 getSrc(2)->emit(Func);
985 Str << ", ";
986 getSrc(1)->emit(Func);
987 Str << ", ";
988 getDest()->emit(Func);
989 }
990 void emitIAS(const Cfg *Func) const override;
991 void dump(const Cfg *Func) const override {
992 if (!BuildDefs::dump())
993 return;
994 Ostream &Str = Func->getContext()->getStrDump();
995 dumpDest(Func);
996 Str << " = " << Opcode << "." << getDest()->getType() << " ";
997 dumpSources(Func);
998 }
999 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1000
1001 private:
1002 InstX8632Ternop(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2)
1003 : InstX8632(Func, K, 3, Dest) {
1004 addSource(Dest);
1005 addSource(Source1);
1006 addSource(Source2);
1007 }
1008
1009 static const char *Opcode;
1010 };
1011
1012 /// Instructions of the form x := y op z
1013 template <InstX8632::InstKindX8632 K>
1014 class InstX8632ThreeAddressop : public InstX8632 {
1015 InstX8632ThreeAddressop() = delete;
1016 InstX8632ThreeAddressop(const InstX8632ThreeAddressop &) = delete;
1017 InstX8632ThreeAddressop &operator=(const InstX8632ThreeAddressop &) = delete;
1018
1019 public:
1020 static InstX8632ThreeAddressop *create(Cfg *Func, Variable *Dest,
1021 Operand *Source0, Operand *Source1) {
1022 return new (Func->allocate<InstX8632ThreeAddressop>())
1023 InstX8632ThreeAddressop(Func, Dest, Source0, Source1);
1024 }
1025 void emit(const Cfg *Func) const override {
1026 if (!BuildDefs::dump())
1027 return;
1028 Ostream &Str = Func->getContext()->getStrEmit();
1029 assert(getSrcSize() == 2);
1030 Str << "\t" << Opcode << "\t";
1031 getSrc(1)->emit(Func);
1032 Str << ", ";
1033 getSrc(0)->emit(Func);
1034 Str << ", ";
1035 getDest()->emit(Func);
1036 }
1037 void emitIAS(const Cfg *Func) const override;
1038 void dump(const Cfg *Func) const override {
1039 if (!BuildDefs::dump())
1040 return;
1041 Ostream &Str = Func->getContext()->getStrDump();
1042 dumpDest(Func);
1043 Str << " = " << Opcode << "." << getDest()->getType() << " ";
1044 dumpSources(Func);
1045 }
1046 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1047
1048 private:
1049 InstX8632ThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0,
1050 Operand *Source1)
1051 : InstX8632(Func, K, 2, Dest) {
1052 addSource(Source0);
1053 addSource(Source1);
1054 }
1055
1056 static const char *Opcode;
1057 };
1058
1059 /// Base class for assignment instructions
1060 template <InstX8632::InstKindX8632 K>
1061 class InstX8632Movlike : public InstX8632 {
1062 InstX8632Movlike() = delete;
1063 InstX8632Movlike(const InstX8632Movlike &) = delete;
1064 InstX8632Movlike &operator=(const InstX8632Movlike &) = delete;
1065
1066 public:
1067 static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) {
1068 return new (Func->allocate<InstX8632Movlike>())
1069 InstX8632Movlike(Func, Dest, Source);
1070 }
1071 bool isRedundantAssign() const override {
1072 return checkForRedundantAssign(getDest(), getSrc(0));
1073 }
1074 bool isSimpleAssign() const override { return true; }
1075 void emit(const Cfg *Func) const override;
1076 void emitIAS(const Cfg *Func) const override;
1077 void dump(const Cfg *Func) const override {
1078 if (!BuildDefs::dump())
1079 return;
1080 Ostream &Str = Func->getContext()->getStrDump();
1081 Str << Opcode << "." << getDest()->getType() << " ";
1082 dumpDest(Func);
1083 Str << ", ";
1084 dumpSources(Func);
1085 }
1086 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1087
1088 private:
1089 InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source)
1090 : InstX8632(Func, K, 1, Dest) {
1091 addSource(Source);
1092 }
1093
1094 static const char *Opcode;
1095 };
1096
1097 typedef InstX8632InplaceopGPR<InstX8632::Bswap> InstX8632Bswap;
1098 typedef InstX8632InplaceopGPR<InstX8632::Neg> InstX8632Neg;
1099 typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf;
1100 typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr;
1101 typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea;
1102 /// Cbwdq instruction - wrapper for cbw, cwd, and cdq
1103 typedef InstX8632UnaryopGPR<InstX8632::Cbwdq> InstX8632Cbwdq;
1104 typedef InstX8632UnaryopGPR<InstX8632::Movsx> InstX8632Movsx;
1105 typedef InstX8632UnaryopGPR<InstX8632::Movzx> InstX8632Movzx;
1106 typedef InstX8632UnaryopXmm<InstX8632::Movd> InstX8632Movd;
1107 typedef InstX8632UnaryopXmm<InstX8632::Sqrtss> InstX8632Sqrtss;
1108 /// Move/assignment instruction - wrapper for mov/movss/movsd.
1109 typedef InstX8632Movlike<InstX8632::Mov> InstX8632Mov;
1110 /// Move packed - copy 128 bit values between XMM registers, or mem128
1111 /// and XMM registers.
1112 typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp;
1113 /// Movq - copy between XMM registers, or mem64 and XMM registers.
1114 typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq;
1115 typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add;
1116 typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW;
1117 typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps;
1118 typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc;
1119 typedef InstX8632BinopRMW<InstX8632::AdcRMW> InstX8632AdcRMW;
1120 typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss;
1121 typedef InstX8632BinopXmm<InstX8632::Padd, true> InstX8632Padd;
1122 typedef InstX8632BinopGPR<InstX8632::Sub> InstX8632Sub;
1123 typedef InstX8632BinopRMW<InstX8632::SubRMW> InstX8632SubRMW;
1124 typedef InstX8632BinopXmm<InstX8632::Subps, true> InstX8632Subps;
1125 typedef InstX8632BinopXmm<InstX8632::Subss, false> InstX8632Subss;
1126 typedef InstX8632BinopGPR<InstX8632::Sbb> InstX8632Sbb;
1127 typedef InstX8632BinopRMW<InstX8632::SbbRMW> InstX8632SbbRMW;
1128 typedef InstX8632BinopXmm<InstX8632::Psub, true> InstX8632Psub;
1129 typedef InstX8632BinopGPR<InstX8632::And> InstX8632And;
1130 typedef InstX8632BinopRMW<InstX8632::AndRMW> InstX8632AndRMW;
1131 typedef InstX8632BinopXmm<InstX8632::Pand, false> InstX8632Pand;
1132 typedef InstX8632BinopXmm<InstX8632::Pandn, false> InstX8632Pandn;
1133 typedef InstX8632BinopGPR<InstX8632::Or> InstX8632Or;
1134 typedef InstX8632BinopRMW<InstX8632::OrRMW> InstX8632OrRMW;
1135 typedef InstX8632BinopXmm<InstX8632::Por, false> InstX8632Por;
1136 typedef InstX8632BinopGPR<InstX8632::Xor> InstX8632Xor;
1137 typedef InstX8632BinopRMW<InstX8632::XorRMW> InstX8632XorRMW;
1138 typedef InstX8632BinopXmm<InstX8632::Pxor, false> InstX8632Pxor;
1139 typedef InstX8632BinopGPR<InstX8632::Imul> InstX8632Imul;
1140 typedef InstX8632BinopXmm<InstX8632::Mulps, true> InstX8632Mulps;
1141 typedef InstX8632BinopXmm<InstX8632::Mulss, false> InstX8632Mulss;
1142 typedef InstX8632BinopXmm<InstX8632::Pmull, true> InstX8632Pmull;
1143 typedef InstX8632BinopXmm<InstX8632::Pmuludq, false> InstX8632Pmuludq;
1144 typedef InstX8632BinopXmm<InstX8632::Divps, true> InstX8632Divps;
1145 typedef InstX8632BinopXmm<InstX8632::Divss, false> InstX8632Divss;
1146 typedef InstX8632BinopGPRShift<InstX8632::Rol> InstX8632Rol;
1147 typedef InstX8632BinopGPRShift<InstX8632::Shl> InstX8632Shl;
1148 typedef InstX8632BinopXmmShift<InstX8632::Psll> InstX8632Psll;
1149 typedef InstX8632BinopXmmShift<InstX8632::Psrl, true> InstX8632Psrl;
1150 typedef InstX8632BinopGPRShift<InstX8632::Shr> InstX8632Shr;
1151 typedef InstX8632BinopGPRShift<InstX8632::Sar> InstX8632Sar;
1152 typedef InstX8632BinopXmmShift<InstX8632::Psra> InstX8632Psra;
1153 typedef InstX8632BinopXmm<InstX8632::Pcmpeq, true> InstX8632Pcmpeq;
1154 typedef InstX8632BinopXmm<InstX8632::Pcmpgt, true> InstX8632Pcmpgt;
1155 /// movss is only a binary operation when the source and dest
1156 /// operands are both registers (the high bits of dest are left untouched).
1157 /// In other cases, it behaves like a copy (mov-like) operation (and the
1158 /// high bits of dest are cleared).
1159 /// InstX8632Movss will assert that both its source and dest operands are
1160 /// registers, so the lowering code should use _mov instead of _movss
1161 /// in cases where a copy operation is intended.
1162 typedef InstX8632BinopXmm<InstX8632::MovssRegs, false> InstX8632MovssRegs;
1163 typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv;
1164 typedef InstX8632Ternop<InstX8632::Div> InstX8632Div;
1165 typedef InstX8632Ternop<InstX8632::Insertps> InstX8632Insertps;
1166 typedef InstX8632Ternop<InstX8632::Pinsr> InstX8632Pinsr;
1167 typedef InstX8632Ternop<InstX8632::Shufps> InstX8632Shufps;
1168 typedef InstX8632Ternop<InstX8632::Blendvps> InstX8632Blendvps;
1169 typedef InstX8632Ternop<InstX8632::Pblendvb> InstX8632Pblendvb;
1170 typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr;
1171 typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd;
1172
1173 /// Base class for a lockable x86-32 instruction (emits a locked prefix).
1174 class InstX8632Lockable : public InstX8632 {
1175 InstX8632Lockable() = delete;
1176 InstX8632Lockable(const InstX8632Lockable &) = delete;
1177 InstX8632Lockable &operator=(const InstX8632Lockable &) = delete;
1178
1179 protected:
1180 bool Locked;
1181
1182 InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs,
1183 Variable *Dest, bool Locked)
1184 : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) {
1185 // Assume that such instructions are used for Atomics and be careful
1186 // with optimizations.
1187 HasSideEffects = Locked;
1188 }
1189 };
1190
1191 /// Mul instruction - unsigned multiply.
1192 class InstX8632Mul : public InstX8632 {
1193 InstX8632Mul() = delete;
1194 InstX8632Mul(const InstX8632Mul &) = delete;
1195 InstX8632Mul &operator=(const InstX8632Mul &) = delete;
1196
1197 public:
1198 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1,
1199 Operand *Source2) {
1200 return new (Func->allocate<InstX8632Mul>())
1201 InstX8632Mul(Func, Dest, Source1, Source2);
1202 }
1203 void emit(const Cfg *Func) const override;
1204 void emitIAS(const Cfg *Func) const override;
1205 void dump(const Cfg *Func) const override;
1206 static bool classof(const Inst *Inst) { return isClassof(Inst, Mul); }
1207
1208 private:
1209 InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2);
1210 };
1211
1212 /// Shld instruction - shift across a pair of operands.
1213 class InstX8632Shld : public InstX8632 {
1214 InstX8632Shld() = delete;
1215 InstX8632Shld(const InstX8632Shld &) = delete;
1216 InstX8632Shld &operator=(const InstX8632Shld &) = delete;
1217
1218 public:
1219 static InstX8632Shld *create(Cfg *Func, Variable *Dest, Variable *Source1,
1220 Variable *Source2) {
1221 return new (Func->allocate<InstX8632Shld>())
1222 InstX8632Shld(Func, Dest, Source1, Source2);
1223 }
1224 void emit(const Cfg *Func) const override;
1225 void emitIAS(const Cfg *Func) const override;
1226 void dump(const Cfg *Func) const override;
1227 static bool classof(const Inst *Inst) { return isClassof(Inst, Shld); }
1228
1229 private:
1230 InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
1231 Variable *Source2);
1232 };
1233
1234 /// Shrd instruction - shift across a pair of operands.
1235 class InstX8632Shrd : public InstX8632 {
1236 InstX8632Shrd() = delete;
1237 InstX8632Shrd(const InstX8632Shrd &) = delete;
1238 InstX8632Shrd &operator=(const InstX8632Shrd &) = delete;
1239
1240 public:
1241 static InstX8632Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1,
1242 Variable *Source2) {
1243 return new (Func->allocate<InstX8632Shrd>())
1244 InstX8632Shrd(Func, Dest, Source1, Source2);
1245 }
1246 void emit(const Cfg *Func) const override;
1247 void emitIAS(const Cfg *Func) const override;
1248 void dump(const Cfg *Func) const override;
1249 static bool classof(const Inst *Inst) { return isClassof(Inst, Shrd); }
1250
1251 private:
1252 InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
1253 Variable *Source2);
1254 };
1255
1256 /// Conditional move instruction.
1257 class InstX8632Cmov : public InstX8632 {
1258 InstX8632Cmov() = delete;
1259 InstX8632Cmov(const InstX8632Cmov &) = delete;
1260 InstX8632Cmov &operator=(const InstX8632Cmov &) = delete;
1261
1262 public:
1263 static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source,
1264 X8632::Traits::Cond::BrCond Cond) {
1265 return new (Func->allocate<InstX8632Cmov>())
1266 InstX8632Cmov(Func, Dest, Source, Cond);
1267 }
1268 void emit(const Cfg *Func) const override;
1269 void emitIAS(const Cfg *Func) const override;
1270 void dump(const Cfg *Func) const override;
1271 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); }
1272
1273 private:
1274 InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
1275 X8632::Traits::Cond::BrCond Cond);
1276
1277 X8632::Traits::Cond::BrCond Condition;
1278 };
1279
1280 /// Cmpps instruction - compare packed singled-precision floating point
1281 /// values
1282 class InstX8632Cmpps : public InstX8632 {
1283 InstX8632Cmpps() = delete;
1284 InstX8632Cmpps(const InstX8632Cmpps &) = delete;
1285 InstX8632Cmpps &operator=(const InstX8632Cmpps &) = delete;
1286
1287 public:
1288 static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source,
1289 X8632::Traits::Cond::CmppsCond Condition) {
1290 return new (Func->allocate<InstX8632Cmpps>())
1291 InstX8632Cmpps(Func, Dest, Source, Condition);
1292 }
1293 void emit(const Cfg *Func) const override;
1294 void emitIAS(const Cfg *Func) const override;
1295 void dump(const Cfg *Func) const override;
1296 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpps); }
1297
1298 private:
1299 InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
1300 X8632::Traits::Cond::CmppsCond Cond);
1301
1302 X8632::Traits::Cond::CmppsCond Condition;
1303 };
1304
1305 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest>
1306 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>.
1307 /// If not, ZF is cleared and <dest> is copied to eax (or subregister).
1308 /// <dest> can be a register or memory, while <desired> must be a register.
1309 /// It is the user's responsiblity to mark eax with a FakeDef.
1310 class InstX8632Cmpxchg : public InstX8632Lockable {
1311 InstX8632Cmpxchg() = delete;
1312 InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete;
1313 InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) = delete;
1314
1315 public:
1316 static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
1317 Variable *Desired, bool Locked) {
1318 return new (Func->allocate<InstX8632Cmpxchg>())
1319 InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked);
1320 }
1321 void emit(const Cfg *Func) const override;
1322 void emitIAS(const Cfg *Func) const override;
1323 void dump(const Cfg *Func) const override;
1324 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); }
1325
1326 private:
1327 InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
1328 Variable *Desired, bool Locked);
1329 };
1330
1331 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64>
1332 /// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>.
1333 /// If not, ZF is cleared and <m64> is copied to edx:eax.
1334 /// The caller is responsible for inserting FakeDefs to mark edx
1335 /// and eax as modified.
1336 /// <m64> must be a memory operand.
1337 class InstX8632Cmpxchg8b : public InstX8632Lockable {
1338 InstX8632Cmpxchg8b() = delete;
1339 InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete;
1340 InstX8632Cmpxchg8b &operator=(const InstX8632Cmpxchg8b &) = delete;
1341
1342 public:
1343 static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest,
1344 Variable *Edx, Variable *Eax, Variable *Ecx,
1345 Variable *Ebx, bool Locked) {
1346 return new (Func->allocate<InstX8632Cmpxchg8b>())
1347 InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked);
1348 }
1349 void emit(const Cfg *Func) const override;
1350 void emitIAS(const Cfg *Func) const override;
1351 void dump(const Cfg *Func) const override;
1352 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); }
1353
1354 private:
1355 InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx,
1356 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked);
1357 };
1358
1359 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i}
1360 /// as appropriate. s=float, d=double, i=int. X and Y are determined
1361 /// from dest/src types. Sign and zero extension on the integer
1362 /// operand needs to be done separately.
1363 class InstX8632Cvt : public InstX8632 {
1364 InstX8632Cvt() = delete;
1365 InstX8632Cvt(const InstX8632Cvt &) = delete;
1366 InstX8632Cvt &operator=(const InstX8632Cvt &) = delete;
1367
1368 public:
1369 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq };
1370 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source,
1371 CvtVariant Variant) {
1372 return new (Func->allocate<InstX8632Cvt>())
1373 InstX8632Cvt(Func, Dest, Source, Variant);
1374 }
1375 void emit(const Cfg *Func) const override;
1376 void emitIAS(const Cfg *Func) const override;
1377 void dump(const Cfg *Func) const override;
1378 static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); }
1379 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; }
1380
1381 private:
1382 CvtVariant Variant;
1383 InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant);
1384 };
1385
1386 /// cmp - Integer compare instruction.
1387 class InstX8632Icmp : public InstX8632 {
1388 InstX8632Icmp() = delete;
1389 InstX8632Icmp(const InstX8632Icmp &) = delete;
1390 InstX8632Icmp &operator=(const InstX8632Icmp &) = delete;
1391
1392 public:
1393 static InstX8632Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) {
1394 return new (Func->allocate<InstX8632Icmp>())
1395 InstX8632Icmp(Func, Src1, Src2);
1396 }
1397 void emit(const Cfg *Func) const override;
1398 void emitIAS(const Cfg *Func) const override;
1399 void dump(const Cfg *Func) const override;
1400 static bool classof(const Inst *Inst) { return isClassof(Inst, Icmp); }
1401
1402 private:
1403 InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2);
1404 };
1405
1406 /// ucomiss/ucomisd - floating-point compare instruction.
1407 class InstX8632Ucomiss : public InstX8632 {
1408 InstX8632Ucomiss() = delete;
1409 InstX8632Ucomiss(const InstX8632Ucomiss &) = delete;
1410 InstX8632Ucomiss &operator=(const InstX8632Ucomiss &) = delete;
1411
1412 public:
1413 static InstX8632Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) {
1414 return new (Func->allocate<InstX8632Ucomiss>())
1415 InstX8632Ucomiss(Func, Src1, Src2);
1416 }
1417 void emit(const Cfg *Func) const override;
1418 void emitIAS(const Cfg *Func) const override;
1419 void dump(const Cfg *Func) const override;
1420 static bool classof(const Inst *Inst) { return isClassof(Inst, Ucomiss); }
1421
1422 private:
1423 InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2);
1424 };
1425
1426 /// UD2 instruction.
1427 class InstX8632UD2 : public InstX8632 {
1428 InstX8632UD2() = delete;
1429 InstX8632UD2(const InstX8632UD2 &) = delete;
1430 InstX8632UD2 &operator=(const InstX8632UD2 &) = delete;
1431
1432 public:
1433 static InstX8632UD2 *create(Cfg *Func) {
1434 return new (Func->allocate<InstX8632UD2>()) InstX8632UD2(Func);
1435 }
1436 void emit(const Cfg *Func) const override;
1437 void emitIAS(const Cfg *Func) const override;
1438 void dump(const Cfg *Func) const override;
1439 static bool classof(const Inst *Inst) { return isClassof(Inst, UD2); }
1440
1441 private:
1442 explicit InstX8632UD2(Cfg *Func);
1443 };
1444
1445 /// Test instruction.
1446 class InstX8632Test : public InstX8632 {
1447 InstX8632Test() = delete;
1448 InstX8632Test(const InstX8632Test &) = delete;
1449 InstX8632Test &operator=(const InstX8632Test &) = delete;
1450
1451 public:
1452 static InstX8632Test *create(Cfg *Func, Operand *Source1, Operand *Source2) {
1453 return new (Func->allocate<InstX8632Test>())
1454 InstX8632Test(Func, Source1, Source2);
1455 }
1456 void emit(const Cfg *Func) const override;
1457 void emitIAS(const Cfg *Func) const override;
1458 void dump(const Cfg *Func) const override;
1459 static bool classof(const Inst *Inst) { return isClassof(Inst, Test); }
1460
1461 private:
1462 InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2);
1463 };
1464
1465 /// Mfence instruction.
1466 class InstX8632Mfence : public InstX8632 {
1467 InstX8632Mfence() = delete;
1468 InstX8632Mfence(const InstX8632Mfence &) = delete;
1469 InstX8632Mfence &operator=(const InstX8632Mfence &) = delete;
1470
1471 public:
1472 static InstX8632Mfence *create(Cfg *Func) {
1473 return new (Func->allocate<InstX8632Mfence>()) InstX8632Mfence(Func);
1474 }
1475 void emit(const Cfg *Func) const override;
1476 void emitIAS(const Cfg *Func) const override;
1477 void dump(const Cfg *Func) const override;
1478 static bool classof(const Inst *Inst) { return isClassof(Inst, Mfence); }
1479
1480 private:
1481 explicit InstX8632Mfence(Cfg *Func);
1482 };
1483
1484 /// This is essentially a "mov" instruction with an OperandX8632Mem
1485 /// operand instead of Variable as the destination. It's important
1486 /// for liveness that there is no Dest operand.
1487 class InstX8632Store : public InstX8632 {
1488 InstX8632Store() = delete;
1489 InstX8632Store(const InstX8632Store &) = delete;
1490 InstX8632Store &operator=(const InstX8632Store &) = delete;
1491
1492 public:
1493 static InstX8632Store *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) {
1494 return new (Func->allocate<InstX8632Store>())
1495 InstX8632Store(Func, Value, Mem);
1496 }
1497 void emit(const Cfg *Func) const override;
1498 void emitIAS(const Cfg *Func) const override;
1499 void dump(const Cfg *Func) const override;
1500 static bool classof(const Inst *Inst) { return isClassof(Inst, Store); }
1501
1502 private:
1503 InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem);
1504 };
1505
1506 /// This is essentially a vector "mov" instruction with an OperandX8632Mem
1507 /// operand instead of Variable as the destination. It's important
1508 /// for liveness that there is no Dest operand. The source must be an
1509 /// Xmm register, since Dest is mem.
1510 class InstX8632StoreP : public InstX8632 {
1511 InstX8632StoreP() = delete;
1512 InstX8632StoreP(const InstX8632StoreP &) = delete;
1513 InstX8632StoreP &operator=(const InstX8632StoreP &) = delete;
1514
1515 public:
1516 static InstX8632StoreP *create(Cfg *Func, Variable *Value,
1517 OperandX8632Mem *Mem) {
1518 return new (Func->allocate<InstX8632StoreP>())
1519 InstX8632StoreP(Func, Value, Mem);
1520 }
1521 void emit(const Cfg *Func) const override;
1522 void emitIAS(const Cfg *Func) const override;
1523 void dump(const Cfg *Func) const override;
1524 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreP); }
1525
1526 private:
1527 InstX8632StoreP(Cfg *Func, Variable *Value, OperandX8632Mem *Mem);
1528 };
1529
1530 class InstX8632StoreQ : public InstX8632 {
1531 InstX8632StoreQ() = delete;
1532 InstX8632StoreQ(const InstX8632StoreQ &) = delete;
1533 InstX8632StoreQ &operator=(const InstX8632StoreQ &) = delete;
1534
1535 public:
1536 static InstX8632StoreQ *create(Cfg *Func, Variable *Value,
1537 OperandX8632Mem *Mem) {
1538 return new (Func->allocate<InstX8632StoreQ>())
1539 InstX8632StoreQ(Func, Value, Mem);
1540 }
1541 void emit(const Cfg *Func) const override;
1542 void emitIAS(const Cfg *Func) const override;
1543 void dump(const Cfg *Func) const override;
1544 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreQ); }
1545
1546 private:
1547 InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem);
1548 };
1549
1550 /// Nop instructions of varying length
1551 class InstX8632Nop : public InstX8632 {
1552 InstX8632Nop() = delete;
1553 InstX8632Nop(const InstX8632Nop &) = delete;
1554 InstX8632Nop &operator=(const InstX8632Nop &) = delete;
1555
1556 public:
1557 // TODO: Replace with enum.
1558 typedef unsigned NopVariant;
1559
1560 static InstX8632Nop *create(Cfg *Func, NopVariant Variant) {
1561 return new (Func->allocate<InstX8632Nop>()) InstX8632Nop(Func, Variant);
1562 }
1563 void emit(const Cfg *Func) const override;
1564 void emitIAS(const Cfg *Func) const override;
1565 void dump(const Cfg *Func) const override;
1566 static bool classof(const Inst *Inst) { return isClassof(Inst, Nop); }
1567
1568 private:
1569 InstX8632Nop(Cfg *Func, SizeT Length);
1570
1571 NopVariant Variant;
1572 };
1573
1574 /// Fld - load a value onto the x87 FP stack.
1575 class InstX8632Fld : public InstX8632 {
1576 InstX8632Fld() = delete;
1577 InstX8632Fld(const InstX8632Fld &) = delete;
1578 InstX8632Fld &operator=(const InstX8632Fld &) = delete;
1579
1580 public:
1581 static InstX8632Fld *create(Cfg *Func, Operand *Src) {
1582 return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src);
1583 }
1584 void emit(const Cfg *Func) const override;
1585 void emitIAS(const Cfg *Func) const override;
1586 void dump(const Cfg *Func) const override;
1587 static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); }
1588
1589 private:
1590 InstX8632Fld(Cfg *Func, Operand *Src);
1591 };
1592
1593 /// Fstp - store x87 st(0) into memory and pop st(0).
1594 class InstX8632Fstp : public InstX8632 {
1595 InstX8632Fstp() = delete;
1596 InstX8632Fstp(const InstX8632Fstp &) = delete;
1597 InstX8632Fstp &operator=(const InstX8632Fstp &) = delete;
1598
1599 public:
1600 static InstX8632Fstp *create(Cfg *Func, Variable *Dest) {
1601 return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest);
1602 }
1603 void emit(const Cfg *Func) const override;
1604 void emitIAS(const Cfg *Func) const override;
1605 void dump(const Cfg *Func) const override;
1606 static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); }
1607
1608 private:
1609 InstX8632Fstp(Cfg *Func, Variable *Dest);
1610 };
1611
1612 class InstX8632Pop : public InstX8632 {
1613 InstX8632Pop() = delete;
1614 InstX8632Pop(const InstX8632Pop &) = delete;
1615 InstX8632Pop &operator=(const InstX8632Pop &) = delete;
1616
1617 public:
1618 static InstX8632Pop *create(Cfg *Func, Variable *Dest) {
1619 return new (Func->allocate<InstX8632Pop>()) InstX8632Pop(Func, Dest);
1620 }
1621 void emit(const Cfg *Func) const override;
1622 void emitIAS(const Cfg *Func) const override;
1623 void dump(const Cfg *Func) const override;
1624 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
1625
1626 private:
1627 InstX8632Pop(Cfg *Func, Variable *Dest);
1628 };
1629
1630 class InstX8632Push : public InstX8632 {
1631 InstX8632Push() = delete;
1632 InstX8632Push(const InstX8632Push &) = delete;
1633 InstX8632Push &operator=(const InstX8632Push &) = delete;
1634
1635 public:
1636 static InstX8632Push *create(Cfg *Func, Variable *Source) {
1637 return new (Func->allocate<InstX8632Push>()) InstX8632Push(Func, Source);
1638 }
1639 void emit(const Cfg *Func) const override;
1640 void emitIAS(const Cfg *Func) const override;
1641 void dump(const Cfg *Func) const override;
1642 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
1643
1644 private:
1645 InstX8632Push(Cfg *Func, Variable *Source);
1646 };
1647
1648 /// Ret instruction. Currently only supports the "ret" version that
1649 /// does not pop arguments. This instruction takes a Source operand
1650 /// (for non-void returning functions) for liveness analysis, though
1651 /// a FakeUse before the ret would do just as well.
1652 class InstX8632Ret : public InstX8632 {
1653 InstX8632Ret() = delete;
1654 InstX8632Ret(const InstX8632Ret &) = delete;
1655 InstX8632Ret &operator=(const InstX8632Ret &) = delete;
1656
1657 public:
1658 static InstX8632Ret *create(Cfg *Func, Variable *Source = nullptr) {
1659 return new (Func->allocate<InstX8632Ret>()) InstX8632Ret(Func, Source);
1660 }
1661 void emit(const Cfg *Func) const override;
1662 void emitIAS(const Cfg *Func) const override;
1663 void dump(const Cfg *Func) const override;
1664 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
1665
1666 private:
1667 InstX8632Ret(Cfg *Func, Variable *Source);
1668 };
1669
1670 /// Conditional set-byte instruction.
1671 class InstX8632Setcc : public InstX8632 {
1672 InstX8632Setcc() = delete;
1673 InstX8632Setcc(const InstX8632Cmov &) = delete;
1674 InstX8632Setcc &operator=(const InstX8632Setcc &) = delete;
1675
1676 public:
1677 static InstX8632Setcc *create(Cfg *Func, Variable *Dest,
1678 X8632::Traits::Cond::BrCond Cond) {
1679 return new (Func->allocate<InstX8632Setcc>())
1680 InstX8632Setcc(Func, Dest, Cond);
1681 }
1682 void emit(const Cfg *Func) const override;
1683 void emitIAS(const Cfg *Func) const override;
1684 void dump(const Cfg *Func) const override;
1685 static bool classof(const Inst *Inst) { return isClassof(Inst, Setcc); }
1686
1687 private:
1688 InstX8632Setcc(Cfg *Func, Variable *Dest, X8632::Traits::Cond::BrCond Cond);
1689
1690 const X8632::Traits::Cond::BrCond Condition;
1691 };
1692
1693 /// Exchanging Add instruction. Exchanges the first operand (destination
1694 /// operand) with the second operand (source operand), then loads the sum
1695 /// of the two values into the destination operand. The destination may be
1696 /// a register or memory, while the source must be a register.
1697 ///
1698 /// Both the dest and source are updated. The caller should then insert a
1699 /// FakeDef to reflect the second udpate.
1700 class InstX8632Xadd : public InstX8632Lockable {
1701 InstX8632Xadd() = delete;
1702 InstX8632Xadd(const InstX8632Xadd &) = delete;
1703 InstX8632Xadd &operator=(const InstX8632Xadd &) = delete;
1704
1705 public:
1706 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source,
1707 bool Locked) {
1708 return new (Func->allocate<InstX8632Xadd>())
1709 InstX8632Xadd(Func, Dest, Source, Locked);
1710 }
1711 void emit(const Cfg *Func) const override;
1712 void emitIAS(const Cfg *Func) const override;
1713 void dump(const Cfg *Func) const override;
1714 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); }
1715
1716 private:
1717 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked);
1718 };
1719
1720 /// Exchange instruction. Exchanges the first operand (destination
1721 /// operand) with the second operand (source operand). At least one of
1722 /// the operands must be a register (and the other can be reg or mem).
1723 /// Both the Dest and Source are updated. If there is a memory operand,
1724 /// then the instruction is automatically "locked" without the need for
1725 /// a lock prefix.
1726 class InstX8632Xchg : public InstX8632 {
1727 InstX8632Xchg() = delete;
1728 InstX8632Xchg(const InstX8632Xchg &) = delete;
1729 InstX8632Xchg &operator=(const InstX8632Xchg &) = delete;
1730
1731 public:
1732 static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) {
1733 return new (Func->allocate<InstX8632Xchg>())
1734 InstX8632Xchg(Func, Dest, Source);
1735 }
1736 void emit(const Cfg *Func) const override;
1737 void emitIAS(const Cfg *Func) const override;
1738 void dump(const Cfg *Func) const override;
1739 static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); }
1740
1741 private:
1742 InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source);
1743 };
1744
1745 /// Declare partial template specializations of emit() methods that
1746 /// already have default implementations. Without this, there is the
1747 /// possibility of ODR violations and link errors.
1748 template <> void InstX8632Addss::emit(const Cfg *Func) const;
1749 template <> void InstX8632Blendvps::emit(const Cfg *Func) const;
1750 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const;
1751 template <> void InstX8632Div::emit(const Cfg *Func) const;
1752 template <> void InstX8632Divss::emit(const Cfg *Func) const;
1753 template <> void InstX8632Idiv::emit(const Cfg *Func) const;
1754 template <> void InstX8632Imul::emit(const Cfg *Func) const;
1755 template <> void InstX8632Lea::emit(const Cfg *Func) const;
1756 template <> void InstX8632Mulss::emit(const Cfg *Func) const;
1757 template <> void InstX8632Padd::emit(const Cfg *Func) const;
1758 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const;
1759 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const;
1760 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const;
1761 template <> void InstX8632Pextr::emit(const Cfg *Func) const;
1762 template <> void InstX8632Pinsr::emit(const Cfg *Func) const;
1763 template <> void InstX8632Pmull::emit(const Cfg *Func) const;
1764 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const;
1765 template <> void InstX8632Psll::emit(const Cfg *Func) const;
1766 template <> void InstX8632Psra::emit(const Cfg *Func) const;
1767 template <> void InstX8632Psrl::emit(const Cfg *Func) const;
1768 template <> void InstX8632Psub::emit(const Cfg *Func) const;
1769 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const;
1770 template <> void InstX8632Subss::emit(const Cfg *Func) const;
1771
1772 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const;
1773 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const;
1774 template <> void InstX8632Div::emitIAS(const Cfg *Func) const;
1775 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const;
1776 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const;
1777 template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const;
1778 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const;
1779 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const;
1780 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const;
1781 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const;
1782 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const;
1783 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const;
1784 template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const;
1785 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const;
1786 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const;
1787 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const;
1788
1789 } // end of namespace Ice
1790
1791 #endif // SUBZERO_SRC_ICEINSTX8632_H 37 #endif // SUBZERO_SRC_ICEINSTX8632_H
OLDNEW
« no previous file with comments | « src/IceAssemblerX86Base.h ('k') | src/IceInstX8632.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698