Commit 132ea7a5 by Srdjan Obucina Committed by Jim Stichnoth

Subzero, MIPS32: Floating point support in ELF output

Patch implements improvements and instruction encodings for many COP1 instructions for handling floating point values. Patch covers load, store, basic arithmetic, data movement for FPR<->FPR, GPR<->FPR, FPR<->GPR, and format conversion instructinos. Added instruction encodings: Load: lb, lh, lwc1, ldc1 Store: sb, sh, swc1, sdc1 FP arith: abs_d, abs_s, add_d, add_s, div_d, div_s, mul_d, mul_s, sqrt_d, sqrt_s, sub_d, sub_s FP movs: mfc1, mov_d, mov_s, movn_d, movn_s, movz_d, movz_s, mtc1 Conversion: cvt_d_l, cvt_d_s, cvt_d_w, cvt_s_d, cvt_s_l, cvt_s_w, trunc_l_d, trunc_l_s, trunc_w_d, trunc_w_s R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2341713003 . Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
parent 40fc8193
...@@ -102,6 +102,8 @@ void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) { ...@@ -102,6 +102,8 @@ void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
this->bind(L); this->bind(L);
} }
namespace {
// Checks that Offset can fit in imm16 constant of branch instruction. // Checks that Offset can fit in imm16 constant of branch instruction.
void assertCanEncodeBranchOffset(IOffsetT Offset) { void assertCanEncodeBranchOffset(IOffsetT Offset) {
(void)Offset; (void)Offset;
...@@ -118,34 +120,26 @@ IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { ...@@ -118,34 +120,26 @@ IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
return (Inst & ~kBranchOffsetMask) | Offset; 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 }; enum RegSetWanted { WantGPRegs, WantFPRegs };
IValueT getEncodedGPRegNum(const Variable *Var) { IValueT getEncodedGPRegNum(const Variable *Var) {
assert(Var->hasReg()); assert(Var->hasReg() && isScalarIntegerType(Var->getType()));
const auto Reg = Var->getRegNum(); const auto Reg = Var->getRegNum();
return RegMIPS32::getEncodedGPR(Reg); return RegMIPS32::getEncodedGPR(Reg);
} }
IValueT getEncodedFPRegNum(const Variable *Var) {
assert(Var->hasReg() && isScalarFloatingType(Var->getType()));
const auto Reg = Var->getRegNum();
IValueT RegEncoding;
if (RegMIPS32::isFPRReg(Reg)) {
RegEncoding = RegMIPS32::getEncodedFPR(Reg);
} else {
RegEncoding = RegMIPS32::getEncodedFPR64(Reg);
}
return RegEncoding;
}
bool encodeOperand(const Operand *Opnd, IValueT &Value, bool encodeOperand(const Operand *Opnd, IValueT &Value,
RegSetWanted WantedRegSet) { RegSetWanted WantedRegSet) {
Value = 0; Value = 0;
...@@ -155,7 +149,8 @@ bool encodeOperand(const Operand *Opnd, IValueT &Value, ...@@ -155,7 +149,8 @@ bool encodeOperand(const Operand *Opnd, IValueT &Value,
case WantGPRegs: case WantGPRegs:
Value = getEncodedGPRegNum(Var); Value = getEncodedGPRegNum(Var);
break; break;
default: case WantFPRegs:
Value = getEncodedFPRegNum(Var);
break; break;
} }
return true; return true;
...@@ -179,6 +174,33 @@ IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, ...@@ -179,6 +174,33 @@ IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
return encodeRegister(OpReg, WantGPRegs, RegName, InstName); return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
} }
IValueT encodeFPRegister(const Operand *OpReg, const char *RegName,
const char *InstName) {
return encodeRegister(OpReg, WantFPRegs, RegName, InstName);
}
} // end of anonymous namespace
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);
}
void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
const Operand *OpRs, const uint32_t Imm, const Operand *OpRs, const uint32_t Imm,
const char *InsnName) { const char *InsnName) {
...@@ -192,6 +214,19 @@ void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, ...@@ -192,6 +214,19 @@ void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
emitInst(Opcode); emitInst(Opcode);
} }
void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt,
const Operand *OpRs, const uint32_t Imm,
const char *InsnName) {
const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
Opcode |= Rs << 21;
Opcode |= Ft << 16;
Opcode |= Imm & 0xffff;
emitInst(Opcode);
}
void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd,
const Operand *OpRt, const uint32_t Sa, const Operand *OpRt, const uint32_t Sa,
const char *InsnName) { const char *InsnName) {
...@@ -219,22 +254,96 @@ void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, ...@@ -219,22 +254,96 @@ void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
emitInst(Opcode); emitInst(Opcode);
} }
void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const char *InsnName) {
const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
Opcode |= Fd << 6;
Opcode |= Fs << 11;
Opcode |= Format << 21;
emitInst(Opcode);
}
void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd,
const Operand *OpFs,
const Operand *OpFt,
const char *InsnName) {
const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
Opcode |= Fd << 6;
Opcode |= Fs << 11;
Opcode |= Ft << 16;
Opcode |= Format << 21;
emitInst(Opcode);
}
void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd,
const Operand *OpFs,
const Operand *OpRt,
const char *InsnName) {
const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
Opcode |= Fd << 6;
Opcode |= Fs << 11;
Opcode |= Rt << 16;
Opcode |= Format << 21;
emitInst(Opcode);
}
void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt,
const Operand *OpFs,
const char *InsnName) {
const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
Opcode |= Fs << 11;
Opcode |= Rt << 16;
emitInst(Opcode);
}
void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000005;
emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d");
}
void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000005;
emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s");
}
void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000000;
emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d");
}
void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000000;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s");
}
void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) { const uint32_t Imm) {
static constexpr IValueT Opcode = 0x24000000; static constexpr IValueT Opcode = 0x24000000;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
} }
void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
const uint32_t Imm) { const Operand *OpRt) {
static constexpr IValueT Opcode = 0x28000000; static constexpr IValueT Opcode = 0x00000021;
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
}
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, void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
...@@ -249,49 +358,130 @@ void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs, ...@@ -249,49 +358,130 @@ void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi"); emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
} }
void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs, void AssemblerMIPS32::b(Label *TargetLabel) {
const Operand *OpRt) { static constexpr Operand *OpRsNone = nullptr;
static constexpr IValueT Opcode = 0x00000025; static constexpr Operand *OpRtNone = nullptr;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or"); 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::ori(const Operand *OpRt, const Operand *OpRs, void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Imm) { static constexpr IValueT Opcode = 0x44000021;
static constexpr IValueT Opcode = 0x34000000; emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l");
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
} }
void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) {
const Operand *OpRt) { static constexpr IValueT Opcode = 0x44000021;
static constexpr IValueT Opcode = 0x00000026; emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s");
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
} }
void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Imm) { static constexpr IValueT Opcode = 0x44000021;
static constexpr IValueT Opcode = 0x38000000; emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w");
emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
} }
void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt, void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Sa) { static constexpr IValueT Opcode = 0x44000020;
static constexpr IValueT Opcode = 0x00000000; emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d");
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
} }
void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt, void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Sa) { static constexpr IValueT Opcode = 0x44000020;
static constexpr IValueT Opcode = 0x00000002; emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l");
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
} }
void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Sa) { static constexpr IValueT Opcode = 0x44000020;
static constexpr IValueT Opcode = 0x00000003; emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w");
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); }
void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000003;
emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d");
}
void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000003;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s");
}
void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) {
switch (OpRt->getType()) {
case IceType_i1:
case IceType_i8: {
static constexpr IValueT Opcode = 0x80000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb");
}
case IceType_i16: {
static constexpr IValueT Opcode = 0x84000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh");
}
case IceType_i32: {
static constexpr IValueT Opcode = 0x8C000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
break;
}
case IceType_f32: {
static constexpr IValueT Opcode = 0xC4000000;
emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1");
}
case IceType_f64: {
static constexpr IValueT Opcode = 0xD4000000;
emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1");
break;
}
default: { UnimplementedError(getFlags()); }
}
}
void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000000;
emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
}
void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000006;
emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d");
}
void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000006;
emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s");
} }
void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
const Type DstType = OpRd->getType();
const Type SrcType = OpRs->getType();
if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
(isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
if (isScalarFloatingType(DstType)) {
mtc1(OpRd, OpRs);
} else {
mfc1(OpRd, OpRs);
}
} else {
switch (DstType) {
case IceType_f32:
mov_s(OpRd, OpRs);
break;
case IceType_f64:
mov_d(OpRd, OpRs);
break;
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32: {
IValueT Opcode = 0x00000021; IValueT Opcode = 0x00000021;
const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
...@@ -300,18 +490,76 @@ void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { ...@@ -300,18 +490,76 @@ void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
Opcode |= Rt << 16; Opcode |= Rt << 16;
Opcode |= Rd << 11; Opcode |= Rd << 11;
emitInst(Opcode); emitInst(Opcode);
break;
}
default: { UnimplementedError(getFlags()); }
}
}
} }
void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpRt) { const Operand *OpFt) {
static constexpr IValueT Opcode = 0x00000021; static constexpr IValueT Opcode = 0x44000013;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.d");
} }
void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000013;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s");
}
void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000012;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.d");
}
void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000012;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s");
}
void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44800000;
emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
}
void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000002;
emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d");
}
void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000002;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
}
void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) { const Operand *OpRt) {
static constexpr IValueT Opcode = 0x0000002B; static constexpr IValueT Opcode = 0x00000025;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); 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::ret(void) {
static constexpr IValueT Opcode = 0x03E00008; // JR $31
emitInst(Opcode);
nop(); // delay slot
}
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::slt(const Operand *OpRd, const Operand *OpRs, void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
...@@ -320,22 +568,121 @@ void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, ...@@ -320,22 +568,121 @@ void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
} }
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::sltu(const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt) {
static constexpr IValueT Opcode = 0x0000002B;
emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
}
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::sqrt_d(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000004;
emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d");
}
void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x44000004;
emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s");
}
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::srl(const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa) {
static constexpr IValueT Opcode = 0x00000002;
emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
}
void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000001;
emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d");
}
void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt) {
static constexpr IValueT Opcode = 0x44000001;
emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s");
}
void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) { const uint32_t Offset) {
switch (OpRt->getType()) {
case IceType_i1:
case IceType_i8: {
static constexpr IValueT Opcode = 0xA0000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb");
break;
}
case IceType_i16: {
static constexpr IValueT Opcode = 0xA4000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh");
break;
}
case IceType_i32: {
static constexpr IValueT Opcode = 0xAC000000; static constexpr IValueT Opcode = 0xAC000000;
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
break;
}
case IceType_f32: {
static constexpr IValueT Opcode = 0xE4000000;
emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1");
break;
}
case IceType_f64: {
static constexpr IValueT Opcode = 0xF4000000;
emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1");
break;
}
default: { UnimplementedError(getFlags()); }
}
} }
void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
const uint32_t Offset) { static constexpr IValueT Opcode = 0x4400000D;
static constexpr IValueT Opcode = 0x8C000000; emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
} }
void AssemblerMIPS32::ret(void) { void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x03E00008; // JR $31 static constexpr IValueT Opcode = 0x4400000D;
emitInst(Opcode); emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s");
nop(); // delay slot }
void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
static constexpr IValueT Opcode = 0x4400000D;
emitCOP1FmtFsFd(Opcode, Word, 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");
}
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::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
...@@ -387,19 +734,6 @@ void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, ...@@ -387,19 +734,6 @@ void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
nop(); // delay slot 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, void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, Label *TargetLabel) { const Operand *OpRt, Label *TargetLabel) {
if (TargetLabel->isBound()) { if (TargetLabel->isBound()) {
......
...@@ -27,6 +27,13 @@ namespace MIPS32 { ...@@ -27,6 +27,13 @@ namespace MIPS32 {
using IValueT = uint32_t; using IValueT = uint32_t;
using IOffsetT = int32_t; using IOffsetT = int32_t;
enum FPInstDataFormat {
SinglePrecision = 16,
DoublePrecision = 17,
Word = 20,
Long = 21
};
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;
...@@ -54,56 +61,134 @@ public: ...@@ -54,56 +61,134 @@ public:
void nop(); void nop();
void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs, void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm, const char *InsnName); uint32_t Imm, const char *InsnName);
void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
uint32_t Imm, const char *InsnName);
void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt, void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
const uint32_t Sa, const char *InsnName); uint32_t Sa, const char *InsnName);
void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs, void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
const Operand *OpRt, const char *InsnName); const Operand *OpRt, const char *InsnName);
void emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const char *InsnName);
void emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const Operand *OpFt, const char *InsnName);
void emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
const Operand *OpFd, const Operand *OpFs,
const Operand *OpRt, const char *InsnName);
void emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, const Operand *OpFs,
const char *InsnName);
void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, IOffsetT Offset); const Operand *OpRt, IOffsetT Offset);
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void abs_d(const Operand *OpFd, const Operand *OpFs);
void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void abs_s(const Operand *OpFd, const Operand *OpFs);
void sltiu(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);
void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void b(Label *TargetLabel);
void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void cvt_d_l(const Operand *OpFd, const Operand *OpFs);
void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void cvt_d_s(const Operand *OpFd, const Operand *OpFs);
void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); void cvt_d_w(const Operand *OpFd, const Operand *OpFs);
void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_d(const Operand *OpFd, const Operand *OpFs);
void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_l(const Operand *OpFd, const Operand *OpFs);
void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); void cvt_s_w(const Operand *OpFd, const Operand *OpFs);
void div_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void div_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
void mfc1(const Operand *OpRt, const Operand *OpFs);
void mov_d(const Operand *OpFd, const Operand *OpFs);
void mov_s(const Operand *OpFd, const Operand *OpFs);
void move(const Operand *OpRd, const Operand *OpRs); void move(const Operand *OpRd, const Operand *OpRs);
void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void movn_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movn_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movz_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void movz_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void mtc1(const Operand *OpRt, const Operand *OpFs);
void mul_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void mul_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void ret(void);
void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
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 sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void sqrt_d(const Operand *OpFd, const Operand *OpFs);
void sqrt_s(const Operand *OpFd, const Operand *OpFs);
void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
void sub_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void sub_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset); 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 trunc_l_d(const Operand *OpFd, const Operand *OpFs);
void ret(void); void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
void b(Label *TargetLabel); void trunc_w_d(const Operand *OpFd, const Operand *OpFs);
void trunc_w_s(const Operand *OpFd, const Operand *OpFs);
void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs, void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
const Operand *OpRt, Label *TargetLabel); const Operand *OpRt, Label *TargetLabel);
......
...@@ -166,42 +166,6 @@ template <> void InstMIPS32Lui::emit(const Cfg *Func) const { ...@@ -166,42 +166,6 @@ template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
} }
} }
template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRFLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRFLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRTLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRTLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitThreeAddrLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitThreeAddrLoHi(Opcode, this, Func);
}
InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
const CfgNode *TargetFalse, const CfgNode *TargetFalse,
const InstMIPS32Label *Label, CondMIPS32::Cond Cond) const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
...@@ -648,18 +612,10 @@ void InstMIPS32Mov::emitIAS(const Cfg *Func) const { ...@@ -648,18 +612,10 @@ void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
// reg to reg // reg to reg
if (DestIsReg && SrcIsReg) { 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>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->move(getDest(), getSrc(0)); Asm->move(getDest(), getSrc(0));
return; return;
} }
}
llvm_unreachable("Not yet implemented"); llvm_unreachable("Not yet implemented");
} }
...@@ -786,19 +742,34 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -786,19 +742,34 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory."); llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
} }
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addiu(getDest(), getSrc(0), Imm); Asm->abs_d(getDest(), getSrc(0));
} }
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->slti(getDest(), getSrc(0), Imm); Asm->abs_s(getDest(), getSrc(0));
} }
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sltiu(getDest(), getSrc(0), Imm); Asm->add_d(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->add_s(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addiu(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 InstMIPS32And::emitIAS(const Cfg *Func) const { template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
...@@ -811,6 +782,140 @@ template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const { ...@@ -811,6 +782,140 @@ template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
Asm->andi(getDest(), getSrc(0), Imm); Asm->andi(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_d_l(getDest(), getSrc(0));
}
template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_d_s(getDest(), getSrc(0));
}
template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_d_w(getDest(), getSrc(0));
}
template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_s_d(getDest(), getSrc(0));
}
template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_s_l(getDest(), getSrc(0));
}
template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->cvt_s_w(getDest(), getSrc(0));
}
template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->div_d(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->div_s(getDest(), getSrc(0), getSrc(1));
}
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);
}
template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mfc1(getDest(), getSrc(0));
}
template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRFLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRFLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mov_d(getDest(), getSrc(0));
}
template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mov_s(getDest(), getSrc(0));
}
template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->movn_d(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->movn_s(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->movz_d(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->movz_s(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mtc1(getDest(), getSrc(0));
}
template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRTLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitUnaryopGPRTLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mul_d(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->mul_s(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitThreeAddrLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
emitThreeAddrLoHi(Opcode, this, Func);
}
template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->or_(getDest(), getSrc(0), getSrc(1)); Asm->or_(getDest(), getSrc(0), getSrc(1));
...@@ -821,24 +926,39 @@ template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const { ...@@ -821,24 +926,39 @@ template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
Asm->ori(getDest(), getSrc(0), Imm); Asm->ori(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->xor_(getDest(), getSrc(0), getSrc(1)); Asm->sll(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->xori(getDest(), getSrc(0), Imm); Asm->slt(getDest(), getSrc(0), getSrc(1));
} }
template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sll(getDest(), getSrc(0), Imm); Asm->slti(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->srl(getDest(), getSrc(0), Imm); Asm->sltiu(getDest(), getSrc(0), Imm);
}
template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sltu(getDest(), getSrc(0), getSrc(1));
}
template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sqrt_d(getDest(), getSrc(0));
}
template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sqrt_s(getDest(), getSrc(0));
} }
template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
...@@ -846,19 +966,19 @@ template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const { ...@@ -846,19 +966,19 @@ template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
Asm->sra(getDest(), getSrc(0), Imm); Asm->sra(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->addu(getDest(), getSrc(0), getSrc(1)); Asm->srl(getDest(), getSrc(0), Imm);
} }
template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->slt(getDest(), getSrc(0), getSrc(1)); Asm->sub_d(getDest(), getSrc(0), getSrc(1));
} }
template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->sltu(getDest(), getSrc(0), getSrc(1)); Asm->sub_s(getDest(), getSrc(0), getSrc(1));
} }
template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
...@@ -869,12 +989,34 @@ template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const { ...@@ -869,12 +989,34 @@ template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
Asm->sw(getSrc(0), Mem->getBase(), Imm); Asm->sw(getSrc(0), Mem->getBase(), Imm);
} }
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0)); Asm->trunc_l_d(getDest(), getSrc(0));
ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset()); }
uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
Asm->lw(getDest(), Mem->getBase(), Imm); template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->trunc_l_s(getDest(), getSrc(0));
}
template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->trunc_w_d(getDest(), getSrc(0));
}
template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->trunc_w_s(getDest(), getSrc(0));
}
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);
} }
} // end of namespace MIPS32 } // end of namespace MIPS32
......
...@@ -1171,31 +1171,60 @@ private: ...@@ -1171,31 +1171,60 @@ private:
// default implementations. Without this, there is the possibility of ODR // default implementations. Without this, there is the possibility of ODR
// violations and link errors. // violations and link errors.
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 InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Cvt_s_w::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 InstMIPS32Lui::emit(const Cfg *Func) const;
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mfc1::emit(const Cfg *Func) const;
template <> void InstMIPS32Mflo::emit(const Cfg *Func) const; template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const; template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const;
template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const;
template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const; template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const;
template <> void InstMIPS32Mthi::emit(const Cfg *Func) const; template <> void InstMIPS32Mthi::emit(const Cfg *Func) const;
template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Mult::emit(const Cfg *Func) const; template <> void InstMIPS32Mult::emit(const Cfg *Func) const;
template <> void InstMIPS32Multu::emit(const Cfg *Func) const; template <> void InstMIPS32Multu::emit(const Cfg *Func) const;
template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const; template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
} // end of namespace MIPS32 } // end of namespace MIPS32
} // end of namespace Ice } // end of namespace Ice
......
...@@ -86,8 +86,19 @@ static inline FPRRegister getEncodedFPR(RegNumT RegNum) { ...@@ -86,8 +86,19 @@ static inline FPRRegister getEncodedFPR(RegNumT RegNum) {
} }
static inline bool isFPRReg(RegNumT RegNum) { static inline bool isFPRReg(RegNumT RegNum) {
return (int(Reg_FPR_First) <= int(RegNum)) && return ((int(Reg_FPR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_FPR_Last); (unsigned(RegNum) <= Reg_FPR_Last));
}
static inline FPRRegister getEncodedFPR64(RegNumT RegNum) {
assert(int(Reg_F64PAIR_First) <= int(RegNum));
assert(unsigned(RegNum) <= Reg_F64PAIR_Last);
return FPRRegister((RegNum - Reg_F64PAIR_First) * 2);
}
static inline bool isFPR64Reg(RegNumT RegNum) {
return (int(Reg_F64PAIR_First) <= int(RegNum)) &&
(unsigned(RegNum) <= Reg_F64PAIR_Last);
} }
const char *getRegName(RegNumT RegNum); const char *getRegName(RegNumT RegNum);
......
; Test encoding of MIPS32 floating point 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
declare float @llvm.fabs.f32(float)
declare double @llvm.fabs.f64(double)
declare float @llvm.sqrt.f32(float)
declare double @llvm.sqrt.f64(double)
define internal float @encAbsFloat(float %a) {
entry:
%c = call float @llvm.fabs.f32(float %a)
ret float %c
}
; ASM-LABEL: encAbsFloat
; ASM-NEXT: .LencAbsFloat$entry:
; ASM-NEXT: abs.s $f12, $f12
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000000 <encAbsFloat>:
; DIS-NEXT: 0: 46006305 abs.s $f12,$f12
; DIS-NEXT: 4: 46006006 mov.s $f0,$f12
; DIS-NEXT: 8: 03e00008 jr ra
; DIS-NEXT: c: 00000000 nop
; IASM-LABEL: encAbsFloat:
; IASM-NEXT: .LencAbsFloat$entry:
; IASM-NEXT: .byte 0x5
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encAbsDouble(double %a) {
entry:
%c = call double @llvm.fabs.f64(double %a)
ret double %c
}
; ASM-LABEL: encAbsDouble:
; ASM-NEXT: .LencAbsDouble$entry:
; ASM-NEXT: abs.d $f12, $f12
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000010 <encAbsDouble>:
; DIS-NEXT: 10: 46206305 abs.d $f12,$f12
; DIS-NEXT: 14: 46206006 mov.d $f0,$f12
; DIS-NEXT: 18: 03e00008 jr ra
; DIS-NEXT: 1c: 00000000 nop
; IASM-LABEL: encAbsDouble:
; IASM-NEXT: .LencAbsDouble$entry:
; IASM-NEXT: .byte 0x5
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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 float @encAddFloat(float %a, float %b) {
entry:
%c = fadd float %a, %b
ret float %c
}
; ASM-LABEL: encAddFloat
; ASM-NEXT: .LencAddFloat$entry:
; ASM-NEXT: add.s $f12, $f12, $f14
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000020 <encAddFloat>:
; DIS-NEXT: 20: 460e6300 add.s $f12,$f12,$f14
; DIS-NEXT: 24: 46006006 mov.s $f0,$f12
; DIS-NEXT: 28: 03e00008 jr ra
; DIS-NEXT: 2c: 00000000 nop
; IASM-LABEL: encAddFloat:
; IASM-NEXT: .LencAddFloat$entry:
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0xe
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encAddDouble(double %a, double %b) {
entry:
%c = fadd double %a, %b
ret double %c
}
; ASM-LABEL: encAddDouble
; ASM-NEXT: .LencAddDouble$entry:
; ASM-NEXT: add.d $f12, $f12, $f14
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000030 <encAddDouble>:
; DIS-NEXT: 30: 462e6300 add.d $f12,$f12,$f14
; DIS-NEXT: 34: 46206006 mov.d $f0,$f12
; DIS-NEXT: 38: 03e00008 jr ra
; DIS-NEXT: 3c: 00000000 nop
; IASM-LABEL: encAddDouble:
; IASM-NEXT: .LencAddDouble$entry:
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x2e
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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 float @encDivFloat(float %a, float %b) {
entry:
%c = fdiv float %a, %b
ret float %c
}
; ASM-LABEL: encDivFloat
; ASM-NEXT: .LencDivFloat$entry:
; ASM-NEXT: div.s $f12, $f12, $f14
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000040 <encDivFloat>:
; DIS-NEXT: 40: 460e6303 div.s $f12,$f12,$f14
; DIS-NEXT: 44: 46006006 mov.s $f0,$f12
; DIS-NEXT: 48: 03e00008 jr ra
; DIS-NEXT: 4c: 00000000 nop
; IASM-LABEL: encDivFloat:
; IASM-NEXT: .LencDivFloat$entry:
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0xe
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encDivDouble(double %a, double %b) {
entry:
%c = fdiv double %a, %b
ret double %c
}
; ASM-LABEL: encDivDouble
; ASM-NEXT: .LencDivDouble$entry:
; ASM-NEXT: div.d $f12, $f12, $f14
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000050 <encDivDouble>:
; DIS-NEXT: 50: 462e6303 div.d $f12,$f12,$f14
; DIS-NEXT: 54: 46206006 mov.d $f0,$f12
; DIS-NEXT: 58: 03e00008 jr ra
; DIS-NEXT: 5c: 00000000 nop
; IASM-LABEL: encDivDouble:
; IASM-NEXT: .LencDivDouble$entry:
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x2e
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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 float @encMulFloat(float %a, float %b) {
entry:
%c = fmul float %a, %b
ret float %c
}
; ASM-LABEL: encMulFloat
; ASM-NEXT: .LencMulFloat$entry:
; ASM-NEXT: mul.s $f12, $f12, $f14
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000060 <encMulFloat>:
; DIS-NEXT: 60: 460e6302 mul.s $f12,$f12,$f14
; DIS-NEXT: 64: 46006006 mov.s $f0,$f12
; DIS-NEXT: 68: 03e00008 jr ra
; DIS-NEXT: 6c: 00000000 nop
; IASM-LABEL: encMulFloat:
; IASM-NEXT: .LencMulFloat$entry:
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0xe
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encMulDouble(double %a, double %b) {
entry:
%c = fmul double %a, %b
ret double %c
}
; ASM-LABEL: encMulDouble
; ASM-NEXT: .LencMulDouble$entry:
; ASM-NEXT: mul.d $f12, $f12, $f14
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000070 <encMulDouble>:
; DIS-NEXT: 70: 462e6302 mul.d $f12,$f12,$f14
; DIS-NEXT: 74: 46206006 mov.d $f0,$f12
; DIS-NEXT: 78: 03e00008 jr ra
; DIS-NEXT: 7c: 00000000 nop
; IASM-LABEL: encMulDouble:
; IASM-NEXT: .LencMulDouble$entry:
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x2e
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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 float @encSqrtFloat(float %a) {
entry:
%c = call float @llvm.sqrt.f32(float %a)
ret float %c
}
; ASM-LABEL: encSqrtFloat
; ASM-NEXT: .LencSqrtFloat$entry:
; ASM-NEXT: sqrt.s $f12, $f12
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000080 <encSqrtFloat>:
; DIS-NEXT: 80: 46006304 sqrt.s $f12,$f12
; DIS-NEXT: 84: 46006006 mov.s $f0,$f12
; DIS-NEXT: 88: 03e00008 jr ra
; DIS-NEXT: 8c: 00000000 nop
; IASM-LABEL: encSqrtFloat:
; IASM-NEXT: .LencSqrtFloat$entry:
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encSqrtDouble(double %a) {
entry:
%c = call double @llvm.sqrt.f64(double %a)
ret double %c
}
; ASM-LABEL: encSqrtDouble
; ASM-NEXT: .LencSqrtDouble$entry:
; ASM-NEXT: sqrt.d $f12, $f12
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 00000090 <encSqrtDouble>:
; DIS-NEXT: 90: 46206304 sqrt.d $f12,$f12
; DIS-NEXT: 94: 46206006 mov.d $f0,$f12
; DIS-NEXT: 98: 03e00008 jr ra
; DIS-NEXT: 9c: 00000000 nop
; IASM-LABEL: encSqrtDouble:
; IASM-NEXT: .LencSqrtDouble$entry:
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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 float @encSubFloat(float %a, float %b) {
entry:
%c = fsub float %a, %b
ret float %c
}
; ASM-LABEL: encSubFloat
; ASM-NEXT: .LencSubFloat$entry:
; ASM-NEXT: sub.s $f12, $f12, $f14
; ASM-NEXT: mov.s $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 000000a0 <encSubFloat>:
; DIS-NEXT: a0: 460e6301 sub.s $f12,$f12,$f14
; DIS-NEXT: a4: 46006006 mov.s $f0,$f12
; DIS-NEXT: a8: 03e00008 jr ra
; DIS-NEXT: ac: 00000000 nop
; IASM-LABEL: encSubFloat:
; IASM-NEXT: .LencSubFloat$entry:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0xe
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x46
; 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 double @encSubDouble(double %a, double %b) {
entry:
%c = fsub double %a, %b
ret double %c
}
; ASM-LABEL: encSubDouble
; ASM-NEXT: .LencSubDouble$entry:
; ASM-NEXT: sub.d $f12, $f12, $f14
; ASM-NEXT: mov.d $f0, $f12
; ASM-NEXT: jr $ra
; DIS-LABEL: 000000b0 <encSubDouble>:
; DIS-NEXT: b0: 462e6301 sub.d $f12,$f12,$f14
; DIS-NEXT: b4: 46206006 mov.d $f0,$f12
; DIS-NEXT: b8: 03e00008 jr ra
; DIS-NEXT: bc: 00000000 nop
; IASM-LABEL: encSubDouble:
; IASM-NEXT: .LencSubDouble$entry:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x63
; IASM-NEXT: .byte 0x2e
; IASM-NEXT: .byte 0x46
; IASM-NEXT: .byte 0x6
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x46
; 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
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