Date: Sun, 6 Mar 2011 11:48:25 +0100 (CET) From: Martin Matuska <mm@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Subject: gnu/155309: [PATCH] gcc: backport bswap32() and bswap64() Message-ID: <20110306104825.8B860F1DEF@mail2.vx.sk> Resent-Message-ID: <201103061100.p26B0MKV083537@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 155309 >Category: gnu >Synopsis: [PATCH] gcc: backport bswap32() and bswap64() >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Mar 06 11:00:22 UTC 2011 >Closed-Date: >Last-Modified: >Originator: Martin Matuska >Release: FreeBSD 9-CURRENT amd64 >Organization: >Environment: >Description: In many ports, we have to deal with patching the missing bswap32() and bswap64() functions. The gcc-4.3 branch SVN revision is 118361, is GPLv2-licensed, applies cleanly and is fully compatible with our code. References: http://gcc.gnu.org/viewcvs?view=revision&revision=118361 >How-To-Repeat: >Fix: Index: contrib/gcc/doc/extend.texi =================================================================== --- contrib/gcc/doc/extend.texi (revision 219330) +++ contrib/gcc/doc/extend.texi (working copy) @@ -6147,7 +6147,17 @@ are @code{long double}. @end deftypefn +@deftypefn {Built-in Function} int32_t __builtin_bswap32 (int32_t x) +Returns @var{x} with the order of the bytes reversed; for example, +@code{0xaabbccdd} becomes @code{0xddccbbaa}. Byte here always means +exactly 8 bits. +@end deftypefn +@deftypefn {Built-in Function} int64_t __builtin_bswap64 (int64_t x) +Similar to @code{__builtin_bswap32}, except the argument and return types +are 64-bit. +@end deftypefn + @node Target Builtins @section Built-in Functions Specific to Particular Target Machines Index: contrib/gcc/doc/libgcc.texi =================================================================== --- contrib/gcc/doc/libgcc.texi (revision 219330) +++ contrib/gcc/doc/libgcc.texi (working copy) @@ -212,6 +212,11 @@ These functions return the number of bits set in @var{a}. @end deftypefn +@deftypefn {Runtime Function} int32_t __bswapsi2 (int32_t @var{a}) +@deftypefnx {Runtime Function} int64_t __bswapdi2 (int64_t @var{a}) +These functions return the @var{a} byteswapped. +@end deftypefn + @node Soft float library routines @section Routines for floating point emulation @cindex soft float library @@ -728,4 +733,3 @@ @deftypefn {Runtime Function} void __clear_cache (char *@var{beg}, char *@var{end}) This function clears the instruction cache between @var{beg} and @var{end}. @end deftypefn - Index: contrib/gcc/doc/rtl.texi =================================================================== --- contrib/gcc/doc/rtl.texi (revision 219330) +++ contrib/gcc/doc/rtl.texi (working copy) @@ -2084,6 +2084,11 @@ Represents the number of 1-bits modulo 2 in @var{x}, represented as an integer of mode @var{m}. The mode of @var{x} will usually be an integer mode. + +@findex bswap +@item (bswap:@var{m} @var{x}) +Represents the value @var{x} with the order of bytes reversed, carried out +in mode @var{m}, which must be a fixed-point machine mode. @end table @node Comparisons Index: contrib/gcc/optabs.c =================================================================== --- contrib/gcc/optabs.c (revision 219330) +++ contrib/gcc/optabs.c (working copy) @@ -2591,6 +2591,10 @@ goto try_libcall; } + /* We can't widen a bswap. */ + if (unoptab == bswap_optab) + goto try_libcall; + if (CLASS_HAS_WIDER_MODES_P (class)) for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; @@ -5253,6 +5257,7 @@ absv_optab = init_optabv (ABS); addcc_optab = init_optab (UNKNOWN); one_cmpl_optab = init_optab (NOT); + bswap_optab = init_optab (BSWAP); ffs_optab = init_optab (FFS); clz_optab = init_optab (CLZ); ctz_optab = init_optab (CTZ); @@ -5456,6 +5461,11 @@ init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, MODE_DECIMAL_FLOAT); init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_DECIMAL_FLOAT, MODE_FLOAT); + /* Explicitly initialize the bswap libfuncs since we need them to be + valid for things other than word_mode. */ + set_optab_libfunc (bswap_optab, SImode, "__bswapsi2"); + set_optab_libfunc (bswap_optab, DImode, "__bswapdi2"); + /* Use cabs for double complex abs, since systems generally have cabs. Don't define any libcall for float complex, so that cabs will be used. */ if (complex_double_type_node) Index: contrib/gcc/optabs.h =================================================================== --- contrib/gcc/optabs.h (revision 219330) +++ contrib/gcc/optabs.h (working copy) @@ -146,6 +146,8 @@ /* Abs value */ OTI_abs, OTI_absv, + /* Byteswap */ + OTI_bswap, /* Bitwise not */ OTI_one_cmpl, /* Bit scanning and counting */ @@ -315,6 +317,7 @@ #define abs_optab (optab_table[OTI_abs]) #define absv_optab (optab_table[OTI_absv]) #define one_cmpl_optab (optab_table[OTI_one_cmpl]) +#define bswap_optab (optab_table[OTI_bswap]) #define ffs_optab (optab_table[OTI_ffs]) #define clz_optab (optab_table[OTI_clz]) #define ctz_optab (optab_table[OTI_ctz]) Index: contrib/gcc/tree.c =================================================================== --- contrib/gcc/tree.c (revision 219330) +++ contrib/gcc/tree.c (working copy) @@ -6584,6 +6584,10 @@ long_double_ptr_type_node = build_pointer_type (long_double_type_node); integer_ptr_type_node = build_pointer_type (integer_type_node); + /* Fixed size integer types. */ + uint32_type_node = build_nonstandard_integer_type (32, true); + uint64_type_node = build_nonstandard_integer_type (64, true); + /* Decimal float types. */ dfloat32_type_node = make_node (REAL_TYPE); TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; Index: contrib/gcc/tree.h =================================================================== --- contrib/gcc/tree.h (revision 219330) +++ contrib/gcc/tree.h (working copy) @@ -3235,6 +3235,9 @@ TI_UINTDI_TYPE, TI_UINTTI_TYPE, + TI_UINT32_TYPE, + TI_UINT64_TYPE, + TI_INTEGER_ZERO, TI_INTEGER_ONE, TI_INTEGER_MINUS_ONE, @@ -3310,6 +3313,9 @@ #define unsigned_intDI_type_node global_trees[TI_UINTDI_TYPE] #define unsigned_intTI_type_node global_trees[TI_UINTTI_TYPE] +#define uint32_type_node global_trees[TI_UINT32_TYPE] +#define uint64_type_node global_trees[TI_UINT64_TYPE] + #define integer_zero_node global_trees[TI_INTEGER_ZERO] #define integer_one_node global_trees[TI_INTEGER_ONE] #define integer_minus_one_node global_trees[TI_INTEGER_MINUS_ONE] Index: contrib/gcc/builtins.c =================================================================== --- contrib/gcc/builtins.c (revision 219330) +++ contrib/gcc/builtins.c (working copy) @@ -4589,6 +4589,30 @@ return result; } +/* Expand a call to a bswap builtin. The arguments are in ARGLIST. MODE + is the mode to expand with. */ + +static rtx +expand_builtin_bswap (tree arglist, rtx target, rtx subtarget) +{ + enum machine_mode mode; + tree arg; + rtx op0; + + if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) + return 0; + + arg = TREE_VALUE (arglist); + mode = TYPE_MODE (TREE_TYPE (arg)); + op0 = expand_expr (arg, subtarget, VOIDmode, 0); + + target = expand_unop (mode, bswap_optab, op0, target, 1); + + gcc_assert (target); + + return convert_to_mode (mode, target, 0); +} + /* Expand a call to a unary builtin. The arguments are in ARGLIST. Return 0 if a normal call should be emitted rather than expanding the function in-line. If convenient, the result should be placed in TARGET. @@ -5877,6 +5901,14 @@ expand_stack_restore (TREE_VALUE (arglist)); return const0_rtx; + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: + target = expand_builtin_bswap (arglist, target, subtarget); + + if (target) + return target; + break; + CASE_INT_FN (BUILT_IN_FFS): case BUILT_IN_FFSIMAX: target = expand_builtin_unop (target_mode, arglist, target, @@ -7539,6 +7571,67 @@ return NULL_TREE; } +/* Fold function call to builtin_bswap and the long and long long + variants. Return NULL_TREE if no simplification can be made. */ +static tree +fold_builtin_bswap (tree fndecl, tree arglist) +{ + tree arg; + + if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) + return 0; + + /* Optimize constant value. */ + arg = TREE_VALUE (arglist); + if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg)) + { + HOST_WIDE_INT hi, width, r_hi = 0; + unsigned HOST_WIDE_INT lo, r_lo = 0; + tree type; + + type = TREE_TYPE (arg); + width = TYPE_PRECISION (type); + lo = TREE_INT_CST_LOW (arg); + hi = TREE_INT_CST_HIGH (arg); + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: + { + int s; + + for (s = 0; s < width; s += 8) + { + int d = width - s - 8; + unsigned HOST_WIDE_INT byte; + + if (s < HOST_BITS_PER_WIDE_INT) + byte = (lo >> s) & 0xff; + else + byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff; + + if (d < HOST_BITS_PER_WIDE_INT) + r_lo |= byte << d; + else + r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT); + } + } + + break; + + default: + gcc_unreachable (); + } + + if (width < HOST_BITS_PER_WIDE_INT) + return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo); + else + return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi); + } + + return NULL_TREE; +} /* Return true if EXPR is the real constant contained in VALUE. */ static bool @@ -9053,6 +9146,10 @@ CASE_FLT_FN (BUILT_IN_LLRINT): return fold_fixed_mathfn (fndecl, arglist); + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: + return fold_builtin_bswap (fndecl, arglist); + CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_CLZ): CASE_INT_FN (BUILT_IN_CTZ): Index: contrib/gcc/fold-const.c =================================================================== --- contrib/gcc/fold-const.c (revision 219330) +++ contrib/gcc/fold-const.c (working copy) @@ -12581,6 +12581,8 @@ CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_PARITY): CASE_INT_FN (BUILT_IN_POPCOUNT): + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: /* Always true. */ return 1; @@ -13618,4 +13620,3 @@ } return NULL_TREE; } - Index: contrib/gcc/builtin-types.def =================================================================== --- contrib/gcc/builtin-types.def (revision 219330) +++ contrib/gcc/builtin-types.def (working copy) @@ -75,6 +75,8 @@ DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node) DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node) DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node) +DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node) +DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node) DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 0)) DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node) DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node) @@ -204,6 +206,10 @@ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT) +DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG) +DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG) +DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32) +DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR) @@ -435,4 +441,3 @@ DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR) DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE) - Index: contrib/gcc/builtins.def =================================================================== --- contrib/gcc/builtins.def (revision 219330) +++ contrib/gcc/builtins.def (working copy) @@ -594,6 +594,8 @@ DEF_GCC_BUILTIN (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_ARGS_INFO, "args_info", BT_FN_INT_INT, ATTR_NULL) +DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LIST) +DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LIST) DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST) Index: contrib/gcc/rtl.def =================================================================== --- contrib/gcc/rtl.def (revision 219330) +++ contrib/gcc/rtl.def (working copy) @@ -567,6 +567,9 @@ /* Square root */ DEF_RTL_EXPR(SQRT, "sqrt", "e", RTX_UNARY) +/* Swap bytes. */ +DEF_RTL_EXPR(BSWAP, "bswap", "e", RTX_UNARY) + /* Find first bit that is set. Value is 1 + number of trailing zeros in the arg., or 0 if arg is 0. */ Index: contrib/gcc/genattrtab.c =================================================================== --- contrib/gcc/genattrtab.c (revision 219330) +++ contrib/gcc/genattrtab.c (working copy) @@ -959,6 +959,7 @@ case CTZ: case POPCOUNT: case PARITY: + case BSWAP: XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr); break; Index: contrib/gcc/libgcc2.c =================================================================== --- contrib/gcc/libgcc2.c (revision 219330) +++ contrib/gcc/libgcc2.c (working copy) @@ -492,6 +492,30 @@ } #endif +#ifdef L_bswapsi2 +UWtype +__bswapSI2 (UWtype u) +{ + return ((((u) & 0xff000000) >> 24) + | (((u) & 0x00ff0000) >> 8) + | (((u) & 0x0000ff00) << 8) + | (((u) & 0x000000ff) << 24)); +} +#endif +#ifdef L_bswapdi2 +UDWtype +__bswapDI2 (UDWtype u) +{ + return ((((u) & 0xff00000000000000ull) >> 56) + | (((u) & 0x00ff000000000000ull) >> 40) + | (((u) & 0x0000ff0000000000ull) >> 24) + | (((u) & 0x000000ff00000000ull) >> 8) + | (((u) & 0x00000000ff000000ull) << 8) + | (((u) & 0x0000000000ff0000ull) << 24) + | (((u) & 0x000000000000ff00ull) << 40) + | (((u) & 0x00000000000000ffull) << 56)); +} +#endif #ifdef L_ffssi2 #undef int int Index: contrib/gcc/libgcc2.h =================================================================== --- contrib/gcc/libgcc2.h (revision 219330) +++ contrib/gcc/libgcc2.h (working copy) @@ -304,11 +304,13 @@ #define __ctzSI2 __NW(ctz,2) #define __popcountSI2 __NW(popcount,2) #define __paritySI2 __NW(parity,2) +#define __bswapSI2 __NW(bswap,2) #define __ffsDI2 __NDW(ffs,2) #define __clzDI2 __NDW(clz,2) #define __ctzDI2 __NDW(ctz,2) #define __popcountDI2 __NDW(popcount,2) #define __parityDI2 __NDW(parity,2) +#define __bswapDI2 __NDW(bswap,2) extern DWtype __muldi3 (DWtype, DWtype); extern DWtype __divdi3 (DWtype, DWtype); @@ -345,11 +347,13 @@ extern Wtype __subvSI3 (Wtype, Wtype); extern Wtype __mulvSI3 (Wtype, Wtype); extern Wtype __negvSI2 (Wtype); +extern UWtype __bswapSI2 (UWtype); extern DWtype __absvDI2 (DWtype); extern DWtype __addvDI3 (DWtype, DWtype); extern DWtype __subvDI3 (DWtype, DWtype); extern DWtype __mulvDI3 (DWtype, DWtype); extern DWtype __negvDI2 (DWtype); +extern UDWtype __bswapDI2 (UDWtype); #ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC extern SItype __absvsi2 (SItype); Index: contrib/gcc/mklibgcc.in =================================================================== --- contrib/gcc/mklibgcc.in (revision 219330) +++ contrib/gcc/mklibgcc.in (working copy) @@ -91,7 +91,7 @@ _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3 - _divxc3 _divtc3' + _divxc3 _divtc3 _bswapsi2 _bswapdi2' if [ "$LIB2_SIDITI_CONV_FUNCS" ]; then for func in $swfloatfuncs; do Index: contrib/gcc/simplify-rtx.c =================================================================== --- contrib/gcc/simplify-rtx.c (revision 219330) +++ contrib/gcc/simplify-rtx.c (working copy) @@ -1043,6 +1043,9 @@ val &= 1; break; + case BSWAP: + return 0; + case TRUNCATE: val = arg0; break; @@ -4886,4 +4889,3 @@ } return NULL; } - Index: contrib/gcc/config/i386/i386.h =================================================================== --- contrib/gcc/config/i386/i386.h (revision 219330) +++ contrib/gcc/config/i386/i386.h (working copy) @@ -164,6 +164,7 @@ extern const int x86_cmpxchg, x86_cmpxchg8b, x86_cmpxchg16b, x86_xadd; extern const int x86_use_incdec; extern const int x86_pad_returns; +extern const int x86_bswap; extern const int x86_partial_flag_reg_stall; extern int x86_prefetch_sse; @@ -237,6 +238,7 @@ #define TARGET_CMPXCHG8B (x86_cmpxchg8b & (1 << ix86_arch)) #define TARGET_CMPXCHG16B (x86_cmpxchg16b & (1 << ix86_arch)) #define TARGET_XADD (x86_xadd & (1 << ix86_arch)) +#define TARGET_BSWAP (x86_bswap & (1 << ix86_arch)) #ifndef TARGET_64BIT_DEFAULT #define TARGET_64BIT_DEFAULT 0 Index: contrib/gcc/config/i386/i386.c =================================================================== --- contrib/gcc/config/i386/i386.c (revision 219330) +++ contrib/gcc/config/i386/i386.c (working copy) @@ -831,6 +831,8 @@ const int x86_cmpxchg16b = m_NOCONA; /* Exchange and add was added for 80486. */ const int x86_xadd = ~m_386; +/* Byteswap was added for 80486. */ +const int x86_bswap = ~m_386; const int x86_pad_returns = m_ATHLON_K8 | m_GENERIC; /* In case the average insn count for single function invocation is Index: contrib/gcc/libgcc-std.ver =================================================================== --- contrib/gcc/libgcc-std.ver (revision 219330) +++ contrib/gcc/libgcc-std.ver (working copy) @@ -274,3 +274,10 @@ __floatuntitf _Unwind_GetIPInfo } + +%inherit GCC_4.3 GCC_4.2.0 +GCC_4.3.0 { + # byte swapping routines + __bswapsi2 + __bswapdi2 +} Index: contrib/gcc/reload1.c =================================================================== --- contrib/gcc/reload1.c (revision 219330) +++ contrib/gcc/reload1.c (working copy) @@ -2555,6 +2555,7 @@ case CTZ: case POPCOUNT: case PARITY: + case BSWAP: new = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false); if (new != XEXP (x, 0)) return gen_rtx_fmt_e (code, GET_MODE (x), new); @@ -2775,6 +2776,7 @@ case CTZ: case POPCOUNT: case PARITY: + case BSWAP: elimination_effects (XEXP (x, 0), mem_mode); return; >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110306104825.8B860F1DEF>