Skip to content

Commit

Permalink
Bswap config and self test improvements
Browse files Browse the repository at this point in the history
* Add DUK_BSWAP64() fill-in when 64-bit types available.

* Add DUK_BSWAP16(), DUK_BSWAP32(), and DUK_BSWAP64() GCC and Clang
  built-ins.  These are nice but unnecessary except at low optimizations
  because the macros compile down to proper bswap instructions.

* Improve bswap self tests.
  • Loading branch information
svaarala committed Jun 23, 2019
1 parent 08fc3c7 commit a61d730
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 13 deletions.
12 changes: 12 additions & 0 deletions config/compilers/compiler_clang.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,15 @@

#undef DUK_USE_GCC_PRAGMAS
#define DUK_USE_PACK_CLANG_ATTR

#if defined(__clang__) && defined(__has_builtin)
#if __has_builtin(__builtin_bswap64)
#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
#endif
#if __has_builtin(__builtin_bswap32)
#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
#endif
#if __has_builtin(__builtin_bswap16)
#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
#endif
#endif
10 changes: 10 additions & 0 deletions config/compilers/compiler_gcc.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,13 @@
#endif

#define DUK_USE_PACK_GCC_ATTR

/* Availability varies based on platform (between GCC 4.4 and 4.8), and there
* are apparently some bugs in GCC 4.x. Check for GCC 5.0 before enabling
* these to be safe.
*/
#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 50000L)
#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
#endif
39 changes: 26 additions & 13 deletions config/header-snippets/compiler_fillins.h.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#if !defined(DUK_U64_CONSTANT)
#define DUK_U64_CONSTANT(x) x##ULL
#endif
#if !defined(DUK_I64_CONSTANT)
#define DUK_I64_CONSTANT(x) x##LL
#endif

#if !defined(DUK_VA_COPY)
/* We need va_copy() which is defined in C99 / C++11, so an awkward
* replacement is needed for pre-C99 / pre-C++11 environments. This
Expand Down Expand Up @@ -148,17 +155,30 @@
#endif
#endif

#if defined(DUK_F_HAVE_64BIT)
#if !defined(DUK_BSWAP64)
#define DUK_BSWAP64(x) \
((((duk_uint64_t) (x)) >> 56U) | \
((((duk_uint64_t) (x)) >> 40U) & DUK_U64_CONSTANT(0xff00)) | \
((((duk_uint64_t) (x)) >> 24U) & DUK_U64_CONSTANT(0xff0000)) | \
((((duk_uint64_t) (x)) >> 8U) & DUK_U64_CONSTANT(0xff000000)) | \
((((duk_uint64_t) (x)) << 8U) & DUK_U64_CONSTANT(0xff00000000)) | \
((((duk_uint64_t) (x)) << 24U) & DUK_U64_CONSTANT(0xff0000000000)) | \
((((duk_uint64_t) (x)) << 40U) & DUK_U64_CONSTANT(0xff000000000000)) | \
(((duk_uint64_t) (x)) << 56U))
#endif
#endif
#if !defined(DUK_BSWAP32)
#define DUK_BSWAP32(x) \
((((duk_uint32_t) (x)) >> 24) | \
((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
(((duk_uint32_t) (x)) << 24))
((((duk_uint32_t) (x)) >> 24U) | \
((((duk_uint32_t) (x)) >> 8U) & 0xff00UL) | \
((((duk_uint32_t) (x)) << 8U) & 0xff0000UL) | \
(((duk_uint32_t) (x)) << 24U))
#endif
#if !defined(DUK_BSWAP16)
#define DUK_BSWAP16(x) \
((duk_uint16_t) (x) >> 8) | \
((duk_uint16_t) (x) << 8)
((duk_uint16_t) (x) >> 8U) | \
((duk_uint16_t) (x) << 8U)
#endif

/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */
Expand All @@ -180,10 +200,3 @@
#if 0 /* not defined by default */
#undef DUK_USE_GCC_PRAGMAS
#endif

#if !defined(DUK_U64_CONSTANT)
#define DUK_U64_CONSTANT(x) x##ULL
#endif
#if !defined(DUK_I64_CONSTANT)
#define DUK_I64_CONSTANT(x) x##LL
#endif
42 changes: 42 additions & 0 deletions src-input/duk_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,23 +187,65 @@ DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {

DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
duk_uint_t error_count = 0;
volatile duk_uint32_t x32_input, x32_output;
duk_uint32_t x32;
volatile duk_uint16_t x16_input, x16_output;
duk_uint16_t x16;
duk_double_union du;
duk_double_t du_diff;
#if defined(DUK_BSWAP64)
volatile duk_uint64_t x64_input, x64_output;
duk_uint64_t x64;
#endif

/* Cover both compile time and runtime bswap operations, as these
* may have different bugs.
*/

x16_input = 0xbeefUL;
x16 = x16_input;
x16 = DUK_BSWAP16(x16);
x16_output = x16;
if (x16_output != (duk_uint16_t) 0xefbeUL) {
DUK__FAILED("DUK_BSWAP16");
}

x16 = 0xbeefUL;
x16 = DUK_BSWAP16(x16);
if (x16 != (duk_uint16_t) 0xefbeUL) {
DUK__FAILED("DUK_BSWAP16");
}

x32_input = 0xdeadbeefUL;
x32 = x32_input;
x32 = DUK_BSWAP32(x32);
x32_output = x32;
if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
DUK__FAILED("DUK_BSWAP32");
}

x32 = 0xdeadbeefUL;
x32 = DUK_BSWAP32(x32);
if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
DUK__FAILED("DUK_BSWAP32");
}

#if defined(DUK_BSWAP64)
x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
x64 = x64_input;
x64 = DUK_BSWAP64(x64);
x64_output = x64;
if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
DUK__FAILED("DUK_BSWAP64");
}

x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
x64 = DUK_BSWAP64(x64);
if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
DUK__FAILED("DUK_BSWAP64");
}
#endif

/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
* (2.008366013071895,)
*/
Expand Down

0 comments on commit a61d730

Please sign in to comment.