Index: src/IceInstX8632.h |
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h |
index 54df8695f1ccfd48198e9d45ea961a171de965ea..e5a219ec234f1fdef0c2132d577e8adcdc6f2c1e 100644 |
--- a/src/IceInstX8632.h |
+++ b/src/IceInstX8632.h |
@@ -54,9 +54,8 @@ class OperandX8632Mem : public OperandX8632 { |
public: |
enum SegmentRegisters { |
DefaultSegment = -1, |
-#define X(val, name) \ |
- val, |
- SEG_REGX8632_TABLE |
+#define X(val, name) val, |
+ SEG_REGX8632_TABLE |
#undef X |
SegReg_NUM |
}; |
@@ -141,6 +140,8 @@ public: |
Br, |
Call, |
Cdq, |
+ Cmpxchg, |
+ Cmpxchg8b, |
Cvt, |
Div, |
Divss, |
@@ -158,6 +159,7 @@ public: |
Movzx, |
Mul, |
Mulss, |
+ Neg, |
Or, |
Pop, |
Push, |
@@ -176,6 +178,7 @@ public: |
Ucomiss, |
UD2, |
Xadd, |
+ Xchg, |
Xor |
}; |
static const char *getWidthString(Type Ty); |
@@ -321,6 +324,41 @@ private: |
virtual ~InstX8632Call() {} |
}; |
+template <InstX8632::InstKindX8632 K> |
+class InstX8632Unaryop : public InstX8632 { |
+public: |
+ // Create an unary-op instruction like neg. |
+ // The source and dest are the same variable. |
+ 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.
|
+ return new (Func->allocate<InstX8632Unaryop>()) |
+ InstX8632Unaryop(Func, SrcDest); |
+ } |
+ virtual void emit(const Cfg *Func) const { |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ assert(getSrcSize() == 1); |
+ Str << "\t" << Opcode << "\t"; |
+ getSrc(0)->emit(Func); |
+ Str << "\n"; |
+ } |
+ virtual void dump(const Cfg *Func) const { |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ dumpDest(Func); |
+ Str << " = " << Opcode << "." << getDest()->getType() << " "; |
+ dumpSources(Func); |
+ } |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
+ |
+private: |
+ InstX8632Unaryop(Cfg *Func, Variable *SrcDest) |
+ : InstX8632(Func, K, 1, SrcDest) { |
+ addSource(SrcDest); |
+ } |
+ InstX8632Unaryop(const InstX8632Unaryop &) LLVM_DELETED_FUNCTION; |
+ InstX8632Unaryop &operator=(const InstX8632Unaryop &) LLVM_DELETED_FUNCTION; |
+ virtual ~InstX8632Unaryop() {} |
+ static const char *Opcode; |
+}; |
+ |
// See the definition of emitTwoAddress() for a description of |
// ShiftHack. |
void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
@@ -393,6 +431,7 @@ private: |
static const char *Opcode; |
}; |
+typedef InstX8632Unaryop<InstX8632::Neg> InstX8632Neg; |
typedef InstX8632Binop<InstX8632::Add> InstX8632Add; |
typedef InstX8632Binop<InstX8632::Adc> InstX8632Adc; |
typedef InstX8632Binop<InstX8632::Addss> InstX8632Addss; |
@@ -411,6 +450,27 @@ typedef InstX8632Binop<InstX8632::Sar, true> InstX8632Sar; |
typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv; |
typedef InstX8632Ternop<InstX8632::Div> InstX8632Div; |
+// Base class for a lockable x86-32 instruction (emits a locked prefix). |
+class InstX8632Lockable : public InstX8632 { |
+public: |
+ virtual void emit(const Cfg *Func) const = 0; |
+ virtual void dump(const Cfg *Func) const; |
+ |
+protected: |
+ InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, |
+ Variable *Dest, bool Locked) |
+ : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |
+ // Assume that such instructions are used for Atomics and be careful |
+ // with optimizations. |
+ HasSideEffects = Locked; |
+ } |
+ bool Locked; |
+ |
+private: |
+ InstX8632Lockable(const InstX8632Lockable &) LLVM_DELETED_FUNCTION; |
+ InstX8632Lockable &operator=(const InstX8632Lockable &) LLVM_DELETED_FUNCTION; |
+}; |
+ |
// Mul instruction - unsigned multiply. |
class InstX8632Mul : public InstX8632 { |
public: |
@@ -490,6 +550,56 @@ private: |
virtual ~InstX8632Cdq() {} |
}; |
+// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |
+// equals eax. If so, the ZF is set and <desired> is stored in <dest>. |
+// If not, ZF is cleared and <dest> is copied to eax (or subregister). |
+// The user is responsible for making a FakeDef to mark eax as |
+// 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
|
+// <dest> can be a register or memory, while <desired> must be a register. |
+class InstX8632Cmpxchg : public InstX8632Lockable { |
+public: |
+ static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
+ Variable *Desired, bool Locked) { |
+ return new (Func->allocate<InstX8632Cmpxchg>()) |
+ InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |
+ } |
+ virtual void emit(const Cfg *Func) const; |
+ virtual void dump(const Cfg *Func) const; |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); } |
+ |
+private: |
+ InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
+ Variable *Desired, bool Locked); |
+ InstX8632Cmpxchg(const InstX8632Cmpxchg &) LLVM_DELETED_FUNCTION; |
+ InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) LLVM_DELETED_FUNCTION; |
+ virtual ~InstX8632Cmpxchg() {} |
+}; |
+ |
+// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> |
+// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. |
+// If not, ZF is cleared and <m64> is copied to edx:eax. |
+// <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
|
+class InstX8632Cmpxchg8b : public InstX8632Lockable { |
+public: |
+ static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632 *Dest, |
+ Variable *Edx, Variable *Eax, Variable *Ecx, |
+ Variable *Ebx, bool Locked) { |
+ return new (Func->allocate<InstX8632Cmpxchg8b>()) |
+ InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |
+ } |
+ virtual void emit(const Cfg *Func) const; |
+ virtual void dump(const Cfg *Func) const; |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); } |
+ |
+private: |
+ InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Dest, Variable *Edx, |
+ Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |
+ InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) LLVM_DELETED_FUNCTION; |
+ InstX8632Cmpxchg8b & |
+ operator=(const InstX8632Cmpxchg8b &) LLVM_DELETED_FUNCTION; |
+ virtual ~InstX8632Cmpxchg8b() {} |
+}; |
+ |
// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} |
// as appropriate. s=float, d=double, i=int. X and Y are determined |
// from dest/src types. Sign and zero extension on the integer |
@@ -811,7 +921,7 @@ private: |
// |
// Both the dest and source are updated. The caller should then insert a |
// FakeDef to reflect the second udpate. |
-class InstX8632Xadd : public InstX8632 { |
+class InstX8632Xadd : public InstX8632Lockable { |
public: |
static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
bool Locked) { |
@@ -823,14 +933,35 @@ public: |
static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } |
private: |
- bool Locked; |
- |
InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
InstX8632Xadd(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; |
InstX8632Xadd &operator=(const InstX8632Xadd &) LLVM_DELETED_FUNCTION; |
virtual ~InstX8632Xadd() {} |
}; |
+// Exchange instruction. Exchanges the first operand (destination |
+// operand) with the second operand (source operand). At least one of |
+// the operands must be a register (and the other can be reg or mem). |
+// Both the Dest and Source are updated. If there is a memory operand, |
+// then the instruction is automatically "locked" without the need for |
+// a lock prefix. |
+class InstX8632Xchg : public InstX8632 { |
+public: |
+ 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
|
+ return new (Func->allocate<InstX8632Xchg>()) |
+ InstX8632Xchg(Func, Dest, Source); |
+ } |
+ virtual void emit(const Cfg *Func) const; |
+ virtual void dump(const Cfg *Func) const; |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); } |
+ |
+private: |
+ InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source); |
+ InstX8632Xchg(const InstX8632Xchg &) LLVM_DELETED_FUNCTION; |
+ InstX8632Xchg &operator=(const InstX8632Xchg &) LLVM_DELETED_FUNCTION; |
+ virtual ~InstX8632Xchg() {} |
+}; |
+ |
} // end of namespace Ice |
#endif // SUBZERO_SRC_ICEINSTX8632_H |