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