gnu/155309: [PATCH] gcc: backport bswap32() and bswap64()
Martin Matuska
mm at FreeBSD.org
Sun Mar 6 11:00:23 UTC 2011
>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
+ at deftypefn {Built-in Function} int32_t __builtin_bswap32 (int32_t x)
+Returns @var{x} with the order of the bytes reversed; for example,
+ at code{0xaabbccdd} becomes @code{0xddccbbaa}. Byte here always means
+exactly 8 bits.
+ at end deftypefn
+ at 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.
+ at 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
+ at deftypefn {Runtime Function} int32_t __bswapsi2 (int32_t @var{a})
+ at deftypefnx {Runtime Function} int64_t __bswapdi2 (int64_t @var{a})
+These functions return the @var{a} byteswapped.
+ at 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.
+
+ at findex bswap
+ at 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:
More information about the freebsd-bugs
mailing list