Index: src/IceInstX8632.h |
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h |
index 840b21bf671d5d7006b7f431f37f0a1f6ce35e2e..b6559f4e48b402e7dd774f7b73f2712edda2e71f 100644 |
--- a/src/IceInstX8632.h |
+++ b/src/IceInstX8632.h |
@@ -176,6 +176,7 @@ public: |
k__Start = Inst::Target, |
Adc, |
Add, |
+ AddRMW, |
Addps, |
Addss, |
Adjuststack, |
@@ -195,6 +196,7 @@ public: |
Div, |
Divps, |
Divss, |
+ FakeRMW, |
Fld, |
Fstp, |
Icmp, |
@@ -312,6 +314,39 @@ private: |
} |
}; |
+// InstX8632FakeRMW represents a non-atomic read-modify-write |
jvoung (off chromium)
2015/06/17 16:40:22
In this case the "Fake" seems a bit different from
Jim Stichnoth
2015/06/18 05:15:12
Done.
|
+// operation on a memory location. If A is some memory address, D is |
+// some data value to apply, and OP is an arithmetic operator, the |
+// instruction operates as: |
+// (*A) = (*A) OP D |
+class InstX8632FakeRMW : public InstX8632 { |
+ InstX8632FakeRMW() = delete; |
+ InstX8632FakeRMW(const InstX8632FakeRMW &) = delete; |
+ InstX8632FakeRMW &operator=(const InstX8632FakeRMW &) = delete; |
+ |
+public: |
+ static InstX8632FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, |
+ Variable *Beacon, InstArithmetic::OpKind Op, |
+ uint32_t Align = 1) { |
+ // TODO(stichnot): Stop ignoring alignment specification. |
+ (void)Align; |
+ return new (Func->allocate<InstX8632FakeRMW>()) |
+ InstX8632FakeRMW(Func, Data, Addr, Op, Beacon); |
+ } |
+ Operand *getAddr() const { return getSrc(1); } |
+ Operand *getData() const { return getSrc(0); } |
+ InstArithmetic::OpKind getOp() const { return Op; } |
+ Variable *getBeacon() const { return llvm::cast<Variable>(getSrc(2)); } |
+ void dump(const Cfg *Func) const override; |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, FakeRMW); } |
+ |
+private: |
+ InstArithmetic::OpKind Op; |
+ InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |
+ InstArithmetic::OpKind Op, Variable *Beacon); |
+ ~InstX8632FakeRMW() override {} |
+}; |
+ |
// InstX8632Label represents an intra-block label that is the target |
// of an intra-block branch. The offset between the label and the |
// branch must be fit into one byte (considered "near"). These are |
@@ -515,6 +550,9 @@ private: |
// Emit a one-operand (GPR) instruction. |
void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, |
const X8632::AssemblerX8632::GPREmitterOneOp &Emitter); |
+void emitIASAsAddrOpTyGPR( |
+ const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, |
+ const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter); |
// Instructions of the form x := op(x). |
template <InstX8632::InstKindX8632 K> |
@@ -765,6 +803,50 @@ private: |
static const X8632::AssemblerX8632::GPREmitterRegOp Emitter; |
}; |
+template <InstX8632::InstKindX8632 K> |
+class InstX8632BinopRMW : public InstX8632 { |
+ InstX8632BinopRMW() = delete; |
+ InstX8632BinopRMW(const InstX8632BinopRMW &) = delete; |
+ InstX8632BinopRMW &operator=(const InstX8632BinopRMW &) = delete; |
+ |
+public: |
+ // Create an ordinary binary-op instruction like add or sub. |
+ static InstX8632BinopRMW *create(Cfg *Func, OperandX8632Mem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX8632BinopRMW>()) |
+ InstX8632BinopRMW(Func, DestSrc0, Src1); |
+ } |
+ void emit(const Cfg *Func) const override { |
+ if (!ALLOW_DUMP) |
+ return; |
+ const bool ShiftHack = false; |
+ emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ void emitIAS(const Cfg *Func) const override { |
+ Type Ty = getSrc(0)->getType(); |
+ assert(getSrcSize() == 2); |
+ emitIASAsAddrOpTyGPR(Func, Ty, getSrc(0), getSrc(1), Emitter); |
+ } |
+ void dump(const Cfg *Func) const override { |
+ if (!ALLOW_DUMP) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ Str << Opcode << "." << getSrc(0)->getType() << " "; |
+ dumpSources(Func); |
+ } |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
+ |
+private: |
+ InstX8632BinopRMW(Cfg *Func, Operand *DestSrc0, Operand *Src1) |
jvoung (off chromium)
2015/06/17 16:40:22
OperandX8632Mem *DestSrc0 too?
Jim Stichnoth
2015/06/18 05:15:12
Done.
|
+ : InstX8632(Func, K, 2, nullptr) { |
+ addSource(DestSrc0); |
+ addSource(Src1); |
+ } |
+ ~InstX8632BinopRMW() override {} |
+ static const char *Opcode; |
+ static const X8632::AssemblerX8632::GPREmitterAddrOp Emitter; |
+}; |
+ |
template <InstX8632::InstKindX8632 K, bool NeedsElementType> |
class InstX8632BinopXmm : public InstX8632 { |
InstX8632BinopXmm() = delete; |
@@ -1017,6 +1099,7 @@ typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp; |
// Movq - copy between XMM registers, or mem64 and XMM registers. |
typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq; |
typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add; |
+typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW; |
typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps; |
typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc; |
typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss; |