Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Unified Diff: src/IceInstMIPS32.h

Issue 1416493002: Implements simple returns and call args for Mips. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Corrections to patch set 3 per stichnot review Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/IceInstMIPS32.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceInstMIPS32.h
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 1c4863f5cf853f74191fb4f5993faae158b7f555..fe3e274a83a9d0ad253e0d2a83284031c4d272cd 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -26,6 +26,84 @@ 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>";
+ }
+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;
+
+ 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);
+
+ void dump(const Cfg *Func, Ostream &Str) const override {
+ (void)Func;
+ (void)Str;
+ }
+
+private:
+ OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base,
+ ConstantInteger32 *ImmOffset, AddrMode Mode);
+
+ Variable *Base;
+ ConstantInteger32 *ImmOffset;
+ AddrMode Mode;
+};
+
/// Base class for Mips instructions.
class InstMIPS32 : public InstTarget {
InstMIPS32() = delete;
@@ -33,12 +111,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 +169,166 @@ 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, 1, 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 {
+ 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, 1, Dest), Imm(Imm){
+ addSource(Source);
+ }
+
+ InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm)
+ : InstMIPS32(Func, K, 0, Dest), Imm(Imm) {
+ }
+
+ static const char *Opcode;
+
+ const uint32_t Imm;
+};
+
+typedef InstMIPS32Imm16<InstMIPS32::Addiu, true> InstMIPS32Addiu;
+typedef InstMIPS32Imm16<InstMIPS32::Lui> InstMIPS32Lui;
+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
« no previous file with comments | « no previous file | src/IceInstMIPS32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698