aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatWai Chong <tatwai.chong@arm.com>2018-12-27 16:01:02 -0800
committerTatWai Chong <tatwai.chong@arm.com>2019-01-29 23:33:48 +0000
commit04edf680e65e6aa55e64f56badf6a51a343fc890 (patch)
tree64e208dea7992dbc1395c354427704ced4ad285d
parent7e3a5c85976dfd832ff2e6ebf428ec791b8804dc (diff)
Add support for random number generation.
Arm8.5 introduces RNDR and RNDRRS which both return a 64-bit random number. Change-Id: I0d942c742232efae5f605233410935512c79b576
-rw-r--r--src/aarch64/constants-aarch64.h4
-rw-r--r--src/aarch64/cpu-features-auditor-aarch64.cc9
-rw-r--r--src/aarch64/disasm-aarch64.cc6
-rw-r--r--src/aarch64/simulator-aarch64.cc18
-rw-r--r--src/aarch64/simulator-aarch64.h3
-rw-r--r--src/cpu-features.h4
-rw-r--r--test/aarch64/test-assembler-aarch64.cc39
-rw-r--r--test/aarch64/test-disasm-aarch64.cc2
-rw-r--r--test/test-api.cc2
9 files changed, 84 insertions, 3 deletions
diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h
index f1361c36..5c3bd491 100644
--- a/src/aarch64/constants-aarch64.h
+++ b/src/aarch64/constants-aarch64.h
@@ -400,7 +400,9 @@ class SystemRegisterEncoder {
// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
enum SystemRegister {
NZCV = SystemRegisterEncoder<3, 3, 4, 2, 0>::value,
- FPCR = SystemRegisterEncoder<3, 3, 4, 4, 0>::value
+ FPCR = SystemRegisterEncoder<3, 3, 4, 4, 0>::value,
+ RNDR = SystemRegisterEncoder<3, 3, 2, 4, 0>::value, // Random number.
+ RNDRRS = SystemRegisterEncoder<3, 3, 2, 4, 1>::value // Reseeded random number.
};
template<int op1, int crn, int crm, int op2>
diff --git a/src/aarch64/cpu-features-auditor-aarch64.cc b/src/aarch64/cpu-features-auditor-aarch64.cc
index 3fa4e54c..0a55a780 100644
--- a/src/aarch64/cpu-features-auditor-aarch64.cc
+++ b/src/aarch64/cpu-features-auditor-aarch64.cc
@@ -1118,6 +1118,15 @@ void CPUFeaturesAuditor::VisitSystem(const Instruction* instr) {
scope.Record(CPUFeatures::kAXFlag);
break;
}
+ } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
+ if (instr->Mask(SystemSysRegMask) == MRS) {
+ switch (instr->GetImmSystemRegister()) {
+ case RNDR:
+ case RNDRRS:
+ scope.Record(CPUFeatures::kRNG);
+ break;
+ }
+ }
}
}
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc
index 43654f38..c3527eec 100644
--- a/src/aarch64/disasm-aarch64.cc
+++ b/src/aarch64/disasm-aarch64.cc
@@ -5585,6 +5585,12 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr,
case FPCR:
AppendToOutput("fpcr");
break;
+ case RNDR:
+ AppendToOutput("rndr");
+ break;
+ case RNDRRS:
+ AppendToOutput("rndrrs");
+ break;
default:
AppendToOutput("S%d_%d_c%d_c%d_%d",
instr->GetSysOp0(),
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index e7f9e9ce..dcf2ef86 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -113,6 +113,11 @@ Simulator::Simulator(Decoder* decoder, FILE* stream)
print_exclusive_access_warning_ = true;
guard_pages_ = false;
+
+ // Initialize the common state of RNDR and RNDRRS.
+ uint16_t seed[3] = {11, 22, 33};
+ VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rndr_state_));
+ memcpy(rndr_state_, seed, sizeof(rndr_state_));
}
@@ -3908,6 +3913,19 @@ void Simulator::VisitSystem(const Instruction* instr) {
case FPCR:
WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
break;
+ case RNDR:
+ case RNDRRS: {
+ uint64_t high = jrand48(rndr_state_);
+ uint64_t low = jrand48(rndr_state_);
+ uint64_t rand_num = (high << 32) | (low & 0xffffffff);
+ WriteXRegister(instr->GetRt(), rand_num);
+ // Simulate successful random number generation.
+ // TODO: Return failure occasionally as a random number cannot be
+ // returned in a period of time.
+ ReadNzcv().SetRawValue(NoFlag);
+ LogSystemRegister(NZCV);
+ break;
+ }
default:
VIXL_UNIMPLEMENTED();
}
diff --git a/src/aarch64/simulator-aarch64.h b/src/aarch64/simulator-aarch64.h
index 075a6061..13803e4f 100644
--- a/src/aarch64/simulator-aarch64.h
+++ b/src/aarch64/simulator-aarch64.h
@@ -3354,6 +3354,9 @@ class Simulator : public DecoderVisitor {
CPUFeaturesAuditor cpu_features_auditor_;
std::vector<CPUFeatures> saved_cpu_features_;
+
+ // The simulated state of RNDR and RNDRRS for generating a random number.
+ uint16_t rndr_state_[3];
};
#if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) && __cplusplus < 201402L
diff --git a/src/cpu-features.h b/src/cpu-features.h
index 25c49d7e..cd82d3c5 100644
--- a/src/cpu-features.h
+++ b/src/cpu-features.h
@@ -100,7 +100,9 @@ namespace vixl {
/* Branch target identification. */ \
V(kBTI, "BTI", NULL) \
/* Flag manipulation instructions: {AX,XA}FLAG */ \
- V(kAXFlag, "AXFlag", NULL)
+ V(kAXFlag, "AXFlag", NULL) \
+ /* Random number generation extension, */ \
+ V(kRNG, "RNG", NULL)
// clang-format on
diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc
index 5def1293..20f4057f 100644
--- a/test/aarch64/test-assembler-aarch64.cc
+++ b/test/aarch64/test-assembler-aarch64.cc
@@ -15026,6 +15026,45 @@ TEST(system_mrs) {
TEARDOWN();
}
+TEST(system_rng) {
+ SETUP_WITH_FEATURES(CPUFeatures::kRNG);
+
+ START();
+ // Random number.
+ __ Mrs(x1, RNDR);
+ // Assume that each generation is successful now.
+ // TODO: Return failure occasionally.
+ __ Mrs(x2, NZCV);
+ __ Mrs(x3, RNDR);
+ __ Mrs(x4, NZCV);
+
+ // Reseeded random number.
+ __ Mrs(x5, RNDRRS);
+ // Assume that each generation is successful now.
+ // TODO: Return failure occasionally.
+ __ Mrs(x6, NZCV);
+ __ Mrs(x7, RNDRRS);
+ __ Mrs(x8, NZCV);
+ END();
+
+#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
+ RUN();
+ // Random number generation series.
+ // Check random numbers have been generated and aren't equal when reseed has
+ // happened.
+ // NOTE: With a different architectural implementation, there may be a
+ // collison.
+ // TODO: Return failure occasionally. Set ZFlag and return UNKNOWN value.
+ ASSERT_NOT_EQUAL_64(x1, x3);
+ ASSERT_EQUAL_64(NoFlag, x2);
+ ASSERT_EQUAL_64(NoFlag, x4);
+ ASSERT_NOT_EQUAL_64(x5, x7);
+ ASSERT_EQUAL_64(NoFlag, x6);
+ ASSERT_EQUAL_64(NoFlag, x8);
+#endif
+
+ TEARDOWN();
+}
TEST(cfinv) {
SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
diff --git a/test/aarch64/test-disasm-aarch64.cc b/test/aarch64/test-disasm-aarch64.cc
index cdddf860..2dfedfc6 100644
--- a/test/aarch64/test-disasm-aarch64.cc
+++ b/test/aarch64/test-disasm-aarch64.cc
@@ -3232,6 +3232,8 @@ TEST(system_mrs) {
COMPARE(mrs(x0, NZCV), "mrs x0, nzcv");
COMPARE(mrs(x30, NZCV), "mrs x30, nzcv");
COMPARE(mrs(x15, FPCR), "mrs x15, fpcr");
+ COMPARE(mrs(x20, RNDR), "mrs x20, rndr");
+ COMPARE(mrs(x5, RNDRRS), "mrs x5, rndrrs");
// Test mrs that use system registers we haven't named.
COMPARE(dci(MRS | (0x5555 << 5)), "mrs x0, S3_2_c10_c10_5");
diff --git a/test/test-api.cc b/test/test-api.cc
index 219d4dfb..9b3d55dd 100644
--- a/test/test-api.cc
+++ b/test/test-api.cc
@@ -393,7 +393,7 @@ TEST(CPUFeatures_format) {
// Armv8.4
"RCpc (imm), FlagM, USCAT, FHM, DIT, "
// Armv8.5
- "BTI, AXFlag",
+ "BTI, AXFlag, RNG",
CPUFeatures::All());
}