Chromium Code Reviews| Index: src/IceInstMIPS32.h |
| diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h |
| index 1c4863f5cf853f74191fb4f5993faae158b7f555..5cbb36149dc60c6bbf25d00383b34d92519cd2d7 100644 |
| --- a/src/IceInstMIPS32.h |
| +++ b/src/IceInstMIPS32.h |
| @@ -26,6 +26,94 @@ namespace Ice { |
| class TargetMIPS32; |
| +/// OperandMips32 extends the Operand hierarchy. |
| +// |
| +class OperandMIPS32 : public Operand { |
| + OperandMIPS32() = delete; |
| + OperandMIPS32(const OperandMIPS32 &) = delete; |
| + OperandMIPS32 &operator=(const OperandMIPS32 &) = delete; |
| + |
| +public: |
| + enum OperandKindMIPS32 { |
| + k__Start = Operand::kTarget, |
| + kMem, |
| + }; |
| + |
| + using Operand::dump; |
| + void dump(const Cfg *, Ostream &Str) const override { |
| + if (BuildDefs::dump()) |
| + Str << "<OperandMIPS32>"; |
| + } |
| + void emit(const Cfg *Func) const override { |
|
Jim Stichnoth
2015/10/18 11:48:39
Remove this emit() method?
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + if (!BuildDefs::dump()) |
| + return; |
| + Ostream &Str = Func->getContext()->getStrEmit(); |
| + // if (isRegReg()) { |
| + Str << "reed\t"; |
| + } |
| + |
| +protected: |
| + OperandMIPS32(OperandKindMIPS32 Kind, Type Ty) |
| + : Operand(static_cast<OperandKind>(Kind), Ty) {} |
| +}; |
| + |
| +class OperandMIPS32Mem : public OperandMIPS32 { |
| + OperandMIPS32Mem() = delete; |
| + OperandMIPS32Mem(const OperandMIPS32Mem &) = delete; |
| + OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete; |
| + |
| +public: |
| + /// Memory operand addressing mode. |
| + /// The enum value also carries the encoding. |
| + // TODO(jvoung): unify with the assembler. |
| + enum AddrMode { Offset }; |
| + |
| + /// NOTE: The Variable-typed operands have to be registers. |
| + /// |
| + /// Reg + Imm. The Immediate actually has a limited number of bits |
| + /// for encoding, so check canHoldOffset first. It cannot handle |
| + /// general Constant operands like ConstantRelocatable, since a relocatable |
| + /// can potentially take up too many bits. |
| + static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base, |
| + ConstantInteger32 *ImmOffset, |
| + AddrMode Mode = Offset) { |
| + return new (Func->allocate<OperandMIPS32Mem>()) |
| + OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode); |
| + } |
| + |
| + Variable *getBase() const { return Base; } |
| + ConstantInteger32 *getOffset() const { return ImmOffset; } |
| + AddrMode getAddrMode() const { return Mode; } |
| + |
| + void emit(const Cfg *Func) const override; |
| + using OperandMIPS32::dump; |
| + // void dump(const Cfg *Func, Ostream &Str) const override; |
|
Jim Stichnoth
2015/10/18 11:48:39
remove commented-out code
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + |
| + static bool classof(const Operand *Operand) { |
| + return Operand->getKind() == static_cast<OperandKind>(kMem); |
| + } |
| + |
| + /// 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 |
| + /// MIPS 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); |
| + |
| + virtual void dump(const Cfg *Func, Ostream &Str) const override { |
|
Jim Stichnoth
2015/10/18 11:48:39
I don't think you need both "virtual" and "overrid
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + (void)Func; |
| + (void)Str; |
| + } |
| + |
| +private: |
| + OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, |
| + ConstantInteger32 *ImmOffset, AddrMode Mode); |
| + |
| + Variable *Base; |
| + ConstantInteger32 *ImmOffset; |
| + // Variable *Index; |
|
Jim Stichnoth
2015/10/18 11:48:39
remove
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + AddrMode Mode; |
| +}; |
| + |
| /// Base class for Mips instructions. |
| class InstMIPS32 : public InstTarget { |
| InstMIPS32() = delete; |
| @@ -33,12 +121,28 @@ class InstMIPS32 : public InstTarget { |
| InstMIPS32 &operator=(const InstMIPS32 &) = delete; |
| public: |
| - enum InstKindMIPS32 { k__Start = Inst::Target, Ret }; |
| + enum InstKindMIPS32 { |
| + k__Start = Inst::Target, |
| + Addiu, |
| + La, |
| + Lui, |
| + Mov, // actually a pseudo op for addi rd, rs, 0 |
| + Ori, |
| + Ret |
| + }; |
| static const char *getWidthString(Type Ty); |
| void dump(const Cfg *Func) const override; |
| + void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const { |
| + Str << Opcode << "." << Ty; |
| + } |
| + |
| + /// Shared emit routines for common forms of instructions. |
| + static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst, |
| + const Cfg *Func); |
| + |
| protected: |
| InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest) |
| : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| @@ -75,6 +179,172 @@ private: |
| InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source); |
| }; |
| +/// Instructions of the form x := op(y). |
| +template <InstMIPS32::InstKindMIPS32 K> |
| +class InstMIPS32UnaryopGPR : public InstMIPS32 { |
| + InstMIPS32UnaryopGPR() = delete; |
| + InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete; |
| + InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete; |
| + |
| +public: |
| + static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { |
| + return new (Func->allocate<InstMIPS32UnaryopGPR>()) |
| + InstMIPS32UnaryopGPR(Func, Dest, Src); |
| + } |
| + void emit(const Cfg *Func) const override { |
| + if (!BuildDefs::dump()) |
| + return; |
| + emitUnaryopGPR(Opcode, this, Func); |
| + } |
| + void emitIAS(const Cfg *Func) const override { |
| + (void)Func; |
| + llvm_unreachable("Not yet implemented"); |
| + } |
| + void dump(const Cfg *Func) const override { |
| + if (!BuildDefs::dump()) |
| + return; |
| + Ostream &Str = Func->getContext()->getStrDump(); |
| + dumpOpcode(Str, Opcode, getDest()->getType()); |
| + Str << " "; |
| + dumpDest(Func); |
| + Str << ", "; |
| + dumpSources(Func); |
| + } |
| + static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| + |
| +protected: |
| + InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |
| + : InstMIPS32(Func, K, 2, Dest) { |
| + addSource(Src); |
| + } |
| + |
| +private: |
| + static const char *Opcode; |
| +}; |
| + |
| +template <InstMIPS32::InstKindMIPS32 K, bool Signed = false> |
| +class InstMIPS32Imm16 : public InstMIPS32 { |
| + InstMIPS32Imm16() = delete; |
| + InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete; |
| + InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete; |
| + |
| +public: |
| + static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source, |
| + uint32_t Imm) { |
| + return new (Func->allocate<InstMIPS32Imm16>()) |
| + InstMIPS32Imm16(Func, Dest, Source, Imm); |
| + } |
| + |
| + static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm) { |
| + return new (Func->allocate<InstMIPS32Imm16>()) |
| + InstMIPS32Imm16(Func, Dest, Imm); |
| + } |
| + |
| + void emit(const Cfg *Func) const override { |
| + (void)Func; |
|
Jim Stichnoth
2015/10/18 11:48:39
remove this, as Func is used below.
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + if (!BuildDefs::dump()) |
| + return; |
| + Ostream &Str = Func->getContext()->getStrEmit(); |
| + Str << "\t" << Opcode << "\t"; |
| + getDest()->emit(Func); |
| + if (getSrcSize() > 0) { |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| + } |
| + Str << ", "; |
| + if (Signed) |
| + Str << (int32_t)Imm; |
| + else |
| + Str << Imm; |
| + Str << "\n"; |
| + } |
| + |
| + void emitIAS(const Cfg *Func) const override { |
| + (void)Func; |
| + llvm_unreachable("Not yet implemented"); |
| + } |
| + void dump(const Cfg *Func) const override { |
| + if (!BuildDefs::dump()) |
| + return; |
| + Ostream &Str = Func->getContext()->getStrDump(); |
| + Str << " "; |
| + Str << "\t" << Opcode << "\t"; |
| + dumpDest(Func); |
| + Str << ", "; |
| + dumpSources(Func); |
| + if (Signed) |
| + Str << (int32_t)Imm; |
| + else |
| + Str << Imm; |
| + Str << "\n"; |
| + } |
| + |
| + static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| + |
| +private: |
| + InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm) |
| + : InstMIPS32(Func, K, 2, Dest) { |
| + this->Dead = Dest; |
|
Jim Stichnoth
2015/10/18 11:48:39
I think maybe you meant to set this->Dest, not thi
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + addSource(Source); |
| + this->Imm = Imm; |
|
Jim Stichnoth
2015/10/18 11:48:38
Initialize this->Imm in the initializer list.
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + } |
| + |
| + InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm) |
| + : InstMIPS32(Func, K, 1, Dest) { |
| + this->Dest = Dest; |
|
Jim Stichnoth
2015/10/18 11:48:38
Dest is already initialized in the Inst base class
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + this->Imm = Imm; |
|
Jim Stichnoth
2015/10/18 11:48:38
Initialize in the initializer list.
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| + } |
| + |
| + static const char *Opcode; |
| + |
| + uint32_t Imm; |
|
Jim Stichnoth
2015/10/18 11:48:38
If you initialize Imm everywhere via an initialize
rkotlerimgtec
2015/10/19 00:12:00
Done.
|
| +}; |
| + |
| +typedef InstMIPS32Imm16<InstMIPS32::Addiu, true> InstMIPS32Addiu; |
| +typedef InstMIPS32Imm16<InstMIPS32::Lui> InstMIPS32Lui; |
| +typedef InstMIPS32UnaryopGPR<InstMIPS32::Mov> InstMIPS32MovBase; |
| +typedef InstMIPS32UnaryopGPR<InstMIPS32::La> InstMIPS32La; |
| +typedef InstMIPS32Imm16<InstMIPS32::Ori> InstMIPS32Ori; |
| + |
| +/// Handles (some of) vmov's various formats. |
| +class InstMIPS32Mov final : public InstMIPS32 { |
| + InstMIPS32Mov() = delete; |
| + InstMIPS32Mov(const InstMIPS32Mov &) = delete; |
| + InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete; |
| + |
| +public: |
| + static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src) { |
| + return new (Func->allocate<InstMIPS32Mov>()) InstMIPS32Mov(Func, Dest, Src); |
| + } |
| + bool isRedundantAssign() const override { |
| + return !isMultiDest() && !isMultiSource() && |
| + checkForRedundantAssign(getDest(), getSrc(0)); |
| + } |
| + bool isSimpleAssign() const override { return true; } |
| + 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, Mov); } |
| + |
| + bool isMultiDest() const { return DestHi != nullptr; } |
| + |
| + bool isMultiSource() const { |
| + assert(getSrcSize() == 1 || getSrcSize() == 2); |
| + return getSrcSize() == 2; |
| + } |
| + |
| + Variable *getDestHi() const { return DestHi; } |
| + |
| +private: |
| + InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src); |
| + |
| + void emitMultiDestSingleSource(const Cfg *Func) const; |
| + void emitSingleDestMultiSource(const Cfg *Func) const; |
| + void emitSingleDestSingleSource(const Cfg *Func) const; |
| + |
| + Variable *DestHi = nullptr; |
| +}; |
| + |
| } // end of namespace Ice |
| #endif // SUBZERO_SRC_ICEINSTMIPS32_H |