Subzero, MIPS32: lowerUnreachable

Patch implements lowerUnreachable and encoding for teq
instruction. To avoid duplicated code, class describing
trap instruction is borrowed from
https://codereview.chromium.org/2339323004/

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

Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
diff --git a/src/IceAssemblerMIPS32.cpp b/src/IceAssemblerMIPS32.cpp
index 961111a..4c9f320 100644
--- a/src/IceAssemblerMIPS32.cpp
+++ b/src/IceAssemblerMIPS32.cpp
@@ -653,6 +653,17 @@
   }
 }
 
+void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt,
+                          const uint32_t TrapCode) {
+  IValueT Opcode = 0x00000034;
+  const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq");
+  const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq");
+  Opcode |= (TrapCode & 0xFFFFF) << 6;
+  Opcode |= Rt << 16;
+  Opcode |= Rs << 21;
+  emitInst(Opcode);
+}
+
 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
   static constexpr IValueT Opcode = 0x4400000D;
   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
diff --git a/src/IceAssemblerMIPS32.h b/src/IceAssemblerMIPS32.h
index ff67904..46a4823 100644
--- a/src/IceAssemblerMIPS32.h
+++ b/src/IceAssemblerMIPS32.h
@@ -178,6 +178,8 @@
 
   void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
 
+  void teq(const Operand *OpRs, const Operand *OpRt, const uint32_t TrapCode);
+
   void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
 
   void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
diff --git a/src/IceInstMIPS32.cpp b/src/IceInstMIPS32.cpp
index 90e10a9..15bf2e1 100644
--- a/src/IceInstMIPS32.cpp
+++ b/src/IceInstMIPS32.cpp
@@ -990,6 +990,11 @@
   Asm->sw(getSrc(0), Mem->getBase(), Imm);
 }
 
+template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
+  auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
+  Asm->teq(getSrc(0), getSrc(1), getTrapCode());
+}
+
 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   Asm->trunc_l_d(getDest(), getSrc(0));
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 3d739b8..3cae464 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -928,6 +928,8 @@
         InstMIPS32Trap(Func, Src0, Src1, Tcode);
   }
 
+  uint32_t getTrapCode() const { return TrapCode; }
+
   void emit(const Cfg *Func) const override {
     if (!BuildDefs::dump())
       return;
@@ -1275,6 +1277,7 @@
 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const;
 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const;
+template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const;
 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const;
 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const;
 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const;
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 51f855d..952aac8 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -3299,8 +3299,9 @@
   UnimplementedLoweringError(this, Instr);
 }
 
-void TargetMIPS32::lowerUnreachable(const InstUnreachable *Instr) {
-  UnimplementedLoweringError(this, Instr);
+void TargetMIPS32::lowerUnreachable(const InstUnreachable *) {
+  const uint32_t TrapCodeZero = 0;
+  _teq(getZero(), getZero(), TrapCodeZero);
 }
 
 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve
diff --git a/tests_lit/assembler/mips32/encoding_trap.ll b/tests_lit/assembler/mips32/encoding_trap.ll
new file mode 100644
index 0000000..a6a86e9
--- /dev/null
+++ b/tests_lit/assembler/mips32/encoding_trap.ll
@@ -0,0 +1,41 @@
+; Test encoding of MIPS32 floating point arithmetic instructions
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=mips32 --args -O2 \
+; RUN:   --allow-externally-defined-symbols --skip-unimplemented \
+; RUN:   | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=mips32 --assemble --disassemble \
+; RUN:   --args -O2 --allow-externally-defined-symbols --skip-unimplemented \
+; RUN:   | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=mips32 --args -O2 \
+; RUN:   --allow-externally-defined-symbols --skip-unimplemented \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=mips32 --assemble --disassemble \
+; RUN:   --args -O2 --allow-externally-defined-symbols --skip-unimplemented \
+; RUN:   | FileCheck %s --check-prefix=DIS
+
+define internal void @encTrap() {
+  unreachable
+}
+
+; ASM-LABEL: encTrap
+; ASM-NEXT: .LencTrap$__0:
+; ASM-NEXT: 	teq	$zero, $zero, 0
+
+; DIS-LABEL: 00000000 <encTrap>:
+; DIS-NEXT:    0:	00000034 	teq	zero,zero
+
+; IASM-LABEL: encTrap:
+; IASM-NEXT: .LencTrap$__0:
+; IASM-NEXT: 	.byte 0x34
+; IASM-NEXT: 	.byte 0x0
+; IASM-NEXT: 	.byte 0x0
+; IASM-NEXT: 	.byte 0x0
diff --git a/tests_lit/llvm2ice_tests/unreachable.ll b/tests_lit/llvm2ice_tests/unreachable.ll
index 71260cc..1ffae40 100644
--- a/tests_lit/llvm2ice_tests/unreachable.ll
+++ b/tests_lit/llvm2ice_tests/unreachable.ll
@@ -18,6 +18,18 @@
 ; RUN:   | %if --need=target_ARM32 --need=allow_dump \
 ; RUN:   --command FileCheck --check-prefix ARM32 %s
 
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble \
+; RUN:   --disassemble --target mips32 -i %s --args -Om1 --skip-unimplemented \
+; RUN:   | %if --need=target_MIPS32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix MIPS32 %s
+
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble \
+; RUN:   --disassemble --target mips32 -i %s --args -O2 --skip-unimplemented \
+; RUN:   | %if --need=target_MIPS32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix MIPS32-O2 %s
+
 define internal i32 @divide(i32 %num, i32 %den) {
 entry:
   %cmp = icmp ne i32 %den, 0
@@ -43,3 +55,15 @@
 ; ARM32: .word 0xe7fedef0
 ; ARM32: bl {{.*}} __divsi3
 ; ARM32: bx lr
+
+; MIPS32-LABEL: divide
+; MIPS32: beqz
+; MIPS32: nop
+; MIPS32: teq zero,zero
+; MIPS32: div
+
+; MIPS32-O2-LABEL: divide
+; MIPS32-O2: bne
+; MIPS32-O2: nop
+; MIPS32-O2: teq zero,zero
+; MIPS32-O2: div