9
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
15
/** Element of a big integer */
16
typedef uint64_t bigint_element_t;
19
* Initialise big integer
21
* @v value0 Element 0 of big integer to initialise
22
* @v size Number of elements
24
* @v len Length of raw data
26
static inline __attribute__ (( always_inline )) void
27
bigint_init_raw ( uint64_t *value0, unsigned int size,
28
const void *data, size_t len ) {
29
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
30
uint8_t *value_byte = ( ( void * ) value0 );
31
const uint8_t *data_byte = ( data + len );
33
/* Copy raw data in reverse order, padding with zeros */
35
*(value_byte++) = *(--data_byte);
43
* @v addend0 Element 0 of big integer to add
44
* @v value0 Element 0 of big integer to be added to
45
* @v size Number of elements
47
static inline __attribute__ (( always_inline )) void
48
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
50
bigint_t ( size ) __attribute__ (( may_alias )) *value =
51
( ( void * ) value0 );
52
uint64_t *discard_addend;
53
uint64_t *discard_value;
54
uint64_t discard_addend_i;
55
uint64_t discard_value_i;
56
unsigned int discard_size;
58
__asm__ __volatile__ ( "cmn xzr, xzr\n\t" /* clear CF */
60
"ldr %3, [%0], #8\n\t"
63
"str %4, [%1], #8\n\t"
64
"sub %w2, %w2, #1\n\t"
66
: "=r" ( discard_addend ),
67
"=r" ( discard_value ),
68
"=r" ( discard_size ),
69
"=r" ( discard_addend_i ),
70
"=r" ( discard_value_i ),
72
: "0" ( addend0 ), "1" ( value0 ), "2" ( size )
77
* Subtract big integers
79
* @v subtrahend0 Element 0 of big integer to subtract
80
* @v value0 Element 0 of big integer to be subtracted from
81
* @v size Number of elements
83
static inline __attribute__ (( always_inline )) void
84
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
86
bigint_t ( size ) __attribute__ (( may_alias )) *value =
87
( ( void * ) value0 );
88
uint64_t *discard_subtrahend;
89
uint64_t *discard_value;
90
uint64_t discard_subtrahend_i;
91
uint64_t discard_value_i;
92
unsigned int discard_size;
94
__asm__ __volatile__ ( "cmp xzr, xzr\n\t" /* set CF */
96
"ldr %3, [%0], #8\n\t"
99
"str %4, [%1], #8\n\t"
100
"sub %w2, %w2, #1\n\t"
102
: "=r" ( discard_subtrahend ),
103
"=r" ( discard_value ),
104
"=r" ( discard_size ),
105
"=r" ( discard_subtrahend_i ),
106
"=r" ( discard_value_i ),
108
: "0" ( subtrahend0 ), "1" ( value0 ),
114
* Rotate big integer left
116
* @v value0 Element 0 of big integer
117
* @v size Number of elements
119
static inline __attribute__ (( always_inline )) void
120
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
121
bigint_t ( size ) __attribute__ (( may_alias )) *value =
122
( ( void * ) value0 );
123
uint64_t *discard_value;
124
uint64_t discard_value_i;
125
unsigned int discard_size;
127
__asm__ __volatile__ ( "cmn xzr, xzr\n\t" /* clear CF */
130
"adcs %2, %2, %2\n\t"
131
"str %2, [%0], #8\n\t"
132
"sub %w1, %w1, #1\n\t"
134
: "=r" ( discard_value ),
135
"=r" ( discard_size ),
136
"=r" ( discard_value_i ),
138
: "0" ( value0 ), "1" ( size )
143
* Rotate big integer right
145
* @v value0 Element 0 of big integer
146
* @v size Number of elements
148
static inline __attribute__ (( always_inline )) void
149
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
150
bigint_t ( size ) __attribute__ (( may_alias )) *value =
151
( ( void * ) value0 );
152
uint64_t *discard_value;
153
uint64_t discard_value_i;
154
uint64_t discard_value_j;
155
unsigned int discard_size;
157
__asm__ __volatile__ ( "mov %3, #0\n\t"
159
"sub %w1, %w1, #1\n\t"
160
"ldr %2, [%0, %1, lsl #3]\n\t"
161
"extr %3, %3, %2, #1\n\t"
162
"str %3, [%0, %1, lsl #3]\n\t"
165
: "=r" ( discard_value ),
166
"=r" ( discard_size ),
167
"=r" ( discard_value_i ),
168
"=r" ( discard_value_j ),
170
: "0" ( value0 ), "1" ( size ) );
174
* Test if big integer is equal to zero
176
* @v value0 Element 0 of big integer
177
* @v size Number of elements
178
* @ret is_zero Big integer is equal to zero
180
static inline __attribute__ (( always_inline, pure )) int
181
bigint_is_zero_raw ( const uint64_t *value0, unsigned int size ) {
182
const uint64_t *value = value0;
186
value_i = *(value++);
191
return ( value_i == 0 );
195
* Compare big integers
197
* @v value0 Element 0 of big integer
198
* @v reference0 Element 0 of reference big integer
199
* @v size Number of elements
200
* @ret geq Big integer is greater than or equal to the reference
202
static inline __attribute__ (( always_inline, pure )) int
203
bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
204
unsigned int size ) {
205
const uint64_t *value = ( value0 + size );
206
const uint64_t *reference = ( reference0 + size );
208
uint64_t reference_i;
211
value_i = *(--value);
212
reference_i = *(--reference);
213
if ( value_i != reference_i )
217
return ( value_i >= reference_i );
221
* Test if bit is set in big integer
223
* @v value0 Element 0 of big integer
224
* @v size Number of elements
226
* @ret is_set Bit is set
228
static inline __attribute__ (( always_inline )) int
229
bigint_bit_is_set_raw ( const uint64_t *value0, unsigned int size,
231
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
232
( ( const void * ) value0 );
233
unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
234
unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
236
return ( !! ( value->element[index] & ( 1UL << subindex ) ) );
240
* Find highest bit set in big integer
242
* @v value0 Element 0 of big integer
243
* @v size Number of elements
244
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
246
static inline __attribute__ (( always_inline )) int
247
bigint_max_set_bit_raw ( const uint64_t *value0, unsigned int size ) {
248
const uint64_t *value = ( value0 + size );
249
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
253
value_i = *(--value);
254
max_bit -= ( 64 - fls ( value_i ) );
265
* @v source0 Element 0 of source big integer
266
* @v source_size Number of elements in source big integer
267
* @v dest0 Element 0 of destination big integer
268
* @v dest_size Number of elements in destination big integer
270
static inline __attribute__ (( always_inline )) void
271
bigint_grow_raw ( const uint64_t *source0, unsigned int source_size,
272
uint64_t *dest0, unsigned int dest_size ) {
273
unsigned int pad_size = ( dest_size - source_size );
275
memcpy ( dest0, source0, sizeof ( bigint_t ( source_size ) ) );
276
memset ( ( dest0 + source_size ), 0, sizeof ( bigint_t ( pad_size ) ) );
282
* @v source0 Element 0 of source big integer
283
* @v source_size Number of elements in source big integer
284
* @v dest0 Element 0 of destination big integer
285
* @v dest_size Number of elements in destination big integer
287
static inline __attribute__ (( always_inline )) void
288
bigint_shrink_raw ( const uint64_t *source0, unsigned int source_size __unused,
289
uint64_t *dest0, unsigned int dest_size ) {
291
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
295
* Finalise big integer
297
* @v value0 Element 0 of big integer to finalise
298
* @v size Number of elements
299
* @v out Output buffer
300
* @v len Length of output buffer
302
static inline __attribute__ (( always_inline )) void
303
bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
304
void *out, size_t len ) {
305
const uint8_t *value_byte = ( ( const void * ) value0 );
306
uint8_t *out_byte = ( out + len );
308
/* Copy raw data in reverse order */
310
*(--out_byte) = *(value_byte++);
313
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
314
const uint64_t *multiplier0,
315
uint64_t *value0, unsigned int size );
317
#endif /* _BITS_BIGINT_H */