Commit 130aca71 by Jaydeep Patil Committed by Jim Stichnoth

[SubZero] Generate relocations for MIPS

The patch generate Hi, Lo, Jal and data relocations. Instruction encoding of instructions like ldc1, sdc1 etc. has been added. Following tests from cross-test framework were tested successfully: (non-vector, OBJ mode, Om1, O2) mem_intrin TotalTests=114300 Passes=114300 Failures=0 simple_loop TotalTests=102 Passes=102 Failures=0 test_arith TotalTests=49489704 Passes=49489704 Failures=0 test_bitmanip TotalTests=1200 Passes=1200 Failures=0 test_cast TotalTests=7444 Passes=7444 Failures=0 test_fcmp TotalTests=123904 Passes=123904 Failures=0 test_global TotalTests=270 Passes=270 Failures=0 test_icmp TotalTests=3341520 Passes=3341520 Failures=0 test_strengthreduce TotalTests=240 Passes=240 Failures=0 Following tests are disabled as they are either all-vectors or contain unimplemented intrinsic lowering: test_calling_conv test_select test_stacksave test_sync_atomic test_vector_ops R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2446273003 . Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
parent 0dabe18f
......@@ -225,6 +225,30 @@ void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
emitInst(Opcode);
}
void AssemblerMIPS32::emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
const Operand *OpRs,
const Operand *OpImm,
const RelocOp Reloc,
const char *InsnName) {
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
uint32_t Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error(std::string(InsnName) + ": Invalid 3rd operand");
}
Opcode |= Rs << 21;
Opcode |= Rt << 16;
Opcode |= Imm16 & 0xffff;
emitInst(Opcode);
}
void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt,
const Operand *OpRs, const uint32_t Imm,
const char *InsnName) {
......@@ -347,6 +371,12 @@ void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) {
emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s");
}
void AssemblerMIPS32::addi(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x20000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addi");
}
void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000000;
......@@ -365,6 +395,12 @@ void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
}
void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
const Operand *OpImm, const RelocOp Reloc) {
static constexpr IValueT Opcode = 0x24000000;
emitRtRsImm16Rel(Opcode, OpRt, OpRs, OpImm, Reloc, "addiu");
}
void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000021;
......@@ -542,11 +578,110 @@ void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) {
emitRsRt(Opcode, OpRs, OpRt, "divu");
}
void AssemblerMIPS32::lui(const Operand *OpRt, const uint16_t Imm) {
MIPS32Fixup *AssemblerMIPS32::createMIPS32Fixup(const RelocOp Reloc,
const Constant *RelOp) {
MIPS32Fixup *Fixup = new (allocate<MIPS32Fixup>()) MIPS32Fixup();
switch (Reloc) {
case RelocOp::RO_Hi:
Fixup->set_kind(llvm::ELF::R_MIPS_HI16);
break;
case RelocOp::RO_Lo:
Fixup->set_kind(llvm::ELF::R_MIPS_LO16);
break;
case RelocOp::RO_Jal:
Fixup->set_kind(llvm::ELF::R_MIPS_26);
break;
default:
llvm::report_fatal_error("Fixup: Invalid Reloc type");
break;
}
Fixup->set_value(RelOp);
Buffer.installFixup(Fixup);
return Fixup;
}
size_t MIPS32Fixup::emit(GlobalContext *Ctx, const Assembler &Asm) const {
if (!BuildDefs::dump())
return InstMIPS32::InstSize;
Ostream &Str = Ctx->getStrEmit();
IValueT Inst = Asm.load<IValueT>(position());
const auto Symbol = symbol().toString();
Str << "\t"
<< ".word " << llvm::format_hex(Inst, 8) << " # ";
switch (kind()) {
case llvm::ELF::R_MIPS_HI16:
Str << "R_MIPS_HI16 ";
break;
case llvm::ELF::R_MIPS_LO16:
Str << "R_MIPS_LO16 ";
break;
case llvm::ELF::R_MIPS_26:
Str << "R_MIPS_26 ";
break;
default:
Str << "Unknown ";
break;
}
Str << Symbol << "\n";
return InstMIPS32::InstSize;
}
void MIPS32Fixup::emitOffset(Assembler *Asm) const {
const IValueT Inst = Asm->load<IValueT>(position());
IValueT ImmMask = 0;
const IValueT Imm = offset();
if (kind() == llvm::ELF::R_MIPS_26) {
ImmMask = 0x03FFFFFF;
} else {
ImmMask = 0x0000FFFF;
}
Asm->store(position(), (Inst & ~ImmMask) | (Imm & ImmMask));
}
void AssemblerMIPS32::jal(const ConstantRelocatable *Target) {
IValueT Opcode = 0x0C000000;
emitFixup(createMIPS32Fixup(RelocOp::RO_Jal, Target));
emitInst(Opcode);
nop();
}
void AssemblerMIPS32::lui(const Operand *OpRt, const Operand *OpImm,
const RelocOp Reloc) {
IValueT Opcode = 0x3C000000;
const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui");
IValueT Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error("lui: Invalid 2nd operand");
}
Opcode |= Rt << 16;
Opcode |= Imm16;
emitInst(Opcode);
}
void AssemblerMIPS32::ldc1(const Operand *OpRt, const Operand *OpBase,
const Operand *OpOff, const RelocOp Reloc) {
IValueT Opcode = 0xD4000000;
const IValueT Rt = encodeFPRegister(OpRt, "Ft", "ldc1");
const IValueT Base = encodeGPRegister(OpBase, "Base", "ldc1");
IValueT Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error("ldc1: Invalid 2nd operand");
}
Opcode |= Base << 21;
Opcode |= Rt << 16;
Opcode |= Imm;
Opcode |= Imm16;
emitInst(Opcode);
}
......@@ -583,6 +718,27 @@ void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
}
}
void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase,
const Operand *OpOff, const RelocOp Reloc) {
IValueT Opcode = 0xC4000000;
const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1");
const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1");
IValueT Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error("lwc1: Invalid 2nd operand");
}
Opcode |= Base << 21;
Opcode |= Rt << 16;
Opcode |= Imm16;
emitInst(Opcode);
}
void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000000;
emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
......@@ -620,7 +776,7 @@ void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
(isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
if (isScalarFloatingType(DstType)) {
mtc1(OpRd, OpRs);
mtc1(OpRs, OpRd);
} else {
mfc1(OpRd, OpRs);
}
......@@ -758,6 +914,11 @@ void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
}
void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000018;
emitRsRt(Opcode, OpRs, OpRt, "mult");
}
void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) {
static constexpr IValueT Opcode = 0x00000019;
emitRsRt(Opcode, OpRs, OpRt, "multu");
......@@ -875,6 +1036,27 @@ void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs,
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu");
}
void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase,
const Operand *OpOff, const RelocOp Reloc) {
IValueT Opcode = 0xF4000000;
const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1");
const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1");
IValueT Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error("sdc1: Invalid 2nd operand");
}
Opcode |= Base << 21;
Opcode |= Rt << 16;
Opcode |= Imm16;
emitInst(Opcode);
}
void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) {
switch (OpRt->getType()) {
......@@ -908,6 +1090,27 @@ void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
}
}
void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase,
const Operand *OpOff, const RelocOp Reloc) {
IValueT Opcode = 0xE4000000;
const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1");
const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1");
IValueT Imm16 = 0;
if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
emitFixup(createMIPS32Fixup(Reloc, OpRel));
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
Imm16 = C32->getValue();
} else {
llvm::report_fatal_error("swc1: Invalid 2nd operand");
}
Opcode |= Base << 21;
Opcode |= Rt << 16;
Opcode |= Imm16;
emitInst(Opcode);
}
void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt,
const uint32_t TrapCode) {
IValueT Opcode = 0x00000034;
......@@ -931,12 +1134,12 @@ void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x4400000D;
emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.d");
emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d");
}
void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x4400000D;
emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.s");
emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s");
}
void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
......
......@@ -34,6 +34,16 @@ enum FPInstDataFormat {
Long = 21
};
class MIPS32Fixup final : public AssemblerFixup {
MIPS32Fixup &operator=(const MIPS32Fixup &) = delete;
MIPS32Fixup(const MIPS32Fixup &) = default;
public:
MIPS32Fixup() = default;
size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
void emitOffset(Assembler *Asm) const;
};
class AssemblerMIPS32 : public Assembler {
AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
......@@ -56,6 +66,8 @@ public:
}
}
MIPS32Fixup *createMIPS32Fixup(const RelocOp Reloc, const Constant *RelOp);
void trap();
void nop();
......@@ -66,6 +78,10 @@ public:
void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
uint32_t Imm, const char *InsnName);
void emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
const Operand *OpRs, const Operand *OpImm,
const RelocOp Reloc, const char *InsnName);
void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
uint32_t Imm, const char *InsnName);
......@@ -101,6 +117,8 @@ public:
void abs_s(const Operand *OpFd, const Operand *OpFs);
void addi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void add_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void add_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
......@@ -109,6 +127,9 @@ public:
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void addiu(const Operand *OpRt, const Operand *OpRs, const Operand *OpImm,
const RelocOp Reloc);
void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
......@@ -165,10 +186,18 @@ public:
void divu(const Operand *OpRs, const Operand *OpRt);
void lui(const Operand *OpRt, const uint16_t Imm);
void jal(const ConstantRelocatable *Target);
void lui(const Operand *OpRt, const Operand *OpImm, const RelocOp Reloc);
void ldc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
const RelocOp Reloc);
void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void lwc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
const RelocOp Reloc);
void mfc1(const Operand *OpRt, const Operand *OpFs);
void mfhi(const Operand *OpRd);
......@@ -209,6 +238,8 @@ public:
void mul_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void mult(const Operand *OpRs, const Operand *OpRt);
void multu(const Operand *OpRs, const Operand *OpRt);
void nor(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
......@@ -249,8 +280,14 @@ public:
void subu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void sdc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
const RelocOp Reloc);
void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void swc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
const RelocOp Reloc);
void teq(const Operand *OpRs, const Operand *OpRt, const uint32_t TrapCode);
void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
......@@ -319,7 +356,7 @@ public:
bool fixupIsPCRel(FixupKind Kind) const override {
(void)Kind;
llvm::report_fatal_error("Not yet implemented.");
return false;
}
static bool classof(const Assembler *Asm) {
......
......@@ -62,6 +62,7 @@ const char *InstMIPS32::getWidthString(Type Ty) {
template <> const char *InstMIPS32Abs_d::Opcode = "abs.d";
template <> const char *InstMIPS32Abs_s::Opcode = "abs.s";
template <> const char *InstMIPS32Addi::Opcode = "addi";
template <> const char *InstMIPS32Add::Opcode = "add";
template <> const char *InstMIPS32Add_d::Opcode = "add.d";
template <> const char *InstMIPS32Add_s::Opcode = "add.s";
......@@ -543,7 +544,7 @@ void InstMIPS32Call::emit(const Cfg *Func) const {
llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
} else if (const auto *CallTarget =
llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
// Calls only have 24-bits, but the linker should insert veneers to extend
// Calls only have 26-bits, but the linker should insert veneers to extend
// the range if needed.
Str << "\t"
"jal"
......@@ -558,8 +559,14 @@ void InstMIPS32Call::emit(const Cfg *Func) const {
}
void InstMIPS32Call::emitIAS(const Cfg *Func) const {
(void)Func;
llvm_unreachable("Not yet implemented");
assert(getSrcSize() == 1);
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
if (const auto *CallTarget =
llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
Asm->jal(CallTarget);
} else {
llvm::report_fatal_error("MIPS32Call: Invalid operand");
}
}
void InstMIPS32Call::dump(const Cfg *Func) const {
......@@ -656,7 +663,6 @@ void InstMIPS32Mov::emit(const Cfg *Func) const {
llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
}
// TODO(jaydeep.patil) Handle all types of operands in mov
void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
Variable *Dest = getDest();
Operand *Src = getSrc(0);
......@@ -671,7 +677,8 @@ void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
Asm->move(getDest(), getSrc(0));
return;
}
llvm_unreachable("Not yet implemented");
llvm::report_fatal_error("InstMIPS32Mov invalid operands");
}
void InstMIPS32Mov::dump(const Cfg *Func) const {
......@@ -701,6 +708,11 @@ template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
Asm->abs_s(getDest(), getSrc(0));
}
template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addi(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->add_d(getDest(), getSrc(0), getSrc(1));
......@@ -713,7 +725,11 @@ template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addiu(getDest(), getSrc(0), Imm);
if (Reloc == RO_No) {
Asm->addiu(getDest(), getSrc(0), Imm);
} else {
Asm->addiu(getDest(), getSrc(0), getSrc(1), Reloc);
}
}
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
......@@ -838,7 +854,7 @@ template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->div(getDest(), getSrc(0));
Asm->div(getSrc(0), getSrc(1));
}
template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
......@@ -853,14 +869,18 @@ template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->divu(getDest(), getSrc(0));
Asm->divu(getSrc(0), getSrc(1));
}
template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *C32 = llvm::dyn_cast<ConstantInteger32>(getSrc(0));
uint16_t Imm = static_cast<uint16_t>(C32->getValue());
Asm->lui(getDest(), Imm);
Asm->lui(getDest(), getSrc(0), Reloc);
}
template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
Asm->ldc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
}
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
......@@ -871,6 +891,12 @@ template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
Asm->lw(getDest(), Mem->getBase(), Imm);
}
template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
Asm->lwc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
}
template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mfc1(getDest(), getSrc(0));
......@@ -961,7 +987,7 @@ template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const {
template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mtc1(getDest(), getSrc(0));
Asm->mtc1(getSrc(0), getDest());
}
template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
......@@ -1007,6 +1033,11 @@ template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
emitThreeAddrLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mult::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mult(getDest(), getSrc(0));
}
template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
......@@ -1015,7 +1046,7 @@ template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->multu(getDest(), getSrc(0));
Asm->multu(getSrc(0), getSrc(1));
}
template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
......@@ -1108,6 +1139,12 @@ template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const {
Asm->subu(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
Asm->sdc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
}
template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
......@@ -1116,6 +1153,12 @@ template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
Asm->sw(getSrc(0), Mem->getBase(), Imm);
}
template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
Asm->swc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
}
template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->teq(getSrc(0), getSrc(1), getTrapCode());
......
......@@ -28,11 +28,11 @@
namespace Ice {
namespace MIPS32 {
enum RelocOp { RO_No, RO_Hi, RO_Lo };
enum RelocOp { RO_No, RO_Hi, RO_Lo, RO_Jal };
inline void emitRelocOp(Ostream &Str, RelocOp Reloc) {
switch (Reloc) {
case RO_No:
default:
break;
case RO_Hi:
Str << "%hi";
......@@ -189,6 +189,7 @@ public:
Add,
Add_d,
Add_s,
Addi,
Addiu,
Addu,
And,
......@@ -1143,6 +1144,7 @@ using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>;
using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>;
using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
using InstMIPS32Addi = InstMIPS32Imm16<InstMIPS32::Addi, true>;
using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
......@@ -1270,6 +1272,7 @@ template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
......@@ -1299,9 +1302,11 @@ template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const;
......
......@@ -1654,9 +1654,7 @@ Variable *TargetMIPS32::PostLoweringLegalizer::newBaseRegister(
const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0;
Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum);
if (ShouldSub) {
Variable *OffsetVal = Target->legalizeToReg(
Target->Ctx->getConstantInt32(-Offset), ScratchRegNum);
Target->_sub(ScratchReg, Base, OffsetVal);
Target->_addi(ScratchReg, Base, -Offset);
} else {
constexpr bool SignExt = true;
if (!OperandMIPS32Mem::canHoldOffset(Base->getType(), SignExt, Offset)) {
......@@ -4973,8 +4971,7 @@ void TargetDataMIPS32::lowerGlobals(const VariableDeclarationList &Vars,
switch (getFlags().getOutFileType()) {
case FT_Elf: {
ELFObjectWriter *Writer = Ctx->getObjectWriter();
Writer->writeDataSection(Vars, llvm::ELF::R_MIPS_GLOB_DAT, SectionSuffix,
IsPIC);
Writer->writeDataSection(Vars, llvm::ELF::R_MIPS_32, SectionSuffix, IsPIC);
} break;
case FT_Asm:
case FT_Iasm: {
......
......@@ -205,6 +205,10 @@ public:
Context.insert<InstMIPS32Abs_s>(Dest, Src);
}
void _addi(Variable *Dest, Variable *Src, uint32_t Imm) {
Context.insert<InstMIPS32Addi>(Dest, Src, Imm);
}
void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
}
......
......@@ -29,7 +29,7 @@
X(Target_X8664, "x86-64", true, EM_X86_64, 0) \
X(Target_ARM32, "arm32", false, EM_ARM, EF_ARM_EABI_VER5) \
X(Target_ARM64, "arm64", true, EM_AARCH64, 0) \
X(Target_MIPS32,"mips32", false, EM_MIPS, 0) \
X(Target_MIPS32,"mips32", false, EM_MIPS, EF_MIPS_ABI_O32|EF_MIPS_ARCH_32)\
//#define X(tag, str, is_elf64, e_machine, e_flags)
#define ICETYPE_TABLE \
......
......@@ -470,3 +470,53 @@ entry:
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
define internal i64 @cast_d2ll_const() {
entry:
%v0 = bitcast double 0x12345678901234 to i64
ret i64 %v0
}
; ASM-LABEL: cast_d2ll_const
; ASM-LABEL: .Lcast_d2ll_const$entry:
; ASM-NEXT: lui $[[REG:.*]], %hi({{.*}})
; ASM-NEXT: ldc1 $[[FREG:.*]], %lo({{.*}})($[[REG]])
; DIS-LABEL: 000000c0 <cast_d2ll_const>:
; DIS-NEXT: c0: 3c020000 lui v0,0x0
; DIS-NEXT: c4: d4400000 ldc1 $f0,0(v0)
; IASM-LABEL: cast_d2ll_const:
; IASM-LABEL: .Lcast_d2ll_const$entry:
; IASM-NEXT: .word 0x3c020000 # R_MIPS_HI16 [[LAB:.*]]
; IASM-NEXT: .word 0xd4400000 # R_MIPS_LO16 [[LAB]]
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x44
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x44
; 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
declare void @bar(i32 %a1, i32 %a2)
define internal void @Call() {
call void @bar(i32 1, i32 2)
ret void
}
; ASM-LABEL: Call
; ASM: jal bar
; DIS-LABEL: 000000e0 <Call>:
; DIS: f0: 0c000000 jal 0
; IASM-LABEL: Call:
; IASM: .word 0xc000000 # R_MIPS_26 bar
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