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) ...@@ -292,6 +292,7 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
# compile, in the hope of improving parallel build time. # compile, in the hope of improving parallel build time.
SRCS = \ SRCS = \
IceAssemblerARM32.cpp \ IceAssemblerARM32.cpp \
IceAssemblerMIPS32.cpp \
IceInstARM32.cpp \ IceInstARM32.cpp \
IceInstMIPS32.cpp \ IceInstMIPS32.cpp \
IceInstX8632.cpp \ IceInstX8632.cpp \
......
//===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Implements the Assembler class for MIPS32.
///
//===----------------------------------------------------------------------===//
#include "IceAssemblerMIPS32.h"
#include "IceCfgNode.h"
#include "IceRegistersMIPS32.h"
#include "IceUtils.h"
namespace {
using namespace Ice;
using namespace Ice::MIPS32;
// Offset modifier to current PC for next instruction.
static constexpr IOffsetT kPCReadOffset = 4;
// Mask to pull out PC offset from branch instruction.
static constexpr int kBranchOffsetBits = 16;
static constexpr IOffsetT kBranchOffsetMask = 0x0000ffff;
} // end of anonymous namespace
namespace Ice {
namespace MIPS32 {
void AssemblerMIPS32::emitTextInst(const std::string &Text, SizeT InstSize) {
AssemblerFixup *F = createTextFixup(Text, InstSize);
emitFixup(F);
for (SizeT I = 0; I < InstSize; ++I) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
Buffer.emit<char>(0);
}
}
namespace {
// TEQ $0, $0 - Trap if equal
static constexpr uint8_t TrapBytesRaw[] = {0x00, 0x00, 0x00, 0x34};
const auto TrapBytes =
llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
} // end of anonymous namespace
llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const {
return TrapBytes;
}
void AssemblerMIPS32::trap() {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
for (const uint8_t &Byte : reverse_range(TrapBytes))
Buffer.emit<uint8_t>(Byte);
}
void AssemblerMIPS32::nop() { emitInst(0); }
void AssemblerMIPS32::padWithNop(intptr_t Padding) {
constexpr intptr_t InstWidth = sizeof(IValueT);
assert(Padding % InstWidth == 0 &&
"Padding not multiple of instruction size");
for (intptr_t i = 0; i < Padding; i += InstWidth)
nop();
}
Label *AssemblerMIPS32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
Label *L = nullptr;
if (Number == Labels.size()) {
L = new (this->allocate<Label>()) Label();
Labels.push_back(L);
return L;
}
if (Number > Labels.size()) {
Labels.resize(Number + 1);
}
L = Labels[Number];
if (L == nullptr) {
L = new (this->allocate<Label>()) Label();
Labels[Number] = L;
}
return L;
}
void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
constexpr SizeT InstSize = 0;
emitTextInst(Node->getAsmName() + ":", InstSize);
}
SizeT NodeNumber = Node->getIndex();
assert(!getPreliminary());
Label *L = getOrCreateCfgNodeLabel(NodeNumber);
this->bind(L);
}
// Checks that Offset can fit in imm16 constant of branch instruction.
void assertCanEncodeBranchOffset(IOffsetT Offset) {
(void)Offset;
(void)kBranchOffsetBits;
assert(Utils::IsAligned(Offset, 4));
assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2));
}
IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
Offset -= kPCReadOffset;
assertCanEncodeBranchOffset(Offset);
Offset >>= 2;
Offset &= kBranchOffsetMask;
return (Inst & ~kBranchOffsetMask) | Offset;
}
IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) {
int16_t imm = (Inst & kBranchOffsetMask);
IOffsetT Offset = imm;
Offset = Offset << 2;
return (Offset + kPCReadOffset);
}
void AssemblerMIPS32::bind(Label *L) {
IOffsetT BoundPc = Buffer.size();
assert(!L->isBound()); // Labels can only be bound once.
while (L->isLinked()) {
IOffsetT Position = L->getLinkPosition();
IOffsetT Dest = BoundPc - Position;
IValueT Inst = Buffer.load<IValueT>(Position);
Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
L->setPosition(decodeBranchOffset(Inst));
}
L->bindTo(BoundPc);
}
enum RegSetWanted { WantGPRegs, WantFPRegs };
IValueT getEncodedGPRegNum(const Variable *Var) {
assert(Var->hasReg());
const auto Reg = Var->getRegNum();
return RegMIPS32::getEncodedGPR(Reg);
}
bool encodeOperand(const Operand *Opnd, IValueT &Value,
RegSetWanted WantedRegSet) {
Value = 0;
if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
if (Var->hasReg()) {
switch (WantedRegSet) {
case WantGPRegs:
Value = getEncodedGPRegNum(Var);
break;
default:
break;
}
return true;
}
return false;
}
return false;
}
IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
const char *RegName, const char *InstName) {
IValueT Reg = 0;
if (encodeOperand(OpReg, Reg, WantedRegSet) != true)
llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
RegName);
return Reg;
}
IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
const char *InstName) {
return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
}
void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
const Operand *OpRs, const uint32_t Imm,
const char *InsnName) {
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
Opcode |= Rs << 21;
Opcode |= Rt << 16;
Opcode |= Imm & 0xffff;
emitInst(Opcode);
}
void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd,
const Operand *OpRt, const uint32_t Sa,
const char *InsnName) {
const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
Opcode |= Rt << 16;
Opcode |= Rd << 11;
Opcode |= (Sa & 0x1f) << 6;
emitInst(Opcode);
}
void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
const Operand *OpRs, const Operand *OpRt,
const char *InsnName) {
const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
Opcode |= Rs << 21;
Opcode |= Rt << 16;
Opcode |= Rd << 11;
emitInst(Opcode);
}
void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x24000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
}
void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x28000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
}
void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x2c000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
}
void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000024;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and");
}
void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x30000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
}
void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000025;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
}
void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x34000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
}
void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000026;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
}
void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x38000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
}
void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa) {
static constexpr IValueT Opcode = 0x00000000;
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
}
void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa) {
static constexpr IValueT Opcode = 0x00000002;
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
}
void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa) {
static constexpr IValueT Opcode = 0x00000003;
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
}
void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
IValueT Opcode = 0x00000021;
const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
const IValueT Rt = 0; // $0
Opcode |= Rs << 21;
Opcode |= Rt << 16;
Opcode |= Rd << 11;
emitInst(Opcode);
}
void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000021;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
}
void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x0000002B;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
}
void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x0000002A;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
}
void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) {
static constexpr IValueT Opcode = 0xAC000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
}
void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) {
static constexpr IValueT Opcode = 0x8C000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
}
void AssemblerMIPS32::ret(void) {
static constexpr IValueT Opcode = 0x03E00008; // JR $31
emitInst(Opcode);
nop(); // delay slot
}
void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, IOffsetT Offset) {
IValueT Opcode = 0;
switch (Cond) {
default:
break;
case CondMIPS32::AL:
case CondMIPS32::EQ:
case CondMIPS32::EQZ:
Opcode = 0x10000000;
break;
case CondMIPS32::NE:
case CondMIPS32::NEZ:
Opcode = 0x14000000;
break;
case CondMIPS32::LEZ:
Opcode = 0x18000000;
break;
case CondMIPS32::LTZ:
Opcode = 0x04000000;
break;
case CondMIPS32::GEZ:
Opcode = 0x04010000;
break;
case CondMIPS32::GTZ:
Opcode = 0x1C000000;
break;
}
if (Opcode == 0) {
llvm::report_fatal_error("Branch: Invalid condition");
}
if (OpRs != nullptr) {
IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch");
Opcode |= Rs << 21;
}
if (OpRt != nullptr) {
IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
Opcode |= Rt << 16;
}
Opcode = encodeBranchOffset(Offset, Opcode);
emitInst(Opcode);
nop(); // delay slot
}
void AssemblerMIPS32::b(Label *TargetLabel) {
static constexpr Operand *OpRsNone = nullptr;
static constexpr Operand *OpRtNone = nullptr;
if (TargetLabel->isBound()) {
const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest);
return;
}
const IOffsetT Position = Buffer.size();
emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, TargetLabel->getEncodedPosition());
TargetLabel->linkTo(*this, Position);
}
void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, Label *TargetLabel) {
if (TargetLabel->isBound()) {
const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
emitBr(Cond, OpRs, OpRt, Dest);
return;
}
const IOffsetT Position = Buffer.size();
emitBr(Cond, OpRs, OpRt, TargetLabel->getEncodedPosition());
TargetLabel->linkTo(*this, Position);
}
void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
Label *TargetLabel) {
static constexpr Operand *OpRtNone = nullptr;
if (TargetLabel->isBound()) {
const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
emitBr(Cond, OpRs, OpRtNone, Dest);
return;
}
const IOffsetT Position = Buffer.size();
emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition());
TargetLabel->linkTo(*this, Position);
}
} // end of namespace MIPS32
} // end of namespace Ice
//===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===// //===- 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 // The Subzero Code Generator
// //
// This file is distributed under the University of Illinois Open Source // This file is distributed under the University of Illinois Open Source
...@@ -26,10 +18,15 @@ ...@@ -26,10 +18,15 @@
#include "IceAssembler.h" #include "IceAssembler.h"
#include "IceDefs.h" #include "IceDefs.h"
#include "IceFixups.h" #include "IceFixups.h"
#include "IceInstMIPS32.h"
#include "IceTargetLowering.h"
namespace Ice { namespace Ice {
namespace MIPS32 { namespace MIPS32 {
using IValueT = uint32_t;
using IOffsetT = int32_t;
class AssemblerMIPS32 : public Assembler { class AssemblerMIPS32 : public Assembler {
AssemblerMIPS32(const AssemblerMIPS32 &) = delete; AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete; AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
...@@ -41,34 +38,113 @@ public: ...@@ -41,34 +38,113 @@ public:
assert(!use_far_branches); assert(!use_far_branches);
(void)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 { 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; } SizeT getBundleAlignLog2Bytes() const override { return 4; }
const char *getAlignDirective() const override { return ".p2alignl"; } const char *getAlignDirective() const override { return ".p2alignl"; }
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { 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);
}
void padWithNop(intptr_t Padding) override { void padWithNop(intptr_t Padding) override;
(void)Padding;
llvm::report_fatal_error("Not yet implemented."); void bind(Label *label);
}
void emitTextInst(const std::string &Text, SizeT InstSize);
Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
(void)NodeNumber; assert(NodeNumber < CfgNodeLabels.size());
llvm_unreachable("Not yet implemented."); return CfgNodeLabels[NodeNumber];
} }
void bindCfgNodeLabel(const CfgNode *) override { Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
llvm::report_fatal_error("Not yet implemented."); return getOrCreateLabel(NodeNumber, CfgNodeLabels);
}
Label *getOrCreateLocalLabel(SizeT Number) {
return getOrCreateLabel(Number, LocalLabels);
} }
bool fixupIsPCRel(FixupKind Kind) const override { bool fixupIsPCRel(FixupKind Kind) const override {
...@@ -82,6 +158,22 @@ public: ...@@ -82,6 +158,22 @@ public:
private: private:
ENABLE_MAKE_UNIQUE; 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 } // end of namespace MIPS32
......
...@@ -424,6 +424,32 @@ void InstMIPS32Ret::emit(const Cfg *Func) const { ...@@ -424,6 +424,32 @@ void InstMIPS32Ret::emit(const Cfg *Func) const {
RA->emit(Func); 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 { void InstMIPS32Br::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
...@@ -536,8 +562,12 @@ void InstMIPS32Call::dump(const Cfg *Func) const { ...@@ -536,8 +562,12 @@ void InstMIPS32Call::dump(const Cfg *Func) const {
} }
void InstMIPS32Ret::emitIAS(const Cfg *Func) const { void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
(void)Func; auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
llvm_unreachable("Not yet implemented"); 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 { void InstMIPS32Ret::dump(const Cfg *Func) const {
...@@ -552,7 +582,7 @@ 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 { void InstMIPS32Mov::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
if (isMultiDest()) { if (isMultiDest()) {
emitMultiDestSingleSource(Func); emitMultiDestSingleSource(Func);
return; return;
...@@ -566,9 +596,38 @@ void InstMIPS32Mov::emit(const Cfg *Func) const { ...@@ -566,9 +596,38 @@ void InstMIPS32Mov::emit(const Cfg *Func) const {
emitSingleDestSingleSource(Func); emitSingleDestSingleSource(Func);
} }
// TODO(jaydeep.patil) Handle all types of operands in mov
void InstMIPS32Mov::emitIAS(const Cfg *Func) const { void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1); assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
(void)Func;
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"); llvm_unreachable("Not yet implemented");
} }
...@@ -664,10 +723,10 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -664,10 +723,10 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
Str << "\t" Str << "\t"
"add" "move"
"\t"; "\t";
getDest()->emit(Func); getDest()->emit(Func);
Str << ", $zero, "; Str << ", ";
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
return; return;
default: default:
...@@ -743,5 +802,96 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -743,5 +802,96 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
llvm::report_fatal_error("mov cant copy stack to stack."); 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 MIPS32
} // end of namespace Ice } // end of namespace Ice
//===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-=== // //===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-----===//
// //
// The Subzero Code Generator // The Subzero Code Generator
// //
...@@ -199,6 +199,8 @@ public: ...@@ -199,6 +199,8 @@ public:
Xori Xori
}; };
static constexpr size_t InstSize = sizeof(uint32_t);
static const char *getWidthString(Type Ty); static const char *getWidthString(Type Ty);
CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond); CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond);
...@@ -679,7 +681,7 @@ public: ...@@ -679,7 +681,7 @@ public:
} }
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
void emit(const Cfg *Func) const 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; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Instr) { return isClassof(Instr, Br); } static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
...@@ -755,7 +757,6 @@ public: ...@@ -755,7 +757,6 @@ public:
Str << (int32_t)Imm; Str << (int32_t)Imm;
else else
Str << Imm; Str << Imm;
Str << "\n";
} }
void emitIAS(const Cfg *Func) const override { void emitIAS(const Cfg *Func) const override {
...@@ -775,7 +776,6 @@ public: ...@@ -775,7 +776,6 @@ public:
Str << (int32_t)Imm; Str << (int32_t)Imm;
else else
Str << Imm; Str << Imm;
Str << "\n";
} }
static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 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: ...@@ -47,7 +47,7 @@ entry:
} }
; MIPS32-LABEL: ignore64BitArg ; 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) { define internal i32 @pass64BitArg(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f) {
entry: entry:
...@@ -203,8 +203,8 @@ entry: ...@@ -203,8 +203,8 @@ entry:
; ARM32: bx lr ; ARM32: bx lr
; MIPS32-LABEL; return64BitArg ; MIPS32-LABEL; return64BitArg
; MIPS32: add v0,zero,a2 ; MIPS32: move v0,a2
; MIPS32: add v1,zero,a3 ; MIPS32: move v1,a3
; MIPS32: jr ra ; MIPS32: jr ra
define internal i64 @return64BitConst() { define internal i64 @return64BitConst() {
...@@ -800,7 +800,7 @@ entry: ...@@ -800,7 +800,7 @@ entry:
; ARM32: mov r0, r2 ; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Signed ; MIPS32-LABEL: trunc64To32Signed
; MIPS32: add v0,zero,a2 ; MIPS32: move v0,a2
define internal i32 @trunc64To16Signed(i64 %a) { define internal i32 @trunc64To16Signed(i64 %a) {
entry: entry:
...@@ -822,7 +822,7 @@ entry: ...@@ -822,7 +822,7 @@ entry:
; MIPS32-LABEL: trunc64To16Signed ; MIPS32-LABEL: trunc64To16Signed
; MIPS32: sll a0,a0,0x10 ; MIPS32: sll a0,a0,0x10
; MIPS32: sra a0,a0,0x10 ; MIPS32: sra a0,a0,0x10
; MIPS32: add v0,zero,a0 ; MIPS32: move v0,a0
define internal i32 @trunc64To8Signed(i64 %a) { define internal i32 @trunc64To8Signed(i64 %a) {
entry: entry:
...@@ -844,7 +844,7 @@ entry: ...@@ -844,7 +844,7 @@ entry:
; MIPS32-LABEL: trunc64To8Signed ; MIPS32-LABEL: trunc64To8Signed
; MIPS32: sll a0,a0,0x18 ; MIPS32: sll a0,a0,0x18
; MIPS32: sra a0,a0,0x18 ; MIPS32: sra a0,a0,0x18
; MIPS32: add v0,zero,a0 ; MIPS32: move v0,a0
define internal i32 @trunc64To32SignedConst() { define internal i32 @trunc64To32SignedConst() {
entry: entry:
...@@ -905,7 +905,7 @@ entry: ...@@ -905,7 +905,7 @@ entry:
; ARM32: mov r0, r2 ; ARM32: mov r0, r2
; MIPS32-LABEL: trunc64To32Unsigned ; MIPS32-LABEL: trunc64To32Unsigned
; MIPS32: add v0,zero,a2 ; MIPS32: move v0,a2
define internal i32 @trunc64To16Unsigned(i64 %a) { define internal i32 @trunc64To16Unsigned(i64 %a) {
entry: entry:
...@@ -926,7 +926,7 @@ entry: ...@@ -926,7 +926,7 @@ entry:
; MIPS32-LABEL: trunc64To16Unsigned ; MIPS32-LABEL: trunc64To16Unsigned
; MIPS32: andi a0,a0,0xffff ; MIPS32: andi a0,a0,0xffff
; MIPS32: add v0,zero,a0 ; MIPS32: move v0,a0
define internal i32 @trunc64To8Unsigned(i64 %a) { define internal i32 @trunc64To8Unsigned(i64 %a) {
entry: entry:
...@@ -947,7 +947,7 @@ entry: ...@@ -947,7 +947,7 @@ entry:
; MIPS32-LABEL: trunc64To8Unsigned ; MIPS32-LABEL: trunc64To8Unsigned
; MIPS32: andi a0,a0,0xff ; MIPS32: andi a0,a0,0xff
; MIPS32: add v0,zero,a0 ; MIPS32: move v0,a0
define internal i32 @trunc64To1(i64 %a) { define internal i32 @trunc64To1(i64 %a) {
entry: entry:
...@@ -972,7 +972,7 @@ entry: ...@@ -972,7 +972,7 @@ entry:
; MIPS32-LABEL: trunc64To1 ; MIPS32-LABEL: trunc64To1
; MIPS32: andi {{.*}},a0,0x1 ; MIPS32: andi {{.*}},a0,0x1
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @sext32To64(i32 %a) { define internal i64 @sext32To64(i32 %a) {
entry: entry:
...@@ -992,8 +992,8 @@ entry: ...@@ -992,8 +992,8 @@ entry:
; MIPS32-LABEL: sext32To64 ; MIPS32-LABEL: sext32To64
; MIPS32-LABEL: sra {{.*}},a0,0x1f ; MIPS32-LABEL: sra {{.*}},a0,0x1f
; MIPS32-LABEL: add v1,{{.*}} ; MIPS32-LABEL: move v1,v0
; MIPS32-LABEL: add v0,{{.*}} ; MIPS32-LABEL: move v0,a0
define internal i64 @sext16To64(i32 %a) { define internal i64 @sext16To64(i32 %a) {
entry: entry:
...@@ -1017,8 +1017,8 @@ entry: ...@@ -1017,8 +1017,8 @@ entry:
; MIPS32: sll {{.*}},{{.*}},0x10 ; MIPS32: sll {{.*}},{{.*}},0x10
; MIPS32: sra {{.*}},{{.*}},0x10 ; MIPS32: sra {{.*}},{{.*}},0x10
; MIPS32: sra {{.*}},{{.*}},0x1f ; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @sext8To64(i32 %a) { define internal i64 @sext8To64(i32 %a) {
entry: entry:
...@@ -1042,8 +1042,8 @@ entry: ...@@ -1042,8 +1042,8 @@ entry:
; MIPS32: sll {{.*}},a0,0x18 ; MIPS32: sll {{.*}},a0,0x18
; MIPS32: sra {{.*}},{{.*}},0x18 ; MIPS32: sra {{.*}},{{.*}},0x18
; MIPS32: sra {{.*}},{{.*}},0x1f ; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @sext1To64(i32 %a) { define internal i64 @sext1To64(i32 %a) {
entry: entry:
...@@ -1070,8 +1070,8 @@ entry: ...@@ -1070,8 +1070,8 @@ entry:
; MIPS32-LABEL: sext1To64 ; MIPS32-LABEL: sext1To64
; MIPS32: sll {{.*}},a0,0x1f ; MIPS32: sll {{.*}},a0,0x1f
; MIPS32: sra {{.*}},{{.*}},0x1f ; MIPS32: sra {{.*}},{{.*}},0x1f
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,a0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @zext32To64(i32 %a) { define internal i64 @zext32To64(i32 %a) {
entry: entry:
...@@ -1091,8 +1091,8 @@ entry: ...@@ -1091,8 +1091,8 @@ entry:
; MIPS32-LABEL: zext32To64 ; MIPS32-LABEL: zext32To64
; MIPS32: li {{.*}},0 ; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @zext16To64(i32 %a) { define internal i64 @zext16To64(i32 %a) {
entry: entry:
...@@ -1115,8 +1115,8 @@ entry: ...@@ -1115,8 +1115,8 @@ entry:
; MIPS32-LABEL: zext16To64 ; MIPS32-LABEL: zext16To64
; MIPS32: andi {{.*}},a0,0xffff ; MIPS32: andi {{.*}},a0,0xffff
; MIPS32: li {{.*}},0 ; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @zext8To64(i32 %a) { define internal i64 @zext8To64(i32 %a) {
entry: entry:
...@@ -1139,8 +1139,8 @@ entry: ...@@ -1139,8 +1139,8 @@ entry:
; MIPS32-LABEL: zext8To64 ; MIPS32-LABEL: zext8To64
; MIPS32: andi {{.*}},a0,0xff ; MIPS32: andi {{.*}},a0,0xff
; MIPS32: li {{.*}},0 ; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal i64 @zext1To64(i32 %a) { define internal i64 @zext1To64(i32 %a) {
entry: entry:
...@@ -1164,8 +1164,8 @@ entry: ...@@ -1164,8 +1164,8 @@ entry:
; MIPS32-LABEL: zext1To64 ; MIPS32-LABEL: zext1To64
; MIPS32: andi {{.*}},a0,0x1 ; MIPS32: andi {{.*}},a0,0x1
; MIPS32: li {{.*}},0 ; MIPS32: li {{.*}},0
; MIPS32: add v1,{{.*}} ; MIPS32: move v1,v0
; MIPS32: add v0,{{.*}} ; MIPS32: move v0,a0
define internal void @icmpEq64(i64 %a, i64 %b, i64 %c, i64 %d) { define internal void @icmpEq64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry: entry:
......
...@@ -42,7 +42,7 @@ entry: ...@@ -42,7 +42,7 @@ entry:
; ARM32-LABEL: test_returning32_arg0 ; ARM32-LABEL: test_returning32_arg0
; ARM32-NEXT: bx lr ; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg0 ; MIPS32-LABEL: test_returning32_arg0
; MIPS32: add v0,zero,a0 ; MIPS32: move v0,a0
; MIPS32-NEXT: jr ra ; 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) { 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: ...@@ -56,7 +56,7 @@ entry:
; ARM32-NEXT: mov r0, r1 ; ARM32-NEXT: mov r0, r1
; ARM32-NEXT: bx lr ; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg1 ; MIPS32-LABEL: test_returning32_arg1
; MIPS32: add v0,zero,a1 ; MIPS32: move v0,a1
; MIPS32-NEXT: jr ra ; 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) { 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: ...@@ -70,7 +70,7 @@ entry:
; ARM32-NEXT: mov r0, r2 ; ARM32-NEXT: mov r0, r2
; ARM32-NEXT: bx lr ; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning32_arg2 ; MIPS32-LABEL: test_returning32_arg2
; MIPS32: add v0,zero,a2 ; MIPS32: move v0,a2
; MIPS32-NEXT: jr ra ; MIPS32-NEXT: jr ra
...@@ -122,8 +122,8 @@ entry: ...@@ -122,8 +122,8 @@ entry:
; ARM32-LABEL: test_returning64_arg0 ; ARM32-LABEL: test_returning64_arg0
; ARM32-NEXT: bx lr ; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning64_arg0 ; MIPS32-LABEL: test_returning64_arg0
; MIPS32-NEXT: add v0,zero,a0 ; MIPS32-NEXT: move v0,a0
; MIPS32-NEXT: add v1,zero,a1 ; MIPS32-NEXT: move v1,a1
define internal i64 @test_returning64_arg1(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) { define internal i64 @test_returning64_arg1(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) {
...@@ -139,8 +139,8 @@ entry: ...@@ -139,8 +139,8 @@ entry:
; ARM32-NEXT: mov r1, r3 ; ARM32-NEXT: mov r1, r3
; ARM32-NEXT: bx lr ; ARM32-NEXT: bx lr
; MIPS32-LABEL: test_returning64_arg1 ; MIPS32-LABEL: test_returning64_arg1
; MIPS32-NEXT: add v0,zero,a2 ; MIPS32-NEXT: move v0,a2
; MIPS32-NEXT: add v1,zero,a3 ; MIPS32-NEXT: move v1,a3
define internal i64 @test_returning64_arg2(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) { define internal i64 @test_returning64_arg2(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3) {
entry: 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