Chromium Code Reviews| Index: src/IceAssemblerMIPS32.cpp |
| diff --git a/src/IceAssemblerMIPS32.cpp b/src/IceAssemblerMIPS32.cpp |
| index ce690426746ffa73d892fcaeee110cc25ed91476..2cf610ab6c498fd5a53598d536cf42c2beafd94b 100644 |
| --- a/src/IceAssemblerMIPS32.cpp |
| +++ b/src/IceAssemblerMIPS32.cpp |
| @@ -225,6 +225,32 @@ 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 { |
|
Jim Stichnoth
2016/10/27 13:58:15
else if ( ... ) ...
I think that pattern is easie
jaydeep.patil
2016/10/28 02:53:57
Done.
|
| + 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 +373,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 +397,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 +580,109 @@ 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(); |
| + if (Reloc == RelocOp::RO_Hi) { |
|
Jim Stichnoth
2016/10/27 13:58:15
Would it be better to use a switch on Reloc here?
jaydeep.patil
2016/10/28 02:53:56
Done.
|
| + Fixup->set_kind(llvm::ELF::R_MIPS_HI16); |
| + } else if (Reloc == RelocOp::RO_Lo) { |
| + Fixup->set_kind(llvm::ELF::R_MIPS_LO16); |
| + } else if (Reloc == RelocOp::RO_Jal) { |
| + Fixup->set_kind(llvm::ELF::R_MIPS_26); |
| + } else { |
| + llvm::report_fatal_error("Fixup: Invalid Reloc type"); |
| + } |
| + 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 +719,29 @@ 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 +779,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 +917,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 +1039,29 @@ 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 +1095,29 @@ 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 +1141,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, |