Skip to content

Commit

Permalink
Only use x86 intrinsics for endian swapping on x86
Browse files Browse the repository at this point in the history
  • Loading branch information
caseif committed Apr 17, 2024
1 parent 5684b57 commit ffa86e2
Showing 1 changed file with 41 additions and 13 deletions.
54 changes: 41 additions & 13 deletions src/util/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,71 @@
#include <stdio.h>
#include <string.h>

#if defined(__x86_64__) || defined(_M_AMD64)
#ifdef _WIN32
#include <intrin.h>
#else
#include <immintrin.h>
#include <sys/mman.h>
#endif
#endif

// This function actually works for both copying LE file data to BE system
// memory, and vice versa. all we care about is if the source and target
// endianness mismatch (which will only happen if the system is BE since the
// file data is guaranteed to be LE), so simply flipping the bytes in this case
// will work regardless of which direction we're copying.
#if defined(__x86_64__) || defined(_M_AMD64)
void copy_int_as_le(void *dst, void *src, size_t len) {
memcpy(dst, src, len);

#ifdef _WIN32
if (len == 2) {
*((uint16_t*) dst) = _byteswap_ushort(*((uint16_t*) dst));
} else if (len == 3 || len == 4) {
*((uint32_t*) dst) = _byteswap_ulong(*((uint32_t*) dst));
} else if (len == 8) {
*((uint64_t*) dst) = _byteswap_uint64(*((uint64_t*) dst));
}
#else
if (len == 2) {
*((uint16_t*) dst) = __builtin_bswap16(*((uint16_t*) dst));
((uint8_t*) dst)[0] ^= ((uint8_t*) dst)[1];
} else if (len == 3 || len == 4) {
*((uint32_t*) dst) = __builtin_bswap32(*((uint32_t*) dst));
} else if (len == 8) {
*((uint64_t*) dst) = __builtin_bswap64(*((uint64_t*) dst));
}
#endif
}
#else
inline static void _swap_bytes(void *bytes, uint8_t off_a, uint8_t off_b) {
unsigned char *byte_arr = (unsigned char *) bytes;
byte_arr[off_a] ^= byte_arr[off_b];
byte_arr[off_b] ^= byte_arr[off_a];
byte_arr[off_a] ^= byte_arr[off_b];
}

void copy_int_as_le(void *dst, void *src, size_t len) {
memcpy(dst, src, len);

int x = 1;
if (((unsigned char*) &x)[0] == 0) {
// system is big-endian, so we need to convert to little
#ifdef _WIN32
if (len == 2) {
*((uint16_t*) dst) = _byteswap_ushort(*((uint16_t*) dst));
_swap_bytes(&dst, 0, 1);
} else if (len == 3 || len == 4) {
*((uint32_t*) dst) = _byteswap_ulong(*((uint32_t*) dst));
_swap_bytes(&dst, 0, 3);
_swap_bytes(&dst, 1, 2);
} else if (len == 8) {
*((uint64_t*) dst) = _byteswap_uint64(*((uint64_t*) dst));
_swap_bytes(&dst, 0, 7);
_swap_bytes(&dst, 1, 6);
_swap_bytes(&dst, 2, 5);
_swap_bytes(&dst, 3, 4);
}
#else
if (len == 2) {
*((uint16_t*) dst) = __builtin_bswap16(*((uint16_t*) dst));
} else if (len == 3 || len == 4) {
*((uint32_t*) dst) = __builtin_bswap32(*((uint32_t*) dst));
} else if (len == 8) {
*((uint64_t*) dst) = __builtin_bswap64(*((uint64_t*) dst));
}
#endif
}
}
#endif

int validate_path_component(const char *cmpnt, uint8_t len_s) {
for (uint8_t i = 0; i < len_s; i++) {
Expand Down

0 comments on commit ffa86e2

Please sign in to comment.