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