From 04edf680e65e6aa55e64f56badf6a51a343fc890 Mon Sep 17 00:00:00 2001 From: TatWai Chong Date: Thu, 27 Dec 2018 16:01:02 -0800 Subject: Add support for random number generation. Arm8.5 introduces RNDR and RNDRRS which both return a 64-bit random number. Change-Id: I0d942c742232efae5f605233410935512c79b576 --- src/aarch64/constants-aarch64.h | 4 ++- src/aarch64/cpu-features-auditor-aarch64.cc | 9 +++++++ src/aarch64/disasm-aarch64.cc | 6 +++++ src/aarch64/simulator-aarch64.cc | 18 +++++++++++++ src/aarch64/simulator-aarch64.h | 3 +++ src/cpu-features.h | 4 ++- test/aarch64/test-assembler-aarch64.cc | 39 +++++++++++++++++++++++++++++ test/aarch64/test-disasm-aarch64.cc | 2 ++ test/test-api.cc | 2 +- 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 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 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()); } -- cgit v1.2.3