forked from catid/cm256
-
Notifications
You must be signed in to change notification settings - Fork 2
/
gf256.h
257 lines (192 loc) · 7.82 KB
/
gf256.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
Copyright (c) 2015 Christopher A. Taylor. All rights reserved.
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 CM256 nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
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.
*/
#ifndef GF256_H
#define GF256_H
#include <stdint.h> // uint32_t etc
#include <string.h> // memcpy, memset
// Library version
#define GF256_VERSION 2
// TBD: Fix the polynomial at one value and use precomputed tables here to
// simplify the API for GF256.h version 2. Avoids user data alignment issues.
//-----------------------------------------------------------------------------
// Platform-Specific Definitions
//
// Edit these to port to your architecture
#if defined(USE_SSSE3)
#ifdef _MSC_VER
// Compiler-specific 128-bit SIMD register keyword
#define GF256_M128 __m128i
// Compiler-specific C++11 restrict keyword
#define GF256_RESTRICT_KW __restrict
// Compiler-specific force inline keyword
#define GF256_FORCE_INLINE __forceinline
// Compiler-specific alignment keyword
#define GF256_ALIGNED __declspec(align(16))
// Compiler-specific SSE headers
#include <tmmintrin.h> // SSE3: _mm_shuffle_epi8
#include <emmintrin.h> // SSE2
#else
// Compiler-specific 128-bit SIMD register keyword
#define GF256_M128 __m128i
// Compiler-specific C++11 restrict keyword
#define GF256_RESTRICT_KW __restrict__
// Compiler-specific force inline keyword
#define GF256_FORCE_INLINE __attribute__((always_inline)) inline
// Compiler-specific alignment keyword
#define GF256_ALIGNED __attribute__((align(16)))
// Compiler-specific SSE headers
#include <x86intrin.h>
#endif
#elif defined(USE_NEON)
#include "sse2neon.h"
// Compiler-specific 128-bit SIMD register keyword
#define GF256_M128 __m128i
// Compiler-specific C++11 restrict keyword
#define GF256_RESTRICT_KW __restrict__
// Compiler-specific force inline keyword
#define GF256_FORCE_INLINE __attribute__((always_inline)) inline
// Compiler-specific alignment keyword
#define GF256_ALIGNED __attribute__((align(16)))
#endif
#if defined(NO_RESTRICT)
#define GF256_RESTRICT
#else
#define GF256_RESTRICT GF256_RESTRICT_KW
#endif
#ifndef nullptr
#define nullptr NULL
#endif
#ifdef __cplusplus
extern "C" {
#endif
//-----------------------------------------------------------------------------
// GF(256) Context
//
// The context object stores tables required to perform library calculations.
//
// Usage Notes:
// This struct should be aligned in memory, meaning that a pointer to it should
// have the low 4 bits cleared. To achieve this simply tag the gf256_ctx object
// with the GF256_ALIGNED macro provided above.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4324) // warning C4324: 'gf256_ctx' : structure was padded due to __declspec(align())
#endif
struct gf256_ctx // 141,072 bytes
{
// Polynomial used
unsigned Polynomial;
// Log/Exp tables
uint16_t GF256_LOG_TABLE[256];
uint8_t GF256_EXP_TABLE[512 * 2 + 1];
// Mul/Div/Inv tables
uint8_t GF256_MUL_TABLE[256 * 256];
uint8_t GF256_DIV_TABLE[256 * 256];
uint8_t GF256_INV_TABLE[256];
// Muladd_mem tables
// We require memory to be aligned since the SIMD instructions benefit from
// aligned accesses to the MM256_* table data.
GF256_M128 MM256_TABLE_LO_Y[256];
GF256_M128 MM256_TABLE_HI_Y[256];
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
extern gf256_ctx GF256Ctx;
//-----------------------------------------------------------------------------
// Initialization
//
// Initialize a context, filling in the tables.
//
// Thread-safety / Usage Notes:
//
// It is perfectly safe and encouraged to use a gf256_ctx object from multiple
// threads. The gf256_init() is relatively expensive and should only be done
// once, though it will take less than a millisecond.
//
// The gf256_ctx object must be aligned to 16 byte boundary.
// Simply tag the object with GF256_ALIGNED to achieve this.
//
// Example:
// static GF256_ALIGNED gf256_ctx TheGF256Context;
// gf256_init(&TheGF256Context, 0);
//
// Returns 0 on success and other values on failure.
extern int gf256_init_(int version);
#define gf256_init() gf256_init_(GF256_VERSION)
//-----------------------------------------------------------------------------
// Math Operations
// return x + y
static GF256_FORCE_INLINE uint8_t gf256_add(uint8_t x, uint8_t y)
{
return x ^ y;
}
// return x * y
// For repeated multiplication by a constant, it is faster to put the constant in y.
static GF256_FORCE_INLINE uint8_t gf256_mul(uint8_t x, uint8_t y)
{
return GF256Ctx.GF256_MUL_TABLE[((unsigned)y << 8) + x];
}
// return x / y
// Memory-access optimized for constant divisors in y.
static GF256_FORCE_INLINE uint8_t gf256_div(uint8_t x, uint8_t y)
{
return GF256Ctx.GF256_DIV_TABLE[((unsigned)y << 8) + x];
}
// return 1 / x
static GF256_FORCE_INLINE uint8_t gf256_inv(uint8_t x)
{
return GF256Ctx.GF256_INV_TABLE[x];
}
// Performs "x[] += y[]" bulk memory XOR operation
extern void gf256_add_mem(void * GF256_RESTRICT vx,
const void * GF256_RESTRICT vy, int bytes);
// Performs "z[] += x[] + y[]" bulk memory operation
extern void gf256_add2_mem(void * GF256_RESTRICT vz, const void * GF256_RESTRICT vx,
const void * GF256_RESTRICT vy, int bytes);
// Performs "z[] = x[] + y[]" bulk memory operation
extern void gf256_addset_mem(void * GF256_RESTRICT vz, const void * GF256_RESTRICT vx,
const void * GF256_RESTRICT vy, int bytes);
// Performs "z[] += x[] * y" bulk memory operation
extern void gf256_muladd_mem(void * GF256_RESTRICT vz, uint8_t y,
const void * GF256_RESTRICT vx, int bytes);
// Performs "z[] = x[] * y" bulk memory operation
extern void gf256_mul_mem(void * GF256_RESTRICT vz,
const void * GF256_RESTRICT vx, uint8_t y, int bytes);
// Performs "x[] /= y" bulk memory operation
static GF256_FORCE_INLINE void gf256_div_mem(void * GF256_RESTRICT vz,
const void * GF256_RESTRICT vx, uint8_t y, int bytes)
{
// Multiply by inverse
gf256_mul_mem(vz, vx, GF256Ctx.GF256_INV_TABLE[y], bytes);
}
//-----------------------------------------------------------------------------
// Misc Operations
// Swap two memory buffers in-place
extern void gf256_memswap(void * GF256_RESTRICT vx, void * GF256_RESTRICT vy, int bytes);
#ifdef __cplusplus
}
#endif
#endif // GF256_H