Commit 135f5dbf by Jaydeep Patil Committed by Jim Stichnoth

[SubZero] Generate ELF output for MIPS

This patch adds encoding of few arithmetic and branch instructions. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2259983004 . Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
parent 13f0ca32
......@@ -292,6 +292,7 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
# compile, in the hope of improving parallel build time.
SRCS = \
IceAssemblerARM32.cpp \
IceAssemblerMIPS32.cpp \
IceInstARM32.cpp \
IceInstMIPS32.cpp \
IceInstX8632.cpp \
......
//===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===//
//
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Modified by the Subzero authors.
//
//===----------------------------------------------------------------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
......@@ -26,10 +18,15 @@
#include "IceAssembler.h"
#include "IceDefs.h"
#include "IceFixups.h"
#include "IceInstMIPS32.h"
#include "IceTargetLowering.h"
namespace Ice {
namespace MIPS32 {
using IValueT = uint32_t;
using IOffsetT = int32_t;
class AssemblerMIPS32 : public Assembler {
AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
......@@ -41,34 +38,113 @@ public:
assert(!use_far_branches);
(void)use_far_branches;
}
~AssemblerMIPS32() override = default;
~AssemblerMIPS32() override {
if (BuildDefs::asserts()) {
for (const Label *Label : CfgNodeLabels) {
Label->finalCheck();
}
for (const Label *Label : LocalLabels) {
Label->finalCheck();
}
}
}
void trap();
void nop();
void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm, const char *InsnName);
void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa, const char *InsnName);
void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt, const char *InsnName);
void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, IOffsetT Offset);
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void move(const Operand *OpRd, const Operand *OpRs);
void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void ret(void);
void b(Label *TargetLabel);
void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, Label *TargetLabel);
void bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
Label *TargetLabel);
void alignFunction() override {
llvm::report_fatal_error("Not yet implemented.");
const SizeT Align = 1 << getBundleAlignLog2Bytes();
SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
constexpr SizeT InstSize = sizeof(IValueT);
assert(BytesNeeded % InstMIPS32::InstSize == 0);
while (BytesNeeded > 0) {
trap();
BytesNeeded -= InstSize;
}
}
SizeT getBundleAlignLog2Bytes() const override { return 4; }
const char *getAlignDirective() const override { return ".p2alignl"; }
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
// TODO(reed kotler) . Find out what this should be.
static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0};
return llvm::ArrayRef<uint8_t>(Padding, 4);
}
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
void padWithNop(intptr_t Padding) override {
(void)Padding;
llvm::report_fatal_error("Not yet implemented.");
}
void padWithNop(intptr_t Padding) override;
void bind(Label *label);
void emitTextInst(const std::string &Text, SizeT InstSize);
Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
(void)NodeNumber;
llvm_unreachable("Not yet implemented.");
assert(NodeNumber < CfgNodeLabels.size());
return CfgNodeLabels[NodeNumber];
}
void bindCfgNodeLabel(const CfgNode *) override {
llvm::report_fatal_error("Not yet implemented.");
Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
return getOrCreateLabel(NodeNumber, CfgNodeLabels);
}
Label *getOrCreateLocalLabel(SizeT Number) {
return getOrCreateLabel(Number, LocalLabels);
}
bool fixupIsPCRel(FixupKind Kind) const override {
......@@ -82,6 +158,22 @@ public:
private:
ENABLE_MAKE_UNIQUE;
using LabelVector = std::vector<Label *>;
LabelVector CfgNodeLabels;
LabelVector LocalLabels;
// Returns the offset encoded in the branch instruction Inst.
static IOffsetT decodeBranchOffset(IValueT Inst);
Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
void bindCfgNodeLabel(const CfgNode *) override;
void emitInst(IValueT Value) {
AssemblerBuffer::EnsureCapacity _(&Buffer);
Buffer.emit<IValueT>(Value);
}
};
} // end of namespace MIPS32
......
......@@ -424,6 +424,32 @@ void InstMIPS32Ret::emit(const Cfg *Func) const {
RA->emit(Func);
}
void InstMIPS32Br::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
if (isUnconditionalBranch()) {
Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
} else {
switch (Predicate) {
default:
break;
case CondMIPS32::EQ:
case CondMIPS32::NE:
Asm->bcc(Predicate, getSrc(0), getSrc(1),
Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
break;
case CondMIPS32::EQZ:
case CondMIPS32::NEZ:
case CondMIPS32::LEZ:
case CondMIPS32::LTZ:
case CondMIPS32::GEZ:
case CondMIPS32::GTZ:
Asm->bzc(Predicate, getSrc(0),
Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
break;
}
}
}
void InstMIPS32Br::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
......@@ -536,8 +562,12 @@ void InstMIPS32Call::dump(const Cfg *Func) const {
}
void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
(void)Func;
llvm_unreachable("Not yet implemented");
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *RA = llvm::cast<Variable>(getSrc(0));
assert(RA->hasReg());
assert(RA->getRegNum() == RegMIPS32::Reg_RA);
(void)RA;
Asm->ret();
}
void InstMIPS32Ret::dump(const Cfg *Func) const {
......@@ -552,7 +582,7 @@ void InstMIPS32Ret::dump(const Cfg *Func) const {
void InstMIPS32Mov::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
if (isMultiDest()) {
emitMultiDestSingleSource(Func);
return;
......@@ -566,9 +596,38 @@ void InstMIPS32Mov::emit(const Cfg *Func) const {
emitSingleDestSingleSource(Func);
}
// TODO(jaydeep.patil) Handle all types of operands in mov
void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
(void)Func;
assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
if (isMultiDest()) {
llvm_unreachable("Not yet implemented");
}
if (isMultiSource()) {
llvm_unreachable("Not yet implemented");
}
Variable *Dest = getDest();
Operand *Src = getSrc(0);
auto *SrcV = llvm::dyn_cast<Variable>(Src);
assert(!llvm::isa<Constant>(Src));
const bool DestIsReg = Dest->hasReg();
const bool SrcIsReg = (SrcV && SrcV->hasReg());
// reg to reg
if (DestIsReg && SrcIsReg) {
switch (Dest->getType()) {
default:
break;
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->move(getDest(), getSrc(0));
return;
}
}
llvm_unreachable("Not yet implemented");
}
......@@ -664,10 +723,10 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
case IceType_i16:
case IceType_i32:
Str << "\t"
"add"
"move"
"\t";
getDest()->emit(Func);
Str << ", $zero, ";
Str << ", ";
getSrc(0)->emit(Func);
return;
default:
......@@ -743,5 +802,96 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
llvm::report_fatal_error("mov cant copy stack to stack.");
}
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addiu(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->slti(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sltiu(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->and_(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->andi(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->or_(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->ori(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->xor_(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->xori(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sll(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->srl(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sra(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addu(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->slt(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sltu(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
Asm->sw(getSrc(0), Mem->getBase(), Imm);
}
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
Asm->lw(getDest(), Mem->getBase(), Imm);
}
} // end of namespace MIPS32
} // end of namespace Ice
//===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-=== //
//===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-----===//
//
// The Subzero Code Generator
//
......@@ -199,6 +199,8 @@ public:
Xori
};
static constexpr size_t InstSize = sizeof(uint32_t);
static const char *getWidthString(Type Ty);
CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond);
......@@ -679,7 +681,7 @@ public:
}
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override { (void)Func; };
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
......@@ -755,7 +757,6 @@ public:
Str << (int32_t)Imm;
else
Str << Imm;
Str << "\n";
}
void emitIAS(const Cfg *Func) const override {
......@@ -775,7 +776,6 @@ public:
Str << (int32_t)Imm;
else
Str << Imm;
Str << "\n";
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
......
; Test encoding of MIPS32 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 i32 @test_01(i32 %a) {
%v = add i32 %a, 1
%v1 = and i32 %v, 1
%v2 = or i32 %v1, 1
%v3 = xor i32 %v2, 1
ret i32 %v3
}
; ASM-LABEL: test_01:
; ASM-NEXT: .Ltest_01$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 1
; ASM-NEXT: addu $a0, $a0, $v0
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 1
; ASM-NEXT: and $a0, $a0, $v0
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 1
; ASM-NEXT: or $a0, $a0, $v0
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 1
; ASM-NEXT: xor $a0, $a0, $v0
; ASM-NEXT: move $v0, $a0
; ASM-NEXT: jr $ra
; DIS-LABEL:00000000 <test_01>:
; DIS-NEXT: 0: 24020001 li v0,1
; DIS-NEXT: 4: 00822021 addu a0,a0,v0
; DIS-NEXT: 8: 24020001 li v0,1
; DIS-NEXT: c: 00822024 and a0,a0,v0
; DIS-NEXT: 10: 24020001 li v0,1
; DIS-NEXT: 14: 00822025 or a0,a0,v0
; DIS-NEXT: 18: 24020001 li v0,1
; DIS-NEXT: 1c: 00822026 xor a0,a0,v0
; DIS-NEXT: 20: 00801021 move v0,a0
; DIS-NEXT: 24: 03e00008 jr ra
; DIS-NEXT: 28: 00000000 nop
; IASM-LABEL: test_01:
; IASM-LABEL: .Ltest_01$__0:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x25
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x26
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
define internal i32 @test_02(i32 %a) {
%cmp = icmp eq i32 %a, 9
%cmp.ret_ext = zext i1 %cmp to i32
ret i32 %cmp.ret_ext
}
; ASM-LABEL: test_02:
; ASM-NEXT: .Ltest_02$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 9
; ASM-NEXT: xor $a0, $a0, $v0
; ASM-NEXT: sltiu $a0, $a0, 1
; ASM-NEXT: andi $a0, $a0, 1
; ASM-NEXT: move $v0, $a0
; ASM-NEXT: jr $ra
; DIS-LABEL:00000030 <test_02>:
; DIS-NEXT: 30: 24020009 li v0,9
; DIS-NEXT: 34: 00822026 xor a0,a0,v0
; DIS-NEXT: 38: 2c840001 sltiu a0,a0,1
; DIS-NEXT: 3c: 30840001 andi a0,a0,0x1
; DIS-NEXT: 40: 00801021 move v0,a0
; DIS-NEXT: 44: 03e00008 jr ra
; DIS-NEXT: 48: 00000000 nop
; IASM-LABEL: test_02:
; IASM-LABEL: .Ltest_02$__0:
; IASM-NEXT: .byte 0x9
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x26
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x84
; IASM-NEXT: .byte 0x2c
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x84
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; Test encoding of MIPS32 branch 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 @test_01(i32 %a) {
%cmp = icmp eq i32 %a, 1
br i1 %cmp, label %then, label %else
then:
br label %end
else:
br label %end
end:
ret void
}
; ASM-LABEL: test_01:
; ASM-LABEL: .Ltest_01$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 1
; ASM-NEXT: bne $a0, $v0, .Ltest_01$end
; ASM-LABEL: .Ltest_01$end:
; ASM-NEXT: jr $ra
; ASM-LABEL: .Ltest_01$then:
; ASM-LABEL: .Ltest_01$else:
; DIS-LABEL:00000000 <test_01>:
; DIS-NEXT: 0: 24020001 li v0,1
; DIS-NEXT: 4: 14820001 bne a0,v0,c <.Ltest_01$end>
; DIS-NEXT: 8: 00000000 nop
; DIS-LABEL:0000000c <.Ltest_01$end>:
; DIS-NEXT: c: 03e00008 jr ra
; DIS-NEXT: 10: 00000000 nop
; IASM-LABEL: test_01:
; IASM-LABEL: .Ltest_01$__0:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_01$end:
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_01$then:
; IASM-LABEL: .Ltest_01$else:
define internal void @test_02(i32 %a) {
%cmp = icmp ne i32 %a, 2
br i1 %cmp, label %then, label %else
then:
br label %end
else:
br label %end
end:
ret void
}
; ASM-LABEL: test_02:
; ASM-LABEL: .Ltest_02$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 2
; ASM-NEXT: beq $a0, $v0, .Ltest_02$end
; ASM-LABEL: .Ltest_02$end:
; ASM-NEXT: jr $ra
; ASM-LABEL: .Ltest_02$then:
; ASM-LABEL: .Ltest_02$else:
; DIS-LABEL:00000020 <test_02>:
; DIS-NEXT: 20: 24020002 li v0,2
; DIS-NEXT: 24: 10820001 beq a0,v0,2c <.Ltest_02$end>
; DIS-NEXT: 28: 00000000 nop
; DIS-LABEL:0000002c <.Ltest_02$end>:
; DIS-NEXT: 2c: 03e00008 jr ra
; DIS-NEXT: 30: 00000000 nop
; IASM-LABEL: test_02:
; IASM-LABEL: .Ltest_02$__0:
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_02$end:
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_02$then:
; IASM-LABEL: .Ltest_02$else:
define internal void @test_03(i32 %a) {
%cmp = icmp ugt i32 %a, 3
br i1 %cmp, label %then, label %else
then:
br label %end
else:
br label %end
end:
ret void
}
; ASM-LABEL: test_03:
; ASM-LABEL: .Ltest_03$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 3
; ASM-NEXT: sltu $v0, $v0, $a0
; ASM-NEXT: beqz $v0, .Ltest_03$end
; ASM-LABEL: .Ltest_03$end:
; ASM-NEXT: jr $ra
; ASM-LABEL: .Ltest_03$then:
; ASM-LABEL: .Ltest_03$else:
; DIS-LABEL:00000040 <test_03>:
; DIS-NEXT: 40: 24020003 li v0,3
; DIS-NEXT: 44: 0044102b sltu v0,v0,a0
; DIS-NEXT: 48: 10400001 beqz v0,50 <.Ltest_03$end>
; DIS-NEXT: 4c: 00000000 nop
; DIS-LABEL:00000050 <.Ltest_03$end>:
; DIS-NEXT: 50: 03e00008 jr ra
; DIS-NEXT: 54: 00000000 nop
; IASM-LABEL: test_03:
; IASM-LABEL: .Ltest_03$__0:
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x2b
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x44
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x40
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_03$end:
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_03$then:
; IASM-LABEL: .Ltest_03$else:
define internal void @test_04(i32 %a) {
%cmp = icmp uge i32 %a, 4
br i1 %cmp, label %then, label %else
then:
br label %end
else:
br label %end
end:
ret void
}
; ASM-LABEL: test_04:
; ASM-LABEL: .Ltest_04$__0:
; ASM-NEXT: # $zero = def.pseudo
; ASM-NEXT: addiu $v0, $zero, 4
; ASM-NEXT: sltu $a0, $a0, $v0
; ASM-NEXT: bnez $a0, .Ltest_04$end
; ASM-LABEL: .Ltest_04$end:
; ASM-NEXT: jr $ra
; ASM-LABEL: .Ltest_04$then:
; ASM-LABEL: .Ltest_04$else:
; DIS-LABEL:00000060 <test_04>:
; DIS-NEXT: 60: 24020004 li v0,4
; DIS-NEXT: 64: 0082202b sltu a0,a0,v0
; DIS-NEXT: 68: 14800001 bnez a0,70 <.Ltest_04$end>
; DIS-NEXT: 6c: 00000000 nop
; DIS-LABEL:00000070 <.Ltest_04$end>:
; DIS-NEXT: 70: 03e00008 jr ra
; DIS-NEXT: 74: 00000000 nop
; IASM-LABEL: test_04:
; IASM-LABEL: .Ltest_04$__0:
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x24
; IASM-NEXT: .byte 0x2b
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_04$end:
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-LABEL: .Ltest_04$then:
; IASM-LABEL: .Ltest_04$else:
......@@ -47,7 +47,7 @@ entry:
}
; MIPS32-LABEL: ignore64BitArg
; MIPS32: add v0,zero,a2
; MIPS32: move v0,a2
define internal i32 @pass64BitArg(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f) {
entry:
......@@ -203,8 +203,8 @@ entry:
; ARM32: bx lr
; MIPS32-LABEL; return64BitArg
; MIPS32: add v0,zero,a2
; MIPS32: add v1,zero,a3
; MIPS32: move v0,a2
; MIPS32: move v1,a3
; MIPS32: jr ra
define internal i64 @return64BitConst() {
......@@ -800,7 +800,7 @@ entry:
; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Signed
; MIPS32: add v0,zero,a2
; MIPS32: move v0,a2
define internal i32 @trunc64To16Signed(i64 %a) {
entry:
......@@ -822,7 +822,7 @@ entry:
; MIPS32-LABEL: trunc64To16Signed
; MIPS32: sll a0,a0,0x10
; MIPS32: sra a0,a0,0x10
; MIPS32: add v0,zero,a0
; MIPS32: move v0,a0
define internal i32 @trunc64To8Signed(i64 %a) {
entry:
......@@ -844,7 +844,7 @@ entry:
; MIPS32-LABEL: trunc64To8Signed
; MIPS32: sll a0,a0,0x18
; MIPS32: sra a0,a0,0x18
; MIPS32: add v0,zero,a0
; MIPS32: move v0,a0
define internal i32 @trunc64To32SignedConst() {
entry:
......@@ -905,7 +905,7 @@ entry:
; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Unsigned
; MIPS32: add v0,zero,a2
; MIPS32: move v0,a2
define internal i32 @trunc64To16Unsigned(i64 %a) {
entry:
......@@ -926,7 +926,7 @@ entry:
; MIPS32-LABEL: trunc64To16Unsigned
; MIPS32: andi a0,a0,0xffff
; MIPS32: add v0,zero,a0
; MIPS32: move v0,a0
define internal i32 @trunc64To8Unsigned(i64 %a) {
entry:
......@@ -947,7 +947,7 @@ entry:
; MIPS32-LABEL: trunc64To8Unsigned
; MIPS32: andi a0,a0,0xff
; MIPS32: add v0,zero,a0
; MIPS32: move v0,a0
define internal i32 @trunc64To1(i64 %a) {
entry:
......@@ -972,7 +972,7 @@ entry:
; MIPS32-LABEL: trunc64To1
; MIPS32: andi {{.*}},a0,0x1
; MIPS32: add v0,{{.*}}
; MIPS32: move v0,a0
define internal i64 @sext32To64(i32 %a) {
entry:
......@@ -992,8 +992,8 @@ entry:
; MIPS32-LABEL: sext32To64
; MIPS32-LABEL: sra {{.*}},a0,0x1f
; MIPS32-LABEL: add v1,{{.*}}
; MIPS32-LABEL: add v0,{{.*}}
; MIPS32-LABEL: move v1,v0
; MIPS32-LABEL: move v0,a0
define internal i64 @sext16To64(i32 %a) {
entry:
......@@ -1017,8 +1017,8 @@ entry:
; MIPS32: sll {{.*}},{{.*}},0x10
; MIPS32: sra {{.*}},{{.*}},0x10
; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal i64 @sext8To64(i32 %a) {
entry:
......@@ -1042,8 +1042,8 @@ entry:
; MIPS32: sll {{.*}},a0,0x18
; MIPS32: sra {{.*}},{{.*}},0x18
; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal i64 @sext1To64(i32 %a) {
entry:
......@@ -1070,8 +1070,8 @@ entry:
; MIPS32-LABEL: sext1To64
; MIPS32: sll {{.*}},a0,0x1f
; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,a0
; MIPS32: move v0,a0
define internal i64 @zext32To64(i32 %a) {
entry:
......@@ -1091,8 +1091,8 @@ entry:
; MIPS32-LABEL: zext32To64
; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal i64 @zext16To64(i32 %a) {
entry:
......@@ -1115,8 +1115,8 @@ entry:
; MIPS32-LABEL: zext16To64
; MIPS32: andi {{.*}},a0,0xffff
; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal i64 @zext8To64(i32 %a) {
entry:
......@@ -1139,8 +1139,8 @@ entry:
; MIPS32-LABEL: zext8To64
; MIPS32: andi {{.*}},a0,0xff
; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal i64 @zext1To64(i32 %a) {
entry:
......@@ -1164,8 +1164,8 @@ entry:
; MIPS32-LABEL: zext1To64
; MIPS32: andi {{.*}},a0,0x1
; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}}
; MIPS32: add v0,{{.*}}
; MIPS32: move v1,v0
; MIPS32: move v0,a0
define internal void @icmpEq64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry:
......
......@@ -42,7 +42,7 @@ entry:
; ARM32-LABEL: test_returning32_arg0
; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg0
; MIPS32: add v0,zero,a0
; MIPS32: move v0,a0
; MIPS32-NEXT: jr ra
define internal i32 @test_returning32_arg1(i32 %arg0, i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4, i32 %arg5, i32 %arg6, i32 %arg7) {
......@@ -56,7 +56,7 @@ entry:
; ARM32-NEXT: mov r0, r1
; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg1
; MIPS32: add v0,zero,a1
; MIPS32: move v0,a1
; MIPS32-NEXT: jr ra
define internal i32 @test_returning32_arg2(i32 %arg0, i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4, i32 %arg5, i32 %arg6, i32 %arg7) {
......@@ -70,7 +70,7 @@ entry:
; ARM32-NEXT: mov r0, r2
; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg2
; MIPS32: add v0,zero,a2
; MIPS32: move v0,a2
; MIPS32-NEXT: jr ra
......@@ -122,8 +122,8 @@ entry:
; ARM32-LABEL: test_returning64_arg0
; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning64_arg0
; MIPS32-NEXT: add v0,zero,a0
; MIPS32-NEXT: add v1,zero,a1
; MIPS32-NEXT: move v0,a0
; MIPS32-NEXT: move v1,a1
define internal i64 @test_returning64_arg1(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) {
......@@ -139,8 +139,8 @@ entry:
; ARM32-NEXT: mov r1, r3
; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning64_arg1
; MIPS32-NEXT: add v0,zero,a2
; MIPS32-NEXT: add v1,zero,a3
; MIPS32-NEXT: move v0,a2
; MIPS32-NEXT: move v1,a3
define internal i64 @test_returning64_arg2(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) {
entry:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment