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