//
// Floating Point, HW Division and Neon Support
+
+// FP loads/stores/moves, shared between VFP and MVE (even in the integer-only
+// version).
+def FeatureFPRegs : SubtargetFeature<"fpregs", "HasFPRegs", "true",
+ "Enable FP registers">;
+
+// 16-bit FP loads/stores/moves, shared between VFP (with the v8.2A FP16
+// extension) and MVE (even in the integer-only version).
+def FeatureFPRegs16 : SubtargetFeature<"fpregs16", "HasFPRegs16", "true",
+ "Enable 16-bit FP registers",
+ [FeatureFPRegs]>;
+
+def FeatureFPRegs64 : SubtargetFeature<"fpregs64", "HasFPRegs64", "true",
+ "Enable 64-bit FP registers",
+ [FeatureFPRegs]>;
+
def FeatureFP64 : SubtargetFeature<"fp64", "HasFP64", "true",
"Floating point unit supports "
- "double precision">;
+ "double precision",
+ [FeatureFPRegs64]>;
def FeatureD32 : SubtargetFeature<"d32", "HasD32", "true",
"Extend FP to 32 double registers">;
!cast<SubtargetFeature>(NAME # "_SP")]>;
}
-defm FeatureVFP2: VFPver<"vfp2", "HasVFPv2", "Enable VFP2 instructions">;
+defm FeatureVFP2: VFPver<"vfp2", "HasVFPv2", "Enable VFP2 instructions",
+ [], [FeatureFPRegs]>;
+
defm FeatureVFP3: VFPver<"vfp3", "HasVFPv3", "Enable VFP3 instructions",
[FeatureVFP2]>;
def FeatureFullFP16 : SubtargetFeature<"fullfp16", "HasFullFP16", "true",
"Enable full half-precision "
"floating point",
- [FeatureFPARMv8_D16_SP]>;
+ [FeatureFPARMv8_D16_SP, FeatureFPRegs16]>;
def FeatureFP16FML : SubtargetFeature<"fp16fml", "HasFP16FML", "true",
"Enable full half-precision "
IIC_VMOVSI, "vmov", "32", "$R, $V$lane",
[(set GPR:$R, (extractelt (v2i32 DPR:$V),
imm:$lane))]>,
- Requires<[HasVFP2, HasFastVGETLNi32]> {
+ Requires<[HasFPRegs, HasFastVGETLNi32]> {
let Inst{21} = lane{0};
}
// def VGETLNf32: see FMRDH and FMRDL in ARMInstrVFP.td
def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$Dd), (ins addrmode5:$addr),
IIC_fpLoad64, "vldr", "\t$Dd, $addr",
- [(set DPR:$Dd, (f64 (alignedload32 addrmode5:$addr)))]>;
+ [(set DPR:$Dd, (f64 (alignedload32 addrmode5:$addr)))]>,
+ Requires<[HasFPRegs]>;
def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$Sd), (ins addrmode5:$addr),
IIC_fpLoad32, "vldr", "\t$Sd, $addr",
- [(set SPR:$Sd, (alignedload32 addrmode5:$addr))]> {
+ [(set SPR:$Sd, (alignedload32 addrmode5:$addr))]>,
+ Requires<[HasFPRegs]> {
// Some single precision VFP instructions may be executed on both NEON and VFP
// pipelines.
let D = VFPNeonDomain;
def VLDRH : AHI5<0b1101, 0b01, (outs HPR:$Sd), (ins addrmode5fp16:$addr),
IIC_fpLoad16, "vldr", ".16\t$Sd, $addr",
[(set HPR:$Sd, (alignedload16 addrmode5fp16:$addr))]>,
- Requires<[HasFullFP16]>;
+ Requires<[HasFPRegs16]>;
} // End of 'let canFoldAsLoad = 1, isReMaterializable = 1 in'
def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$Dd, addrmode5:$addr),
IIC_fpStore64, "vstr", "\t$Dd, $addr",
- [(alignedstore32 (f64 DPR:$Dd), addrmode5:$addr)]>;
+ [(alignedstore32 (f64 DPR:$Dd), addrmode5:$addr)]>,
+ Requires<[HasFPRegs]>;
def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$Sd, addrmode5:$addr),
IIC_fpStore32, "vstr", "\t$Sd, $addr",
- [(alignedstore32 SPR:$Sd, addrmode5:$addr)]> {
+ [(alignedstore32 SPR:$Sd, addrmode5:$addr)]>,
+ Requires<[HasFPRegs]> {
// Some single precision VFP instructions may be executed on both NEON and VFP
// pipelines.
let D = VFPNeonDomain;
def VSTRH : AHI5<0b1101, 0b00, (outs), (ins HPR:$Sd, addrmode5fp16:$addr),
IIC_fpStore16, "vstr", ".16\t$Sd, $addr",
[(alignedstore16 HPR:$Sd, addrmode5fp16:$addr)]>,
- Requires<[HasFullFP16]>;
+ Requires<[HasFPRegs16]>;
//===----------------------------------------------------------------------===//
// Load / store multiple Instructions.
multiclass vfp_ldst_mult<string asm, bit L_bit,
InstrItinClass itin, InstrItinClass itin_upd> {
+ let Predicates = [HasFPRegs] in {
// Double Precision
def DIA :
AXDI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
// VFP pipelines.
let D = VFPNeonDomain;
}
+ }
}
let hasSideEffects = 0 in {
// However, there is no UAL syntax for them, so we keep them around for
// (dis)assembly only.
multiclass vfp_ldstx_mult<string asm, bit L_bit> {
+ let Predicates = [HasFPRegs] in {
// Unknown precision
def XIA :
AXXI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
}
+ }
}
defm FLDM : vfp_ldstx_mult<"fldm", 1>;
let isMoveReg = 1 in {
def VMOVD : ADuI<0b11101, 0b11, 0b0000, 0b01, 0,
(outs DPR:$Dd), (ins DPR:$Dm),
- IIC_fpUNA64, "vmov", ".f64\t$Dd, $Dm", []>;
+ IIC_fpUNA64, "vmov", ".f64\t$Dd, $Dm", []>,
+ Requires<[HasFPRegs64]>;
def VMOVS : ASuI<0b11101, 0b11, 0b0000, 0b01, 0,
(outs SPR:$Sd), (ins SPR:$Sm),
- IIC_fpUNA32, "vmov", ".f32\t$Sd, $Sm", []>;
+ IIC_fpUNA32, "vmov", ".f32\t$Sd, $Sm", []>,
+ Requires<[HasFPRegs]>;
} // isMoveReg
let PostEncoderMethod = "", DecoderNamespace = "VFPV8", isUnpredicable = 1 in {
(outs GPR:$Rt), (ins SPR:$Sn),
IIC_fpMOVSI, "vmov", "\t$Rt, $Sn",
[(set GPR:$Rt, (bitconvert SPR:$Sn))]>,
+ Requires<[HasFPRegs]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<4> Rt;
(outs SPR:$Sn), (ins GPR:$Rt),
IIC_fpMOVIS, "vmov", "\t$Sn, $Rt",
[(set SPR:$Sn, (bitconvert GPR:$Rt))]>,
- Requires<[HasVFP2, UseVMOVSR]>,
+ Requires<[HasFPRegs, UseVMOVSR]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<5> Sn;
(outs GPR:$Rt, GPR:$Rt2), (ins DPR:$Dm),
IIC_fpMOVDI, "vmov", "\t$Rt, $Rt2, $Dm",
[(set GPR:$Rt, GPR:$Rt2, (arm_fmrrd DPR:$Dm))]>,
+ Requires<[HasFPRegs]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<5> Dm;
(outs GPR:$Rt, GPR:$Rt2), (ins SPR:$src1, SPR:$src2),
IIC_fpMOVDI, "vmov", "\t$Rt, $Rt2, $src1, $src2",
[/* For disassembly only; pattern left blank */]>,
+ Requires<[HasFPRegs]>,
Sched<[WriteFPMOV]> {
bits<5> src1;
bits<4> Rt;
(outs DPR:$Dm), (ins GPR:$Rt, GPR:$Rt2),
IIC_fpMOVID, "vmov", "\t$Dm, $Rt, $Rt2",
[(set DPR:$Dm, (arm_fmdrr GPR:$Rt, GPR:$Rt2))]>,
+ Requires<[HasFPRegs]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<5> Dm;
(outs SPR:$dst1, SPR:$dst2), (ins GPR:$src1, GPR:$src2),
IIC_fpMOVID, "vmov", "\t$dst1, $dst2, $src1, $src2",
[/* For disassembly only; pattern left blank */]>,
+ Requires<[HasFPRegs]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<5> dst1;
(outs GPR:$Rt), (ins HPR:$Sn),
IIC_fpMOVSI, "vmov", ".f16\t$Rt, $Sn",
[(set GPR:$Rt, (arm_vmovrh HPR:$Sn))]>,
- Requires<[HasFullFP16]>,
+ Requires<[HasFPRegs16]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<4> Rt;
(outs HPR:$Sn), (ins GPR:$Rt),
IIC_fpMOVIS, "vmov", ".f16\t$Sn, $Rt",
[(set HPR:$Sn, (arm_vmovhr GPR:$Rt))]>,
- Requires<[HasFullFP16]>,
+ Requires<[HasFPRegs16]>,
Sched<[WriteFPMOV]> {
// Instruction operands.
bits<5> Sn;
// APSR is the application level alias of CPSR. This FPSCR N, Z, C, V flags
// to APSR.
-let Defs = [CPSR], Uses = [FPSCR_NZCV], Rt = 0b1111 /* apsr_nzcv */ in
+let Defs = [CPSR], Uses = [FPSCR_NZCV], Predicates = [HasFPRegs],
+ Rt = 0b1111 /* apsr_nzcv */ in
def FMSTAT : MovFromVFP<0b0001 /* fpscr */, (outs), (ins),
"vmrs", "\tAPSR_nzcv, fpscr", [(arm_fmstat)]>;
let DecoderMethod = "DecodeForVMRSandVMSR" in {
// Application level FPSCR -> GPR
- let hasSideEffects = 1, Uses = [FPSCR] in
+ let hasSideEffects = 1, Uses = [FPSCR], Predicates = [HasFPRegs] in
def VMRS : MovFromVFP<0b0001 /* fpscr */, (outs GPRnopc:$Rt), (ins),
"vmrs", "\t$Rt, fpscr",
[(set GPRnopc:$Rt, (int_arm_get_fpscr))]>;
let DecoderMethod = "DecodeForVMRSandVMSR" in {
let Defs = [FPSCR] in {
+ let Predicates = [HasFPRegs] in
// Application level GPR -> FPSCR
def VMSR : MovToVFP<0b0001 /* fpscr */, (outs), (ins GPRnopc:$src),
"vmsr", "\tfpscr, $src",
def : VFP2InstAlias<"fcmpzs${p} $val", (VCMPZS SPR:$val, pred:$p)>;
-def : VFP2InstAlias<"fmstat${p}", (FMSTAT pred:$p)>;
+def : InstAlias<"fmstat${p}", (FMSTAT pred:$p), 0>, Requires<[HasFPRegs]>;
def : VFP2InstAlias<"fadds${p} $Sd, $Sn, $Sm",
(VADDS SPR:$Sd, SPR:$Sn, SPR:$Sm, pred:$p)>;
def : VFP2DPInstAlias<"faddd${p} $Dd, $Dn, $Dm",
def HasV8MMainline : Predicate<"Subtarget->hasV8MMainlineOps()">,
AssemblerPredicate<"HasV8MMainlineOps",
"armv8m.main">;
+def HasFPRegs : Predicate<"Subtarget->hasFPRegs()">,
+ AssemblerPredicate<"FeatureFPRegs",
+ "fp registers">;
+def HasFPRegs16 : Predicate<"Subtarget->hasFPRegs16()">,
+ AssemblerPredicate<"FeatureFPRegs16",
+ "16-bit fp registers">;
+def HasFPRegs64 : Predicate<"Subtarget->hasFPRegs64()">,
+ AssemblerPredicate<"FeatureFPRegs64",
+ "64-bit fp registers">;
def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">,
AssemblerPredicate<"HasV6T2Ops", "armv6t2">;
def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">;
bool HasVFPv4 = false;
bool HasFPARMv8 = false;
bool HasNEON = false;
+ bool HasFPRegs = false;
+ bool HasFPRegs16 = false;
+ bool HasFPRegs64 = false;
/// Versions of the VFP flags restricted to single precision, or to
/// 16 d-registers, or both.
bool hasV8_5aOps() const { return HasV8_5aOps; }
bool hasV8MBaselineOps() const { return HasV8MBaselineOps; }
bool hasV8MMainlineOps() const { return HasV8MMainlineOps; }
+ bool hasFPRegs() const { return HasFPRegs; }
+ bool hasFPRegs16() const { return HasFPRegs16; }
+ bool hasFPRegs64() const { return HasFPRegs64; }
/// @{
/// These functions are obsolete, please consider adding subtarget features
vldr.16 s2, [pc, #510]
vldr.16 s3, [pc, #-510]
vldr.16 s4, [r4, #-18]
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
vstr.16 s1, [pc, #6]
vstr.16 s2, [pc, #510]
vstr.16 s3, [pc, #-510]
vstr.16 s4, [r4, #-18]
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
vmov.f16 s0, #1.0
@ CHECK: instruction requires: full half-float
vmov.f16 s1, r2
vmov.f16 r3, s4
-@ CHECK: instruction requires: full half-float
-@ CHECK: instruction requires: full half-float
+@ CHECK: instruction requires: 16-bit fp registers
+@ CHECK: instruction requires: 16-bit fp registers
--- /dev/null
+// Some simple operations on S, D and Q registers (loads, stores and moves) are
+// also avaliable in MVE, even in the integer-only version. Some of these
+// instructions (operating on D or Q registers, or FP16 values) are only
+// available for certain targets.
+
+// Note that it's not always obvious which instructions are available, for
+// example several instructions operating on D registers are available for
+// single-precision only FPUs.
+
+// All of these instructions are rejected if no VFP or MVE features are
+// present.
+// RUN: not llvm-mc -triple=thumbv8.1m.main -show-encoding 2>%t < %s
+// RUN: FileCheck %s < %t --check-prefix=NOFP16 --check-prefix=NOFP32 --check-prefix=NOFP64
+
+// VFP and NEON implementations by default have FP32 and FP64, but not FP16.
+// The VFPv3 FP16 extension just added conversion instructions, which we don't
+// care about here.
+// RUN: not llvm-mc -triple=thumbv8.1m.main -show-encoding -mattr=+vfp2 2>%t < %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=FP32 --check-prefix=FP64
+// RUN: FileCheck %s < %t --check-prefix=NOFP16
+// RUN: not llvm-mc -triple=thumbv8.1m.main -show-encoding -mattr=+fp-armv8,+neon 2>%t < %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=FP32 --check-prefix=FP64
+// RUN: FileCheck %s < %t --check-prefix=NOFP16
+
+// The v8.2A FP16 extension added loads, stores and moves for FP16.
+// RUN: llvm-mc -triple=thumbv8.1m.main -show-encoding -mattr=+fp-armv8,+fullfp16 < %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=FP16 --check-prefix=FP32 --check-prefix=FP64
+
+// M-profile FPUs (e.g. Cortex-M4/M7/M33) do not have FP16 instructions, and
+// the FP64 instructions are optional. They are also limited to 16 D registers,
+// but we don't test that here.
+// RUN: not llvm-mc -triple=thumbv8.1m.main -show-encoding -mattr=+vfp4d16sp 2>%t < %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=FP32
+// RUN: FileCheck %s < %t --check-prefix=NOFP16 --check-prefix=NOFP64
+// RUN: not llvm-mc -triple=thumbv8.1m.main -show-encoding -mattr=+vfp4,-d32 2>%t < %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=FP32 --check-prefix=FP64
+// RUN: FileCheck %s < %t --check-prefix=NOFP16
+
+vldmia r0, {d0}
+# FP32: vldmia r0, {d0} @ encoding: [0x90,0xec,0x02,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vstmia r0, {d0}
+# FP32: vstmia r0, {d0} @ encoding: [0x80,0xec,0x02,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vldmia r0, {s0}
+# FP32: vldmia r0, {s0} @ encoding: [0x90,0xec,0x01,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vstmia r0, {s0}
+# FP32: vstmia r0, {s0} @ encoding: [0x80,0xec,0x01,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+fldmdbx r0!, {d0}
+# FP32: fldmdbx r0!, {d0} @ encoding: [0x30,0xed,0x03,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+fstmiax r0, {d0}
+# FP32: fstmiax r0, {d0} @ encoding: [0x80,0xec,0x03,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vldr.16 s0, [r0]
+# FP16: vldr.16 s0, [r0] @ encoding: [0x90,0xed,0x00,0x09]
+# NOFP16: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: 16-bit fp registers
+
+vldr s0, [r0]
+# FP32: vldr s0, [r0] @ encoding: [0x90,0xed,0x00,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vldr d0, [r0]
+# FP32: vldr d0, [r0] @ encoding: [0x90,0xed,0x00,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vstr.16 s0, [r0]
+# FP16: vstr.16 s0, [r0] @ encoding: [0x80,0xed,0x00,0x09]
+# NOFP16: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: 16-bit fp registers
+
+vstr s0, [r0]
+# FP32: vstr s0, [r0] @ encoding: [0x80,0xed,0x00,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vstr d0, [r0]
+# FP32: vstr d0, [r0] @ encoding: [0x80,0xed,0x00,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov.f16 r0, s0
+# FP16: vmov.f16 r0, s0 @ encoding: [0x10,0xee,0x10,0x09]
+# NOFP16: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: 16-bit fp registers
+
+vmov.f16 s0, r0
+# FP16: vmov.f16 s0, r0 @ encoding: [0x00,0xee,0x10,0x09]
+# NOFP16: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: 16-bit fp registers
+
+vmov s0, r0
+# FP32: vmov s0, r0 @ encoding: [0x00,0xee,0x10,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov r0, s0
+# FP32: vmov r0, s0 @ encoding: [0x10,0xee,0x10,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov r0, r1, d0
+# FP32: vmov r0, r1, d0 @ encoding: [0x51,0xec,0x10,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov d0, r0, r1
+# FP32: vmov d0, r0, r1 @ encoding: [0x41,0xec,0x10,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov r0, r1, s0, s1
+# FP32: vmov r0, r1, s0, s1 @ encoding: [0x51,0xec,0x10,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov s0, s1, r0, r1
+# FP32: vmov s0, s1, r0, r1 @ encoding: [0x41,0xec,0x10,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov.f32 s0, s1
+# FP32: vmov.f32 s0, s1 @ encoding: [0xb0,0xee,0x60,0x0a]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
+
+vmov.f64 d0, d1
+# FP64: vmov.f64 d0, d1 @ encoding: [0xb0,0xee,0x41,0x0b]
+# NOFP64: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: 64-bit fp registers
+
+vmov.32 r0, d1[0]
+# FP32: vmov.32 r0, d1[0] @ encoding: [0x11,0xee,0x10,0x0b]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: error: instruction requires: fp registers
+
+vmrs apsr_nzcv, fpscr
+# FP32: vmrs APSR_nzcv, fpscr @ encoding: [0xf1,0xee,0x10,0xfa]
+# NOFP32: :[[@LINE-2]]:{{[0-9]+}}: {{note|error}}: instruction requires: fp registers
-@ RUN: not llvm-mc < %s -triple thumbv8-unknown-unknown -show-encoding -mattr=-fp64,-neon 2> %t > %t2
+@ RUN: not llvm-mc < %s -triple thumbv8-unknown-unknown -show-encoding -mattr=-fp64,-fpregs64,-neon 2> %t > %t2
@ RUN: FileCheck %s < %t --check-prefix=CHECK-ERRORS
@ RUN: FileCheck %s < %t2
@ FIXME: overlapping aliases and a probable TableGen indeterminacy mean
@ that the actual reason can vary by platform.
vmov.f64 d11, d10
-@ CHECK-ERRORS: instruction requires: NEON
+@ CHECK-ERRORS: instruction requires: 64-bit fp registers
@ CHECK-ERRORS-NEXT: vmov.f64 d11, d10
vcvt.f64.s32 d9, s8
// ERROR-V8M: invalid operand for instruction
// ERROR-V8M: invalid operand for instruction
-// ERROR-NOVFP: instruction requires: VFP2
-// ERROR-NOVFP: instruction requires: VFP2
-// ERROR-NOVFP: instruction requires: VFP2
-// ERROR-NOVFP: instruction requires: VFP2
+// ERROR-NOVFP: instruction requires: fp registers
+// ERROR-NOVFP: instruction requires: fp registers
+// ERROR-NOVFP: instruction requires: fp registers
+// ERROR-NOVFP: instruction requires: fp registers
// ERROR-NOVFP: instruction requires: VFP2
// ERROR-NOVFP: instruction requires: VFP2
// ERROR-NOVFP: instruction requires: VFP2
// ERROR-V8M: operand must be a register in range [r0, r14]
// ERROR-NOVFP: invalid instruction
+// ERROR-NOVFP: instruction requires: fp registers
// ERROR-NOVFP: instruction requires: VFP2
// ERROR-NOVFP: instruction requires: VFP2
-// ERROR-NOVFP: instruction requires: VFP2
-// ERROR-NOVFP: instruction requires: VFP2
+// ERROR-NOVFP: instruction requires: fp registers
// ERROR-NOVFP: invalid instruction
// ERROR-NOVFP: invalid instruction