Skip to content

Commit c0fd917

Browse files
committed
WiP
1 parent 91164ac commit c0fd917

File tree

12 files changed

+214
-34
lines changed

12 files changed

+214
-34
lines changed

src/attributes.h

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
# define unlikely(params) (params)
2525

2626
#else // _MSC_VER
27+
#if defined __has_builtin
28+
# define has_builtin(params) __has_builtin(params)
29+
#else
30+
# define has_builtin(params) (0)
31+
#endif
32+
2733
# if (zone_has_attribute(always_inline) || zone_has_gnuc(3, 1)) && ! defined __NO_INLINE__
2834
// Compilation using GCC 4.2.1 without optimizations fails.
2935
// sorry, unimplemented: inlining failed in call to ...

src/fallback/bits.h

+45
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,60 @@ static really_inline uint64_t leading_zeroes(uint64_t mask)
2929
else
3030
return 64;
3131
}
32+
3233
#else
34+
3335
static really_inline uint64_t trailing_zeroes(uint64_t mask)
3436
{
37+
#if has_builtin(__builtin_ctzll)
3538
return (uint64_t)__builtin_ctzll(mask);
39+
#else
40+
// Code by Kim Walish from https://www.chessprogramming.org/BitScan.
41+
// Distributed under CC BY-SA 3.0.
42+
static const uint64_t magic = 0x03f79d71b4cb0a89ull;
43+
const int magictable[64] = {
44+
0, 47, 1, 56, 48, 27, 2, 60,
45+
57, 49, 41, 37, 28, 16, 3, 61,
46+
54, 58, 35, 52, 50, 42, 21, 44,
47+
38, 32, 29, 23, 17, 11, 4, 62,
48+
46, 55, 26, 59, 40, 36, 15, 53,
49+
34, 51, 20, 43, 31, 22, 10, 45,
50+
25, 39, 14, 33, 19, 30, 9, 24,
51+
13, 18, 8, 12, 7, 6, 5, 63
52+
};
53+
54+
return magictable[((mask ^ (mask - 1)) * magic) >> 58];
55+
#endif
3656
}
3757

3858
static really_inline uint64_t leading_zeroes(uint64_t mask)
3959
{
60+
#if has_builtin(__builtin_clzll)
4061
return (uint64_t)__builtin_clzll(mask);
62+
#else
63+
// Code by Kim Walish from https://www.chessprogramming.org/BitScan.
64+
// Distributed under CC BY-SA 3.0.
65+
static const uint64_t magic = 0x03f79d71b4cb0a89ull;
66+
const int magictable[64] = {
67+
63, 16, 62, 7, 15, 36, 61, 3,
68+
6, 14, 22, 26, 35, 47, 60, 2,
69+
9, 5, 28, 11, 13, 21, 42, 19,
70+
25, 31, 34, 40, 46, 52, 59, 1,
71+
17, 8, 37, 4, 23, 27, 48, 10,
72+
29, 12, 43, 20, 32, 41, 53, 18,
73+
38, 24, 49, 30, 44, 33, 54, 39,
74+
50, 45, 55, 51, 56, 57, 58, 0
75+
};
76+
77+
mask |= mask >> 1;
78+
mask |= mask >> 2;
79+
mask |= mask >> 4;
80+
mask |= mask >> 8;
81+
mask |= mask >> 16;
82+
mask |= mask >> 32;
83+
84+
return magictable[(mask * magic) >> 58];
85+
#endif
4186
}
4287
#endif // _MSC_VER
4388
#endif // BITS_H

src/generic/base16.h

+4
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ static really_inline int base16_stream_decode(
173173
// Duff's device again:
174174
switch (st.bytes)
175175
{
176+
#if defined __SUNPRO_C
177+
#pragma error_messages(off, E_STATEMENT_NOT_REACHED)
176178
for (;;)
179+
#pragma error_messages(default, E_STATEMENT_NOT_REACHED)
180+
#endif
177181
{
178182
case 0:
179183
base16_dec_loop_generic_32(&s, &slen, &o, &olen);

src/generic/base64.h

+4
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,11 @@ static really_inline int base64_stream_decode(
575575
// Duff's device again:
576576
switch (st.bytes)
577577
{
578+
#if defined __SUNPRO_C
579+
#pragma error_messages(off, E_STATEMENT_NOT_REACHED)
578580
for (;;)
581+
#pragma error_messages(default, E_STATEMENT_NOT_REACHED)
582+
#endif
579583
{
580584
case 0:
581585
dec_loop_generic_32(&s, &slen, &o, &olen);

src/generic/endian.h

+84
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,90 @@
7575

7676
#else
7777
#include <endian.h>
78+
79+
static really_inline uint16_t bswap16(uint16_t x)
80+
{
81+
// Copied from src/common/lib/libc/gen/bswap16.c in NetBSD
82+
// Written by Manuel Bouyer <[email protected]>.
83+
// Public domain.
84+
return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff);
85+
}
86+
87+
static really_inline uint32_t bswap32(uint32_t x)
88+
{
89+
// Copied from src/common/lib/libc/gen/bswap32.c in NetBSD
90+
// Written by Manuel Bouyer <[email protected]>.
91+
// Public domain.
92+
return ( (x << 24) & 0xff000000 ) |
93+
( (x << 8) & 0x00ff0000 ) |
94+
( (x >> 8) & 0x0000ff00 ) |
95+
( (x >> 24) & 0x000000ff );
96+
}
97+
98+
static really_inline uint64_t bswap64(uint64_t x)
99+
{
100+
// Copied from src/common/lib/libc/gen/bswap64.c in NetBSD
101+
// Written by Manuel Bouyer <[email protected]>.
102+
// Public domain.
103+
return ( (x << 56) & 0xff00000000000000ull ) |
104+
( (x << 40) & 0x00ff000000000000ull ) |
105+
( (x << 24) & 0x0000ff0000000000ull ) |
106+
( (x << 8) & 0x000000ff00000000ull ) |
107+
( (x >> 8) & 0x00000000ff000000ull ) |
108+
( (x >> 24) & 0x0000000000ff0000ull ) |
109+
( (x >> 40) & 0x000000000000ff00ull ) |
110+
( (x >> 56) & 0x00000000000000ffull );
111+
}
112+
113+
# if BYTE_ORDER == LITTLE_ENDIAN
114+
# define htobe(bits, x) bswap ## bits((x))
115+
# define htole(bits, x) (x)
116+
# define betoh(bits, x) bswap ## bits((x))
117+
# define letoh(bits, x) (x)
118+
# else
119+
# define htobe(bits, x) (x)
120+
# define htole(bits, x) bswap ## bits((x))
121+
# define betoh(bits, x) (x)
122+
# define letoh(bits, x) bswap ## bits((x))
123+
# endif
124+
125+
# if !defined htobe16
126+
# define htobe16(x) htobe(16,(x))
127+
# endif
128+
# if !defined htobe32
129+
# define htobe32(x) htobe(32,(x))
130+
# endif
131+
# if !defined htobe64
132+
# define htobe64(x) htobe(64,(x))
133+
# endif
134+
# if !defined htole16
135+
# define htole16(x) htole(16,(x))
136+
# endif
137+
# if !defined htole32
138+
# define htole32(x) htole(32,(x))
139+
# endif
140+
# if !defined htole64
141+
# define htole64(x) htole(64,(x))
142+
# endif
143+
144+
# if !defined be16toh
145+
# define be16toh(x) betoh(16,(x))
146+
# endif
147+
# if !defined be32toh
148+
# define be32toh(x) betoh(32,(x))
149+
# endif
150+
# if !defined be64toh
151+
# define be64toh(x) betoh(64,(x))
152+
# endif
153+
# if !defined le16toh
154+
# define le16toh(x) letoh(16,(x))
155+
# endif
156+
# if !defined le32toh
157+
# define le32toh(x) letoh(32,(x))
158+
# endif
159+
# if !defined le64toh
160+
# define le64toh(x) letoh(64,(x))
161+
# endif
78162
#endif
79163

80164
#endif // ENDIAN_H

src/generic/types.h

+14-21
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,8 @@ static really_inline int32_t parse_text(
6666
#define UNKNOWN_TYPE(code) \
6767
{ { { "", 0 }, code }, 0, false, false, { 0, NULL }, check_generic_rr, parse_unknown_rdata }
6868

69-
#if _WIN32
70-
// FIXME: check functions can be simplified as int32_t is wide enough to
71-
// represent errors and the maximum length of rdata.
72-
#include <basetsd.h>
73-
typedef SSIZE_T ssize_t;
74-
#endif
75-
7669
nonnull((1,2,3,4))
77-
static really_inline ssize_t check_bytes(
70+
static really_inline int32_t check_bytes(
7871
parser_t *parser,
7972
const type_info_t *type,
8073
const rdata_info_t *field,
@@ -85,7 +78,7 @@ static really_inline ssize_t check_bytes(
8578
(void)data;
8679
if (length < size)
8780
SYNTAX_ERROR(parser, "Missing %s in %s", NAME(field), NAME(type));
88-
return (ssize_t)size;
81+
return (int32_t)size;
8982
}
9083

9184
#define check_int8(...) check_bytes(__VA_ARGS__, sizeof(uint8_t))
@@ -101,7 +94,7 @@ static really_inline ssize_t check_bytes(
10194
#define check_ilnp64(...) check_bytes(__VA_ARGS__, sizeof(uint64_t))
10295

10396
nonnull((1,2,3,4))
104-
static really_inline ssize_t check_ttl(
97+
static really_inline int32_t check_ttl(
10598
parser_t *parser,
10699
const type_info_t *type,
107100
const rdata_info_t *field,
@@ -123,14 +116,14 @@ static really_inline ssize_t check_ttl(
123116
}
124117

125118
zone_nonnull((1,2,3,4))
126-
static really_inline ssize_t check_name(
119+
static really_inline int32_t check_name(
127120
parser_t *parser,
128121
const type_info_t *type,
129122
const rdata_info_t *field,
130123
const uint8_t *data,
131124
const size_t length)
132125
{
133-
size_t label = 0, count = 0;
126+
int32_t label = 0, count = 0;
134127
while (count < length) {
135128
label = data[count];
136129
count += 1 + label;
@@ -141,34 +134,34 @@ static really_inline ssize_t check_name(
141134
if (!count || count > length)
142135
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
143136

144-
return (ssize_t)count;
137+
return count;
145138
}
146139

147140
zone_nonnull((1,2,3,4))
148-
static really_inline ssize_t check_string(
141+
static really_inline int32_t check_string(
149142
parser_t *parser,
150143
const type_info_t *type,
151144
const rdata_info_t *field,
152145
const uint8_t *data,
153146
const size_t length)
154147
{
155-
size_t count;
148+
int32_t count;
156149

157150
if (!length || (count = 1 + (size_t)data[0]) > length)
158151
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
159152

160-
return (ssize_t)count;
153+
return count;
161154
}
162155

163156
zone_nonnull((1,2,3,4))
164-
static really_inline ssize_t check_nsec(
157+
static really_inline int32_t check_nsec(
165158
parser_t *parser,
166159
const type_info_t *type,
167160
const rdata_info_t *field,
168161
const uint8_t *data,
169162
const size_t length)
170163
{
171-
size_t count = 0;
164+
int32_t count = 0;
172165
int32_t last_window = -1;
173166

174167
while ((count + 2) < length) {
@@ -187,14 +180,14 @@ static really_inline ssize_t check_nsec(
187180
if (count != length)
188181
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
189182

190-
return (ssize_t)count;
183+
return count;
191184
}
192185

193186
zone_nonnull((1))
194-
static really_inline int32_t check(size_t *length, ssize_t count)
187+
static really_inline int32_t check(size_t *length, int32_t count)
195188
{
196189
if (count < 0)
197-
return (int32_t)count;
190+
return count;
198191
*length += (size_t)count;
199192
return 0;
200193
}

src/haswell/base32.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define BASE32_H
1111

1212
#include <stdint.h>
13-
#include <x86intrin.h> // update if we need to support Windows.
13+
//#include <x86intrin.h> // update if we need to support Windows.
1414

1515

1616
//////////////////////////
@@ -44,7 +44,7 @@ static size_t base32hex_avx(uint8_t *dst, const uint8_t *src) {
4444
unsigned int m = (unsigned)_mm256_movemask_epi8(check);
4545

4646
if (m) {
47-
int length = __builtin_ctz(m);
47+
int length = (int)trailing_zeroes(m);
4848
if (length == 0) {
4949
break;
5050
}

src/haswell/bits.h

+21-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
#include <immintrin.h>
1515

1616
static inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
17+
#if has_builtin(__builtin_uaddll_overflow)
1718
return __builtin_uaddll_overflow(value1, value2, (unsigned long long *)result);
19+
#else
20+
*result = value1 + value2;
21+
return *result < value1;
22+
#endif
1823
}
1924

2025
static inline uint64_t count_ones(uint64_t bits) {
@@ -23,7 +28,7 @@ static inline uint64_t count_ones(uint64_t bits) {
2328

2429
no_sanitize_undefined
2530
static inline uint64_t trailing_zeroes(uint64_t bits) {
26-
return (uint64_t)__builtin_ctzll(bits);
31+
return (uint64_t)_tzcnt_u64(bits);
2732
}
2833

2934
// result might be undefined when bits is zero
@@ -32,15 +37,26 @@ static inline uint64_t clear_lowest_bit(uint64_t bits) {
3237
}
3338

3439
static inline uint64_t leading_zeroes(uint64_t bits) {
35-
return (uint64_t)__builtin_clzll(bits);
40+
return (uint64_t)_lzcnt_u64(bits);
3641
}
3742

3843
static inline uint64_t prefix_xor(const uint64_t bitmask) {
44+
__m128i all_ones = _mm_set1_epi8('\xFF');
45+
__m128i mask = _mm_set_epi64x(0ULL, (long long)bitmask);
46+
#if defined __SUNPRO_C
47+
//asm("pclmulqdq %0, %1, 0\n\t" : "+x" (mask) : "x" (all_ones));
48+
// Oracle Developer Studio has issues generating vpclmulqdq
49+
// Oracle Solaris and Intel assembler use the opposite order for source and
50+
// destination operands. See x86 Assemble Language Reference Manual.
51+
__asm volatile ("vpclmulqdq $0,%[all_ones],%[mask],%[mask]"
52+
: [mask] "+x" (mask)
53+
: [all_ones] "x" (all_ones));
54+
#else
3955
// There should be no such thing with a processor supporting avx2
4056
// but not clmul.
41-
__m128i all_ones = _mm_set1_epi8('\xFF');
42-
__m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, (long long)bitmask), all_ones, 0);
43-
return (uint64_t)_mm_cvtsi128_si64(result);
57+
mask = _mm_clmulepi64_si128(mask, all_ones, 0);
58+
#endif
59+
return (uint64_t)_mm_cvtsi128_si64(mask);
4460
}
4561

4662
#endif // BITS_H

src/westmere/base32.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define BASE32_H
1111

1212
#include <stdint.h>
13-
#include <x86intrin.h> // update if we need to support Windows.
13+
#include <immintrin.h>
1414

1515

1616
//////////////////////////
@@ -37,7 +37,7 @@ static size_t base32hex_sse(uint8_t *dst, const uint8_t *src) {
3737
unsigned int m = (unsigned)_mm_movemask_epi8(check);
3838

3939
if (m) {
40-
int length = __builtin_ctz(m);
40+
int length = (int)trailing_zeroes(m);
4141
if (length == 0) {
4242
break;
4343
}

0 commit comments

Comments
 (0)