/src/blst_normal/src/bytes.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright Supranational LLC |
3 | | * Licensed under the Apache License, Version 2.0, see LICENSE for details. |
4 | | * SPDX-License-Identifier: Apache-2.0 |
5 | | */ |
6 | | #ifndef __BLS12_381_ASM_BYTES_H__ |
7 | | #define __BLS12_381_ASM_BYTES_H__ |
8 | | |
9 | | static inline void bytes_zero(unsigned char *a, size_t num) |
10 | 4.30k | { |
11 | 4.30k | size_t i; |
12 | | |
13 | 619k | for (i = 0; i < num; i++) |
14 | 615k | a[i] = 0; |
15 | 4.30k | } |
16 | | |
17 | | static inline void limbs_from_be_bytes(limb_t *restrict ret, |
18 | | const unsigned char *in, size_t n) |
19 | 10.5k | { |
20 | 10.5k | limb_t limb = 0; |
21 | | |
22 | 661k | while(n--) { |
23 | 650k | limb <<= 8; |
24 | 650k | limb |= *in++; |
25 | | /* |
26 | | * 'if (n % sizeof(limb_t) == 0)' is omitted because it's cheaper |
27 | | * to perform redundant stores than to pay penalty for |
28 | | * mispredicted branch. Besides, some compilers unroll the |
29 | | * loop and remove redundant stores to 'restrict'-ed storage... |
30 | | */ |
31 | 650k | ret[n / sizeof(limb_t)] = limb; |
32 | 650k | } |
33 | 10.5k | } |
34 | | |
35 | | static inline void be_bytes_from_limbs(unsigned char *out, const limb_t *in, |
36 | | size_t n) |
37 | 563 | { |
38 | 563 | limb_t limb; |
39 | | |
40 | 27.5k | while(n--) { |
41 | 27.0k | limb = in[n / sizeof(limb_t)]; |
42 | 27.0k | *out++ = (unsigned char)(limb >> (8 * (n % sizeof(limb_t)))); |
43 | 27.0k | } |
44 | 563 | } |
45 | | |
46 | | static inline void limbs_from_le_bytes(limb_t *restrict ret, |
47 | | const unsigned char *in, size_t n) |
48 | 6.25k | { |
49 | 6.25k | limb_t limb = 0; |
50 | | |
51 | 206k | while(n--) { |
52 | 200k | limb <<= 8; |
53 | 200k | limb |= in[n]; |
54 | | /* |
55 | | * 'if (n % sizeof(limb_t) == 0)' is omitted because it's cheaper |
56 | | * to perform redundant stores than to pay penalty for |
57 | | * mispredicted branch. Besides, some compilers unroll the |
58 | | * loop and remove redundant stores to 'restrict'-ed storage... |
59 | | */ |
60 | 200k | ret[n / sizeof(limb_t)] = limb; |
61 | 200k | } |
62 | 6.25k | } |
63 | | |
64 | | static inline void le_bytes_from_limbs(unsigned char *out, const limb_t *in, |
65 | | size_t n) |
66 | 6.35k | { |
67 | 6.35k | const union { |
68 | 6.35k | long one; |
69 | 6.35k | char little; |
70 | 6.35k | } is_endian = { 1 }; |
71 | 6.35k | limb_t limb; |
72 | 6.35k | size_t i, j, r; |
73 | | |
74 | 6.35k | if ((uptr_t)out == (uptr_t)in && is_endian.little) |
75 | 6.25k | return; |
76 | | |
77 | 98 | r = n % sizeof(limb_t); |
78 | 98 | n /= sizeof(limb_t); |
79 | | |
80 | 490 | for(i = 0; i < n; i++) { |
81 | 3.52k | for (limb = in[i], j = 0; j < sizeof(limb_t); j++, limb >>= 8) |
82 | 3.13k | *out++ = (unsigned char)limb; |
83 | 392 | } |
84 | 98 | if (r) { |
85 | 0 | for (limb = in[i], j = 0; j < r; j++, limb >>= 8) |
86 | 0 | *out++ = (unsigned char)limb; |
87 | 0 | } |
88 | 98 | } |
89 | | |
90 | | static inline char hex_from_nibble(unsigned char nibble) |
91 | 0 | { |
92 | 0 | int mask = (9 - (nibble &= 0xf)) >> 31; |
93 | 0 | return (char)(nibble + ((('a'-10) & mask) | ('0' & ~mask))); |
94 | 0 | } |
95 | | |
96 | | static unsigned char nibble_from_hex(char c) |
97 | 0 | { |
98 | 0 | int mask, ret; |
99 | |
|
100 | 0 | mask = (('a'-c-1) & (c-1-'f')) >> 31; |
101 | 0 | ret = (10 + c - 'a') & mask; |
102 | 0 | mask = (('A'-c-1) & (c-1-'F')) >> 31; |
103 | 0 | ret |= (10 + c - 'A') & mask; |
104 | 0 | mask = (('0'-c-1) & (c-1-'9')) >> 31; |
105 | 0 | ret |= (c - '0') & mask; |
106 | 0 | mask = ((ret-1) & ~mask) >> 31; |
107 | 0 | ret |= 16 & mask; |
108 | |
|
109 | 0 | return (unsigned char)ret; |
110 | 0 | } |
111 | | |
112 | | static void bytes_from_hexascii(unsigned char *ret, size_t sz, const char *hex) |
113 | 0 | { |
114 | 0 | size_t len; |
115 | 0 | unsigned char b = 0; |
116 | |
|
117 | 0 | if (hex[0]=='0' && (hex[1]=='x' || hex[1]=='X')) |
118 | 0 | hex += 2; |
119 | |
|
120 | 0 | for (len = 0; len<2*sz && nibble_from_hex(hex[len])<16; len++) ; |
121 | |
|
122 | 0 | bytes_zero(ret, sz); |
123 | |
|
124 | 0 | while(len--) { |
125 | 0 | b <<= 4; |
126 | 0 | b |= nibble_from_hex(*hex++); |
127 | 0 | if (len % 2 == 0) |
128 | 0 | ret[len / 2] = b; |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | static void limbs_from_hexascii(limb_t *ret, size_t sz, const char *hex) |
133 | 0 | { |
134 | 0 | size_t len; |
135 | 0 | limb_t limb = 0; |
136 | |
|
137 | 0 | if (hex[0]=='0' && (hex[1]=='x' || hex[1]=='X')) |
138 | 0 | hex += 2; |
139 | |
|
140 | 0 | for (len = 0; len<2*sz && nibble_from_hex(hex[len])<16; len++) ; |
141 | |
|
142 | 0 | vec_zero(ret, sz); |
143 | |
|
144 | 0 | while(len--) { |
145 | 0 | limb <<= 4; |
146 | 0 | limb |= nibble_from_hex(*hex++); |
147 | 0 | if (len % (2*sizeof(limb_t)) == 0) |
148 | 0 | ret[len / (2*sizeof(limb_t))] = limb; |
149 | 0 | } |
150 | 0 | } |
151 | | |
152 | | #endif |