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

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

Powered by Google App Engine
This is Rietveld 408576698