MIPS32: Implement intrinsics from java.lang.Math:
- abs(double) - abs(float) - abs(int)
- abs(long) - max(double, double) - max(float, float)
- max(int, int) - max(long, long) - min(double, double)
- min(float, float) - min(int, int) - min(long, long)
- sqrt(double)
The math intrinsics:
- ceil(double) - floor(double) - rint(double)
- round(double) - round(float)
aren't implemented because they require instructions which only exist
for MIPS64, or for MIPS32r6.
Change-Id: I943be3592b52a423fcb7ac40f46f38a5e2a58c50
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 6fd65ee..7c41813 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -537,12 +537,20 @@
EmitI(0x7, rt, static_cast<Register>(0), imm16);
}
+void MipsAssembler::Bc1f(uint16_t imm16) {
+ Bc1f(0, imm16);
+}
+
void MipsAssembler::Bc1f(int cc, uint16_t imm16) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16);
}
+void MipsAssembler::Bc1t(uint16_t imm16) {
+ Bc1t(0, imm16);
+}
+
void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
@@ -843,6 +851,22 @@
EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
}
+void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4);
+}
+
+void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4);
+}
+
+void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5);
+}
+
+void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5);
+}
+
void MipsAssembler::MovS(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6);
}
@@ -859,84 +883,140 @@
EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7);
}
+void MipsAssembler::CunS(FRegister fs, FRegister ft) {
+ CunS(0, fs, ft);
+}
+
void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31);
}
+void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
+ CeqS(0, fs, ft);
+}
+
void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32);
}
+void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
+ CueqS(0, fs, ft);
+}
+
void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33);
}
+void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
+ ColtS(0, fs, ft);
+}
+
void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34);
}
+void MipsAssembler::CultS(FRegister fs, FRegister ft) {
+ CultS(0, fs, ft);
+}
+
void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35);
}
+void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
+ ColeS(0, fs, ft);
+}
+
void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36);
}
+void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
+ CuleS(0, fs, ft);
+}
+
void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37);
}
+void MipsAssembler::CunD(FRegister fs, FRegister ft) {
+ CunD(0, fs, ft);
+}
+
void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31);
}
+void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
+ CeqD(0, fs, ft);
+}
+
void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32);
}
+void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
+ CueqD(0, fs, ft);
+}
+
void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33);
}
+void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
+ ColtD(0, fs, ft);
+}
+
void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34);
}
+void MipsAssembler::CultD(FRegister fs, FRegister ft) {
+ CultD(0, fs, ft);
+}
+
void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35);
}
+void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
+ ColeD(0, fs, ft);
+}
+
void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36);
}
+void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
+ CuleD(0, fs, ft);
+}
+
void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
@@ -1055,6 +1135,70 @@
EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01);
}
+void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
+}
+
+void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
+}
+
+void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
+}
+
+void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b);
+}
+
+void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b);
+}
+
+void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
+}
+
+void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
+}
+
+void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
+}
+
+void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
+}
+
void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09);
}
@@ -1095,6 +1239,14 @@
EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21);
}
+void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf);
+}
+
+void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf);
+}
+
void MipsAssembler::Mfc1(Register rt, FRegister fs) {
EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
}
@@ -2062,11 +2214,19 @@
}
}
+void MipsAssembler::Bc1f(MipsLabel* label) {
+ Bc1f(0, label);
+}
+
void MipsAssembler::Bc1f(int cc, MipsLabel* label) {
CHECK(IsUint<3>(cc)) << cc;
Bcond(label, kCondF, static_cast<Register>(cc), ZERO);
}
+void MipsAssembler::Bc1t(MipsLabel* label) {
+ Bc1t(0, label);
+}
+
void MipsAssembler::Bc1t(int cc, MipsLabel* label) {
CHECK(IsUint<3>(cc)) << cc;
Bcond(label, kCondT, static_cast<Register>(cc), ZERO);
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index 2262af4..a7179fd 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -51,6 +51,20 @@
kStoreDoubleword
};
+// Used to test the values returned by ClassS/ClassD.
+enum FPClassMaskType {
+ kSignalingNaN = 0x001,
+ kQuietNaN = 0x002,
+ kNegativeInfinity = 0x004,
+ kNegativeNormal = 0x008,
+ kNegativeSubnormal = 0x010,
+ kNegativeZero = 0x020,
+ kPositiveInfinity = 0x040,
+ kPositiveNormal = 0x080,
+ kPositiveSubnormal = 0x100,
+ kPositiveZero = 0x200,
+};
+
class MipsLabel : public Label {
public:
MipsLabel() : prev_branch_id_plus_one_(0) {}
@@ -191,7 +205,9 @@
void Bgez(Register rt, uint16_t imm16);
void Blez(Register rt, uint16_t imm16);
void Bgtz(Register rt, uint16_t imm16);
+ void Bc1f(uint16_t imm16); // R2
void Bc1f(int cc, uint16_t imm16); // R2
+ void Bc1t(uint16_t imm16); // R2
void Bc1t(int cc, uint16_t imm16); // R2
void J(uint32_t addr26);
void Jal(uint32_t addr26);
@@ -227,24 +243,42 @@
void SubD(FRegister fd, FRegister fs, FRegister ft);
void MulD(FRegister fd, FRegister fs, FRegister ft);
void DivD(FRegister fd, FRegister fs, FRegister ft);
+ void SqrtS(FRegister fd, FRegister fs);
+ void SqrtD(FRegister fd, FRegister fs);
+ void AbsS(FRegister fd, FRegister fs);
+ void AbsD(FRegister fd, FRegister fs);
void MovS(FRegister fd, FRegister fs);
void MovD(FRegister fd, FRegister fs);
void NegS(FRegister fd, FRegister fs);
void NegD(FRegister fd, FRegister fs);
+ void CunS(FRegister fs, FRegister ft); // R2
void CunS(int cc, FRegister fs, FRegister ft); // R2
+ void CeqS(FRegister fs, FRegister ft); // R2
void CeqS(int cc, FRegister fs, FRegister ft); // R2
+ void CueqS(FRegister fs, FRegister ft); // R2
void CueqS(int cc, FRegister fs, FRegister ft); // R2
+ void ColtS(FRegister fs, FRegister ft); // R2
void ColtS(int cc, FRegister fs, FRegister ft); // R2
+ void CultS(FRegister fs, FRegister ft); // R2
void CultS(int cc, FRegister fs, FRegister ft); // R2
+ void ColeS(FRegister fs, FRegister ft); // R2
void ColeS(int cc, FRegister fs, FRegister ft); // R2
+ void CuleS(FRegister fs, FRegister ft); // R2
void CuleS(int cc, FRegister fs, FRegister ft); // R2
+ void CunD(FRegister fs, FRegister ft); // R2
void CunD(int cc, FRegister fs, FRegister ft); // R2
+ void CeqD(FRegister fs, FRegister ft); // R2
void CeqD(int cc, FRegister fs, FRegister ft); // R2
+ void CueqD(FRegister fs, FRegister ft); // R2
void CueqD(int cc, FRegister fs, FRegister ft); // R2
+ void ColtD(FRegister fs, FRegister ft); // R2
void ColtD(int cc, FRegister fs, FRegister ft); // R2
+ void CultD(FRegister fs, FRegister ft); // R2
void CultD(int cc, FRegister fs, FRegister ft); // R2
+ void ColeD(FRegister fs, FRegister ft); // R2
void ColeD(int cc, FRegister fs, FRegister ft); // R2
+ void CuleD(FRegister fs, FRegister ft); // R2
void CuleD(int cc, FRegister fs, FRegister ft); // R2
void CmpUnS(FRegister fd, FRegister fs, FRegister ft); // R6
void CmpEqS(FRegister fd, FRegister fs, FRegister ft); // R6
@@ -266,8 +300,20 @@
void CmpOrD(FRegister fd, FRegister fs, FRegister ft); // R6
void CmpUneD(FRegister fd, FRegister fs, FRegister ft); // R6
void CmpNeD(FRegister fd, FRegister fs, FRegister ft); // R6
- void Movf(Register rd, Register rs, int cc); // R2
- void Movt(Register rd, Register rs, int cc); // R2
+ void Movf(Register rd, Register rs, int cc = 0); // R2
+ void Movt(Register rd, Register rs, int cc = 0); // R2
+ void MovfS(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovfD(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovtS(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovtD(FRegister fd, FRegister fs, int cc = 0); // R2
+ void SelS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void SelD(FRegister fd, FRegister fs, FRegister ft); // R6
+ void ClassS(FRegister fd, FRegister fs); // R6
+ void ClassD(FRegister fd, FRegister fs); // R6
+ void MinS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MinD(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MaxS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MaxD(FRegister fd, FRegister fs, FRegister ft); // R6
void TruncLS(FRegister fd, FRegister fs); // R2+, FR=1
void TruncLD(FRegister fd, FRegister fs); // R2+, FR=1
@@ -279,6 +325,8 @@
void Cvtds(FRegister fd, FRegister fs);
void Cvtsl(FRegister fd, FRegister fs); // R2+, FR=1
void Cvtdl(FRegister fd, FRegister fs); // R2+, FR=1
+ void FloorWS(FRegister fd, FRegister fs);
+ void FloorWD(FRegister fd, FRegister fs);
void Mfc1(Register rt, FRegister fs);
void Mtc1(Register rt, FRegister fs);
@@ -322,7 +370,9 @@
void Bge(Register rs, Register rt, MipsLabel* label);
void Bltu(Register rs, Register rt, MipsLabel* label);
void Bgeu(Register rs, Register rt, MipsLabel* label);
+ void Bc1f(MipsLabel* label); // R2
void Bc1f(int cc, MipsLabel* label); // R2
+ void Bc1t(MipsLabel* label); // R2
void Bc1t(int cc, MipsLabel* label); // R2
void Bc1eqz(FRegister ft, MipsLabel* label); // R6
void Bc1nez(FRegister ft, MipsLabel* label); // R6