aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gilday <alexander.gilday@arm.com>2018-11-06 15:28:07 +0000
committerJacob Bramley <jacob.bramley@arm.com>2018-11-12 10:45:30 +0000
commit84ee144ecd16f0ee52c24a6273430f37c92322ad (patch)
tree84bf04bfb1adb44ef18cb571776a8315bb93e625
parent2487f14e5dca4d6dca4cb2eddb378402cdd8bf6d (diff)
downloadvixl-84ee144ecd16f0ee52c24a6273430f37c92322ad.tar.gz
Add support for AXFLAG and XAFLAG instructions.
Change-Id: I95867fa8adb6eeefe49dc5e0f56ed51b4d060a1d
-rw-r--r--src/aarch64/assembler-aarch64.cc12
-rw-r--r--src/aarch64/assembler-aarch64.h8
-rw-r--r--src/aarch64/constants-aarch64.h4
-rw-r--r--src/aarch64/cpu-features-auditor-aarch64.cc4
-rw-r--r--src/aarch64/disasm-aarch64.cc8
-rw-r--r--src/aarch64/macro-assembler-aarch64.h10
-rw-r--r--src/aarch64/simulator-aarch64.cc18
-rw-r--r--src/cpu-features.h4
-rw-r--r--test/aarch64/test-assembler-aarch64.cc64
-rw-r--r--test/aarch64/test-disasm-aarch64.cc2
-rw-r--r--test/test-api.cc2
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());
}