Subzero: Basic unconditional branch for Mips.

This is part of ARM patch:
https://codereview.chromium.org/1151663004/

BUG=
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1724643002 .

Patch from Reed Kotler <rkotlerimgtec@gmail.com>.
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 4b492c0..506ca6e 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -121,8 +121,10 @@
     Addu,
     And,
     Addiu,
+    Br,
     Call,
     La,
+    Label,
     Lui,
     Mfhi,
     Mflo,
@@ -292,6 +294,73 @@
   static const char *Opcode;
 };
 
+// InstMIPS32Label represents an intra-block label that is the target of an
+// intra-block branch. The offset between the label and the branch must be fit
+// in the instruction immediate (considered "near").
+class InstMIPS32Label : public InstMIPS32 {
+  InstMIPS32Label() = delete;
+  InstMIPS32Label(const InstMIPS32Label &) = delete;
+  InstMIPS32Label &operator=(const InstMIPS32Label &) = delete;
+
+public:
+  static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) {
+    return new (Func->allocate<InstMIPS32Label>())
+        InstMIPS32Label(Func, Target);
+  }
+  uint32_t getEmitInstCount() const override { return 0; }
+  IceString getName(const Cfg *Func) const;
+  SizeT getNumber() const { return Number; }
+  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 *Instr) { return isClassof(Instr, Label); }
+
+private:
+  InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target);
+
+  RelocOffset *OffsetReloc = nullptr;
+
+  SizeT Number; // used for unique label generation.
+};
+
+/// Direct branch instruction.
+class InstMIPS32Br : public InstMIPS32 {
+  InstMIPS32Br() = delete;
+  InstMIPS32Br(const InstMIPS32Br &) = delete;
+  InstMIPS32Br &operator=(const InstMIPS32Br &) = delete;
+
+public:
+  /// Create an unconditional branch to a node.
+  static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) {
+    constexpr CfgNode *NoCondTarget = nullptr;
+    constexpr InstMIPS32Label *NoLabel = nullptr;
+    return new (Func->allocate<InstMIPS32Br>())
+        InstMIPS32Br(Func, NoCondTarget, Target, NoLabel);
+  }
+  const CfgNode *getTargetTrue() const { return TargetTrue; }
+  const CfgNode *getTargetFalse() const { return TargetFalse; }
+
+  bool isUnconditionalBranch() const override { return true; }
+  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override {
+    (void)OldNode;
+    (void)NewNode;
+    return true;
+  };
+  void emit(const Cfg *Func) const override;
+  void emitIAS(const Cfg *Func) const override { (void)Func; };
+  void dump(const Cfg *Func) const override { (void)Func; };
+  static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
+
+private:
+  InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
+               const InstMIPS32Label *Label);
+
+  const CfgNode *TargetTrue;
+  const CfgNode *TargetFalse;
+  const InstMIPS32Label *Label; // Intra-block branch target
+};
+
 class InstMIPS32Call : public InstMIPS32 {
   InstMIPS32Call() = delete;
   InstMIPS32Call(const InstMIPS32Call &) = delete;