]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
2.5-18.1 cvs/fedora-2_5-branch cvs/fedora-glibc-2_5-18_1
authorJakub Jelinek <jakub@redhat.com>
Thu, 12 Jul 2007 18:26:36 +0000 (18:26 +0000)
committerJakub Jelinek <jakub@redhat.com>
Thu, 12 Jul 2007 18:26:36 +0000 (18:26 +0000)
fedora/glibc-rh234946.patch [new file with mode: 0644]
fedora/glibc-x86_64-memcpy.patch [new file with mode: 0644]
fedora/glibc.spec.in

diff --git a/fedora/glibc-rh234946.patch b/fedora/glibc-rh234946.patch
new file mode 100644 (file)
index 0000000..add3f80
--- /dev/null
@@ -0,0 +1,32 @@
+2006-12-25  Sripathi Kodi  <sripathik@in.ibm.com>
+
+       * include/link.h: Declare new flag l_fini_called in struct link_map.
+       * elf/dl-fini.c: In _dl_fini, set l_fini_called to 1 instead of 
+       l_init_called to 0.
+
+--- libc/elf/dl-fini.c 2006-12-22 01:54:22.000000000 -0600
++++ libc/elf/dl-fini.c 2006-12-24 22:51:52.000000000 -0600
+@@ -215,10 +215,10 @@ _dl_fini (void)
+       {
+         l = maps[i];
+-        if (l->l_init_called)
++        if (l->l_init_called && !l->l_fini_called)
+           {
+             /* Make sure nothing happens if we are called twice.  */
+-            l->l_init_called = 0;
++            l->l_fini_called = 1;
+             /* Is there a destructor function?  */
+             if (l->l_info[DT_FINI_ARRAY] != NULL
+--- libc/include/link.h        2006-12-22 01:54:22.000000000 -0600
++++ libc/include/link.h        2006-12-24 22:53:29.000000000 -0600
+@@ -185,6 +185,8 @@ struct link_map
+     unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
+                                   mprotected or if no holes are present at
+                                   all.  */
++    unsigned int l_fini_called:1; /* Nonzero if _dl_fini has processed
++                                   this object */
+     /* Array with version names.  */
+     unsigned int l_nversions;
diff --git a/fedora/glibc-x86_64-memcpy.patch b/fedora/glibc-x86_64-memcpy.patch
new file mode 100644 (file)
index 0000000..3888134
--- /dev/null
@@ -0,0 +1,1439 @@
+2007-05-21  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/x86_64/cacheinfo.c (init_cacheinfo): Pass correct value
+       as second parameter to handle_intel.
+
+       * sysdeps/unix/sysv/linux/x86_64/sysconf.c: Move cache information
+       handling to ...
+       * sysdeps/x86_64/cacheinfo.c: ... here.  New file.
+       * sysdeps/x86_64/Makefile [subdir=string] (sysdep_routines): Add
+       cacheinfo.
+       * sysdeps/x86_64/memcpy.S: Complete rewrite.
+       * sysdeps/x86_64/mempcpy.S: Adjust appropriately.
+       Patch by Evandro Menezes <evandro.menezes@amd.com>.
+
+--- libc/sysdeps/x86_64/Makefile       16 Aug 2004 06:46:14 -0000      1.4
++++ libc/sysdeps/x86_64/Makefile       21 May 2007 19:20:45 -0000      1.5
+@@ -9,3 +9,7 @@ endif
+ ifeq ($(subdir),gmon)
+ sysdep_routines += _mcount
+ endif
++
++ifeq ($(subdir),string)
++sysdep_routines += cacheinfo
++endif
+--- libc/sysdeps/x86_64/cacheinfo.c    1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/x86_64/cacheinfo.c    21 May 2007 22:37:45 -0000      1.2
+@@ -0,0 +1,451 @@
++/* x86_64 cache info.
++   Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library 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
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.
++*/
++
++#include <assert.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++static const struct intel_02_cache_info
++{
++  unsigned int idx;
++  int name;
++  long int size;
++  long int assoc;
++  long int linesize;
++} intel_02_known [] =
++  {
++    { 0x06, _SC_LEVEL1_ICACHE_SIZE,    8192,  4, 32 },
++    { 0x08, _SC_LEVEL1_ICACHE_SIZE,   16384,  4, 32 },
++    { 0x0a, _SC_LEVEL1_DCACHE_SIZE,    8192,  2, 32 },
++    { 0x0c, _SC_LEVEL1_DCACHE_SIZE,   16384,  4, 32 },
++    { 0x22, _SC_LEVEL3_CACHE_SIZE,   524288,  4, 64 },
++    { 0x23, _SC_LEVEL3_CACHE_SIZE,  1048576,  8, 64 },
++    { 0x25, _SC_LEVEL3_CACHE_SIZE,  2097152,  8, 64 },
++    { 0x29, _SC_LEVEL3_CACHE_SIZE,  4194304,  8, 64 },
++    { 0x2c, _SC_LEVEL1_DCACHE_SIZE,   32768,  8, 64 },
++    { 0x30, _SC_LEVEL1_ICACHE_SIZE,   32768,  8, 64 },
++    { 0x39, _SC_LEVEL2_CACHE_SIZE,   131072,  4, 64 },
++    { 0x3a, _SC_LEVEL2_CACHE_SIZE,   196608,  6, 64 },
++    { 0x3b, _SC_LEVEL2_CACHE_SIZE,   131072,  2, 64 },
++    { 0x3c, _SC_LEVEL2_CACHE_SIZE,   262144,  4, 64 },
++    { 0x3d, _SC_LEVEL2_CACHE_SIZE,   393216,  6, 64 },
++    { 0x3e, _SC_LEVEL2_CACHE_SIZE,   524288,  4, 64 },
++    { 0x41, _SC_LEVEL2_CACHE_SIZE,   131072,  4, 32 },
++    { 0x42, _SC_LEVEL2_CACHE_SIZE,   262144,  4, 32 },
++    { 0x43, _SC_LEVEL2_CACHE_SIZE,   524288,  4, 32 },
++    { 0x44, _SC_LEVEL2_CACHE_SIZE,  1048576,  4, 32 },
++    { 0x45, _SC_LEVEL2_CACHE_SIZE,  2097152,  4, 32 },
++    { 0x46, _SC_LEVEL3_CACHE_SIZE,  4194304,  4, 64 },
++    { 0x47, _SC_LEVEL3_CACHE_SIZE,  8388608,  8, 64 },
++    { 0x49, _SC_LEVEL2_CACHE_SIZE,  4194304, 16, 64 },
++    { 0x4a, _SC_LEVEL3_CACHE_SIZE,  6291456, 12, 64 },
++    { 0x4b, _SC_LEVEL3_CACHE_SIZE,  8388608, 16, 64 },
++    { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
++    { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
++    { 0x60, _SC_LEVEL1_DCACHE_SIZE,   16384,  8, 64 },
++    { 0x66, _SC_LEVEL1_DCACHE_SIZE,    8192,  4, 64 },
++    { 0x67, _SC_LEVEL1_DCACHE_SIZE,   16384,  4, 64 },
++    { 0x68, _SC_LEVEL1_DCACHE_SIZE,   32768,  4, 64 },
++    { 0x78, _SC_LEVEL2_CACHE_SIZE,  1048576,  8, 64 },
++    { 0x79, _SC_LEVEL2_CACHE_SIZE,   131072,  8, 64 },
++    { 0x7a, _SC_LEVEL2_CACHE_SIZE,   262144,  8, 64 },
++    { 0x7b, _SC_LEVEL2_CACHE_SIZE,   524288,  8, 64 },
++    { 0x7c, _SC_LEVEL2_CACHE_SIZE,  1048576,  8, 64 },
++    { 0x7d, _SC_LEVEL2_CACHE_SIZE,  2097152,  8, 64 },
++    { 0x7f, _SC_LEVEL2_CACHE_SIZE,   524288,  2, 64 },
++    { 0x82, _SC_LEVEL2_CACHE_SIZE,   262144,  8, 32 },
++    { 0x83, _SC_LEVEL2_CACHE_SIZE,   524288,  8, 32 },
++    { 0x84, _SC_LEVEL2_CACHE_SIZE,  1048576,  8, 32 },
++    { 0x85, _SC_LEVEL2_CACHE_SIZE,  2097152,  8, 32 },
++    { 0x86, _SC_LEVEL2_CACHE_SIZE,   524288,  4, 64 },
++    { 0x87, _SC_LEVEL2_CACHE_SIZE,  1048576,  8, 64 },
++  };
++
++#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0]))
++
++static int
++intel_02_known_compare (const void *p1, const void *p2)
++{
++  const struct intel_02_cache_info *i1;
++  const struct intel_02_cache_info *i2;
++
++  i1 = (const struct intel_02_cache_info *) p1;
++  i2 = (const struct intel_02_cache_info *) p2;
++
++  if (i1->idx == i2->idx)
++    return 0;
++
++  return i1->idx < i2->idx ? -1 : 1;
++}
++
++
++static long int
++__attribute__ ((noinline))
++intel_check_word (int name, unsigned int value, bool *has_level_2,
++                bool *no_level_2_or_3)
++{
++  if ((value & 0x80000000) != 0)
++    /* The register value is reserved.  */
++    return 0;
++
++  /* Fold the name.  The _SC_ constants are always in the order SIZE,
++     ASSOC, LINESIZE.  */
++  int folded_name = (_SC_LEVEL1_ICACHE_SIZE
++                   + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3);
++
++  while (value != 0)
++    {
++      unsigned int byte = value & 0xff;
++
++      if (byte == 0x40)
++      {
++        *no_level_2_or_3 = true;
++
++        if (folded_name == _SC_LEVEL3_CACHE_SIZE)
++          /* No need to look further.  */
++          break;
++      }
++      else
++      {
++        if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
++          {
++            /* Intel reused this value.  For family 15, model 6 it
++               specifies the 3rd level cache.  Otherwise the 2nd
++               level cache.  */
++            unsigned int eax;
++            unsigned int ebx;
++            unsigned int ecx;
++            unsigned int edx;
++            asm volatile ("cpuid"
++                          : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                          : "0" (1));
++
++            unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
++            unsigned int model = ((((eax >>16) & 0xf) << 4)
++                                  + ((eax >> 4) & 0xf));
++            if (family == 15 && model == 6)
++              {
++                /* The level 3 cache is encoded for this model like
++                   the level 2 cache is for other models.  Pretend
++                   the caller asked for the level 2 cache.  */
++                name = (_SC_LEVEL2_CACHE_SIZE
++                        + (name - _SC_LEVEL3_CACHE_SIZE));
++                folded_name = _SC_LEVEL3_CACHE_SIZE;
++              }
++          }
++
++        struct intel_02_cache_info *found;
++        struct intel_02_cache_info search;
++
++        search.idx = byte;
++        found = bsearch (&search, intel_02_known, nintel_02_known,
++                         sizeof (intel_02_known[0]), intel_02_known_compare);
++        if (found != NULL)
++          {
++            if (found->name == folded_name)
++              {
++                unsigned int offset = name - folded_name;
++
++                if (offset == 0)
++                  /* Cache size.  */
++                  return found->size;
++                if (offset == 1)
++                  return found->assoc;
++
++                assert (offset == 2);
++                return found->linesize;
++              }
++
++            if (found->name == _SC_LEVEL2_CACHE_SIZE)
++              *has_level_2 = true;
++          }
++      }
++
++      /* Next byte for the next round.  */
++      value >>= 8;
++    }
++
++  /* Nothing found.  */
++  return 0;
++}
++
++
++static long int __attribute__ ((noinline))
++handle_intel (int name, unsigned int maxidx)
++{
++  assert (maxidx >= 2);
++
++  /* OK, we can use the CPUID instruction to get all info about the
++     caches.  */
++  unsigned int cnt = 0;
++  unsigned int max = 1;
++  long int result = 0;
++  bool no_level_2_or_3 = false;
++  bool has_level_2 = false;
++
++  while (cnt++ < max)
++    {
++      unsigned int eax;
++      unsigned int ebx;
++      unsigned int ecx;
++      unsigned int edx;
++      asm volatile ("cpuid"
++                  : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                  : "0" (2));
++
++      /* The low byte of EAX in the first round contain the number of
++       rounds we have to make.  At least one, the one we are already
++       doing.  */
++      if (cnt == 1)
++      {
++        max = eax & 0xff;
++        eax &= 0xffffff00;
++      }
++
++      /* Process the individual registers' value.  */
++      result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3);
++      if (result != 0)
++      return result;
++
++      result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3);
++      if (result != 0)
++      return result;
++
++      result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3);
++      if (result != 0)
++      return result;
++
++      result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3);
++      if (result != 0)
++      return result;
++    }
++
++  if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE
++      && no_level_2_or_3)
++    return -1;
++
++  return 0;
++}
++
++
++static long int __attribute__ ((noinline))
++handle_amd (int name)
++{
++  unsigned int eax;
++  unsigned int ebx;
++  unsigned int ecx;
++  unsigned int edx;
++  asm volatile ("cpuid"
++              : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++              : "0" (0x80000000));
++
++  if (name >= _SC_LEVEL3_CACHE_SIZE)
++    return 0;
++
++  unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
++  if (eax < fn)
++    return 0;
++
++  asm volatile ("cpuid"
++              : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++              : "0" (fn));
++
++  if (name < _SC_LEVEL1_DCACHE_SIZE)
++    {
++      name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
++      ecx = edx;
++    }
++
++  switch (name)
++    {
++    case _SC_LEVEL1_DCACHE_SIZE:
++      return (ecx >> 14) & 0x3fc00;
++    case _SC_LEVEL1_DCACHE_ASSOC:
++      ecx >>= 16;
++      if ((ecx & 0xff) == 0xff)
++      /* Fully associative.  */
++      return (ecx << 2) & 0x3fc00;
++      return ecx & 0xff;
++    case _SC_LEVEL1_DCACHE_LINESIZE:
++      return ecx & 0xff;
++    case _SC_LEVEL2_CACHE_SIZE:
++      return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
++    case _SC_LEVEL2_CACHE_ASSOC:
++      ecx >>= 12;
++      switch (ecx & 0xf)
++        {
++        case 0:
++        case 1:
++        case 2:
++        case 4:
++        return ecx & 0xf;
++      case 6:
++        return 8;
++      case 8:
++        return 16;
++      case 0xf:
++        return (ecx << 6) & 0x3fffc00;
++      default:
++        return 0;
++        }
++    case _SC_LEVEL2_CACHE_LINESIZE:
++      return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
++    default:
++      assert (! "cannot happen");
++    }
++  return -1;
++}
++
++
++/* Get the value of the system variable NAME.  */
++long int
++attribute_hidden
++__cache_sysconf (int name)
++{
++  /* Find out what brand of processor.  */
++  unsigned int eax;
++  unsigned int ebx;
++  unsigned int ecx;
++  unsigned int edx;
++  asm volatile ("cpuid"
++              : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++              : "0" (0));
++
++  /* This spells out "GenuineIntel".  */
++  if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
++    return handle_intel (name, eax);
++
++  /* This spells out "AuthenticAMD".  */
++  if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
++    return handle_amd (name);
++
++  // XXX Fill in more vendors.
++
++  /* CPU not known, we have no information.  */
++  return 0;
++}
++
++
++/* Half the core cache size for use in memory and string routines, typically
++   L1 size. */
++long int __x86_64_core_cache_size_half attribute_hidden = 32 * 1024 / 2;
++/* Shared cache size for use in memory and string routines, typically
++   L2 or L3 size. */
++long int __x86_64_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2;
++/* PREFETCHW support flag for use in memory and string routines. */
++int __x86_64_prefetchw attribute_hidden;
++
++
++static void
++__attribute__((constructor))
++init_cacheinfo (void)
++{
++  /* Find out what brand of processor.  */
++  unsigned int eax;
++  unsigned int ebx;
++  unsigned int ecx;
++  unsigned int edx;
++  int max_cpuid;
++  int max_cpuid_ex;
++  long int core = -1;
++  long int shared = -1;
++  unsigned int level;
++  unsigned int threads = 0;
++
++  asm volatile ("cpuid"
++              : "=a" (max_cpuid), "=b" (ebx), "=c" (ecx), "=d" (edx)
++              : "0" (0));
++
++  /* This spells out "GenuineIntel".  */
++  if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
++    {
++      core = handle_intel (_SC_LEVEL1_DCACHE_SIZE, max_cpuid);
++
++      /* Try L3 first. */
++      level  = 3;
++      shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, max_cpuid);
++
++      if (shared <= 0)
++        {
++        /* Try L2 otherwise. */
++          level  = 2;
++          shared = handle_intel (_SC_LEVEL2_CACHE_SIZE, max_cpuid);
++      }
++
++      /* Figure out the number of logical threads that share the
++       highest cache level. */
++      if (max_cpuid >= 4)
++        {
++        int i = 0;
++
++        /* Query until desired cache level is enumerated. */
++        do
++          {
++              asm volatile ("cpuid"
++                          : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                          : "0" (4), "2" (i++));
++          }
++          while (((eax >> 5) & 0x7) != level);
++
++        threads = ((eax >> 14) & 0x3ff) + 1;
++      }
++      else
++        {
++        /* Assume that all logical threads share the highest cache level. */
++          asm volatile ("cpuid"
++                      : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                      : "0" (1));
++
++        threads = (ebx >> 16) & 0xff;
++      }
++
++      /* Cap usage of highest cache level to the number of supported
++       threads. */
++      if (shared > 0 && threads > 0)
++        shared /= threads;
++    }
++  /* This spells out "AuthenticAMD".  */
++  else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
++    {
++      core   = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
++      shared = handle_amd (_SC_LEVEL2_CACHE_SIZE);
++
++      asm volatile ("cpuid"
++                  : "=a" (max_cpuid_ex), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                  : "0" (0x80000000));
++
++      if (max_cpuid_ex >= 0x80000001)
++      {
++        asm volatile ("cpuid"
++                      : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++                      : "0" (0x80000001));
++        /*  PREFETCHW     || 3DNow! */
++        if ((ecx & 0x100) || (edx & 0x80000000))
++          __x86_64_prefetchw = -1;
++      }
++    }
++
++  if (core > 0)
++    __x86_64_core_cache_size_half = core / 2;
++
++  if (shared > 0)
++    __x86_64_shared_cache_size_half = shared / 2;
++}
+--- libc/sysdeps/x86_64/memcpy.S       18 Oct 2004 04:17:08 -0000      1.5
++++ libc/sysdeps/x86_64/memcpy.S       21 May 2007 19:21:01 -0000      1.6
+@@ -1,7 +1,10 @@
+-/* Highly optimized version for x86-64.
+-   Copyright (C) 1997, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
++/*
++   Optimized memcpy for x86-64.
++
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   Contributed by Evandro Menezes <evandro.menezes@amd.com>, 2007.
++
+    This file is part of the GNU C Library.
+-   Based on i586 version contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+    The GNU C Library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+@@ -16,86 +19,556 @@
+    You should have received a copy of the GNU Lesser General Public
+    License along with the GNU C Library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+-   02111-1307 USA.  */
++   02111-1307 USA.
++*/
+ #include <sysdep.h>
+ #include "asm-syntax.h"
+-#include "bp-sym.h"
+-#include "bp-asm.h"
+-/* BEWARE: `#ifdef memcpy' means that memcpy is redefined as `mempcpy',
+-   and the return value is the byte after the last one copied in
+-   the destination. */
+-#define MEMPCPY_P (defined memcpy)
++/* Stack slots in the red-zone. */
++
++#ifdef USE_AS_MEMPCPY
++#  define RETVAL      (0)
++#else
++#  define RETVAL      (-8)
++#endif
++#define SAVE0 (RETVAL - 8)
++#define SAVE1 (SAVE0  - 8)
++#define SAVE2 (SAVE1  - 8)
++#define SAVE3 (SAVE2  - 8)
+         .text
++
+ #if defined PIC && !defined NOT_IN_libc
+ ENTRY (__memcpy_chk)
++
+       cmpq    %rdx, %rcx
+       jb      HIDDEN_JUMPTARGET (__chk_fail)
++
+ END (__memcpy_chk)
+ #endif
+-ENTRY (BP_SYM (memcpy))
+-      /* Cutoff for the big loop is a size of 32 bytes since otherwise
+-         the loop will never be entered.  */
++
++ENTRY(memcpy)                         /* (void *, const void*, size_t) */
++
++/* Handle tiny blocks. */
++
++L(1try):                              /* up to 32B */
+       cmpq    $32, %rdx
+-      movq    %rdx, %rcx
+-#if !MEMPCPY_P
+-      movq    %rdi, %r10      /* Save value. */
++#ifndef USE_AS_MEMPCPY
++      movq    %rdi, %rax              /* save return value */
+ #endif
++      jae     L(1after)
+-      /* We need this in any case.  */
+-      cld
++L(1):                                 /* 1-byte once */
++      testb   $1, %dl
++      jz      L(1a)
+-      jbe     1f
++      movzbl  (%rsi), %ecx
++      movb    %cl, (%rdi)
+-      /* Align destination.  */
+-      movq    %rdi, %rax
+-      negq    %rax
+-      andq    $7, %rax
+-      subq    %rax, %rcx
+-      xchgq   %rax, %rcx
++      incq    %rsi
++      incq    %rdi
++
++      .p2align 4,, 4
++
++L(1a):                                        /* 2-byte once */
++      testb   $2, %dl
++      jz      L(1b)
++
++      movzwl  (%rsi), %ecx
++      movw    %cx, (%rdi)
+-      rep; movsb
++      addq    $2, %rsi
++      addq    $2, %rdi
+-      movq    %rax, %rcx
+-      subq    $32, %rcx
+-      js      2f
++      .p2align 4,, 4
++
++L(1b):                                        /* 4-byte once */
++      testb   $4, %dl
++      jz      L(1c)
++
++      movl    (%rsi), %ecx
++      movl    %ecx, (%rdi)
++
++      addq    $4, %rsi
++      addq    $4, %rdi
++
++      .p2align 4,, 4
++
++L(1c):                                        /* 8-byte once */
++      testb   $8, %dl
++      jz      L(1d)
++
++      movq    (%rsi), %rcx
++      movq    %rcx, (%rdi)
++
++      addq    $8, %rsi
++      addq    $8, %rdi
++
++      .p2align 4,, 4
++
++L(1d):                                        /* 16-byte loop */
++      andl    $0xf0, %edx
++      jz      L(exit)
+       .p2align 4
+-3:
+-      /* Now correct the loop counter.  Please note that in the following
+-         code the flags are not changed anymore.  */
+-      subq    $32, %rcx
++L(1loop):
++      movq      (%rsi), %rcx
++      movq    8 (%rsi), %r8
++      movq    %rcx,   (%rdi)
++      movq     %r8, 8 (%rdi)
++
++      subl    $16, %edx
++
++      leaq    16 (%rsi), %rsi
++      leaq    16 (%rdi), %rdi
++
++      jnz     L(1loop)
++
++      .p2align 4,, 4
++
++L(exit):                              /* exit */
++#ifdef USE_AS_MEMPCPY
++      movq    %rdi, %rax              /* return value */
++#else
++      rep
++#endif
++      retq
++
++      .p2align 4
++
++L(1after):
++#ifndef USE_AS_MEMPCPY
++      movq    %rax, RETVAL (%rsp)     /* save return value */
++#endif
++
++/* Align to the natural word size. */
++
++L(aligntry):
++      movl    %esi, %ecx              /* align by destination */
++
++      andl    $7, %ecx
++      jz      L(alignafter)           /* already aligned */
++
++L(align):                             /* align */
++      leaq    -8 (%rcx, %rdx), %rdx   /* calculate remaining bytes */
++      subl    $8, %ecx
++
++      .p2align 4
++
++L(alignloop):                         /* 1-byte alignment loop */
++      movzbl  (%rsi), %eax
++      movb    %al, (%rdi)
++
++      incl    %ecx
++
++      leaq    1 (%rsi), %rsi
++      leaq    1 (%rdi), %rdi
++
++      jnz     L(alignloop)
++
++      .p2align 4
++
++L(alignafter):
++
++/* Loop to handle mid-sized blocks. */
++
++L(32try):                             /* up to 1KB */
++      cmpq    $1024, %rdx
++      ja      L(32after)
++
++L(32):                                        /* 32-byte loop */
++      movl    %edx, %ecx
++      shrl    $5, %ecx
++      jz      L(32skip)
++
++      .p2align 4
++
++L(32loop):
++      decl    %ecx
+       movq    (%rsi), %rax
+-      movq    8(%rsi), %rdx
+-      movq    16(%rsi), %r8
+-      movq    24(%rsi), %r9
++      movq     8 (%rsi), %r8
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++
+       movq    %rax, (%rdi)
+-      movq    %rdx, 8(%rdi)
+-      movq    %r8, 16(%rdi)
+-      movq    %r9, 24(%rdi)
++      movq     %r8,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
+       leaq    32(%rsi), %rsi
+       leaq    32(%rdi), %rdi
+-      jns     3b
++      jz      L(32skip)               /* help out smaller blocks */
++
++      decl    %ecx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %r8
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++
++      movq    %rax,    (%rdi)
++      movq     %r8,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
++
++      leaq    32 (%rsi), %rsi
++      leaq    32 (%rdi), %rdi
++
++      jnz     L(32loop)
++
++      .p2align 4
+-      /* Correct extra loop counter modification.  */
+-2:    addq    $32, %rcx
+-1:    rep; movsb
++L(32skip):
++      andl    $31, %edx               /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++      jnz     L(1)
+-#if MEMPCPY_P
+-      movq    %rdi, %rax              /* Set return value.  */
++      movq    %rdi, %rax
+ #else
+-      movq    %r10, %rax              /* Set return value.  */
++      movq    RETVAL (%rsp), %rax
++      jnz     L(1)
+       
++      rep
++#endif
++      retq                            /* exit */
++
++      .p2align 4
++
++L(32after):
++
++/*
++      In order to minimize code-size in RTLD, algorithms specific for
++      larger blocks are excluded when building for RTLD.
++*/
++
++/* Handle large blocks smaller than 1/2 L1. */
++
++L(fasttry):                           /* first 1/2 L1 */
++#ifndef NOT_IN_libc                   /* only up to this algorithm outside of libc.so */
++      movq    __x86_64_core_cache_size_half (%rip), %r11
++      cmpq    %rdx, %r11              /* calculate the smaller of */
++      cmovaq  %rdx, %r11              /* remaining bytes and 1/2 L1 */
++#endif
++
++L(fast):                              /* good ol' MOVS */
++#ifndef NOT_IN_libc
++      movq    %r11, %rcx
++      andq    $-8, %r11
++#else
++      movq    %rdx, %rcx
++#endif
++      shrq    $3, %rcx
++      jz      L(fastskip)
++
++      rep
++      movsq
++
++      .p2align 4,, 4
++
++L(fastskip):
++#ifndef NOT_IN_libc
++      subq    %r11, %rdx              /* check for more */
++      testq   $-8, %rdx
++      jnz     L(fastafter)
+ #endif
+-      ret
+-END (BP_SYM (memcpy))
+-#if !MEMPCPY_P
++      andl    $7, %edx                /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++      jnz     L(1)
++
++      movq    %rdi, %rax
++#else
++      movq    RETVAL (%rsp), %rax
++      jnz     L(1)
++
++      rep
++#endif
++      retq                            /* exit */
++
++#ifndef NOT_IN_libc                   /* none of the algorithms below for RTLD */
++
++      .p2align 4
++
++L(fastafter):
++
++/* Handle large blocks smaller than 1/2 L2. */
++
++L(pretry):                            /* first 1/2 L2 */
++      movq    __x86_64_shared_cache_size_half (%rip), %r8
++      cmpq    %rdx, %r8               /* calculate the lesser of */
++      cmovaq  %rdx, %r8               /* remaining bytes and 1/2 L2 */
++
++L(pre):                                       /* 64-byte with prefetching */
++      movq    %r8, %rcx
++      andq    $-64, %r8
++      shrq    $6, %rcx
++      jz      L(preskip)
++
++      movq    %r14, SAVE0 (%rsp)
++      cfi_rel_offset (%r14, SAVE0)
++      movq    %r13, SAVE1 (%rsp)
++      cfi_rel_offset (%r13, SAVE1)
++      movq    %r12, SAVE2 (%rsp)
++      cfi_rel_offset (%r12, SAVE2)
++      movq    %rbx, SAVE3 (%rsp)
++      cfi_rel_offset (%rbx, SAVE3)
++
++      cmpl    $0, __x86_64_prefetchw (%rip)
++      jz      L(preloop)              /* check if PREFETCHW OK */
++
++      .p2align 4
++
++/* ... when PREFETCHW is available (less cache-probe traffic in MP systems). */
++
++L(prewloop):                          /* cache-line in state M */
++      decq    %rcx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %rbx
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++      movq    32 (%rsi), %r11
++      movq    40 (%rsi), %r12
++      movq    48 (%rsi), %r13
++      movq    56 (%rsi), %r14
++
++      prefetcht0       0 + 896 (%rsi)
++      prefetcht0      64 + 896 (%rsi)
++
++      movq    %rax,    (%rdi)
++      movq    %rbx,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
++      movq    %r11, 32 (%rdi)
++      movq    %r12, 40 (%rdi)
++      movq    %r13, 48 (%rdi)
++      movq    %r14, 56 (%rdi)
++
++      leaq    64 (%rsi), %rsi
++      leaq    64 (%rdi), %rdi
++
++      jz      L(prebail)
++
++      decq    %rcx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %rbx
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++      movq    32 (%rsi), %r11
++      movq    40 (%rsi), %r12
++      movq    48 (%rsi), %r13
++      movq    56 (%rsi), %r14
++
++      movq    %rax,    (%rdi)
++      movq    %rbx,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
++      movq    %r11, 32 (%rdi)
++      movq    %r12, 40 (%rdi)
++      movq    %r13, 48 (%rdi)
++      movq    %r14, 56 (%rdi)
++
++      prefetchw       896 - 64 (%rdi)
++      prefetchw       896 -  0 (%rdi)
++
++      leaq    64 (%rsi), %rsi
++      leaq    64 (%rdi), %rdi
++
++      jnz     L(prewloop)
++      jmp     L(prebail)
++
++      .p2align 4
++
++/* ... when PREFETCHW is not available. */
++
++L(preloop):                           /* cache-line in state E */
++      decq    %rcx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %rbx
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++      movq    32 (%rsi), %r11
++      movq    40 (%rsi), %r12
++      movq    48 (%rsi), %r13
++      movq    56 (%rsi), %r14
++
++      prefetcht0      896 +  0 (%rsi)
++      prefetcht0      896 + 64 (%rsi)
++
++      movq    %rax,    (%rdi)
++      movq    %rbx,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
++      movq    %r11, 32 (%rdi)
++      movq    %r12, 40 (%rdi)
++      movq    %r13, 48 (%rdi)
++      movq    %r14, 56 (%rdi)
++
++      leaq    64 (%rsi), %rsi
++      leaq    64 (%rdi), %rdi
++
++      jz      L(prebail)
++
++      decq    %rcx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %rbx
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++      movq    32 (%rsi), %r11
++      movq    40 (%rsi), %r12
++      movq    48 (%rsi), %r13
++      movq    56 (%rsi), %r14
++
++      prefetcht0      896 - 64 (%rdi)
++      prefetcht0      896 -  0 (%rdi)
++
++      movq    %rax,    (%rdi)
++      movq    %rbx,  8 (%rdi)
++      movq     %r9, 16 (%rdi)
++      movq    %r10, 24 (%rdi)
++      movq    %r11, 32 (%rdi)
++      movq    %r12, 40 (%rdi)
++      movq    %r13, 48 (%rdi)
++      movq    %r14, 56 (%rdi)
++
++      leaq    64 (%rsi), %rsi
++      leaq    64 (%rdi), %rdi
++
++      jnz     L(preloop)
++
++L(prebail):
++      movq    SAVE3 (%rsp), %rbx
++      cfi_restore (%rbx)
++      movq    SAVE2 (%rsp), %r12
++      cfi_restore (%r12)
++      movq    SAVE1 (%rsp), %r13
++      cfi_restore (%r13)
++      movq    SAVE0 (%rsp), %r14
++      cfi_restore (%r14)
++
++/*       .p2align 4 */
++
++L(preskip):
++      subq    %r8, %rdx               /* check for more */
++      testq   $-64, %rdx
++      jnz     L(preafter)
++
++      andl    $63, %edx               /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++      jnz     L(1)
++
++      movq    %rdi, %rax
++#else
++      movq    RETVAL (%rsp), %rax
++      jnz     L(1)
++
++      rep
++#endif
++      retq                            /* exit */
++
++      .p2align 4
++
++L(preafter):
++
++/* Loop to handle huge blocks. */
++
++L(NTtry):
++
++L(NT):                                        /* non-temporal 128-byte */
++      movq    %rdx, %rcx
++      shrq    $7, %rcx
++      jz      L(NTskip)
++
++      movq    %r14, SAVE0 (%rsp)
++      cfi_rel_offset (%r14, SAVE0)
++      movq    %r13, SAVE1 (%rsp)
++      cfi_rel_offset (%r13, SAVE1)
++      movq    %r12, SAVE2 (%rsp)
++      cfi_rel_offset (%r12, SAVE2)
++
++       .p2align 4
++
++L(NTloop):
++      prefetchnta     768 (%rsi)
++      prefetchnta     832 (%rsi)
++
++      decq    %rcx
++
++      movq       (%rsi), %rax
++      movq     8 (%rsi), %r8
++      movq    16 (%rsi), %r9
++      movq    24 (%rsi), %r10
++      movq    32 (%rsi), %r11
++      movq    40 (%rsi), %r12
++      movq    48 (%rsi), %r13
++      movq    56 (%rsi), %r14
++
++      movntiq %rax,    (%rdi)
++      movntiq  %r8,  8 (%rdi)
++      movntiq  %r9, 16 (%rdi)
++      movntiq %r10, 24 (%rdi)
++      movntiq %r11, 32 (%rdi)
++      movntiq %r12, 40 (%rdi)
++      movntiq %r13, 48 (%rdi)
++      movntiq %r14, 56 (%rdi)
++
++      movq     64 (%rsi), %rax
++      movq     72 (%rsi), %r8
++      movq     80 (%rsi), %r9
++      movq     88 (%rsi), %r10
++      movq     96 (%rsi), %r11
++      movq    104 (%rsi), %r12
++      movq    112 (%rsi), %r13
++      movq    120 (%rsi), %r14
++
++      movntiq %rax,  64 (%rdi)
++      movntiq  %r8,  72 (%rdi)
++      movntiq  %r9,  80 (%rdi)
++      movntiq %r10,  88 (%rdi)
++      movntiq %r11,  96 (%rdi)
++      movntiq %r12, 104 (%rdi)
++      movntiq %r13, 112 (%rdi)
++      movntiq %r14, 120 (%rdi)
++
++      leaq    128 (%rsi), %rsi
++      leaq    128 (%rdi), %rdi
++
++      jnz     L(NTloop)
++
++      sfence                          /* serialize memory stores */
++
++      movq    SAVE2 (%rsp), %r12
++      cfi_restore (%r12)
++      movq    SAVE1 (%rsp), %r13
++      cfi_restore (%r13)
++      movq    SAVE0 (%rsp), %r14
++      cfi_restore (%r14)
++
++L(NTskip):
++      andl    $127, %edx              /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++      jnz     L(1)
++
++      movq    %rdi, %rax
++#else
++      movq    RETVAL (%rsp), %rax
++      jnz     L(1)
++
++      rep
++#endif
++      retq                            /* exit */
++
++#endif /* !NOT_IN_libc */
++
++END(memcpy)
++
++#ifndef USE_AS_MEMPCPY
+ libc_hidden_builtin_def (memcpy)
+ #endif
+--- libc/sysdeps/x86_64/mempcpy.S      18 Oct 2004 04:17:08 -0000      1.3
++++ libc/sysdeps/x86_64/mempcpy.S      21 May 2007 19:21:16 -0000      1.4
+@@ -1,3 +1,4 @@
++#define USE_AS_MEMPCPY
+ #define memcpy __mempcpy
+ #define __memcpy_chk __mempcpy_chk
+ #include <sysdeps/x86_64/memcpy.S>
+--- libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c      10 Nov 2006 07:31:55 -0000      1.7
++++ libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c      21 May 2007 19:18:37 -0000      1.8
+@@ -24,328 +24,17 @@
+ static long int linux_sysconf (int name);
+-
+-
+-static const struct intel_02_cache_info
+-{
+-  unsigned int idx;
+-  int name;
+-  long int size;
+-  long int assoc;
+-  long int linesize;
+-} intel_02_known[] =
+-  {
+-    { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 },
+-    { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 },
+-    { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 },
+-    { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 },
+-    { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 },
+-    { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 },
+-    { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 },
+-    { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 },
+-    { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 },
+-    { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 },
+-    { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 },
+-    { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 },
+-    { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 },
+-    { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 },
+-    { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 },
+-    { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+-    { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 },
+-    { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 },
+-    { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 },
+-    { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 },
+-    { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
+-    { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
+-    { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
+-    { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 },
+-    { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
+-    { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
+-    { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
+-    { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
+-    { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 },
+-    { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 },
+-    { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 },
+-    { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 },
+-    { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+-    { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 },
+-    { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 },
+-    { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 },
+-    { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+-    { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 },
+-    { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 },
+-    { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 },
+-    { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 },
+-    { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 },
+-    { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 },
+-    { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+-    { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+-  };
+-#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known[0]))
+-
+-
+-static int
+-intel_02_known_compare (const void *p1, const void *p2)
+-{
+-  const struct intel_02_cache_info *i1;
+-  const struct intel_02_cache_info *i2;
+-
+-  i1 = (const struct intel_02_cache_info *) p1;
+-  i2 = (const struct intel_02_cache_info *) p2;
+-
+-  if (i1->idx == i2->idx)
+-    return 0;
+-
+-  return i1->idx < i2->idx ? -1 : 1;
+-}
+-
+-
+-static long int
+-__attribute__ ((noinline))
+-intel_check_word (int name, unsigned int value, bool *has_level_2,
+-                bool *no_level_2_or_3)
+-{
+-  if ((value & 0x80000000) != 0)
+-    /* The register value is reserved.  */
+-    return 0;
+-
+-  /* Fold the name.  The _SC_ constants are always in the order SIZE,
+-     ASSOC, LINESIZE.  */
+-  int folded_name = (_SC_LEVEL1_ICACHE_SIZE
+-                   + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3);
+-
+-  while (value != 0)
+-    {
+-      unsigned int byte = value & 0xff;
+-
+-      if (byte == 0x40)
+-      {
+-        *no_level_2_or_3 = true;
+-
+-        if (folded_name == _SC_LEVEL3_CACHE_SIZE)
+-          /* No need to look further.  */
+-          break;
+-      }
+-      else
+-      {
+-        if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
+-          {
+-            /* Intel reused this value.  For family 15, model 6 it
+-               specifies the 3rd level cache.  Otherwise the 2nd
+-               level cache.  */
+-            unsigned int eax;
+-            unsigned int ebx;
+-            unsigned int ecx;
+-            unsigned int edx;
+-            asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+-                          : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+-                          : "0" (1));
+-
+-            unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
+-            unsigned int model = ((((eax >>16) & 0xf) << 4)
+-                                  + ((eax >> 4) & 0xf));
+-            if (family == 15 && model == 6)
+-              {
+-                /* The level 3 cache is encoded for this model like
+-                   the level 2 cache is for other models.  Pretend
+-                   the caller asked for the level 2 cache.  */
+-                name = (_SC_LEVEL2_CACHE_SIZE
+-                        + (name - _SC_LEVEL3_CACHE_SIZE));
+-                folded_name = _SC_LEVEL3_CACHE_SIZE;
+-              }
+-          }
+-
+-        struct intel_02_cache_info *found;
+-        struct intel_02_cache_info search;
+-
+-        search.idx = byte;
+-        found = bsearch (&search, intel_02_known, nintel_02_known,
+-                         sizeof (intel_02_known[0]), intel_02_known_compare);
+-        if (found != NULL)
+-          {
+-            if (found->name == folded_name)
+-              {
+-                unsigned int offset = name - folded_name;
+-
+-                if (offset == 0)
+-                  /* Cache size.  */
+-                  return found->size;
+-                if (offset == 1)
+-                  return found->assoc;
+-
+-                assert (offset == 2);
+-                return found->linesize;
+-              }
+-
+-            if (found->name == _SC_LEVEL2_CACHE_SIZE)
+-              *has_level_2 = true;
+-          }
+-      }
+-
+-      /* Next byte for the next round.  */
+-      value >>= 8;
+-    }
+-
+-  /* Nothing found.  */
+-  return 0;
+-}
+-
+-
+-static long int __attribute__ ((noinline))
+-handle_intel (int name, unsigned int maxidx)
+-{
+-  assert (maxidx >= 2);
+-
+-  /* OK, we can use the CPUID instruction to get all info about the
+-     caches.  */
+-  unsigned int cnt = 0;
+-  unsigned int max = 1;
+-  long int result = 0;
+-  bool no_level_2_or_3 = false;
+-  bool has_level_2 = false;
+-  while (cnt++ < max)
+-    {
+-      unsigned int eax;
+-      unsigned int ebx;
+-      unsigned int ecx;
+-      unsigned int edx;
+-      asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+-                  : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+-                  : "0" (2));
+-
+-      /* The low byte of EAX in the first round contain the number of
+-       rounds we have to make.  At least one, the one we are already
+-       doing.  */
+-      if (cnt == 1)
+-      {
+-        max = eax & 0xff;
+-        eax &= 0xffffff00;
+-      }
+-
+-      /* Process the individual registers' value.  */
+-      result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3);
+-      if (result != 0)
+-      return result;
+-
+-      result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3);
+-      if (result != 0)
+-      return result;
+-
+-      result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3);
+-      if (result != 0)
+-      return result;
+-
+-      result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3);
+-      if (result != 0)
+-      return result;
+-    }
+-
+-  if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE
+-      && no_level_2_or_3)
+-    return -1;
+-
+-  return 0;
+-}
+-
+-
+-static long int __attribute__ ((noinline))
+-handle_amd (int name)
+-{
+-  unsigned int eax;
+-  unsigned int ebx;
+-  unsigned int ecx;
+-  unsigned int edx;
+-  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+-              : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+-              : "0" (0x80000000));
+-
+-  if (name >= _SC_LEVEL3_CACHE_SIZE)
+-    return 0;
+-
+-  unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
+-  if (eax < fn)
+-    return 0;
+-
+-  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+-              : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+-              : "0" (fn));
+-
+-  if (name < _SC_LEVEL1_DCACHE_SIZE)
+-    {
+-      name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
+-      ecx = edx;
+-    }
+-
+-  switch (name)
+-    {
+-    case _SC_LEVEL1_DCACHE_SIZE:
+-      return (ecx >> 14) & 0x3fc00;
+-    case _SC_LEVEL1_DCACHE_ASSOC:
+-      ecx >>= 16;
+-      if ((ecx & 0xff) == 0xff)
+-      /* Fully associative.  */
+-      return (ecx << 2) & 0x3fc00;
+-      return ecx & 0xff;
+-    case _SC_LEVEL1_DCACHE_LINESIZE:
+-      return ecx & 0xff;
+-    case _SC_LEVEL2_CACHE_SIZE:
+-      return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
+-    case _SC_LEVEL2_CACHE_ASSOC:
+-      ecx >>= 12;
+-      switch (ecx & 0xf)
+-        {
+-        case 0:
+-        case 1:
+-        case 2:
+-        case 4:
+-        return ecx & 0xf;
+-      case 6:
+-        return 8;
+-      case 8:
+-        return 16;
+-      case 0xf:
+-        return (ecx << 6) & 0x3fffc00;
+-      default:
+-        return 0;
+-        }
+-    case _SC_LEVEL2_CACHE_LINESIZE:
+-      return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
+-    default:
+-      assert (! "cannot happen");
+-    }
+-  return -1;
+-}
++extern long int __cache_sysconf (int) attribute_hidden;
+ /* Get the value of the system variable NAME.  */
+ long int
+ __sysconf (int name)
+ {
+-  /* We only handle the cache information here (for now).  */
+-  if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
+-    return linux_sysconf (name);
+-
+-  /* Find out what brand of processor.  */
+-  unsigned int eax;
+-  unsigned int ebx;
+-  unsigned int ecx;
+-  unsigned int edx;
+-  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+-              : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+-              : "0" (0));
+-
+-  /* This spells out "GenuineIntel".  */
+-  if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
+-    return handle_intel (name, eax);
+-
+-  /* This spells out "AuthenticAMD".  */
+-  if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+-    return handle_amd (name);
+-
+-  // XXX Fill in more vendors.
++  if (name >= _SC_LEVEL1_ICACHE_SIZE && name <= _SC_LEVEL4_CACHE_LINESIZE)
++    return __cache_sysconf (name);
+-  /* CPU not known, we have no information.  */
+-  return 0;
++  return linux_sysconf (name);
+ }
+ /* Now the generic Linux version.  */
index 6710838ca547f3c78b661e6fa40705b4208eeff1..5e13ea805a85b1eb70f3cb8e2c7a5d241ea29c42 100644 (file)
@@ -1,4 +1,4 @@
-%define glibcrelease 19
+%define glibcrelease 18.1
 %define auxarches i586 i686 athlon sparcv9 alphaev6
 %define xenarches i686 athlon
 %ifarch %{xenarches}
@@ -31,6 +31,8 @@ Source2: %(echo %{glibcsrcdir} | sed s/glibc-/glibc-libidn-/).tar.bz2
 Source3: %{glibcname}-fedora-%{glibcdate}.tar.bz2
 Patch0: %{glibcname}-fedora.patch
 Patch1: %{name}-ia64-lib64.patch
+Patch2: glibc-rh234946.patch
+Patch3: glibc-x86_64-memcpy.patch
 Buildroot: %{_tmppath}/glibc-%{PACKAGE_VERSION}-root
 Obsoletes: zoneinfo, libc-static, libc-devel, libc-profile, libc-headers,
 Obsoletes: gencat, locale, ldconfig, locale-ja, glibc-profile
@@ -242,6 +244,9 @@ package or when debugging this package.
 %patch1 -p1
 %endif
 %endif
+%patch2 -p1
+# Postpone until this is enough tested in F7
+#%patch3 -p1
 
 # Hack till glibc-kernheaders get updated, argh
 mkdir -p override_headers/linux