| 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.
|
|
|