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
......@@ -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