| Index: src/IceInstARM32.h
|
| diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
|
| index e65ef4aaec4515579d7f3d7094ef529bec943a60..9e0bb650c54bf5900bacfad9f54ce6c2f539112d 100644
|
| --- a/src/IceInstARM32.h
|
| +++ b/src/IceInstARM32.h
|
| @@ -113,7 +113,14 @@ public:
|
| AddrMode getAddrMode() const { return Mode; }
|
|
|
| bool isRegReg() const { return Index != nullptr; }
|
| - bool isNegAddrMode() const { return Mode >= NegOffset; }
|
| + bool isNegAddrMode() const {
|
| + // Positive address modes have the "U" bit set, and negative modes don't.
|
| + static_assert((PreIndex & (4 << 21)) != 0,
|
| + "Positive addr modes should have U bit set.");
|
| + static_assert((NegPreIndex & (4 << 21)) == 0,
|
| + "Negative addr modes should have U bit clear.");
|
| + return (Mode & (4 << 21)) == 0;
|
| + }
|
|
|
| void emit(const Cfg *Func) const override;
|
| using OperandARM32::dump;
|
| @@ -266,6 +273,8 @@ public:
|
| Mul,
|
| Mvn,
|
| Orr,
|
| + Pop,
|
| + Push,
|
| Ret,
|
| Sbc,
|
| Sub,
|
| @@ -682,6 +691,49 @@ private:
|
| ~InstARM32Mla() override {}
|
| };
|
|
|
| +// Pop into a list of GPRs. Technically this can be predicated, but we don't
|
| +// need that functionality.
|
| +class InstARM32Pop : public InstARM32 {
|
| + InstARM32Pop() = delete;
|
| + InstARM32Pop(const InstARM32Pop &) = delete;
|
| + InstARM32Pop &operator=(const InstARM32Pop &) = delete;
|
| +
|
| +public:
|
| + static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
|
| + return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
|
| + }
|
| + 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, Pop); }
|
| +
|
| +private:
|
| + InstARM32Pop(Cfg *Func, const VarList &Dests);
|
| + ~InstARM32Pop() override {}
|
| + VarList Dests;
|
| +};
|
| +
|
| +// Push a list of GPRs. Technically this can be predicated, but we don't
|
| +// need that functionality.
|
| +class InstARM32Push : public InstARM32 {
|
| + InstARM32Push() = delete;
|
| + InstARM32Push(const InstARM32Push &) = delete;
|
| + InstARM32Push &operator=(const InstARM32Push &) = delete;
|
| +
|
| +public:
|
| + static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
|
| + return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
|
| + }
|
| + 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, Push); }
|
| +
|
| +private:
|
| + InstARM32Push(Cfg *Func, const VarList &Srcs);
|
| + ~InstARM32Push() override {}
|
| +};
|
| +
|
| // Ret pseudo-instruction. This is actually a "bx" instruction with
|
| // an "lr" register operand, but epilogue lowering will search for a Ret
|
| // instead of a generic "bx". This instruction also takes a Source
|
|
|