| Index: src/IceInstARM32.h
|
| diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
|
| index d254180d8e3c9d28d47b4ec8837db7ee90d4967f..66d571236b9d0c64208b20cdb23f8b9d2ef3ca3c 100644
|
| --- a/src/IceInstARM32.h
|
| +++ b/src/IceInstARM32.h
|
| @@ -320,12 +320,24 @@ public:
|
| Tst,
|
| Udiv,
|
| Umull,
|
| - Uxt
|
| + Uxt,
|
| + Vadd,
|
| + Vdiv,
|
| + Vldr,
|
| + Vmov,
|
| + Vmul,
|
| + Vsqrt,
|
| + Vsub
|
| };
|
|
|
| static const char *getWidthString(Type Ty);
|
| + static const char *getVecWidthString(Type Ty);
|
| static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
|
|
|
| + /// Shared emit routines for common forms of instructions.
|
| + static void emitThreeAddrFP(const char *Opcode, const InstARM32 *Inst,
|
| + const Cfg *Func);
|
| +
|
| void dump(const Cfg *Func) const override;
|
|
|
| protected:
|
| @@ -357,6 +369,8 @@ public:
|
| /// Shared emit routines for common forms of instructions.
|
| static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
|
| const Cfg *Func, bool NeedsWidthSuffix);
|
| + static void emitUnaryopFP(const char *Opcode, const InstARM32Pred *Inst,
|
| + const Cfg *Func);
|
| static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
|
| const Cfg *Func);
|
| static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
|
| @@ -420,6 +434,50 @@ private:
|
| static const char *Opcode;
|
| };
|
|
|
| +/// Instructions of the form x := op(y), for vector/FP.
|
| +template <InstARM32::InstKindARM32 K>
|
| +class InstARM32UnaryopFP : public InstARM32Pred {
|
| + InstARM32UnaryopFP() = delete;
|
| + InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
|
| + InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
|
| +
|
| +public:
|
| + static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
|
| + CondARM32::Cond Predicate) {
|
| + return new (Func->allocate<InstARM32UnaryopFP>())
|
| + InstARM32UnaryopFP(Func, Dest, Src, Predicate);
|
| + }
|
| + void emit(const Cfg *Func) const override {
|
| + if (!BuildDefs::dump())
|
| + return;
|
| + emitUnaryopFP(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 (!BuildDefs::dump())
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + dumpDest(Func);
|
| + Str << " = ";
|
| + dumpOpcodePred(Str, Opcode, getDest()->getType());
|
| + Str << " ";
|
| + dumpSources(Func);
|
| + }
|
| + static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
|
| +
|
| +private:
|
| + InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
|
| + CondARM32::Cond Predicate)
|
| + : InstARM32Pred(Func, K, 1, Dest, Predicate) {
|
| + addSource(Src);
|
| + }
|
| +
|
| + static const char *Opcode;
|
| +};
|
| +
|
| /// Instructions of the form x := x op y.
|
| template <InstARM32::InstKindARM32 K>
|
| class InstARM32TwoAddrGPR : public InstARM32Pred {
|
| @@ -559,7 +617,56 @@ private:
|
| bool SetFlags;
|
| };
|
|
|
| -// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
|
| +/// Instructions of the form x := y op z, for vector/FP. We leave these as
|
| +/// unconditional: "ARM deprecates the conditional execution of any instruction
|
| +/// encoding provided by the Advanced SIMD Extension that is not also provided
|
| +/// by the Floating-point (VFP) extension". They do not set flags.
|
| +template <InstARM32::InstKindARM32 K>
|
| +class InstARM32ThreeAddrFP : public InstARM32 {
|
| + InstARM32ThreeAddrFP() = delete;
|
| + InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
|
| + InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
|
| +
|
| +public:
|
| + /// Create a vector/FP binary-op instruction like vadd, and vsub.
|
| + /// Everything must be a register.
|
| + static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
|
| + Variable *Src1) {
|
| + return new (Func->allocate<InstARM32ThreeAddrFP>())
|
| + InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
|
| + }
|
| + void emit(const Cfg *Func) const override {
|
| + if (!BuildDefs::dump())
|
| + return;
|
| + emitThreeAddrFP(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 (!BuildDefs::dump())
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + dumpDest(Func);
|
| + Str << " = ";
|
| + Str << Opcode << "." << getDest()->getType() << " ";
|
| + dumpSources(Func);
|
| + }
|
| + static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
|
| +
|
| +private:
|
| + InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0,
|
| + Variable *Src1)
|
| + : InstARM32(Func, K, 2, Dest) {
|
| + addSource(Src0);
|
| + addSource(Src1);
|
| + }
|
| +
|
| + static const char *Opcode;
|
| +};
|
| +
|
| +/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
|
| template <InstARM32::InstKindARM32 K>
|
| class InstARM32FourAddrGPR : public InstARM32Pred {
|
| InstARM32FourAddrGPR() = delete;
|
| @@ -608,7 +715,7 @@ private:
|
| static const char *Opcode;
|
| };
|
|
|
| -// Instructions of the form x cmpop y (setting flags).
|
| +/// Instructions of the form x cmpop y (setting flags).
|
| template <InstARM32::InstKindARM32 K>
|
| class InstARM32CmpLike : public InstARM32Pred {
|
| InstARM32CmpLike() = delete;
|
| @@ -666,10 +773,19 @@ typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc;
|
| typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv;
|
| typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub;
|
| typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv;
|
| +typedef InstARM32ThreeAddrFP<InstARM32::Vadd> InstARM32Vadd;
|
| +typedef InstARM32ThreeAddrFP<InstARM32::Vdiv> InstARM32Vdiv;
|
| +typedef InstARM32ThreeAddrFP<InstARM32::Vmul> InstARM32Vmul;
|
| +typedef InstARM32ThreeAddrFP<InstARM32::Vsub> InstARM32Vsub;
|
| +typedef InstARM32Movlike<InstARM32::Ldr> InstARM32Ldr;
|
| /// 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.
|
| typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov;
|
| +/// Represents various vector mov instruction forms (simple single source,
|
| +/// single dest forms only, not the 2 GPR <-> 1 D reg forms, etc.).
|
| +typedef InstARM32Movlike<InstARM32::Vmov> InstARM32Vmov;
|
| +typedef InstARM32Movlike<InstARM32::Vldr> InstARM32Vldr;
|
| /// MovT leaves the bottom bits alone so dest is also a source.
|
| /// This helps indicate that a previous MovW setting dest is not dead code.
|
| typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt;
|
| @@ -683,6 +799,7 @@ typedef InstARM32UnaryopGPR<InstARM32::Rev, false> InstARM32Rev;
|
| // but we aren't using that for now, so just model as a Unaryop.
|
| typedef InstARM32UnaryopGPR<InstARM32::Sxt, true> InstARM32Sxt;
|
| typedef InstARM32UnaryopGPR<InstARM32::Uxt, true> InstARM32Uxt;
|
| +typedef InstARM32UnaryopFP<InstARM32::Vsqrt> InstARM32Vsqrt;
|
| typedef InstARM32FourAddrGPR<InstARM32::Mla> InstARM32Mla;
|
| typedef InstARM32FourAddrGPR<InstARM32::Mls> InstARM32Mls;
|
| typedef InstARM32CmpLike<InstARM32::Cmp> InstARM32Cmp;
|
| @@ -838,29 +955,6 @@ private:
|
| InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
|
| };
|
|
|
| -/// Load instruction.
|
| -class InstARM32Ldr : public InstARM32Pred {
|
| - InstARM32Ldr() = delete;
|
| - InstARM32Ldr(const InstARM32Ldr &) = delete;
|
| - InstARM32Ldr &operator=(const InstARM32Ldr &) = delete;
|
| -
|
| -public:
|
| - /// Dest must be a register.
|
| - static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
|
| - CondARM32::Cond Predicate) {
|
| - return new (Func->allocate<InstARM32Ldr>())
|
| - InstARM32Ldr(Func, Dest, Mem, Predicate);
|
| - }
|
| - void emit(const Cfg *Func) const override;
|
| - void emitIAS(const Cfg *Func) const override;
|
| - void dump(const Cfg *Func) const override;
|
| - static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); }
|
| -
|
| -private:
|
| - InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
|
| - CondARM32::Cond Predicate);
|
| -};
|
| -
|
| /// Pop into a list of GPRs. Technically this can be predicated, but we don't
|
| /// need that functionality.
|
| class InstARM32Pop : public InstARM32 {
|
| @@ -1003,8 +1097,12 @@ private:
|
| // already have default implementations. Without this, there is the
|
| // possibility of ODR violations and link errors.
|
|
|
| +template <> void InstARM32Ldr::emit(const Cfg *Func) const;
|
| +template <> void InstARM32Mov::emit(const Cfg *Func) const;
|
| template <> void InstARM32Movw::emit(const Cfg *Func) const;
|
| template <> void InstARM32Movt::emit(const Cfg *Func) const;
|
| +template <> void InstARM32Vldr::emit(const Cfg *Func) const;
|
| +template <> void InstARM32Vmov::emit(const Cfg *Func) const;
|
|
|
| } // end of namespace Ice
|
|
|
|
|