diff options
-rw-r--r-- | src/aarch64/assembler-aarch64.cc | 12 | ||||
-rw-r--r-- | src/aarch64/assembler-aarch64.h | 8 | ||||
-rw-r--r-- | src/aarch64/constants-aarch64.h | 4 | ||||
-rw-r--r-- | src/aarch64/cpu-features-auditor-aarch64.cc | 4 | ||||
-rw-r--r-- | src/aarch64/disasm-aarch64.cc | 8 | ||||
-rw-r--r-- | src/aarch64/macro-assembler-aarch64.h | 10 | ||||
-rw-r--r-- | src/aarch64/simulator-aarch64.cc | 18 | ||||
-rw-r--r-- | src/cpu-features.h | 4 | ||||
-rw-r--r-- | test/aarch64/test-assembler-aarch64.cc | 64 | ||||
-rw-r--r-- | test/aarch64/test-disasm-aarch64.cc | 2 | ||||
-rw-r--r-- | test/test-api.cc | 2 |
11 files changed, 133 insertions, 3 deletions
diff --git a/src/aarch64/assembler-aarch64.cc b/src/aarch64/assembler-aarch64.cc index 060681be..04bd2267 100644 --- a/src/aarch64/assembler-aarch64.cc +++ b/src/aarch64/assembler-aarch64.cc @@ -2549,6 +2549,18 @@ void Assembler::cfinv() { } +void Assembler::axflag() { + VIXL_ASSERT(CPUHas(CPUFeatures::kAXFlag)); + Emit(AXFLAG); +} + + +void Assembler::xaflag() { + VIXL_ASSERT(CPUHas(CPUFeatures::kAXFlag)); + Emit(XAFLAG); +} + + void Assembler::clrex(int imm4) { Emit(CLREX | CRm(imm4)); } diff --git a/src/aarch64/assembler-aarch64.h b/src/aarch64/assembler-aarch64.h index d67824df..309b49ac 100644 --- a/src/aarch64/assembler-aarch64.h +++ b/src/aarch64/assembler-aarch64.h @@ -2126,6 +2126,14 @@ class Assembler : public vixl::internal::AssemblerBase { // Invert carry flag [Armv8.4]. void cfinv(); + // Convert floating-point condition flags from alternative format to Arm + // format [Armv8.5]. + void xaflag(); + + // Convert floating-point condition flags from Arm format to alternative + // format [Armv8.5]. + void axflag(); + // System instruction. void sys(int op1, int crn, int crm, int op2, const Register& xt = xzr); diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h index 3f6dc587..16f2715e 100644 --- a/src/aarch64/constants-aarch64.h +++ b/src/aarch64/constants-aarch64.h @@ -779,7 +779,9 @@ enum SystemPStateOp { SystemPStateFixed = 0xD5004000, SystemPStateFMask = 0xFFF8F000, SystemPStateMask = 0xFFFFF0FF, - CFINV = SystemPStateFixed | 0x0000001F + CFINV = SystemPStateFixed | 0x0000001F, + XAFLAG = SystemPStateFixed | 0x0000003F, + AXFLAG = SystemPStateFixed | 0x0000005F }; enum SystemHintOp { diff --git a/src/aarch64/cpu-features-auditor-aarch64.cc b/src/aarch64/cpu-features-auditor-aarch64.cc index c0cd5a91..d3639d35 100644 --- a/src/aarch64/cpu-features-auditor-aarch64.cc +++ b/src/aarch64/cpu-features-auditor-aarch64.cc @@ -1086,6 +1086,10 @@ void CPUFeaturesAuditor::VisitSystem(const Instruction* instr) { case CFINV: scope.Record(CPUFeatures::kFlagM); break; + case AXFLAG: + case XAFLAG: + scope.Record(CPUFeatures::kAXFlag); + break; } } } diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc index e9766037..21610432 100644 --- a/src/aarch64/disasm-aarch64.cc +++ b/src/aarch64/disasm-aarch64.cc @@ -2069,6 +2069,14 @@ void Disassembler::VisitSystem(const Instruction *instr) { mnemonic = "cfinv"; form = NULL; break; + case AXFLAG: + mnemonic = "axflag"; + form = NULL; + break; + case XAFLAG: + mnemonic = "xaflag"; + form = NULL; + break; } } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) { switch (instr->Mask(SystemPAuthMask)) { diff --git a/src/aarch64/macro-assembler-aarch64.h b/src/aarch64/macro-assembler-aarch64.h index a1de4dd5..8051bd1b 100644 --- a/src/aarch64/macro-assembler-aarch64.h +++ b/src/aarch64/macro-assembler-aarch64.h @@ -2007,6 +2007,16 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { SingleEmissionCheckScope guard(this); cfinv(); } + void Axflag() { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + axflag(); + } + void Xaflag() { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + xaflag(); + } void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) { VIXL_ASSERT(allow_macro_instructions_); SingleEmissionCheckScope guard(this); diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc index c1d32a92..1c1d52e7 100644 --- a/src/aarch64/simulator-aarch64.cc +++ b/src/aarch64/simulator-aarch64.cc @@ -3732,6 +3732,24 @@ void Simulator::VisitSystem(const Instruction* instr) { case CFINV: ReadNzcv().SetC(!ReadC()); break; + case AXFLAG: + ReadNzcv().SetN(0); + ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV()); + ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV()); + ReadNzcv().SetV(0); + break; + case XAFLAG: { + // Can't set the flags in place due to the logical dependencies. + uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1; + uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC(); + uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ(); + uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ(); + ReadNzcv().SetN(n); + ReadNzcv().SetZ(z); + ReadNzcv().SetC(c); + ReadNzcv().SetV(v); + break; + } } } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) { // Check BType allows PACI[AB]SP instructions. diff --git a/src/cpu-features.h b/src/cpu-features.h index 88b6914e..fffef44f 100644 --- a/src/cpu-features.h +++ b/src/cpu-features.h @@ -96,7 +96,9 @@ namespace vixl { /* Data-independent timing (for selected instructions). */ \ V(kDIT, "DIT", "dit") \ /* Branch target identification. */ \ - V(kBTI, "BTI", NULL) + V(kBTI, "BTI", NULL) \ + /* Flag manipulation instructions: {AX,XA}FLAG */ \ + V(kAXFlag, "AXFlag", NULL) // clang-format on diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc index 38fee97e..8f0a87fb 100644 --- a/test/aarch64/test-assembler-aarch64.cc +++ b/test/aarch64/test-assembler-aarch64.cc @@ -15058,6 +15058,70 @@ TEST(cfinv) { } +TEST(axflag_xaflag) { + // The AXFLAG and XAFLAG instructions are designed for converting the FP + // conditional flags from Arm format to an alternate format efficiently. + // There are only 4 cases which are relevant for this conversion but we test + // the behaviour for all 16 cases anyway. The 4 important cases are labelled + // below. + StatusFlags expected_x[16] = {NoFlag, + ZFlag, + CFlag, // Greater than + ZFlag, // Unordered + ZFlag, + ZFlag, + ZCFlag, // Equal to + ZFlag, + NoFlag, // Less than + ZFlag, + CFlag, + ZFlag, + ZFlag, + ZFlag, + ZCFlag, + ZFlag}; + StatusFlags expected_a[16] = {NFlag, // Less than + NFlag, + CFlag, // Greater than + CFlag, + CVFlag, // Unordered + CVFlag, + ZCFlag, // Equal to + ZCFlag, + NFlag, + NFlag, + CFlag, + CFlag, + CVFlag, + CVFlag, + ZCFlag, + ZCFlag}; + + for (unsigned i = 0; i < 16; i++) { + SETUP_WITH_FEATURES(CPUFeatures::kAXFlag); + + START(); + __ Mov(x0, i << Flags_offset); + __ Msr(NZCV, x0); + __ Axflag(); + __ Mrs(x1, NZCV); + __ Msr(NZCV, x0); + __ Xaflag(); + __ Mrs(x2, NZCV); + END(); + +#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 + RUN(); + ASSERT_EQUAL_32(expected_x[i], w1); + ASSERT_EQUAL_32(expected_a[i], w2); +#else + USE(expected_x, expected_a); +#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 + TEARDOWN(); + } +} + + TEST(system_msr) { // All FPCR fields that must be implemented: AHP, DN, FZ, RMode const uint64_t fpcr_core = 0x07c00000; diff --git a/test/aarch64/test-disasm-aarch64.cc b/test/aarch64/test-disasm-aarch64.cc index 0d7642fd..5fb98d2c 100644 --- a/test/aarch64/test-disasm-aarch64.cc +++ b/test/aarch64/test-disasm-aarch64.cc @@ -3212,6 +3212,8 @@ TEST(system_pstate) { SETUP(); COMPARE(cfinv(), "cfinv"); + COMPARE(axflag(), "axflag"); + COMPARE(xaflag(), "xaflag"); CLEANUP(); } diff --git a/test/test-api.cc b/test/test-api.cc index f0332716..d3a62019 100644 --- a/test/test-api.cc +++ b/test/test-api.cc @@ -392,7 +392,7 @@ TEST(CPUFeatures_format) { // Armv8.4 "RCpc (imm), FlagM, USCAT, FHM, DIT, " // Armv8.5 - "BTI", + "BTI, AXFlag", CPUFeatures::All()); } |