| Index: src/IceInstARM32.h
|
| diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
|
| index 1c7d346bc92e8c9608fc511152c360e3071b50f7..e4e6c49ab8be20e2ba81dc0e380eb930df4205cb 100644
|
| --- a/src/IceInstARM32.h
|
| +++ b/src/IceInstARM32.h
|
| @@ -17,11 +17,104 @@
|
| #define SUBZERO_SRC_ICEINSTARM32_H
|
|
|
| #include "IceDefs.h"
|
| +#include "IceInst.h"
|
| +#include "IceInstARM32.def"
|
| +#include "IceOperand.h"
|
|
|
| namespace Ice {
|
|
|
| class TargetARM32;
|
| -// Fill this in.
|
| +
|
| +// OperandARM32 extends the Operand hierarchy.
|
| +// TODO(jvoung): Add the OperandARM32Mem and OperandARM32Flex.
|
| +class OperandARM32 : public Operand {
|
| + OperandARM32() = delete;
|
| + OperandARM32(const OperandARM32 &) = delete;
|
| + OperandARM32 &operator=(const OperandARM32 &) = delete;
|
| +
|
| +public:
|
| + enum OperandKindARM32 { k__Start = Operand::kTarget };
|
| +
|
| + enum ShiftKind {
|
| + kNoShift = -1,
|
| +#define X(enum, emit) enum,
|
| + ICEINSTARM32SHIFT_TABLE
|
| +#undef X
|
| + };
|
| +
|
| + using Operand::dump;
|
| + void dump(const Cfg *, Ostream &Str) const override {
|
| + if (ALLOW_DUMP)
|
| + Str << "<OperandARM32>";
|
| + }
|
| +
|
| +protected:
|
| + OperandARM32(OperandKindARM32 Kind, Type Ty)
|
| + : Operand(static_cast<OperandKind>(Kind), Ty) {}
|
| + ~OperandARM32() override {}
|
| +};
|
| +
|
| +// OperandARM32Mem represents a memory operand in any of the various ARM32
|
| +// addressing modes.
|
| +// TODO(jvoung): Fill out more.
|
| +class OperandARM32Mem : public OperandARM32 {
|
| + OperandARM32Mem() = delete;
|
| + OperandARM32Mem(const OperandARM32Mem &) = delete;
|
| + OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
|
| +
|
| +public:
|
| + // Return true if a load/store instruction for an element of type Ty
|
| + // can encode the Offset directly in the immediate field of the 32-bit
|
| + // ARM instruction. For some types, if the load is Sign extending, then
|
| + // the range is reduced.
|
| + static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
|
| +};
|
| +
|
| +class InstARM32 : public InstTarget {
|
| + InstARM32() = delete;
|
| + InstARM32(const InstARM32 &) = delete;
|
| + InstARM32 &operator=(const InstARM32 &) = delete;
|
| +
|
| +public:
|
| + enum InstKindARM32 { k__Start = Inst::Target, Ret };
|
| +
|
| + static const char *getWidthString(Type Ty);
|
| +
|
| + void dump(const Cfg *Func) const override;
|
| +
|
| +protected:
|
| + InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
|
| + : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
|
| + ~InstARM32() override {}
|
| + static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
|
| + return Inst->getKind() == static_cast<InstKind>(MyKind);
|
| + }
|
| +};
|
| +
|
| +// 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
|
| +// operand (for non-void returning functions) for liveness analysis, though
|
| +// a FakeUse before the ret would do just as well.
|
| +class InstARM32Ret : public InstARM32 {
|
| + InstARM32Ret() = delete;
|
| + InstARM32Ret(const InstARM32Ret &) = delete;
|
| + InstARM32Ret &operator=(const InstARM32Ret &) = delete;
|
| +
|
| +public:
|
| + static InstARM32Ret *create(Cfg *Func, Variable *LR,
|
| + Variable *Source = nullptr) {
|
| + return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
|
| + }
|
| + 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, Ret); }
|
| +
|
| +private:
|
| + InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
|
| + ~InstARM32Ret() override {}
|
| +};
|
|
|
| } // end of namespace Ice
|
|
|
|
|