Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
program_exec.c
1/* Copyright (c) 2020 tevador <tevador@gmail.com> */
2/* See LICENSE for licensing information */
3
4#include "program.h"
5#include "force_inline.h"
6#include "unreachable.h"
7#include "siphash.h"
8#include "hashx_endian.h"
9
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;
15 }
16static FORCE_INLINE int64_t smulh(int64_t a, int64_t b) {
17 return ((int128_t)a * b) >> 64;
18}
19#define HAVE_UMULH
20#define HAVE_SMULH
21#endif
22
23#if defined(_MSC_VER)
24#pragma warning (disable : 4146) /* unary minus applied to unsigned type */
25#define HAS_VALUE(X) X ## 0
26#define EVAL_DEFINE(X) HAS_VALUE(X)
27#include <intrin.h>
28#include <stdlib.h>
29
30static FORCE_INLINE uint64_t rotr64(uint64_t x, unsigned int c) {
31 return _rotr64(x, c);
32}
33
34#define HAVE_ROTR
35
36#if EVAL_DEFINE(__MACHINEARM64_X64(1))
37static FORCE_INLINE uint64_t umulh(uint64_t a, uint64_t b) {
38 return __umulh(a, b);
39}
40#define HAVE_UMULH
41#endif
42
43#if EVAL_DEFINE(__MACHINEX64(1))
44static FORCE_INLINE int64_t smulh(int64_t a, int64_t b) {
45 int64_t hi;
46 _mul128(a, b, &hi);
47 return hi;
48}
49#define HAVE_SMULH
50#endif
51
52#endif
53
54#ifndef HAVE_ROTR
55static FORCE_INLINE uint64_t rotr64(uint64_t a, unsigned int b) {
56 return (a >> b) | (a << (64 - b));
57}
58#define HAVE_ROTR
59#endif
60
61#ifndef HAVE_UMULH
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);
74
75 return (m3 << 32) + LO(m2);
76}
77#undef LO
78#undef HI
79#define HAVE_UMULH
80#endif
81
82#ifndef HAVE_SMULH
83static int64_t smulh(int64_t a, int64_t b) {
84 int64_t hi = umulh(a, b);
85 if (a < 0LL) hi -= b;
86 if (b < 0LL) hi -= a;
87 return hi;
88}
89#define HAVE_SMULH
90#endif
91
92static FORCE_INLINE uint64_t sign_extend_2s_compl(uint32_t x) {
93 return (-1 == ~0) ?
94 (uint64_t)(int64_t)(int32_t)(x) :
95 (x > INT32_MAX ? (x | 0xffffffff00000000ULL) : (uint64_t)x);
96}
97
98void hashx_program_execute(const hashx_program* program, uint64_t r[8]) {
99 size_t target = 0;
100 bool branch_enable = true;
101 uint32_t result = 0;
102#ifdef HASHX_PROGRAM_STATS
103 int branch_idx = 0;
104#endif
105 for (size_t i = 0; i < program->code_size; ++i) {
106 const instruction* instr = &program->code[i];
107 switch (instr->opcode)
108 {
109 case INSTR_UMULH_R:
110 result = (uint32_t) (r[instr->dst] = umulh(r[instr->dst],
111 r[instr->src]));
112 break;
113 case INSTR_SMULH_R:
114 result = (uint32_t) (r[instr->dst] = smulh(r[instr->dst],
115 r[instr->src]));
116 break;
117 case INSTR_MUL_R:
118 r[instr->dst] *= r[instr->src];
119 break;
120 case INSTR_SUB_R:
121 r[instr->dst] -= r[instr->src];
122 break;
123 case INSTR_XOR_R:
124 r[instr->dst] ^= r[instr->src];
125 break;
126 case INSTR_ADD_RS:
127 r[instr->dst] += r[instr->src] << instr->imm32;
128 break;
129 case INSTR_ROR_C:
130 r[instr->dst] = rotr64(r[instr->dst], instr->imm32);
131 break;
132 case INSTR_ADD_C:
133 r[instr->dst] += sign_extend_2s_compl(instr->imm32);
134 break;
135 case INSTR_XOR_C:
136 r[instr->dst] ^= sign_extend_2s_compl(instr->imm32);
137 break;
138 case INSTR_TARGET:
139 target = i;
140 break;
141 case INSTR_BRANCH:
142 if (branch_enable && (result & instr->imm32) == 0) {
143 i = target;
144 branch_enable = false;
145#ifdef HASHX_PROGRAM_STATS
146 ((hashx_program*)program)->branch_count++;
147 ((hashx_program*)program)->branches[branch_idx]++;
148#endif
149 }
150#ifdef HASHX_PROGRAM_STATS
151 branch_idx++;
152#endif
153 break;
154 default:
155 UNREACHABLE;
156 }
157 }
158}