Index: llvm/trunk/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64.td +++ llvm/trunk/lib/Target/AArch64/AArch64.td @@ -204,6 +204,9 @@ "true", "Enable Aggressive FMA for floating-point.">; +def FeatureAltFPCmp : SubtargetFeature<"altnzcv", "HasAlternativeNZCV", "true", + "Enable alternative NZCV format for floating point comparisons">; + //===----------------------------------------------------------------------===// // Architectures. // @@ -221,7 +224,7 @@ "Support ARM v8.4a instructions", [HasV8_3aOps, FeatureDotProd]>; def HasV8_5aOps : SubtargetFeature<"v8.5a", "HasV8_5aOps", "true", - "Support ARM v8.5a instructions", [HasV8_4aOps]>; + "Support ARM v8.5a instructions", [HasV8_4aOps, FeatureAltFPCmp]>; //===----------------------------------------------------------------------===// // Register File Description Index: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td @@ -62,7 +62,8 @@ AssemblerPredicate<"FeatureSVE", "sve">; def HasRCPC : Predicate<"Subtarget->hasRCPC()">, AssemblerPredicate<"FeatureRCPC", "rcpc">; - +def HasAltNZCV : Predicate<"Subtarget->hasAlternativeNZCV()">, + AssemblerPredicate<"FeatureAltFPCmp", "altnzcv">; def IsLE : Predicate<"Subtarget->isLittleEndian()">; def IsBE : Predicate<"!Subtarget->isLittleEndian()">; def UseAlternateSExtLoadCVTF32 @@ -608,6 +609,25 @@ "{\t$Rn, $imm, $mask}">; } // HasV8_4a +// v8.5 flag manipulation instructions +let Predicates = [HasAltNZCV], Uses = [NZCV], Defs = [NZCV] in { + +def XAFLAG : PstateWriteSimple<(ins), "xaflag", "">, Sched<[WriteSys]> { + let Inst{18-16} = 0b000; + let Inst{11-8} = 0b0000; + let Unpredictable{11-8} = 0b1111; + let Inst{7-5} = 0b001; +} + +def AXFLAG : PstateWriteSimple<(ins), "axflag", "">, Sched<[WriteSys]> { + let Inst{18-16} = 0b000; + let Inst{11-8} = 0b0000; + let Unpredictable{11-8} = 0b1111; + let Inst{7-5} = 0b010; +} + +} // HasAltNZCV + def : InstAlias<"clrex", (CLREX 0xf)>; def : InstAlias<"isb", (ISB 0xf)>; Index: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h @@ -94,6 +94,9 @@ bool HasRCPC = false; bool HasAggressiveFMA = false; + // Armv8.5-A Extensions + bool HasAlternativeNZCV = false; + // HasZeroCycleRegMove - Has zero-cycle register mov instructions. bool HasZeroCycleRegMove = false; @@ -306,6 +309,7 @@ bool hasSVE() const { return HasSVE; } bool hasRCPC() const { return HasRCPC; } bool hasAggressiveFMA() const { return HasAggressiveFMA; } + bool hasAlternativeNZCV() const { return HasAlternativeNZCV; } bool isLittleEndian() const { return IsLittle; } Index: llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1712,9 +1712,14 @@ uint64_t op1 = fieldFromInstruction(insn, 16, 3); uint64_t op2 = fieldFromInstruction(insn, 5, 3); uint64_t crm = fieldFromInstruction(insn, 8, 4); - uint64_t pstate_field = (op1 << 3) | op2; + switch (pstate_field) { + case 0x01: // XAFlag + case 0x02: // AXFlag + return Fail; + } + if ((pstate_field == AArch64PState::PAN || pstate_field == AArch64PState::UAO) && crm > 1) return Fail; Index: llvm/trunk/test/MC/AArch64/armv8.5a-altnzcv.s =================================================================== --- llvm/trunk/test/MC/AArch64/armv8.5a-altnzcv.s +++ llvm/trunk/test/MC/AArch64/armv8.5a-altnzcv.s @@ -0,0 +1,16 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a,+altnzcv < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a,-v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOALTFP +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=-v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOALTFP + +// Flag manipulation +xaflag +axflag + +// CHECK: xaflag // encoding: [0x3f,0x40,0x00,0xd5] +// CHECK: axflag // encoding: [0x5f,0x40,0x00,0xd5] + +// NOALTFP: instruction requires: altnzcv +// NOALTFP-NEXT: xaflag +// NOALTFP: instruction requires: altnzcv +// NOALTFP-NEXT: axflag Index: llvm/trunk/test/MC/AArch64/armv8.5a-xaflag-error.s =================================================================== --- llvm/trunk/test/MC/AArch64/armv8.5a-xaflag-error.s +++ llvm/trunk/test/MC/AArch64/armv8.5a-xaflag-error.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +// Check that XAFlag/AXFlag don't accept operands like MSR does +xaflag S0_0_C4_C0_1, xzr +axflag S0_0_C4_C0_1, xzr + +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: xaflag S0_0_C4_C0_1, xzr +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: axflag S0_0_C4_C0_1, xzr Index: llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt +++ llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt @@ -0,0 +1,12 @@ +# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.5a --disassemble < %s | FileCheck %s +# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=-v8.5a --disassemble < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOV85 + +# Flag manipulation +[0x3f,0x40,0x00,0xd5] +[0x5f,0x40,0x00,0xd5] + +#CHECK: xaflag +#CHECK: axflag + +#CHECK-NOV85: msr S0_0_C4_C0_1, xzr +#CHECK-NOV85: msr S0_0_C4_C0_2, xzr