Index: src/IceInstARM32.h |
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h |
index 2e3f764d2953740ccfbbf3c4aa526af9c4c96e14..11878aea115cd8839f3e5de6d59492c650dc9282 100644 |
--- a/src/IceInstARM32.h |
+++ b/src/IceInstARM32.h |
@@ -245,12 +245,19 @@ class InstARM32 : public InstTarget { |
public: |
enum InstKindARM32 { |
k__Start = Inst::Target, |
+ Adc, |
+ Add, |
+ And, |
+ Ldr, |
Mov, |
Movt, |
Movw, |
Mvn, |
Ret, |
- Ldr |
+ Rsb, |
+ Rsc, |
+ Sbc, |
+ Sub |
}; |
static const char *getWidthString(Type Ty); |
@@ -267,6 +274,7 @@ protected: |
}; |
void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func); |
+void emitBinop(const char *Opcode, const Inst *Inst, const Cfg *Func); |
// TODO(jvoung): add condition codes if instruction can be predicated. |
@@ -397,6 +405,57 @@ private: |
static const char *Opcode; |
}; |
+// Instructions of the form x := y op z. |
+template <InstARM32::InstKindARM32 K> |
+class InstARM32BinopGPR : public InstARM32 { |
+ InstARM32BinopGPR() = delete; |
+ InstARM32BinopGPR(const InstARM32BinopGPR &) = delete; |
+ InstARM32BinopGPR &operator=(const InstARM32BinopGPR &) = delete; |
+ |
+public: |
+ // Create an ordinary binary-op instruction like add, sub, or rsb. |
+ // Dest and Src1 must be registers. |
+ static InstARM32BinopGPR *create(Cfg *Func, Variable *Dest, Variable *Src1, |
+ Operand *Src2) { |
+ return new (Func->allocate<InstARM32BinopGPR>()) |
+ InstARM32BinopGPR(Func, Dest, Src1, Src2); |
+ } |
+ void emit(const Cfg *Func) const override { |
+ if (!ALLOW_DUMP) |
+ return; |
+ emitBinop(Opcode, this, Func); |
+ } |
+ void emitIAS(const Cfg *Func) const override { |
+ (void)Func; |
+ llvm::report_fatal_error("Not yet implemented"); |
+ } |
+ void dump(const Cfg *Func) const override { |
+ if (!ALLOW_DUMP) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ dumpDest(Func); |
+ Str << " = " << Opcode << "." << getDest()->getType() << " "; |
+ dumpSources(Func); |
+ } |
+ static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
+ |
+private: |
+ InstARM32BinopGPR(Cfg *Func, Variable *Dest, Variable *Src1, Operand *Src2) |
+ : InstARM32(Func, K, 2, Dest) { |
+ addSource(Src1); |
+ addSource(Src2); |
+ } |
+ ~InstARM32BinopGPR() override {} |
+ static const char *Opcode; |
+}; |
+ |
+typedef InstARM32BinopGPR<InstARM32::Adc> InstARM32Adc; |
+typedef InstARM32BinopGPR<InstARM32::Add> InstARM32Add; |
+typedef InstARM32BinopGPR<InstARM32::And> InstARM32And; |
+typedef InstARM32BinopGPR<InstARM32::Rsb> InstARM32Rsb; |
+typedef InstARM32BinopGPR<InstARM32::Rsc> InstARM32Rsc; |
+typedef InstARM32BinopGPR<InstARM32::Sbc> InstARM32Sbc; |
+typedef InstARM32BinopGPR<InstARM32::Sub> InstARM32Sub; |
// Move instruction (variable <- flex). This is more of a pseudo-inst. |
// If var is a register, then we use "mov". If var is stack, then we use |
// "str" to store to the stack. |