libcruft-util/rand/rdrand.cpp

49 lines
1.2 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#include "rdrand.hpp"
using cruft::rand::rdrand;
///////////////////////////////////////////////////////////////////////////////
rdrand::rdrand ()
{ ; }
//---------------------------------------------------------------------------------------
rdrand::rdrand (std::string const &)
: rdrand ()
{ ; }
///////////////////////////////////////////////////////////////////////////////
rdrand::result_type
rdrand::operator() ()
{
uint64_t res;
char success;
__asm__ __volatile__ (
"rdrand %0;"
"setc %1;"
: "=r" (res)
, "=qm" (success)
);
if (!__builtin_expect(success, 1))
throw std::runtime_error ("no value available for rdrand");
// As long as the u64 we just grabbed is of a type we can truncate then
// we'll do just that and return it.
static_assert (sizeof (result_type) <= sizeof (res));
static_assert (std::is_signed_v<result_type> == std::is_signed_v<decltype(res)>);
return static_cast<result_type> (res);
}