5#include "force_inline.h"
6#include "unreachable.h"
8#include "hashx_endian.h"
10#if defined(__SIZEOF_INT128__)
11typedef unsigned __int128 uint128_t;
12typedef __int128 int128_t;
13static FORCE_INLINE uint64_t umulh(uint64_t a, uint64_t b) {
14 return ((uint128_t)a * b) >> 64;
16static FORCE_INLINE int64_t smulh(int64_t a, int64_t b) {
17 return ((int128_t)a * b) >> 64;
24#pragma warning (disable : 4146)
25#define HAS_VALUE(X) X ## 0
26#define EVAL_DEFINE(X) HAS_VALUE(X)
30static FORCE_INLINE uint64_t rotr64(uint64_t x,
unsigned int c) {
36#if EVAL_DEFINE(__MACHINEARM64_X64(1))
37static FORCE_INLINE uint64_t umulh(uint64_t a, uint64_t b) {
43#if EVAL_DEFINE(__MACHINEX64(1))
44static FORCE_INLINE int64_t smulh(int64_t a, int64_t b) {
55static FORCE_INLINE uint64_t rotr64(uint64_t a,
unsigned int b) {
56 return (a >> b) | (a << (64 - b));
62#define LO(x) ((x)&0xffffffff)
63#define HI(x) ((x)>>32)
64static uint64_t umulh(uint64_t a, uint64_t b) {
65 uint64_t ah = HI(a), al = LO(a);
66 uint64_t bh = HI(b), bl = LO(b);
67 uint64_t x00 = al * bl;
68 uint64_t x01 = al * bh;
69 uint64_t x10 = ah * bl;
70 uint64_t x11 = ah * bh;
71 uint64_t m1 = LO(x10) + LO(x01) + HI(x00);
72 uint64_t m2 = HI(x10) + HI(x01) + LO(x11) + HI(m1);
73 uint64_t m3 = HI(x11) + HI(m2);
75 return (m3 << 32) + LO(m2);
83static int64_t smulh(int64_t a, int64_t b) {
84 int64_t hi = umulh(a, b);
92static FORCE_INLINE uint64_t sign_extend_2s_compl(uint32_t x) {
94 (uint64_t)(int64_t)(int32_t)(x) :
95 (x > INT32_MAX ? (x | 0xffffffff00000000ULL) : (uint64_t)x);
98void hashx_program_execute(
const hashx_program* program, uint64_t r[8]) {
100 bool branch_enable =
true;
102#ifdef HASHX_PROGRAM_STATS
105 for (
size_t i = 0; i < program->code_size; ++i) {
107 switch (instr->opcode)
110 result = (uint32_t) (r[instr->dst] = umulh(r[instr->dst],
114 result = (uint32_t) (r[instr->dst] = smulh(r[instr->dst],
118 r[instr->dst] *= r[instr->src];
121 r[instr->dst] -= r[instr->src];
124 r[instr->dst] ^= r[instr->src];
127 r[instr->dst] += r[instr->src] << instr->imm32;
130 r[instr->dst] = rotr64(r[instr->dst], instr->imm32);
133 r[instr->dst] += sign_extend_2s_compl(instr->imm32);
136 r[instr->dst] ^= sign_extend_2s_compl(instr->imm32);
142 if (branch_enable && (result & instr->imm32) == 0) {
144 branch_enable =
false;
145#ifdef HASHX_PROGRAM_STATS
150#ifdef HASHX_PROGRAM_STATS