| Index: src/IceAssemblerMIPS32.cpp
|
| diff --git a/src/IceAssemblerMIPS32.cpp b/src/IceAssemblerMIPS32.cpp
|
| index ce690426746ffa73d892fcaeee110cc25ed91476..ca8a6311abfbc52481ffab84f82d8444ac8b1885 100644
|
| --- a/src/IceAssemblerMIPS32.cpp
|
| +++ b/src/IceAssemblerMIPS32.cpp
|
| @@ -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,
|
|
|