Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: src/IceAssemblerMIPS32.cpp

Issue 2341713003: Subzero, MIPS32: Floating point support in ELF output (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addressing review comments, tests added, more instructions added Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/IceAssemblerMIPS32.cpp
diff --git a/src/IceAssemblerMIPS32.cpp b/src/IceAssemblerMIPS32.cpp
index b9ddff1cf3dddca2e063e13dd7fe942b85ebc64f..1ce1aa300338cf8a041895c26aa4e9e73fcff38d 100644
--- a/src/IceAssemblerMIPS32.cpp
+++ b/src/IceAssemblerMIPS32.cpp
@@ -102,6 +102,8 @@ void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
this->bind(L);
}
+namespace {
+
// Checks that Offset can fit in imm16 constant of branch instruction.
void assertCanEncodeBranchOffset(IOffsetT Offset) {
(void)Offset;
@@ -118,34 +120,26 @@ IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
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 };
IValueT getEncodedGPRegNum(const Variable *Var) {
- assert(Var->hasReg());
+ assert(Var->hasReg() && isScalarIntegerType(Var->getType()));
const auto Reg = Var->getRegNum();
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,
RegSetWanted WantedRegSet) {
Value = 0;
@@ -155,7 +149,8 @@ bool encodeOperand(const Operand *Opnd, IValueT &Value,
case WantGPRegs:
Value = getEncodedGPRegNum(Var);
break;
- default:
+ case WantFPRegs:
+ Value = getEncodedFPRegNum(Var);
break;
}
return true;
@@ -179,6 +174,32 @@ IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
}
+IValueT encodeFPRegister(const Operand *OpReg, const char *RegName,
+ const char *InstName) {
+ return encodeRegister(OpReg, WantFPRegs, RegName, InstName);
+}
+}
Jim Stichnoth 2016/09/16 03:25:00 // 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,
const Operand *OpRs, const uint32_t Imm,
const char *InsnName) {
@@ -192,6 +213,19 @@ void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
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,
const Operand *OpRt, const uint32_t Sa,
const char *InsnName) {
@@ -219,6 +253,176 @@ void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
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::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::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::movn_d(const Operand *OpFd, const Operand *OpFs,
+ const Operand *OpFt) {
+ static constexpr IValueT Opcode = 0x44000013;
+ emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.d");
+}
+
+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::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::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::addiu(const Operand *OpRt, const Operand *OpRs,
const uint32_t Imm) {
static constexpr IValueT Opcode = 0x24000000;
@@ -292,14 +496,42 @@ void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
}
void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
- IValueT Opcode = 0x00000021;
- const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
- const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
- const IValueT Rt = 0; // $0
- Opcode |= Rs << 21;
- Opcode |= Rt << 16;
- Opcode |= Rd << 11;
- emitInst(Opcode);
+
+ 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;
+ const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
+ const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
+ const IValueT Rt = 0; // $0
+ Opcode |= Rs << 21;
+ Opcode |= Rt << 16;
+ Opcode |= Rd << 11;
+ emitInst(Opcode);
+ break;
+ }
+ default: { UnimplementedError(getFlags()); }
+ }
+ }
}
void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
@@ -322,14 +554,65 @@ void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
const uint32_t Offset) {
- static constexpr IValueT Opcode = 0xAC000000;
- emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
+ 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;
+ 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,
const uint32_t Offset) {
- static constexpr IValueT Opcode = 0x8C000000;
- emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
+ 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::ret(void) {

Powered by Google App Engine
This is Rietveld 408576698