2018-12-11 20:00:30 +00:00
|
|
|
/*
|
2019-05-18 12:21:47 +00:00
|
|
|
Copyright (c) 2018-2019, tevador <tevador@gmail.com>
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-05-18 12:21:47 +00:00
|
|
|
All rights reserved.
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-05-18 12:21:47 +00:00
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the copyright holder nor the
|
|
|
|
names of its contributors may be used to endorse or promote products
|
|
|
|
derived from this software without specific prior written permission.
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-05-18 12:21:47 +00:00
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2018-12-11 20:00:30 +00:00
|
|
|
*/
|
2019-04-20 14:53:06 +00:00
|
|
|
|
2019-04-26 09:07:47 +00:00
|
|
|
#pragma STDC FENV_ACCESS ON
|
2018-12-11 20:00:30 +00:00
|
|
|
#include <cfenv>
|
|
|
|
#include <cmath>
|
2019-02-09 14:45:26 +00:00
|
|
|
#include "common.hpp"
|
2019-04-20 14:53:06 +00:00
|
|
|
#include "intrin_portable.h"
|
|
|
|
#include "blake2/endian.h"
|
2018-12-11 20:00:30 +00:00
|
|
|
|
|
|
|
#if defined(__SIZEOF_INT128__)
|
|
|
|
typedef unsigned __int128 uint128_t;
|
|
|
|
typedef __int128 int128_t;
|
2019-02-04 16:07:00 +00:00
|
|
|
uint64_t mulh(uint64_t a, uint64_t b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
return ((uint128_t)a * b) >> 64;
|
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
int64_t smulh(int64_t a, int64_t b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
return ((int128_t)a * b) >> 64;
|
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
#define HAVE_MULH
|
|
|
|
#define HAVE_SMULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#define HAS_VALUE(X) X ## 0
|
|
|
|
#define EVAL_DEFINE(X) HAS_VALUE(X)
|
|
|
|
#include <intrin.h>
|
|
|
|
#include <stdlib.h>
|
2019-02-04 16:07:00 +00:00
|
|
|
|
|
|
|
uint64_t rotl(uint64_t x, int c) {
|
|
|
|
return _rotl64(x, c);
|
|
|
|
}
|
|
|
|
uint64_t rotr(uint64_t x , int c) {
|
|
|
|
return _rotr64(x, c);
|
|
|
|
}
|
|
|
|
#define HAVE_ROTL
|
|
|
|
#define HAVE_ROTR
|
|
|
|
|
2018-12-11 20:00:30 +00:00
|
|
|
#if EVAL_DEFINE(__MACHINEARM64_X64(1))
|
2019-02-04 16:07:00 +00:00
|
|
|
uint64_t mulh(uint64_t a, uint64_t b) {
|
|
|
|
return __umulh(a, b);
|
|
|
|
}
|
|
|
|
#define HAVE_MULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
2019-02-04 16:07:00 +00:00
|
|
|
|
2018-12-11 20:00:30 +00:00
|
|
|
#if EVAL_DEFINE(__MACHINEX64(1))
|
2019-02-04 16:07:00 +00:00
|
|
|
int64_t smulh(int64_t a, int64_t b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
int64_t hi;
|
|
|
|
_mul128(a, b, &hi);
|
|
|
|
return hi;
|
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
#define HAVE_SMULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
2019-02-04 16:07:00 +00:00
|
|
|
|
2019-04-22 16:20:46 +00:00
|
|
|
static void setRoundMode_(uint32_t mode) {
|
2019-02-04 16:07:00 +00:00
|
|
|
_controlfp(mode, _MCW_RC);
|
2018-12-11 20:00:30 +00:00
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
#define HAVE_SETROUNDMODE_IMPL
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#ifndef HAVE_SETROUNDMODE_IMPL
|
2019-04-22 16:20:46 +00:00
|
|
|
static void setRoundMode_(uint32_t mode) {
|
2019-02-04 16:07:00 +00:00
|
|
|
fesetround(mode);
|
|
|
|
}
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#ifndef HAVE_ROTR
|
|
|
|
uint64_t rotr(uint64_t a, int b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
return (a >> b) | (a << (64 - b));
|
|
|
|
}
|
2019-04-20 14:53:06 +00:00
|
|
|
#define HAVE_ROTR
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#ifndef HAVE_ROTL
|
|
|
|
uint64_t rotl(uint64_t a, int b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
return (a << b) | (a >> (64 - b));
|
|
|
|
}
|
2019-04-20 14:53:06 +00:00
|
|
|
#define HAVE_ROTL
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#ifndef HAVE_MULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#define LO(x) ((x)&0xffffffff)
|
|
|
|
#define HI(x) ((x)>>32)
|
2019-02-04 16:07:00 +00:00
|
|
|
uint64_t mulh(uint64_t a, uint64_t b) {
|
2018-12-11 20:00:30 +00:00
|
|
|
uint64_t ah = HI(a), al = LO(a);
|
|
|
|
uint64_t bh = HI(b), bl = LO(b);
|
|
|
|
uint64_t x00 = al * bl;
|
|
|
|
uint64_t x01 = al * bh;
|
|
|
|
uint64_t x10 = ah * bl;
|
|
|
|
uint64_t x11 = ah * bh;
|
|
|
|
uint64_t m1 = LO(x10) + LO(x01) + HI(x00);
|
|
|
|
uint64_t m2 = HI(x10) + HI(x01) + LO(x11) + HI(m1);
|
|
|
|
uint64_t m3 = HI(x11) + HI(m2);
|
|
|
|
|
|
|
|
return (m3 << 32) + LO(m2);
|
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
#define HAVE_MULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#ifndef HAVE_SMULH
|
|
|
|
int64_t smulh(int64_t a, int64_t b) {
|
|
|
|
int64_t hi = mulh(a, b);
|
2018-12-11 20:00:30 +00:00
|
|
|
if (a < 0LL) hi -= b;
|
|
|
|
if (b < 0LL) hi -= a;
|
|
|
|
return hi;
|
|
|
|
}
|
2019-02-04 16:07:00 +00:00
|
|
|
#define HAVE_SMULH
|
2018-12-11 20:00:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-05-14 07:13:38 +00:00
|
|
|
#ifdef RANDOMX_DEFAULT_FENV
|
|
|
|
|
|
|
|
void rx_reset_float_state() {
|
|
|
|
setRoundMode_(FE_TONEAREST);
|
2019-05-15 14:30:20 +00:00
|
|
|
rx_set_double_precision(); //set precision to 53 bits if needed by the platform
|
2019-05-14 07:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void rx_set_rounding_mode(uint32_t mode) {
|
|
|
|
switch (mode & 3) {
|
|
|
|
case RoundDown:
|
|
|
|
setRoundMode_(FE_DOWNWARD);
|
|
|
|
break;
|
|
|
|
case RoundUp:
|
|
|
|
setRoundMode_(FE_UPWARD);
|
|
|
|
break;
|
|
|
|
case RoundToZero:
|
|
|
|
setRoundMode_(FE_TOWARDZERO);
|
|
|
|
break;
|
|
|
|
case RoundToNearest:
|
|
|
|
setRoundMode_(FE_TONEAREST);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
2019-02-04 16:07:00 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-02-04 16:07:00 +00:00
|
|
|
#endif
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-05-15 14:30:20 +00:00
|
|
|
#ifdef RANDOMX_USE_X87
|
|
|
|
|
|
|
|
#ifdef _M_IX86
|
|
|
|
|
|
|
|
void rx_set_double_precision() {
|
|
|
|
_control87(_PC_53, _MCW_PC);
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(__i386)
|
|
|
|
|
|
|
|
void rx_set_double_precision() {
|
|
|
|
uint16_t volatile x87cw;
|
|
|
|
asm volatile("fstcw %0" : "=m" (x87cw));
|
|
|
|
x87cw &= ~0x300;
|
|
|
|
x87cw |= 0x200;
|
|
|
|
asm volatile("fldcw %0" : : "m" (x87cw));
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif //RANDOMX_USE_X87
|
|
|
|
|
2019-02-09 14:45:26 +00:00
|
|
|
union double_ser_t {
|
|
|
|
double f;
|
|
|
|
uint64_t i;
|
|
|
|
};
|
2018-12-11 20:00:30 +00:00
|
|
|
|
2019-02-09 14:45:26 +00:00
|
|
|
double loadDoublePortable(const void* addr) {
|
|
|
|
double_ser_t ds;
|
|
|
|
ds.i = load64(addr);
|
|
|
|
return ds.f;
|
|
|
|
}
|