From 4eed3157327f8406921658442a11af7e9d84d603 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 4 Oct 2013 00:36:22 -0700 Subject: [PATCH] Use hardware support for byteswapping on glibc x86 etc. On Fedora 19 x86-64, the new bswap_64 needs 1 instruction, whereas the old swap64 needed 30. * admin/merge-gnulib (GNULIB_MODULES): Add byteswap. * lib/byteswap.in.h, m4/byteswap.m4: New files, copied from Gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * src/fringe.c (init_fringe_bitmap) [WORDS_BIGENDIAN]: * src/sound.c (le2hl, le2hs, be2hl) [!WINDOWSNT]: Use byteswap.h's macros to swap bytes. * src/lisp.h (swap16, swap32, swap64): Remove. All uses replaced by bswap_16, bswap_32, bswap_64. --- ChangeLog | 6 ++++++ admin/ChangeLog | 5 +++++ admin/merge-gnulib | 2 +- lib/byteswap.in.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib/gnulib.mk | 25 ++++++++++++++++++++++++- m4/byteswap.m4 | 19 +++++++++++++++++++ m4/gnulib-comp.m4 | 4 ++++ src/ChangeLog | 9 +++++++++ src/data.c | 5 +++-- src/fringe.c | 4 +++- src/lisp.h | 24 ------------------------ src/sound.c | 29 +++++------------------------ src/xsettings.c | 11 +++++++---- 13 files changed, 130 insertions(+), 57 deletions(-) create mode 100644 lib/byteswap.in.h create mode 100644 m4/byteswap.m4 diff --git a/ChangeLog b/ChangeLog index 44e83d2573..4769f5d575 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-10-04 Paul Eggert + + Use hardware insns for byteswapping on glibc hosts that support it. + * lib/byteswap.in.h, m4/byteswap.m4: New files, copied from Gnulib. + * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. + 2013-10-03 Paul Eggert Merge from gnulib, incorporating: diff --git a/admin/ChangeLog b/admin/ChangeLog index 29118deba7..837a0a2e6d 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog @@ -1,3 +1,8 @@ +2013-10-04 Paul Eggert + + Use hardware support for byteswapping on glibc x86 etc. + * merge-gnulib (GNULIB_MODULES): Add byteswap. + 2013-08-28 Paul Eggert * unidata/Makefile.in (SHELL): Now @SHELL@, not /bin/sh, diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 97126704d1..aba0fa67a1 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -26,7 +26,7 @@ GNULIB_URL=git://git.savannah.gnu.org/gnulib.git GNULIB_MODULES=' - alloca-opt c-ctype c-strcase + alloca-opt byteswap c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync diff --git a/lib/byteswap.in.h b/lib/byteswap.in.h new file mode 100644 index 0000000000..a323ca3570 --- /dev/null +++ b/lib/byteswap.in.h @@ -0,0 +1,44 @@ +/* byteswap.h - Byte swapping + Copyright (C) 2005, 2007, 2009-2013 Free Software Foundation, Inc. + Written by Oskar Liljeblad , 2005. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_BYTESWAP_H +#define _GL_BYTESWAP_H + +/* Given an unsigned 16-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_16(x) ((((x) & 0x00FF) << 8) | \ + (((x) & 0xFF00) >> 8)) + +/* Given an unsigned 32-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0xFF000000) >> 24)) + +/* Given an unsigned 64-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ + (((x) & 0x000000000000FF00ULL) << 40) | \ + (((x) & 0x0000000000FF0000ULL) << 24) | \ + (((x) & 0x00000000FF000000ULL) << 8) | \ + (((x) & 0x000000FF00000000ULL) >> 8) | \ + (((x) & 0x0000FF0000000000ULL) >> 24) | \ + (((x) & 0x00FF000000000000ULL) >> 40) | \ + (((x) & 0xFF00000000000000ULL) >> 56)) + +#endif /* _GL_BYTESWAP_H */ diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 14d45e798e..73381f2bdc 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt byteswap c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings MOSTLYCLEANFILES += core *.stackdump @@ -81,6 +81,29 @@ libgnu_a_SOURCES += binary-io.h binary-io.c ## end gnulib module binary-io +## begin gnulib module byteswap + +BUILT_SOURCES += $(BYTESWAP_H) + +# We need the following in order to create when the system +# doesn't have one. +if GL_GENERATE_BYTESWAP_H +byteswap.h: byteswap.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/byteswap.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +byteswap.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += byteswap.h byteswap.h-t + +EXTRA_DIST += byteswap.in.h + +## end gnulib module byteswap + ## begin gnulib module c-ctype libgnu_a_SOURCES += c-ctype.h c-ctype.c diff --git a/m4/byteswap.m4 b/m4/byteswap.m4 new file mode 100644 index 0000000000..7566903dc4 --- /dev/null +++ b/m4/byteswap.m4 @@ -0,0 +1,19 @@ +# byteswap.m4 serial 4 +dnl Copyright (C) 2005, 2007, 2009-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Oskar Liljeblad. + +AC_DEFUN([gl_BYTESWAP], +[ + dnl Prerequisites of lib/byteswap.in.h. + AC_CHECK_HEADERS([byteswap.h], [ + BYTESWAP_H='' + ], [ + BYTESWAP_H='byteswap.h' + ]) + AC_SUBST([BYTESWAP_H]) + AM_CONDITIONAL([GL_GENERATE_BYTESWAP_H], [test -n "$BYTESWAP_H"]) +]) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 2e5a9cf97d..ff36981c8d 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -42,6 +42,7 @@ AC_DEFUN([gl_EARLY], # Code from module allocator: # Code from module at-internal: # Code from module binary-io: + # Code from module byteswap: # Code from module c-ctype: # Code from module c-strcase: # Code from module careadlinkat: @@ -169,6 +170,7 @@ AC_DEFUN([gl_INIT], gl_COMMON gl_source_base='lib' gl_FUNC_ALLOCA + gl_BYTESWAP AC_CHECK_FUNCS_ONCE([readlinkat]) gl_CLOCK_TIME gl_CLOSE_STREAM @@ -794,6 +796,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/at-func.c lib/binary-io.c lib/binary-io.h + lib/byteswap.in.h lib/c-ctype.c lib/c-ctype.h lib/c-strcase.h @@ -912,6 +915,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/00gnulib.m4 m4/acl.m4 m4/alloca.m4 + m4/byteswap.m4 m4/c-strtod.m4 m4/clock_time.m4 m4/close-stream.m4 diff --git a/src/ChangeLog b/src/ChangeLog index 4fae03d696..38fb35ddf5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,14 @@ 2013-10-04 Paul Eggert + Use hardware support for byteswapping on glibc x86 etc. + On Fedora 19 x86-64, the new bswap_64 needs 1 instruction, + whereas the old swap64 needed 30. + * fringe.c (init_fringe_bitmap) [WORDS_BIGENDIAN]: + * sound.c (le2hl, le2hs, be2hl) [!WINDOWSNT]: + Use byteswap.h's macros to swap bytes. + * lisp.h (swap16, swap32, swap64): Remove. + All uses replaced by bswap_16, bswap_32, bswap_64. + * bytecode.c (exec_byte_code): Use some more volatile variables to work around local variables getting clobbered by longjmp. Port to pre-C99, which doesn't allow decls after stmts. diff --git a/src/data.c b/src/data.c index b268616fd2..a6bfe50a3b 100644 --- a/src/data.c +++ b/src/data.c @@ -21,6 +21,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include "lisp.h" @@ -3185,9 +3186,9 @@ size_t_to_host_endian (size_t val) { #ifdef WORDS_BIGENDIAN # if BITS_PER_SIZE_T == 64 - return swap64 (val); + return bswap_64 (val); # else - return swap32 (val); + return bswap_32 (val); # endif #else return val; diff --git a/src/fringe.c b/src/fringe.c index 85103f7f08..3537027f1d 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -20,6 +20,8 @@ along with GNU Emacs. If not, see . */ #include #include +#include + #include "lisp.h" #include "frame.h" #include "window.h" @@ -1519,7 +1521,7 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p) | (swap_nibble[(b>>12) & 0xf])); b >>= (16 - fb->width); #ifdef WORDS_BIGENDIAN - b = ((b >> 8) | (b << 8)); + b = bswap_16 (b); #endif *bits++ = b; } diff --git a/src/lisp.h b/src/lisp.h index f949978cee..2f0279ef54 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4366,30 +4366,6 @@ functionp (Lisp_Object object) return 0; } -INLINE uint16_t -swap16 (uint16_t val) -{ - return (val << 8) | (val & 0xFF); -} - -INLINE uint32_t -swap32 (uint32_t val) -{ - uint32_t low = swap16 (val & 0xFFFF); - uint32_t high = swap16 (val >> 16); - return (low << 16) | high; -} - -#ifdef UINT64_MAX -INLINE uint64_t -swap64 (uint64_t val) -{ - uint64_t low = swap32 (val & 0xFFFFFFFF); - uint64_t high = swap32 (val >> 32); - return (low << 32) | high; -} -#endif - #if ((SIZE_MAX >> 31) >> 1) & 1 # define BITS_PER_SIZE_T 64 #else diff --git a/src/sound.c b/src/sound.c index 27e06b8aba..f8c6b48305 100644 --- a/src/sound.c +++ b/src/sound.c @@ -55,6 +55,8 @@ along with GNU Emacs. If not, see . */ /* BEGIN: Non Windows Includes */ #ifndef WINDOWSNT +#include + #include /* FreeBSD has machine/soundcard.h. Voxware sound driver docs mention @@ -461,8 +463,7 @@ static u_int32_t le2hl (u_int32_t value) { #ifdef WORDS_BIGENDIAN - unsigned char *p = (unsigned char *) &value; - value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); + value = bswap_32 (value); #endif return value; } @@ -475,8 +476,7 @@ static u_int16_t le2hs (u_int16_t value) { #ifdef WORDS_BIGENDIAN - unsigned char *p = (unsigned char *) &value; - value = p[0] + (p[1] << 8); + value = bswap_16 (value); #endif return value; } @@ -489,30 +489,11 @@ static u_int32_t be2hl (u_int32_t value) { #ifndef WORDS_BIGENDIAN - unsigned char *p = (unsigned char *) &value; - value = p[3] + (p[2] << 8) + (p[1] << 16) + (p[0] << 24); + value = bswap_32 (value); #endif return value; } - -#if 0 /* Currently not used. */ - -/* Convert 16-bit value VALUE which is in big-endian byte-order - to host byte-order. */ - -static u_int16_t -be2hs (u_int16_t value) -{ -#ifndef WORDS_BIGENDIAN - unsigned char *p = (unsigned char *) &value; - value = p[1] + (p[0] << 8); -#endif - return value; -} - -#endif /* 0 */ - /*********************************************************************** RIFF-WAVE (*.wav) ***********************************************************************/ diff --git a/src/xsettings.c b/src/xsettings.c index 8fe82fec74..e5a66c4cf0 100644 --- a/src/xsettings.c +++ b/src/xsettings.c @@ -22,6 +22,9 @@ along with GNU Emacs. If not, see . */ #include #include #include + +#include + #include "lisp.h" #include "xterm.h" #include "xsettings.h" @@ -405,7 +408,7 @@ parse_settings (unsigned char *prop, if (bytes < 12) return BadLength; memcpy (&n_settings, prop+8, 4); - if (my_bo != that_bo) n_settings = swap32 (n_settings); + if (my_bo != that_bo) n_settings = bswap_32 (n_settings); bytes_parsed = 12; memset (settings, 0, sizeof (*settings)); @@ -427,7 +430,7 @@ parse_settings (unsigned char *prop, memcpy (&nlen, prop+bytes_parsed, 2); bytes_parsed += 2; - if (my_bo != that_bo) nlen = swap16 (nlen); + if (my_bo != that_bo) nlen = bswap_16 (nlen); if (bytes_parsed+nlen > bytes) return BadLength; to_cpy = nlen > 127 ? 127 : nlen; memcpy (name, prop+bytes_parsed, to_cpy); @@ -454,7 +457,7 @@ parse_settings (unsigned char *prop, if (want_this) { memcpy (&ival, prop+bytes_parsed, 4); - if (my_bo != that_bo) ival = swap32 (ival); + if (my_bo != that_bo) ival = bswap_32 (ival); } bytes_parsed += 4; break; @@ -463,7 +466,7 @@ parse_settings (unsigned char *prop, if (bytes_parsed+4 > bytes) return BadLength; memcpy (&vlen, prop+bytes_parsed, 4); bytes_parsed += 4; - if (my_bo != that_bo) vlen = swap32 (vlen); + if (my_bo != that_bo) vlen = bswap_32 (vlen); if (want_this) { to_cpy = vlen > 127 ? 127 : vlen; -- 2.20.1