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