MIPS64: Check for MSA presence in each MSA instruction

Test: mma test-art-host-gtest

Change-Id: I123fe1e33de13af6a2b2a76f37f7ad23004a81c0
diff --git a/compiler/utils/jni_macro_assembler.cc b/compiler/utils/jni_macro_assembler.cc
index 2f154fb..3ac6c3c 100644
--- a/compiler/utils/jni_macro_assembler.cc
+++ b/compiler/utils/jni_macro_assembler.cc
@@ -84,7 +84,11 @@
 MacroAsm64UniquePtr JNIMacroAssembler<PointerSize::k64>::Create(
     ArenaAllocator* arena,
     InstructionSet instruction_set,
-    const InstructionSetFeatures* instruction_set_features ATTRIBUTE_UNUSED) {
+    const InstructionSetFeatures* instruction_set_features) {
+#ifndef ART_ENABLE_CODEGEN_mips64
+  UNUSED(instruction_set_features);
+#endif
+
   switch (instruction_set) {
 #ifdef ART_ENABLE_CODEGEN_arm64
     case kArm64:
@@ -92,7 +96,11 @@
 #endif
 #ifdef ART_ENABLE_CODEGEN_mips64
     case kMips64:
-      return MacroAsm64UniquePtr(new (arena) mips64::Mips64Assembler(arena));
+      return MacroAsm64UniquePtr(new (arena) mips64::Mips64Assembler(
+          arena,
+          instruction_set_features != nullptr
+              ? instruction_set_features->AsMips64InstructionSetFeatures()
+              : nullptr));
 #endif
 #ifdef ART_ENABLE_CODEGEN_x86_64
     case kX86_64:
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index 4e7f635..8a5ae75 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -1180,373 +1180,456 @@
   Nor(rd, rs, ZERO);
 }
 
-// TODO: Check for MSA presence in Mips64InstructionSetFeatures for each MSA instruction.
-
 void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
 }
 
 void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
 }
 
 void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
 }
 
 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
+  CHECK(HasMsa());
   EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
+  CHECK(HasMsa());
   EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
+  CHECK(HasMsa());
   EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
+  CHECK(HasMsa());
   EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
 }
 
 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+  CHECK(HasMsa());
   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
 }
 
 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
+  CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
   EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
+  CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
   EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
+  CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
   EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
+  CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
   EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
+  CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
   EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
+  CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
   EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
+  CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
   EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
+  CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
   EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
+  CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
   EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
+  CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
   EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
+  CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
   EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
+  CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
   EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
 }
 
 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
+  CHECK(HasMsa());
   EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
 }
 
 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
+  CHECK(HasMsa());
   CHECK(IsUint<4>(n4)) << n4;
   EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
 }
 
 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
+  CHECK(HasMsa());
   CHECK(IsUint<3>(n3)) << n3;
   EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
 }
 
 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
+  CHECK(HasMsa());
   CHECK(IsUint<2>(n2)) << n2;
   EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
 }
 
 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
+  CHECK(HasMsa());
   CHECK(IsUint<1>(n1)) << n1;
   EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
 }
 
 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
+  CHECK(HasMsa());
   EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
 }
 
 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
+  CHECK(HasMsa());
   EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
 }
 
 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
+  CHECK(HasMsa());
   EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
 }
 
 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
+  CHECK(HasMsa());
   EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
 }
 
 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<10>(offset)) << offset;
   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
 }
 
 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<11>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
 }
 
 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<12>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64WordSize);
   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
 }
 
 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<13>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
 }
 
 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<10>(offset)) << offset;
   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
 }
 
 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<11>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
 }
 
 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<12>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64WordSize);
   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
 }
 
 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
+  CHECK(HasMsa());
   CHECK(IsInt<13>(offset)) << offset;
   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index f42c162..a8035b6 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -21,6 +21,7 @@
 #include <utility>
 #include <vector>
 
+#include "arch/mips64/instruction_set_features_mips64.h"
 #include "base/arena_containers.h"
 #include "base/enums.h"
 #include "base/macros.h"
@@ -413,7 +414,8 @@
  public:
   using JNIBase = JNIMacroAssembler<PointerSize::k64>;
 
-  explicit Mips64Assembler(ArenaAllocator* arena)
+  explicit Mips64Assembler(ArenaAllocator* arena,
+                           const Mips64InstructionSetFeatures* instruction_set_features = nullptr)
       : Assembler(arena),
         overwriting_(false),
         overwrite_location_(0),
@@ -422,7 +424,8 @@
         jump_tables_(arena->Adapter(kArenaAllocAssembler)),
         last_position_adjustment_(0),
         last_old_position_(0),
-        last_branch_id_(0) {
+        last_branch_id_(0),
+        has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false) {
     cfi().DelayEmittingAdvancePCs();
   }
 
@@ -1479,6 +1482,10 @@
   // Emits exception block.
   void EmitExceptionPoll(Mips64ExceptionSlowPath* exception);
 
+  bool HasMsa() const {
+    return has_msa_;
+  }
+
   // List of exception blocks to generate at the end of the code cache.
   std::vector<Mips64ExceptionSlowPath> exception_blocks_;
 
@@ -1502,6 +1509,8 @@
   uint32_t last_old_position_;
   uint32_t last_branch_id_;
 
+  const bool has_msa_;
+
   DISALLOW_COPY_AND_ASSIGN(Mips64Assembler);
 };
 
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index 12660ce..cadbe27 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -46,6 +46,9 @@
                         uint32_t,
                         mips64::VectorRegister> Base;
 
+  AssemblerMIPS64Test()
+      : instruction_set_features_(Mips64InstructionSetFeatures::FromVariant("default", nullptr)) {}
+
  protected:
   // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
   std::string GetArchitectureString() OVERRIDE {
@@ -78,6 +81,10 @@
     return " -D -bbinary -mmips:isa64r6";
   }
 
+  mips64::Mips64Assembler* CreateAssembler(ArenaAllocator* arena) OVERRIDE {
+    return new (arena) mips64::Mips64Assembler(arena, instruction_set_features_.get());
+  }
+
   void SetUpHelpers() OVERRIDE {
     if (registers_.size() == 0) {
       registers_.push_back(new mips64::GpuRegister(mips64::ZERO));
@@ -313,8 +320,9 @@
 
   std::vector<mips64::FpuRegister*> fp_registers_;
   std::vector<mips64::VectorRegister*> vec_registers_;
-};
 
+  std::unique_ptr<const Mips64InstructionSetFeatures> instruction_set_features_;
+};
 
 TEST_F(AssemblerMIPS64Test, Toolchain) {
   EXPECT_TRUE(CheckTools());