Kernel: Implement super simple PRNG
This commit is contained in:
44
kernel/kernel/Random.cpp
Normal file
44
kernel/kernel/Random.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <kernel/Debug.h>
|
||||
#include <kernel/CPUID.h>
|
||||
#include <kernel/Random.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
||||
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
|
||||
|
||||
static uint64_t s_rand_seed = 0x4d595df4d0f33173;
|
||||
static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
||||
static constexpr uint64_t s_rand_increment = 1442695040888963407;
|
||||
|
||||
void Random::initialize()
|
||||
{
|
||||
uint32_t ecx, edx;
|
||||
CPUID::get_features(ecx, edx);
|
||||
|
||||
if (ecx & CPUID::ECX_RDRND)
|
||||
asm volatile("rdrand %0" : "=a"(s_rand_seed));
|
||||
else
|
||||
dprintln("No RDRAND available");
|
||||
}
|
||||
|
||||
uint32_t Random::get_u32()
|
||||
{
|
||||
auto rotr32 = [](uint32_t x, unsigned r) { return x >> r | x << (-r & 31); };
|
||||
|
||||
uint64_t x = s_rand_seed;
|
||||
unsigned count = (unsigned)(x >> 59);
|
||||
|
||||
s_rand_seed = x * s_rand_multiplier + s_rand_increment;
|
||||
x ^= x >> 18;
|
||||
|
||||
return rotr32(x >> 27, count) % UINT32_MAX;
|
||||
}
|
||||
|
||||
uint64_t Random::get_u64()
|
||||
{
|
||||
return ((uint64_t)get_u32() << 32) | get_u32();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user