OLD | NEW |
---|---|
1 //===- subzero/src/IceInstX8632.h - Low-level x86 instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstX8632.h - Low-level x86 instructions --*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file declares the InstX8632 and OperandX8632 classes and | 10 // This file declares the InstX8632 and OperandX8632 classes and |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 OperandX8632 &operator=(const OperandX8632 &) LLVM_DELETED_FUNCTION; | 47 OperandX8632 &operator=(const OperandX8632 &) LLVM_DELETED_FUNCTION; |
48 }; | 48 }; |
49 | 49 |
50 // OperandX8632Mem represents the m32 addressing mode, with optional | 50 // OperandX8632Mem represents the m32 addressing mode, with optional |
51 // base and index registers, a constant offset, and a fixed shift | 51 // base and index registers, a constant offset, and a fixed shift |
52 // value for the index register. | 52 // value for the index register. |
53 class OperandX8632Mem : public OperandX8632 { | 53 class OperandX8632Mem : public OperandX8632 { |
54 public: | 54 public: |
55 enum SegmentRegisters { | 55 enum SegmentRegisters { |
56 DefaultSegment = -1, | 56 DefaultSegment = -1, |
57 #define X(val, name) \ | 57 #define X(val, name) val, |
58 val, | 58 SEG_REGX8632_TABLE |
59 SEG_REGX8632_TABLE | |
60 #undef X | 59 #undef X |
61 SegReg_NUM | 60 SegReg_NUM |
62 }; | 61 }; |
63 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base, | 62 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base, |
64 Constant *Offset, Variable *Index = NULL, | 63 Constant *Offset, Variable *Index = NULL, |
65 uint16_t Shift = 0, | 64 uint16_t Shift = 0, |
66 SegmentRegisters SegmentReg = DefaultSegment) { | 65 SegmentRegisters SegmentReg = DefaultSegment) { |
67 return new (Func->allocate<OperandX8632Mem>()) | 66 return new (Func->allocate<OperandX8632Mem>()) |
68 OperandX8632Mem(Func, Ty, Base, Offset, Index, Shift, SegmentReg); | 67 OperandX8632Mem(Func, Ty, Base, Offset, Index, Shift, SegmentReg); |
69 } | 68 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 public: | 133 public: |
135 enum InstKindX8632 { | 134 enum InstKindX8632 { |
136 k__Start = Inst::Target, | 135 k__Start = Inst::Target, |
137 Adc, | 136 Adc, |
138 Add, | 137 Add, |
139 Addss, | 138 Addss, |
140 And, | 139 And, |
141 Br, | 140 Br, |
142 Call, | 141 Call, |
143 Cdq, | 142 Cdq, |
143 Cmpxchg, | |
144 Cmpxchg8b, | |
144 Cvt, | 145 Cvt, |
145 Div, | 146 Div, |
146 Divss, | 147 Divss, |
147 Fld, | 148 Fld, |
148 Fstp, | 149 Fstp, |
149 Icmp, | 150 Icmp, |
150 Idiv, | 151 Idiv, |
151 Imul, | 152 Imul, |
152 Label, | 153 Label, |
153 Load, | 154 Load, |
154 Mfence, | 155 Mfence, |
155 Mov, | 156 Mov, |
156 Movq, | 157 Movq, |
157 Movsx, | 158 Movsx, |
158 Movzx, | 159 Movzx, |
159 Mul, | 160 Mul, |
160 Mulss, | 161 Mulss, |
162 Neg, | |
161 Or, | 163 Or, |
162 Pop, | 164 Pop, |
163 Push, | 165 Push, |
164 Ret, | 166 Ret, |
165 Sar, | 167 Sar, |
166 Sbb, | 168 Sbb, |
167 Shl, | 169 Shl, |
168 Shld, | 170 Shld, |
169 Shr, | 171 Shr, |
170 Shrd, | 172 Shrd, |
171 Store, | 173 Store, |
172 StoreQ, | 174 StoreQ, |
173 Sub, | 175 Sub, |
174 Subss, | 176 Subss, |
175 Test, | 177 Test, |
176 Ucomiss, | 178 Ucomiss, |
177 UD2, | 179 UD2, |
178 Xadd, | 180 Xadd, |
181 Xchg, | |
179 Xor | 182 Xor |
180 }; | 183 }; |
181 static const char *getWidthString(Type Ty); | 184 static const char *getWidthString(Type Ty); |
182 virtual void emit(const Cfg *Func) const = 0; | 185 virtual void emit(const Cfg *Func) const = 0; |
183 virtual void dump(const Cfg *Func) const; | 186 virtual void dump(const Cfg *Func) const; |
184 | 187 |
185 protected: | 188 protected: |
186 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest) | 189 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest) |
187 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 190 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
188 virtual ~InstX8632() {} | 191 virtual ~InstX8632() {} |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 virtual void dump(const Cfg *Func) const; | 317 virtual void dump(const Cfg *Func) const; |
315 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } | 318 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
316 | 319 |
317 private: | 320 private: |
318 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 321 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
319 InstX8632Call(const InstX8632Call &) LLVM_DELETED_FUNCTION; | 322 InstX8632Call(const InstX8632Call &) LLVM_DELETED_FUNCTION; |
320 InstX8632Call &operator=(const InstX8632Call &) LLVM_DELETED_FUNCTION; | 323 InstX8632Call &operator=(const InstX8632Call &) LLVM_DELETED_FUNCTION; |
321 virtual ~InstX8632Call() {} | 324 virtual ~InstX8632Call() {} |
322 }; | 325 }; |
323 | 326 |
327 template <InstX8632::InstKindX8632 K> | |
328 class InstX8632Unaryop : public InstX8632 { | |
329 public: | |
330 // Create an unary-op instruction like neg. | |
331 // The source and dest are the same variable. | |
332 static InstX8632Unaryop *create(Cfg *Func, Variable *SrcDest) { | |
Jim Stichnoth
2014/07/08 04:50:19
An instruction like this is valid x86:
neg [eax+
jvoung (off chromium)
2014/07/08 18:14:07
Okay, I think I will try making it a more generic
jvoung (off chromium)
2014/07/09 17:07:55
Done.
Not sure about liveness either, but Dest wo
Jim Stichnoth
2014/07/09 18:14:28
Yes, that's also what I'd expect.
| |
333 return new (Func->allocate<InstX8632Unaryop>()) | |
334 InstX8632Unaryop(Func, SrcDest); | |
335 } | |
336 virtual void emit(const Cfg *Func) const { | |
337 Ostream &Str = Func->getContext()->getStrEmit(); | |
338 assert(getSrcSize() == 1); | |
339 Str << "\t" << Opcode << "\t"; | |
340 getSrc(0)->emit(Func); | |
341 Str << "\n"; | |
342 } | |
343 virtual void dump(const Cfg *Func) const { | |
344 Ostream &Str = Func->getContext()->getStrDump(); | |
345 dumpDest(Func); | |
346 Str << " = " << Opcode << "." << getDest()->getType() << " "; | |
347 dumpSources(Func); | |
348 } | |
349 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | |
350 | |
351 private: | |
352 InstX8632Unaryop(Cfg *Func, Variable *SrcDest) | |
353 : InstX8632(Func, K, 1, SrcDest) { | |
354 addSource(SrcDest); | |
355 } | |
356 InstX8632Unaryop(const InstX8632Unaryop &) LLVM_DELETED_FUNCTION; | |
357 InstX8632Unaryop &operator=(const InstX8632Unaryop &) LLVM_DELETED_FUNCTION; | |
358 virtual ~InstX8632Unaryop() {} | |
359 static const char *Opcode; | |
360 }; | |
361 | |
324 // See the definition of emitTwoAddress() for a description of | 362 // See the definition of emitTwoAddress() for a description of |
325 // ShiftHack. | 363 // ShiftHack. |
326 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | 364 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
327 bool ShiftHack = false); | 365 bool ShiftHack = false); |
328 | 366 |
329 template <InstX8632::InstKindX8632 K, bool ShiftHack = false> | 367 template <InstX8632::InstKindX8632 K, bool ShiftHack = false> |
330 class InstX8632Binop : public InstX8632 { | 368 class InstX8632Binop : public InstX8632 { |
331 public: | 369 public: |
332 // Create an ordinary binary-op instruction like add or sub. | 370 // Create an ordinary binary-op instruction like add or sub. |
333 static InstX8632Binop *create(Cfg *Func, Variable *Dest, Operand *Source) { | 371 static InstX8632Binop *create(Cfg *Func, Variable *Dest, Operand *Source) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 addSource(Dest); | 424 addSource(Dest); |
387 addSource(Source1); | 425 addSource(Source1); |
388 addSource(Source2); | 426 addSource(Source2); |
389 } | 427 } |
390 InstX8632Ternop(const InstX8632Ternop &) LLVM_DELETED_FUNCTION; | 428 InstX8632Ternop(const InstX8632Ternop &) LLVM_DELETED_FUNCTION; |
391 InstX8632Ternop &operator=(const InstX8632Ternop &) LLVM_DELETED_FUNCTION; | 429 InstX8632Ternop &operator=(const InstX8632Ternop &) LLVM_DELETED_FUNCTION; |
392 virtual ~InstX8632Ternop() {} | 430 virtual ~InstX8632Ternop() {} |
393 static const char *Opcode; | 431 static const char *Opcode; |
394 }; | 432 }; |
395 | 433 |
434 typedef InstX8632Unaryop<InstX8632::Neg> InstX8632Neg; | |
396 typedef InstX8632Binop<InstX8632::Add> InstX8632Add; | 435 typedef InstX8632Binop<InstX8632::Add> InstX8632Add; |
397 typedef InstX8632Binop<InstX8632::Adc> InstX8632Adc; | 436 typedef InstX8632Binop<InstX8632::Adc> InstX8632Adc; |
398 typedef InstX8632Binop<InstX8632::Addss> InstX8632Addss; | 437 typedef InstX8632Binop<InstX8632::Addss> InstX8632Addss; |
399 typedef InstX8632Binop<InstX8632::Sub> InstX8632Sub; | 438 typedef InstX8632Binop<InstX8632::Sub> InstX8632Sub; |
400 typedef InstX8632Binop<InstX8632::Subss> InstX8632Subss; | 439 typedef InstX8632Binop<InstX8632::Subss> InstX8632Subss; |
401 typedef InstX8632Binop<InstX8632::Sbb> InstX8632Sbb; | 440 typedef InstX8632Binop<InstX8632::Sbb> InstX8632Sbb; |
402 typedef InstX8632Binop<InstX8632::And> InstX8632And; | 441 typedef InstX8632Binop<InstX8632::And> InstX8632And; |
403 typedef InstX8632Binop<InstX8632::Or> InstX8632Or; | 442 typedef InstX8632Binop<InstX8632::Or> InstX8632Or; |
404 typedef InstX8632Binop<InstX8632::Xor> InstX8632Xor; | 443 typedef InstX8632Binop<InstX8632::Xor> InstX8632Xor; |
405 typedef InstX8632Binop<InstX8632::Imul> InstX8632Imul; | 444 typedef InstX8632Binop<InstX8632::Imul> InstX8632Imul; |
406 typedef InstX8632Binop<InstX8632::Mulss> InstX8632Mulss; | 445 typedef InstX8632Binop<InstX8632::Mulss> InstX8632Mulss; |
407 typedef InstX8632Binop<InstX8632::Divss> InstX8632Divss; | 446 typedef InstX8632Binop<InstX8632::Divss> InstX8632Divss; |
408 typedef InstX8632Binop<InstX8632::Shl, true> InstX8632Shl; | 447 typedef InstX8632Binop<InstX8632::Shl, true> InstX8632Shl; |
409 typedef InstX8632Binop<InstX8632::Shr, true> InstX8632Shr; | 448 typedef InstX8632Binop<InstX8632::Shr, true> InstX8632Shr; |
410 typedef InstX8632Binop<InstX8632::Sar, true> InstX8632Sar; | 449 typedef InstX8632Binop<InstX8632::Sar, true> InstX8632Sar; |
411 typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv; | 450 typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv; |
412 typedef InstX8632Ternop<InstX8632::Div> InstX8632Div; | 451 typedef InstX8632Ternop<InstX8632::Div> InstX8632Div; |
413 | 452 |
453 // Base class for a lockable x86-32 instruction (emits a locked prefix). | |
454 class InstX8632Lockable : public InstX8632 { | |
455 public: | |
456 virtual void emit(const Cfg *Func) const = 0; | |
457 virtual void dump(const Cfg *Func) const; | |
458 | |
459 protected: | |
460 InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, | |
461 Variable *Dest, bool Locked) | |
462 : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | |
463 // Assume that such instructions are used for Atomics and be careful | |
464 // with optimizations. | |
465 HasSideEffects = Locked; | |
466 } | |
467 bool Locked; | |
468 | |
469 private: | |
470 InstX8632Lockable(const InstX8632Lockable &) LLVM_DELETED_FUNCTION; | |
471 InstX8632Lockable &operator=(const InstX8632Lockable &) LLVM_DELETED_FUNCTION; | |
472 }; | |
473 | |
414 // Mul instruction - unsigned multiply. | 474 // Mul instruction - unsigned multiply. |
415 class InstX8632Mul : public InstX8632 { | 475 class InstX8632Mul : public InstX8632 { |
416 public: | 476 public: |
417 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 477 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, |
418 Operand *Source2) { | 478 Operand *Source2) { |
419 return new (Func->allocate<InstX8632Mul>()) | 479 return new (Func->allocate<InstX8632Mul>()) |
420 InstX8632Mul(Func, Dest, Source1, Source2); | 480 InstX8632Mul(Func, Dest, Source1, Source2); |
421 } | 481 } |
422 virtual void emit(const Cfg *Func) const; | 482 virtual void emit(const Cfg *Func) const; |
423 virtual void dump(const Cfg *Func) const; | 483 virtual void dump(const Cfg *Func) const; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 virtual void dump(const Cfg *Func) const; | 543 virtual void dump(const Cfg *Func) const; |
484 static bool classof(const Inst *Inst) { return isClassof(Inst, Cdq); } | 544 static bool classof(const Inst *Inst) { return isClassof(Inst, Cdq); } |
485 | 545 |
486 private: | 546 private: |
487 InstX8632Cdq(Cfg *Func, Variable *Dest, Operand *Source); | 547 InstX8632Cdq(Cfg *Func, Variable *Dest, Operand *Source); |
488 InstX8632Cdq(const InstX8632Cdq &) LLVM_DELETED_FUNCTION; | 548 InstX8632Cdq(const InstX8632Cdq &) LLVM_DELETED_FUNCTION; |
489 InstX8632Cdq &operator=(const InstX8632Cdq &) LLVM_DELETED_FUNCTION; | 549 InstX8632Cdq &operator=(const InstX8632Cdq &) LLVM_DELETED_FUNCTION; |
490 virtual ~InstX8632Cdq() {} | 550 virtual ~InstX8632Cdq() {} |
491 }; | 551 }; |
492 | 552 |
553 // Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | |
554 // equals eax. If so, the ZF is set and <desired> is stored in <dest>. | |
555 // If not, ZF is cleared and <dest> is copied to eax (or subregister). | |
556 // The user is responsible for making a FakeDef to mark eax as | |
557 // possibly changed. | |
Jim Stichnoth
2014/07/08 04:50:19
Would it be simpler to swap the roles of Eax and D
jvoung (off chromium)
2014/07/08 18:14:07
I think this is similar to Xchg. See below?
jvoung (off chromium)
2014/07/09 17:07:55
Okay, this is slightly different from Xchg, in tha
Jim Stichnoth
2014/07/09 18:14:27
After more thought, I would go simple and just dis
| |
558 // <dest> can be a register or memory, while <desired> must be a register. | |
559 class InstX8632Cmpxchg : public InstX8632Lockable { | |
560 public: | |
561 static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | |
562 Variable *Desired, bool Locked) { | |
563 return new (Func->allocate<InstX8632Cmpxchg>()) | |
564 InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | |
565 } | |
566 virtual void emit(const Cfg *Func) const; | |
567 virtual void dump(const Cfg *Func) const; | |
568 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); } | |
569 | |
570 private: | |
571 InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | |
572 Variable *Desired, bool Locked); | |
573 InstX8632Cmpxchg(const InstX8632Cmpxchg &) LLVM_DELETED_FUNCTION; | |
574 InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) LLVM_DELETED_FUNCTION; | |
575 virtual ~InstX8632Cmpxchg() {} | |
576 }; | |
577 | |
578 // Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> | |
579 // equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. | |
580 // If not, ZF is cleared and <m64> is copied to edx:eax. | |
581 // <m64> must be a memory operand. | |
Jim Stichnoth
2014/07/08 04:50:19
Document the user's responsibility to add appropri
jvoung (off chromium)
2014/07/09 17:07:55
Documented.
The other 64-bit integer instruction
Jim Stichnoth
2014/07/09 18:14:28
I was thinking of the 64-bit ret, but there may be
| |
582 class InstX8632Cmpxchg8b : public InstX8632Lockable { | |
583 public: | |
584 static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632 *Dest, | |
585 Variable *Edx, Variable *Eax, Variable *Ecx, | |
586 Variable *Ebx, bool Locked) { | |
587 return new (Func->allocate<InstX8632Cmpxchg8b>()) | |
588 InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | |
589 } | |
590 virtual void emit(const Cfg *Func) const; | |
591 virtual void dump(const Cfg *Func) const; | |
592 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); } | |
593 | |
594 private: | |
595 InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Dest, Variable *Edx, | |
596 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); | |
597 InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) LLVM_DELETED_FUNCTION; | |
598 InstX8632Cmpxchg8b & | |
599 operator=(const InstX8632Cmpxchg8b &) LLVM_DELETED_FUNCTION; | |
600 virtual ~InstX8632Cmpxchg8b() {} | |
601 }; | |
602 | |
493 // Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} | 603 // Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} |
494 // as appropriate. s=float, d=double, i=int. X and Y are determined | 604 // as appropriate. s=float, d=double, i=int. X and Y are determined |
495 // from dest/src types. Sign and zero extension on the integer | 605 // from dest/src types. Sign and zero extension on the integer |
496 // operand needs to be done separately. | 606 // operand needs to be done separately. |
497 class InstX8632Cvt : public InstX8632 { | 607 class InstX8632Cvt : public InstX8632 { |
498 public: | 608 public: |
499 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source) { | 609 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source) { |
500 return new (Func->allocate<InstX8632Cvt>()) | 610 return new (Func->allocate<InstX8632Cvt>()) |
501 InstX8632Cvt(Func, Dest, Source); | 611 InstX8632Cvt(Func, Dest, Source); |
502 } | 612 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
804 virtual ~InstX8632Ret() {} | 914 virtual ~InstX8632Ret() {} |
805 }; | 915 }; |
806 | 916 |
807 // Exchanging Add instruction. Exchanges the first operand (destination | 917 // Exchanging Add instruction. Exchanges the first operand (destination |
808 // operand) with the second operand (source operand), then loads the sum | 918 // operand) with the second operand (source operand), then loads the sum |
809 // of the two values into the destination operand. The destination may be | 919 // of the two values into the destination operand. The destination may be |
810 // a register or memory, while the source must be a register. | 920 // a register or memory, while the source must be a register. |
811 // | 921 // |
812 // Both the dest and source are updated. The caller should then insert a | 922 // Both the dest and source are updated. The caller should then insert a |
813 // FakeDef to reflect the second udpate. | 923 // FakeDef to reflect the second udpate. |
814 class InstX8632Xadd : public InstX8632 { | 924 class InstX8632Xadd : public InstX8632Lockable { |
815 public: | 925 public: |
816 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | 926 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
817 bool Locked) { | 927 bool Locked) { |
818 return new (Func->allocate<InstX8632Xadd>()) | 928 return new (Func->allocate<InstX8632Xadd>()) |
819 InstX8632Xadd(Func, Dest, Source, Locked); | 929 InstX8632Xadd(Func, Dest, Source, Locked); |
820 } | 930 } |
821 virtual void emit(const Cfg *Func) const; | 931 virtual void emit(const Cfg *Func) const; |
822 virtual void dump(const Cfg *Func) const; | 932 virtual void dump(const Cfg *Func) const; |
823 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } | 933 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } |
824 | 934 |
825 private: | 935 private: |
826 bool Locked; | |
827 | |
828 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | 936 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
829 InstX8632Xadd(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; | 937 InstX8632Xadd(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; |
830 InstX8632Xadd &operator=(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; | 938 InstX8632Xadd &operator=(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; |
831 virtual ~InstX8632Xadd() {} | 939 virtual ~InstX8632Xadd() {} |
832 }; | 940 }; |
833 | 941 |
942 // Exchange instruction. Exchanges the first operand (destination | |
943 // operand) with the second operand (source operand). At least one of | |
944 // the operands must be a register (and the other can be reg or mem). | |
945 // Both the Dest and Source are updated. If there is a memory operand, | |
946 // then the instruction is automatically "locked" without the need for | |
947 // a lock prefix. | |
948 class InstX8632Xchg : public InstX8632 { | |
949 public: | |
950 static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | |
Jim Stichnoth
2014/07/08 04:50:19
Can we structure this so that Dest is the Variable
jvoung (off chromium)
2014/07/08 18:14:07
I think the motivation for this was to make it lik
Jim Stichnoth
2014/07/09 18:14:27
At least for now, I would just be conservative and
| |
951 return new (Func->allocate<InstX8632Xchg>()) | |
952 InstX8632Xchg(Func, Dest, Source); | |
953 } | |
954 virtual void emit(const Cfg *Func) const; | |
955 virtual void dump(const Cfg *Func) const; | |
956 static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); } | |
957 | |
958 private: | |
959 InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source); | |
960 InstX8632Xchg(const InstX8632Xchg &) LLVM_DELETED_FUNCTION; | |
961 InstX8632Xchg &operator=(const InstX8632Xchg &) LLVM_DELETED_FUNCTION; | |
962 virtual ~InstX8632Xchg() {} | |
963 }; | |
964 | |
834 } // end of namespace Ice | 965 } // end of namespace Ice |
835 | 966 |
836 #endif // SUBZERO_SRC_ICEINSTX8632_H | 967 #endif // SUBZERO_SRC_ICEINSTX8632_H |
OLD | NEW |