Check CPU features in the Assembler.

Now, when the Assembler is asked to assemble an instruction, it asserts (in
debug mode) that the necessary features are available.

This also updates the tests to use no features by default, so that they must be
explicitly requested in the test itself. This provides some assurance that the
Assembler contains reasonable checks.

This patch uses variadic macros, which are a C99/C++11 feature, and I had to
silence a warning in the build system for C++98 builds. However, its use is
restricted to the tests, and we already rely on some other C99 features.

Change-Id: Ifb9846504f98c6d0912f60ff25f219ce2b780755
diff --git a/SConstruct b/SConstruct
index 671bc74..3c64b3f 100644
--- a/SConstruct
+++ b/SConstruct
@@ -395,6 +395,7 @@
   # When compiling with c++98 (the default), allow long long constants.
   if 'std' not in env or env['std'] == 'c++98':
     env.Append(CPPFLAGS = ['-Wno-long-long'])
+    env.Append(CPPFLAGS = ['-Wno-variadic-macros'])
   # When compiling with c++11, suggest missing override keywords on methods.
   if 'std' in env and env['std'] in ['c++11', 'c++14']:
     if compiler >= 'gcc-5':
diff --git a/src/aarch64/assembler-aarch64.cc b/src/aarch64/assembler-aarch64.cc
index 7fe91f1..c4c77c4 100644
--- a/src/aarch64/assembler-aarch64.cc
+++ b/src/aarch64/assembler-aarch64.cc
@@ -255,6 +255,7 @@
                           const VRegister& vn,
                           const VRegister& vm,
                           NEONTableOp op) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.Is16B() || vd.Is8B());
   VIXL_ASSERT(vn.Is16B());
   VIXL_ASSERT(AreSameFormat(vd, vm));
@@ -265,6 +266,7 @@
 void Assembler::tbl(const VRegister& vd,
                     const VRegister& vn,
                     const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONTable(vd, vn, vm, NEON_TBL_1v);
 }
 
@@ -274,6 +276,7 @@
                     const VRegister& vn2,
                     const VRegister& vm) {
   USE(vn2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2));
   VIXL_ASSERT(AreConsecutive(vn, vn2));
   NEONTable(vd, vn, vm, NEON_TBL_2v);
@@ -286,6 +289,7 @@
                     const VRegister& vn3,
                     const VRegister& vm) {
   USE(vn2, vn3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2, vn3));
   VIXL_ASSERT(AreConsecutive(vn, vn2, vn3));
   NEONTable(vd, vn, vm, NEON_TBL_3v);
@@ -299,6 +303,7 @@
                     const VRegister& vn4,
                     const VRegister& vm) {
   USE(vn2, vn3, vn4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2, vn3, vn4));
   VIXL_ASSERT(AreConsecutive(vn, vn2, vn3, vn4));
   NEONTable(vd, vn, vm, NEON_TBL_4v);
@@ -308,6 +313,7 @@
 void Assembler::tbx(const VRegister& vd,
                     const VRegister& vn,
                     const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONTable(vd, vn, vm, NEON_TBX_1v);
 }
 
@@ -317,6 +323,7 @@
                     const VRegister& vn2,
                     const VRegister& vm) {
   USE(vn2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2));
   VIXL_ASSERT(AreConsecutive(vn, vn2));
   NEONTable(vd, vn, vm, NEON_TBX_2v);
@@ -329,6 +336,7 @@
                     const VRegister& vn3,
                     const VRegister& vm) {
   USE(vn2, vn3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2, vn3));
   VIXL_ASSERT(AreConsecutive(vn, vn2, vn3));
   NEONTable(vd, vn, vm, NEON_TBX_3v);
@@ -342,6 +350,7 @@
                     const VRegister& vn4,
                     const VRegister& vm) {
   USE(vn2, vn3, vn4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vn, vn2, vn3, vn4));
   VIXL_ASSERT(AreConsecutive(vn, vn2, vn3, vn4));
   NEONTable(vd, vn, vm, NEON_TBX_4v);
@@ -736,6 +745,7 @@
 void Assembler::crc32b(const Register& wd,
                        const Register& wn,
                        const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32B | Rn(wn) | Rd(wd));
 }
@@ -744,6 +754,7 @@
 void Assembler::crc32h(const Register& wd,
                        const Register& wn,
                        const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32H | Rn(wn) | Rd(wd));
 }
@@ -752,6 +763,7 @@
 void Assembler::crc32w(const Register& wd,
                        const Register& wn,
                        const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32W | Rn(wn) | Rd(wd));
 }
@@ -760,6 +772,7 @@
 void Assembler::crc32x(const Register& wd,
                        const Register& wn,
                        const Register& xm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && xm.Is64Bits());
   Emit(SF(xm) | Rm(xm) | CRC32X | Rn(wn) | Rd(wd));
 }
@@ -768,6 +781,7 @@
 void Assembler::crc32cb(const Register& wd,
                         const Register& wn,
                         const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32CB | Rn(wn) | Rd(wd));
 }
@@ -776,6 +790,7 @@
 void Assembler::crc32ch(const Register& wd,
                         const Register& wn,
                         const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32CH | Rn(wn) | Rd(wd));
 }
@@ -784,6 +799,7 @@
 void Assembler::crc32cw(const Register& wd,
                         const Register& wn,
                         const Register& wm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && wm.Is32Bits());
   Emit(SF(wm) | Rm(wm) | CRC32CW | Rn(wn) | Rd(wd));
 }
@@ -792,6 +808,7 @@
 void Assembler::crc32cx(const Register& wd,
                         const Register& wn,
                         const Register& xm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kCRC32));
   VIXL_ASSERT(wd.Is32Bits() && wn.Is32Bits() && xm.Is64Bits());
   Emit(SF(xm) | Rm(xm) | CRC32CX | Rn(wn) | Rd(wd));
 }
@@ -969,6 +986,8 @@
                               const CPURegister& rt2,
                               const MemOperand& addr,
                               LoadStorePairOp op) {
+  VIXL_ASSERT(CPUHas(rt, rt2));
+
   // 'rt' and 'rt2' can only be aliased for stores.
   VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2));
   VIXL_ASSERT(AreSameSizeAndType(rt, rt2));
@@ -1012,6 +1031,8 @@
                                          const CPURegister& rt2,
                                          const MemOperand& addr,
                                          LoadStorePairNonTemporalOp op) {
+  VIXL_ASSERT(CPUHas(rt, rt2));
+
   VIXL_ASSERT(!rt.Is(rt2));
   VIXL_ASSERT(AreSameSizeAndType(rt, rt2));
   VIXL_ASSERT(addr.IsImmediateOffset());
@@ -1198,6 +1219,7 @@
 
 
 void Assembler::ldr(const CPURegister& rt, RawLiteral* literal) {
+  VIXL_ASSERT(CPUHas(rt));
   VIXL_ASSERT(literal->GetSize() == static_cast<size_t>(rt.GetSizeInBytes()));
   ldr(rt, static_cast<int>(LinkAndGetWordOffsetTo(literal)));
 }
@@ -1209,6 +1231,7 @@
 
 
 void Assembler::ldr(const CPURegister& rt, int64_t imm19) {
+  VIXL_ASSERT(CPUHas(rt));
   LoadLiteralOp op = LoadLiteralOpFor(rt);
   Emit(op | ImmLLiteral(imm19) | Rt(rt));
 }
@@ -1389,18 +1412,21 @@
 
 
 void Assembler::stllrb(const Register& rt, const MemOperand& dst) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(dst.IsImmediateOffset() && (dst.GetOffset() == 0));
   Emit(STLLRB | Rs_mask | Rt(rt) | Rt2_mask | RnSP(dst.GetBaseRegister()));
 }
 
 
 void Assembler::stllrh(const Register& rt, const MemOperand& dst) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(dst.IsImmediateOffset() && (dst.GetOffset() == 0));
   Emit(STLLRH | Rs_mask | Rt(rt) | Rt2_mask | RnSP(dst.GetBaseRegister()));
 }
 
 
 void Assembler::stllr(const Register& rt, const MemOperand& dst) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(dst.IsImmediateOffset() && (dst.GetOffset() == 0));
   LoadStoreExclusive op = rt.Is64Bits() ? STLLR_x : STLLR_w;
   Emit(op | Rs_mask | Rt(rt) | Rt2_mask | RnSP(dst.GetBaseRegister()));
@@ -1408,18 +1434,21 @@
 
 
 void Assembler::ldlarb(const Register& rt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));
   Emit(LDLARB | Rs_mask | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister()));
 }
 
 
 void Assembler::ldlarh(const Register& rt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));
   Emit(LDLARH | Rs_mask | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister()));
 }
 
 
 void Assembler::ldlar(const Register& rt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kLORegions));
   VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));
   LoadStoreExclusive op = rt.Is64Bits() ? LDLAR_x : LDLAR_w;
   Emit(op | Rs_mask | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister()));
@@ -1438,6 +1467,7 @@
   void Assembler::FN(const Register& rs,                                 \
                      const Register& rt,                                 \
                      const MemOperand& src) {                            \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kAtomics));                          \
     VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));      \
     LoadStoreExclusive op = rt.Is64Bits() ? OP##_x : OP##_w;             \
     Emit(op | Rs(rs) | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister())); \
@@ -1461,6 +1491,7 @@
   void Assembler::FN(const Register& rs,                                 \
                      const Register& rt,                                 \
                      const MemOperand& src) {                            \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kAtomics));                          \
     VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));      \
     Emit(OP | Rs(rs) | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister())); \
   }
@@ -1482,6 +1513,7 @@
                      const Register& rt,                                 \
                      const Register& rt1,                                \
                      const MemOperand& src) {                            \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kAtomics));                          \
     USE(rs1, rt1);                                                       \
     VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0));      \
     VIXL_ASSERT(AreEven(rs, rt));                                        \
@@ -1653,6 +1685,7 @@
 
 
 void Assembler::ld1(const VRegister& vt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   LoadStoreStruct(vt, src, NEON_LD1_1v);
 }
 
@@ -1661,6 +1694,7 @@
                     const VRegister& vt2,
                     const MemOperand& src) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStruct(vt, src, NEON_LD1_2v);
@@ -1672,6 +1706,7 @@
                     const VRegister& vt3,
                     const MemOperand& src) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStruct(vt, src, NEON_LD1_3v);
@@ -1684,6 +1719,7 @@
                     const VRegister& vt4,
                     const MemOperand& src) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStruct(vt, src, NEON_LD1_4v);
@@ -1694,6 +1730,7 @@
                     const VRegister& vt2,
                     const MemOperand& src) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStruct(vt, src, NEON_LD2);
@@ -1705,6 +1742,7 @@
                     int lane,
                     const MemOperand& src) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad2);
@@ -1715,6 +1753,7 @@
                      const VRegister& vt2,
                      const MemOperand& src) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStructSingleAllLanes(vt, src, NEON_LD2R);
@@ -1726,6 +1765,7 @@
                     const VRegister& vt3,
                     const MemOperand& src) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStruct(vt, src, NEON_LD3);
@@ -1738,6 +1778,7 @@
                     int lane,
                     const MemOperand& src) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad3);
@@ -1749,6 +1790,7 @@
                      const VRegister& vt3,
                      const MemOperand& src) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStructSingleAllLanes(vt, src, NEON_LD3R);
@@ -1761,6 +1803,7 @@
                     const VRegister& vt4,
                     const MemOperand& src) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStruct(vt, src, NEON_LD4);
@@ -1774,6 +1817,7 @@
                     int lane,
                     const MemOperand& src) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad4);
@@ -1786,6 +1830,7 @@
                      const VRegister& vt4,
                      const MemOperand& src) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStructSingleAllLanes(vt, src, NEON_LD4R);
@@ -1793,6 +1838,7 @@
 
 
 void Assembler::st1(const VRegister& vt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   LoadStoreStruct(vt, src, NEON_ST1_1v);
 }
 
@@ -1801,6 +1847,7 @@
                     const VRegister& vt2,
                     const MemOperand& src) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStruct(vt, src, NEON_ST1_2v);
@@ -1812,6 +1859,7 @@
                     const VRegister& vt3,
                     const MemOperand& src) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStruct(vt, src, NEON_ST1_3v);
@@ -1824,6 +1872,7 @@
                     const VRegister& vt4,
                     const MemOperand& src) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStruct(vt, src, NEON_ST1_4v);
@@ -1834,6 +1883,7 @@
                     const VRegister& vt2,
                     const MemOperand& dst) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStruct(vt, dst, NEON_ST2);
@@ -1845,6 +1895,7 @@
                     int lane,
                     const MemOperand& dst) {
   USE(vt2);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2));
   VIXL_ASSERT(AreConsecutive(vt, vt2));
   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore2);
@@ -1856,6 +1907,7 @@
                     const VRegister& vt3,
                     const MemOperand& dst) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStruct(vt, dst, NEON_ST3);
@@ -1868,6 +1920,7 @@
                     int lane,
                     const MemOperand& dst) {
   USE(vt2, vt3);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3));
   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore3);
@@ -1880,6 +1933,7 @@
                     const VRegister& vt4,
                     const MemOperand& dst) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStruct(vt, dst, NEON_ST4);
@@ -1893,6 +1947,7 @@
                     int lane,
                     const MemOperand& dst) {
   USE(vt2, vt3, vt4);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vt, vt2, vt3, vt4));
   VIXL_ASSERT(AreConsecutive(vt, vt2, vt3, vt4));
   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore4);
@@ -1940,16 +1995,19 @@
 
 
 void Assembler::ld1(const VRegister& vt, int lane, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad1);
 }
 
 
 void Assembler::ld1r(const VRegister& vt, const MemOperand& src) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   LoadStoreStructSingleAllLanes(vt, src, NEON_LD1R);
 }
 
 
 void Assembler::st1(const VRegister& vt, int lane, const MemOperand& dst) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore1);
 }
 
@@ -2039,12 +2097,13 @@
 // clang-format on
 
 
-#define DEFINE_ASM_FUNC(FN, OP, AS)        \
-void Assembler::FN(const VRegister& vd,    \
-                   const VRegister& vn,    \
-                   const VRegister& vm) {  \
-  VIXL_ASSERT(AS);                         \
-  NEON3DifferentL(vd, vn, vm, OP);         \
+#define DEFINE_ASM_FUNC(FN, OP, AS)                   \
+void Assembler::FN(const VRegister& vd,               \
+                   const VRegister& vn,               \
+                   const VRegister& vm) {             \
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));            \
+  VIXL_ASSERT(AS);                                    \
+  NEON3DifferentL(vd, vn, vm, OP);                    \
 }
 NEON_3DIFF_LONG_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
@@ -2061,12 +2120,13 @@
   V(rsubhn2, NEON_RSUBHN2, vd.IsQ())
 // clang-format on
 
-#define DEFINE_ASM_FUNC(FN, OP, AS)         \
-  void Assembler::FN(const VRegister& vd,   \
-                     const VRegister& vn,   \
-                     const VRegister& vm) { \
-    VIXL_ASSERT(AS);                        \
-    NEON3DifferentHN(vd, vn, vm, OP);       \
+#define DEFINE_ASM_FUNC(FN, OP, AS)          \
+  void Assembler::FN(const VRegister& vd,    \
+                     const VRegister& vn,    \
+                     const VRegister& vm) {  \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON)); \
+    VIXL_ASSERT(AS);                         \
+    NEON3DifferentHN(vd, vn, vm, OP);        \
   }
 NEON_3DIFF_HN_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
@@ -2074,6 +2134,7 @@
 void Assembler::uaddw(const VRegister& vd,
                       const VRegister& vn,
                       const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsD());
   NEON3DifferentW(vd, vn, vm, NEON_UADDW);
 }
@@ -2082,6 +2143,7 @@
 void Assembler::uaddw2(const VRegister& vd,
                        const VRegister& vn,
                        const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsQ());
   NEON3DifferentW(vd, vn, vm, NEON_UADDW2);
 }
@@ -2090,6 +2152,7 @@
 void Assembler::saddw(const VRegister& vd,
                       const VRegister& vn,
                       const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsD());
   NEON3DifferentW(vd, vn, vm, NEON_SADDW);
 }
@@ -2098,6 +2161,7 @@
 void Assembler::saddw2(const VRegister& vd,
                        const VRegister& vn,
                        const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsQ());
   NEON3DifferentW(vd, vn, vm, NEON_SADDW2);
 }
@@ -2106,6 +2170,7 @@
 void Assembler::usubw(const VRegister& vd,
                       const VRegister& vn,
                       const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsD());
   NEON3DifferentW(vd, vn, vm, NEON_USUBW);
 }
@@ -2114,6 +2179,7 @@
 void Assembler::usubw2(const VRegister& vd,
                        const VRegister& vn,
                        const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsQ());
   NEON3DifferentW(vd, vn, vm, NEON_USUBW2);
 }
@@ -2122,6 +2188,7 @@
 void Assembler::ssubw(const VRegister& vd,
                       const VRegister& vn,
                       const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsD());
   NEON3DifferentW(vd, vn, vm, NEON_SSUBW);
 }
@@ -2130,6 +2197,7 @@
 void Assembler::ssubw2(const VRegister& vd,
                        const VRegister& vn,
                        const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vm.IsQ());
   NEON3DifferentW(vd, vn, vm, NEON_SSUBW2);
 }
@@ -2184,10 +2252,12 @@
 void Assembler::csdb() { hint(CSDB); }
 
 void Assembler::fmov(const VRegister& vd, double imm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   if (vd.IsScalar()) {
     VIXL_ASSERT(vd.Is1D());
     Emit(FMOV_d_imm | Rd(vd) | ImmFP64(imm));
   } else {
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
     VIXL_ASSERT(vd.Is2D());
     Instr op = NEONModifiedImmediate_MOVI | NEONModifiedImmediateOpBit;
     Instr q = NEON_Q;
@@ -2198,10 +2268,12 @@
 
 
 void Assembler::fmov(const VRegister& vd, float imm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   if (vd.IsScalar()) {
     VIXL_ASSERT(vd.Is1S());
     Emit(FMOV_s_imm | Rd(vd) | ImmFP32(imm));
   } else {
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
     VIXL_ASSERT(vd.Is2S() | vd.Is4S());
     Instr op = NEONModifiedImmediate_MOVI;
     Instr q = vd.Is4S() ? NEON_Q : 0;
@@ -2212,11 +2284,13 @@
 
 
 void Assembler::fmov(const VRegister& vd, F16 imm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kFPHalf));
   uint16_t rawbits = imm.ToRawbits();
   if (vd.IsScalar()) {
     VIXL_ASSERT(vd.Is1H());
     Emit(FMOV_h_imm | Rd(vd) | ImmFP16(rawbits));
   } else {
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
     VIXL_ASSERT(vd.Is4H() | vd.Is8H());
     Instr q = vd.Is8H() ? NEON_Q : 0;
     uint32_t encoded_imm = FP16ToImm8(rawbits);
@@ -2227,11 +2301,13 @@
 
 
 void Assembler::fmov(const Register& rd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vn.Is1H() || vn.Is1S() || vn.Is1D());
   VIXL_ASSERT((rd.GetSizeInBits() == vn.GetSizeInBits()) || vn.Is1H());
   FPIntegerConvertOp op;
   switch (vn.GetSizeInBits()) {
     case 16:
+      VIXL_ASSERT(CPUHas(CPUFeatures::kFPHalf));
       op = rd.Is64Bits() ? FMOV_xh : FMOV_wh;
       break;
     case 32:
@@ -2245,11 +2321,13 @@
 
 
 void Assembler::fmov(const VRegister& vd, const Register& rn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vd.Is1H() || vd.Is1S() || vd.Is1D());
   VIXL_ASSERT((vd.GetSizeInBits() == rn.GetSizeInBits()) || vd.Is1H());
   FPIntegerConvertOp op;
   switch (vd.GetSizeInBits()) {
     case 16:
+      VIXL_ASSERT(CPUHas(CPUFeatures::kFPHalf));
       op = rn.Is64Bits() ? FMOV_hx : FMOV_hw;
       break;
     case 32:
@@ -2263,6 +2341,10 @@
 
 
 void Assembler::fmov(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
+  if (vd.Is1H()) {
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFPHalf));
+  }
   VIXL_ASSERT(vd.Is1H() || vd.Is1S() || vd.Is1D());
   VIXL_ASSERT(vd.IsSameFormat(vn));
   Emit(FPType(vd) | FMOV | Rd(vd) | Rn(vn));
@@ -2270,6 +2352,7 @@
 
 
 void Assembler::fmov(const VRegister& vd, int index, const Register& rn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kFP));
   VIXL_ASSERT((index == 1) && vd.Is1D() && rn.IsX());
   USE(index);
   Emit(FMOV_d1_x | Rd(vd) | Rn(rn));
@@ -2277,6 +2360,7 @@
 
 
 void Assembler::fmov(const Register& rd, const VRegister& vn, int index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kFP));
   VIXL_ASSERT((index == 1) && vn.Is1D() && rd.IsX());
   USE(index);
   Emit(FMOV_x_d1 | Rd(rd) | Rn(vn));
@@ -2287,6 +2371,7 @@
                       const VRegister& vn,
                       const VRegister& vm,
                       const VRegister& va) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPDataProcessing3Source(vd, vn, vm, va, vd.Is1S() ? FMADD_s : FMADD_d);
 }
 
@@ -2295,6 +2380,7 @@
                       const VRegister& vn,
                       const VRegister& vm,
                       const VRegister& va) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPDataProcessing3Source(vd, vn, vm, va, vd.Is1S() ? FMSUB_s : FMSUB_d);
 }
 
@@ -2303,6 +2389,7 @@
                        const VRegister& vn,
                        const VRegister& vm,
                        const VRegister& va) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPDataProcessing3Source(vd, vn, vm, va, vd.Is1S() ? FNMADD_s : FNMADD_d);
 }
 
@@ -2311,6 +2398,7 @@
                        const VRegister& vn,
                        const VRegister& vm,
                        const VRegister& va) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPDataProcessing3Source(vd, vn, vm, va, vd.Is1S() ? FNMSUB_s : FNMSUB_d);
 }
 
@@ -2318,6 +2406,7 @@
 void Assembler::fnmul(const VRegister& vd,
                       const VRegister& vn,
                       const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(AreSameSizeAndType(vd, vn, vm));
   Instr op = vd.Is1S() ? FNMUL_s : FNMUL_d;
   Emit(FPType(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
@@ -2349,21 +2438,25 @@
 
 
 void Assembler::fcmp(const VRegister& vn, const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCompareMacro(vn, vm, DisableTrap);
 }
 
 
 void Assembler::fcmpe(const VRegister& vn, const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCompareMacro(vn, vm, EnableTrap);
 }
 
 
 void Assembler::fcmp(const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCompareMacro(vn, value, DisableTrap);
 }
 
 
 void Assembler::fcmpe(const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCompareMacro(vn, value, EnableTrap);
 }
 
@@ -2383,6 +2476,7 @@
                       const VRegister& vm,
                       StatusFlags nzcv,
                       Condition cond) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCCompareMacro(vn, vm, nzcv, cond, DisableTrap);
 }
 
@@ -2391,6 +2485,7 @@
                        const VRegister& vm,
                        StatusFlags nzcv,
                        Condition cond) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   FPCCompareMacro(vn, vm, nzcv, cond, EnableTrap);
 }
 
@@ -2399,12 +2494,84 @@
                       const VRegister& vn,
                       const VRegister& vm,
                       Condition cond) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vd.Is1S() || vd.Is1D());
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   Emit(FPType(vd) | FCSEL | Rm(vm) | Cond(cond) | Rn(vn) | Rd(vd));
 }
 
 
+void Assembler::fcvt(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
+  FPDataProcessing1SourceOp op;
+  if (vd.Is1D()) {
+    VIXL_ASSERT(vn.Is1S() || vn.Is1H());
+    op = vn.Is1S() ? FCVT_ds : FCVT_dh;
+  } else if (vd.Is1S()) {
+    VIXL_ASSERT(vn.Is1D() || vn.Is1H());
+    op = vn.Is1D() ? FCVT_sd : FCVT_sh;
+  } else {
+    VIXL_ASSERT(vd.Is1H());
+    VIXL_ASSERT(vn.Is1D() || vn.Is1S());
+    op = vn.Is1D() ? FCVT_hd : FCVT_hs;
+  }
+  FPDataProcessing1Source(vd, vn, op);
+}
+
+
+void Assembler::fcvtl(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  VIXL_ASSERT((vd.Is4S() && vn.Is4H()) || (vd.Is2D() && vn.Is2S()));
+  Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
+  Emit(format | NEON_FCVTL | Rn(vn) | Rd(vd));
+}
+
+
+void Assembler::fcvtl2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  VIXL_ASSERT((vd.Is4S() && vn.Is8H()) || (vd.Is2D() && vn.Is4S()));
+  Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
+  Emit(NEON_Q | format | NEON_FCVTL | Rn(vn) | Rd(vd));
+}
+
+
+void Assembler::fcvtn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  VIXL_ASSERT((vn.Is4S() && vd.Is4H()) || (vn.Is2D() && vd.Is2S()));
+  Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
+  Emit(format | NEON_FCVTN | Rn(vn) | Rd(vd));
+}
+
+
+void Assembler::fcvtn2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  VIXL_ASSERT((vn.Is4S() && vd.Is8H()) || (vn.Is2D() && vd.Is4S()));
+  Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
+  Emit(NEON_Q | format | NEON_FCVTN | Rn(vn) | Rd(vd));
+}
+
+
+void Assembler::fcvtxn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  Instr format = 1 << NEONSize_offset;
+  if (vd.IsScalar()) {
+    VIXL_ASSERT(vd.Is1S() && vn.Is1D());
+    Emit(format | NEON_FCVTXN_scalar | Rn(vn) | Rd(vd));
+  } else {
+    VIXL_ASSERT(vd.Is2S() && vn.Is2D());
+    Emit(format | NEON_FCVTXN | Rn(vn) | Rd(vd));
+  }
+}
+
+
+void Assembler::fcvtxn2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
+  VIXL_ASSERT(vd.Is4S() && vn.Is2D());
+  Instr format = 1 << NEONSize_offset;
+  Emit(NEON_Q | format | NEON_FCVTXN | Rn(vn) | Rd(vd));
+}
+
+
 void Assembler::NEONFPConvertToInt(const Register& rd,
                                    const VRegister& vn,
                                    Instr op) {
@@ -2423,70 +2590,6 @@
 }
 
 
-void Assembler::fcvt(const VRegister& vd, const VRegister& vn) {
-  FPDataProcessing1SourceOp op;
-  if (vd.Is1D()) {
-    VIXL_ASSERT(vn.Is1S() || vn.Is1H());
-    op = vn.Is1S() ? FCVT_ds : FCVT_dh;
-  } else if (vd.Is1S()) {
-    VIXL_ASSERT(vn.Is1D() || vn.Is1H());
-    op = vn.Is1D() ? FCVT_sd : FCVT_sh;
-  } else {
-    VIXL_ASSERT(vd.Is1H());
-    VIXL_ASSERT(vn.Is1D() || vn.Is1S());
-    op = vn.Is1D() ? FCVT_hd : FCVT_hs;
-  }
-  FPDataProcessing1Source(vd, vn, op);
-}
-
-
-void Assembler::fcvtl(const VRegister& vd, const VRegister& vn) {
-  VIXL_ASSERT((vd.Is4S() && vn.Is4H()) || (vd.Is2D() && vn.Is2S()));
-  Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
-  Emit(format | NEON_FCVTL | Rn(vn) | Rd(vd));
-}
-
-
-void Assembler::fcvtl2(const VRegister& vd, const VRegister& vn) {
-  VIXL_ASSERT((vd.Is4S() && vn.Is8H()) || (vd.Is2D() && vn.Is4S()));
-  Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
-  Emit(NEON_Q | format | NEON_FCVTL | Rn(vn) | Rd(vd));
-}
-
-
-void Assembler::fcvtn(const VRegister& vd, const VRegister& vn) {
-  VIXL_ASSERT((vn.Is4S() && vd.Is4H()) || (vn.Is2D() && vd.Is2S()));
-  Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
-  Emit(format | NEON_FCVTN | Rn(vn) | Rd(vd));
-}
-
-
-void Assembler::fcvtn2(const VRegister& vd, const VRegister& vn) {
-  VIXL_ASSERT((vn.Is4S() && vd.Is8H()) || (vn.Is2D() && vd.Is4S()));
-  Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
-  Emit(NEON_Q | format | NEON_FCVTN | Rn(vn) | Rd(vd));
-}
-
-
-void Assembler::fcvtxn(const VRegister& vd, const VRegister& vn) {
-  Instr format = 1 << NEONSize_offset;
-  if (vd.IsScalar()) {
-    VIXL_ASSERT(vd.Is1S() && vn.Is1D());
-    Emit(format | NEON_FCVTXN_scalar | Rn(vn) | Rd(vd));
-  } else {
-    VIXL_ASSERT(vd.Is2S() && vn.Is2D());
-    Emit(format | NEON_FCVTXN | Rn(vn) | Rd(vd));
-  }
-}
-
-
-void Assembler::fcvtxn2(const VRegister& vd, const VRegister& vn) {
-  VIXL_ASSERT(vd.Is4S() && vn.Is2D());
-  Instr format = 1 << NEONSize_offset;
-  Emit(NEON_Q | format | NEON_FCVTXN | Rn(vn) | Rd(vd));
-}
-
-
 #define NEON_FP2REGMISC_FCVT_LIST(V) \
   V(fcvtnu, NEON_FCVTNU, FCVTNU)     \
   V(fcvtns, NEON_FCVTNS, FCVTNS)     \
@@ -2499,9 +2602,12 @@
 
 #define DEFINE_ASM_FUNCS(FN, VEC_OP, SCA_OP)                     \
   void Assembler::FN(const Register& rd, const VRegister& vn) {  \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP));                       \
     NEONFPConvertToInt(rd, vn, SCA_OP);                          \
   }                                                              \
   void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
+    /* This form is a NEON scalar FP instruction. */             \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));   \
     NEONFPConvertToInt(vd, vn, VEC_OP);                          \
   }
 NEON_FP2REGMISC_FCVT_LIST(DEFINE_ASM_FUNCS)
@@ -2509,6 +2615,7 @@
 
 
 void Assembler::fcvtzs(const Register& rd, const VRegister& vn, int fbits) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vn.Is1S() || vn.Is1D());
   VIXL_ASSERT((fbits >= 0) && (fbits <= rd.GetSizeInBits()));
   if (fbits == 0) {
@@ -2521,6 +2628,8 @@
 
 
 void Assembler::fcvtzs(const VRegister& vd, const VRegister& vn, int fbits) {
+  // This form is a NEON scalar FP instruction.
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
     NEONFP2RegMisc(vd, vn, NEON_FCVTZS);
@@ -2532,6 +2641,7 @@
 
 
 void Assembler::fcvtzu(const Register& rd, const VRegister& vn, int fbits) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vn.Is1S() || vn.Is1D());
   VIXL_ASSERT((fbits >= 0) && (fbits <= rd.GetSizeInBits()));
   if (fbits == 0) {
@@ -2544,6 +2654,8 @@
 
 
 void Assembler::fcvtzu(const VRegister& vd, const VRegister& vn, int fbits) {
+  // This form is a NEON scalar FP instruction.
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
     NEONFP2RegMisc(vd, vn, NEON_FCVTZU);
@@ -2554,6 +2666,8 @@
 }
 
 void Assembler::ucvtf(const VRegister& vd, const VRegister& vn, int fbits) {
+  // This form is a NEON scalar FP instruction.
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
     NEONFP2RegMisc(vd, vn, NEON_UCVTF);
@@ -2564,6 +2678,8 @@
 }
 
 void Assembler::scvtf(const VRegister& vd, const VRegister& vn, int fbits) {
+  // This form is a NEON scalar FP instruction.
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
     NEONFP2RegMisc(vd, vn, NEON_SCVTF);
@@ -2575,6 +2691,7 @@
 
 
 void Assembler::scvtf(const VRegister& vd, const Register& rn, int fbits) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vd.Is1S() || vd.Is1D());
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
@@ -2587,6 +2704,7 @@
 
 
 void Assembler::ucvtf(const VRegister& vd, const Register& rn, int fbits) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vd.Is1S() || vd.Is1D());
   VIXL_ASSERT(fbits >= 0);
   if (fbits == 0) {
@@ -2643,17 +2761,22 @@
 // clang-format on
 
 
-#define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)                      \
-  void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
-    Instr op;                                                    \
-    if (vd.IsScalar()) {                                         \
-      VIXL_ASSERT(vd.Is1S() || vd.Is1D());                       \
-      op = SCA_OP;                                               \
-    } else {                                                     \
-      VIXL_ASSERT(vd.Is2S() || vd.Is2D() || vd.Is4S());          \
-      op = VEC_OP;                                               \
-    }                                                            \
-    NEONFP2RegMisc(vd, vn, op);                                  \
+#define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)                                \
+  void Assembler::FN(const VRegister& vd, const VRegister& vn) {           \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP));                                 \
+    Instr op;                                                              \
+    if (vd.IsScalar()) {                                                   \
+      if ((SCA_OP & NEONScalar2RegMiscFMask) == NEONScalar2RegMiscFixed) { \
+        VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));                           \
+      }                                                                    \
+      VIXL_ASSERT(vd.Is1S() || vd.Is1D());                                 \
+      op = SCA_OP;                                                         \
+    } else {                                                               \
+      VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));                             \
+      VIXL_ASSERT(vd.Is2S() || vd.Is2D() || vd.Is4S());                    \
+      op = VEC_OP;                                                         \
+    }                                                                      \
+    NEONFP2RegMisc(vd, vn, op);                                            \
   }
 NEON_FP2REGMISC_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
@@ -2688,18 +2811,21 @@
 
 
 void Assembler::cmeq(const VRegister& vd, const VRegister& vn, int value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_CMEQ_zero, value);
 }
 
 
 void Assembler::cmge(const VRegister& vd, const VRegister& vn, int value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_CMGE_zero, value);
 }
 
 
 void Assembler::cmgt(const VRegister& vd, const VRegister& vn, int value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_CMGT_zero, value);
 }
@@ -2707,27 +2833,31 @@
 
 void Assembler::cmle(const VRegister& vd, const VRegister& vn, int value) {
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEON2RegMisc(vd, vn, NEON_CMLE_zero, value);
 }
 
 
 void Assembler::cmlt(const VRegister& vd, const VRegister& vn, int value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_CMLT_zero, value);
 }
 
 
 void Assembler::shll(const VRegister& vd, const VRegister& vn, int shift) {
+  USE(shift);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is8H() && vn.Is8B() && shift == 8) ||
               (vd.Is4S() && vn.Is4H() && shift == 16) ||
               (vd.Is2D() && vn.Is2S() && shift == 32));
-  USE(shift);
   Emit(VFormat(vn) | NEON_SHLL | Rn(vn) | Rd(vd));
 }
 
 
 void Assembler::shll2(const VRegister& vd, const VRegister& vn, int shift) {
   USE(shift);
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is8H() && vn.Is16B() && shift == 8) ||
               (vd.Is4S() && vn.Is8H() && shift == 16) ||
               (vd.Is2D() && vn.Is4S() && shift == 32));
@@ -2756,31 +2886,37 @@
 
 
 void Assembler::fcmeq(const VRegister& vd, const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   NEONFP2RegMisc(vd, vn, NEON_FCMEQ_zero, value);
 }
 
 
 void Assembler::fcmge(const VRegister& vd, const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   NEONFP2RegMisc(vd, vn, NEON_FCMGE_zero, value);
 }
 
 
 void Assembler::fcmgt(const VRegister& vd, const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   NEONFP2RegMisc(vd, vn, NEON_FCMGT_zero, value);
 }
 
 
 void Assembler::fcmle(const VRegister& vd, const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   NEONFP2RegMisc(vd, vn, NEON_FCMLE_zero, value);
 }
 
 
 void Assembler::fcmlt(const VRegister& vd, const VRegister& vn, double value) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   NEONFP2RegMisc(vd, vn, NEON_FCMLT_zero, value);
 }
 
 
 void Assembler::frecpx(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP));
   VIXL_ASSERT(vd.IsScalar());
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is1S() || vd.Is1D());
@@ -2845,12 +2981,13 @@
   V(uqrshl,   NEON_UQRSHL,   true)
 // clang-format on
 
-#define DEFINE_ASM_FUNC(FN, OP, AS)         \
-  void Assembler::FN(const VRegister& vd,   \
-                     const VRegister& vn,   \
-                     const VRegister& vm) { \
-    VIXL_ASSERT(AS);                        \
-    NEON3Same(vd, vn, vm, OP);              \
+#define DEFINE_ASM_FUNC(FN, OP, AS)          \
+  void Assembler::FN(const VRegister& vd,    \
+                     const VRegister& vn,    \
+                     const VRegister& vm) {  \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON)); \
+    VIXL_ASSERT(AS);                         \
+    NEON3Same(vd, vn, vm, OP);               \
   }
 NEON_3SAME_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
@@ -2883,26 +3020,32 @@
   V(fminnmp, NEON_FMINNMP, 0)
 // clang-format on
 
-#define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)             \
-  void Assembler::FN(const VRegister& vd,               \
-                     const VRegister& vn,               \
-                     const VRegister& vm) {             \
-    Instr op;                                           \
-    if ((SCA_OP != 0) && vd.IsScalar()) {               \
-      VIXL_ASSERT(vd.Is1S() || vd.Is1D());              \
-      op = SCA_OP;                                      \
-    } else {                                            \
-      VIXL_ASSERT(vd.IsVector());                       \
-      VIXL_ASSERT(vd.Is2S() || vd.Is2D() || vd.Is4S()); \
-      op = VEC_OP;                                      \
-    }                                                   \
-    NEONFP3Same(vd, vn, vm, op);                        \
+#define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)                          \
+  void Assembler::FN(const VRegister& vd,                            \
+                     const VRegister& vn,                            \
+                     const VRegister& vm) {                          \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP));                           \
+    Instr op;                                                        \
+    if ((SCA_OP != 0) && vd.IsScalar()) {                            \
+      if ((SCA_OP & NEONScalar3SameFMask) == NEONScalar3SameFixed) { \
+        VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));                     \
+      }                                                              \
+      VIXL_ASSERT(vd.Is1S() || vd.Is1D());                           \
+      op = SCA_OP;                                                   \
+    } else {                                                         \
+      VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));                       \
+      VIXL_ASSERT(vd.IsVector());                                    \
+      VIXL_ASSERT(vd.Is2S() || vd.Is2D() || vd.Is4S());              \
+      op = VEC_OP;                                                   \
+    }                                                                \
+    NEONFP3Same(vd, vn, vm, op);                                     \
   }
 NEON_FP3SAME_OP_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
 
 
 void Assembler::addp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1D() && vn.Is2D()));
   Emit(SFormat(vd) | NEON_ADDP_scalar | Rn(vn) | Rd(vd));
 }
@@ -2911,6 +3054,7 @@
 void Assembler::sqrdmlah(const VRegister& vd,
                          const VRegister& vn,
                          const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kRDM));
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   VIXL_ASSERT(vd.IsVector() || !vd.IsQ());
 
@@ -2929,6 +3073,7 @@
 void Assembler::sqrdmlsh(const VRegister& vd,
                          const VRegister& vn,
                          const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kRDM));
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   VIXL_ASSERT(vd.IsVector() || !vd.IsQ());
 
@@ -2947,6 +3092,7 @@
 void Assembler::sdot(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kDotProduct));
   VIXL_ASSERT(AreSameFormat(vn, vm));
   VIXL_ASSERT((vd.Is2S() && vn.Is8B()) || (vd.Is4S() && vn.Is16B()));
 
@@ -2957,6 +3103,7 @@
 void Assembler::udot(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kDotProduct));
   VIXL_ASSERT(AreSameFormat(vn, vm));
   VIXL_ASSERT((vd.Is2S() && vn.Is8B()) || (vd.Is4S() && vn.Is16B()));
 
@@ -2965,30 +3112,35 @@
 
 
 void Assembler::faddp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
   Emit(FPFormat(vd) | NEON_FADDP_scalar | Rn(vn) | Rd(vd));
 }
 
 
 void Assembler::fmaxp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
   Emit(FPFormat(vd) | NEON_FMAXP_scalar | Rn(vn) | Rd(vd));
 }
 
 
 void Assembler::fminp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
   Emit(FPFormat(vd) | NEON_FMINP_scalar | Rn(vn) | Rd(vd));
 }
 
 
 void Assembler::fmaxnmp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
   Emit(FPFormat(vd) | NEON_FMAXNMP_scalar | Rn(vn) | Rd(vd));
 }
 
 
 void Assembler::fminnmp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));
   VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
   Emit(FPFormat(vd) | NEON_FMINNMP_scalar | Rn(vn) | Rd(vd));
 }
@@ -3000,6 +3152,7 @@
                       const VRegister& vm,
                       int vm_index,
                       int rot) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kFcma));
   VIXL_ASSERT(vd.IsVector() && AreSameFormat(vd, vn));
   VIXL_ASSERT((vm.IsH() && (vd.Is8H() || vd.Is4H())) ||
               (vm.IsS() && vd.Is4S()));
@@ -3014,6 +3167,7 @@
                       const VRegister& vn,
                       const VRegister& vm,
                       int rot) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kFcma));
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   VIXL_ASSERT(vd.IsVector() && !vd.IsLaneSizeB());
   Emit(VFormat(vd) | Rm(vm) | NEON_FCMLA | ImmRotFcmlaVec(rot) | Rn(vn) |
@@ -3026,6 +3180,7 @@
                       const VRegister& vn,
                       const VRegister& vm,
                       int rot) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kFcma));
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   VIXL_ASSERT(vd.IsVector() && !vd.IsLaneSizeB());
   Emit(VFormat(vd) | Rm(vm) | NEON_FCADD | ImmRotFcadd(rot) | Rn(vn) | Rd(vd));
@@ -3033,11 +3188,13 @@
 
 
 void Assembler::orr(const VRegister& vd, const int imm8, const int left_shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_ORR);
 }
 
 
 void Assembler::mov(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   if (vd.IsD()) {
     orr(vd.V8B(), vn.V8B(), vn.V8B());
@@ -3049,6 +3206,7 @@
 
 
 void Assembler::bic(const VRegister& vd, const int imm8, const int left_shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_BIC);
 }
 
@@ -3057,6 +3215,7 @@
                      const uint64_t imm,
                      Shift shift,
                      const int shift_amount) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((shift == LSL) || (shift == MSL));
   if (vd.Is2D() || vd.Is1D()) {
     VIXL_ASSERT(shift_amount == 0);
@@ -3088,6 +3247,7 @@
 
 
 void Assembler::mvn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   if (vd.IsD()) {
     not_(vd.V8B(), vn.V8B());
@@ -3102,6 +3262,7 @@
                      const int imm8,
                      Shift shift,
                      const int shift_amount) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((shift == LSL) || (shift == MSL));
   if (shift == LSL) {
     NEONModifiedImmShiftLsl(vd, imm8, shift_amount, NEONModifiedImmediate_MVNI);
@@ -3190,6 +3351,7 @@
                      const VRegister& vn,
                      const VRegister& vm,
                      int vm_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kDotProduct));
   VIXL_ASSERT((vd.Is2S() && vn.Is8B() && vm.Is1S4B()) ||
               (vd.Is4S() && vn.Is16B() && vm.Is1S4B()));
 
@@ -3203,6 +3365,7 @@
                      const VRegister& vn,
                      const VRegister& vm,
                      int vm_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kDotProduct));
   VIXL_ASSERT((vd.Is2S() && vn.Is8B() && vm.Is1S4B()) ||
               (vd.Is4S() && vn.Is16B() && vm.Is1S4B()));
 
@@ -3213,30 +3376,46 @@
 
 
 // clang-format off
-#define NEON_BYELEMENT_LIST(V)                         \
-  V(mul,      NEON_MUL_byelement,      vn.IsVector())  \
-  V(mla,      NEON_MLA_byelement,      vn.IsVector())  \
-  V(mls,      NEON_MLS_byelement,      vn.IsVector())  \
-  V(sqdmulh,  NEON_SQDMULH_byelement,  true)           \
-  V(sqrdmulh, NEON_SQRDMULH_byelement, true)           \
-  V(sqrdmlah, NEON_SQRDMLAH_byelement, true)           \
-  V(sqrdmlsh, NEON_SQRDMLSH_byelement, true)
+#define NEON_BYELEMENT_LIST(V)                        \
+  V(mul,      NEON_MUL_byelement,      vn.IsVector()) \
+  V(mla,      NEON_MLA_byelement,      vn.IsVector()) \
+  V(mls,      NEON_MLS_byelement,      vn.IsVector()) \
+  V(sqdmulh,  NEON_SQDMULH_byelement,  true)          \
+  V(sqrdmulh, NEON_SQRDMULH_byelement, true)          \
 // clang-format on
 
-
-#define DEFINE_ASM_FUNC(FN, OP, AS)          \
-  void Assembler::FN(const VRegister& vd,    \
-                     const VRegister& vn,    \
-                     const VRegister& vm,    \
-                     int vm_index) {         \
-    VIXL_ASSERT(AS);                         \
-    NEONByElement(vd, vn, vm, vm_index, OP); \
+#define DEFINE_ASM_FUNC(FN, OP, AS)                     \
+  void Assembler::FN(const VRegister& vd,               \
+                     const VRegister& vn,               \
+                     const VRegister& vm,               \
+                     int vm_index) {                    \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));            \
+    VIXL_ASSERT(AS);                                    \
+    NEONByElement(vd, vn, vm, vm_index, OP);            \
   }
 NEON_BYELEMENT_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
 
 
 // clang-format off
+#define NEON_BYELEMENT_RDM_LIST(V)     \
+  V(sqrdmlah, NEON_SQRDMLAH_byelement) \
+  V(sqrdmlsh, NEON_SQRDMLSH_byelement)
+// clang-format on
+
+#define DEFINE_ASM_FUNC(FN, OP)                                 \
+  void Assembler::FN(const VRegister& vd,                       \
+                     const VRegister& vn,                       \
+                     const VRegister& vm,                       \
+                     int vm_index) {                            \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kRDM)); \
+    NEONByElement(vd, vn, vm, vm_index, OP);                    \
+  }
+NEON_BYELEMENT_RDM_LIST(DEFINE_ASM_FUNC)
+#undef DEFINE_ASM_FUNC
+
+
+// clang-format off
 #define NEON_FPBYELEMENT_LIST(V) \
   V(fmul,  NEON_FMUL_byelement)  \
   V(fmla,  NEON_FMLA_byelement)  \
@@ -3244,13 +3423,13 @@
   V(fmulx, NEON_FMULX_byelement)
 // clang-format on
 
-
-#define DEFINE_ASM_FUNC(FN, OP)                \
-  void Assembler::FN(const VRegister& vd,      \
-                     const VRegister& vn,      \
-                     const VRegister& vm,      \
-                     int vm_index) {           \
-    NEONFPByElement(vd, vn, vm, vm_index, OP); \
+#define DEFINE_ASM_FUNC(FN, OP)                                \
+  void Assembler::FN(const VRegister& vd,                      \
+                     const VRegister& vn,                      \
+                     const VRegister& vm,                      \
+                     int vm_index) {                           \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON)); \
+    NEONFPByElement(vd, vn, vm, vm_index, OP);                 \
   }
 NEON_FPBYELEMENT_LIST(DEFINE_ASM_FUNC)
 #undef DEFINE_ASM_FUNC
@@ -3284,6 +3463,7 @@
                      const VRegister& vn,     \
                      const VRegister& vm,     \
                      int vm_index) {          \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));  \
     VIXL_ASSERT(AS);                          \
     NEONByElementL(vd, vn, vm, vm_index, OP); \
   }
@@ -3292,33 +3472,39 @@
 
 
 void Assembler::suqadd(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEON2RegMisc(vd, vn, NEON_SUQADD);
 }
 
 
 void Assembler::usqadd(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEON2RegMisc(vd, vn, NEON_USQADD);
 }
 
 
 void Assembler::abs(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_ABS);
 }
 
 
 void Assembler::sqabs(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEON2RegMisc(vd, vn, NEON_SQABS);
 }
 
 
 void Assembler::neg(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEON2RegMisc(vd, vn, NEON_NEG);
 }
 
 
 void Assembler::sqneg(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEON2RegMisc(vd, vn, NEON_SQNEG);
 }
 
@@ -3326,6 +3512,7 @@
 void Assembler::NEONXtn(const VRegister& vd,
                         const VRegister& vn,
                         NEON2RegMiscOp vop) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   Instr format, op = vop;
   if (vd.IsScalar()) {
     VIXL_ASSERT((vd.Is1B() && vn.Is1H()) || (vd.Is1H() && vn.Is1S()) ||
@@ -3343,48 +3530,56 @@
 
 
 void Assembler::xtn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() && vd.IsD());
   NEONXtn(vd, vn, NEON_XTN);
 }
 
 
 void Assembler::xtn2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() && vd.IsQ());
   NEONXtn(vd, vn, NEON_XTN);
 }
 
 
 void Assembler::sqxtn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsScalar() || vd.IsD());
   NEONXtn(vd, vn, NEON_SQXTN);
 }
 
 
 void Assembler::sqxtn2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() && vd.IsQ());
   NEONXtn(vd, vn, NEON_SQXTN);
 }
 
 
 void Assembler::sqxtun(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsScalar() || vd.IsD());
   NEONXtn(vd, vn, NEON_SQXTUN);
 }
 
 
 void Assembler::sqxtun2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() && vd.IsQ());
   NEONXtn(vd, vn, NEON_SQXTUN);
 }
 
 
 void Assembler::uqxtn(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsScalar() || vd.IsD());
   NEONXtn(vd, vn, NEON_UQXTN);
 }
 
 
 void Assembler::uqxtn2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() && vd.IsQ());
   NEONXtn(vd, vn, NEON_UQXTN);
 }
@@ -3392,6 +3587,7 @@
 
 // NEON NOT and RBIT are distinguised by bit 22, the bottom bit of "size".
 void Assembler::not_(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B());
   Emit(VFormat(vd) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
@@ -3399,6 +3595,7 @@
 
 
 void Assembler::rbit(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B());
   Emit(VFormat(vn) | (1 << NEONSize_offset) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
@@ -3409,6 +3606,7 @@
                     const VRegister& vn,
                     const VRegister& vm,
                     int index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn, vm));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B());
   VIXL_ASSERT((0 <= index) && (index < vd.GetLanes()));
@@ -3417,6 +3615,7 @@
 
 
 void Assembler::dup(const VRegister& vd, const VRegister& vn, int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   Instr q, scalar;
 
   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
@@ -3453,12 +3652,14 @@
 
 
 void Assembler::mov(const VRegister& vd, const VRegister& vn, int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsScalar());
   dup(vd, vn, vn_index);
 }
 
 
 void Assembler::dup(const VRegister& vd, const Register& rn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(!vd.Is1D());
   VIXL_ASSERT(vd.Is2D() == rn.IsX());
   int q = vd.IsD() ? 0 : NEON_Q;
@@ -3470,6 +3671,7 @@
                     int vd_index,
                     const VRegister& vn,
                     int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
   // number of lanes, and T is b, h, s or d.
@@ -3506,11 +3708,13 @@
                     int vd_index,
                     const VRegister& vn,
                     int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   ins(vd, vd_index, vn, vn_index);
 }
 
 
 void Assembler::ins(const VRegister& vd, int vd_index, const Register& rn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
   // number of lanes, and T is b, h, s or d.
   int lane_size = vd.GetLaneSizeInBytes();
@@ -3543,11 +3747,13 @@
 
 
 void Assembler::mov(const VRegister& vd, int vd_index, const Register& rn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   ins(vd, vd_index, rn);
 }
 
 
 void Assembler::umov(const Register& rd, const VRegister& vn, int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
   // number of lanes, and T is b, h, s or d.
   int lane_size = vn.GetLaneSizeInBytes();
@@ -3582,12 +3788,14 @@
 
 
 void Assembler::mov(const Register& rd, const VRegister& vn, int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.GetSizeInBytes() >= 4);
   umov(rd, vn, vn_index);
 }
 
 
 void Assembler::smov(const Register& rd, const VRegister& vn, int vn_index) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
   // number of lanes, and T is b, h, s.
   int lane_size = vn.GetLaneSizeInBytes();
@@ -3616,6 +3824,7 @@
 
 
 void Assembler::cls(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(!vd.Is1D() && !vd.Is2D());
   Emit(VFormat(vn) | NEON_CLS | Rn(vn) | Rd(vd));
@@ -3623,6 +3832,7 @@
 
 
 void Assembler::clz(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(!vd.Is1D() && !vd.Is2D());
   Emit(VFormat(vn) | NEON_CLZ | Rn(vn) | Rd(vd));
@@ -3630,6 +3840,7 @@
 
 
 void Assembler::cnt(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B());
   Emit(VFormat(vn) | NEON_CNT | Rn(vn) | Rd(vd));
@@ -3637,6 +3848,7 @@
 
 
 void Assembler::rev16(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B());
   Emit(VFormat(vn) | NEON_REV16 | Rn(vn) | Rd(vd));
@@ -3644,6 +3856,7 @@
 
 
 void Assembler::rev32(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is8B() || vd.Is16B() || vd.Is4H() || vd.Is8H());
   Emit(VFormat(vn) | NEON_REV32 | Rn(vn) | Rd(vd));
@@ -3651,6 +3864,7 @@
 
 
 void Assembler::rev64(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(!vd.Is1D() && !vd.Is2D());
   Emit(VFormat(vn) | NEON_REV64 | Rn(vn) | Rd(vd));
@@ -3658,6 +3872,7 @@
 
 
 void Assembler::ursqrte(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is2S() || vd.Is4S());
   Emit(VFormat(vn) | NEON_URSQRTE | Rn(vn) | Rd(vd));
@@ -3665,6 +3880,7 @@
 
 
 void Assembler::urecpe(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(AreSameFormat(vd, vn));
   VIXL_ASSERT(vd.Is2S() || vd.Is4S());
   Emit(VFormat(vn) | NEON_URECPE | Rn(vn) | Rd(vd));
@@ -3674,6 +3890,7 @@
 void Assembler::NEONAddlp(const VRegister& vd,
                           const VRegister& vn,
                           NEON2RegMiscOp op) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT((op == NEON_SADDLP) || (op == NEON_UADDLP) ||
               (op == NEON_SADALP) || (op == NEON_UADALP));
 
@@ -3685,21 +3902,25 @@
 
 
 void Assembler::saddlp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAddlp(vd, vn, NEON_SADDLP);
 }
 
 
 void Assembler::uaddlp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAddlp(vd, vn, NEON_UADDLP);
 }
 
 
 void Assembler::sadalp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAddlp(vd, vn, NEON_SADALP);
 }
 
 
 void Assembler::uadalp(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAddlp(vd, vn, NEON_UADALP);
 }
 
@@ -3715,11 +3936,13 @@
 
 
 void Assembler::saddlv(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAcrossLanesL(vd, vn, NEON_SADDLV);
 }
 
 
 void Assembler::uaddlv(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONAcrossLanesL(vd, vn, NEON_UADDLV);
 }
 
@@ -3738,20 +3961,16 @@
 }
 
 
-#define NEON_ACROSSLANES_LIST(V)      \
-  V(fmaxv, NEON_FMAXV, vd.Is1S())     \
-  V(fminv, NEON_FMINV, vd.Is1S())     \
-  V(fmaxnmv, NEON_FMAXNMV, vd.Is1S()) \
-  V(fminnmv, NEON_FMINNMV, vd.Is1S()) \
-  V(addv, NEON_ADDV, true)            \
-  V(smaxv, NEON_SMAXV, true)          \
-  V(sminv, NEON_SMINV, true)          \
-  V(umaxv, NEON_UMAXV, true)          \
+#define NEON_ACROSSLANES_LIST(V) \
+  V(addv, NEON_ADDV, true)       \
+  V(smaxv, NEON_SMAXV, true)     \
+  V(sminv, NEON_SMINV, true)     \
+  V(umaxv, NEON_UMAXV, true)     \
   V(uminv, NEON_UMINV, true)
 
-
 #define DEFINE_ASM_FUNC(FN, OP, AS)                              \
   void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));                     \
     VIXL_ASSERT(AS);                                             \
     NEONAcrossLanes(vd, vn, OP);                                 \
   }
@@ -3759,6 +3978,22 @@
 #undef DEFINE_ASM_FUNC
 
 
+#define NEON_ACROSSLANES_FP_LIST(V)   \
+  V(fmaxv, NEON_FMAXV, vd.Is1S())     \
+  V(fminv, NEON_FMINV, vd.Is1S())     \
+  V(fmaxnmv, NEON_FMAXNMV, vd.Is1S()) \
+  V(fminnmv, NEON_FMINNMV, vd.Is1S())
+
+#define DEFINE_ASM_FUNC(FN, OP, AS)                              \
+  void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
+    VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON));   \
+    VIXL_ASSERT(AS);                                             \
+    NEONAcrossLanes(vd, vn, OP);                                 \
+  }
+NEON_ACROSSLANES_FP_LIST(DEFINE_ASM_FUNC)
+#undef DEFINE_ASM_FUNC
+
+
 void Assembler::NEONPerm(const VRegister& vd,
                          const VRegister& vn,
                          const VRegister& vm,
@@ -3772,6 +4007,7 @@
 void Assembler::trn1(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_TRN1);
 }
 
@@ -3779,6 +4015,7 @@
 void Assembler::trn2(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_TRN2);
 }
 
@@ -3786,6 +4023,7 @@
 void Assembler::uzp1(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_UZP1);
 }
 
@@ -3793,6 +4031,7 @@
 void Assembler::uzp2(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_UZP2);
 }
 
@@ -3800,6 +4039,7 @@
 void Assembler::zip1(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_ZIP1);
 }
 
@@ -3807,6 +4047,7 @@
 void Assembler::zip2(const VRegister& vd,
                      const VRegister& vn,
                      const VRegister& vm) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONPerm(vd, vn, vm, NEON_ZIP2);
 }
 
@@ -3891,221 +4132,259 @@
 
 
 void Assembler::shl(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftLeftImmediate(vd, vn, shift, NEON_SHL);
 }
 
 
 void Assembler::sli(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftLeftImmediate(vd, vn, shift, NEON_SLI);
 }
 
 
 void Assembler::sqshl(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHL_imm);
 }
 
 
 void Assembler::sqshlu(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHLU);
 }
 
 
 void Assembler::uqshl(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   NEONShiftLeftImmediate(vd, vn, shift, NEON_UQSHL_imm);
 }
 
 
 void Assembler::sshll(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsD());
   NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
 }
 
 
 void Assembler::sshll2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsQ());
   NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
 }
 
 
 void Assembler::sxtl(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   sshll(vd, vn, 0);
 }
 
 
 void Assembler::sxtl2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   sshll2(vd, vn, 0);
 }
 
 
 void Assembler::ushll(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsD());
   NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
 }
 
 
 void Assembler::ushll2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsQ());
   NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
 }
 
 
 void Assembler::uxtl(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   ushll(vd, vn, 0);
 }
 
 
 void Assembler::uxtl2(const VRegister& vd, const VRegister& vn) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   ushll2(vd, vn, 0);
 }
 
 
 void Assembler::sri(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_SRI);
 }
 
 
 void Assembler::sshr(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_SSHR);
 }
 
 
 void Assembler::ushr(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_USHR);
 }
 
 
 void Assembler::srshr(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_SRSHR);
 }
 
 
 void Assembler::urshr(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_URSHR);
 }
 
 
 void Assembler::ssra(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_SSRA);
 }
 
 
 void Assembler::usra(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_USRA);
 }
 
 
 void Assembler::srsra(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_SRSRA);
 }
 
 
 void Assembler::ursra(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsVector() || vd.Is1D());
   NEONShiftRightImmediate(vd, vn, shift, NEON_URSRA);
 }
 
 
 void Assembler::shrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsD());
   NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
 }
 
 
 void Assembler::shrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
 }
 
 
 void Assembler::rshrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsD());
   NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
 }
 
 
 void Assembler::rshrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
 }
 
 
 void Assembler::sqshrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
 }
 
 
 void Assembler::sqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
 }
 
 
 void Assembler::sqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
 }
 
 
 void Assembler::sqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
 }
 
 
 void Assembler::sqshrun(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
 }
 
 
 void Assembler::sqshrun2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
 }
 
 
 void Assembler::sqrshrun(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
 }
 
 
 void Assembler::sqrshrun2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
 }
 
 
 void Assembler::uqshrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
 }
 
 
 void Assembler::uqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
 }
 
 
 void Assembler::uqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
   NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
 }
 
 
 void Assembler::uqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
+  VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
   VIXL_ASSERT(vn.IsVector() && vd.IsQ());
   NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
 }
@@ -4594,6 +4873,7 @@
                           const MemOperand& addr,
                           LoadStoreOp op,
                           LoadStoreScalingOption option) {
+  VIXL_ASSERT(CPUHas(rt));
   Emit(op | Rt(rt) | LoadStoreMemOperand(addr, CalcLSDataSize(op), option));
 }
 
@@ -5052,6 +5332,31 @@
 }
 
 
+bool Assembler::CPUHas(const CPURegister& rt) const {
+  // Core registers are available without any particular CPU features.
+  if (rt.IsRegister()) return true;
+  VIXL_ASSERT(rt.IsVRegister());
+  // The architecture does not allow FP and NEON to be implemented separately,
+  // but we can crudely categorise them based on register size, since FP only
+  // uses D, S and (occasionally) H registers.
+  if (rt.IsH() || rt.IsS() || rt.IsD()) {
+    return CPUHas(CPUFeatures::kFP) || CPUHas(CPUFeatures::kNEON);
+  }
+  VIXL_ASSERT(rt.IsB() || rt.IsQ());
+  return CPUHas(CPUFeatures::kNEON);
+}
+
+
+bool Assembler::CPUHas(const CPURegister& rt, const CPURegister& rt2) const {
+  // This is currently only used for loads and stores, where rt and rt2 must
+  // have the same size and type. We could extend this to cover other cases if
+  // necessary, but for now we can avoid checking both registers.
+  VIXL_ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  return CPUHas(rt);
+}
+
+
 bool AreAliased(const CPURegister& reg1,
                 const CPURegister& reg2,
                 const CPURegister& reg3,
diff --git a/src/aarch64/assembler-aarch64.h b/src/aarch64/assembler-aarch64.h
index 4c4cb7f..9ccd2c5 100644
--- a/src/aarch64/assembler-aarch64.h
+++ b/src/aarch64/assembler-aarch64.h
@@ -29,6 +29,7 @@
 
 #include "../assembler-base-vixl.h"
 #include "../code-generation-scopes-vixl.h"
+#include "../cpu-features.h"
 #include "../globals-vixl.h"
 #include "../invalset-vixl.h"
 #include "../utils-vixl.h"
@@ -405,15 +406,19 @@
  public:
   explicit Assembler(
       PositionIndependentCodeOption pic = PositionIndependentCode)
-      : pic_(pic) {}
+      : pic_(pic), cpu_features_(CPUFeatures::AArch64LegacyBaseline()) {}
   explicit Assembler(
       size_t capacity,
       PositionIndependentCodeOption pic = PositionIndependentCode)
-      : AssemblerBase(capacity), pic_(pic) {}
+      : AssemblerBase(capacity),
+        pic_(pic),
+        cpu_features_(CPUFeatures::AArch64LegacyBaseline()) {}
   Assembler(byte* buffer,
             size_t capacity,
             PositionIndependentCodeOption pic = PositionIndependentCode)
-      : AssemblerBase(buffer, capacity), pic_(pic) {}
+      : AssemblerBase(buffer, capacity),
+        pic_(pic),
+        cpu_features_(CPUFeatures::AArch64LegacyBaseline()) {}
 
   // Upon destruction, the code will assert that one of the following is true:
   //  * The Assembler object has not been used.
@@ -3286,6 +3291,12 @@
     return GetPic();
   }
 
+  CPUFeatures* GetCPUFeatures() { return &cpu_features_; }
+
+  void SetCPUFeatures(const CPUFeatures& cpu_features) {
+    cpu_features_ = cpu_features;
+  }
+
   bool AllowPageOffsetDependentCode() const {
     return (GetPic() == PageOffsetDependentCode) ||
            (GetPic() == PositionDependentCode);
@@ -3389,6 +3400,23 @@
       const CPURegister& rt, const CPURegister& rt2);
   static LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
 
+  // Convenience pass-through for CPU feature checks.
+  bool CPUHas(CPUFeatures::Feature feature0,
+              CPUFeatures::Feature feature1 = CPUFeatures::kNone,
+              CPUFeatures::Feature feature2 = CPUFeatures::kNone,
+              CPUFeatures::Feature feature3 = CPUFeatures::kNone) const {
+    return cpu_features_.Has(feature0, feature1, feature2, feature3);
+  }
+
+  // Determine whether the target CPU has the specified registers, based on the
+  // currently-enabled CPU features. Presence of a register does not imply
+  // support for arbitrary operations on it. For example, CPUs with FP have H
+  // registers, but most half-precision operations require the FPHalf feature.
+  //
+  // These are used to check CPU features in loads and stores that have the same
+  // entry point for both integer and FP registers.
+  bool CPUHas(const CPURegister& rt) const;
+  bool CPUHas(const CPURegister& rt, const CPURegister& rt2) const;
 
  private:
   static uint32_t FP16ToImm8(float16 imm);
@@ -3552,6 +3580,8 @@
   }
 
   PositionIndependentCodeOption pic_;
+
+  CPUFeatures cpu_features_;
 };
 
 
diff --git a/src/cpu-features.h b/src/cpu-features.h
index 649e46c..a0475cc 100644
--- a/src/cpu-features.h
+++ b/src/cpu-features.h
@@ -90,8 +90,8 @@
 // A representation of the set of features known to be supported by the target
 // device. Each feature is represented by a simple boolean flag.
 //
-//   - TODO: When the Assembler is asked to assemble an instruction, it should
-//     assert (in debug mode) that the necessary features are available.
+//   - When the Assembler is asked to assemble an instruction, it asserts (in
+//     debug mode) that the necessary features are available.
 //
 //   - TODO: The Simulator assumes that all features are available by default,
 //     but it should be possible to configure it to either warn or fail if the
diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc
index aa2e429..7df078c 100644
--- a/test/aarch64/test-assembler-aarch64.cc
+++ b/test/aarch64/test-assembler-aarch64.cc
@@ -103,12 +103,18 @@
   MacroAssembler masm; \
   SETUP_COMMON()
 
+#define SETUP_WITH_FEATURES(...) \
+  MacroAssembler masm;           \
+  SETUP_COMMON();                \
+  masm.SetCPUFeatures(CPUFeatures(__VA_ARGS__))
+
 #define SETUP_CUSTOM(size, pic)                                       \
   byte* buf = new byte[size + CodeBuffer::kDefaultCapacity];          \
   MacroAssembler masm(buf, size + CodeBuffer::kDefaultCapacity, pic); \
   SETUP_COMMON()
 
 #define SETUP_COMMON()                                      \
+  masm.SetCPUFeatures(CPUFeatures());                       \
   masm.SetGenerateSimulatorCode(true);                      \
   Decoder simulator_decoder;                                \
   Simulator simulator(&simulator_decoder);                  \
@@ -124,7 +130,11 @@
 #define START()                                                               \
   masm.Reset();                                                               \
   simulator.ResetState();                                                     \
-  __ PushCalleeSavedRegisters();                                              \
+  {                                                                           \
+    /* PushCalleeSavedRegisters() uses NEON stores. */                        \
+    CPUFeaturesScope cpu(&masm, CPUFeatures::kNEON);                          \
+    __ PushCalleeSavedRegisters();                                            \
+  }                                                                           \
   {                                                                           \
     int trace_parameters = 0;                                                 \
     if (Test::trace_reg()) trace_parameters |= LOG_STATE;                     \
@@ -142,17 +152,21 @@
   /* Avoid unused-variable warnings in case a test never calls RUN(). */      \
   USE(offset_after_infrastructure_start)
 
-#define END()                                                            \
-  offset_before_infrastructure_end = masm.GetCursorOffset();             \
-  /* Avoid unused-variable warnings in case a test never calls RUN(). */ \
-  USE(offset_before_infrastructure_end);                                 \
-  if (Test::instruction_stats()) {                                       \
-    __ DisableInstrumentation();                                         \
-  }                                                                      \
-  __ Trace(LOG_ALL, TRACE_DISABLE);                                      \
-  core.Dump(&masm);                                                      \
-  __ PopCalleeSavedRegisters();                                          \
-  __ Ret();                                                              \
+#define END()                                                             \
+  offset_before_infrastructure_end = masm.GetCursorOffset();              \
+  /* Avoid unused-variable warnings in case a test never calls RUN(). */  \
+  USE(offset_before_infrastructure_end);                                  \
+  if (Test::instruction_stats()) {                                        \
+    __ DisableInstrumentation();                                          \
+  }                                                                       \
+  __ Trace(LOG_ALL, TRACE_DISABLE);                                       \
+  {                                                                       \
+    /* Dump() and PopCalleeSavedRegisters() use NEON loads and stores. */ \
+    CPUFeaturesScope cpu(&masm, CPUFeatures::kNEON);                      \
+    core.Dump(&masm);                                                     \
+    __ PopCalleeSavedRegisters();                                         \
+  }                                                                       \
+  __ Ret();                                                               \
   masm.FinalizeCode()
 
 #define RUN()    \
@@ -171,6 +185,11 @@
   MacroAssembler masm; \
   SETUP_COMMON()
 
+#define SETUP_WITH_FEATURES(...) \
+  MacroAssembler masm;           \
+  SETUP_COMMON();                \
+  masm.SetCPUFeatures(CPUFeatures(__VA_ARGS__))
+
 #define SETUP_CUSTOM(size, pic)                                         \
   byte* buffer =                                                        \
       reinterpret_cast<byte*>(mmap(NULL,                                \
@@ -183,30 +202,39 @@
   MacroAssembler masm(buffer, buffer_size, pic);                        \
   SETUP_COMMON()
 
-#define SETUP_COMMON()                         \
-  Disassembler disasm;                         \
-  Decoder disassembler_decoder;                \
-  disassembler_decoder.AppendVisitor(&disasm); \
-  masm.SetGenerateSimulatorCode(false);        \
-  RegisterDump core;                           \
-  CPU::SetUp();                                \
-  ptrdiff_t offset_after_infrastructure_start; \
+#define SETUP_COMMON()                               \
+  Disassembler disasm;                               \
+  Decoder disassembler_decoder;                      \
+  disassembler_decoder.AppendVisitor(&disasm);       \
+  masm.GetCPUFeatures()->Remove(CPUFeatures::All()); \
+  masm.SetGenerateSimulatorCode(false);              \
+  RegisterDump core;                                 \
+  CPU::SetUp();                                      \
+  ptrdiff_t offset_after_infrastructure_start;       \
   ptrdiff_t offset_before_infrastructure_end
 
 #define START()                                                          \
   masm.Reset();                                                          \
-  __ PushCalleeSavedRegisters();                                         \
+  {                                                                      \
+    /* PushCalleeSavedRegisters() uses NEON stores. */                   \
+    CPUFeaturesScope cpu(&masm, CPUFeatures::kNEON);                     \
+    __ PushCalleeSavedRegisters();                                       \
+  }                                                                      \
   offset_after_infrastructure_start = masm.GetCursorOffset();            \
   /* Avoid unused-variable warnings in case a test never calls RUN(). */ \
   USE(offset_after_infrastructure_start)
 
-#define END()                                                            \
-  offset_before_infrastructure_end = masm.GetCursorOffset();             \
-  /* Avoid unused-variable warnings in case a test never calls RUN(). */ \
-  USE(offset_before_infrastructure_end);                                 \
-  core.Dump(&masm);                                                      \
-  __ PopCalleeSavedRegisters();                                          \
-  __ Ret();                                                              \
+#define END()                                                             \
+  offset_before_infrastructure_end = masm.GetCursorOffset();              \
+  /* Avoid unused-variable warnings in case a test never calls RUN(). */  \
+  USE(offset_before_infrastructure_end);                                  \
+  {                                                                       \
+    /* Dump() and PopCalleeSavedRegisters() use NEON loads and stores. */ \
+    CPUFeaturesScope cpu(&masm, CPUFeatures::kNEON);                      \
+    core.Dump(&masm);                                                     \
+    __ PopCalleeSavedRegisters();                                         \
+  }                                                                       \
+  __ Ret();                                                               \
   masm.FinalizeCode()
 
 // Execute the generated code from the memory area.
@@ -2841,7 +2869,7 @@
 
 
 TEST(load_store_float) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   float src[3] = {1.0, 2.0, 3.0};
   float dst[3] = {0.0, 0.0, 0.0};
@@ -2883,7 +2911,7 @@
 
 
 TEST(load_store_double) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   double src[3] = {1.0, 2.0, 3.0};
   double dst[3] = {0.0, 0.0, 0.0};
@@ -2925,7 +2953,7 @@
 
 
 TEST(load_store_b) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[3] = {0x12, 0x23, 0x34};
   uint8_t dst[3] = {0, 0, 0};
@@ -2967,7 +2995,7 @@
 
 
 TEST(load_store_h) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint16_t src[3] = {0x1234, 0x2345, 0x3456};
   uint16_t dst[3] = {0, 0, 0};
@@ -3009,7 +3037,7 @@
 
 
 TEST(load_store_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[48] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe, 0x01, 0x23,
                      0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x21, 0x43, 0x65, 0x87,
@@ -3059,7 +3087,7 @@
 
 
 TEST(load_store_v_regoffset) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3144,7 +3172,7 @@
 
 
 TEST(neon_ld1_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[32 + 5];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3194,7 +3222,7 @@
 
 
 TEST(neon_ld1_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[32 + 5];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3263,7 +3291,7 @@
 
 
 TEST(neon_ld1_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3306,7 +3334,7 @@
 
 
 TEST(neon_ld1_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3363,7 +3391,7 @@
 
 
 TEST(neon_ld1_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3426,7 +3454,7 @@
 }
 
 TEST(neon_ld2_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3460,7 +3488,7 @@
 }
 
 TEST(neon_ld2_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[32 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3505,7 +3533,7 @@
 
 
 TEST(neon_ld2_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3544,7 +3572,7 @@
 
 
 TEST(neon_ld2_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3591,7 +3619,7 @@
 
 
 TEST(neon_ld2_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3671,7 +3699,7 @@
 
 
 TEST(neon_ld2_lane_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3767,7 +3795,7 @@
 
 
 TEST(neon_ld2_alllanes) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3815,7 +3843,7 @@
 
 
 TEST(neon_ld2_alllanes_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3858,7 +3886,7 @@
 
 
 TEST(neon_ld3_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3897,7 +3925,7 @@
 
 
 TEST(neon_ld3_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[32 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3948,7 +3976,7 @@
 
 
 TEST(neon_ld3_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -3992,7 +4020,7 @@
 
 
 TEST(neon_ld3_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4044,7 +4072,7 @@
 
 
 TEST(neon_ld3_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4130,7 +4158,7 @@
 
 
 TEST(neon_ld3_lane_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4238,7 +4266,7 @@
 
 
 TEST(neon_ld3_alllanes) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4293,7 +4321,7 @@
 
 
 TEST(neon_ld3_alllanes_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4344,7 +4372,7 @@
 
 
 TEST(neon_ld4_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4387,7 +4415,7 @@
 
 
 TEST(neon_ld4_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[32 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4463,7 +4491,7 @@
 
 
 TEST(neon_ld4_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4511,7 +4539,7 @@
 
 
 TEST(neon_ld4_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 4];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4589,7 +4617,7 @@
 
 
 TEST(neon_ld4_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4696,7 +4724,7 @@
 
 
 TEST(neon_ld4_lane_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4841,7 +4869,7 @@
 
 
 TEST(neon_ld4_alllanes) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4905,7 +4933,7 @@
 
 
 TEST(neon_ld4_alllanes_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -4992,7 +5020,7 @@
 
 
 TEST(neon_st1_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5043,7 +5071,7 @@
 
 
 TEST(neon_st2_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   // Struct size * addressing modes * element sizes * vector size.
   uint8_t dst[2 * 2 * 4 * 16];
@@ -5136,7 +5164,7 @@
 
 
 TEST(neon_st3_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   // Struct size * addressing modes * element sizes * vector size.
   uint8_t dst[3 * 2 * 4 * 16];
@@ -5235,7 +5263,7 @@
 
 
 TEST(neon_st4_lane) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   // Struct size * element sizes * vector size.
   uint8_t dst[4 * 4 * 16];
@@ -5318,7 +5346,7 @@
 
 
 TEST(neon_ld1_lane_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5396,7 +5424,7 @@
 
 
 TEST(neon_st1_lane_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5443,7 +5471,7 @@
 
 
 TEST(neon_ld1_alllanes) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5486,7 +5514,7 @@
 
 
 TEST(neon_ld1_alllanes_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5522,7 +5550,7 @@
 
 
 TEST(neon_st1_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[14 * kDRegSizeInBytes];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5579,7 +5607,7 @@
 
 
 TEST(neon_st1_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 14 * kDRegSizeInBytes];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5644,7 +5672,7 @@
 
 
 TEST(neon_st1_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 160];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5696,7 +5724,7 @@
 
 
 TEST(neon_st1_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[64 + 160];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5757,7 +5785,7 @@
 
 
 TEST(neon_st2_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[4 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5797,7 +5825,7 @@
 
 
 TEST(neon_st2_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[4 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5835,7 +5863,7 @@
 
 
 TEST(neon_st2_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[5 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5876,7 +5904,7 @@
 
 
 TEST(neon_st2_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[5 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5918,7 +5946,7 @@
 
 
 TEST(neon_st3_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[3 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5956,7 +5984,7 @@
 
 
 TEST(neon_st3_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[4 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -5997,7 +6025,7 @@
 
 
 TEST(neon_st3_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[6 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6044,7 +6072,7 @@
 
 
 TEST(neon_st3_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[7 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6091,7 +6119,7 @@
 
 
 TEST(neon_st4_d) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[4 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6134,7 +6162,7 @@
 
 
 TEST(neon_st4_d_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[5 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6186,7 +6214,7 @@
 
 
 TEST(neon_st4_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[7 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6237,7 +6265,7 @@
 
 
 TEST(neon_st4_q_postindex) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint8_t src[9 * 16];
   for (unsigned i = 0; i < sizeof(src); i++) {
@@ -6301,7 +6329,7 @@
 
 
 TEST(neon_destructive_minmaxp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   __ Movi(v0.V2D(), 0, 0x2222222233333333);
@@ -6367,7 +6395,7 @@
 
 
 TEST(neon_destructive_tbl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   __ Movi(v0.V2D(), 0x0041424334353627, 0x28291a1b1c0d0e0f);
@@ -6423,7 +6451,7 @@
 
 
 TEST(neon_destructive_tbx) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   __ Movi(v0.V2D(), 0x0041424334353627, 0x28291a1b1c0d0e0f);
@@ -6479,7 +6507,7 @@
 
 
 TEST(neon_destructive_fcvtl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(v0.V2D(), 0x400000003f800000, 0xbf800000c0000000);
@@ -6517,7 +6545,7 @@
 
 
 TEST(ldp_stp_float) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   float src[2] = {1.0, 2.0};
   float dst[3] = {0.0, 0.0, 0.0};
@@ -6546,7 +6574,7 @@
 
 
 TEST(ldp_stp_double) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   double src[2] = {1.0, 2.0};
   double dst[3] = {0.0, 0.0, 0.0};
@@ -6575,7 +6603,7 @@
 
 
 TEST(ldp_stp_quad) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint64_t src[4] = {0x0123456789abcdef,
                      0xaaaaaaaa55555555,
@@ -6723,7 +6751,7 @@
 
 
 TEST(ldnp_stnp_offset) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   uint64_t src[4] = {0x0011223344556677,
                      0x8899aabbccddeeff,
@@ -6801,7 +6829,7 @@
 
 
 TEST(ldnp_stnp_offset_float) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   float src[3] = {1.2, 2.3, 3.4};
   float dst[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
@@ -6849,7 +6877,7 @@
 
 
 TEST(ldnp_stnp_offset_double) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   double src[3] = {1.2, 2.3, 3.4};
   double dst[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
@@ -7198,8 +7226,8 @@
 }
 
 
-TEST(ldur_stur_fp) {
-  SETUP();
+TEST(ldur_stur_neon) {
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   int64_t src[3] = {0x0123456789abcdef, 0x0123456789abcdef, 0x0123456789abcdef};
   int64_t dst[5] = {0, 0, 0, 0, 0};
@@ -7238,7 +7266,7 @@
 
 
 TEST(ldr_literal) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   __ Ldr(x2, 0x1234567890abcdef);
@@ -7265,7 +7293,7 @@
 
 
 TEST(ldr_literal_range) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   // Make sure the pool is empty;
@@ -7326,7 +7354,7 @@
 
 
 TEST(ldr_literal_values_q) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   static const uint64_t kHalfValues[] = {0x8000000000000000,
                                          0x7fffffffffffffff,
@@ -7423,7 +7451,7 @@
 
 template <typename T>
 void LoadFPValueHelper(T values[], int card) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   const bool is_32bits = (sizeof(T) == 4);
   const FPRegister& fp_tgt = is_32bits ? s2 : d2;
@@ -7467,7 +7495,7 @@
 
 
 TEST(ldr_literal_custom) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   Label end_of_pool_before;
   Label end_of_pool_after;
@@ -7556,7 +7584,7 @@
 
 
 TEST(ldr_literal_custom_shared) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   Label end_of_pool_before;
   Label end_of_pool_after;
@@ -7809,7 +7837,7 @@
 
 TEST(load_prfm_literal) {
   // Test literals shared between both prfm and ldr.
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   Label end_of_pool_before;
   Label end_of_pool_after;
@@ -9843,7 +9871,7 @@
 
 
 TEST(fmov_imm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP, CPUFeatures::kFPHalf);
 
   START();
   __ Fmov(s1, 255.0);
@@ -9895,7 +9923,9 @@
 
 
 TEST(fmov_vec_imm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON,
+                      CPUFeatures::kFP,
+                      CPUFeatures::kFPHalf);
 
   START();
 
@@ -9920,7 +9950,9 @@
 
 
 TEST(fmov_reg) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON,
+                      CPUFeatures::kFP,
+                      CPUFeatures::kFPHalf);
 
   START();
 
@@ -9971,7 +10003,7 @@
 
 
 TEST(fadd) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s14, -0.0f);
@@ -10027,7 +10059,7 @@
 
 
 TEST(fsub) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s14, -0.0f);
@@ -10083,7 +10115,7 @@
 
 
 TEST(fmul) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s14, -0.0f);
@@ -10146,7 +10178,8 @@
                              double fmsub,
                              double fnmadd,
                              double fnmsub) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   __ Fmov(d0, n);
@@ -10227,7 +10260,8 @@
                              float fmsub,
                              float fnmadd,
                              float fnmsub) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   __ Fmov(s0, n);
@@ -10498,7 +10532,7 @@
 
 
 TEST(fdiv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s14, -0.0f);
@@ -10638,7 +10672,7 @@
 
 static void FminFmaxDoubleHelper(
     double n, double m, double min, double max, double minnm, double maxnm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(d0, n);
@@ -10742,7 +10776,7 @@
 
 static void FminFmaxFloatHelper(
     float n, float m, float min, float max, float minnm, float maxnm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, n);
@@ -10845,7 +10879,7 @@
 
 
 TEST(fccmp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 0.0);
@@ -10942,7 +10976,7 @@
 
 
 TEST(fcmp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
 
@@ -11041,7 +11075,7 @@
 
 
 TEST(fcsel) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Mov(x16, 0);
@@ -11077,7 +11111,7 @@
 
 
 TEST(fneg) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11121,7 +11155,7 @@
 
 
 TEST(fabs) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, -1.0);
@@ -11157,7 +11191,7 @@
 
 
 TEST(fsqrt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 0.0);
@@ -11213,7 +11247,7 @@
 
 
 TEST(frinta) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11303,7 +11337,7 @@
 TEST(frinti) {
   // VIXL only supports the round-to-nearest FPCR mode, so this test has the
   // same results as frintn.
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11391,7 +11425,7 @@
 
 
 TEST(frintm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11479,7 +11513,7 @@
 
 
 TEST(frintn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11567,7 +11601,7 @@
 
 
 TEST(frintp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11657,7 +11691,7 @@
 TEST(frintx) {
   // VIXL only supports the round-to-nearest FPCR mode, and it doesn't support
   // FP exceptions, so this test has the same results as frintn (and frinti).
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11745,7 +11779,7 @@
 
 
 TEST(frintz) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11827,7 +11861,7 @@
 
 
 TEST(fcvt_ds) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s16, 1.0);
@@ -11896,7 +11930,7 @@
   // Test simple conversions here. Complex behaviour (such as rounding
   // specifics) are tested in the simulator tests.
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(d16, 1.0);
@@ -11962,7 +11996,7 @@
 
 
 TEST(fcvt_half) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   Label done;
@@ -11995,7 +12029,7 @@
       __ Fmov(s1, w1);
       __ Fcvt(d2, h1);
       __ Fcvt(h2, d2);
-      __ Mov(w2, v2.S(), 0);
+      __ Fmov(w2, s2);
       __ Cmp(w1, w2);
       __ B(&fail, ne);
     }
@@ -12066,7 +12100,7 @@
 
 
 TEST(fcvtas) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12170,7 +12204,7 @@
 
 
 TEST(fcvtau) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12269,7 +12303,7 @@
 
 
 TEST(fcvtms) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12373,7 +12407,7 @@
 
 
 TEST(fcvtmu) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12475,7 +12509,7 @@
 
 
 TEST(fcvtns) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12579,7 +12613,7 @@
 
 
 TEST(fcvtnu) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12678,7 +12712,7 @@
 
 
 TEST(fcvtzs) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12781,7 +12815,7 @@
 }
 
 TEST(fcvtzu) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 1.0);
@@ -12883,7 +12917,7 @@
 
 
 TEST(neon_fcvtl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -12922,7 +12956,7 @@
 
 
 TEST(neon_fcvtn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -12958,7 +12992,7 @@
 
 
 TEST(neon_fcvtxn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(v0.V2D(), 0x3e200000be200000, 0x7f800000ff800000);
@@ -13021,7 +13055,8 @@
   double results_scvtf_w[33];
   double results_ucvtf_w[33];
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   __ Mov(x0, reinterpret_cast<uintptr_t>(results_scvtf_x));
@@ -13175,7 +13210,8 @@
   float results_scvtf_w[33];
   float results_ucvtf_w[33];
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   __ Mov(x0, reinterpret_cast<uintptr_t>(results_scvtf_x));
@@ -13426,7 +13462,8 @@
 
 
 TEST(system) {
-  SETUP();
+  // RegisterDump::Dump uses NEON.
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
   RegisterDump before;
 
   START();
@@ -13445,7 +13482,8 @@
 
 
 TEST(zero_dest) {
-  SETUP();
+  // RegisterDump::Dump uses NEON.
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
   RegisterDump before;
 
   START();
@@ -13514,7 +13552,8 @@
 
 
 TEST(zero_dest_setflags) {
-  SETUP();
+  // RegisterDump::Dump uses NEON.
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
   RegisterDump before;
 
   START();
@@ -13879,7 +13918,8 @@
 
 
 TEST(peek_poke_reglist) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
@@ -13969,7 +14009,8 @@
 
 
 TEST(load_store_reglist) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // The literal base is chosen to have two useful properties:
@@ -14355,7 +14396,7 @@
                                   int reg_size,
                                   PushPopMethod push_method,
                                   PushPopMethod pop_method) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
 
@@ -14988,7 +15029,10 @@
 
 
 TEST(printf) {
-  SETUP();
+  // RegisterDump::Dump uses NEON.
+  // Printf uses FP to cast FP arguments to doubles.
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
+
   START();
 
   char const* test_plain_string = "Printf with no arguments.\n";
@@ -15097,7 +15141,9 @@
 
 
 TEST(printf_no_preserve) {
-  SETUP();
+  // PrintfNoPreserve uses FP to cast FP arguments to doubles.
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   char const* test_plain_string = "Printf with no arguments.\n";
@@ -15363,7 +15409,8 @@
   VIXL_ASSERT(IsQuietNaN(sn_proc));
   VIXL_ASSERT(IsQuietNaN(qn_proc));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Execute a number of instructions which all use ProcessNaN, and check that
@@ -15438,7 +15485,8 @@
   VIXL_ASSERT(IsQuietNaN(sn_proc));
   VIXL_ASSERT(IsQuietNaN(qn_proc));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Execute a number of instructions which all use ProcessNaN, and check that
@@ -15504,7 +15552,8 @@
   VIXL_ASSERT(std::isnan(n) || std::isnan(m));
   VIXL_ASSERT(std::isnan(expected));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Execute a number of instructions which all use ProcessNaNs, and check that
@@ -15575,7 +15624,8 @@
   VIXL_ASSERT(std::isnan(n) || std::isnan(m));
   VIXL_ASSERT(std::isnan(expected));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Execute a number of instructions which all use ProcessNaNs, and check that
@@ -15648,7 +15698,8 @@
   bool test_1op = std::isnan(n);
   bool test_2op = std::isnan(n) || std::isnan(m);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Enable Default-NaN mode in the FPCR.
@@ -15775,7 +15826,8 @@
   bool test_1op = std::isnan(n);
   bool test_2op = std::isnan(n) || std::isnan(m);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
+
   START();
 
   // Enable Default-NaN mode in the FPCR.
@@ -15957,7 +16009,8 @@
   uint32_t w[] = {0, 0x12345678, 0};
   uint64_t x[] = {0, 0x123456789abcdef0, 0};
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kLORegions);
+
   START();
 
   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
@@ -16497,7 +16550,8 @@
   uint64_t* data7_aligned = AlignUp(data7, kXRegSizeInBytes * 2);
   uint64_t* data8_aligned = AlignUp(data8, kXRegSizeInBytes * 2);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
+
   START();
 
   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
@@ -16576,7 +16630,8 @@
   uint64_t* data7_aligned = AlignUp(data7, kXRegSizeInBytes * 2);
   uint64_t* data8_aligned = AlignUp(data8, kXRegSizeInBytes * 2);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
+
   START();
 
   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
@@ -16655,7 +16710,8 @@
   uint64_t* data7_aligned = AlignUp(data7, kXRegSizeInBytes * 2);
   uint64_t* data8_aligned = AlignUp(data8, kXRegSizeInBytes * 2);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
+
   START();
 
   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
@@ -16734,7 +16790,8 @@
   uint64_t* data7_aligned = AlignUp(data7, kXRegSizeInBytes * 2);
   uint64_t* data8_aligned = AlignUp(data8, kXRegSizeInBytes * 2);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
+
   START();
 
   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
@@ -16813,7 +16870,8 @@
   uint64_t* data7_aligned = AlignUp(data7, kXRegSizeInBytes * 2);
   uint64_t* data8_aligned = AlignUp(data8, kXRegSizeInBytes * 2);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
+
   START();
 
   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
@@ -16918,7 +16976,7 @@
 
       memset(dst, 0, kMaxDataLength);
 
-      SETUP();
+      SETUP_WITH_FEATURES(CPUFeatures::kNEON);
       START();
 
       __ Mov(x0, src_tagged);
@@ -17131,7 +17189,7 @@
         dst[k] = 0;
       }
 
-      SETUP();
+      SETUP_WITH_FEATURES(CPUFeatures::kNEON);
       START();
 
       // Each MemOperand must apply a pre-index equal to the size of the
@@ -17302,7 +17360,7 @@
         dst[k] = 0;
       }
 
-      SETUP();
+      SETUP_WITH_FEATURES(CPUFeatures::kNEON);
       START();
 
       int postindex = 2 * kXRegSizeInBytes;
@@ -17473,7 +17531,7 @@
           dst[k] = 0;
         }
 
-        SETUP();
+        SETUP_WITH_FEATURES(CPUFeatures::kNEON);
         START();
 
         __ Mov(x0, src_tagged);
@@ -17572,7 +17630,8 @@
 
   for (int j = 0; j < tag_count; j++) {
     for (int i = 0; i < tag_count; i++) {
-      SETUP();
+      SETUP_WITH_FEATURES(CPUFeatures::kNEON);
+
       uint64_t src_base = reinterpret_cast<uint64_t>(src);
       uint64_t src_tagged = CPU::SetPointerTag(src_base, tags[i]);
       uint64_t offset_tagged = CPU::SetPointerTag(UINT64_C(0), tags[j]);
@@ -17704,7 +17763,7 @@
 }
 
 TEST(neon_3same_addp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -17720,7 +17779,7 @@
 }
 
 TEST(neon_3same_sqdmulh_sqrdmulh) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -17754,7 +17813,7 @@
 }
 
 TEST(neon_byelement_sqdmulh_sqrdmulh) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -17788,7 +17847,7 @@
 }
 
 TEST(neon_3same_sqrdmlah) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRDM);
 
   START();
 
@@ -17821,7 +17880,7 @@
 }
 
 TEST(neon_byelement_sqrdmlah) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRDM);
 
   START();
 
@@ -17853,7 +17912,7 @@
 }
 
 TEST(neon_3same_sqrdmlsh) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRDM);
 
   START();
 
@@ -17885,7 +17944,7 @@
 }
 
 TEST(neon_byelement_sqrdmlsh) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRDM);
 
   START();
 
@@ -17917,7 +17976,7 @@
 }
 
 TEST(neon_3same_sdot_udot) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kDotProduct);
 
   START();
 
@@ -17950,7 +18009,7 @@
 }
 
 TEST(neon_byelement_sdot_udot) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kDotProduct);
 
   START();
 
@@ -17983,7 +18042,7 @@
 
 
 TEST(neon_2regmisc_saddlp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18011,7 +18070,7 @@
 }
 
 TEST(neon_2regmisc_uaddlp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18039,7 +18098,7 @@
 }
 
 TEST(neon_2regmisc_sadalp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18077,7 +18136,7 @@
 }
 
 TEST(neon_2regmisc_uadalp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18115,7 +18174,7 @@
 }
 
 TEST(neon_3same_mul) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18139,7 +18198,7 @@
 
 
 TEST(neon_3same_absdiff) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18165,7 +18224,7 @@
 
 
 TEST(neon_byelement_mul) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18220,7 +18279,7 @@
 
 
 TEST(neon_byelement_mull) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18277,7 +18336,7 @@
 
 
 TEST(neon_byelement_sqdmull) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18325,7 +18384,7 @@
 
 
 TEST(neon_3diff_absdiff) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18353,7 +18412,7 @@
 
 
 TEST(neon_3diff_sqdmull) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18383,7 +18442,7 @@
 
 
 TEST(neon_3diff_sqdmlal) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18420,7 +18479,7 @@
 
 
 TEST(neon_3diff_sqdmlsl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18458,7 +18517,7 @@
 
 
 TEST(neon_3diff_mla) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18486,7 +18545,7 @@
 
 
 TEST(neon_3diff_mls) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18514,7 +18573,7 @@
 
 
 TEST(neon_3same_compare) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18550,7 +18609,7 @@
 
 
 TEST(neon_3same_scalar_compare) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18593,7 +18652,7 @@
 }
 
 TEST(neon_2regmisc_fcmeq) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -18630,7 +18689,7 @@
 }
 
 TEST(neon_2regmisc_fcmge) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -18668,7 +18727,7 @@
 
 
 TEST(neon_2regmisc_fcmgt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -18705,7 +18764,7 @@
 }
 
 TEST(neon_2regmisc_fcmle) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -18743,7 +18802,7 @@
 
 
 TEST(neon_2regmisc_fcmlt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
 
@@ -18780,7 +18839,7 @@
 }
 
 TEST(neon_2regmisc_cmeq) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18814,7 +18873,7 @@
 
 
 TEST(neon_2regmisc_cmge) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18848,7 +18907,7 @@
 
 
 TEST(neon_2regmisc_cmlt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18882,7 +18941,7 @@
 
 
 TEST(neon_2regmisc_cmle) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18916,7 +18975,7 @@
 
 
 TEST(neon_2regmisc_cmgt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18950,7 +19009,7 @@
 
 
 TEST(neon_2regmisc_neg) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -18988,7 +19047,7 @@
 
 
 TEST(neon_2regmisc_sqneg) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19034,7 +19093,7 @@
 
 
 TEST(neon_2regmisc_abs) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19072,7 +19131,7 @@
 
 
 TEST(neon_2regmisc_sqabs) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19117,7 +19176,7 @@
 }
 
 TEST(neon_2regmisc_suqadd) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19178,7 +19237,7 @@
 }
 
 TEST(neon_2regmisc_usqadd) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19300,7 +19359,7 @@
 
 
 TEST(neon_2regmisc_xtn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19328,7 +19387,7 @@
 
 
 TEST(neon_2regmisc_sqxtn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19362,7 +19421,7 @@
 
 
 TEST(neon_2regmisc_uqxtn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19396,7 +19455,7 @@
 
 
 TEST(neon_2regmisc_sqxtun) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19429,7 +19488,7 @@
 }
 
 TEST(neon_3same_and) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19451,7 +19510,7 @@
 }
 
 TEST(neon_3same_bic) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19473,7 +19532,7 @@
 }
 
 TEST(neon_3same_orr) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19495,7 +19554,7 @@
 }
 
 TEST(neon_3same_mov) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19526,7 +19585,7 @@
 }
 
 TEST(neon_3same_orn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19548,7 +19607,7 @@
 }
 
 TEST(neon_3same_eor) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19570,7 +19629,7 @@
 }
 
 TEST(neon_3same_bif) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19600,7 +19659,7 @@
 }
 
 TEST(neon_3same_bit) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19630,7 +19689,7 @@
 }
 
 TEST(neon_3same_bsl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19661,7 +19720,7 @@
 
 
 TEST(neon_3same_smax) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19690,7 +19749,7 @@
 
 
 TEST(neon_3same_smaxp) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19719,7 +19778,7 @@
 
 
 TEST(neon_addp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19742,7 +19801,7 @@
 }
 
 TEST(neon_acrosslanes_addv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19770,7 +19829,7 @@
 
 
 TEST(neon_acrosslanes_saddlv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19798,7 +19857,7 @@
 
 
 TEST(neon_acrosslanes_uaddlv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19826,7 +19885,7 @@
 
 
 TEST(neon_acrosslanes_smaxv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19854,7 +19913,7 @@
 
 
 TEST(neon_acrosslanes_sminv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19881,7 +19940,7 @@
 }
 
 TEST(neon_acrosslanes_umaxv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19909,7 +19968,7 @@
 
 
 TEST(neon_acrosslanes_uminv) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19937,7 +19996,7 @@
 
 
 TEST(neon_3same_smin) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19966,7 +20025,7 @@
 
 
 TEST(neon_3same_umax) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -19995,7 +20054,7 @@
 
 
 TEST(neon_3same_umin) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20024,9 +20083,10 @@
 
 
 TEST(neon_3same_extra_fcadd) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP, CPUFeatures::kFcma);
 
   START();
+
   // (0i, 5) (d)
   __ Movi(v0.V2D(), 0x0, 0x4014000000000000);
   // (5i, 0) (d)
@@ -20073,7 +20133,7 @@
 
 
 TEST(neon_3same_extra_fcmla) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP, CPUFeatures::kFcma);
 
   START();
 
@@ -20148,7 +20208,7 @@
 
 
 TEST(neon_byelement_fcmla) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP, CPUFeatures::kFcma);
 
   START();
 
@@ -20224,7 +20284,7 @@
 
 
 TEST(neon_2regmisc_mvn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20256,7 +20316,7 @@
 
 
 TEST(neon_2regmisc_not) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20276,7 +20336,7 @@
 
 
 TEST(neon_2regmisc_cls_clz_cnt) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20325,7 +20385,7 @@
 }
 
 TEST(neon_2regmisc_rev) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20377,7 +20437,7 @@
 
 
 TEST(neon_sli) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20423,7 +20483,7 @@
 
 
 TEST(neon_sri) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20469,7 +20529,7 @@
 
 
 TEST(neon_shrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20497,7 +20557,7 @@
 
 
 TEST(neon_rshrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20525,7 +20585,7 @@
 
 
 TEST(neon_uqshrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20560,7 +20620,7 @@
 
 
 TEST(neon_uqrshrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20595,7 +20655,7 @@
 
 
 TEST(neon_sqshrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20630,7 +20690,7 @@
 
 
 TEST(neon_sqrshrn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20665,7 +20725,7 @@
 
 
 TEST(neon_sqshrun) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20700,7 +20760,7 @@
 
 
 TEST(neon_sqrshrun) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20734,7 +20794,7 @@
 }
 
 TEST(neon_modimm_bic) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20790,7 +20850,7 @@
 
 
 TEST(neon_modimm_movi_16bit_any) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20817,7 +20877,7 @@
 
 
 TEST(neon_modimm_movi_32bit_any) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20869,7 +20929,7 @@
 
 
 TEST(neon_modimm_movi_64bit_any) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20896,7 +20956,7 @@
 
 
 TEST(neon_modimm_movi) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -20961,7 +21021,7 @@
 
 
 TEST(neon_modimm_mvni) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21014,7 +21074,7 @@
 
 
 TEST(neon_modimm_orr) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21071,7 +21131,7 @@
 
 // TODO: add arbitrary values once load literal to Q registers is supported.
 TEST(neon_modimm_fmov) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   // Immediates which can be encoded in the instructions.
   const float kOne = 1.0f;
@@ -21128,7 +21188,7 @@
 
 
 TEST(neon_perm) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21158,7 +21218,7 @@
 
 
 TEST(neon_copy_dup_element) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21215,7 +21275,7 @@
 
 
 TEST(neon_copy_dup_general) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21257,7 +21317,7 @@
 
 
 TEST(neon_copy_ins_element) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21301,7 +21361,7 @@
 
 
 TEST(neon_copy_mov_element) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21345,7 +21405,7 @@
 
 
 TEST(neon_copy_smov) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21386,7 +21446,7 @@
 
 
 TEST(neon_copy_umov_mov) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21416,7 +21476,7 @@
 
 
 TEST(neon_copy_ins_general) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21459,7 +21519,7 @@
 
 
 TEST(neon_extract_ext) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21497,7 +21557,7 @@
 
 
 TEST(neon_3different_uaddl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21540,7 +21600,7 @@
 
 
 TEST(neon_3different_addhn_subhn) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21571,7 +21631,7 @@
 }
 
 TEST(neon_d_only_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21620,7 +21680,7 @@
 
 
 TEST(neon_sqshl_imm_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21677,7 +21737,7 @@
 
 
 TEST(neon_uqshl_imm_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21734,7 +21794,7 @@
 
 
 TEST(neon_sqshlu_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21791,7 +21851,7 @@
 
 
 TEST(neon_sshll) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21822,7 +21882,7 @@
 }
 
 TEST(neon_shll) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21853,7 +21913,7 @@
 }
 
 TEST(neon_ushll) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21885,7 +21945,7 @@
 
 
 TEST(neon_sxtl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21917,7 +21977,7 @@
 
 
 TEST(neon_uxtl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -21949,7 +22009,7 @@
 
 
 TEST(neon_ssra) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22001,7 +22061,7 @@
 }
 
 TEST(neon_srsra) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22054,7 +22114,7 @@
 }
 
 TEST(neon_usra) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22107,7 +22167,7 @@
 }
 
 TEST(neon_ursra) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22160,7 +22220,7 @@
 
 
 TEST(neon_uqshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22212,7 +22272,7 @@
 
 
 TEST(neon_sqshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22264,7 +22324,7 @@
 
 
 TEST(neon_urshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22292,7 +22352,7 @@
 
 
 TEST(neon_srshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22320,7 +22380,7 @@
 
 
 TEST(neon_uqrshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22372,7 +22432,7 @@
 
 
 TEST(neon_sqrshl_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22424,7 +22484,7 @@
 
 
 TEST(neon_uqadd_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22467,7 +22527,7 @@
 
 
 TEST(neon_sqadd_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22510,7 +22570,7 @@
 
 
 TEST(neon_uqsub_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22555,7 +22615,7 @@
 
 
 TEST(neon_sqsub_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
 
@@ -22600,7 +22660,7 @@
 
 
 TEST(neon_fmla_fmls) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(v0.V2D(), 0x3f80000040000000, 0x4100000000000000);
@@ -22635,7 +22695,7 @@
 
 
 TEST(neon_fmulx_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 2.0);
@@ -22687,7 +22747,8 @@
 // available.
 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
 TEST(crc32b) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22729,7 +22790,8 @@
 
 
 TEST(crc32h) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22771,7 +22833,8 @@
 
 
 TEST(crc32w) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22808,7 +22871,8 @@
 
 
 TEST(crc32x) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22845,7 +22909,8 @@
 
 
 TEST(crc32cb) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22887,7 +22952,8 @@
 
 
 TEST(crc32ch) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22929,7 +22995,8 @@
 
 
 TEST(crc32cw) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -22966,7 +23033,8 @@
 
 
 TEST(crc32cx) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
+
   START();
 
   __ Mov(w0, 0);
@@ -23004,7 +23072,7 @@
 
 
 TEST(neon_fabd_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Fmov(s0, 2.0);
@@ -23050,7 +23118,7 @@
 
 
 TEST(neon_faddp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(d0, 0x3f80000040000000);
@@ -23082,7 +23150,7 @@
 
 
 TEST(neon_fmaxp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(d0, 0x3f80000040000000);
@@ -23114,7 +23182,7 @@
 
 
 TEST(neon_fmaxnmp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(d0, 0x3f80000040000000);
@@ -23146,7 +23214,7 @@
 
 
 TEST(neon_fminp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(d0, 0x3f80000040000000);
@@ -23178,7 +23246,7 @@
 
 
 TEST(neon_fminnmp_scalar) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
 
   START();
   __ Movi(d0, 0x3f80000040000000);
@@ -23210,7 +23278,7 @@
 
 
 TEST(neon_tbl) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON);
 
   START();
   __ Movi(v30.V2D(), 0xbf561e188b1280e9, 0xbd542b8cbd24e8e8);
@@ -23690,7 +23758,7 @@
 
 
 TEST(collision_literal_veneer_pools) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // This is a code generation test. The code generated is not executed.
@@ -23781,7 +23849,7 @@
 
 
 TEST(ldr_literal_automatically_placed) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   START();
 
@@ -23920,7 +23988,7 @@
 
 
 TEST(generic_operand) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   int32_t data_32_array[5] = {0xbadbeef,
                               0x11111111,
@@ -24071,7 +24139,7 @@
 uint16_t test_uint16_t(uint16_t x) { return x; }
 
 TEST(runtime_calls) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
 #ifndef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
   if (masm.GenerateSimulatorCode()) {
diff --git a/test/aarch64/test-disasm-aarch64.cc b/test/aarch64/test-disasm-aarch64.cc
index d7abd8c..2bd7157 100644
--- a/test/aarch64/test-disasm-aarch64.cc
+++ b/test/aarch64/test-disasm-aarch64.cc
@@ -36,11 +36,12 @@
 
 #define TEST(name) TEST_(AARCH64_DISASM_##name)
 
-#define SETUP_COMMON()   \
-  uint32_t encoding = 0; \
-  MacroAssembler masm;   \
-  Decoder decoder;       \
-  Disassembler disasm;   \
+#define SETUP_COMMON()                                \
+  uint32_t encoding = 0;                              \
+  MacroAssembler masm;                                \
+  masm.GetCPUFeatures()->Combine(CPUFeatures::All()); \
+  Decoder decoder;                                    \
+  Disassembler disasm;                                \
   decoder.AppendVisitor(&disasm)
 
 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
diff --git a/test/aarch64/test-simulator-aarch64.cc b/test/aarch64/test-simulator-aarch64.cc
index 11f53c0..b5b3aba 100644
--- a/test/aarch64/test-simulator-aarch64.cc
+++ b/test/aarch64/test-simulator-aarch64.cc
@@ -55,10 +55,13 @@
 #define __ masm.
 #define TEST(name) TEST_(AARCH64_SIM_##name)
 
+#define SETUP() SETUP_WITH_FEATURES(CPUFeatures())
+
 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
 
-#define SETUP()                                       \
+#define SETUP_WITH_FEATURES(...)                      \
   MacroAssembler masm;                                \
+  masm.SetCPUFeatures(CPUFeatures(__VA_ARGS__));      \
   Decoder decoder;                                    \
   Simulator simulator(&decoder);                      \
   simulator.SetColouredTrace(Test::coloured_trace()); \
@@ -97,8 +100,9 @@
 
 #else  // VIXL_INCLUDE_SIMULATOR_AARCH64
 
-#define SETUP()        \
-  MacroAssembler masm; \
+#define SETUP_WITH_FEATURES(...)                 \
+  MacroAssembler masm;                           \
+  masm.SetCPUFeatures(CPUFeatures(__VA_ARGS__)); \
   CPU::SetUp()
 
 #define START() \
@@ -202,7 +206,7 @@
   VIXL_ASSERT((d_size == kDRegSize) || (d_size == kSRegSize));
   VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -321,7 +325,7 @@
                            unsigned reg_size) {
   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -454,7 +458,7 @@
                            unsigned reg_size) {
   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -603,7 +607,7 @@
                            unsigned reg_size) {
   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -742,7 +746,7 @@
                                unsigned reg_size) {
   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -870,7 +874,7 @@
   VIXL_ASSERT((d_size == kXRegSize) || (d_size == kWRegSize));
   VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -922,7 +926,7 @@
   VIXL_ASSERT((d_size == kXRegSize) || (d_size == kWRegSize));
   VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -1303,7 +1307,7 @@
   VIXL_ASSERT(vd_form != kFormatUndefined);
   VIXL_ASSERT(vn_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -1501,7 +1505,7 @@
   VIXL_ASSERT(vd_form != kFormatUndefined);
   VIXL_ASSERT(vn_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -1726,7 +1730,7 @@
   VIXL_ASSERT(vn_form != kFormatUndefined);
   VIXL_ASSERT(vm_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -1967,7 +1971,7 @@
   VIXL_ASSERT(vn_form != kFormatUndefined);
   VIXL_ASSERT(vm_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -2224,7 +2228,7 @@
     VectorFormat vn_form) {
   VIXL_ASSERT(vd_form != kFormatUndefined && vn_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -2437,7 +2441,7 @@
   VIXL_ASSERT(vd_form != kFormatUndefined);
   VIXL_ASSERT(vn_form != kFormatUndefined);
 
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
   START();
 
   // Roll up the loop to keep the code size down.
@@ -4554,7 +4558,7 @@
 
 
 TEST(RunFrom) {
-  SETUP();
+  SETUP_WITH_FEATURES(CPUFeatures::kFP);
 
   // Run a function returning `void` and taking no argument.
   int32_t value = 0xbad;