[meta-freescale] [PATCH 09/18] glibc : add 2.20 version

Chunrong Guo B40290 at freescale.com
Thu Dec 28 02:05:47 PST 2017


From: Chunrong Guo <chunrong.guo at nxp.com>

*ppc machine only  support glibc 2.20 version

Signed-off-by: Chunrong Guo <chunrong.guo at nxp.com>
---
 .../fix_for_centos_5.8.patch                       |    18 +
 recipes-core/glibc/cross-localedef-native_2.20.bb  |    57 +
 recipes-core/glibc/cross-localedef-native_2.22.bb  |    59 +
 .../glibc/cross-localedef-native_2.22.bbappend     |     7 +
 .../cross-localedef/enable-host-aarch64.patch      |    13 +
 recipes-core/glibc/glibc-common.inc                |     9 +
 .../glibc/glibc-fsl/0001.glibc.fix_sqrt2.patch     |  1692 ++
 .../glibc-fsl/0002.glibc.fix_sqrt_finite.patch     |   187 +
 .../0003.glibc.fix_slow_ieee754_sqrt.patch         |   410 +
 .../glibc-fsl/0004.glibc.fsl-ppc-no-fsqrt.patch    |   101 +
 .../glibc/glibc-fsl/0005.glibc.fix_prof.patch      |    47 +
 .../glibc/glibc-fsl/0006.glibc.fsl-crosszic.patch  |    76 +
 .../0007.glibc.fix_MTWX51911-enable_8xx.patch      |   530 +
 .../glibc-fsl/0008.glibc.e500v2_lib_support.patch  |  2542 +++
 .../0009.glibc.fsl-mcpy-e500mc-e5500-e6500.patch   |  1191 ++
 .../0010.glibc.fsl-e500mc-e5500-mset.patch         |  1337 ++
 .../glibc-fsl/0011.glibc.fsl-mset-e6500.patch      |   537 +
 .../glibc-fsl/0012.glibc.fsl-mcmp-e6500.patch      |   832 +
 .../glibc-fsl/0013.glibc.fsl-stcmp-e5500.patch     |   380 +
 .../0014.glibc.fsl-strchr-e500mc-e5500.patch       |   659 +
 .../0015.glibc.fsl-strcpy-e500mc-e5500.patch       |   627 +
 ...move-bash-dependency-for-nscd-init-script.patch |    75 +
 .../0016.glibc.fsl-strlen-e500mc-e5500.patch       |   407 +
 .../0017.glibc.fsl-strrchr-e500mc-e5500.patch      |  1072 ++
 ...0018.glibc.testsuite_remove-blocking-test.patch |   258 +
 .../glibc/glibc-fsl/0019.glibc.readv_proto.patch   |    61 +
 ...20.glibc.fsl-largemcpy-e500mc-e5500-e6500.patch |   932 +
 .../glibc-fsl/0021.glibc.undefined_static.patch    |    37 +
 .../glibc-fsl/0022.glibc.use-option-groups.patch   |   149 +
 .../00xx.glibc.add-option-groups-support.patch     |  1389 ++
 .../00xx.glibc.rtld_debug_option_group.patch       |   517 +
 .../glibc-fsl/00xx.glibc.use-option-groups.patch   | 16551 ++++++++++++++++++
 recipes-core/glibc/glibc-initial.inc               |    83 +
 recipes-core/glibc/glibc-initial_2.20.bb           |    11 +
 recipes-core/glibc/glibc-ld.inc                    |    56 +
 recipes-core/glibc/glibc-locale_2.20.bb            |     1 +
 recipes-core/glibc/glibc-mtrace_2.20.bb            |     1 +
 recipes-core/glibc/glibc-options.inc               |   162 +
 recipes-core/glibc/glibc-package.inc               |   227 +
 recipes-core/glibc/glibc-scripts_2.20.bb           |     1 +
 recipes-core/glibc/glibc-testing.inc               |    79 +
 .../glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch      |    56 +
 ...n-libm-err-tab.pl-with-specific-dirs-in-S.patch |    33 +
 ...-timezone-re-written-tzselect-as-posix-sh.patch |    45 +
 ...c-Cross-building-and-testing-instructions.patch |   619 +
 ...g-Eglibc-option-group-infrastructure-to-g.patch |  1436 ++
 ...020-eglibc-Help-bootstrap-cross-toolchain.patch |   100 +
 ...ry-picked-from-http-www.eglibc.org-archiv.patch |    64 +
 .../0022-eglibc-Clear-cache-lines-on-ppc8xx.patch  |    81 +
 ...0023-eglibc-Resolve-__fpscr_values-on-SH4.patch |    56 +
 ...orward-port-eglibc-options-groups-support.patch | 16842 +++++++++++++++++++
 .../glibc/0025-eglibc-Install-PIC-archives.patch   |   123 +
 ...ebug_mask-is-controlled-by-__OPTION_EGLIB.patch |   556 +
 ...option-groups-Conditionally-exclude-c-tes.patch |   145 +
 ...-3406-Stack-overflow-in-vfprintf-BZ-16617.patch |   339 +
 ...4-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch |   215 +
 .../CVE-2014-9402_endless-loop-in-getaddr_r.patch  |    65 +
 ...81-resolv-nss_dns-dns-host.c-buffer-overf.patch |    43 +
 recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch  |   529 +
 recipes-core/glibc/glibc/IO-acquire-lock-fix.patch |    17 +
 .../glibc/glibc/add_resource_h_to_wait_h.patch     |    20 +
 .../glibc/glibc/eglibc-header-bootstrap.patch      |    85 +
 .../glibc/glibc/eglibc-install-pic-archives.patch  |   109 +
 .../eglibc-ppc8xx-cache-line-workaround.patch      |    68 +
 .../glibc/glibc/eglibc-resolv-dynamic.patch        |    54 +
 .../glibc/glibc/eglibc-sh4-fpscr_values.patch      |    42 +
 .../glibc/glibc/eglibc-use-option-groups.patch     | 16546 ++++++++++++++++++
 recipes-core/glibc/glibc/eglibc.patch              |   602 +
 recipes-core/glibc/glibc/etc/ld.so.conf            |     0
 .../glibc/glibc/fix-tibetian-locales.patch         |    38 +
 recipes-core/glibc/glibc/fix_am_rootsbindir.patch  |    29 +
 recipes-core/glibc/glibc/fsl-ppc-no-fsqrt.patch    |   100 +
 recipes-core/glibc/glibc/generate-supported.mk     |    11 +
 recipes-core/glibc/glibc/glibc.fix_sqrt2.patch     |  1516 ++
 recipes-core/glibc/glibc/grok_gold.patch           |    34 +
 recipes-core/glibc/glibc/initgroups_keys.patch     |    20 +
 .../intl-Merge-with-gettext-version-0.19.3.patch   |  4797 ++++++
 recipes-core/glibc/glibc/ld-search-order.patch     |    56 +
 recipes-core/glibc/glibc/mips-rld-map-check.patch  |    27 +
 recipes-core/glibc/glibc/multilib_readlib.patch    |    19 +
 recipes-core/glibc/glibc/option-groups.patch       |  1397 ++
 recipes-core/glibc/glibc/ppc-sqrt_finite.patch     |   184 +
 .../glibc/glibc/ppc_slow_ieee754_sqrt.patch        |   365 +
 .../glibc/ppce6500-32b_slow_ieee754_sqrt.patch     |    47 +
 recipes-core/glibc/glibc/relocatable_sdk.patch     |   108 +
 .../glibc/glibc/relocatable_sdk_fix_openpath.patch |    41 +
 .../timezone-re-written-tzselect-as-posix-sh.patch |    38 +
 recipes-core/glibc/glibc_2.20.bb                   |   193 +
 .../glibc/ldconfig-native-2.12.1/32and64bit.patch  |   331 +
 recipes-core/glibc/ldconfig-native-2.12.1/README   |     8 +
 .../endian-ness_handling.patch                     |   454 +
 .../endian-ness_handling_fix.patch                 |    47 +
 .../ldconfig-native-2.12.1/endianess-header.patch  |   113 +
 .../glibc/ldconfig-native-2.12.1/flag_fix.patch    |    24 +
 .../ldconfig-default-to-all-multilib-dirs.patch    |    37 +
 .../ldconfig-native-2.12.1.tar.bz2                 |   Bin 0 -> 21491 bytes
 .../glibc/ldconfig-native-2.12.1/ldconfig.patch    |   471 +
 .../ldconfig_aux-cache_path_fix.patch              |    36 +
 recipes-core/glibc/ldconfig-native_2.12.1.bb       |    33 +
 recipes-core/glibc/site_config/funcs               |   474 +
 recipes-core/glibc/site_config/headers             |   156 +
 recipes-core/glibc/site_config/types               |    21 +
 102 files changed, 83495 insertions(+)
 create mode 100644 recipes-core/glibc/cross-localedef-native/fix_for_centos_5.8.patch
 create mode 100644 recipes-core/glibc/cross-localedef-native_2.20.bb
 create mode 100644 recipes-core/glibc/cross-localedef-native_2.22.bb
 create mode 100644 recipes-core/glibc/cross-localedef-native_2.22.bbappend
 create mode 100644 recipes-core/glibc/cross-localedef/enable-host-aarch64.patch
 create mode 100644 recipes-core/glibc/glibc-common.inc
 create mode 100755 recipes-core/glibc/glibc-fsl/0001.glibc.fix_sqrt2.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0002.glibc.fix_sqrt_finite.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0003.glibc.fix_slow_ieee754_sqrt.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0004.glibc.fsl-ppc-no-fsqrt.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0005.glibc.fix_prof.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0006.glibc.fsl-crosszic.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0007.glibc.fix_MTWX51911-enable_8xx.patch
 create mode 100644 recipes-core/glibc/glibc-fsl/0008.glibc.e500v2_lib_support.patch
 create mode 100644 recipes-core/glibc/glibc-fsl/0009.glibc.fsl-mcpy-e500mc-e5500-e6500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0010.glibc.fsl-e500mc-e5500-mset.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0011.glibc.fsl-mset-e6500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0012.glibc.fsl-mcmp-e6500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0013.glibc.fsl-stcmp-e5500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0014.glibc.fsl-strchr-e500mc-e5500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0015.glibc.fsl-strcpy-e500mc-e5500.patch
 create mode 100644 recipes-core/glibc/glibc-fsl/0016-Remove-bash-dependency-for-nscd-init-script.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0016.glibc.fsl-strlen-e500mc-e5500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0017.glibc.fsl-strrchr-e500mc-e5500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0018.glibc.testsuite_remove-blocking-test.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0019.glibc.readv_proto.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0020.glibc.fsl-largemcpy-e500mc-e5500-e6500.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/0021.glibc.undefined_static.patch
 create mode 100644 recipes-core/glibc/glibc-fsl/0022.glibc.use-option-groups.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/00xx.glibc.add-option-groups-support.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/00xx.glibc.rtld_debug_option_group.patch
 create mode 100755 recipes-core/glibc/glibc-fsl/00xx.glibc.use-option-groups.patch
 create mode 100644 recipes-core/glibc/glibc-initial.inc
 create mode 100644 recipes-core/glibc/glibc-initial_2.20.bb
 create mode 100644 recipes-core/glibc/glibc-ld.inc
 create mode 100644 recipes-core/glibc/glibc-locale_2.20.bb
 create mode 100644 recipes-core/glibc/glibc-mtrace_2.20.bb
 create mode 100644 recipes-core/glibc/glibc-options.inc
 create mode 100644 recipes-core/glibc/glibc-package.inc
 create mode 100644 recipes-core/glibc/glibc-scripts_2.20.bb
 create mode 100644 recipes-core/glibc/glibc-testing.inc
 create mode 100644 recipes-core/glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch
 create mode 100644 recipes-core/glibc/glibc/0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch
 create mode 100644 recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch
 create mode 100644 recipes-core/glibc/glibc/0018-eglibc-Cross-building-and-testing-instructions.patch
 create mode 100644 recipes-core/glibc/glibc/0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch
 create mode 100644 recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch
 create mode 100644 recipes-core/glibc/glibc/0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch
 create mode 100644 recipes-core/glibc/glibc/0022-eglibc-Clear-cache-lines-on-ppc8xx.patch
 create mode 100644 recipes-core/glibc/glibc/0023-eglibc-Resolve-__fpscr_values-on-SH4.patch
 create mode 100644 recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch
 create mode 100644 recipes-core/glibc/glibc/0025-eglibc-Install-PIC-archives.patch
 create mode 100644 recipes-core/glibc/glibc/0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch
 create mode 100644 recipes-core/glibc/glibc/0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch
 create mode 100644 recipes-core/glibc/glibc/CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch
 create mode 100644 recipes-core/glibc/glibc/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
 create mode 100644 recipes-core/glibc/glibc/CVE-2014-9402_endless-loop-in-getaddr_r.patch
 create mode 100644 recipes-core/glibc/glibc/CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch
 create mode 100644 recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch
 create mode 100644 recipes-core/glibc/glibc/IO-acquire-lock-fix.patch
 create mode 100644 recipes-core/glibc/glibc/add_resource_h_to_wait_h.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-header-bootstrap.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-install-pic-archives.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-ppc8xx-cache-line-workaround.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-resolv-dynamic.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-sh4-fpscr_values.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc-use-option-groups.patch
 create mode 100644 recipes-core/glibc/glibc/eglibc.patch
 create mode 100644 recipes-core/glibc/glibc/etc/ld.so.conf
 create mode 100644 recipes-core/glibc/glibc/fix-tibetian-locales.patch
 create mode 100644 recipes-core/glibc/glibc/fix_am_rootsbindir.patch
 create mode 100644 recipes-core/glibc/glibc/fsl-ppc-no-fsqrt.patch
 create mode 100644 recipes-core/glibc/glibc/generate-supported.mk
 create mode 100644 recipes-core/glibc/glibc/glibc.fix_sqrt2.patch
 create mode 100644 recipes-core/glibc/glibc/grok_gold.patch
 create mode 100644 recipes-core/glibc/glibc/initgroups_keys.patch
 create mode 100644 recipes-core/glibc/glibc/intl-Merge-with-gettext-version-0.19.3.patch
 create mode 100644 recipes-core/glibc/glibc/ld-search-order.patch
 create mode 100644 recipes-core/glibc/glibc/mips-rld-map-check.patch
 create mode 100644 recipes-core/glibc/glibc/multilib_readlib.patch
 create mode 100644 recipes-core/glibc/glibc/option-groups.patch
 create mode 100644 recipes-core/glibc/glibc/ppc-sqrt_finite.patch
 create mode 100644 recipes-core/glibc/glibc/ppc_slow_ieee754_sqrt.patch
 create mode 100644 recipes-core/glibc/glibc/ppce6500-32b_slow_ieee754_sqrt.patch
 create mode 100644 recipes-core/glibc/glibc/relocatable_sdk.patch
 create mode 100644 recipes-core/glibc/glibc/relocatable_sdk_fix_openpath.patch
 create mode 100644 recipes-core/glibc/glibc/timezone-re-written-tzselect-as-posix-sh.patch
 create mode 100644 recipes-core/glibc/glibc_2.20.bb
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/32and64bit.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/README
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling_fix.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/endianess-header.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/flag_fix.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-default-to-all-multilib-dirs.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-native-2.12.1.tar.bz2
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch
 create mode 100644 recipes-core/glibc/ldconfig-native-2.12.1/ldconfig_aux-cache_path_fix.patch
 create mode 100644 recipes-core/glibc/ldconfig-native_2.12.1.bb
 create mode 100644 recipes-core/glibc/site_config/funcs
 create mode 100644 recipes-core/glibc/site_config/headers
 create mode 100644 recipes-core/glibc/site_config/types

diff --git a/recipes-core/glibc/cross-localedef-native/fix_for_centos_5.8.patch b/recipes-core/glibc/cross-localedef-native/fix_for_centos_5.8.patch
new file mode 100644
index 0000000..186a480
--- /dev/null
+++ b/recipes-core/glibc/cross-localedef-native/fix_for_centos_5.8.patch
@@ -0,0 +1,18 @@
+Upstream-Status: Inappropriate [other]
+
+This is a hack to fix building the locale bits on an older
+CentOs 5.X machine
+
+Index: git/locale/programs/config.h
+===================================================================
+--- git/locale/programs/config.h
++++ git.orig/locale/programs/config.h
+@@ -19,6 +19,8 @@
+ #ifndef _LD_CONFIG_H
+ #define _LD_CONFIG_H	1
+ 
++#define DUMMY_LOCALE_T
++
+ /* Use the internal textdomain used for libc messages.  */
+ #define PACKAGE _libc_intl_domainname
+ #ifndef VERSION
diff --git a/recipes-core/glibc/cross-localedef-native_2.20.bb b/recipes-core/glibc/cross-localedef-native_2.20.bb
new file mode 100644
index 0000000..c94501a
--- /dev/null
+++ b/recipes-core/glibc/cross-localedef-native_2.20.bb
@@ -0,0 +1,57 @@
+SUMMARY = "Cross locale generation tool for glibc"
+HOMEPAGE = "http://www.gnu.org/software/libc/libc.html"
+SECTION = "libs"
+LICENSE = "LGPL-2.1"
+
+LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \
+      file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+      file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \
+      file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c"
+
+
+inherit native
+inherit autotools
+
+FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:"
+
+PV = "2.20"
+
+SRC_URI = "git://sourceware.org/git/glibc.git;branch=release/${PV}/master;name=glibc \
+           git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \
+	   file://fix_for_centos_5.8.patch \
+           ${EGLIBCPATCHES} \
+          "
+EGLIBCPATCHES = "\
+           file://intl-Merge-with-gettext-version-0.19.3.patch \
+           file://timezone-re-written-tzselect-as-posix-sh.patch \
+           file://eglibc.patch \
+           file://option-groups.patch \
+           file://GLRO_dl_debug_mask.patch \
+           file://eglibc-header-bootstrap.patch \
+           file://eglibc-resolv-dynamic.patch \
+           file://eglibc-ppc8xx-cache-line-workaround.patch \
+           file://eglibc-sh4-fpscr_values.patch \
+           file://eglibc-use-option-groups.patch \
+          "
+
+SRCREV_glibc = "b8079dd0d360648e4e8de48656c5c38972621072"
+SRCREV_localedef = "c833367348d39dad7ba018990bfdaffaec8e9ed3"
+
+# Makes for a rather long rev (22 characters), but...
+#
+SRCREV_FORMAT = "glibc__localedef"
+
+S = "${WORKDIR}/git"
+
+EXTRA_OECONF = "--with-glibc=${S}"
+CFLAGS += "-fgnu89-inline -std=gnu99 -DNOT_IN_libc=1"
+
+do_configure () {
+	${S}/localedef/configure ${EXTRA_OECONF}
+}
+
+
+do_install() {
+	install -d ${D}${bindir} 
+	install -m 0755 ${B}/localedef ${D}${bindir}/cross-localedef
+}
diff --git a/recipes-core/glibc/cross-localedef-native_2.22.bb b/recipes-core/glibc/cross-localedef-native_2.22.bb
new file mode 100644
index 0000000..03be9c0
--- /dev/null
+++ b/recipes-core/glibc/cross-localedef-native_2.22.bb
@@ -0,0 +1,59 @@
+SUMMARY = "Cross locale generation tool for glibc"
+HOMEPAGE = "http://www.gnu.org/software/libc/libc.html"
+SECTION = "libs"
+LICENSE = "LGPL-2.1"
+
+LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \
+      file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+      file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \
+      file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c"
+
+
+inherit native
+inherit autotools
+
+FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:"
+
+SRCBRANCH ?= "release/${PV}/master"
+GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
+
+SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
+           git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \
+           file://fix_for_centos_5.8.patch \
+           ${EGLIBCPATCHES} \
+"
+EGLIBCPATCHES = "\
+           file://0017-timezone-re-written-tzselect-as-posix-sh.patch \
+           file://0018-eglibc-Cross-building-and-testing-instructions.patch \
+           file://0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch \
+           file://0020-eglibc-Help-bootstrap-cross-toolchain.patch \
+           file://0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch \
+           file://0022-eglibc-Clear-cache-lines-on-ppc8xx.patch \
+           file://0023-eglibc-Resolve-__fpscr_values-on-SH4.patch \
+           file://0024-eglibc-Forward-port-eglibc-options-groups-support.patch \
+           file://0025-eglibc-Install-PIC-archives.patch \
+           file://0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch \
+           file://0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch \
+"
+
+SRCREV_glibc ?= "a34d1c6afc86521d6ad17662a3b5362d8481514c"
+SRCREV_localedef ?= "c833367348d39dad7ba018990bfdaffaec8e9ed3"
+
+# Makes for a rather long rev (22 characters), but...
+#
+SRCREV_FORMAT = "glibc_localedef"
+
+S = "${WORKDIR}/git"
+
+EXTRA_OECONF = "--with-glibc=${S}"
+CFLAGS += "-fgnu89-inline -std=gnu99 -DIS_IN\(x\)='0'"
+
+do_configure () {
+	${S}/localedef/configure ${EXTRA_OECONF}
+}
+
+
+do_install() {
+	install -d ${D}${bindir}
+	install -m 0755 ${B}/localedef ${D}${bindir}/cross-localedef
+}
diff --git a/recipes-core/glibc/cross-localedef-native_2.22.bbappend b/recipes-core/glibc/cross-localedef-native_2.22.bbappend
new file mode 100644
index 0000000..2fe775d
--- /dev/null
+++ b/recipes-core/glibc/cross-localedef-native_2.22.bbappend
@@ -0,0 +1,7 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
+
+# We need this patch to allow host side aarch64
+SRC_URI_append_fsl-qoriq = "\
+    file://enable-host-aarch64.patch \
+"
+
diff --git a/recipes-core/glibc/cross-localedef/enable-host-aarch64.patch b/recipes-core/glibc/cross-localedef/enable-host-aarch64.patch
new file mode 100644
index 0000000..c129a51
--- /dev/null
+++ b/recipes-core/glibc/cross-localedef/enable-host-aarch64.patch
@@ -0,0 +1,13 @@
+diff --git a/localedef/config.guess b/localedef/config.guess
+index 61f2e4c..9834a43 100644
+--- a/localedef/config.guess
++++ b/localedef/config.guess
+@@ -820,7 +820,7 @@ EOF
+     i*86:Minix:*:*)
+ 	echo ${UNAME_MACHINE}-pc-minix
+ 	exit 0 ;;
+-    arm*:Linux:*:*)
++    arm*:Linux:*:* | aarch*:Linux:*:*)
+ 	echo ${UNAME_MACHINE}-unknown-linux-gnu
+ 	exit 0 ;;
+     cris:Linux:*:*)
diff --git a/recipes-core/glibc/glibc-common.inc b/recipes-core/glibc/glibc-common.inc
new file mode 100644
index 0000000..bba1568
--- /dev/null
+++ b/recipes-core/glibc/glibc-common.inc
@@ -0,0 +1,9 @@
+SUMMARY = "GLIBC (GNU C Library)"
+DESCRIPTION = "The GNU C Library is used as the system C library in most systems with the Linux kernel."
+HOMEPAGE = "http://www.gnu.org/software/libc/libc.html"
+SECTION = "libs"
+LICENSE = "GPLv2 & LGPLv2.1"
+LIC_FILES_CHKSUM ?= "file://LICENSES;md5=07a394b26e0902b9ffdec03765209770 \
+      file://COPYING;md5=393a5ca445f6965873eca0259a17f833 \
+      file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \
+      file://COPYING.LIB;md5=bbb461211a33b134d42ed5ee802b37ff "
diff --git a/recipes-core/glibc/glibc-fsl/0001.glibc.fix_sqrt2.patch b/recipes-core/glibc/glibc-fsl/0001.glibc.fix_sqrt2.patch
new file mode 100755
index 0000000..16f742a
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0001.glibc.fix_sqrt2.patch
@@ -0,0 +1,1692 @@
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c	2012-06-14 14:51:50.452001745 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c	2012-06-14 14:51:50.452001745 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c	2012-06-14 14:55:14.749001061 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c	2012-06-14 14:55:14.749001061 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c	2012-06-14 14:55:21.812002270 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c	2012-06-14 14:55:21.812002270 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	2012-06-14 14:55:24.620001266 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	2012-06-14 14:55:24.620001266 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c	2012-06-14 14:51:50.452001745 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c	2012-06-14 14:51:50.452001745 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c	2012-06-14 14:56:02.080000985 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++  
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c	2012-06-14 14:56:02.080000985 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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 <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l[1] & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies	2012-06-14 14:51:50.452001745 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc32/603e/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies	2012-06-14 14:54:00.481000876 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc32/e500mc/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies	2012-06-14 14:54:17.000001007 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc32/e5500/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies	2012-06-14 14:54:31.054001299 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc32/e6500/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies	2012-06-14 14:51:50.453001709 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc64/e5500/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies	2012-06-14 14:58:14.298001288 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc64/e6500/fpu
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c	2014-07-24 04:42:30.366372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c	2014-07-24 04:42:46.249372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c	2014-07-24 04:42:30.366372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c	2014-07-24 04:42:46.249372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c	2014-07-24 04:42:30.366372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c	2014-07-24 04:42:46.249372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c	2014-07-24 04:42:30.366372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c	2014-07-24 04:42:46.249372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c	2014-07-24 04:42:46.250372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c	2014-07-24 04:42:46.250372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	2014-07-24 04:42:46.250372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	2014-07-24 04:42:46.250372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c	2014-07-24 04:42:46.250372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c	2014-07-24 04:42:30.367372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c	2014-07-24 04:42:46.250372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c libc-sqrt-patch/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c	2014-07-24 04:42:30.368372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c	2014-07-24 04:42:46.251372001 -0500
+@@ -80,7 +80,7 @@
+ 
+           g = b * y;
+           h = 0.5 * y;
+-  
++
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+             return __ieee754_sqrt (b * two108) * twom54;
+@@ -125,7 +125,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c libc-sqrt-patch/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+--- libc-sqrt-orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c	2014-07-24 04:42:30.368372001 -0500
++++ libc-sqrt-patch/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c	2014-07-24 04:42:46.251372001 -0500
+@@ -92,7 +92,7 @@
+       feraiseexcept (FE_INVALID_SQRT);
+ 
+       fenv_union_t u = { .fenv = fegetenv_register () };
+-      if ((u.l[1] & FE_INVALID) == 0)
++      if ((u.l & FE_INVALID) == 0)
+ #endif
+ 	feraiseexcept (FE_INVALID);
+       b = a_nan.value;
+diff -Naur libc-sqrt-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies libc-sqrt-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies
+--- libc-sqrt-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
++++ libc-sqrt-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies	2014-07-24 04:42:46.251372001 -0500
+@@ -0,0 +1,2 @@
++# e300c3 is a variant of 603e so use the same optimizations for sqrt
++powerpc/powerpc32/603e/fpu
diff --git a/recipes-core/glibc/glibc-fsl/0002.glibc.fix_sqrt_finite.patch b/recipes-core/glibc/glibc-fsl/0002.glibc.fix_sqrt_finite.patch
new file mode 100755
index 0000000..d793774
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0002.glibc.fix_sqrt_finite.patch
@@ -0,0 +1,187 @@
+# Problem Statement:
+  on ppc fixes the errors like below
+  | ./.libs/libpulsecore-1.1.so: undefined reference to `__sqrt_finite'
+  | collect2: ld returned 1 exit status
+
+# Reference:
+  ppc-sqrt_finite.patch
+
+ChangeLog
+
+2012-01-06  Khem Raj  <raj.khem at gmail.com>
+
+	* sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c: Add __*_finite alias.
+	Remove cruft.
+	* sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c: Ditto.
+	* sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c: Ditto.
+	* sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c: Ditto.
+ 
+Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+@@ -39,14 +39,8 @@ static const float half = 0.5;
+    We find the actual square root and half of its reciprocal
+    simultaneously.  */
+ 
+-#ifdef __STDC__
+ double
+ __ieee754_sqrt (double b)
+-#else
+-double
+-__ieee754_sqrt (b)
+-     double b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -132,3 +126,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+@@ -37,14 +37,8 @@ static const float threehalf = 1.5;
+    We find the reciprocal square root and use that to compute the actual
+    square root.  */
+ 
+-#ifdef __STDC__
+ float
+ __ieee754_sqrtf (float b)
+-#else
+-float
+-__ieee754_sqrtf (b)
+-     float b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -99,3 +93,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+@@ -39,14 +39,8 @@ static const float half = 0.5;
+    We find the actual square root and half of its reciprocal
+    simultaneously.  */
+ 
+-#ifdef __STDC__
+ double
+ __ieee754_sqrt (double b)
+-#else
+-double
+-__ieee754_sqrt (b)
+-     double b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -132,3 +126,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+@@ -37,14 +37,8 @@ static const float threehalf = 1.5;
+    We find the reciprocal square root and use that to compute the actual
+    square root.  */
+ 
+-#ifdef __STDC__
+ float
+ __ieee754_sqrtf (float b)
+-#else
+-float
+-__ieee754_sqrtf (b)
+-     float b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -99,3 +93,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+
diff --git a/recipes-core/glibc/glibc-fsl/0003.glibc.fix_slow_ieee754_sqrt.patch b/recipes-core/glibc/glibc-fsl/0003.glibc.fix_slow_ieee754_sqrt.patch
new file mode 100755
index 0000000..b1fcaba
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0003.glibc.fix_slow_ieee754_sqrt.patch
@@ -0,0 +1,410 @@
+# Problem Statement:
+  __ieee754_sqrt{,f} are now inline functions and call out __slow versions
+
+# Reference 
+  ppc_slow_ieee754_sqrt.patch
+
+
+Signed-off-by: Khem Raj <raj.khem at gmail.com>
+Upstream-Status: Pending
+Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+@@ -40,7 +40,7 @@ static const float half = 0.5;
+    simultaneously.  */
+ 
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -77,7 +77,7 @@ __ieee754_sqrt (double b)
+   
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -126,4 +126,12 @@ __ieee754_sqrt (double b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+@@ -38,7 +38,7 @@ static const float threehalf = 1.5;
+    square root.  */
+ 
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -93,4 +93,10 @@ __ieee754_sqrtf (float b)
+     }
+   return f_washf (b);
+ }
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+@@ -40,7 +40,7 @@ static const float half = 0.5;
+    simultaneously.  */
+ 
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -77,7 +77,7 @@ __ieee754_sqrt (double b)
+   
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -126,4 +126,12 @@ __ieee754_sqrt (double b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++  return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+@@ -38,7 +38,7 @@ static const float threehalf = 1.5;
+    square root.  */
+ 
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -93,4 +93,11 @@ __ieee754_sqrtf (float b)
+     }
+   return f_washf (b);
+ }
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+   
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+   
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+   
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+===================================================================
+--- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff -rNu libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	2014-04-08 04:39:58.487229887 -0500
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c	2014-04-08 04:40:52.643069198 -0500
+@@ -41,10 +41,10 @@
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+diff -rNu libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	2014-04-08 04:39:58.487229887 -0500
++++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c	2014-04-08 04:41:26.017067682 -0500
+@@ -39,10 +39,10 @@
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
diff --git a/recipes-core/glibc/glibc-fsl/0004.glibc.fsl-ppc-no-fsqrt.patch b/recipes-core/glibc/glibc-fsl/0004.glibc.fsl-ppc-no-fsqrt.patch
new file mode 100755
index 0000000..24a85b6
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0004.glibc.fsl-ppc-no-fsqrt.patch
@@ -0,0 +1,101 @@
+Create e5500 specific math_private.h and let it include when compiling for e5500/64bit core
+We prefefine __CPU_HAS_FSQRT to 0 and then in general ppc64 math_private.h we check if its
+already defined before redefining it. This way we can ensure that on e5500 builds it wont
+emit fsqrt intructions
+
+-Khem
+
+Upstream-Status: Pending
+
+Index: git/sysdeps/powerpc/fpu/math_private.h
+===================================================================
+--- git.orig/sysdeps/powerpc/fpu/math_private.h	2014-08-29 10:31:30.224070587 -0700
++++ git/sysdeps/powerpc/fpu/math_private.h	2014-08-29 10:31:30.212070587 -0700
+@@ -25,10 +25,12 @@
+ #include <fenv_private.h>
+ #include_next <math_private.h>
+ 
+-# if __WORDSIZE == 64 || defined _ARCH_PWR4
+-#  define __CPU_HAS_FSQRT 1
+-# else
+-#  define __CPU_HAS_FSQRT ((GLRO(dl_hwcap) & PPC_FEATURE_64) != 0)
++# ifndef __CPU_HAS_FSQRT
++#  if __WORDSIZE == 64 || defined _ARCH_PWR4
++#   define __CPU_HAS_FSQRT 1
++#  else
++#   define __CPU_HAS_FSQRT ((GLRO(dl_hwcap) & PPC_FEATURE_64) != 0)
++#  endif
+ # endif
+ 
+ extern double __slow_ieee754_sqrt (double);
+Index: git/sysdeps/powerpc/powerpc64/e5500/fpu/math_private.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ git/sysdeps/powerpc/powerpc64/e5500/fpu/math_private.h	2014-08-29 10:31:30.212070587 -0700
+@@ -0,0 +1,9 @@
++#ifndef _E5500_MATH_PRIVATE_H_
++#define _E5500_MATH_PRIVATE_H_ 1
++/* E5500 core FPU does not implement
++   fsqrt */
++
++#define __CPU_HAS_FSQRT 0
++#include_next <math_private.h>
++
++#endif /* _E5500_MATH_PRIVATE_H_ */
+Index: git/sysdeps/powerpc/powerpc64/e6500/fpu/math_private.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ git/sysdeps/powerpc/powerpc64/e6500/fpu/math_private.h	2014-08-29 10:31:30.212070587 -0700
+@@ -0,0 +1,9 @@
++#ifndef _E6500_MATH_PRIVATE_H_
++#define _E6500_MATH_PRIVATE_H_ 1
++/* E6500 core FPU does not implement
++   fsqrt */
++
++#define __CPU_HAS_FSQRT 0
++#include_next <math_private.h>
++
++#endif /* _E6500_MATH_PRIVATE_H_ */
+Index: git/sysdeps/powerpc/powerpc32/e500mc/fpu/math_private.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ git/sysdeps/powerpc/powerpc32/e500mc/fpu/math_private.h	2014-08-29 10:31:30.212070587 -0700
+@@ -0,0 +1,9 @@
++#ifndef _E500MC_MATH_PRIVATE_H_
++#define _E500MC_MATH_PRIVATE_H_ 1
++/* E500MC core FPU does not implement
++   fsqrt */
++
++#define __CPU_HAS_FSQRT 0
++#include_next <math_private.h>
++
++#endif /* _E500MC_MATH_PRIVATE_H_ */
+Index: git/sysdeps/powerpc/powerpc32/e5500/fpu/math_private.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ git/sysdeps/powerpc/powerpc32/e5500/fpu/math_private.h	2014-08-29 10:31:30.216070587 -0700
+@@ -0,0 +1,9 @@
++#ifndef _E5500_MATH_PRIVATE_H_
++#define _E5500_MATH_PRIVATE_H_ 1
++/* E5500 core FPU does not implement
++   fsqrt */
++
++#define __CPU_HAS_FSQRT 0
++#include_next <math_private.h>
++
++#endif /* _E5500_MATH_PRIVATE_H_ */
+Index: git/sysdeps/powerpc/powerpc32/e6500/fpu/math_private.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ git/sysdeps/powerpc/powerpc32/e6500/fpu/math_private.h	2014-08-29 10:31:30.216070587 -0700
+@@ -0,0 +1,9 @@
++#ifndef _E6500_MATH_PRIVATE_H_
++#define _E6500_MATH_PRIVATE_H_ 1
++/* E6500 core FPU does not implement
++   fsqrt */
++
++#define __CPU_HAS_FSQRT 0
++#include_next <math_private.h>
++
++#endif /* _E6500_MATH_PRIVATE_H_ */
+
diff --git a/recipes-core/glibc/glibc-fsl/0005.glibc.fix_prof.patch b/recipes-core/glibc/glibc-fsl/0005.glibc.fix_prof.patch
new file mode 100755
index 0000000..43ba12b
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0005.glibc.fix_prof.patch
@@ -0,0 +1,47 @@
+# Problem Statement:
+  Modify Glibc so that gnu profiling is works with Glibc
+# Reported by:
+  James Yang 
+# Owned by:
+  Srinivas
+# Action:
+  * Modify Glibc such that it can be built with profiling and gprof data is generated correctly for Glibc functions
+  * Added profiling fixes provided in 'powerpc-profiling-fix.diff' file to the latest sources and checked flat-profiling
+    data generated for Glibc functions.
+
+diff -ruN libc-orig/elf/dl-runtime.c libc/elf/dl-runtime.c
+--- libc-orig/elf/dl-runtime.c	2014-06-11 02:51:20.000000000 -0500
++++ libc/elf/dl-runtime.c	2014-07-25 00:36:20.743371998 -0500
+@@ -148,7 +148,6 @@
+   return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
+ }
+ 
+-#ifndef PROF
+ DL_FIXUP_VALUE_TYPE
+ __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+ _dl_profile_fixup (
+@@ -433,7 +432,6 @@
+   return value;
+ }
+ 
+-#endif /* PROF */
+ 
+ 
+ #include <stdio.h>
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/dl-trampoline.S libc/sysdeps/powerpc/powerpc32/dl-trampoline.S
+--- libc-orig/sysdeps/powerpc/powerpc32/dl-trampoline.S	2014-06-11 02:44:56.000000000 -0500
++++ libc/sysdeps/powerpc/powerpc32/dl-trampoline.S	2014-07-25 00:36:20.942372001 -0500
+@@ -70,7 +70,6 @@
+ 	cfi_endproc
+ 	.size	 _dl_runtime_resolve,.-_dl_runtime_resolve
+ 
+-#ifndef PROF
+ 	.align 2
+ 	.globl _dl_prof_resolve
+ 	.type _dl_prof_resolve, at function
+@@ -186,4 +185,4 @@
+ 	bctr
+ 	cfi_endproc
+ 	.size	 _dl_prof_resolve,.-_dl_prof_resolve
+-#endif
++
diff --git a/recipes-core/glibc/glibc-fsl/0006.glibc.fsl-crosszic.patch b/recipes-core/glibc/glibc-fsl/0006.glibc.fsl-crosszic.patch
new file mode 100755
index 0000000..5077771
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0006.glibc.fsl-crosszic.patch
@@ -0,0 +1,76 @@
+# Problem Statement:
+  Install timezone data while building glibc v2.20.
+
+# Owned by:
+  Rohit
+
+# Actions:
+  * Created a patch which updates the timezone/Makefile to build cross-zic.
+  * Updated build.sh script to build & install tzdata after glibc build is
+    complete.
+
+diff -Naur glibc-2.20/timezone/Makefile glibc-2.20-tzdata/timezone/Makefile
+--- glibc-2.20/timezone/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-tzdata/timezone/Makefile	2015-02-18 08:02:49.041739203 -0600
+@@ -25,6 +25,9 @@
+ extra-objs := scheck.o ialloc.o
+ 
+ others	:= zdump zic
++ifneq ($(cross-compiling),no)
++others	+= cross-zic
++endif
+ tests	:= test-tz tst-timezone
+ 
+ # pacificnew doesn't compile; if it is to be used, it should be included in
+@@ -53,10 +56,21 @@
+ 
+ include ../Rules
+ 
++zic-objs = zic.o ialloc.o scheck.o
++
++$(addprefix $(objpfx)cross-,$(zic-objs)): $(objpfx)cross-%.o: %.c
++	$(BUILD_CC) $< -c $(OUTPUT_OPTION) $(CFLAGS-$*.c) $(CPPFLAGS-$*) \
++		-DREPORT_BUGS_TO='"$(REPORT_BUGS_TO)"' \
++		-DPKGVERSION='"$(PKGVERSION)"' \
++		$(compile-mkdep-flags) -iquote $(objpfx)
++
++$(objpfx)cross-zic: $(addprefix $(objpfx)cross-,$(zic-objs))
++	$(BUILD_CC) $(addprefix $(objpfx)cross-,$(zic-objs)) -o $@
+ 
+ $(objpfx)zic: $(objpfx)scheck.o $(objpfx)ialloc.o
+ 
+ $(objpfx)zic.o $(objpfx)zdump.o: $(objpfx)version.h
++$(objpfx)cross-zic.o $(objpfx)cross-zdump.o: $(objpfx)version.h
+ 
+ $(objpfx)version.h: $(common-objpfx)config.make
+ 	echo 'static char const TZVERSION[]="$(version)";' \
+@@ -77,10 +91,17 @@
+ # We have to make sure the data for testing the tz functions is available.
+ # Don't add leapseconds here since test-tz made checks that work only without
+ # leapseconds.
++ifeq (no,$(cross-compiling))
+ define build-testdata
+ $(built-program-cmd) -d $(testdata) -y ./yearistype $<; \
+ $(evaluate-test)
+ endef
++else
++define build-testdata
++LANGUAGE=C LC_ALL=C \
++  $(objpfx)cross-zic -d $(testdata) -y ./yearistype $<
++endef
++endif
+ 
+ $(objpfx)test-tz.out: $(addprefix $(testdata)/, America/New_York Etc/UTC UTC)
+ $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \
+@@ -93,7 +114,11 @@
+ tst-timezone-ENV = TZDIR=$(testdata)
+ 
+ # Note this must come second in the deps list for $(built-program-cmd) to work.
++ifeq (no,$(cross-compiling))
+ zic-deps = $(objpfx)zic $(leapseconds) yearistype
++else
++zic-deps = $(objpfx)cross-zic $(objpfx)zic $(leapseconds) yearistype
++endif
+ 
+ $(testdata)/America/New_York: northamerica $(zic-deps)
+ 	$(build-testdata)
diff --git a/recipes-core/glibc/glibc-fsl/0007.glibc.fix_MTWX51911-enable_8xx.patch b/recipes-core/glibc/glibc-fsl/0007.glibc.fix_MTWX51911-enable_8xx.patch
new file mode 100755
index 0000000..f4159a3
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0007.glibc.fix_MTWX51911-enable_8xx.patch
@@ -0,0 +1,530 @@
+# Problem Statement:
+  ENGR00215432:
+  The purpose of this patch is to disable the use of dcbz in the 32-bit memset.
+  However, this does not fix the root problem because any program
+  -- not just one using eglibc's memset -- can contain dcbz instruction,
+  so it is an incomplete fix anyway.
+
+  There is support in the Linux kernel as of 2.6.33 to emulate the correct
+  behavior (though it seems nobody really knows how well the workaround works),
+  so if the program that uses libc is running on this or a later kernel it does
+  not need to check for an 8xx.
+
+  Therefore one solution is to require kernel 2.6.33 or later.
+
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/dl-sysdep.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/dl-sysdep.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/dl-sysdep.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/dl-sysdep.c	2015-02-24 13:57:36.709739425 -0600
+@@ -0,0 +1,35 @@
++/* Operating system support for run-time dynamic linker.  Linux/PPC version.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <config.h>
++#include <ldsodefs.h>
++
++int __cache_line_size attribute_hidden;
++
++/* Scan the Aux Vector for the "Data Cache Block Size" entry.  If found
++   verify that the static extern __cache_line_size is defined by checking
++   for not NULL.  If it is defined then assign the cache block size
++   value to __cache_line_size. This is used by memset to
++   optimize setting to zero.  We have to detect 8xx processors, which
++   have buggy dcbz implementations that cannot report page faults
++   correctly. */
++#define DL_PLATFORM_AUXV						      \
++      case AT_DCACHEBSIZE:						      \
++	break;
++
++#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/libc-start.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/libc-start.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/libc-start.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/801/libc-start.c	2015-02-24 13:53:49.721737701 -0600
+@@ -0,0 +1,86 @@
++/* Copyright (C) 1998-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <ldsodefs.h>
++#include <sysdep.h>
++
++
++int __cache_line_size attribute_hidden;
++/* The main work is done in the generic function.  */
++#define LIBC_START_MAIN generic_start_main
++#define LIBC_START_DISABLE_INLINE
++#define LIBC_START_MAIN_AUXVEC_ARG
++#define MAIN_AUXVEC_ARG
++#define INIT_MAIN_ARGS
++#include <csu/libc-start.c>
++
++struct startup_info
++  {
++    void *sda_base;
++    int (*main) (int, char **, char **, void *);
++    int (*init) (int, char **, char **, void *);
++    void (*fini) (void);
++  };
++
++int
++__libc_start_main (int argc, char **argv,
++		   char **ev,
++		   ElfW (auxv_t) * auxvec,
++		   void (*rtld_fini) (void),
++		   struct startup_info *stinfo,
++		   char **stack_on_entry)
++{
++  /* the PPC SVR4 ABI says that the top thing on the stack will
++     be a NULL pointer, so if not we assume that we're being called
++     as a statically-linked program by Linux...  */
++  if (*stack_on_entry != NULL)
++    {
++      char **temp;
++      /* ...in which case, we have argc as the top thing on the
++         stack, followed by argv (NULL-terminated), envp (likewise),
++         and the auxiliary vector.  */
++      /* 32/64-bit agnostic load from stack */
++      argc = *(long int *) stack_on_entry;
++      argv = stack_on_entry + 1;
++      ev = argv + argc + 1;
++#ifdef HAVE_AUX_VECTOR
++      temp = ev;
++      while (*temp != NULL)
++	++temp;
++      auxvec = (ElfW (auxv_t) *)++ temp;
++#endif
++      rtld_fini = NULL;
++    }
++
++  /* Initialize the __cache_line_size variable from the aux vector.
++     This is used by memset to optimize setting to zero.  We have to
++     detect 8xx processors, which have buggy dcbz implementations that
++     cannot report page faults correctly.  That requires reading SPR,
++     which is a privileged operation.*/
++  for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
++    switch (av->a_type)
++      {
++      case AT_DCACHEBSIZE:
++	break;
++      }
++
++  return generic_start_main (stinfo->main, argc, argv, auxvec,
++			     stinfo->init, stinfo->fini, rtld_fini,
++			     stack_on_entry);
++}
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/dl-sysdep.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/dl-sysdep.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/dl-sysdep.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/dl-sysdep.c	2015-02-24 13:58:00.043738993 -0600
+@@ -0,0 +1,35 @@
++/* Operating system support for run-time dynamic linker.  Linux/PPC version.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <config.h>
++#include <ldsodefs.h>
++
++int __cache_line_size attribute_hidden;
++
++/* Scan the Aux Vector for the "Data Cache Block Size" entry.  If found
++   verify that the static extern __cache_line_size is defined by checking
++   for not NULL.  If it is defined then assign the cache block size
++   value to __cache_line_size. This is used by memset to
++   optimize setting to zero.  We have to detect 8xx processors, which
++   have buggy dcbz implementations that cannot report page faults
++   correctly. */
++#define DL_PLATFORM_AUXV						      \
++      case AT_DCACHEBSIZE:						      \
++	break;
++
++#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/libc-start.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/libc-start.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/libc-start.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/821/libc-start.c	2015-02-24 13:58:00.043738993 -0600
+@@ -0,0 +1,86 @@
++/* Copyright (C) 1998-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <ldsodefs.h>
++#include <sysdep.h>
++
++
++int __cache_line_size attribute_hidden;
++/* The main work is done in the generic function.  */
++#define LIBC_START_MAIN generic_start_main
++#define LIBC_START_DISABLE_INLINE
++#define LIBC_START_MAIN_AUXVEC_ARG
++#define MAIN_AUXVEC_ARG
++#define INIT_MAIN_ARGS
++#include <csu/libc-start.c>
++
++struct startup_info
++  {
++    void *sda_base;
++    int (*main) (int, char **, char **, void *);
++    int (*init) (int, char **, char **, void *);
++    void (*fini) (void);
++  };
++
++int
++__libc_start_main (int argc, char **argv,
++		   char **ev,
++		   ElfW (auxv_t) * auxvec,
++		   void (*rtld_fini) (void),
++		   struct startup_info *stinfo,
++		   char **stack_on_entry)
++{
++  /* the PPC SVR4 ABI says that the top thing on the stack will
++     be a NULL pointer, so if not we assume that we're being called
++     as a statically-linked program by Linux...  */
++  if (*stack_on_entry != NULL)
++    {
++      char **temp;
++      /* ...in which case, we have argc as the top thing on the
++         stack, followed by argv (NULL-terminated), envp (likewise),
++         and the auxiliary vector.  */
++      /* 32/64-bit agnostic load from stack */
++      argc = *(long int *) stack_on_entry;
++      argv = stack_on_entry + 1;
++      ev = argv + argc + 1;
++#ifdef HAVE_AUX_VECTOR
++      temp = ev;
++      while (*temp != NULL)
++	++temp;
++      auxvec = (ElfW (auxv_t) *)++ temp;
++#endif
++      rtld_fini = NULL;
++    }
++
++  /* Initialize the __cache_line_size variable from the aux vector.
++     This is used by memset to optimize setting to zero.  We have to
++     detect 8xx processors, which have buggy dcbz implementations that
++     cannot report page faults correctly.  That requires reading SPR,
++     which is a privileged operation.*/
++  for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
++    switch (av->a_type)
++      {
++      case AT_DCACHEBSIZE:
++	break;
++      }
++
++  return generic_start_main (stinfo->main, argc, argv, auxvec,
++			     stinfo->init, stinfo->fini, rtld_fini,
++			     stack_on_entry);
++}
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/dl-sysdep.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/dl-sysdep.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/dl-sysdep.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/dl-sysdep.c	2015-02-24 13:58:03.323739026 -0600
+@@ -0,0 +1,35 @@
++/* Operating system support for run-time dynamic linker.  Linux/PPC version.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <config.h>
++#include <ldsodefs.h>
++
++int __cache_line_size attribute_hidden;
++
++/* Scan the Aux Vector for the "Data Cache Block Size" entry.  If found
++   verify that the static extern __cache_line_size is defined by checking
++   for not NULL.  If it is defined then assign the cache block size
++   value to __cache_line_size. This is used by memset to
++   optimize setting to zero.  We have to detect 8xx processors, which
++   have buggy dcbz implementations that cannot report page faults
++   correctly. */
++#define DL_PLATFORM_AUXV						      \
++      case AT_DCACHEBSIZE:						      \
++	break;
++
++#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/libc-start.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/libc-start.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/libc-start.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/823/libc-start.c	2015-02-24 13:58:03.323739026 -0600
+@@ -0,0 +1,86 @@
++/* Copyright (C) 1998-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <ldsodefs.h>
++#include <sysdep.h>
++
++
++int __cache_line_size attribute_hidden;
++/* The main work is done in the generic function.  */
++#define LIBC_START_MAIN generic_start_main
++#define LIBC_START_DISABLE_INLINE
++#define LIBC_START_MAIN_AUXVEC_ARG
++#define MAIN_AUXVEC_ARG
++#define INIT_MAIN_ARGS
++#include <csu/libc-start.c>
++
++struct startup_info
++  {
++    void *sda_base;
++    int (*main) (int, char **, char **, void *);
++    int (*init) (int, char **, char **, void *);
++    void (*fini) (void);
++  };
++
++int
++__libc_start_main (int argc, char **argv,
++		   char **ev,
++		   ElfW (auxv_t) * auxvec,
++		   void (*rtld_fini) (void),
++		   struct startup_info *stinfo,
++		   char **stack_on_entry)
++{
++  /* the PPC SVR4 ABI says that the top thing on the stack will
++     be a NULL pointer, so if not we assume that we're being called
++     as a statically-linked program by Linux...  */
++  if (*stack_on_entry != NULL)
++    {
++      char **temp;
++      /* ...in which case, we have argc as the top thing on the
++         stack, followed by argv (NULL-terminated), envp (likewise),
++         and the auxiliary vector.  */
++      /* 32/64-bit agnostic load from stack */
++      argc = *(long int *) stack_on_entry;
++      argv = stack_on_entry + 1;
++      ev = argv + argc + 1;
++#ifdef HAVE_AUX_VECTOR
++      temp = ev;
++      while (*temp != NULL)
++	++temp;
++      auxvec = (ElfW (auxv_t) *)++ temp;
++#endif
++      rtld_fini = NULL;
++    }
++
++  /* Initialize the __cache_line_size variable from the aux vector.
++     This is used by memset to optimize setting to zero.  We have to
++     detect 8xx processors, which have buggy dcbz implementations that
++     cannot report page faults correctly.  That requires reading SPR,
++     which is a privileged operation.*/
++  for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
++    switch (av->a_type)
++      {
++      case AT_DCACHEBSIZE:
++	break;
++      }
++
++  return generic_start_main (stinfo->main, argc, argv, auxvec,
++			     stinfo->init, stinfo->fini, rtld_fini,
++			     stack_on_entry);
++}
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/dl-sysdep.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/dl-sysdep.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/dl-sysdep.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/dl-sysdep.c	2015-02-24 13:58:41.664736975 -0600
+@@ -0,0 +1,35 @@
++/* Operating system support for run-time dynamic linker.  Linux/PPC version.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <config.h>
++#include <ldsodefs.h>
++
++int __cache_line_size attribute_hidden;
++
++/* Scan the Aux Vector for the "Data Cache Block Size" entry.  If found
++   verify that the static extern __cache_line_size is defined by checking
++   for not NULL.  If it is defined then assign the cache block size
++   value to __cache_line_size. This is used by memset to
++   optimize setting to zero.  We have to detect 8xx processors, which
++   have buggy dcbz implementations that cannot report page faults
++   correctly. */
++#define DL_PLATFORM_AUXV						      \
++      case AT_DCACHEBSIZE:						      \
++	break;
++
++#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/libc-start.c glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/libc-start.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/libc-start.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/powerpc/powerpc32/860/libc-start.c	2015-02-24 13:58:41.664736975 -0600
+@@ -0,0 +1,86 @@
++/* Copyright (C) 1998-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <ldsodefs.h>
++#include <sysdep.h>
++
++
++int __cache_line_size attribute_hidden;
++/* The main work is done in the generic function.  */
++#define LIBC_START_MAIN generic_start_main
++#define LIBC_START_DISABLE_INLINE
++#define LIBC_START_MAIN_AUXVEC_ARG
++#define MAIN_AUXVEC_ARG
++#define INIT_MAIN_ARGS
++#include <csu/libc-start.c>
++
++struct startup_info
++  {
++    void *sda_base;
++    int (*main) (int, char **, char **, void *);
++    int (*init) (int, char **, char **, void *);
++    void (*fini) (void);
++  };
++
++int
++__libc_start_main (int argc, char **argv,
++		   char **ev,
++		   ElfW (auxv_t) * auxvec,
++		   void (*rtld_fini) (void),
++		   struct startup_info *stinfo,
++		   char **stack_on_entry)
++{
++  /* the PPC SVR4 ABI says that the top thing on the stack will
++     be a NULL pointer, so if not we assume that we're being called
++     as a statically-linked program by Linux...  */
++  if (*stack_on_entry != NULL)
++    {
++      char **temp;
++      /* ...in which case, we have argc as the top thing on the
++         stack, followed by argv (NULL-terminated), envp (likewise),
++         and the auxiliary vector.  */
++      /* 32/64-bit agnostic load from stack */
++      argc = *(long int *) stack_on_entry;
++      argv = stack_on_entry + 1;
++      ev = argv + argc + 1;
++#ifdef HAVE_AUX_VECTOR
++      temp = ev;
++      while (*temp != NULL)
++	++temp;
++      auxvec = (ElfW (auxv_t) *)++ temp;
++#endif
++      rtld_fini = NULL;
++    }
++
++  /* Initialize the __cache_line_size variable from the aux vector.
++     This is used by memset to optimize setting to zero.  We have to
++     detect 8xx processors, which have buggy dcbz implementations that
++     cannot report page faults correctly.  That requires reading SPR,
++     which is a privileged operation.*/
++  for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
++    switch (av->a_type)
++      {
++      case AT_DCACHEBSIZE:
++	break;
++      }
++
++  return generic_start_main (stinfo->main, argc, argv, auxvec,
++			     stinfo->init, stinfo->fini, rtld_fini,
++			     stack_on_entry);
++}
diff --git a/recipes-core/glibc/glibc-fsl/0008.glibc.e500v2_lib_support.patch b/recipes-core/glibc/glibc-fsl/0008.glibc.e500v2_lib_support.patch
new file mode 100644
index 0000000..b2f04be
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0008.glibc.e500v2_lib_support.patch
@@ -0,0 +1,2542 @@
+# Problem Statement:
+  Optimized library functions for e500v2
+
+# Owned By:
+  Edmar Wienskoski
+
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/memcpy.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memcpy.S
+--- libc/sysdeps/powerpc/powerpc32/e500/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memcpy.S	2014-08-01 06:43:32.864371998 -0500
+@@ -0,0 +1,408 @@
++/*------------------------------------------------------------------
++ * memcpy.S
++ *
++ * Standard memcpy function optimized for e500 using SPE.  This
++ * function does not handle overlap, as per spec.  This file is
++ * identical to the memmove.S file.  To get a memmove out of it,
++ * specify -D__MEMMOVE__ to the compiler
++ *
++ *------------------------------------------------------------------
++ *      Copyright (c) 2005 Freescale Semiconductor, Inc
++ *      ALL RIGHTS RESERVED
++ *
++ *	Redistribution and use in source and binary forms, with or
++ *	without modification, are permitted provided that the following
++ *	conditions are met:
++ *	
++ *	
++ *	Redistributions of source code must retain the above copyright
++ *	notice, this list of conditions and the following disclaimer.
++ *	
++ *	Redistributions in binary form must reproduce the above copyright
++ *	notice, this list of conditions and the following disclaimer in
++ *	the documentation and/or other materials provided with the
++ *	distribution.
++ *	
++ *	Neither the name of Freescale Semiconductor, Inc nor the names of
++ *	its contributors may be used to endorse or promote products derived
++ *	from this software without specific prior written permission.
++ *	
++ *	
++ *	
++ *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
++ *	CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
++ *	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ *	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ *	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
++ *	BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ *	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ *	TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ *	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ *	ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
++ *	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ *	OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ *	POSSIBILITY OF SUCH DAMAGE.
++ *------------------------------------------------------------------
++ */
++
++#include <sysdep.h>
++
++/*------------------------------------------------------------------
++ * int memcpy(const unsigned char* dst,
++ *            const unsigned char* src,
++ *            long count);
++ * void * memmove(const unsigned char* dst,
++ *                const unsigned char* src,
++ *                long count);
++ * Returns:
++ *  dst
++ *------------------------------------------------------------------
++ */
++
++#ifdef __MEMMOVE__
++	.file	"memmove.S"
++#else /* memcpy */
++	.file	"memcpy.S"
++#endif /* __MEMMOVE */
++	.section	".text"
++	.align 4
++#ifdef __MEMMOVE__
++	#define FUNCTION memmove
++#else /* memcpy */
++	#define FUNCTION memcpy
++#endif /* __MEMMOVE__ */
++EALIGN (FUNCTION, 5, 1)
++
++/* Prologs are different for memcpy and memmove.  memmove needs
++ * to handle the case where the buffers overlap correctly.
++ * memcpy does not.  In order to make the implementation simple,
++ * memmove ONLY copies backwards if it needs to, and only for as 
++ * much as is necessary to remove the overlap.
++ */
++#ifdef __MEMMOVE__
++        or r0,r4,r3
++        subf r9,r4,r3
++        mr r6,r3
++        subf r11,r9,r5
++        andi. r0,r0,7
++        rlwinm r9,r9,0,0,0
++        xor r0,r4,r6
++        bne L(memcpy_unaligned)
++
++        or. r11,r9,r11
++        bgt L(Handle_Overlap)
++
++/* memcpy is simpler */
++#else /* memcpy */
++
++        or r0,r4,r3
++        mr r6,r3
++        andi. r0,r0,7
++        xor r0,r4,r6
++        bne L(memcpy_unaligned)
++
++#endif /* __MEMMOVE__ */
++
++L(aligned_copy):
++        srwi. r12,r5,5
++        mtcrf 0x2,r5
++        mtcrf 0x1,r5
++        bne L(big_loop)
++
++L(try_two_doubles):
++        bf 27,L(try_one_double)
++        evldd r7,0(r4)
++        evstdd r7,0(r6)
++        evldd r8,8(r4)
++        addi r4,r4,16
++        evstdd r8,8(r6)
++        addi r6,r6,16
++
++L(try_one_double):
++        bf 28,L(try_word)
++        evldd r7,0(r4)
++        addi r4,r4,8
++        evstdd r7,0(r6)
++        addi r6,r6,8
++
++L(try_word):
++        bf 29,L(try_half)
++        lwz r7,0(r4)
++        addi r4,r4,4
++        stw r7,0(r6)
++        addi r6,r6,4
++
++L(try_half):
++        bf 30,L(try_byte)
++        lhz r7,0(r4)
++        addi r4,r4,2
++        sth r7,0(r6)
++        addi r6,r6,2
++
++L(try_byte):
++        bf 31,L(finish)
++        lbz r7,0(r4)
++        stb r7,0(r6)
++
++L(finish):
++        blr
++
++L(big_loop):
++        evldd r7,0(r4)
++        addic. r12,r12,-1
++        evldd r8,8(r4)
++        evldd r9,16(r4)
++        evldd r10,24(r4)
++        addi r4,r4,32
++        evstdd r7,0(r6)
++        evstdd r8,8(r6)
++        evstdd r9,16(r6)
++        evstdd r10,24(r6)
++        addi r6,r6,32
++        bne L(big_loop)
++
++        b L(try_two_doubles)
++
++L(align_dest_word):
++L(align_dest_double):
++        /* First make sure there are at least 8 bytes left to
++	 * copy.  Otherwise, realignment could go out of bounds
++	 */
++        cmpwi r5,8
++        neg r0,r6
++        blt L(small_copy)
++
++        andi. r7,r6,0x3
++        mtcrf 0x1,r0
++
++        bne L(more_alignment)
++
++/* Don't need to check if r6 needs another word to be aligned.
++ * We're here, therefore we must have only been off by a word.
++ * So we shorten the path a bit by taking 2 branches out from the
++ * more common path (ie things tend to be at least word-aligned)
++ */
++L(align_one_word):
++        lwz r7,0(r4)
++        addi r4,r4,4
++        stw r7,0(r6)
++        addi r6,r6,4
++        addi r5,r5,-4
++        bne cr6,L(unaligned_double_copy)
++        b L(aligned_copy)
++
++L(more_alignment):
++        bf 31, L(try_align_word)
++        lbz r7,0(r4)
++        addi r4,r4,1
++        stb r7,0(r6)
++        addi r6,r6,1
++        addi r5,r5,-1
++
++L(try_align_word):
++        bf 30, L(try_align_double)
++        lhz r7,0(r4)
++        addi r4,r4,2
++        sth r7,0(r6)
++        addi r6,r6,2
++        addi r5,r5,-2
++
++L(try_align_double):
++        bt 29, L(align_one_word)
++        beq cr6,L(aligned_copy)
++
++/* For each double word copied, we load the double words with
++ * each half from r4 (which starts at 0x*4 or 0x*c).  Then we
++ * use evmergelohi to take the halves and rejoin them.  Notice
++ * that any double load will necessarily be 4 bytes ahead.
++ * Invariant: at the start of any block (except the first) which
++ * loads a doubleword, r10 will hold the first half of the
++ * first doubleword
++ */
++L(unaligned_double_copy):
++        /* align r4 to a doubleword boundary */
++        rlwinm r4,r4,0,0,28
++        srwi. r12, r5,5
++
++        /* grab the first doubleword */
++        evldd r10,0(r4)
++
++	/* Set the CR to indicate how many bytes remain to be
++	 * copied after the big loop is done */
++        mtcrf 0x2,r5
++        mtcrf 0x1,r5
++        bne L(unaligned_big_loop)
++
++/* There are less than 4 double words left, so we take care of
++ * them
++ */
++L(try_unaligned_2_doubles):
++        bf 27, L(try_unaligned_double)
++        evldd r9,8(r4)
++        evmergelohi r10,r10,r9
++        evstdd r10,0(r6)
++        evldd r10,16(r4)
++        addi r4,r4,16
++        evmergelohi r9,r9,r10
++        evstdd r9,8(r6)
++        addi r6,r6,16
++
++L(try_unaligned_double):
++        bf 28, L(try_unaligned_word)
++        evldd r9,8(r4)
++        addi r4,r4,8
++        evmergelohi r10,r10,r9
++        evstdd r10,0(r6)
++        addi r6,r6,8
++        evmr r10,r9
++
++L(try_unaligned_word):
++        addi r4,r4,4
++        bf 29, L(try_unaligned_half)
++        stw r10,0(r6)
++        addi r4,r4,4
++        addi r6,r6,4
++
++L(try_unaligned_half):
++        bf 30, L(try_unaligned_byte)
++        lhz r10,0(r4)
++        addi r4,r4,2
++        sth r10,0(r6)
++        addi r6,r6,2
++
++L(try_unaligned_byte):
++        bf 31, L(finish)
++        lbz r10,0(r4)
++        stb r10,0(r6)
++        blr
++
++L(unaligned_big_loop):
++        evldd r7,8(r4)
++        evldd r8,16(r4)
++        addic. r12,r12,-1
++        evldd r9,24(r4)
++        addi r4,r4,32
++        evmergelohi r10,r10,r7
++        evstdd r10,0(r6)
++        evmergelohi r7,r7,r8
++        evldd r10,0(r4)
++        evmergelohi r8,r8,r9
++        evstdd r7,8(r6)
++        evmergelohi r9,r9,r10
++        evstdd r8,16(r6)
++        evstdd r9,24(r6)
++        addi r6,r6,32
++        bne L(unaligned_big_loop)
++        b L(try_unaligned_2_doubles)
++
++
++L(small_copy):
++        mtcrf 0x1,r5
++        bf 29,L(try_small_half)
++        lbz r7,0(r4)
++        lbz r8,1(r4)
++        lbz r9,2(r4)
++        lbz r10,3(r4)
++        addi r4,r4,4
++        stb r7,0(r6)
++        stb r8,1(r6)
++        stb r9,2(r6)
++        stb r10,3(r6)
++        addi r6,r6,4
++
++L(try_small_half):
++        bf 30,L(try_small_byte)
++        lbz r7,0(r4)
++        lbz r8,1(r4)
++        addi r4,r4,2
++        stb r7,0(r6)
++        stb r8,1(r6)
++        addi r6,r6,2
++
++L(try_small_byte):
++        bf 31, L(finish)
++        lbz r7,0(r4)
++        stb r7,0(r6)
++        blr
++
++L(memcpy_unaligned):
++#ifdef __MEMMOVE__
++
++        or. r11,r9,r11
++        bgt L(Handle_Overlap)
++
++L(choose_alignment):
++#endif /* __MEMMOVE */
++        /* If both pointers can be double-aligned, align r6,
++	 * setting eq6 to indicate "aligned
++	 */
++        rlwinm. r0,r0,0,29,31
++        cmpw cr6,r31,r31 /* set eq6 */
++
++        /* Look at r6 to see if we're aligned already (but not
++	 * both aligned, which is why we're here)
++	 */
++        rlwinm r7,r6,0,29,31
++        beq L(align_dest_double)
++
++        /* Compare to find out if r6 is already doublealigned
++	 * If both pointers can be word-aligned, align r6,
++	 * clearing eq6 to indicate unaligned
++	 */
++        rlwinm. r0,r0,0,30,31
++        cmpwi cr1,r7,0
++
++        /* Only skip to unaligned_double_copy if r6 is aligned,
++	 * AND r0 indicates word-alignment
++	 */
++        crand 6,6,2
++
++        crxor 26,26,26 /* clear eq6 */
++        beq cr1,L(unaligned_double_copy)
++        beq L(align_dest_word)
++
++        /* Before we hop into bytewise copying, make sure that
++	 * there are bytes to copy (don't want to loop 4 billion+
++	 * times!
++	 */
++        cmpwi r5,0
++        beqlr
++
++        /* Well, alignment is just icky, copy bytewise */
++        mtctr r5
++L(byte_copy):
++        lbz r7,0(r4)
++        addi r4,r4,1
++        stb r7,0(r6)
++        addi r6,r6,1
++        bdnz L(byte_copy)
++        blr
++
++#ifdef __MEMMOVE__
++
++
++        /* If the regions being copied overlap, and r4 is lower
++	 * in memory than r6, then we need to copy backward
++	 * until the overlap is gone, then just do the normal
++	 * copy
++	 */
++L(Handle_Overlap):
++        /* r11 has the size of the overlap */
++        add r8,r6,r5
++        add r10,r4,r5
++
++        mtctr r11
++
++L(bkw_fix_loop):
++        lbzu r9,-1(r10)
++        stbu r9,-1(r8)
++        bdnz L(bkw_fix_loop)
++
++        /* We're done, correct r5, and return */
++        subf r5,r11,r5
++
++        b FUNCTION at local
++#endif /* __MEMMOVE */
++
++END (FUNCTION)
++libc_hidden_builtin_def (FUNCTION)
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/memmove.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memmove.S
+--- libc/sysdeps/powerpc/powerpc32/e500/memmove.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memmove.S	2014-08-01 06:42:29.703372001 -0500
+@@ -0,0 +1,2 @@
++#define __MEMMOVE__ 1
++#include <memcpy.S>
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/memset.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memset.S
+--- libc/sysdeps/powerpc/powerpc32/e500/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/memset.S	2014-08-01 06:44:25.470371998 -0500
+@@ -0,0 +1,393 @@
++/*------------------------------------------------------------------
++ * memset.S
++ *
++ * Standard memset function optimized for e500 using SPE
++ *
++ * Copyright (c) 2005 Freescale Semiconductor, Inc
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *     * Redistributions of source code must retain the above copyright
++ *       notice, this list of conditions and the following disclaimer.
++ *     * Redistributions in binary form must reproduce the above copyright
++ *       notice, this list of conditions and the following disclaimer in the
++ *       documentation and/or other materials provided with the distribution.
++ *     * Neither the name of Freescale Semiconductor nor the
++ *       names of its contributors may be used to endorse or promote products
++ *       derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *------------------------------------------------------------------
++ */
++
++#include <sysdep.h>
++
++/*------------------------------------------------------------------
++ * void * memset(void *origdest, int value, size_t len)
++ *
++ * returns dest
++ *
++ *------------------------------------------------------------------
++ */
++
++
++	.file	"memset.S"
++	.section	".text"
++EALIGN (memset, 5, 0)
++        /* Find out whether the destination buffer is already
++	 * aligned, and propagate the byte through the entire
++	 * word.
++	 */
++        andi. r0,r3,0x7
++        rlwimi r4,r4,8,16,23
++
++        /* Check if value (r4) is zero (most common case).  If it
++	 * is, we jump to bzero
++	 */
++        cmpwi cr1,r4,0
++
++        rlwimi r4,r4,16,0,15
++
++        /* If r4 is 0, then we will jump to bzero.  If so,
++	 * we want the count to be in the right place for bzero (r4)
++	 */
++        mr r11,r4
++        mr r4,r5
++
++        beq cr1, L(bzero_entry)
++
++        mr r6,r3
++        bne L(align_dest_double)
++
++L(aligned_set):
++        /* Get the number of doubles/4, since we write 4 at a
++	 * time in the big loop.
++	 */
++        srwi. r12,r5,5
++
++        /* Set the condition register so that each bit represents
++	 * some number of bytes to set.
++	 */
++        mtcrf 0x2,r5
++        mtcrf 0x1,r5
++
++        /* Copy r11 up into the hi word, so we can set 8 bytes
++	 * at a time.
++	 */
++        evmergelo r11,r11,r11
++
++        /* If there aren't at least 32 bytes to set, take care of
++	 * the last 0-31
++	 */
++        bne L(big_loop)
++
++/* We only store to memory that we are changing.  No extra loads
++ * or stores are done.
++ */
++L(try_two_doubles):
++        bf 27,L(try_one_double)
++        evstdd r11,0(r6)
++        evstdd r11,8(r6)
++        addi r6,r6,16
++
++L(try_one_double):
++        bf 28,L(try_word)
++        evstdd r11,0(r6)
++        addi r6,r6,8
++        nop
++
++L(try_word):
++        bf 29,L(try_half)
++        stw r11,0(r6)
++        addi r6,r6,4
++        nop
++
++L(try_half):
++        bf 30,L(try_byte)
++        sth r11,0(r6)
++        addi r6,r6,2
++        nop
++
++L(try_byte):
++        bf 31,L(finish)
++        stb r11,0(r6)
++
++L(finish):
++        blr
++
++/* Write 32 bytes at a time */
++L(big_loop):
++        /* adjust r6 back by 8.  We need to do this so we can
++	 * hoist the pointer update above the last store in the
++	 * loop.  This means that a store can be done every cycle
++	 */
++        addi r6,r6,-8
++L(loop):
++        evstdd r11,8(r6)
++        addic. r12,r12,-1
++        evstdd r11,16(r6)
++        evstdd r11,24(r6)
++        addi r6,r6,32
++        evstdd r11,0(r6)
++        bne L(loop)
++
++        /* Readjust r6 */
++        addi r6,r6,8
++        /* Jump back to take care of the last 0-31 bytes */
++        b L(try_two_doubles)
++
++L(align_dest_double):
++        /* First make sure there are at least 8 bytes left to
++	 * set.  Otherwise, realignment could go out of bounds
++	 */
++        cmpwi cr1, r5,8
++
++        /* Find out how many bytes we need to set in order to
++	 * align r6
++	 */
++        neg r0,r6
++        andi. r7,r6,0x3
++
++        blt cr1, L(small_set)
++
++        /* Set the condition register so that each bit in cr7
++	 * represents a number of bytes to write to align r6
++	 */
++        mtcrf 0x1,r0
++
++        /* The most common case is that r6 is at least
++	 * word-aligned, so that is the fall-through case.
++	 * Otherwise, we skip ahead to align a bit more.
++	 */
++        bne L(more_alignment)
++L(align_one_word):
++        addi r5,r5,-4
++        stw r11,0(r6)
++        addi r6,r6,4
++        b L(aligned_set)
++
++L(more_alignment):
++        bf 31, L(try_align_word)
++        addi r5,r5,-1
++        stb r11,0(r6)
++        addi r6,r6,1
++
++L(try_align_word):
++        bf 30, L(try_align_double)
++        addi r5,r5,-2
++        sth r11,0(r6)
++        addi r6,r6,2
++
++L(try_align_double):
++        bt 29, L(align_one_word)
++        b L(aligned_set)
++
++L(small_set):
++        mtcrf 0x1,r5
++        bf 29,L(try_small_half)
++        /* This may be better, but stw SHOULD do the same thing
++	 * as fast or faster.  It just has a chance of being
++	 * unaligned
++	 *	stb	r11,0(r6)
++	 *	stb	r11,1(r6)
++	 *	stb	r11,2(r6)
++	 *	stb	r11,3(r6)
++	 */
++
++        stw r11,0(r6)
++        addi r6,r6,4
++
++L(try_small_half):
++        bf 30,L(try_small_byte)
++
++        /* Storing half should take the same or less time than
++	 * two stb, so we do that
++	 */
++        sth r11,0(r6)
++        addi r6,r6,2
++
++L(try_small_byte):
++        bf 31, L(finish)
++        stb r11,0(r6)
++        blr
++
++END (memset)
++libc_hidden_builtin_def (memset)
++
++EALIGN (bzero, 5, 0)
++L(bzero_entry):
++        /* Check dest's alignment (within a cache-line) */
++        neg r8,r3
++
++        /* r12, here, is the number of 128 byte chunks to
++	 * zero out.
++	 */
++        srwi r12,r4,7
++
++        /* Find out the number of bytes needed to copy to align
++	 * dest to a cacheline boundary
++	 */
++        andi. r8, r8,0x1f
++        cmpwi cr1,r12,0
++
++        /* bzero can be called from memset, so we want it to
++	 * return the same value memset would.  This doesn't hurt
++	 * anything, so we keep the old value of r3, and copy it
++	 * into another register which we are free to change.
++	 */
++        mr r6,r3
++
++        /* Jump to align r6 if it isn't already aligned */
++        bne L(align_dest_32)
++
++        /* r6 is aligned to a cache-line, so we can zero
++	 * out using dcbz if the buffer is large enough
++	 */
++L(zero_aligned):
++        /* set the cr bits for the last 0-127 bytes remaining */
++        mtcrf 0x1,r4
++        mtcrf 0x2,r4
++
++        li r10,-32
++        li r9,32
++        beq cr1,L(try_two_lines)
++
++        li r11,64
++
++L(zero_loop):
++        dcbz 0,r6
++        addic. r12,r12,-1
++        dcbz r9,r6
++        dcbz r11,r6
++        addi r6,r6,128
++        dcbz r10,r6
++        bne L(zero_loop)
++
++L(try_two_lines):
++        /* Put 0 into r11 such that memset can handle the last
++	 * 0-31 bytes (yay, instruction savings!)
++	 */
++        evsplati r11,0
++
++        rlwinm. r0, r4,0,27,31
++
++        bf 25, L(try_one_line)
++        dcbz 0,r6
++        dcbz r9,r6
++        addi r6,r6,64
++
++L(try_one_line):
++        bf 26, L(try_two_doubles)
++        dcbz 0,r6
++        addi r6,r6,32
++
++        bne L(try_two_doubles)
++        /* there weren't any bytes left, so we return */
++        blr
++
++L(align_dest_32):
++        /* move r8 into the crfields so that we can align
++	 * easily
++	 */
++        mtcrf 0x1,r8
++        mtcrf 0x2,r8
++
++        /* update the counter */
++        subf. r4,r8,r4
++
++        /* if r4 is not great enough to align r6, then we
++	 * zero in small amounts
++	 */
++        blt L(zero_small)
++
++        /* zero out a register to store to memory */
++        evsplati r8,0
++
++        bf 31,L(zero_one_half)
++        stb r8,0(r6)
++        addi r6,r6,1
++        nop
++
++L(zero_one_half):
++        bf 30, L(zero_word)
++        sth r8,0(r6)
++        addi r6,r6,2
++        nop
++
++L(zero_word):
++        bf 29, L(zero_double)
++        stw r8,0(r6)
++        addi r6,r6,4
++        nop
++
++L(zero_double):
++        bf 28, L(zero_two)
++        evstdd r8,0(r6)
++        addi r6,r6,8
++        nop
++
++L(zero_two):
++        bf 27,L(zero_finish)
++        evstdd r8,0(r6)
++        evstdd r8,8(r6)
++        addi r6,r6,16
++
++L(zero_finish):
++        srwi. r12,r4,7
++        li r9,32
++        li r11,64
++        li r10,-32
++
++        mtcrf 0x1,r4
++        mtcrf 0x2,r4
++        bne L(zero_loop)
++        b L(try_two_lines)
++
++L(zero_small):
++        add r4,r8,r4
++        mtcrf 0x1,r4
++        mtcrf 0x2,r4
++
++        evsplati r8,0
++
++        bf 27,L(zero_one_small)
++        stw r8,0(r6)
++        stw r8,4(r6)
++        stw r8,8(r6)
++        stw r8,12(r6)
++        addi r6,r6,16
++
++L(zero_one_small):
++        bf 28,L(zero_word_small)
++        stw r8,0(r6)
++        stw r8,4(r6)
++        addi r6,r6,8
++
++L(zero_word_small):
++        bf 29,L(zero_half_small)
++        stw r8,0(r6)
++        addi r6,r6,4
++
++L(zero_half_small):
++        bf 30,L(zero_byte_small)
++        sth r8,0(r6)
++        addi r6,r6,2
++
++L(zero_byte_small):
++        bf 31,L(finish)
++        stb r8,0(r6)
++
++        blr
++
++END (bzero)
++libc_hidden_builtin_def (bzero)
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/strcmp.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strcmp.S
+--- libc/sysdeps/powerpc/powerpc32/e500/strcmp.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strcmp.S	2014-08-01 06:44:54.397372002 -0500
+@@ -0,0 +1,685 @@
++/*------------------------------------------------------------------
++ * strcmp.S
++ * 
++ * Standard strcmp function optimized for e500 using SPE
++ *
++ * Copyright (c) 2005 Freescale Semiconductor, Inc
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *     * Redistributions of source code must retain the above copyright
++ *       notice, this list of conditions and the following disclaimer.
++ *     * Redistributions in binary form must reproduce the above copyright
++ *       notice, this list of conditions and the following disclaimer in the
++ *       documentation and/or other materials provided with the distribution.
++ *     * Neither the name of Freescale Semiconductor nor the
++ *       names of its contributors may be used to endorse or promote products
++ *       derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *------------------------------------------------------------------
++ */
++
++#include <sysdep.h>
++
++/*------------------------------------------------------------------
++ * int strcmp(const unsigned char* sourceA,
++ *            const unsigned char* sourceB);
++ * Returns:
++ *  value < 0  if source1 < source2
++ *  value = 0  if source1 = source2
++ *  value > 0  if source1 > source2
++ *------------------------------------------------------------------
++ */
++
++	.file   "strcmp.S"
++	.section        ".text"
++/* If sourceA and sourceB are aligned the same wrt doublewords,
++ * or aligned the same wrt words, we compare in doublewords.
++ * Otherwise, go byte by byte.
++ */
++EALIGN (strcmp, 5, 0)
++
++        /* Load constant 0x01010101 */
++        lis r11,0x0101
++        ori r11,r11,0x0101
++
++        /* r3 will be used for returning stuff, so lets move
++	 * sourceA out of there
++	 */
++        mr r10,r3
++
++        /* Load doubleword constant 0x01010101 */
++        evmergelo r12,r11,r11
++
++        /* generate a mask to set the unwanted bits to 1
++	 * take the alignment of r10 * 8
++	 */
++        rlwinm r6, r10, 3, 27,28
++
++        /* Load doubleword constant 0x80808080 */
++        evslwi r11,r12,7
++
++        /* start the mask with all Fs */
++        li r8, -1
++
++        or r0,r10,r4
++
++        subfic r6, r6, 32
++
++        andi. r0,r0,0x7
++
++        /* Shift r8 by r6 to mask off preceding bytes */
++        slw r8, r8, r6
++
++        /* Save the stack, cuz we need to save a reg */
++        stwu r1, -32(r1)
++
++        /* save r14 for counting.  This is cheaper than bdnz */
++        stw r14, 8(r1)
++
++        beq L(Aligned_Double)
++
++/* load the first words (on word boundaries) and process them,
++ * setting bits preceding the first byte to 1.
++ */
++
++        /* If r10 and r4 can't be aligned to words, then jump
++	 * to unaligned compare
++	 */
++        xor r0,r10,r4
++        rlwinm. r0,r0,0,30,31
++        bne L(unaligned_compare)
++
++        /* align r10 to word */
++        rlwinm r10, r10, 0,0,29
++
++        /* process the first word, and word align r4 */
++        lwz r5, 0(r10)
++        rlwinm r4, r4, 0,0,29
++
++        /* Check whether r10 and r4 are both aligned double or not.
++	 * Jump to Unaligned_Double if they are different.
++	 */
++        xor r0,r10,r4
++        addi r10, r10, 4
++
++        /* Load the other first word (B), and set all the bits
++	 * preceding the first real byte
++	 */
++        lwz r7, 0(r4)
++        or r5, r5, r8
++
++        /* This will be 0b100 if the ptrs are only word aligned
++	 * (not doubleword aligned)
++	 */
++        rlwinm r0,r0,0,29,29
++
++        /* Look for nulls in the first (partial) word */
++        subfc r3, r12, r5
++        andc r9, r11, r5
++
++        /* Update r4, and find out if there were any nulls */
++        addi r4,r4,4
++        and. r9, r3, r9
++
++        /* Find out if we are doubleword aligned, and set all the
++	 * bits preceding the first byte in word B
++	 */
++        cmpwi 6, r0,0
++        or r7,r7,r8
++
++        /* jump out if we found a null, otherwise compare the two words */
++        bne L(find_null1)
++        subfc. r0, r5, r7
++
++        /* Set a condition bit if r10 is not yet doubleword
++	 * aligned, and branch if the first words were different
++	 */
++        mtcrf 0x01,r10
++        bne L(found_diff_early)
++
++        /* process another word if necessary to align to a doubleword
++	 * boundary.
++	 */
++        bf 29, L(Check_Aligned_Double)
++
++        /* Load another word from each string, to align r10 to a
++	 * double word
++	 */
++        lwz r5, 0(r10)
++        addi r10, r10, 4
++        lwz r7, 0(r4)
++        addi r4,r4,4
++
++
++        /* Check for nulls and differences in the words */
++        subfc r3, r12, r5
++        andc r9, r11, r5
++        and. r9, r3, r9
++        bne L(find_null1)
++        subfc. r0, r5, r7
++        bne L(found_diff_early)
++
++        /* r10 is now aligned to a doubleword boundary, but it
++	 * may be that we are not both double aligned.  We set a
++	 * bit based on this earlier, so branch if it is set.
++	 */
++L(Check_Aligned_Double):
++        bne 6, L(Unaligned_Double)
++
++        /* loop through 2 doublewords at once in this page, until one of
++	 * these happens:
++	 * 1) A null byte is found in r10
++	 * 2) a byte is found which is different between r10 and r4
++	 * 3) the end of the page is reached
++	 * 
++	 * If 3 happens, then we finish processing the last doubleword in
++	 * the page, and if it checks out, we jump to the next one.  The
++	 * hope is that no small strings are going to cross page
++	 * boundaries.  For large strings, the hit should be minimal
++	 *
++	 * If 1 happens, some extra checking goes on to see whether the
++	 * strings are the same or not.
++	 */
++L(Aligned_Double):
++        /* Start figuring out how far to the next page */
++        not r6,r10
++        not r8,r4
++
++        rlwinm r6,r6,29,23,31
++        rlwinm r8,r8,29,23,31
++
++        subfc. r0,r6,r8
++        evldd r5, 0(r10)
++
++        /* zero out a reg for comparison (the result of the final
++	 * and is nonzero for any word with a null byte)
++	 */
++        evsplati r0,0
++        evldd r7, 0(r4)
++
++        /* Select the shortest distance to the page */
++        isellt r14,r8,r6
++
++        evsubfw r3, r12, r5
++        addic. r14,r14,-6
++
++        evandc r9, r11, r5
++
++        blt L(aligned_double_loop_end)
++
++        /* The loop */
++L(aligned_double_loop):
++        evldd r6, 8(r10)
++        evand r9, r9, r3
++        addi r10,r10,16
++        evcmpgtu 1, r9, r0
++        evldd r8, 8(r4)
++        evcmpeq 6, r5, r7
++        bt 6, L(found_null1)
++        evsubfw r3,r12, r6
++        bf 27, L(found_diff1)
++        evandc r9, r11, r6
++        evldd r5, 0(r10)
++        evand r9,r9,r3
++        addi r4,r4,16
++        evcmpgtu 5, r9, r0
++        evldd r7, 0(r4)
++        evcmpeq 7, r6, r8
++        bt 22, L(found_null2)
++        evsubfw r3, r12, r5
++        bf 31, L(found_diff2)
++        evandc r9, r11, r5
++
++        evldd r6, 8(r10)
++        evand r9, r9, r3
++        addi r10,r10,16
++        evcmpgtu 1, r9, r0
++        evldd r8, 8(r4)
++        evcmpeq 6, r5, r7
++        bt 6, L(found_null1)
++        evsubfw r3,r12, r6
++        bf 27, L(found_diff1)
++        evandc r9, r11, r6
++        evldd r5, 0(r10)
++        evand r9,r9,r3
++        addi r4,r4,16
++        evcmpgtu 5, r9, r0
++        evldd r7, 0(r4)
++        evcmpeq 7, r6, r8
++        bt 22, L(found_null2)
++        evsubfw r3, r12, r5
++        bf 31, L(found_diff2)
++        addic. r14,r14,-4
++        evandc r9, r11, r5
++        bge L(aligned_double_loop)
++
++        /* we exited the loop, we must be at the end of a page.
++	 * Finish the last one, and then see if we are done or
++	 * not.
++	 */
++L(aligned_double_loop_end):
++        evand r9, r9, r3
++        evcmpgtu 1, r9, r0
++        evcmpeq 6, r5, r7
++        bt 6, L(found_null1)
++        bf 27, L(found_diff1)
++        addi r10,r10,8
++        addi r4,r4,8
++
++        or r3, r10,r4
++        andi. r3, r3, 0xFFF
++        beq L(find_next_page)
++        /* We need to check the next doubleword, too.  It may be
++	 * in the next page, but it may be the last one in this
++	 * page.
++	 */
++        li r14,3
++L(find_page_end):
++        evldd r5, 0(r10)
++        addi r10,r10,8
++        evldd r7, 0(r4)
++        addi r4,r4,8
++        evsubfw r3, r12, r5
++        addic. r14,r14,-1
++        evandc r9, r11, r5
++        evand r9, r9, r3
++        evcmpgtu 1, r9, r0
++        evcmpeq 6, r5, r7
++        bt 6, L(found_null1)
++        bf 27, L(found_diff1)
++        bne L(find_page_end)
++
++
++        /* It is now safe to proceed to the next page.  load the
++	 * counter with the number of doublewords before the next
++	 * page
++	 */
++
++L(find_next_page):
++        not r6,r10
++        not r8,r4
++        rlwinm r6,r6,29,23,31
++        rlwinm r8,r8,29,23,31
++        subfc. r0,r6,r8
++        isellt r14,r8,r6
++        evldd r5, 0(r10)
++        addic. r14,r14,-6
++        evldd r7, 0(r4)
++        evsubfw r3, r12, r5
++        evandc r9, r11, r5
++        evsplati r0, 0
++        blt L(aligned_double_loop_end)
++        b L(aligned_double_loop)
++
++        /* The first doubleword had a null byte */
++L(found_unaligned_null1):
++        evmr r7,r15
++        evldd r15, 16(r1)
++L(found_null1):
++        /* If there was a null in the hi word, or if the hi words
++	 * were not equal, we want to check the hi word, so move
++	 * it down into the lo word
++	 */
++        crorc 4,4,24 
++        bf 4, L(find_null1)
++        evmergehi r5, r5, r5
++        evmergehi r7,r7,r7
++L(find_null1):
++        rlwinm. r11,r5,0,0,7
++        li r12,24
++        beq L(aligned_shift1)
++        rlwinm. r11,r5,0,8,15
++        li r12,16
++        beq L(aligned_shift1)
++        rlwinm. r11,r5,0,16,23
++        li r12,8
++        beq L(aligned_shift1)
++        li r12,0
++
++        /* If the signs are different for these words,
++	 * then overflow can occur
++	 */
++        xor. r0,r5,r7
++
++L(aligned_shift1):
++        srw r5,r5,r12
++        srw r7,r7,r12
++        lwz r14, 8(r1)
++        subfc r3,r7,r5
++        addi r1,r1,32
++
++        /* return now if the signs were the same (r3
++	 * has the appropriate value).  Otherwise, return
++	 * r7.  r7's sign matches that of the necessary
++	 * return value, since the comparison is actually
++	 * unsigned.  This means that a negative number is
++	 * actually large, and, if the signs are different,
++	 * guaranteed to be larger than r5. The same is true
++	 * for the opposite case.  We also make sure it is
++	 * non-zero.
++	 */
++        bgelr
++        ori r3,r7,1
++        blr
++
++L(found_unaligned_null2):
++        evmr r8,r15
++        evldd r15, 16(r1)
++L(found_null2):
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word
++	 */
++        evmr r5,r6
++        crorc 20, 20, 28 
++        evmr r7,r8
++        bf 20, L(find_null1)
++        evmergehi r5, r5, r5
++        evmergehi r7, r7, r7
++        b L(find_null1)
++
++/* Now we know that there is a difference in one of the
++   two doublewords.  We find the first different bit within
++   each word, and then rotate each word of B so that the sign
++   bit is that bit.  When B is greater, that bit will be one, and
++   the sign of the return should be negative, and when B is less,
++   the bit will be zero, making the return positive.  Also,
++   we need to OR the r3 with 1 to make sure it is non-zero
++ */
++L(found_unaligned1):
++        evmr r7,r15
++        evldd r15, 16(r1)
++L(found_diff1):
++        evxor r0,r5,r7
++        lwz r14,8(r1)
++        evcntlzw r0,r0
++        addi r1,r1,32
++        evrlw r3,r7,r0
++        evmergehi r4,r3,r3
++        isel r3,r3,r4,24
++        ori r3,r3,1
++        blr
++
++/* See found_diff1 description for explanation of this code */
++L(found_unaligned2):
++        evmr r8,r15
++        evldd r15, 16(r1)
++L(found_diff2):
++        evxor r0,r6,r8
++        lwz r14,8(r1)
++        evcntlzw r0,r0
++        addi r1,r1,32
++        evrlw r3,r8,r0
++        evmergehi r4,r3,r3
++        isel r3,r3,r4,28
++        ori r3,r3,1
++        blr
++
++L(Unaligned_Double):
++        /* Invert the pointers so that the last 12 bits hold the
++	 * number of bytes to the end of the page (minus 1)
++	 */
++        not r6,r10
++        not r8,r4
++
++        /* remove all but the last 12 bits from the nots, and
++	 * shift the result right by 3, thus making it the number
++	 * of doubles to the end of the page
++	 */
++        rlwinm r6,r6,29,23,31
++        rlwinm r8,r8,29,23,31
++
++        /* align r4 to a doubleword boundary, and load the
++	 * first double of r10 (prologue for loop)
++	 */
++        rlwinm r4,r4,0,0,28
++        evldd r5, 0(r10)
++
++        /* subtract the distances from each other, setting the
++	 * condition code so we know which was shorter.
++	 * And load the first word of r4 into a doubleword
++	 */
++        subfc. r0,r6,r8
++        evldd r7, 0(r4)
++
++        /* zero out a reg for comparison (the result of the final
++	 * and is nonzero for any word with a null byte)
++	 * Save off a register for merging into
++	 */
++        evsplati r0,0
++        evstdd r15,16(r1)
++
++        /* And start looking for nulls in r10 */
++        evsubfw r3, r12, r5
++
++        /* Select the shortest distance to the page */
++        isellt r14,r8,r6
++
++        /* And continue looking for nulls */
++        evandc r9, r11, r5
++
++        /* We want to jump out early (before we load the next
++	 * double) if this is the last double.
++	 * Then update r14 so that it reflects the number of
++	 * doublewords that will have been loaded by the end
++	 * of the first iteration of the loop (4)
++	 */
++        cmpwi cr1,r14,1
++
++        addic. r14,r14,-4
++
++        /* Can't do this load until we know the previous one is
++	 * free of null bytes
++	 */
++        blt cr1,L(unaligned_last_was_first)
++        evldd r8, 8(r4)
++
++        /* Align the first double,  and branch over the loop if
++	 * we are less than 3 doubles from the end of the page
++	 */
++        evmergelohi r15,r7,r8
++        blt L(unaligned_double_loop_end)
++
++        /* And away we go!  Loop as many times as we can before
++	 * we hit the end of the page.  This code is scheduled
++	 * such that there are no stalls in execution.  Because
++	 * loads take 3 cycles, there could be stalls in
++	 * completion.
++	 * NOTE TO SELF:
++	 *
++	 * Issues:
++	 * 1) evmergelohi must be before any connected branch.
++	 *   the exit cases (found_null1, etc) assume that the
++	 *   values are all properly lined up.
++	 * 2) null case must branch before diff case.  diff
++	 *    assumes it to be so
++	 * 3) When near the end of the page, have to make sure
++	 *    that the hi word of r10, and the lo word of r4
++	 *    don't have any nulls before grabbing the next double
++	 *    for r4
++	 */
++L(unaligned_loop):
++        evcmpeq 6, r5,r15
++        evldd r6, 8(r10)
++        evand r9,r9,r3
++        addi r10,r10,16
++        evcmpgtu 1,r9, r0
++        evldd r7, 16(r4)
++        evsubfw r3,r12,r6
++        bt 6,L(found_unaligned_null1)
++        evandc r9,r11,r6
++        bf 27,L(found_unaligned1)
++        evmergelohi r15,r8,r7
++        addi r4,r4,16
++        evcmpeq 7,r6,r15
++        evldd r5,0(r10)
++        evand r9,r9,r3
++        addic. r14,r14,-2
++        evcmpgtu 5,r9, r0
++        evldd r8,8(r4)
++        evsubfw r3,r12,r5
++        bt 22,L(found_unaligned_null2)
++        evandc r9,r11,r5
++        bf 31,L(found_unaligned2)
++        evmergelohi r15,r7,r8
++        bge L(unaligned_loop)
++
++        /* we exited the loop, we must be at the end of a page.
++	 * Finish the last one, and then see if we are done or
++	 * not.
++	 */
++L(unaligned_double_loop_end):
++        evcmpeq 6, r5, r15
++        evand r9,r9,r3
++        evcmpgtu 1, r9, r0
++        addi r10,r10,8
++        bt 6, L(found_unaligned_null1)
++        addi r4,r4,8
++        bf 27, L(found_unaligned1)
++
++        /* We need to check the next doubleword, too.  It may be
++	 * in the next page, but it may be the last one in this
++	 * page.
++	 */
++L(unaligned_find_page_end):
++        evldd r6, 0(r10)
++        addi r10,r10,8
++        evsubfw r3, r12, r6
++        evandc r9, r11, r6
++        evand r9, r9, r3
++        evcmpgtu 5, r9, r0
++        bt 20,L(found_early_null2)
++
++        /* Check r8 */
++        evsubfw r3, r12,r8
++        evandc r9, r11,r8
++        evand r9,r9,r3
++        evcmpgtu 1,r9,r0
++        bt 6,L(found_early_null2)
++        evldd r7, 8(r4)
++        addi r4,r4,8
++        evmergelohi r15,r8,r7
++        evcmpeq 7, r6, r15
++        bt 22, L(found_unaligned_null2)
++        bf 31, L(found_unaligned2)
++
++
++        /* At this point, we will have crossed a page boundary in
++	 * one of the strings safely.  However, the other string
++	 * could be near the end of the page.  So we calculate
++	 * which string is closest to the end of the page again,
++	 * and redo the end of page code if it is less than 3
++	 * doublewords from the end.
++	 */
++L(unaligned_find_next_page):
++        not r6,r10
++        not r8,r4
++        rlwinm r6,r6,29,23,31
++        rlwinm r8,r8,29,23,31
++        subfc. r0,r6,r8
++        evldd r5, 0(r10)
++        evsplati r0,0
++        isellt r14,r8,r6
++        cmpwi cr1,r14,1
++        evsubfw r3, r12, r5
++        addic. r14,r14,-3
++        evandc r9, r11, r5
++        blt cr1,L(unaligned_last_was_first)
++        evldd r8, 8(r4)
++        evmergelohi r15,r7,r8
++        blt L(unaligned_double_loop_end)
++        b L(unaligned_loop)
++
++/* The end of the page happened so early, we couldn't load more
++ * than one doubleword safely.
++ * We need to make sure both CURRENTLY LOADED doublewords are
++ * null-free, since either one could be the one at the end of the
++ * page.
++ */
++L(unaligned_last_was_first):
++        evand r9,r9,r3
++        addi r10,r10,8
++        evcmpgtu 1,r9,r0
++        bt 4,L(found_early_null)
++
++        /* now check r7 */
++        evsubfw r3,r12,r7
++        evandc r9,r11,r7
++        evand r9,r3,r9
++        evcmpgtu 5,r9,r0
++        bt 22,L(found_early_null)
++
++        /* Now load the next 2 words of r4, and realign the
++	 * data to r10.  Then branch out if any of the bytes
++	 * were null.
++	 */
++        evldd r8,8(r4)
++        addi r4,r4,8
++        evmergelohi r15,r7,r8
++        evcmpeq 6,r5,r15
++        bt 6,L(found_unaligned_null1)
++        bf 27, L(found_unaligned1)
++
++        /* unaligned_find_next_page expects the previous
++	 * doubleword to be in r7, so move r8 there
++	 */
++        evmr r7,r8
++
++        /* find out where the next page is */
++        b L(unaligned_find_next_page)
++
++/* We found a null in the hi word of r5, near the end of the
++ * page.  r7 has the value we want to deal with, but we want
++ * the important word in A to be in the lo word.  So we merge
++ */
++L(found_early_null):
++        evmergehi r5,r5,r5
++        evldd r15,16(r1)
++        b L(find_null1)
++
++L(found_early_null2):
++        evmergehi r5,r6,r6
++        evldd r15,16(r1)
++        evmr r7,r8
++        b L(find_null1)
++
++L(unaligned_compare):
++        lbz r5, 0(r10)
++        lbz r7, 0(r4)
++        lwz r14, 8(r1)
++        addi r1,r1,32
++        subfc. r3, r7, r5
++        bnelr
++L(unaligned_byte_loop):
++        cmpwi cr1, r5,0
++        beq cr1, L(Null_Byte)
++        lbzu r5,1(r10)
++        lbzu r7,1(r4)
++        subfc. r3,r7,r5
++        beq L(unaligned_byte_loop)
++        blr
++L(Null_Byte):
++        li r3,0
++        blr
++
++L(found_diff_early):
++        subfe r3,r0,r0
++        not r3,r3
++        ori r3,r3,1
++        lwz r14, 8(r1)
++        addi r1,r1,32
++        blr
++
++END (strcmp)
++libc_hidden_builtin_def (strcmp)
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/strcpy.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strcpy.S
+--- libc/sysdeps/powerpc/powerpc32/e500/strcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strcpy.S	2014-08-01 06:45:17.052372002 -0500
+@@ -0,0 +1,665 @@
++/*------------------------------------------------------------------
++ * strcpy.S
++ * 
++ * Standard strcpy function optimized for e500 using SPE
++ *
++ * Copyright (c) 2005 Freescale Semiconductor, Inc
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *     * Redistributions of source code must retain the above copyright
++ *       notice, this list of conditions and the following disclaimer.
++ *     * Redistributions in binary form must reproduce the above copyright
++ *       notice, this list of conditions and the following disclaimer in the
++ *       documentation and/or other materials provided with the distribution.
++ *     * Neither the name of Freescale Semiconductor nor the
++ *       names of its contributors may be used to endorse or promote products
++ *       derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *------------------------------------------------------------------
++ */
++
++#include <sysdep.h>
++
++/*------------------------------------------------------------------
++ * char * strcpy(char* dest, const char* src);
++ * Returns:
++ * dest
++ *------------------------------------------------------------------
++ */
++
++	.file   "strcpy.S"
++	.section        ".text"
++/* If dest and src are aligned the same wrt doublewords,
++ * or aligned the same wrt words, we copy in doublewords.
++ * Otherwise, go byte by byte.
++ */
++EALIGN (strcpy, 5, 0)
++
++        /* All of the string functions use an algorithm for null
++	 * detection taken from the original libmoto:
++	 *
++	 * 1) load in a word
++	 * 2a) subtract 0x01010101 from the word.  This will cause
++	 * all bytes with a null to be 0xff (unless it is right
++	 * before another null, in which case it will be 0xfe)
++	 *
++	 * 3b) AND 0x80808080 with the complement of the word.
++	 * The resulting bytes will only have their high bit set
++	 * if the corresponding bit was 0 in the original word
++	 *
++	 * So now we (basically) have a word with the high bit of
++	 * any byte set which was between 0x81 and 0xff, or 0x00.
++	 * We also have a mask which will only select the high
++	 * bits of bytes which were between 0x00 and 0x7f.  There
++	 * is only one overlap:  a null byte (0x00).  If we now:
++	 *
++	 * 4) and the two results
++	 *
++	 * The result will only have 1s in the high bits of bytes
++	 * which had nulls.  With one exception.  If there is a
++	 * byte with 0x01 before a byte with 0x00, then that
++	 * byte, too, will have a 1 in the high bit.  However,
++	 * since this only happens when a byte with 0x00 occurs
++	 * in the word, this technique is useful for detecting if
++	 * there are any nulls in the word.
++	 */
++
++        /* r3 needs to return the original dest, but r3 is used,
++	 * so move r3 into the upper half of r10
++	 */
++        evmergelo r10,r3,r3
++
++        /* Load constant 0x01010101 */
++        lis r11,0x0101
++        ori r11,r11,0x0101
++
++        /* Load doubleword constant 0x01010101 */
++        evmergelo r12,r11,r11
++
++        /* Determine whether r4 and r10 are doubleword-aligned */
++        or r0,r10,r4
++
++        /* Load doubleword constant 0x80808080 */
++        evslwi r11,r12,7
++
++        /* Save the stack, cuz we need to save a reg */
++        stwu r1, -16(r1)
++
++        andi. r0,r0,0x7
++
++        /* save r14.  This is cheaper than bdnz */
++        stw r14, 8(r1)
++
++        beq L(Aligned_Double)
++
++/* load the first words (on word boundaries) and process them,
++ * setting bits preceding the first byte to 1.
++ */
++
++        /* If r10 and r4 are off by 4, we can handle that almost
++	 * as fast as in the fully-aligned case, so we want to go
++	 * there as soon as possible.  If this is true, then
++	 * r0 will be 4.  The Unaligned_Double loop needs
++	 * r10 to be double-aligned, so we move bit 29 of r10
++	 * into bit 29 of r0, and if r0 is then zero,
++	 * r10 is already properly aligned, and we jump to
++	 * Unaligned_Double.
++	 */
++        rlwimi. r0,r10,0,29,29
++        not r6, r10
++        xor r0,r10,r4
++        beq L(Unaligned_Double)
++
++        /* If the last two bits of r4 and r10 are
++	 * different, then it is not efficient to copy
++	 * them in chunks larger than a byte
++	 */
++        andi. r14,r0,0x3
++        addi r6, r6, 1
++        bne L(unaligned_copy)
++
++        /* Check for double alignment */
++        rlwinm r0,r0,0,29,29
++
++        /* Move the alignment amount into the CR */
++        mtcrf 0x1, r6
++
++        /* Set the condition code for double alignment */
++        cmpwi 5, r0,0
++
++        /* Process a byte if r10 is only byte-aligned */
++        bf 31, L(try_halfword)
++        lbz r5, 0(r4)
++        addi r4,r4,1
++        cmpwi r5, 0
++        stb r5, 0(r10)
++        addi r10,r10,1
++        beq L(aligned_end1)
++
++        /* Process 2 bytes if r10 is only halfword aligned */
++L(try_halfword):
++        bf 30, L(try_word)
++        lbz r5, 0(r4)
++        lbz r6, 1(r4)
++        addi r4,r4,2
++        cmpwi r5, 0
++        stb r5, 0(r10)
++        beq L(aligned_end1)
++        cmpwi r6, 0
++        stb r6, 1(r10)
++        beq L(aligned_end1)
++        addi r10,r10,2
++
++        /* process another word if necessary to align to a doubleword
++	 * boundary.
++	 */
++L(try_word):
++        bf 29, L(Check_Aligned_Double)
++
++        /* Load the next word, to align r10 to a double word */
++        lwz r5, 0(r4)
++        addi r4,r4,4
++
++        /* Process it */
++        subfc r3, r12, r5
++        andc r9, r11, r5
++        and. r9, r3, r9
++
++        /* Need to have r5 in r0, because find_null1 assumes
++	 * that r0 will have the word in which the first null was
++	 * found.  (found_null1 assumes that condition codes have
++	 * been set by evcmpgtu, so we have to jump into that
++	 * block of code after the logic which figures out the
++	 * first word has been executed)
++	 */
++        mr r0,r5
++        bne L(find_null1)
++
++        /* Store the word */
++        stw r5,0(r10)
++        addi r10, r10, 4
++
++        /* r10 is now doubleword aligned, but both strings may
++	 * not be doubleword aligned.  We set a bit earlier for
++	 * this, so branch if it was set.
++	 */
++L(Check_Aligned_Double):
++        bne 5, L(Unaligned_Double)
++
++        /* loop through 2 doublewords at once in this page, until one of
++	 * these happens:
++	 * 1) A null byte is found in r4
++	 * 2) the end of the page is reached
++	 * 
++	 * If 2 happens, then we finish processing the last doubleword in
++	 * the page, and if it checks out, we jump to the next one.  The
++	 * hope is that no small strings are going to cross page
++	 * boundaries.  For large strings, the hit should be minimal
++	 *
++	 * If 1 happens, some extra checking goes on to see whether the
++	 * strings are the same or not.
++	 *
++	 * The primary loop is capable of 2 IPC (it issues
++	 * 2/cycle, but completion may stall).  If it gets 2 IPC,
++	 * then it is doing a load or store every other cycle.
++	 * This means that a doubleword is stored every fourth
++	 * cycle.  So the code will approach copying 2
++	 * bytes/cycle.  This is 2x what the optimized scalar
++	 * code can do.
++	 */
++L(Aligned_Double):
++        /* Start figuring out how far to the next page */
++        not r8,r4
++
++        evldd r5, 0(r4)
++
++        /* zero out a reg for comparison (the result of the final
++	 * and is nonzero for any word with a null byte)
++	 */
++        evsplati r0,0
++
++        rlwinm r8,r8,29,23,31
++
++        evsubfw r3, r12, r5
++
++        /* We will load 2 doublewords, but it could be that the
++	 * first null is in the the first double.
++	 * If this double is also the last in the page, then
++	 * loading the next double could cause a segmentation
++	 * fault.  So we check to see if this is the last, and if
++	 * so we jump to a special case.
++	 */
++        addic. r14, r8,-1
++        blt L(last_double_was_first)
++
++        evldd r6, 8(r4)
++        evandc r9, r11, r5
++
++        evand r9,r9,r3
++        addic. r14,r14,-5
++
++        evcmpgtu 1,r9,r0
++        evsubfw r3,r12, r6
++
++        blt L(aligned_double_loop_end)
++        /* The loop */
++L(aligned_double_loop):
++        evandc r9, r11, r6
++        evldd r7, 16(r4)
++        evand r9,r9,r3
++        bt 6, L(found_null1)
++        evcmpgtu 5, r9, r0
++        evstdd r5,0(r10)
++        evsubfw r3, r12, r7
++        evldd r8, 24(r4)
++        evandc r9, r11, r7
++        bt 22, L(found_null2)
++        evand r9, r9, r3
++        evstdd r6,8(r10)
++        evcmpgtu 6, r9, r0
++        addic. r14,r14,-4
++        evsubfw r3,r12, r8
++        addi r4,r4,32
++        evandc r9, r11, r8
++        evldd r5, 0(r4)
++        evand r9, r9, r3
++        bt 26, L(found_null3)
++        evcmpgtu 7, r9, r0
++        evstdd r7,16(r10)
++        evsubfw r3,r12, r5
++        evldd r6, 8(r4)
++        evandc r9, r11, r5
++        bt 30, L(found_null4)
++        evand r9, r9, r3
++        evstdd r8,24(r10)
++        evcmpgtu 1, r9, r0
++        addi r10,r10,32
++        evsubfw r3,r12, r6
++        bge L(aligned_double_loop)
++
++        /* we exited the loop, we must be at the end of a page.
++	 * Finish the last one, and then see if we are done or
++	 * not.
++	 */
++L(aligned_double_loop_end):
++        bt 6, L(found_null1)
++        evstdd r5, 0(r10)
++        evandc r9,r11,r6
++        evand r9,r9,r3
++        evcmpgtu 5,r9,r0
++        bt 22, L(found_null2)
++        evstdd r6, 8(r10)
++
++        addi r4,r4,16
++        addi r10,r10,16
++
++        andi. r3,r4,0xFFF
++        beq L(start_new_loop)
++
++L(find_page_end):
++        evldd r5,0(r4)
++        addi r4,r4,8
++        evsubfw r3, r12, r5
++        evandc r9, r11, r5
++        evand r9, r3, r9
++        andi. r3,r4,0xFFF
++        evcmpgtu 1, r9, r0
++        bt 6, L(found_null1)
++        evstdd r5, 0(r10)
++        addi r10,r10,8
++        bne L(find_page_end)
++
++L(start_new_loop):
++        /* It is now safe to proceed to the next page.  load the
++	 * r14 with the number of doublewords in a page 
++	 * (-6 to account for the first loop)
++	 */
++        evldd r5, 0(r4)
++        li r14, 505
++
++        /* Now we set up for the beginning of the loop */
++        evldd r6, 8(r4)
++        evsubfw r3, r12, r5
++        evandc r9, r11, r5
++        evand r9,r9,r3
++        evcmpgtu 1,r9,r0
++        evsubfw r3,r12,r6
++        b L(aligned_double_loop)
++
++L(last_double_was_first):
++        addi r4,r4,8
++        evandc r9,r11,r5
++        evand r9,r9,r3
++        evcmpgtu 1,r9,r0
++        bt 6, L(found_null1)
++        evstdd r5,0(r10)
++        addi r10,r10,8
++        b L(start_new_loop)
++
++
++        /* The first doubleword had a null byte */
++L(found_null1):
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word
++	 */
++        evmergehi r0, r5, r5
++        bt 4, L(find_null1)
++        stw r0,0(r10)
++        addi r10,r10,4
++        mr r0,r5
++L(find_null1):
++        rlwinm. r11,r0,8,24,31
++        stb r11, 0(r10)
++        beq L(aligned_end1)
++        rlwinm. r11,r0,16,24,31
++        stb r11, 1(r10)
++        beq L(aligned_end1)
++        rlwinm. r11,r0,24,24,31
++        stb r11, 2(r10)
++        beq L(aligned_end1)
++        stb r0, 3(r10)
++
++L(aligned_end1):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++        /* The second doubleword had a null byte */
++L(found_null2):
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word
++	 */
++        evmergehi r0, r6, r6
++        bt 20, L(find_null2)
++        stw r0,8(r10)
++        addi r10,r10,4
++        mr r0,r6
++L(find_null2):
++        rlwinm. r11,r0,8,24,31
++        stb r11, 8(r10)
++        beq L(aligned_end2)
++        rlwinm. r11,r0,16,24,31
++        stb r11, 9(r10)
++        beq L(aligned_end2)
++        rlwinm. r11,r0,24,24,31
++        stb r11, 10(r10)
++        beq L(aligned_end2)
++        stb r0, 11(r10)
++
++L(aligned_end2):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++        /* The third doubleword had a null byte */
++L(found_null3):
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word
++	 */
++        evmergehi r0, r7, r7
++        bt 24, L(find_null3)
++        stw r0,16(r10)
++        addi r10,r10,4
++        mr r0,r7
++L(find_null3):
++        rlwinm. r11,r0,8,24,31
++        stb r11,16(r10)
++        beq L(aligned_shift3)
++        rlwinm. r11,r0,16,24,31
++        stb r11,17(r10)
++        beq L(aligned_shift3)
++        rlwinm. r11,r0,24,24,31
++        stb r11,18(r10)
++        beq L(aligned_shift3)
++        stb r0,19(r10)
++
++L(aligned_shift3):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++
++        /* The fourth doubleword had a null byte */
++L(found_null4):
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word
++	 */
++        evmergehi r0, r8, r8
++        bt 28, L(find_null4)
++        stw r0,24(r10)
++        addi r10,r10,4
++        mr r0,r8
++L(find_null4):
++        rlwinm. r11,r0,8,24,31
++        stb r11,24(r10)
++        beq L(aligned_shift4)
++        rlwinm. r11,r0,16,24,31
++        stb r11,25(r10)
++        beq L(aligned_shift4)
++        rlwinm. r11,r0,24,24,31
++        stb r11,26(r10)
++        beq L(aligned_shift4)
++        stb r0,27(r10)
++
++L(aligned_shift4):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++L(found_unaligned_null1):
++        evmergehi r0,r7,r7
++        bt 24, L(find_unaligned_null1)
++        stw r0,0(r10)
++        addi r10,r10,4
++        mr r0,r7
++L(find_unaligned_null1):
++        rlwinm. r11,r0,8,24,31
++        stb r11, 0(r10)
++        beq L(unaligned_end1)
++        rlwinm. r11,r0,16,24,31
++        stb r11, 1(r10)
++        beq L(unaligned_end1)
++        rlwinm. r11,r0,24,24,31
++        stb r11, 2(r10)
++        beq L(unaligned_end1)
++        stb r0, 3(r10)
++
++L(unaligned_end1):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++L(found_unaligned_null2):
++        evmergehi r0,r8,r8
++        bt 28, L(find_unaligned_null2)
++        stw r0,8(r10)
++        addi r10,r10,4
++        mr r0,r8
++L(find_unaligned_null2):
++        rlwinm. r11,r0,8,24,31
++        stb r11, 8(r10)
++        beq L(unaligned_end2)
++        rlwinm. r11,r0,16,24,31
++        stb r11, 9(r10)
++        beq L(unaligned_end2)
++        rlwinm. r11,r0,24,24,31
++        stb r11, 10(r10)
++        beq L(unaligned_end2)
++        stb r0, 11(r10)
++
++L(unaligned_end2):
++        evmergehi r3,r10,r10
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++L(Unaligned_Double):
++        /* Align r4 to doubleword.
++	 * Get number of bytes before end of page
++	 */
++        not r8,r4
++        rlwinm r4,r4,0,0,28
++
++        /* Load the first doubleword (only half of which is good) */
++        rlwinm r8,r8,29,23,31
++        evldd r6,0(r4)
++
++        /* We will load 2 doublewords, but it could be that the
++	 * first null is in the lower word of the first double.
++	 * If this double is also the last in the page, then
++	 * loading the next double could cause a segmentation
++	 * fault.  So we check to see if the word has any
++	 * nulls, and if so, we jump to a special case
++	 * And zero a register for comparison
++	 */
++        addic. r14,r8,-1
++        evsplati r0,0
++        addi r10,r10,-16 /* predecrement r10 */
++        blt L(unaligned_first_was_last)
++
++        evldd r5,8(r4)
++        addic. r14,r14,-5
++        evmergelohi r7,r6,r5
++        evsubfw r3,r12,r7
++        blt L(unaligned_loop_end)
++
++L(unaligned_double_loop):
++        evandc r9,r11,r7
++        evldd r6,16(r4)
++        evand r9,r9,r3
++        addi r4,r4,16
++        evcmpgtu 6,r9,r0
++        addi r10,r10,16
++        evmergelohi r8,r5,r6
++        bt 26, L(found_unaligned_null1)
++        evsubfw r3,r12,r8
++        evstdd r7,0(r10)
++        evandc r9,r11,r8
++        evldd r5,8(r4)
++        evand r9,r9,r3
++        addic. r14,r14,-4
++        evcmpgtu 7,r9,r0
++        evmergelohi r7,r6,r5
++        bt 30,L(found_unaligned_null2)
++        evsubfw r3,r12,r7
++        evstdd r8,8(r10)
++
++        evandc r9,r11,r7
++        evldd r6,16(r4)
++        evand r9,r9,r3
++        addi r4,r4,16
++        evcmpgtu 6,r9,r0
++        addi r10,r10,16
++        evmergelohi r8,r5,r6
++        bt 26,L(found_unaligned_null1)
++        evsubfw r3,r12,r8
++        evstdd r7,0(r10)
++        evandc r9,r11,r8
++        evldd r5,8(r4)
++        evand r9,r9,r3
++        evcmpgtu 7,r9,r0
++        bt 30,L(found_unaligned_null2)
++        evmergelohi r7,r6,r5
++        evstdd r8,8(r10)
++        evsubfw r3,r12,r7
++        bge L(unaligned_double_loop)
++
++/* Hit the end of the page, finish up the epilog of the loop, and
++ * then run the process without any special scheduling to get
++ * into the next page
++ */
++L(unaligned_loop_end):
++        evandc r9,r11,r7
++        addi r4,r4,16
++        evand r9,r9,r3
++        addi r10,r10,16
++        evcmpgtu 6,r9,r0
++        bt 26,L(found_unaligned_null1)
++        evstdd r7,0(r10)
++        addi r10,r10,8
++
++/* At this point, r4 and r10 point to the next place to load
++ * and store.  We move forward, one word at a time, until r4
++ * has passed over into a new page.
++ */
++L(unaligned_find_next_page):
++        /* Check this word for null bytes */
++        subf r3,r12,r5
++        andc r9,r11,r5
++        and. r9,r9,r3
++        mr r0,r5
++        bne L(find_null1)
++        stw r5,0(r10)
++        addi r10,r10,4
++
++        lwz r0,0(r4)
++        addi r4,r4,4
++        subf r3,r12,r0
++        andc r9,r11,r0
++        and. r9,r9,r3
++        bne L(find_null1)
++
++        /* Calculate if r4 is on a new page */
++        andi. r6,r4,0x0f00
++
++        /* Store the 2nd word */
++        stw r0,0(r10)
++        addi r10,r10,4
++
++        beq L(Unaligned_Double)
++        lwz r5,0(r4)
++        addi r4,r4,4
++        b L(unaligned_find_next_page)
++
++L(unaligned_first_was_last):
++        addi r10,r10,16
++        addi r4,r4,8
++        mr r5,r6
++        b L(unaligned_find_next_page)
++
++L(unaligned_copy):
++        lbz r5, 0(r4)
++        addi r10, r10, -1
++        cmpwi cr1,r5,0
++        beq cr1,L(Null_Byte1)
++L(unaligned_byte_loop):
++        lbzu r6,1(r4)
++        stbu r5,1(r10)
++        cmpwi cr1,r6,0
++        beq cr1,L(Null_Byte2)
++        lbzu r5,1(r4)
++        stbu r6,1(r10)
++        cmpwi cr1,r5,0
++        bne cr1, L(unaligned_byte_loop)
++
++L(Null_Byte1):
++        stb r5,1(r10)
++        b L(Byte_End)
++L(Null_Byte2):
++        stb r6, 1(r10)
++
++L(Byte_End):
++        /* r3 still has original r10 value */
++        lwz r14, 8(r1)
++        addi r1,r1,16
++        blr
++
++END (strcpy)
++libc_hidden_builtin_def (strcpy)
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500/strlen.S libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strlen.S
+--- libc/sysdeps/powerpc/powerpc32/e500/strlen.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-e500v2-lib/sysdeps/powerpc/powerpc32/e500/strlen.S	2014-08-01 06:45:39.755371998 -0500
+@@ -0,0 +1,342 @@
++/*------------------------------------------------------------------
++ * strlen.S
++ *
++ * Standard strlen function optimized for e500 using SPE
++ *
++ * Copyright (c) 2005 Freescale Semiconductor, Inc
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *     * Redistributions of source code must retain the above copyright
++ *       notice, this list of conditions and the following disclaimer.
++ *     * Redistributions in binary form must reproduce the above copyright
++ *       notice, this list of conditions and the following disclaimer in the
++ *       documentation and/or other materials provided with the distribution.
++ *     * Neither the name of Freescale Semiconductor nor the
++ *       names of its contributors may be used to endorse or promote products
++ *       derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *------------------------------------------------------------------
++ */
++
++#include <sysdep.h>
++
++/*------------------------------------------------------------------
++ * int strlen(const char *src)
++ *
++ * Returns:
++ * length of string up to first null byte
++ *------------------------------------------------------------------
++ */
++
++	.file   "strlen.S"
++	.section        ".text"
++        /* check enough bytes to align the src pointer to a
++	 * doubleword boundary, and then run through the bytes
++	 * until a null is detected, adding up the length as we
++	 * go.
++	 */
++EALIGN (strlen, 5, 0)
++
++        /* All of the string functions use an algorithm for null
++	 * detection taken from the original libmoto:
++	 *
++	 * 1) load in a word
++	 * 2a) subtract 0x01010101 from the word.  This will cause
++	 * all bytes with a null to be 0xff (unless it is right
++	 * before another null, in which case it will be 0xfe)
++	 *
++	 * 3b) AND 0x80808080 with the complement of the word.
++	 * The resulting bytes will only have their high bit set
++	 * if the corresponding bit was 0 in the original word
++	 *
++	 * So now we (basically) have a word with the high bit of
++	 * any byte set which was between 0x81 and 0xff, or 0x00.
++	 * We also have a mask which will only select the high
++	 * bits of bytes which were between 0x00 and 0x7f.  There
++	 * is only one overlap:  a null byte (0x00).  If we now:
++	 *
++	 * 4) and the two results
++	 *
++	 * The result will only have 1s in the high bits of bytes
++	 * which had nulls.  With one exception.  If there is a
++	 * byte with 0x01 before a byte with 0x00, then that
++	 * byte, too, will have a 1 in the high bit.  However,
++	 * since this only happens when a byte with 0x00 occurs
++	 * in the word, this technique is useful for detecting if
++	 * there are any nulls in the word.
++	 */
++
++        /* Load constant 0x01010101 */
++        lis r11,0x0101
++        ori r11,r11,0x0101
++
++        /* r3 will be used for returning length, so lets move src
++	 * out of there to r10
++	 */
++        mr r10,r3
++
++        /* Get src's alignment (within a doubleword), and check
++	 * if it's zero
++	 */
++        andi. r3,r3,0x7
++
++        /* Load doubleword constant 0x01010101 */
++        evmergelo r12,r11,r11
++
++        /* Clear r0 out */
++        evsplati r0,0
++
++        /* get (the word alignment of r10) * 8 to shift a mask by the
++	 * number of bytes which are unused by r10
++	 * This is: clrlslwi r6,r10,30,3
++	 */
++        rlwinm r6, r10, 3, 27,28
++
++        /* Load doubleword constant 0x80808080 */
++        evslwi r11,r12,7
++
++        /* Skip out now if r10 was aligned. */
++        beq L(Aligned_Double)
++
++        subfic r6, r6, 32
++
++        /* start the mask with all Fs */
++        li r5, -1
++
++        /* Shift r8 by r6 to mask off preceding bytes */
++        slw r8, r5, r6
++
++        /* We want the result of r3+r10 to be a
++	 * doubleword-aligned value, so r3 will be -1*(r10)
++	 * alignment)
++	 */
++        neg r3,r3
++
++/* load the first words (on word boundaries) and process them,
++ * setting bits preceding the first byte to 1.
++ */
++
++        /* Grab the first doubleword of r10 */
++        evlddx r4,r3,r10
++
++        /* The loop is usually ahead by 16, and if we detect a
++	 * null, the exit code assumes that r3 is ahead by
++	 * 16, so we add 16 now, and can subtract 8 if there was
++	 * no null
++	 */
++        addi r3,r3,16
++
++        mtcrf 0x01,r10
++
++        evmergelo r0,r8,r0
++        cror 28,29,29
++
++        evmergelo r5,r5,r8
++
++        evsel r8,r5,r0,cr7
++
++        evsplati r0,0
++
++        /* Set the unwanted bytes of the source */
++        evor r4, r4, r8
++
++        /* Process fist doubleword with fun algorithm */
++        evsubfw r7, r12, r4
++        evandc r9, r11, r4
++        evand r9, r7, r9
++        evcmpgtu 1,r9,r0
++
++        /* Skip out if there was a null */
++        bt 6, L(found_null1)
++
++        /* There was no null; correct the length */
++        addi r3,r3,-8
++
++        /* loop through 2 doublewords at once in this page, until one of
++	 * these happens:
++	 * 1) A null byte is found in src
++	 * 2) the end of the page is reached
++	 * 
++	 * If 2 happens, then we finish processing the last doubleword in
++	 * the page, and if it checks out, we jump to the next one.  The
++	 * hope is that no small strings are going to cross page
++	 * boundaries.  For large strings, the hit should be minimal
++	 */
++
++        /* The main loop is unrolled, and software pipelined to
++	 * get as close to 2 IPC as possible.  This means it has
++	 * a prolog and epilog that need to be executed.  Prolog
++	 * is:
++	 * load, subtract
++	 */
++L(Aligned_Double):
++        /* Start figuring out how far to the next page */
++        not r8,r10
++        evlddx r4,r3,r10
++
++        /* Find the distance (in doublewords) from r10 to the end
++	 * of the page
++	 */
++        rlwinm r8,r8,29,23,31
++
++        /* Find out if this is the last double on the page */
++        addic. r6, r8,-1
++        addi r3,r3,8 /* increment the length */
++
++        /* start calculating now, since the loop needs this at
++	 * the beginning.
++	 */
++        evsubfw r7, r12, r4
++        beq L(aligned_double_loop_end)
++
++        /* decrement the counter to account for the first
++	 * iteration of the loop, and skip to the end if it turns
++	 * out we don't have enough doubles left for 1 iter.
++	 */
++        addic. r6,r6,-2
++        blt L(aligned_double_loop_end)
++        /* The loop */
++L(aligned_double_loop):
++        evandc r9, r11, r4
++        evlddx r5,r3,r10
++        evand r9,r9,r7
++        addi r3,r3,8
++        evcmpgtu 1, r9, r0
++        addic. r6,r6,-2
++        evsubfw r7,r12,r5
++        bt 6, L(found_null1)
++        evandc r9, r11, r5
++        evlddx r4,r3,r10
++        evand r9, r9, r7
++        addi r3,r3,8
++        evcmpgtu 5, r9, r0
++        bt 22, L(found_null2)
++        evsubfw r7,r12, r4
++        bge L(aligned_double_loop)
++
++        /* we exited the loop, we must be at the end of a page.
++	 * Finish the last one, and then see if we are done or
++	 * not.
++	 */
++L(aligned_double_loop_end):
++        evandc r9,r11,r4
++        evand r9,r9,r7
++        evcmpgtu 1,r9,r0
++
++        /* r3 has to be ahead by 16 in found_null, and is
++	 * only ahead by 8 right now, so we add 8 here
++	 */
++        addi r3,r3,8
++        bt 6, L(found_null1)
++
++        /* However, r3 needed to be only 8 ahead to load the
++	 * next doubleword, so take 8 away again
++	 */
++        addi r3,r3,-8
++
++        /* To make things nice, we finish off the remaining
++	 * doublewords here, so that the next loop has exactly
++	 * 512 iterations
++	 */
++        addi r7, r10, r3
++        andi. r7,r7,0xFFF
++        beq L(start_new_loop)
++L(find_page_end):
++        evlddx r4,r3,r10
++        addi r3,r3,16 /* overadjust */
++        evsubfw r7, r12, r4
++        evandc r9, r11, r4
++        evand r9, r7, r9
++        evcmpgtu 1, r9, r0
++        bt 6, L(found_null1)
++        addi r3,r3,-8 /* readjust */
++        addi r7,r10,r3
++        andi. r7,r7,0xFFF
++        bne L(find_page_end)
++
++L(start_new_loop):
++        /* It is now safe to proceed to the next page.  load the
++	 * counter with the number of doublewords in a page
++	 * (minus 4 to account for the first iteration)
++	 */
++        evlddx r4,r3,r10
++        li r6, 508
++
++        evsubfw r7, r12, r4
++        addi r3,r3,8
++        b L(aligned_double_loop)
++
++L(last_double_was_first):
++        evandc r9,r11,r4
++        evand r9,r9,r7
++        evcmpgtu 1,r9,r0
++        addi r3,r3,8 /* adjust */
++        bt 6,L(found_null1)
++        addi r3,r3,-8 /*readjust */
++        b L(start_new_loop)
++
++
++        /* The first doubleword had a null byte */
++L(found_null1):
++        /* Compensate for the fact that r3 is 16 ahead */
++        addi r3,r3,-12
++
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word, and subtract 4 from r3
++	 */
++        bf 4, L(find_null1)
++        evmergehi r4, r4, r4
++        addi r3,r3,-4
++L(find_null1):
++        rlwinm. r11,r4,0,0,7
++        beq L(finish1)
++        addi r3,r3,1
++        rlwinm. r11,r4,0,8,15
++        beq L(finish1)
++        addi r3,r3,1
++        rlwinm. r11,r4,0,16,23
++        beq L(finish1)
++        addi r3,r3,1
++
++L(finish1):
++        blr
++
++        /* The second doubleword had a null byte */
++L(found_null2):
++        /* Compensate for the fact that r3 is 16 ahead */
++        addi r3,r3,-12
++
++        /* If there was a null in the hi word, move that word
++	 * down into the lo word, and subtract 4 from r3
++	 */
++        bf 20, L(find_null2)
++        evmergehi r5, r5, r5
++        addi r3,r3,-4
++L(find_null2):
++        rlwinm. r11,r5,0,0,7
++        beq L(finish2)
++        addi r3,r3,1
++        rlwinm. r11,r5,0,8,15
++        beq L(finish2)
++        addi r3,r3,1
++        rlwinm. r11,r5,0,16,23
++        beq L(finish2)
++        addi r3,r3,1
++
++L(finish2):
++        blr
++
++END (strlen)
++libc_hidden_builtin_def (strlen)
+diff -Naur glibc-2.20/sysdeps/powerpc/powerpc32/e500/strcmp.S glibc-2.20-stcmp/sysdeps/powerpc/powerpc32/e500/strcmp.S
+--- glibc-2.20/sysdeps/powerpc/powerpc32/e500/strcmp.S	2015-08-27 04:27:44.436000785 -0500
++++ glibc-2.20-stcmp/sysdeps/powerpc/powerpc32/e500/strcmp.S	2015-08-27 04:33:45.417000790 -0500
+@@ -618,7 +618,7 @@
+         evandc r9,r11,r7
+         evand r9,r3,r9
+         evcmpgtu 5,r9,r0
+-        bt 22,L(found_early_null)
++        bt 21,L(found_early_null)
+ 
+         /* Now load the next 2 words of r4, and realign the
+ 	 * data to r10.  Then branch out if any of the bytes
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500/memcopy.h glibc-2.20-new/sysdeps/powerpc/powerpc32/e500/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-new/sysdeps/powerpc/powerpc32/e500/memcopy.h	2015-09-10 11:06:13.243187000 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
diff --git a/recipes-core/glibc/glibc-fsl/0009.glibc.fsl-mcpy-e500mc-e5500-e6500.patch b/recipes-core/glibc/glibc-fsl/0009.glibc.fsl-mcpy-e500mc-e5500-e6500.patch
new file mode 100644
index 0000000..97fc606
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0009.glibc.fsl-mcpy-e500mc-e5500-e6500.patch
@@ -0,0 +1,1191 @@
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500mc/memcopy.h glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e500mc/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500mc/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e500mc/memcopy.h	2015-09-23 14:26:35.273121001 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500mc/memcpy.S glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e500mc/memcpy.S
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e500mc/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e500mc/memcpy.S	2015-09-23 14:26:35.275121002 -0500
+@@ -0,0 +1,285 @@
++/* Optimized memcpy implementation for e500mc PowerPC.
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (memcpy, 5, 0)
++	cmplw	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 8, (optimal value TBD),
++	   but greater than zero copy byte-by-byte.  */
++	cmplwi	r5, 8
++	mr	r6, r3
++	blt	L(copy_bytes)
++	neg	r0, r4
++	andi.	r11, r0, 7
++	beq	L(src_aligned)
++	/* We have to align the src pointer by r11 bytes */
++	cmplwi	cr1, r11, 4
++	cmplwi	cr0, r11, 1
++	bgt	cr1, L(src_567)
++	ble	cr0, L(src_1)
++	/* 2, 3 or 4 bytes */
++	addi	r0, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r12, r4, r0
++	sth	r9, 0(r6)
++	sthx	r12, r6, r0
++	b	L(src_0)
++L(src_567):
++	addi	r0, r11, -4
++	lwz	r9, 0(r4)
++	lwzx	r12, r4, r0
++	stw	r9, 0(r6)
++	stwx	r12, r6, r0
++	b	L(src_0)
++L(src_1):
++	lbz	r0, 0(r4)
++	stb	r0, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(src_aligned):
++	cmplwi	7, r5, 63
++	ble	7, L(copy_remaining)
++	srwi	r11, r5, 6		/* No of 64 byte copy count.  */
++	rlwinm	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	rlwinm.	r0, r6, 0, 29, 31
++	mtctr	r11
++	bne	0, L(dst_naligned)
++L(copy_dalign):
++#ifndef _SOFT_FLOAT
++	lfd	0, 0(r4)
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	lfd	0, 32(r4)
++	lfd	1, 40(r4)
++	lfd	2, 48(r4)
++	lfd	3, 56(r4)
++	addi	r4, r4, 64
++	stfd	0, 32(r6)
++	stfd	1, 40(r6)
++	stfd	2, 48(r6)
++	stfd	3, 56(r6)
++#else
++	lwz	r0, 0(r4)
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++#endif
++	addi	r6, r6, 64
++	bdnz	L(copy_dalign)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	lwz	r0, 0(r4)		/* copy 32 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	addi	r4, r4, 32
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	lwz	r0, 0(r4)		/* copy 16 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	addi	r4, r4, 16
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	lwz	r0, 0(r4)		/* copy 8 bytes.  */
++	lwz	r7, 4(r4)
++	addi	r4, r4, 8
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmplwi	cr1, r5, 4
++	cmplwi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++L(dst_naligned):
++	rlwinm.	r0, r6, 0, 30, 31
++	beq	0, L(copy_dalign4)
++L(copy_dnalign):
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_dnalign)
++	b	L(copy_remaining)
++
++L(copy_dalign4):
++	lwz	r0, 0(r4)
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	lwz	r0, 32(r4)
++	lwz	r7, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 32(r6)
++	stw	r7, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r7, 52(r4)
++	lwz	r8, 56(r4)
++	lwz	r9, 60(r4)
++	addi	r4, r4, 64
++	stw	r0, 48(r6)
++	stw	r7, 52(r6)
++	stw	r8, 56(r6)
++	stw	r9, 60(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_dalign4)
++	b	L(copy_remaining)
++
++END (memcpy)
++libc_hidden_builtin_def (memcpy)
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e5500/memcopy.h glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e5500/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e5500/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e5500/memcopy.h	2015-09-23 14:26:35.275121002 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e5500/memcpy.S glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e5500/memcpy.S
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e5500/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e5500/memcpy.S	2015-09-23 14:26:35.275121002 -0500
+@@ -0,0 +1,252 @@
++/* Optimized memcpy implementation for e5500 32-bit PowerPC.
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (memcpy, 5, 0)
++	cmplw	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 8, (optimal value TBD),
++	   but greater than zero copy byte-by-byte.  */
++	cmplwi	r5, 8
++	mr	r6, r3
++	blt	L(copy_bytes)
++	neg	r0, r4
++	andi.	r11, r0, 3
++	beq	L(src_align4)
++	/* We have to align the src pointer by r11 bytes */
++	cmplwi	cr0, r11, 1
++	ble	L(src_1)
++	/* 2 or 3 bytes */
++	addi	r8, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r12, r4, r8
++	sth	r9, 0(r6)
++	sthx	r12, r6, r8
++	b	L(src_0)
++L(src_1):
++	lbz	r8, 0(r4)
++	stb	r8, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(src_align4):
++	/* Aligned by 4, now extend it to 16 */
++	cmplwi	7, r5, 63
++	ble	7, L(copy_remaining)
++	andi.	r10, r0, 15
++	beq	L(src_aligned16)
++	subf.	r10, r11, r10
++	beq	0, L(src_aligned16)
++	srwi	r11, r10, 2
++	subf	r5, r10, r5
++	mtctr	r11
++L(copy_salign16):
++	lwz	0, 0(r4)
++	addi	r4, r4, 4
++	stw	0, 0(r6)
++	addi	r6, r6, 4
++	bdnz	L(copy_salign16)
++L(src_aligned16):
++	srwi.	r11, r5, 6		/* No of 64 byte copy count.  */
++	beq	0, L(copy_remaining)
++	rlwinm	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	rlwinm.	r0, r6, 0, 29, 31
++	mtctr	r11
++	bne	0, L(copy_dnalign)
++L(copy_dalign):
++#ifndef _SOFT_FLOAT
++	lfd	0, 0(r4)		/* copy 64 bytes.  */
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	lfd	0, 32(r4)
++	lfd	1, 40(r4)
++	lfd	2, 48(r4)
++	lfd	3, 56(r4)
++	addi	r4, r4, 64
++	stfd	0, 32(r6)
++	stfd	1, 40(r6)
++	stfd	2, 48(r6)
++	stfd	3, 56(r6)
++	addi	r6, r6, 64
++#else
++	lwz	r0, 0(r4)
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	lwz	r0, 32(r4)
++	lwz	r7, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 32(r6)
++	stw	r7, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r7, 52(r4)
++	lwz	r8, 56(r4)
++	lwz	r9, 60(r4)
++	addi	r4, r4, 64
++	stw	r0, 48(r6)
++	stw	r7, 52(r6)
++	stw	r8, 56(r6)
++	stw	r9, 60(r6)
++	addi	r6, r6, 64
++#endif
++	bdnz	L(copy_dalign)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	lwz	r0, 0(r4)		/* copy 32 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	addi	r4, r4, 32
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	lwz	r0, 0(r4)		/* copy 16 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	addi	r4, r4, 16
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	lwz	r0, 0(r4)		/* copy 8 bytes.  */
++	lwz	r7, 4(r4)
++	addi	r4, r4, 8
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmplwi	cr1, r5, 4
++	cmplwi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++L(copy_dnalign):
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	lwz	r0, 32(r4)
++	lwz	r7, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 32(r6)
++	stw	r7, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r7, 52(r4)
++	lwz	r8, 56(r4)
++	lwz	r9, 60(r4)
++	addi	r4, r4, 64
++	stw	r0, 48(r6)
++	stw	r7, 52(r6)
++	stw	r8, 56(r6)
++	stw	r9, 60(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_dnalign)
++	b	L(copy_remaining)
++
++END (memcpy)
++libc_hidden_builtin_def (memcpy)
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e6500/memcopy.h glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e6500/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e6500/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e6500/memcopy.h	2015-09-23 14:26:35.275121002 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc32/e6500/memcpy.S glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e6500/memcpy.S
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc32/e6500/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc32/e6500/memcpy.S	2015-09-25 19:05:12.776925259 -0500
+@@ -0,0 +1,241 @@
++/* Optimized memcpy implementation for e6500 32-bit PowerPC.
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (memcpy, 5, 0)
++	cmplw	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 16, (optimal value TBD),
++	   but greater than zero copy byte-by-byte.  */
++	cmplwi	r5, 16
++	mr	r6, r3
++	blt	L(copy_remaining)
++	neg	r0, r3
++	andi.	r11, r0, 15
++	beq	L(dst_align16)
++	cmplwi	cr1, r11, 8
++	ble	cr1, L(src_1_8)
++	addi	r0, r11, -8
++	addi	r10, r11, -4
++	lwz	r9, 0(r4)
++	lwz	r8, 4(r4)
++	lwzx	r7, r4, r0
++	lwzx	r6, r4, r10
++	stw	r9, 0(r3)
++	stw	r8, 4(r3)
++	stwx	r7, r3, r0
++	stwx	r6, r3, r10
++	mr	r6, r3
++	b	L(src_0)
++L(src_1_8):
++	cmplwi	cr1, r11, 4
++	cmplwi	cr0, r11, 1
++	bgt	cr1, L(src_567)
++	ble	cr0, L(src_1)
++	/* 2, 3 or 4 bytes */
++	addi	r0, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r8, r4, r0
++	sth	r9, 0(r6)
++	sthx	r8, r6, r0
++	b	L(src_0)
++L(src_567):
++	addi	r0, r11, -4
++	lwz	r9, 0(r4)
++	lwzx	r8, r4, r0
++	stw	r9, 0(r6)
++	stwx	r8, r6, r0
++	b	L(src_0)
++L(src_1):
++	lbz	r0, 0(r4)
++	stb	r0, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(dst_align16):
++	cmplwi	7, r5, 63
++	ble	7, L(copy_remaining)
++	srwi	r11, r5, 6		/* No of 64 byte copy count.  */
++	rlwinm	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	rlwinm.	r0, r4, 0, 28, 31
++	mtctr	r11
++	li	r7, 16
++	li	r8, 32
++	li	r9, 48
++	bne	0, L(src_naligned)
++L(copy_salign16):
++	lvx	v14, 0, r4		/* copy 64 bytes.  */
++	lvx	v15, r7, r4
++	lvx	v16, r8, r4
++	lvx	v17, r9, r4
++	addi	r4, r4, 64
++	stvx	v14, 0, r6
++	stvx	v15, r7, r6
++	stvx	v16, r8, r6
++	stvx	v17, r9, r6
++	addi	r6, r6, 64
++	bdnz	L(copy_salign16)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++
++	lwz	r0, 0(r4)		/* copy 32 bytes */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++
++	lwz	r0, 16(r4)
++	lwz	r7, 20(r4)
++	lwz	r8, 24(r4)
++	lwz	r9, 28(r4)
++	addi	r4, r4, 32
++
++	stw	r0, 16(r6)
++	stw	r7, 20(r6)
++	stw	r8, 24(r6)
++	stw	r9, 28(r6)
++	addi r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	lwz	r0, 0(r4)		/* copy 16 bytes */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++
++	addi	r4, r4, 16
++
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	lwz	r0, 0(r4)		/* copy 8 bytes */
++	lwz	r7, 4(r4)
++	addi	r4, r4, 8
++
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmplwi	cr1, r5, 4
++	cmplwi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++L(src_naligned):
++#ifndef _SOFT_FLOAT
++	rlwinm.	r0, r4, 0, 29, 31
++	beq	0, L(copy_salign8)
++#endif
++L(copy_snalign):			/* copy 64 bytes.  */
++	lvx	v0, 0, r4		/* load MSQ.  */
++	lvsl	v18, 0, r4		/* set permute control vector.  */
++	lvx	v19, r7, r4		/* load LSQ.  */
++	vperm	v14, v0, v19, v18	/* align the data.  */
++	lvx	v0, r7, r4		/* load MSQ.  */
++	lvsl	v18, r7, r4		/* set permute control vector.  */
++	lvx	v19, r8, r4		/* load LSQ.  */
++	vperm	v15, v0, v19, v18	/* align the data.  */
++	lvx	v0, r8, r4		/* load MSQ.  */
++	lvsl	v18, r8, r4		/* set permute control vector.  */
++	lvx	v19, r9, r4		/* load LSQ.  */
++	vperm	v16, v0, v19, v18	/* align the data.  */
++	lvx	v0, r9, r4		/* load MSQ.  */
++	lvsl	v18, r9, r4		/* set permute control vector.  */
++	addi	r4, r4, 64
++	lvx	v19, 0, r4		/* load LSQ.  */
++	vperm	v17, v0, v19, v18	/* align the data.  */
++	stvx	v14, 0, r6
++	stvx	v15, r7, r6
++	stvx	v16, r8, r6
++	stvx	v17, r9, r6
++	addi	r6, r6, 64
++	bdnz	L(copy_snalign)
++	b	L(copy_remaining)
++
++#ifndef _SOFT_FLOAT
++L(copy_salign8):
++	lfd	0, 0(r4)		/* copy 64 bytes.  */
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	lfd	0, 32(r4)
++	lfd	1, 40(r4)
++	lfd	2, 48(r4)
++	lfd	3, 56(r4)
++	addi	r4, r4, 64
++	stfd	0, 32(r6)
++	stfd	1, 40(r6)
++	stfd	2, 48(r6)
++	stfd	3, 56(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_salign8)
++	b	L(copy_remaining)
++#endif
++
++END (memcpy)
++libc_hidden_builtin_def (memcpy)
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc64/e5500/memcopy.h glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e5500/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc64/e5500/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e5500/memcopy.h	2015-09-23 14:26:35.275121002 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc64/e5500/memcpy.S glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e5500/memcpy.S
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc64/e5500/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e5500/memcpy.S	2015-09-23 14:26:35.276121001 -0500
+@@ -0,0 +1,155 @@
++/* Optimized memcpy implementation for e5500 64-bit PowerPC.
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (memcpy, 5, 0)
++	CALL_MCOUNT 3
++	cmpld	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 8 but greater than zero,
++	   copy byte-by-byte.  */
++	cmpldi	r5, 8
++	mr	r6, r3
++	blt	L(copy_bytes)
++	neg	r0, r4
++	andi.	r11, r0, 7
++	beq	L(src_aligned)
++	/* We have to align the src pointer by r11 bytes */
++	cmplwi	cr1, r11, 4
++	cmplwi	cr0, r11, 1
++	bgt	cr1, L(src_567)
++	ble	cr0, L(src_1)
++	/* 2, 3 or 4 bytes */
++	addi	r0, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r12, r4, r0
++	sth	r9, 0(r6)
++	sthx	r12, r6, r0
++	b	L(src_0)
++L(src_567):
++	addi	r0, r11, -4
++	lwz	r9, 0(r4)
++	lwzx	r12, r4, r0
++	stw	r9, 0(r6)
++	stwx	r12, r6, r0
++	b	L(src_0)
++L(src_1):
++	lbz	r0, 0(r4)
++	stb	r0, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(src_aligned):
++	cmpldi	7, r5, 63
++	ble	7, L(copy_remaining)
++	srwi	r11, r5, 6		/* No of 64 byte copy count.  */
++	rlwinm.	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	mtctr	r11
++L(copy_salign):
++	ld	r0, 0(r4)		/* 64-byte copy.  */
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	ld	r0, 32(r4)
++	ld	r7, 40(r4)
++	ld	r8, 48(r4)
++	ld	r9, 56(r4)
++	addi	r4, r4, 64
++	std	r0, 32(r6)
++	std	r7, 40(r6)
++	std	r8, 48(r6)
++	std	r9, 56(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_salign)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	ld	r0, 0(r4)		/* copy 32 bytes.  */
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	addi	r4, r4, 32
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	ld	r7, 0(r4)		/* copy 16 bytes.  */
++	ld	r8, 8(r4)
++	addi	r4, r4, 16
++	std	r7, 0(r6)
++	std	r8, 8(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	ld	r7, 0(r4)		/* copy 8 bytes.  */
++	addi	r4, r4, 8
++	std	r7, 0(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmpldi	cr1, r5, 4
++	cmpldi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++END_GEN_TB (memcpy,TB_TOCLESS)
++libc_hidden_builtin_def (memcpy)
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc64/e6500/memcopy.h glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e6500/memcopy.h
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc64/e6500/memcopy.h	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e6500/memcopy.h	2015-09-23 14:26:35.276121001 -0500
+@@ -0,0 +1 @@
++#include "../../powerpc32/power4/memcopy.h"
+diff -ruN glibc-2.20-orig/sysdeps/powerpc/powerpc64/e6500/memcpy.S glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e6500/memcpy.S
+--- glibc-2.20-orig/sysdeps/powerpc/powerpc64/e6500/memcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-memcpy-fixed/sysdeps/powerpc/powerpc64/e6500/memcpy.S	2015-09-25 19:05:35.132924985 -0500
+@@ -0,0 +1,213 @@
++/* Optimized memcpy implementation for e6500 64-bit PowerPC.
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (memcpy, 5, 0)
++	CALL_MCOUNT 3
++	cmpld	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 16 but greater than zero,
++	   copy byte-by-byte.  */
++	cmpldi	r5, 16
++	mr	r6, r3
++	ble	L(copy_remaining)
++	neg	r0, r3
++	andi.	r11, r0, 15
++	beq	L(dst_align)
++ 	/* We have to align the src pointer by r11 bytes */
++	cmpldi	cr1, r11, 8
++	ble	cr1, L(src_1_8)
++	/* Take care of 8 bytes at once */
++	addi	r0, r11, -8
++	ld	r9, 0(r4)
++	ldx	r8, r4, r0
++	std	r9, 0(r6)
++	stdx	r8, r6, r0
++	b	L(src_0)
++L(src_1_8):
++	cmpldi	cr1, r11, 4
++	cmpldi	cr0, r11, 1
++	bgt	cr1, L(src_567)
++	ble	cr0, L(src_1)
++	/* 2, 3 or 4 bytes */
++	addi	r0, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r8, r4, r0
++	sth	r9, 0(r6)
++	sthx	r8, r6, r0
++	b	L(src_0)
++L(src_567):
++	addi	r0, r11, -4
++	lwz	r9, 0(r4)
++	lwzx	r8, r4, r0
++	stw	r9, 0(r6)
++	stwx	r8, r6, r0
++	b	L(src_0)
++L(src_1):
++	lbz	r0, 0(r4)
++	stb	r0, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(dst_align):
++	cmpldi	7, r5, 63
++	ble	7, L(copy_remaining)
++	srwi	r11, r5, 6		/* No of 64 byte copy count.  */
++	rlwinm	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	rlwinm.	r0, r4, 0, 28, 31
++	mtctr	r11
++	li	r7, 16
++	li	r8, 32
++	li	r9, 48
++	bne	0, L(src_naligned)
++L(copy_salign):
++	lvx	v14, 0, r4
++	lvx	v15, r7, r4
++	lvx	v16, r8, r4
++	lvx	v17, r9, r4
++	addi	r4, r4, 64
++	stvx	v14, 0, r6
++	stvx	v15, r7, r6
++	stvx	v16, r8, r6
++	stvx	v17, r9, r6
++	addi	r6, r6, 64
++	bdnz	L(copy_salign)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	ld	r0, 0(r4)		/* copy 32 bytes.  */
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	addi	r4, r4, 32
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	ld	r7, 0(r4)		/* copy 16 bytes.  */
++	ld	r8, 8(r4)
++	addi	r4, r4, 16
++	std	r7, 0(r6)
++	std	r8, 8(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	ld	r7, 0(r4)		/* copy 8 bytes.  */
++	addi	r4, r4, 8
++	std	r7, 0(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmpldi	cr1, r5, 4
++	cmpldi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++L(src_naligned):
++	rlwinm.	r0, r4, 0, 29, 31
++	beq	0, L(copy_salign8)
++L(copy_snalign):
++	lvx	v0, 0, r4		/* load MSQ.  */
++	lvsl	v18, 0, r4		/* set permute control vector.  */
++	lvx	v19, r7, r4		/* load LSQ.  */
++	vperm	v14, v0, v19, v18	/* align the data.  */
++	lvx	v0, r7, r4		/* load MSQ.  */
++	lvsl	v18, r7, r4		/* set permute control vector.  */
++	lvx	v19, r8, r4		/* load LSQ.  */
++	vperm	v15, v0, v19, v18	/* align the data.  */
++	lvx	v0, r8, r4		/* load MSQ.  */
++	lvsl	v18, r8, r4		/* set permute control vector.  */
++	lvx	v19, r9, r4		/* load LSQ.  */
++	vperm	v16, v0, v19, v18	/* align the data.  */
++	lvx	v0, r9, r4		/* load MSQ.  */
++	lvsl	v18, r9, r4		/* set permute control vector.  */
++	addi	r4, r4, 64
++	lvx	v19, 0, r4		/* load LSQ.  */
++	vperm	v17, v0, v19, v18	/* align the data.  */
++	stvx	v14, 0, r6
++	stvx	v15, r7, r6
++	stvx	v16, r8, r6
++	stvx	v17, r9, r6
++	addi	r6, r6, 64
++	bdnz	L(copy_snalign)
++	b	L(copy_remaining)
++
++L(copy_salign8):
++	ld	r0, 0(r4)
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	ld	r0, 32(r4)
++	ld	r7, 40(r4)
++	ld	r8, 48(r4)
++	ld	r9, 56(r4)
++	addi	r4, r4, 64
++	std	r0, 32(r6)
++	std	r7, 40(r6)
++	std	r8, 48(r6)
++	std	r9, 56(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_salign8)
++	b	L(copy_remaining)
++
++END_GEN_TB (memcpy,TB_TOCLESS)
++libc_hidden_builtin_def (memcpy)
diff --git a/recipes-core/glibc/glibc-fsl/0010.glibc.fsl-e500mc-e5500-mset.patch b/recipes-core/glibc/glibc-fsl/0010.glibc.fsl-e500mc-e5500-mset.patch
new file mode 100755
index 0000000..477c93a
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0010.glibc.fsl-e500mc-e5500-mset.patch
@@ -0,0 +1,1337 @@
+# Problem Statement:
+  Implement target specific optimized memset routine for e500mc,
+  e5500 32 bit & 64-bit target
+
+# Owned by:
+  Ram
+
+# Actions:
+  * For memset of non zero values, cache line size [64] bytes are
+    set at one go per iteration and along with this 'dcbzl' cache
+    management instruction is used to generate higher performance.
+
+  * For memset of zero value, cache management instruction 'dcbzl'
+    is used to generate higher performance.
+
+
+diff -Naur libc/sysdeps/powerpc/powerpc32/e500mc/memset.S libc_release/sysdeps/powerpc/powerpc32/e500mc/memset.S
+--- libc/sysdeps/powerpc/powerpc32/e500mc/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ libc_release/sysdeps/powerpc/powerpc32/e500mc/memset.S	2015-06-29 07:31:28.885952000 -0500
+@@ -0,0 +1,415 @@
++/* Optimized memset implementation for PowerPC e500mc target.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++/* This implementation is based on 'powerpc/powerpc32/memset.S'.  */
++
++/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
++   Returns 's'.
++
++   The memset is done in three sizes: byte (8 bits), word (32 bits),
++   32-byte blocks (256 bits) and __cache_line_size (512 bits).  There
++   is a special case for setting whole cache lines to 0, which takes
++   advantage of the dcbzl instruction.  */
++
++#include <sysdep.h>
++
++	.section ".text"
++EALIGN (memset, 6, 1)
++
++#define rTMP	r0
++#define rMEMP0	r3	/* original value of 1st arg.  */
++#define rCHR	r4	/* char to set in each byte.  */
++#define rLEN	r5	/* length of region to set.  */
++#define rMEMP	r6	/* address at which we are storing.  */
++#define rALIGN	r7	/* number of bytes we are setting
++			   now (when aligning).  */
++#define rTMP2	r8
++#define rMEMP2	r9
++#define rCNT	r0
++
++#define rPOS64	r10	/* constant +64 for clearing with dcbz.  */
++#define rCLS	r11
++#define rGOT	r12
++
++#ifndef _SOFT_FLOAT
++#define rFLD	fp0	/* float double register with char(s) to set
++			   in each byte.  */
++#endif
++
++	/* For sizes <= 4 bytes, do byte by byte set.  */
++	cmplwi	cr1, rLEN, 4
++	mr	rMEMP, rMEMP0
++	ble	cr1, L(le_4bytes)
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	andi.	rALIGN, rMEMP, 3
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	beq	L(4b_aligned)
++	/* By now, we know that there are at least 5 bytes to memset
++	   and the destination address is not word aligned.  Do not bother
++	   about non-alignment and do a one word store at once and word
++	   align the destination address.  The penalty for non-aligned
++	   store is less compared to the if-else checks and related code.  */
++	subfic	rALIGN, rALIGN, 4
++	stw	rCHR, 0(rMEMP0)
++	sub	rLEN, rLEN, rALIGN
++	add	rMEMP, rMEMP, rALIGN
++L(4b_aligned):
++	/* For sizes < 32 bytes, do it in a combination of word/half word/byte
++	   stores.  */
++	srwi.	rALIGN, rLEN, 5
++	beq	L(lt_32bytes)
++	/* For sizes where 128 > size >= 32, do the memset in a loop where
++	   32 bytes are set per each iteration.  For this size range, the
++	   overhead in getting the destination address cache aligned is more
++	   compared to the advantage of setting cache line size (64) bytes
++	   per iteration.  */
++	srwi.	rTMP2, rALIGN, 2
++	bne	L(set_cache_lines)
++	mtctr	rALIGN
++	/* By now, we know that there are at least 32 bytes to memset.  Hence
++	   no need to check for zero loop count.  */
++L(32b_loop):
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	addi	rMEMP, rMEMP, 32
++	bdnz	L(32b_loop)
++	rlwinm.	rLEN, rLEN, 0, 27, 31
++	beqlr
++	b	L(lt_32bytes)
++
++L(set_cache_lines):
++	neg	rTMP2, rMEMP
++	andi.	rALIGN, rTMP2, 60
++	beq	L(cache_aligned)
++	add	rMEMP, rMEMP, rALIGN
++	/* The cr6 and cr7 fields together will hold the number of bytes to
++	   set to make the destination address cache line aligned.  */
++	mtcrf	0x03, rALIGN
++	sub	rLEN, rLEN, rALIGN
++	cmplwi	cr1, rALIGN, 32
++	mr	rMEMP2, rMEMP
++	bf	cr6*4+3, L(a1)
++	stw	rCHR, -4(rMEMP2)
++	stw	rCHR, -8(rMEMP2)
++	stw	rCHR, -12(rMEMP2)
++	stwu	rCHR, -16(rMEMP2)
++L(a1):
++	blt	cr1, L(a2)
++	stw	rCHR, -4(rMEMP2)
++	stw	rCHR, -8(rMEMP2)
++	stw	rCHR, -12(rMEMP2)
++	stw	rCHR, -16(rMEMP2)
++	stw	rCHR, -20(rMEMP2)
++	stw	rCHR, -24(rMEMP2)
++	stw	rCHR, -28(rMEMP2)
++	stwu	rCHR, -32(rMEMP2)
++L(a2):
++	bf	cr7*4, L(a3)
++	stw	rCHR, -4(rMEMP2)
++	stwu	rCHR, -8(rMEMP2)
++L(a3):
++	bf	cr7*4+1, L(cache_aligned)
++	stw	rCHR, -4(rMEMP2)
++
++L(cache_aligned):
++#ifdef SHARED
++	mflr	rTMP
++	/* Establishes GOT addressability so we can load
++	   __cache_line_size from static.  This value was set from the aux
++	   vector during startup.  */
++	SETUP_GOT_ACCESS(rGOT, got_label_1)
++	addis	rGOT, rGOT, __cache_line_size-got_label_1 at ha
++	lwz	rCLS, __cache_line_size-got_label_1 at l(rGOT)
++	mtlr	rTMP
++#else
++	/* Load __cache_line_size from static.  This value was set from the
++	   aux vector during startup.  */
++	lis	rCLS, __cache_line_size at ha
++	lwz	rCLS, __cache_line_size at l(rCLS)
++#endif
++	/* If the cache line size is set and is 64 bytes, do the memset using
++	   data cache block instructions i.e. dcbz etc.  Otherwise do not use
++	   the dcb* instructions.  */
++	cmplwi	cr5, rCLS, 64
++	cmplwi	cr1, rCHR, 0
++	bne	cr5, L(nondcbz_loop_start)
++	beq	cr1, L(z_loop_start)
++L(nz_loop_start):
++#ifndef _SOFT_FLOAT
++	stw	rCHR, 0(rMEMP)
++	srwi	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	stw	rCHR, 4(rMEMP)
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* n = n % CACHE_LINE_SIZE.  */
++	subic.	rCNT, rALIGN, 4
++	lfd	rFLD, 0(rMEMP)
++#else
++	srwi	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* n = n % CACHE_LINE_SIZE.  */
++	subic.	rCNT, rALIGN, 4
++#endif
++	li	rPOS64, 64
++	ble	L(nz_loop_big_done)
++	mtctr	rCNT
++L(nz_loop_big):
++	dcbzl	rPOS64, rMEMP
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++	stfd	rFLD, 32(rMEMP)
++	stfd	rFLD, 40(rMEMP)
++	stfd	rFLD, 48(rMEMP)
++	stfd	rFLD, 56(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++#endif
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(nz_loop_big)
++	li	rALIGN, 4
++L(nz_loop_big_done):
++	cmplwi	cr1, rALIGN, 0
++	beq	cr1, L(nz_loop_small_done)
++	mtctr	rALIGN
++L(nz_loop_small):
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++	stfd	rFLD, 32(rMEMP)
++	stfd	rFLD, 40(rMEMP)
++	stfd	rFLD, 48(rMEMP)
++	stfd	rFLD, 56(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++#endif
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(nz_loop_small)
++L(nz_loop_small_done):
++	srwi.	rTMP2, rLEN, 5
++	beq	L(lt_32bytes)
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++#endif
++	andi.	rLEN, rLEN, 31
++	addi	rMEMP, rMEMP, 32
++	beqlr
++	b	L(lt_32bytes)
++
++	.p2align 6
++L(nondcbz_loop_start):
++	srwi.	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	beq	L(nondcbz_loop_done)
++#ifndef _SOFT_FLOAT
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* n = n % CACHE_LINE_SIZE.  */
++	lfd	rFLD, 0(rMEMP)
++#else
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* n = n % CACHE_LINE_SIZE.  */
++#endif
++	mtctr	rALIGN
++L(nondcbz_loop):
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++	stfd	rFLD, 32(rMEMP)
++	stfd	rFLD, 40(rMEMP)
++	stfd	rFLD, 48(rMEMP)
++	stfd	rFLD, 56(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++#endif
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(nondcbz_loop)
++L(nondcbz_loop_done):
++	srwi.	rTMP2, rLEN, 5
++	beq	L(lt_32bytes)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	andi.	rLEN, rLEN, 31
++	addi	rMEMP, rMEMP, 32
++	beqlr
++	b	L(lt_32bytes)
++
++	/* Memset of 4 bytes or less.  */
++	.p2align 6
++L(le_4bytes):
++	cmplwi	cr5, rLEN, 0
++	beqlr	cr5
++	cmplwi	cr1, rLEN, 1
++	stb	rCHR, 0(rMEMP)
++	beqlr	cr1
++	cmplwi	cr5, rLEN, 2
++	stb	rCHR, 1(rMEMP)
++	beqlr	cr5
++	cmplwi	cr1, rLEN, 4
++	stb	rCHR, 2(rMEMP)
++	bnelr	cr1
++	stb	rCHR, 3(rMEMP)
++	blr
++
++	/* Clear cache lines of memory in 128-byte chunks per iteration
++	   using the data cache block zero line instruction.  */
++	.p2align 6
++L(z_loop_start):
++	cmplwi	cr1, rLEN, 128
++	li	rPOS64, 64
++L(z_loop):
++	blt	cr1, L(z_loop_done)
++	addi	rLEN, rLEN, -128
++	dcbzl	0, rMEMP
++	dcbzl	rPOS64, rMEMP
++	cmplwi	cr1, rLEN, 128
++	addi	rMEMP, rMEMP, 128
++	b	L(z_loop)
++L(z_loop_done):
++	cmplwi	cr5, rLEN, 64
++	andi.	rTMP2, rLEN, 32
++	blt	cr5, L(z0)
++	dcbzl	0, rMEMP
++	addi	rLEN, rLEN, -64
++	addi	rMEMP, rMEMP, 64
++L(z0):
++	beq	L(lt_32bytes)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	andi.	rLEN, rLEN, 31
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	addi	rMEMP, rMEMP, 32
++	beqlr
++
++	/* Memset of 0-31 bytes.  */
++L(lt_32bytes):
++	mtcrf	0x01, rLEN
++	cmplwi	cr1, rLEN, 16
++	add	rMEMP, rMEMP, rLEN
++	bt	31, L(b31t)
++	bt	30, L(b30t)
++L(b30f):
++	bt	29, L(b29t)
++L(b29f):
++	bge	cr1, L(b27t)
++	bflr	28
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++L(b31t):
++	stbu	rCHR, -1(rMEMP)
++	bf	30, L(b30f)
++L(b30t):
++	sthu	rCHR, -2(rMEMP)
++	bf	29, L(b29f)
++L(b29t):
++	stwu	rCHR, -4(rMEMP)
++	blt	cr1, L(b27f)
++L(b27t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	stw	rCHR, -12(rMEMP)
++	stwu	rCHR, -16(rMEMP)
++L(b27f):
++	bflr	28
++L(b28t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++
++END (memset)
++libc_hidden_builtin_def (memset)
++
+diff -Naur libc/sysdeps/powerpc/powerpc32/e5500/memset.S libc_release/sysdeps/powerpc/powerpc32/e5500/memset.S
+--- libc/sysdeps/powerpc/powerpc32/e5500/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ libc_release/sysdeps/powerpc/powerpc32/e5500/memset.S	2015-06-29 09:33:17.564951999 -0500
+@@ -0,0 +1,477 @@
++/* Optimized memset implementation for PowerPC e5500 32-bit target.
++   Copyright (C) 2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++/* This implementation is based on 'powerpc/powerpc32/memset.S'.  */
++
++/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
++   Returns 's'.
++
++   The memset is done in different sizes: byte (8 bits), word (32 bits),
++   32-byte blocks (256 bits) and __cache_line_size (512 bits).  There
++   is a special case for setting whole cache lines to 0, which takes
++   advantage of the dcbzl instruction.  */
++
++#include <sysdep.h>
++
++	.section ".text"
++EALIGN (memset, 6, 1)
++
++#define rTMP	r0
++#define rMEMP0	r3	/* original value of 1st arg.  */
++#define rCHR	r4	/* char to set in each byte.  */
++#define rLEN	r5	/* length of region to set.  */
++#define rMEMP	r6	/* address at which we are storing.  */
++#define rALIGN	r7	/* number of bytes we are setting
++			   now (when aligning).  */
++#define rTMP2	r8
++#define rMEMP2	r9
++#define rCNT	r0
++#define rNEG128	r10	/* constant -128 for clearing with dcbzl.  */
++#define rNEG64	r11	/* constant -64 for clearing with dcbzl.  */
++#define rCLS	r11
++#define rGOT	r12
++#ifndef _SOFT_FLOAT
++#define rFLD	fp0	/* float double register with char(s) to set
++			   in each byte.  */
++#endif
++
++	cmplwi	cr1, rLEN, 7
++	mtcrf	0x1, rLEN
++	add	rMEMP2, rMEMP0, rLEN
++	ble	cr1, L(Upto7Bytes)
++	cmplwi	cr5, rLEN, 31
++	rlwimi	rCHR, rCHR, 8, 16, 23	/* Replicate byte to halfword.  */
++	rlwimi	rCHR, rCHR, 16, 0, 15	/* Replicate half word to word.  */
++	ble	cr5, L(Upto31Bytes)
++	andi.	rALIGN, rMEMP0, 3
++	cmplwi	cr1, rCHR, 0
++	beq	L(wAligned)
++	/* By now, we know that there are at least 4 bytes to memset
++	   and the destination address is not word aligned.  Do not bother
++	   about non-alignment and do a one word store at once and word
++	   align the destination address.  The penalty for non-aligned
++	   store is less compared to the if-else checks and related code.  */
++	subfic	rALIGN, rALIGN, 4
++	sub	rLEN, rLEN, rALIGN
++	stw	rCHR, 0(rMEMP0)
++L(wAligned):
++	/* For '128 > n >= 32' for zero fill value and for '256 > n >= 32'
++	   for non-zero fill value, the overhead in getting the destination
++	   address cache line aligned is more compared to the advantage of
++	   caching data and/or using the dcbzl instruction.  Hence, for
++	   those sizes, do it without using any explicit cache mechanism.  */
++	srwi.	rTMP, rLEN, 7
++	add	rMEMP, rMEMP0, rALIGN
++	beq	L(Upto255Bytes)
++	srwi.	rTMP, rLEN, 8
++	beq	cr1, L(SetCacheLines)
++	bne	L(SetCacheLines)
++L(Upto255Bytes):
++	mtcrf	0x2, rLEN
++	bf	cr6*4+2, L(wA64b)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	addi	rMEMP, rMEMP, 32
++L(wA64b):
++	rlwinm.	rLEN, rLEN, 0, 27, 31
++	bf	cr6*4+1, L(wA128b)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++	addi	rMEMP, rMEMP, 64
++L(wA128b):
++	bf	cr6*4, L(tail31Bytes)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++	stw	rCHR, 64(rMEMP)
++	stw	rCHR, 68(rMEMP)
++	stw	rCHR, 72(rMEMP)
++	stw	rCHR, 76(rMEMP)
++	stw	rCHR, 80(rMEMP)
++	stw	rCHR, 84(rMEMP)
++	stw	rCHR, 88(rMEMP)
++	stw	rCHR, 92(rMEMP)
++	stw	rCHR, 96(rMEMP)
++	stw	rCHR, 100(rMEMP)
++	stw	rCHR, 104(rMEMP)
++	stw	rCHR, 108(rMEMP)
++	stw	rCHR, 112(rMEMP)
++	stw	rCHR, 116(rMEMP)
++	stw	rCHR, 120(rMEMP)
++	stw	rCHR, 124(rMEMP)
++	b	L(tail31Bytes)
++
++L(SetCacheLines):
++	neg	rTMP2, rMEMP
++	andi.	rALIGN, rTMP2, 60
++	beq	L(cAligned)
++	mtcrf	0x02, rALIGN
++	add	rTMP2, rMEMP, rALIGN
++	rlwinm	rTMP, rALIGN, 0, 0, 29
++	bf	cr6*4+3, L(a1)
++	stw	rCHR, -4(rTMP2)
++	stw	rCHR, -8(rTMP2)
++	stw	rCHR, -12(rTMP2)
++	stwu	rCHR, -16(rTMP2)
++L(a1):
++	mtcrf	0x1, rALIGN
++	bf	cr6*4+2, L(a2)
++	stw	rCHR, -4(rTMP2)
++	stw	rCHR, -8(rTMP2)
++	stw	rCHR, -12(rTMP2)
++	stw	rCHR, -16(rTMP2)
++	stw	rCHR, -20(rTMP2)
++	stw	rCHR, -24(rTMP2)
++	stw	rCHR, -28(rTMP2)
++	stwu	rCHR, -32(rTMP2)
++L(a2):
++	sub	rLEN, rLEN, rTMP
++	bf	cr7*4, L(a3)
++	stw	rCHR, -4(rTMP2)
++	stwu	rCHR, -8(rTMP2)
++L(a3):
++	bf	cr7*4+1, L(cAligned)
++	stw	rCHR, -4(rTMP2)
++
++L(cAligned):
++#ifdef SHARED
++	mflr	rTMP
++	/* Establishes GOT addressability so we can load
++	   __cache_line_size from static.  This value was set from the aux
++	   vector during startup.  */
++	SETUP_GOT_ACCESS(rGOT, got_label_1)
++	addis	rGOT, rGOT, __cache_line_size-got_label_1 at ha
++	lwz	rCLS, __cache_line_size-got_label_1 at l(rGOT)
++	mtlr	rTMP
++#else
++	/* Load __cache_line_size from static.  This value was set from the
++	   aux vector during startup.  */
++	lis	rCLS, __cache_line_size at ha
++	lwz	rCLS, __cache_line_size at l(rCLS)
++#endif
++	/* If the cache line size is set and is 64 bytes, do the memset using
++	   data cache block instructions i.e. dcbzl etc.  Otherwise do not use
++	   the dcb* instructions.  */
++	cmplwi	cr5, rCLS, 64
++	add	rMEMP, rMEMP, rALIGN
++	rlwinm	rTMP2, rLEN, 0, 0, 25
++	bne	cr5, L(nondcbzLoopStart)
++	add	rMEMP, rMEMP, rTMP2
++	beq	cr1, L(zLoopStart)
++L(nzLoopStart):
++#ifndef _SOFT_FLOAT
++	srwi	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	subic.	rCNT, rALIGN, 32
++	mtcrf	0x2, rLEN
++	lfd	rFLD, -8(rMEMP)
++	ble	L(nzLoopBigDone)
++	li	rNEG128, -128
++	mtctr	rCNT
++#else
++	srwi	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	subic.	rCNT, rALIGN, 32
++	mtcrf	0x2, rLEN
++	ble	L(nzLoopBigDone)
++	li	rNEG128, -128
++	mtctr	rCNT
++#endif
++L(nzLoopBig):
++	dcbzl	rNEG128, rMEMP
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, -8(rMEMP)
++	stfd	rFLD, -16(rMEMP)
++	stfd	rFLD, -24(rMEMP)
++	stfd	rFLD, -32(rMEMP)
++	stfd	rFLD, -40(rMEMP)
++	stfd	rFLD, -48(rMEMP)
++	stfd	rFLD, -56(rMEMP)
++	stfdu	rFLD, -64(rMEMP)
++#else
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	stw	rCHR, -12(rMEMP)
++	stw	rCHR, -16(rMEMP)
++	stw	rCHR, -20(rMEMP)
++	stw	rCHR, -24(rMEMP)
++	stw	rCHR, -28(rMEMP)
++	stw	rCHR, -32(rMEMP)
++	stw	rCHR, -36(rMEMP)
++	stw	rCHR, -40(rMEMP)
++	stw	rCHR, -44(rMEMP)
++	stw	rCHR, -48(rMEMP)
++	stw	rCHR, -52(rMEMP)
++	stw	rCHR, -56(rMEMP)
++	stw	rCHR, -60(rMEMP)
++	stwu	rCHR, -64(rMEMP)
++#endif
++	bdnz	L(nzLoopBig)
++	li	rALIGN, 32
++L(nzLoopBigDone):
++	cmplwi	cr1, rALIGN, 0
++	beq	cr1, L(nzLoopSmallDone)
++	mtctr	rALIGN
++L(nzLoopSmall):
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, -8(rMEMP)
++	stfd	rFLD, -16(rMEMP)
++	stfd	rFLD, -24(rMEMP)
++	stfd	rFLD, -32(rMEMP)
++	stfd	rFLD, -40(rMEMP)
++	stfd	rFLD, -48(rMEMP)
++	stfd	rFLD, -56(rMEMP)
++	stfdu	rFLD, -64(rMEMP)
++#else
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	stw	rCHR, -12(rMEMP)
++	stw	rCHR, -16(rMEMP)
++	stw	rCHR, -20(rMEMP)
++	stw	rCHR, -24(rMEMP)
++	stw	rCHR, -28(rMEMP)
++	stw	rCHR, -32(rMEMP)
++	stw	rCHR, -36(rMEMP)
++	stw	rCHR, -40(rMEMP)
++	stw	rCHR, -44(rMEMP)
++	stw	rCHR, -48(rMEMP)
++	stw	rCHR, -52(rMEMP)
++	stw	rCHR, -56(rMEMP)
++	stw	rCHR, -60(rMEMP)
++	stwu	rCHR, -64(rMEMP)
++#endif
++	bdnz	L(nzLoopSmall)
++L(nzLoopSmallDone):
++	rlwinm.	rLEN, rLEN, 0, 27, 31
++	bf	cr6*4+2, L(tail31Bytes)
++	add	rMEMP, rMEMP, rTMP2
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++#endif
++	b	L(tail31Bytes)
++
++	.p2align 6
++L(nondcbzLoopStart):
++	srwi.	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	mtcrf	0x2, rLEN
++	beq	L(nondcbzLoopDone)
++#ifndef _SOFT_FLOAT
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	lfd	rFLD, 0(rMEMP)
++#endif
++	mtctr	rALIGN
++L(nondcbzLoop):
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++	stfd	rFLD, 32(rMEMP)
++	stfd	rFLD, 40(rMEMP)
++	stfd	rFLD, 48(rMEMP)
++	stfd	rFLD, 56(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	stw	rCHR, 32(rMEMP)
++	stw	rCHR, 36(rMEMP)
++	stw	rCHR, 40(rMEMP)
++	stw	rCHR, 44(rMEMP)
++	stw	rCHR, 48(rMEMP)
++	stw	rCHR, 52(rMEMP)
++	stw	rCHR, 56(rMEMP)
++	stw	rCHR, 60(rMEMP)
++#endif
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(nondcbzLoop)
++L(nondcbzLoopDone):
++	rlwinm.	rLEN, rLEN, 0, 27, 31
++	bf	cr6*4+2, L(tail31Bytes)
++#ifndef _SOFT_FLOAT
++	stfd	rFLD, 0(rMEMP)
++	stfd	rFLD, 8(rMEMP)
++	stfd	rFLD, 16(rMEMP)
++	stfd	rFLD, 24(rMEMP)
++#else
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++#endif
++	b	L(tail31Bytes)
++
++	/* Memset of 7 bytes or less.  */
++	.p2align 6
++L(Upto7Bytes):
++	bf	cr7*4+3, L(b1)
++	stbu	rCHR, -1(rMEMP2)
++L(b1):
++	rlwimi	rCHR, rCHR, 8, 16, 23	/* Replicate byte to halfword.  */
++	bf	cr7*4+2, L(b2)
++	sthu	rCHR, -2(rMEMP2)
++L(b2):
++	bflr	cr7*4+1
++	rlwimi	rCHR, rCHR, 16, 0, 15	/* Replicate half word to word.  */
++	stw	rCHR, -4(rMEMP2)
++	blr
++
++	/* Memset of 31 bytes or less.  By now we know that there are at
++	   least 8 bytes to memset.  */
++	.p2align 6
++L(Upto31Bytes):
++	cmplwi	cr1, rLEN, 16
++	bf	cr7*4+3, L(c1)
++	stbu	rCHR, -1(rMEMP2)
++L(c1):
++	bf	cr7*4+2, L(c2)
++	sthu	rCHR, -2(rMEMP2)
++L(c2):
++	bf	cr7*4+1, L(c3)
++	stwu	rCHR, -4(rMEMP2)
++L(c3):
++	stw	rCHR, -4(rMEMP2)
++	stw	rCHR, -8(rMEMP2)
++	bltlr	cr1
++	stw	rCHR, -12(rMEMP2)
++	stw	rCHR, -16(rMEMP2)
++	bflr	cr7*4
++	stw	rCHR, -20(rMEMP2)
++	stw	rCHR, -24(rMEMP2)
++	blr
++
++	/* Memset of tail bytes upto 31 bytes or less.  */
++	.p2align 6
++L(tail31Bytes):
++	beqlr
++	mtcrf	0x1, rLEN
++	bf	cr7*4+3, L(tb2)
++	stbu	rCHR, -1(rMEMP2)
++L(tb2):
++	bf	cr7*4+2, L(tb4)
++	sthu	rCHR, -2(rMEMP2)
++L(tb4):
++	bf	cr7*4+1, L(tb8)
++	stwu	rCHR, -4(rMEMP2)
++L(tb8):
++	bf	cr7*4, L(tb16)
++	stw	rCHR, -4(rMEMP2)
++	stwu	rCHR, -8(rMEMP2)
++L(tb16):
++	bflr	cr6*4+3
++	stw	rCHR, -4(rMEMP2)
++	stw	rCHR, -8(rMEMP2)
++	stw	rCHR, -12(rMEMP2)
++	stw	rCHR, -16(rMEMP2)
++	blr
++
++
++	/* Clear cache lines of memory in 128-byte chunks per iteration
++	   using the data cache block zero line instruction.  */
++	.p2align 6
++L(zLoopStart):
++	mtcrf	0x2, rLEN
++	srwi.	rCNT, rLEN, 7
++	li	rNEG64, -64
++	bf	cr6*4+1, L(z1)
++	dcbzl	rNEG64, rMEMP
++	addi	rMEMP, rMEMP, -64
++L(z1):
++	beq	L(zLoopDone)
++	mtctr	rCNT
++	li	rNEG128, -128
++L(zLoop):
++	dcbzl	rNEG64, rMEMP
++	dcbzl	rNEG128, rMEMP
++	addi	rMEMP, rMEMP, -128
++	bdnz	L(zLoop)
++L(zLoopDone):
++	rlwinm.	rLEN, rLEN, 0, 27, 31
++	bf	cr6*4+2, L(tail31Bytes)
++	add	rMEMP, rMEMP, rTMP2
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	b	L(tail31Bytes)
++	
++END (memset)
++libc_hidden_builtin_def (memset)
++
+diff -Naur libc/sysdeps/powerpc/powerpc64/e5500/memset.S libc_release/sysdeps/powerpc/powerpc64/e5500/memset.S
+--- libc/sysdeps/powerpc/powerpc64/e5500/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ libc_release/sysdeps/powerpc/powerpc64/e5500/memset.S	2015-06-29 07:31:28.886952000 -0500
+@@ -0,0 +1,417 @@
++/* Optimized memset implementation for PowerPC e5500 64-bit target
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++/* This implementation is based on 'powerpc/powerpc64/memset.S'.  */
++
++/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
++   Returns 's'.
++
++   The memset is done in four sizes: byte (8 bits), word (32 bits),
++   32-byte blocks (256 bits) and __cache_line_size (512 bits).
++   There is a special case for setting whole cache lines to 0, which
++   takes advantage of the dcbz instruction.  */
++
++#include <sysdep.h>
++
++	.section ".toc","aw"
++.LC0:
++	.tc __cache_line_size[TC],__cache_line_size
++	.section ".text"
++	.align 2
++
++	.section ".text"
++EALIGN (memset, 6, 0)
++	CALL_MCOUNT 3
++
++#define rTMP	r0
++#define rCNT	r0
++#define rMEMP0	r3	/* original value of 1st arg.  */
++#define rCHR	r4	/* char to set in each byte.  */
++#define rLEN	r5	/* length of region to set.  */
++#define rMEMP	r6	/* address at which we are storing.  */
++#define rALIGN	r7	/* number of bytes we are setting now
++			   (when aligning).  */
++#define rTMP2	r8
++#define rMEMP2	r9
++#define rPOS64	r10	/* constant +64 for clearing with dcbzl.  */
++#define rPOS128	r11	/* constant +128 for clearing with dcbzl.  */
++#define rNEG128	r11	/* constant -128 for clearing with dcbzl.  */
++#define rPOS192	r12	/* constant +192 for clearing with dcbzl.  */
++#define rNEG192	r12	/* constant -192 for clearing with dcbzl.  */
++#define rCLS	r11
++#define rGOT	r12
++
++L(_memset):
++	/* For sizes < 8 bytes, do it in a combination of
++	   word/half word/byte stores.  */
++	cmpldi	cr1, rLEN, 7
++	mtcrf	0x01, rLEN
++	add	rMEMP2, rMEMP0, rLEN
++	ble	cr1, L(upTo7Bytes)
++	/* For sizes < 32 bytes, do it in a combination of double word,
++	   word, half word and byte stores.  */
++	cmpldi	cr5, rLEN, 31
++	rlwimi	rCHR, rCHR, 8, 16, 23	/* Replicate byte to halfword.  */
++	rlwimi	rCHR, rCHR, 16, 0, 15	/* Replicate half word to word.  */
++	ble	cr5, L(nAupTo31Bytes)
++	/* Get the destination address double word aligned.  */
++	mr	rMEMP, rMEMP0
++	andi.	rALIGN, rMEMP, 7
++	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
++	beq	L(DwAligned)
++	andi.	rTMP, rMEMP, 4
++	subfic	rALIGN, rALIGN, 8
++	/* By now, we know that there are at least 7 bytes to memset and
++	   the destination address is not double word aligned.  Do not
++	   bother about non-alignment and do a one word store at once and
++	   word align the destination address.  The penalty for non-aligned
++	   store is less compared to the if-else checks and related code.  */
++	stw	rCHR, 0(rMEMP0)
++	sub	rLEN, rLEN, rALIGN
++	add	rMEMP, rMEMP, rALIGN
++	bne	L(DwAligned)
++	stw	rCHR, -4(rMEMP)
++L(DwAligned):
++	/* Now the destination address is double word aligned.  For sizes
++	   512 > size >= 32, do the memset in a combination of
++	   64 bytes/32 bytes.  For this size range, the overhead in getting
++	   the destination address cache aligned is more compared to the
++	   advantage of setting cache line size (64) bytes per iteration.
++	   But for the memset of zero value case, since we use 'dcbzl'
++	   instruction to clear entire cache line, we can set cache lines for
++	   sizes >= 128 bytes.  */
++	cmpldi	cr5, rLEN, 128
++	cmpldi	cr1, rCHR, 0
++	blt	cr5, L(Upto511Bytes)
++	srdi.	rTMP, rLEN, 10
++	beq	cr1, L(SetCacheLines)
++	bne	L(SetCacheLines)
++L(Upto511Bytes):
++	srdi.	rTMP2, rLEN, 6
++	mtcrf	0x02, rLEN
++	beq	L(DwA8WordSet)
++	mtctr	rTMP2
++	/* Store 64 bytes at one go.  */
++L(DwA16WordSet):
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	std	rCHR, 32(rMEMP)
++	std	rCHR, 40(rMEMP)
++	std	rCHR, 48(rMEMP)
++	std	rCHR, 56(rMEMP)
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(DwA16WordSet)
++	/* Store 32 bytes at one go.  */
++L(DwA8WordSet):
++	rldicl.	rLEN, rLEN, 0, 59
++	bf	cr6*4+2, L(Upto31Bytes)
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	addi	rMEMP, rMEMP, 32
++	beqlr
++	b	L(Upto31Bytes)
++
++L(SetCacheLines):
++	neg	rTMP2, rMEMP
++	andi.	rALIGN, rTMP2, 60
++	beq	L(CacheAligned)
++	add	rMEMP, rMEMP, rALIGN
++	/* The cr6 and cr7 fields together will hold the number of bytes
++	   to set to make the destination address cache line aligned.  */
++	mtcrf	0x03, rALIGN
++	sub	rLEN, rLEN, rALIGN
++	cmpldi	cr1, rALIGN, 32
++	mr	rMEMP2, rMEMP
++	bf	cr6*4+3, L(a1)
++	std	rCHR, -8(rMEMP2)
++	stdu	rCHR, -16(rMEMP2)
++L(a1):
++	blt	cr1, L(a2)
++	std	rCHR, -8(rMEMP2)
++	std	rCHR, -16(rMEMP2)
++	std	rCHR, -24(rMEMP2)
++	stdu	rCHR, -32(rMEMP2)
++L(a2):
++	bf	cr7*4, L(CacheAligned)
++	std	rCHR, -8(rMEMP2)
++	/* Now the address is aligned to cache line boundary.  */
++L(CacheAligned):
++	ld	rCLS, .LC0 at toc(r2)
++	lwz	rCLS, 0(rCLS)
++	/* The data cache instructions should be used only if the cache
++	   line size is 64 bytes.  This check is required to not to break
++	   the memset when this code is being verified on machines having
++	   cache line size other than 64 bytes.  */
++	cmpldi	cr5, rCLS, 64
++	cmpldi	cr1, rCHR, 0
++	bne	cr5, L(NonDcbzLoopStart)
++	beq	cr1, L(zLoopStart)
++L(nzLoopStart):
++	srdi	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	rldicl	rLEN, rLEN, 0, 58	/* n = n % CACHE_LINE_SIZE.  */
++	sldi	rMEMP2, rALIGN, 6
++	cmplwi	cr1, rALIGN, 8192
++	add	rMEMP, rMEMP, rMEMP2
++	li	rNEG192, -0xc0
++	subic	rCNT, rALIGN, 1024
++	ble	cr1, L(nzLoopBigDone)
++	mtctr	rCNT
++	b	L(nzLoopBig)
++	.align 6
++	/* Memset 64 bytes per iteration.  */
++L(nzLoopBig):
++	/* The 'dcbzl' here clears the entire cache line and hints the core
++	   that the data in the <rNEG192+rMEMP> cache block is new and hence
++	   no need to fetch the block from either L2 cache or main memory
++	   and that will save us some cycles.  */
++	dcbzl	rNEG192, rMEMP
++	std	rCHR, -8(rMEMP)
++	std	rCHR, -16(rMEMP)
++	std	rCHR, -24(rMEMP)
++	std	rCHR, -32(rMEMP)
++	std	rCHR, -40(rMEMP)
++	std	rCHR, -48(rMEMP)
++	std	rCHR, -56(rMEMP)
++	stdu	rCHR, -64(rMEMP)
++	bdnz	L(nzLoopBig)
++	li	rALIGN, 1024
++L(nzLoopBigDone):
++	cmpldi	cr5, rALIGN, 768
++	subic	rCNT, rALIGN, 32
++	cmpldi	cr1, rALIGN, 0
++	ble	cr5, L(nzLoopMediumDone)
++	li	rNEG128, -0x80
++	mtctr	rCNT
++L(nzLoopMedium):
++	dcbtst	rNEG128, rMEMP
++	std	rCHR, -8(rMEMP)
++	std	rCHR, -16(rMEMP)
++	std	rCHR, -24(rMEMP)
++	std	rCHR, -32(rMEMP)
++	std	rCHR, -40(rMEMP)
++	std	rCHR, -48(rMEMP)
++	std	rCHR, -56(rMEMP)
++	stdu	rCHR, -64(rMEMP)
++	bdnz	L(nzLoopMedium)
++	li	rALIGN, 32
++L(nzLoopMediumDone):
++	srdi.	rTMP2, rLEN, 5
++	beq	cr1, L(nzLoopSmallDone)
++	mtctr	rALIGN
++	/* Like above, memset 64 bytes per iteration but do not use the
++	   'dcbzl' instruction because using it will cost more than cache
++	   prefetching for small number of cache blocks.  */
++L(nzLoopSmall):
++	std	rCHR, -8(rMEMP)
++	std	rCHR, -16(rMEMP)
++	std	rCHR, -24(rMEMP)
++	std	rCHR, -32(rMEMP)
++	std	rCHR, -40(rMEMP)
++	std	rCHR, -48(rMEMP)
++	std	rCHR, -56(rMEMP)
++	stdu	rCHR, -64(rMEMP)
++	bdnz	L(nzLoopSmall)
++L(nzLoopSmallDone):
++	/* Memset the residual bytes.  */
++	add	rMEMP, rMEMP, rMEMP2
++	beq	L(Upto31Bytes)
++	andi.	rLEN, rLEN, 31
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	addi	rMEMP, rMEMP, 32
++	beqlr
++	b	L(Upto31Bytes)
++
++	/* We are here because the cache line size is not 64 bytes.  Memset
++	   64 bytes per each iteration without using the data cache
++	   instructions.  */
++	.align 6
++L(NonDcbzLoopStart):
++	srdi.	rALIGN, rLEN, 6		/* Number of cache line size
++					   blocks = n / CACHE_LINE_SIZE.  */
++	beq	L(NonDcbzLoopDone)
++	rldicl	rLEN, rLEN, 0, 58	/* n = n % CACHE_LINE_SIZE.  */
++	mtctr	rALIGN
++L(NonDcbzLoop):
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	std	rCHR, 32(rMEMP)
++	std	rCHR, 40(rMEMP)
++	std	rCHR, 48(rMEMP)
++	std	rCHR, 56(rMEMP)
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(NonDcbzLoop)
++L(NonDcbzLoopDone):
++	/* Memset the residual bytes.  */
++	srdi.	rTMP2, rLEN, 5
++	beq	L(Upto31Bytes)
++	andi.	rLEN, rLEN, 31
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	addi	rMEMP, rMEMP, 32
++	beqlr
++	b	L(Upto31Bytes)
++
++	.align 6
++	/* Memset of 7 bytes or less.  */
++L(upTo7Bytes):
++	cmpldi	cr5, rLEN, 2
++	bf	cr7*4+3, L(b1)
++	stbu	rCHR, -1(rMEMP2)
++	bltlr	cr5
++L(b1):
++	rlwimi	rCHR, rCHR, 8, 16, 23	/* Replicate byte to halfword.  */
++	bf	cr7*4+2, L(b2)
++	sthu	rCHR, -2(rMEMP2)
++	bflr	cr7*4+1
++L(b2):
++	rlwimi	rCHR, rCHR, 16, 0, 15	/* Replicate half word to word.  */
++	bflr	cr7*4+1
++	stw	rCHR, -4(rMEMP2)
++	blr
++
++	.align 6
++	/* Memset of 0-31 bytes.  This code gets invoked only when the
++	   size, which is not the tail bytes size, is less than 32 bytes.  */
++L(nAupTo31Bytes):
++	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
++	cmplwi	cr1, rLEN, 16
++	bf	cr7*4+3, L(nA2)
++	stbu	rCHR, -1(rMEMP2)
++L(nA2):
++	bf	30, L(nA4)
++	sthu	rCHR, -2(rMEMP2)
++L(nA4):
++	bf	29, L(nA8)
++	stwu	rCHR, -4(rMEMP2)
++L(nA8):
++	std	rCHR, -8(rMEMP2)
++	bltlr	cr1
++	std	rCHR, -16(rMEMP2)
++	bflr	28
++	std	rCHR, -24(rMEMP2)
++	blr
++
++	/* Clear cache lines of memory in 256-byte chunks per iteration
++	   using the data cache block zero line instruction.  */
++	.align 6
++L(zLoopStart):
++	cmpldi	cr5, rLEN, 256
++	andi.	rTMP, rLEN, 128
++	li	rPOS64, 64
++	blt	cr5, L(zLoopDone)
++	li	rPOS128, 128
++	li	rPOS192, 192
++L(zLoop):
++	subic	rLEN, rLEN, 256
++	dcbzl	0, rMEMP
++	cmpldi	cr1, rLEN, 256
++	dcbzl	rPOS64, rMEMP
++	dcbzl	rPOS128, rMEMP
++	dcbzl	rPOS192, rMEMP
++	addi	rMEMP, rMEMP, 256
++	bge	cr1, L(zLoop)
++L(zLoopDone):
++	beq	L(z1)
++	dcbzl	0, rMEMP
++	dcbzl	rPOS64, rMEMP
++	addi	rMEMP, rMEMP, 128
++L(z1):
++	andi.	rTMP2, rLEN, 64
++	beq	L(z0)
++	dcbzl	0, rMEMP
++	addi	rMEMP, rMEMP, 64
++L(z0):
++	/* Memset the residual bytes.  */
++	andi.	rTMP2, rLEN, 32
++	rldicl	rLEN, rLEN, 0, 59
++	beq	L(Upto31Bytes)
++	rldicl.	rLEN, rLEN, 0, 59
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	beqlr
++	addi	rMEMP, rMEMP, 32
++	b	L(Upto31Bytes)
++
++	/* Memset of 0-31 bytes.  */
++	.align 6
++L(Upto31Bytes):
++	mtcrf	0x01, rLEN
++	cmpldi	cr1, rLEN, 16
++	add	rMEMP, rMEMP, rLEN
++	bt	cr7*4+3, L(b31t)
++	bt	cr7*4+2, L(b30t)
++L(b30f):
++	bt	cr7*4+1, L(b29t)
++L(b29f):
++	bge	cr1, L(b27t)
++	bflr	cr7*4
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++
++L(b31t):
++	stbu	rCHR, -1(rMEMP)
++	bf	cr7*4+2, L(b30f)
++L(b30t):
++	sthu	rCHR, -2(rMEMP)
++	bf	cr7*4+1, L(b29f)
++L(b29t):
++	stwu	rCHR, -4(rMEMP)
++	blt	cr1, L(b27f)
++L(b27t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	stw	rCHR, -12(rMEMP)
++	stwu	rCHR, -16(rMEMP)
++L(b27f):
++	bflr	cr7*4
++L(b28t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++
++END (memset)
++libc_hidden_builtin_def (memset)
++
++#ifndef NO_BZERO_IMPL
++	/* Copied from bzero.S to prevent the linker from inserting a stub
++	   between bzero and memset.  */
++ENTRY (__bzero)
++	CALL_MCOUNT 3
++	mr	r5, r4
++	li	r4, 0
++	b	L(_memset)
++
++END_GEN_TB (__bzero, TB_TOCLESS)
++weak_alias (__bzero, bzero)
++#endif
++
diff --git a/recipes-core/glibc/glibc-fsl/0011.glibc.fsl-mset-e6500.patch b/recipes-core/glibc/glibc-fsl/0011.glibc.fsl-mset-e6500.patch
new file mode 100755
index 0000000..51a0a0a
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0011.glibc.fsl-mset-e6500.patch
@@ -0,0 +1,537 @@
+# Problem Statement:
+  Implement target specific optimized memset for e6500 [32 & 64 bit]
+
+# Owned by:
+  Rohit
+
+# Actions:
+  * Used altivec instructions to generate optimized performance.
+  * for memset zero, made use of 'dcbzl' cache management instruction.
+
+diff -Naur glibc-2.20/sysdeps/powerpc/powerpc32/e6500/memset.S glibc-2.20-mset/sysdeps/powerpc/powerpc32/e6500/memset.S
+--- glibc-2.20/sysdeps/powerpc/powerpc32/e6500/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mset/sysdeps/powerpc/powerpc32/e6500/memset.S	2015-07-08 04:33:07.395952006 -0500
+@@ -0,0 +1,257 @@
++/* Optimized memset implementation for e6500 32-bit PowerPC.
++
++   Copyright (C) 2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
++   Returns 's'.  */
++
++#define rTMP	r0
++#define rRTN	r3	/* initial value of 1st argument.  */
++#define rMEMP0	r3	/* original value of 1st arg.  */
++#define rCHR	r4	/* char to set in each byte.  */
++#define rLEN	r5	/* length of region to set.  */
++#define rMEMP	r6	/* address at which we are storing.  */
++#define rALIGN	r7	/* no. of bytes we are setting now (when aligning).  */
++#define rPOS16	r7	/* constant +16.  */
++#define rPOS32	r8	/* constant +32.  */
++#define rPOS48	r9	/* constant +48.  */
++#define rGOT	r9	/* Address of the Global Offset Table.  */
++#define rCLS	r9	/* Cache line size obtained from static.  */
++#define rCTR2	r7
++#define rCTR1	r11
++#define rTMP1	r12
++#define vCHR	v14	/* char to set in each byte.  */
++#define vTMP1	v15
++#define vTMP2	v16
++
++	.section ".text"
++EALIGN (memset, 5, 1)
++	cmplwi	cr1, rLEN, 4
++	cmplwi	cr5, rLEN, 32
++	mr	rMEMP, rMEMP0
++	ble	cr1, L(small)
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	blt	cr5, L(medium)
++	neg	rTMP, rMEMP
++	andi.	rTMP, rTMP, 15
++	bne	L(nalign16)
++L(align16):
++	cmplwi	7, rLEN, 63
++	rlwinm.	rTMP1, rCHR, 28, 28, 3
++	li	rPOS16, 16
++	ble	7, L(copy_remaining)
++	beq	L(check_cache_line_size)
++L(vec_nz):
++	srwi	rCTR1, rLEN, 6		/* No of 64 byte copy count.  */
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* remaining bytes.  */
++	vxor	vCHR, vCHR, vCHR
++	mtctr	rCTR1			/* move count.  */
++	lvsl	vCHR, 0, rTMP1		/* LSU Move upper
++					   nibble to byte 0 of VR.  */
++	vspltisb	vTMP1, 4	/* VPU Splat 0x4 to every byte.  */
++	lvsl	vTMP2, 0, rCHR		/* LSU Move lower
++					   nibble to byte 0 of VR.  */
++	vslb	vCHR, vCHR, vTMP1	/* VIU Move upper nibble to VR[0:3].  */
++	vor	vCHR, vCHR, vTMP2	/* VIU Form FILL byte in VR[0:7].  */
++	vspltb	vCHR, vCHR, 0		/* VPU Splat the fill
++					   byte to all bytes.  */
++	li	rPOS32, 32
++	li	rPOS48, 48
++L(vnz_loop):
++	stvx	vCHR, 0, rMEMP
++	stvx	vCHR, rPOS16, rMEMP
++	stvx	vCHR, rPOS32, rMEMP
++	stvx	vCHR, rPOS48, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vnz_loop)
++L(copy_remaining):
++	srwi.	rCTR1, rLEN, 3		/* No of 8 byte copy count.  */
++	rlwinm	rLEN, rLEN, 0, 29, 31	/* remaining bytes.  */
++	cmplwi	cr1, rLEN, 1
++	bne	0, L(copy_words)
++L(copy_bytes):
++	bltlr	cr1
++	cmplwi	cr0, rLEN, 4
++	beq	cr1, 2f			/* nb <= 1? (0, 1 bytes).  */
++	bgt	cr0, 1f			/* nb > 4?  (5, 6, 7 bytes).  */
++	addi	rTMP, rLEN, -2		/* 2, 3, 4 bytes.  */
++	sth	rCHR, 0(rMEMP)
++	sthx	rCHR, rMEMP, rTMP
++	blr
++1:
++	addi	rTMP, rLEN, -4		/* 5, 6, 7 bytes.  */
++	stw	rCHR, 0(rMEMP)
++	stwx	rCHR, rMEMP, rTMP
++	blr
++2:	stb	rCHR, 0(rMEMP)
++	blr
++
++L(copy_words):
++	mtcrf	0x01, rCTR1
++	bf	cr7*4+1, 16f
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	stw	rCHR, 16(rMEMP)
++	stw	rCHR, 20(rMEMP)
++	stw	rCHR, 24(rMEMP)
++	stw	rCHR, 28(rMEMP)
++	addi	rMEMP, rMEMP, 32
++16:
++	bf	cr7*4+2, 8f
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	addi	rMEMP, rMEMP, 16
++8:
++	bf	cr7*4+3, L(copy_bytes)
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	bltlr	cr1
++	addi	rMEMP, rMEMP, 8
++	b	L(copy_bytes)
++
++	.align 5
++L(check_cache_line_size):
++#ifdef	SHARED
++	mflr	rTMP
++/* Establishes GOT addressability so we can load __cache_line_size
++   from static.  This value was set from the aux vector during startup.  */
++	SETUP_GOT_ACCESS(rGOT,got_label_1)
++	addis	rGOT, rGOT, __cache_line_size-got_label_1 at ha
++	lwz	rCLS, __cache_line_size-got_label_1 at l(rGOT)
++	mtlr	rTMP
++#else
++/* Load __cache_line_size from static.  This value was set from the
++   aux vector during startup.  */
++	lis	rCLS, __cache_line_size at ha
++	lwz	rCLS, __cache_line_size at l(rCLS)
++#endif
++	cmplwi	5, rCLS, 64
++	neg	rTMP, rMEMP
++	bne	5, L(vec_nz)
++	andi.	rTMP, rTMP, 63
++	bne	L(nalign64)
++L(align64):
++	srwi	rCTR1, rLEN, 6
++	cmplwi	7, rCTR1, 32767
++	rlwinm	rLEN, rLEN, 0, 26, 31
++	mtctr	rCTR1
++	bgt	7, L(vec_zbig)
++L(vz_loop):
++	dcbzl	0, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vz_loop)
++	b	L(copy_remaining)
++
++L(vec_zbig):
++	addi	rCTR2, rCTR1, -32767
++	mtctr	rCTR2
++L(vz_big_loop):
++	dcbzl	0, rMEMP
++	dcbf	0, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vz_big_loop)
++	li	rCTR1, 32767
++	mtctr	rCTR1
++	b	L(vz_loop)
++
++L(nalign64):
++	vxor	vCHR, vCHR, vCHR
++	subf	rLEN, rTMP, rLEN
++	li	rPOS48, 48
++	li	rPOS32, 32
++	stvx	vCHR, 0, rMEMP
++	stvx	vCHR, rPOS16, rMEMP
++	cmplwi	7, rLEN, 64
++	stvx	vCHR, rPOS32, rMEMP
++	stvx	vCHR, rPOS48, rMEMP
++	add	rMEMP, rMEMP, rTMP
++	blt	7, L(copy_remaining)
++	b	L(align64)
++
++L(nalign16):
++	stw	rCHR, 0(rMEMP)
++	stw	rCHR, 4(rMEMP)
++	subf	rLEN, rTMP, rLEN
++	stw	rCHR, 8(rMEMP)
++	stw	rCHR, 12(rMEMP)
++	add	rMEMP, rMEMP, rTMP
++	b	L(align16)
++
++	.align 5
++	/* Memset of 0-4 bytes.  Taken from GLIBC default memset.  */
++L(small):
++	cmplwi	cr5, rLEN, 1
++	cmplwi	cr1, rLEN, 3
++	bltlr	cr5
++	stb	rCHR, 0(rMEMP)
++	beqlr	cr5
++	nop
++	stb	rCHR, 1(rMEMP)
++	bltlr	cr1
++	stb	rCHR, 2(rMEMP)
++	beqlr	cr1
++	nop
++	stb	rCHR, 3(rMEMP)
++	blr
++
++	/* Memset of 0-31 bytes.  Taken from GLIBC default memset.  */
++	.align 5
++L(medium):
++	mtcrf	0x01, rLEN
++	cmplwi	cr1, rLEN, 16
++	add	rMEMP, rMEMP, rLEN
++	bt	31, L(medium_31t)
++	bt	30, L(medium_30t)
++L(medium_30f):
++	bt	29, L(medium_29t)
++L(medium_29f):
++	bge	cr1, L(medium_27t)
++	bflr	28
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++L(medium_31t):
++	stbu	rCHR, -1(rMEMP)
++	bf	30, L(medium_30f)
++L(medium_30t):
++	sthu	rCHR, -2(rMEMP)
++	bf	29, L(medium_29f)
++L(medium_29t):
++	stwu	rCHR, -4(rMEMP)
++	blt	cr1, L(medium_27f)
++L(medium_27t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	stw	rCHR, -12(rMEMP)
++	stwu	rCHR, -16(rMEMP)
++L(medium_27f):
++	bflr	28
++L(medium_28t):
++	stw	rCHR, -4(rMEMP)
++	stw	rCHR, -8(rMEMP)
++	blr
++
++END (memset)
++libc_hidden_builtin_def (memset)
+diff -Naur glibc-2.20/sysdeps/powerpc/powerpc64/e6500/memset.S glibc-2.20-mset/sysdeps/powerpc/powerpc64/e6500/memset.S
+--- glibc-2.20/sysdeps/powerpc/powerpc64/e6500/memset.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mset/sysdeps/powerpc/powerpc64/e6500/memset.S	2015-07-08 04:28:48.089952006 -0500
+@@ -0,0 +1,262 @@
++/* Optimized memset implementation for e6500 64-bit PowerPC.
++
++   Copyright (C) 2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#define rTMP	r0
++#define rRTN	r3	/* initial value of 1st argument.  */
++#define rMEMP0	r3	/* original value of 1st arg.  */
++#define rCHR	r4	/* char to set in each byte.  */
++#define rLEN	r5	/* length of region to set.  */
++#define rMEMP	r6	/* address at which we are storing.  */
++#define rALIGN	r7	/* no. of bytes we are setting now (when aligning).  */
++#define rPOS16	r7	/* constant +16.  */
++#define rPOS32	r8	/* constant +32.  */
++#define rPOS48	r9	/* constant +48.  */
++#define rGOT	r9	/* Address of the Global Offset Table.  */
++#define rCLS	r9	/* Cache line size obtained from static.  */
++#define rCTR2	r7
++#define rCTR1	r11
++#define rTMP1	r12
++#define vCHR	v14	/* char to set in each byte.  */
++#define vTMP1	v15
++#define vTMP2	v16
++
++#include <sysdep.h>
++
++	.section ".toc", "aw"
++.LC0:
++	.tc __cache_line_size[TC], __cache_line_size
++	.section ".text"
++	.align 2
++
++/* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
++   Returns 's'.  */
++
++EALIGN (memset, 5, 0)
++	CALL_MCOUNT 3
++L(_memset):
++	cmpldi	cr1, rLEN, 8
++	cmpldi	cr5, rLEN, 32
++	mr	rMEMP, rMEMP0
++	ble	cr1, L(small)
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	blt	cr5, L(medium)
++	neg	rTMP, rMEMP
++	andi.	rTMP, rTMP, 15
++	bne	L(nalign16)
++L(align16):
++	cmpldi	7, rLEN, 63
++	rlwinm.	rTMP1, rCHR, 28, 28, 3
++	li	rPOS16, 16
++	ble	7, L(copy_remaining)
++	beq	L(check_cache_line_size)
++L(vec_nz):
++	srwi	rCTR1, rLEN, 6		/* No of 64 byte copy count.  */
++	rlwinm	rLEN, rLEN, 0, 26, 31	/* remaining bytes.  */
++	vxor	vCHR, vCHR, vCHR
++	mtctr	rCTR1			/* move count.  */
++	lvsl	vCHR, 0, rTMP1		/* LSU Move upper nibble
++					   to byte 0 of VR.  */
++	vspltisb	vTMP1, 4	/* VPU Splat 0x4 to every byte.  */
++	lvsl	vTMP2, 0, rCHR		/* LSU Move lower nibble
++					   to byte 0 of VR.  */
++	vslb	vCHR, vCHR, vTMP1	/* VIU Move upper nibble to VR[0:3].  */
++	vor	vCHR, vCHR, vTMP2	/* VIU Form FILL byte in VR[0:7].  */
++	vspltb	vCHR, vCHR, 0		/* VPU Splat the fill
++					   byte to all bytes.  */
++	li	rPOS32, 32
++	li	rPOS48, 48
++L(vnz_loop):
++	stvx	vCHR, 0, rMEMP
++	stvx	vCHR, rPOS16, rMEMP
++	stvx	vCHR, rPOS32, rMEMP
++	stvx	vCHR, rPOS48, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vnz_loop)
++L(copy_remaining):
++	srwi.	rCTR1, rLEN, 3		/* No of 8 byte copy count.  */
++	rlwinm	rLEN, rLEN, 0, 29, 31	/* remaining bytes.  */
++	cmpldi	cr1, rLEN, 1
++	bne	0, L(copy_words)
++L(copy_bytes):
++	bltlr	cr1
++	cmpldi	cr0, rLEN, 4
++	beq	cr1, 2f			/* nb <= 1? (0, 1 bytes).  */
++	bgt	cr0, 1f			/* nb > 4?  (5, 6, 7 bytes).  */
++	addi	rTMP, rLEN, -2		/* 2, 3, 4 bytes.  */
++	sth	rCHR, 0(rMEMP)
++	sthx	rCHR, rMEMP, rTMP
++	blr
++1:
++	addi	rTMP, rLEN, -4		/* 5, 6, 7 bytes.  */
++	stw	rCHR, 0(rMEMP)
++	stwx	rCHR, rMEMP, rTMP
++	blr
++2:	stb	rCHR, 0(rMEMP)
++	blr
++
++L(copy_words):
++	mtcrf	0x01, rCTR1
++	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
++	bf	cr7*4+1, 16f
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	std	rCHR, 16(rMEMP)
++	std	rCHR, 24(rMEMP)
++	addi	rMEMP, rMEMP, 32
++16:
++	bf	cr7*4+2, 8f
++	std	rCHR, 0(rMEMP)
++	std	rCHR, 8(rMEMP)
++	addi	rMEMP, rMEMP, 16
++8:
++	bf	cr7*4+3, L(copy_bytes)
++	std	rCHR, 0(rMEMP)
++	addi	rMEMP, rMEMP, 8
++	b	L(copy_bytes)
++
++	.align 5
++L(check_cache_line_size):
++	ld	rCLS, .LC0 at toc(r2)
++	lwz	rCLS, 0(rCLS)
++	cmpldi	5, rCLS, 64
++	neg	rTMP, rMEMP
++	bne	5, L(vec_nz)
++	andi.	rTMP, rTMP, 63
++	bne	L(nalign64)
++L(align64):
++	srwi	rCTR1, rLEN, 6
++	cmpldi	7, rCTR1, 32767
++	rlwinm	rLEN, rLEN, 0, 26, 31
++	mtctr	rCTR1
++	bgt	7, L(vec_zbig)
++L(vz_loop):
++	dcbzl	0, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vz_loop)
++	b	L(copy_remaining)
++
++L(vec_zbig):
++	addi	rCTR2, rCTR1, -32767
++	mtctr	rCTR2
++L(vz_big_loop):
++	dcbzl	0, rMEMP
++	dcbf	0, rMEMP
++	addi	rMEMP, rMEMP, 64
++	bdnz	L(vz_big_loop)
++	li	rCTR1, 32767
++	mtctr	rCTR1
++	b	L(vz_loop)
++
++L(nalign64):
++	vxor	vCHR, vCHR, vCHR
++	subf	rLEN, rTMP, rLEN
++	li	rPOS48, 48
++	li	rPOS32, 32
++	stvx	vCHR, 0, rMEMP
++	stvx	vCHR, rPOS16, rMEMP
++	cmpldi	7, rLEN, 64
++	stvx	vCHR, rPOS32, rMEMP
++	stvx	vCHR, rPOS48, rMEMP
++	add	rMEMP, rMEMP, rTMP
++	blt	7, L(copy_remaining)
++	b	L(align64)
++
++L(nalign16):
++	insrdi	rCHR, rCHR, 32, 0 	/* Replicate word to double word.  */
++	std	rCHR, 0(rMEMP)
++	subf	rLEN, rTMP, rLEN
++	std	rCHR, 8(rMEMP)
++	add	rMEMP, rMEMP, rTMP
++	b	L(align16)
++
++	/* Memset of 8 bytes or less.  Taken from GLIBC default memset.  */
++	.align 5
++L(small):
++	cmpldi	cr6, rLEN, 4
++	cmpldi	cr5, rLEN, 1
++	ble	cr6, L(le4)
++	subi	rLEN, rLEN, 4
++	stb	rCHR, 0(rMEMP)
++	stb	rCHR, 1(rMEMP)
++	stb	rCHR, 2(rMEMP)
++	stb	rCHR, 3(rMEMP)
++	addi	rMEMP, rMEMP, 4
++	cmpldi	cr5, rLEN, 1
++L(le4):
++	cmpldi	cr1, rLEN, 3
++	bltlr	cr5
++	stb	rCHR, 0(rMEMP)
++	beqlr	cr5
++	stb	rCHR, 1(rMEMP)
++	bltlr	cr1
++	stb	rCHR, 2(rMEMP)
++	beqlr	cr1
++	stb	rCHR, 3(rMEMP)
++	blr
++
++	/* Memset of 0-31 bytes.  Taken from GLIBC default memset.  */
++	.align 5
++L(medium):
++	mtcrf	0x01, rLEN
++	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
++	cmpldi	cr1, rLEN, 16
++L(medium_tail2):
++	add	rMEMP, rMEMP, rLEN
++L(medium_tail):
++	bt	31, L(medium_31t)
++	bt	30, L(medium_30t)
++L(medium_30f):
++	bt	29, L(medium_29t)
++L(medium_29f):
++	bge	cr1, L(medium_27t)
++	bflr	28
++	std	rCHR, -8(rMEMP)
++	blr
++L(medium_31t):
++	stbu	rCHR, -1(rMEMP)
++	bf	30, L(medium_30f)
++L(medium_30t):
++	sthu	rCHR, -2(rMEMP)
++	bf	29, L(medium_29f)
++L(medium_29t):
++	stwu	rCHR, -4(rMEMP)
++	blt	cr1, L(medium_27f)
++L(medium_27t):
++	std	rCHR, -8(rMEMP)
++	stdu	rCHR, -16(rMEMP)
++L(medium_27f):
++	bflr	28
++L(medium_28t):
++	std	rCHR, -8(rMEMP)
++	blr
++END_GEN_TB (memset,TB_TOCLESS)
++libc_hidden_builtin_def (memset)
++
++#ifndef	NO_BZERO_IMPL
++/* Copied from bzero.S to prevent the linker from inserting a stub
++   between bzero and memset.  */
++ENTRY (__bzero)
++	mr	r5, r4
++	li	r4, 0
++	b	L(_memset)
++END_GEN_TB (__bzero,TB_TOCLESS)
++
++weak_alias (__bzero, bzero)
++#endif
diff --git a/recipes-core/glibc/glibc-fsl/0012.glibc.fsl-mcmp-e6500.patch b/recipes-core/glibc/glibc-fsl/0012.glibc.fsl-mcmp-e6500.patch
new file mode 100755
index 0000000..88e46e7
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0012.glibc.fsl-mcmp-e6500.patch
@@ -0,0 +1,832 @@
+# Problem Statement:
+  Implement target specific optimized memcmp for e6500 [32 & 64 bit]
+
+# Owned by:
+  Rohit
+
+# Actions:
+  * Use altivec instructions to generate optimized performance.
+
+diff -Naur glibc-2.20/sysdeps/powerpc/powerpc32/e6500/memcmp.S glibc-2.20-mcmp/sysdeps/powerpc/powerpc32/e6500/memcmp.S
+--- glibc-2.20/sysdeps/powerpc/powerpc32/e6500/memcmp.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcmp/sysdeps/powerpc/powerpc32/e6500/memcmp.S	2015-03-12 17:10:38.572951270 -0500
+@@ -0,0 +1,387 @@
++/* Optimized memcmp implementation for 32-bit e6500 PowerPC.
++
++   Copyright (C) 2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* int [r3] memcmp (const char *s1 [r3],
++		    const char *s2 [r4],
++		    size_t size [r5])
++	r3:source1 address, return equality
++	r4:source2 address
++	r5:byte count
++
++	volatile fixed point registers usable:
++	r0, r3-r12
++
++	volatile floating point registers usable:
++	f0-f13
++
++	v0-v1 General use Volatile (caller save)
++	v2-v13 Parameters, general volatile (caller save)
++	v14-v19 General Volatile (caller save)
++
++	CR0-CR1 Volatile condition code register fields
++	CR5-CR7 Volatile condition code register fields.  */
++
++#define rTMP	r0
++#define rRTN	r3
++#define rSTR1	r3	/* first string arg.  */
++#define rSTR2	r4	/* second string arg.  */
++#define rS2OFF	r7	/* second string arg + 16.  */
++#define rN	r5
++#define rWORD1	r6	/* current word in s1.  */
++#define rWORD2	r7	/* current word in s2.  */
++#define rWORD3	r8	/* next word in s1.  */
++#define rWORD4	r9	/* next word in s2.  */
++#define rWORD5	r10	/* next word in s1.  */
++#define rWORD6	r11	/* next word in s2.  */
++#define rWORD7	r5	/* next word in s1.  */
++#define rWORD8	r12	/* next word in s2.  */
++#define rCOUNT	r11
++#define rINDEX	r8
++#define rVR0	v0
++#define rVR1	v1
++#define rVR2	v2
++#define rVR3	v3
++#define rVR4	v4
++#define rVR5	v5
++#define rVR6	v6
++#define rVR7	v7
++#define rVR8	v8
++#define rVR9	v9
++#define rVR10	v10
++#define rVR11	v11
++#define rVR14	v14
++#define rVR15	v15
++#define rVR16	v16
++#define rVR17	v17
++#define rVR18	v18
++#define rVR19	v19
++
++EALIGN (memcmp, 5, 0)
++	cmplwi	rN, 0
++	cmplwi	cr1, rN, 32
++	beq	L(zero)
++	ble	cr1, L(medium)
++	neg	rTMP, rSTR1
++	andi.	rCOUNT, rTMP, 15	/* check src1 alignment.  */
++	bne	L(src1_nalign)
++L(src1align16):
++	rlwinm.	rTMP, r4, 0, 28, 31	/* check src2 alignment.  */
++	srwi	rCOUNT, rN, 4		/* no. of bytes / 16.  */
++	cmplwi	cr5, rCOUNT, 0xFFF0	/* check for large data compares.  */
++	rlwinm	rN, rN, 0, 28, 31	/* remaining bytes.  */
++	mtctr	rCOUNT
++	li	rINDEX, 0
++	bne	L(src2_nalign)
++	bgt	cr5, L(large_align)
++L(loop_align):
++	lvx	rVR14, rSTR1, rINDEX
++	lvx	rVR15, rSTR2, rINDEX
++	addi	rINDEX, rINDEX, 16
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(loop_align)
++	cmplwi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++L(small):
++	srwi.	rCOUNT, rN, 3
++	rlwinm	rN, rN, 0, 29, 31
++	beq	L(cmp_bytes)
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 8
++	cmplwi	cr5, rN, 0
++	bne	cr0, L(bLcr0)
++	cmplw	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 8
++	bne	cr1, L(bLcr1)
++	beq	cr5, L(zero)
++	.align 4
++L(cmp_bytes):
++	mtctr	rN
++	lbz	rWORD1, 0(rSTR1)
++	lbz	rWORD2, 0(rSTR2)
++	bdz	L(b11)
++	lbz	rWORD3, 1(rSTR1)
++	lbz	rWORD4, 1(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	bdz	L(b12)
++	lbz	rWORD5, 2(rSTR1)
++	lbz	rWORD6, 2(rSTR2)
++	cmplw	cr1, rWORD3, rWORD4
++	bdz	L(b13)
++	lbz	rWORD7, 3(rSTR1)
++	lbz	rWORD8, 3(rSTR2)
++	bne	cr0, L(bx11)
++	cmplw	cr5, rWORD5, rWORD6
++	bdz	L(b14)
++	cmplw	cr6, rWORD7, rWORD8
++	lbz	rWORD1, 4(rSTR1)
++	lbz	rWORD2, 4(rSTR2)
++	bne	cr1, L(bx12)
++	bdz	L(b15)
++	lbz	rWORD3, 5(rSTR1)
++	lbz	rWORD4, 5(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	bne	cr5, L(bx13)
++	bdz	L(b16)
++	lbz	rWORD5, 6(rSTR1)
++	lbz	rWORD6, 6(rSTR2)
++	cmplw	cr1, rWORD3, rWORD4
++	bne	cr6, L(bx14)
++	bne	cr0, L(bx15)
++	bne	cr1, L(bx16)
++	sub	rRTN, rWORD5, rWORD6
++	blr
++L(b16):
++	bne	cr6, L(bx14)
++	bne	cr0, L(bx15)
++L(bx16):
++	sub	rRTN, rWORD3, rWORD4
++	blr
++L(b15):
++	bne	cr5, L(bx13)
++	bne	cr6, L(bx14)
++L(bx15):
++	sub	rRTN, rWORD1, rWORD2
++	blr
++L(b14):
++	bne	cr1, L(bx12)
++	bne	cr5, L(bx13)
++L(bx14):
++	sub	rRTN, rWORD7, rWORD8
++	blr
++L(b13):
++	bne	cr0, L(bx11)
++	bne	cr1, L(bx12)
++L(bx13):
++	sub	rRTN, rWORD5, rWORD6
++	blr
++L(b12):
++	bne	cr0, L(bx11)
++L(bx12):
++	sub	rRTN, rWORD3, rWORD4
++	blr
++L(b11):
++L(bx11):
++	sub	rRTN, rWORD1, rWORD2
++	blr
++
++	.align 4
++L(medium):
++	srwi.	rCOUNT, rN, 3
++	rlwinm	rN, rN, 0, 29, 31
++	beq	L(cmp_bytes)
++	mtctr	rCOUNT
++	cmplwi	cr5, rN, 0
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 8
++	bne	cr0, L(bLcr0)
++	cmplw	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 8
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 8
++	bne	cr0, L(bLcr0)
++	cmplw	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 8
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 8
++	bne	cr0, L(bLcr0)
++	cmplw	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 8
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	cmplw	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 8
++	bne	cr0, L(bLcr0)
++	cmplw	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 8
++	bne	cr1, L(bLcr1)
++	li	rRTN, 0
++	blr
++
++	.align 4
++L(check_small):
++	beq	cr5, L(zero)
++	b	L(cmp_bytes)
++
++	.align 4
++L(src1_nalign):
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lwz	rWORD3, 4(rSTR1)
++	lwz	rWORD4, 4(rSTR2)
++	subfc.	rWORD1, rWORD1, rWORD2
++	bne	L(Words_Differ)
++	subfc.	rWORD1, rWORD3, rWORD4
++	bne	L(Words_Differ)
++	lwz	rWORD1, 8(rSTR1)
++	lwz	rWORD2, 8(rSTR2)
++	lwz	rWORD3, 12(rSTR1)
++	lwz	rWORD4, 12(rSTR2)
++	subfc.	rWORD1, rWORD1, rWORD2
++	bne	L(Words_Differ)
++	subfc.	rWORD1, rWORD3, rWORD4
++	bne	L(Words_Differ)
++	subf	rN, rCOUNT, rN
++	cmplwi	cr7, rN, 32
++	add	rSTR1, rSTR1, rCOUNT
++	add	rSTR2, rSTR2, rCOUNT
++	ble	cr7, L(medium)
++	b	L(src1align16)
++
++	.align 4
++L(bLcr0):
++	li	rRTN, 1
++	bgtlr	cr0
++	li	rRTN, -1
++	blr
++
++	.align 4
++L(bLcr1):
++	li	rRTN, 1
++	bgtlr	cr1
++	li	rRTN, -1
++	blr
++
++	.align 4
++L(src2_nalign):
++	addi	rS2OFF, rSTR2, 16
++	bgt	cr5, L(large_nalign)
++L(loop_nalign):
++	lvx	rVR14, rSTR1, rINDEX
++	lvsl	rVR3, 0, rSTR2		/* set permute control vector.  */
++	lvx	rVR4, rS2OFF, rINDEX	/* load LSQ.  */
++	lvx	rVR2, rSTR2, rINDEX	/* load MSQ.  */
++	addi	rINDEX, rINDEX, 16
++	vperm	rVR15, rVR2, rVR4, rVR3	/* align the data.  */
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(loop_nalign)
++	cmplwi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(large_nalign):
++	lvxl	rVR14, rSTR1, rINDEX
++	lvsl	rVR3, 0, rSTR2		/* set permute control vector.  */
++	lvxl	rVR4, rS2OFF, rINDEX	/* load LSQ.  */
++	lvxl	rVR2, rSTR2, rINDEX	/* load MSQ.  */
++	addi	rINDEX, rINDEX, 16
++	vperm	rVR15, rVR2, rVR4, rVR3	/* align the data.  */
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(large_nalign)
++	cmplwi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(large_align):
++	lvxl	rVR14, rSTR1, rINDEX
++	lvxl	rVR15, rSTR2, rINDEX
++	addi	rINDEX, rINDEX, 16
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(large_align)
++	cmplwi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(Words_Differ):
++	subfe	rRTN, rWORD1, rWORD1
++	nand	rRTN, rRTN, rRTN
++	ori	rRTN, rRTN, 1
++	blr
++
++	.align 4
++L(Vwords_Differ):
++	vspltisb	rVR18, 1
++	vspltisb	rVR1, 8
++	vslb	rVR0, rVR1, rVR18
++	vslb	rVR19, rVR0, rVR18
++	vslb	rVR18, rVR19, rVR18
++	vxor	rVR5, rVR5, rVR5
++	vsum4ubs	rVR2, rVR1, rVR18
++	vsro	rVR9, rVR17, rVR19
++	vsrw	rVR19, rVR17, rVR1
++	vsro	rVR10, rVR17, rVR18
++	vsrw	rVR18, rVR17, rVR0
++	vsro	rVR0, rVR17, rVR2
++	vor	rVR11, rVR9, rVR10
++	vsro	rVR2, rVR18, rVR1
++	vor	rVR11, rVR11, rVR0
++	vcmpgtuw	rVR11, rVR11, rVR5
++	vor	rVR11, rVR11, rVR19
++	vor	rVR11, rVR11, rVR18
++	vor	rVR11, rVR11, rVR2
++	vor	rVR15, rVR15, rVR11
++	vor	rVR14, rVR14, rVR11
++	li	rRTN, -1
++	vcmpgtub.	rVR8, rVR15, rVR14
++	bnelr	cr6
++	li	rRTN, 1
++	blr
++
++	.align 4
++L(zero):
++	li	rRTN, 0
++	blr
++
++END (memcmp)
++libc_hidden_builtin_def (memcmp)
++weak_alias (memcmp, bcmp)
+diff -Naur glibc-2.20/sysdeps/powerpc/powerpc64/e6500/memcmp.S glibc-2.20-mcmp/sysdeps/powerpc/powerpc64/e6500/memcmp.S
+--- glibc-2.20/sysdeps/powerpc/powerpc64/e6500/memcmp.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcmp/sysdeps/powerpc/powerpc64/e6500/memcmp.S	2015-03-12 17:26:44.637951961 -0500
+@@ -0,0 +1,428 @@
++/* Optimized memcmp implementation for 64-bit e6500 PowerPC.
++
++   Copyright (C) 2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* int [r3] memcmp (const char *s1 [r3],
++		    const char *s2 [r4],
++		    size_t size [r5])
++	r3:source1 address, return equality
++	r4:source2 address
++	r5:byte count
++
++	volatile fixed point registers usable:
++	r0, r3-r12
++
++	volatile floating point registers usable:
++	f0-f13
++
++	v0-v1 General use volatile (caller save)
++	v2-v13 Parameters, general volatile (caller save)
++	v14-v19 General Volatile (caller save)
++
++	CR0-CR1 Volatile condition code register fields
++	CR5-CR7 Volatile condition code register fields.  */
++
++#define rTMP	r0
++#define rRTN	r3
++#define rSTR1	r3	/* first string arg.  */
++#define rSTR2	r4	/* second string arg.  */
++#define rS2OFF	r7	/* second string arg + 16.  */
++#define rN	r5
++#define rWORD1	r6	/* current word in s1.  */
++#define rWORD2	r7	/* current word in s2.  */
++#define rWORD3	r8	/* next word in s1.  */
++#define rWORD4	r9	/* next word in s2.  */
++#define rWORD5	r10	/* next word in s1.  */
++#define rWORD6	r11	/* next word in s2.  */
++#define rWORD7	r5	/* next word in s1.  */
++#define rWORD8	r12	/* next word in s2.  */
++#define rCOUNT	r11
++#define rINDEX	r8
++#define rVR0	v0
++#define rVR1	v1
++#define rVR2	v2
++#define rVR3	v3
++#define rVR4	v4
++#define rVR5	v5
++#define rVR6	v6
++#define rVR7	v7
++#define rVR8	v8
++#define rVR9	v9
++#define rVR10	v10
++#define rVR11	v11
++#define rVR14	v14
++#define rVR15	v15
++#define rVR16	v16
++#define rVR17	v17
++#define rVR18	v18
++#define rVR19	v19
++
++EALIGN (memcmp, 5, 0)
++	CALL_MCOUNT 3
++	cmpldi	rN, 0
++	cmpldi	cr1, rN, 16
++	cmpldi	cr5, rN, 64
++	beq	L(zero)
++	blt	cr1, L(small)
++	ble	cr5, L(medium)
++	neg	rTMP, rSTR1
++	andi.	rCOUNT, rTMP, 15	/* check src1 alignment.  */
++	bne	L(src1_nalign)
++L(src1align16):
++	rlwinm.	rTMP, rSTR2, 0, 28, 31	/* check src2 alignment.  */
++	bne	L(src2_nalign)
++	srdi	rCOUNT, rN, 4		/* nb / 16.  */;
++	cmpldi	cr5, rCOUNT, 0xFFF0	/* check for large data compares.  */
++	rlwinm	rN, rN, 0, 28, 31	/* remaining bytes.  */
++	mtctr	rCOUNT
++	li	rINDEX, 0
++	bgt	cr5, L(large_align)
++	.align 4
++L(loop_align):
++	lvx	rVR14, rSTR1, rINDEX
++	lvx	rVR15, rSTR2, rINDEX
++	addi	rINDEX, rINDEX, 16
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(loop_align)
++	cmpldi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	.align 4
++L(small):
++	srdi.	rCOUNT, rN, 3
++	rlwinm	rN, rN, 0, 29, 31
++	beq	L(cmp_bytes)
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	cmpldi	cr1, rN, 0
++	addi	rSTR1, rSTR1, 8
++	addi	rSTR2, rSTR2, 8
++	bne	cr0, L(bLcr0)
++	beq	cr1, L(zero)
++	.align 4
++L(cmp_bytes):
++	mtctr	rN
++	lbz	rWORD1, 0(rSTR1)
++	lbz	rWORD2, 0(rSTR2)
++	bdz	L(b11)
++	lbz	rWORD3, 1(rSTR1)
++	lbz	rWORD4, 1(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	bdz	L(b12)
++	lbz	rWORD5, 2(rSTR1)
++	lbz	rWORD6, 2(rSTR2)
++	cmpld	cr1, rWORD3, rWORD4
++	bdz	L(b13)
++	lbz	rWORD7, 3(rSTR1)
++	lbz	rWORD8, 3(rSTR2)
++	bne	cr0, L(bx11)
++	cmpld	cr5, rWORD5, rWORD6
++	bdz	L(b14)
++	cmpld	cr6, rWORD7, rWORD8
++	lbz	rWORD1, 4(rSTR1)
++	lbz	rWORD2, 4(rSTR2)
++	bne	cr1, L(bx12)
++	bdz	L(b15)
++	lbz	rWORD3, 5(rSTR1)
++	lbz	rWORD4, 5(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	bne	cr5, L(bx13)
++	bdz	L(b16)
++	lbz	rWORD5, 6(rSTR1)
++	lbz	rWORD6, 6(rSTR2)
++	cmpld	cr1, rWORD3, rWORD4
++	bne	cr6, L(bx14)
++	bne	cr0, L(bx15)
++	bne	cr1, L(bx16)
++	sub	rRTN, rWORD5, rWORD6
++	blr
++L(b16):
++	bne	cr6, L(bx14)
++	bne	cr0, L(bx15)
++L(bx16):
++	sub	rRTN, rWORD3, rWORD4
++	blr
++L(b15):
++	bne	cr5, L(bx13)
++	bne	cr6, L(bx14)
++L(bx15):
++	sub	rRTN, rWORD1, rWORD2
++	blr
++L(b14):
++	bne	cr1, L(bx12)
++	bne	cr5, L(bx13)
++L(bx14):
++	sub	rRTN, rWORD7, rWORD8
++	blr
++L(b13):
++	bne	cr0, L(bx11)
++	bne	cr1, L(bx12)
++L(bx13):
++	sub	rRTN, rWORD5, rWORD6
++	blr
++L(b12):
++	bne	cr0, L(bx11)
++L(bx12):
++	sub	rRTN, rWORD3, rWORD4
++	blr
++L(b11):
++L(bx11):
++	sub	rRTN, rWORD1, rWORD2
++	blr
++
++	.align 4
++L(medium):
++	srwi	rCOUNT, rN, 4
++	rlwinm	rN, rN, 0, 28, 31
++	mtctr	rCOUNT
++	cmpldi	cr5, rN, 0
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 16
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 16
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 16
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 16
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 16
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 16
++	bne	cr1, L(bLcr1)
++	bdz	L(check_small)
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 16
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 16
++	bne	cr1, L(bLcr1)
++	li	rRTN, 0
++	blr
++
++	.align 4
++L(check_small):
++	beq	cr5, L(zero)
++	b	L(small)
++
++	.align 4
++L(src1_nalign):
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	add	rSTR1, rSTR1, rCOUNT
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	add	rSTR2, rSTR2, rCOUNT
++	bne	cr1, L(bLcr1)
++	subf	rN, rCOUNT, rN
++	cmpldi	cr7, rN, 64
++	ble	cr7, L(medium)
++	b	L(src1align16)
++
++	.align 4
++L(src2_nalign):
++	rlwinm.	rTMP, rSTR2, 0, 29, 31
++	beq	cr0, L(src2_dwalign)
++	srdi	rCOUNT, rN, 4		/* n / 16.  */;
++	cmpldi	cr5, rCOUNT, 0xFFF0	/* check for large data compares.  */
++	rlwinm	rN, rN, 0, 28, 31	/* remaining bytes.  */
++	mtctr	rCOUNT
++	li	rINDEX, 0
++	addi	rS2OFF, rSTR2, 16
++	bgt	cr5, L(large_nalign)
++	.align 4
++L(loop_nalign):
++	lvx	rVR14, rSTR1, rINDEX
++	lvsl	rVR3, 0, rSTR2		/* set permute control vector.  */
++	lvx	rVR4, rS2OFF, rINDEX	/* load LSQ.  */
++	lvx	rVR2, rSTR2, rINDEX	/* load MSQ.  */
++	addi	rINDEX, rINDEX, 16
++	vperm	rVR15, rVR2, rVR4, rVR3	/* align the data.  */
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(loop_nalign)
++	cmpldi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(src2_dwalign):
++	srdi	rCOUNT, rN, 6
++	rlwinm	rN, rN, 0, 26, 31
++	mtctr	rCOUNT
++	li	rINDEX, 0
++	cmpldi	cr5, rN, 0
++	cmpldi	cr6, rN, 16
++L(dw_loop):
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	ld	rWORD3, 8(rSTR1)
++	ld	rWORD4, 8(rSTR2)
++	cmpld	cr0, rWORD1, rWORD2
++	ld	rWORD1, 16(rSTR1)
++	ld	rWORD2, 16(rSTR2)
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	ld	rWORD3, 24(rSTR1)
++	ld	rWORD4, 24(rSTR2)
++	bne	cr1, L(bLcr1)
++	cmpld	cr0, rWORD1, rWORD2
++	ld	rWORD1, 32(rSTR1)
++	ld	rWORD2, 32(rSTR2)
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	ld	rWORD3, 40(rSTR1)
++	ld	rWORD4, 40(rSTR2)
++	bne	cr1, L(bLcr1)
++	cmpld	cr0, rWORD1, rWORD2
++	ld	rWORD1, 48(rSTR1)
++	ld	rWORD2, 48(rSTR2)
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	ld	rWORD3, 56(rSTR1)
++	ld	rWORD4, 56(rSTR2)
++	bne	cr1, L(bLcr1)
++	cmpld	cr0, rWORD1, rWORD2
++	addi	rSTR1, rSTR1, 64
++	bne	cr0, L(bLcr0)
++	cmpld	cr1, rWORD3, rWORD4
++	addi	rSTR2, rSTR2, 64
++	bne	cr1, L(bLcr1)
++	bdnz	L(dw_loop)
++	beq	cr5, L(zero)
++	blt	cr6, L(small)
++	b	L(medium)
++
++	.align 4
++L(bLcr0):
++	li	rRTN, 1
++	bgtlr	cr0
++	li	rRTN, -1
++	blr
++
++	.align 4
++L(bLcr1):
++	li	rRTN, 1
++	bgtlr	cr1
++	li	rRTN, -1
++	blr
++
++	.align 4
++L(large_nalign):
++	lvxl	rVR14, rSTR1, rINDEX
++	lvsl	rVR3, 0, rSTR2		/* set permute control vector.  */
++	lvxl	rVR4, rS2OFF, rINDEX	/* load LSQ.  */
++	lvxl	rVR2, rSTR2, rINDEX	/* load MSQ.  */
++	addi	rINDEX, rINDEX, 16
++	vperm	rVR15, rVR2, rVR4, rVR3	/* align the data.  */
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(large_nalign)
++	cmpldi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(large_align):
++	lvxl	rVR14, rSTR1, rINDEX
++	lvxl	rVR15, rSTR2, rINDEX
++	addi	rINDEX, rINDEX, 16
++	vcmpequb.	rVR16, rVR14, rVR15
++	vnor	rVR17, rVR16, rVR16
++	bdnzt	4*cr6+lt, L(large_align)
++	cmpldi	cr1, rN, 0
++	bge	cr6, L(Vwords_Differ)
++	beq	cr1, L(zero)
++	add	rSTR1, rSTR1, rINDEX
++	add	rSTR2, rSTR2, rINDEX
++	b	L(small)
++
++	.align 4
++L(Vwords_Differ):
++	vspltisb	rVR18, 1
++	vspltisb	rVR1, 8
++	vslb	rVR0, rVR1, rVR18
++	vslb	rVR19, rVR0, rVR18
++	vslb	rVR18, rVR19, rVR18
++	vxor	rVR5, rVR5, rVR5
++	vsum4ubs	rVR2, rVR1, rVR18
++	vsro	rVR9, rVR17, rVR19
++	vsrw	rVR19, rVR17, rVR1
++	vsro	rVR10, rVR17, rVR18
++	vsrw	rVR18, rVR17, rVR0
++	vsro	rVR0, rVR17, rVR2
++	vor	rVR11, rVR9, rVR10
++	vsro	rVR2, rVR18, rVR1
++	vor	rVR11, rVR11, rVR0
++	vcmpgtuw	rVR11, rVR11, rVR5
++	vor	rVR11, rVR11, rVR19
++	vor	rVR11, rVR11, rVR18
++	vor	rVR11, rVR11, rVR2
++	vor	rVR15, rVR15, rVR11
++	vor	rVR14, rVR14, rVR11
++	li	rRTN, -1
++	vcmpgtub.	rVR8, rVR15, rVR14
++	bnelr	cr6
++	li	rRTN, 1
++	blr
++
++	.align 4
++L(zero):
++	li	rRTN, 0
++	blr
++
++END (memcmp)
++libc_hidden_builtin_def (memcmp)
++weak_alias (memcmp, bcmp)
diff --git a/recipes-core/glibc/glibc-fsl/0013.glibc.fsl-stcmp-e5500.patch b/recipes-core/glibc/glibc-fsl/0013.glibc.fsl-stcmp-e5500.patch
new file mode 100755
index 0000000..511d88c
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0013.glibc.fsl-stcmp-e5500.patch
@@ -0,0 +1,380 @@
+# Problem Statement:
+  Dhrystone benchmark gave performance degradation due to
+  code alignment.
+  Target: e5500 (32 & 64-bit) 
+
+  Note: This is not a library optimization patch but a performance fix.
+
+# Owned by:
+  Rohit
+
+# Actions:
+  * Aligned loop code of strcmp library to 16 bytes.
+  * Broke down lwzu/ldu to lwz/ld+addi.
+    This combination gives good performance numbers.
+
+diff -Naur libc/sysdeps/powerpc/powerpc32/e5500/strcmp.S libc-strcmp/sysdeps/powerpc/powerpc32/e5500/strcmp.S
+--- libc/sysdeps/powerpc/powerpc32/e5500/strcmp.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-strcmp/sysdeps/powerpc/powerpc32/e5500/strcmp.S	2014-12-15 09:42:36.119952087 -0600
+@@ -0,0 +1,150 @@
++/* Optimized strcmp implementation for PowerPC.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how the end-of-string testing works.  */
++
++/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4])  */
++
++EALIGN (strcmp, 4, 0)
++
++#define rTMP2	r0
++#define rRTN	r3
++#define rSTR1	r3	/* first string arg */
++#define rSTR2	r4	/* second string arg */
++#define rWORD1	r5	/* current word in s1 */
++#define rWORD2	r6	/* current word in s2 */
++#define rFEFE	r7	/* constant 0xfefefeff (-0x01010101) */
++#define r7F7F	r8	/* constant 0x7f7f7f7f */
++#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f) */
++#define rBITDIF	r10	/* bits that differ in s1 & s2 words */
++#define rTMP	r11
++
++
++	or	rTMP, rSTR2, rSTR1
++	clrlwi.	rTMP, rTMP, 30
++	lis	rFEFE, -0x101
++	bne	L(unaligned)
++
++	lwz	rWORD1, 0(rSTR1)
++	lwz	rWORD2, 0(rSTR2)
++	lis	r7F7F, 0x7f7f
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	b	L(g1)
++
++L(g0):	lwzu	rWORD1, 4(rSTR1)
++	bne	cr1, L(different)
++	lwzu	rWORD2, 4(rSTR2)
++L(g1):	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	cmpw	cr1, rWORD1, rWORD2
++	beq+	L(g0)
++
++/* OK. We've hit the end of the string. We need to be careful that
++   we don't compare two strings as different because of gunk beyond
++   the end of the strings...  */
++#ifdef __LITTLE_ENDIAN__
++L(endstring):
++	addi    rTMP2, rTMP, -1
++	andc    rTMP2, rTMP2, rTMP
++	rlwimi	rTMP2, rTMP2, 1, 0, 30
++	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
++	and	rWORD1, rWORD1, rTMP2
++	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
++	rlwinm	rTMP, rWORD1, 8, 0xffffffff
++	rlwimi	rTMP2, rWORD2, 24, 0, 7
++	rlwimi	rTMP, rWORD1, 24, 0, 7
++	rlwimi	rTMP2, rWORD2, 24, 16, 23
++	rlwimi	rTMP, rWORD1, 24, 16, 23
++	xor.	rBITDIF, rTMP, rTMP2
++	sub	rRTN, rTMP, rTMP2
++	bgelr+
++	ori	rRTN, rTMP2, 1
++	blr
++
++L(different):
++	lwz	rWORD1, -4(rSTR1)
++	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
++	rlwinm	rTMP, rWORD1, 8, 0xffffffff
++	rlwimi	rTMP2, rWORD2, 24, 0, 7
++	rlwimi	rTMP, rWORD1, 24, 0, 7
++	rlwimi	rTMP2, rWORD2, 24, 16, 23
++	rlwimi	rTMP, rWORD1, 24, 16, 23
++	xor.	rBITDIF, rTMP, rTMP2
++	sub	rRTN, rTMP, rTMP2
++	bgelr+
++	ori	rRTN, rTMP2, 1
++	blr
++
++#else
++L(endstring):
++	and	rTMP, r7F7F, rWORD1
++	beq	cr1, L(equal)
++	add	rTMP, rTMP, r7F7F
++	xor.	rBITDIF, rWORD1, rWORD2
++	andc	rNEG, rNEG, rTMP
++	blt-	L(highbit)
++	cntlzw	rBITDIF, rBITDIF
++	cntlzw	rNEG, rNEG
++	addi	rNEG, rNEG, 7
++	cmpw	cr1, rNEG, rBITDIF
++	sub	rRTN, rWORD1, rWORD2
++	bgelr+	cr1
++L(equal):
++	li	rRTN, 0
++	blr
++
++L(different):
++	lwz	rWORD1, -4(rSTR1)
++	xor.	rBITDIF, rWORD1, rWORD2
++	sub	rRTN, rWORD1, rWORD2
++	bgelr+
++L(highbit):
++	ori	rRTN, rWORD2, 1
++	blr
++#endif
++
++/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
++	.align 4
++L(unaligned):
++	lbz	rWORD1, 0(rSTR1)
++	lbz	rWORD2, 0(rSTR2)
++	b	L(u1)
++
++L(u0):	lbzu	rWORD1, 1(rSTR1)
++	bne-	L(u4)
++	lbzu	rWORD2, 1(rSTR2)
++L(u1):	cmpwi	cr1, rWORD1, 0
++	beq-	cr1, L(u3)
++	cmpw	rWORD1, rWORD2
++	bne-	L(u3)
++	lbzu	rWORD1, 1(rSTR1)
++	lbzu	rWORD2, 1(rSTR2)
++	cmpwi	cr1, rWORD1, 0
++	cmpw	rWORD1, rWORD2
++	bne+	cr1, L(u0)
++L(u3):	sub	rRTN, rWORD1, rWORD2
++	blr
++L(u4):	lbz	rWORD1, -1(rSTR1)
++	sub	rRTN, rWORD1, rWORD2
++	blr
++END (strcmp)
++libc_hidden_builtin_def (strcmp)
+diff -Naur libc/sysdeps/powerpc/powerpc64/e5500/strcmp.S libc-strcmp/sysdeps/powerpc/powerpc64/e5500/strcmp.S
+--- libc/sysdeps/powerpc/powerpc64/e5500/strcmp.S	1969-12-31 18:00:00.000000000 -0600
++++ libc-strcmp/sysdeps/powerpc/powerpc64/e5500/strcmp.S	2014-12-15 09:42:46.247951902 -0600
+@@ -0,0 +1,176 @@
++/* Optimized strcmp implementation for PowerPC64.
++   Copyright (C) 1997-2014 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how the end-of-string testing works.  */
++
++/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4])  */
++
++EALIGN (strcmp, 4, 0)
++	CALL_MCOUNT 2
++
++#define rTMP2	r0
++#define rRTN	r3
++#define rSTR1	r3	/* first string arg */
++#define rSTR2	r4	/* second string arg */
++#define rWORD1	r5	/* current word in s1 */
++#define rWORD2	r6	/* current word in s2 */
++#define rFEFE	r7	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
++#define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f */
++#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
++#define rBITDIF	r10	/* bits that differ in s1 & s2 words */
++#define rTMP	r11
++
++	dcbt	0,rSTR1
++	or	rTMP, rSTR2, rSTR1
++	dcbt	0,rSTR2
++	clrldi.	rTMP, rTMP, 61
++	lis	rFEFE, -0x101
++	bne	L(unaligned)
++
++	ld	rWORD1, 0(rSTR1)
++	ld	rWORD2, 0(rSTR2)
++	lis	r7F7F, 0x7f7f
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	sldi	rTMP, rFEFE, 32
++	insrdi	r7F7F, r7F7F, 32, 0
++	add	rFEFE, rFEFE, rTMP
++	b	L(g1)
++
++L(g0):	ldu	rWORD1, 8(rSTR1)
++	bne	cr1, L(different)
++	ldu	rWORD2, 8(rSTR2)
++L(g1):	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	cmpd	cr1, rWORD1, rWORD2
++	beq+	L(g0)
++
++/* OK. We've hit the end of the string. We need to be careful that
++   we don't compare two strings as different because of gunk beyond
++   the end of the strings...  */
++#ifdef __LITTLE_ENDIAN__
++L(endstring):
++	addi    rTMP2, rTMP, -1
++	beq	cr1, L(equal)
++	andc    rTMP2, rTMP2, rTMP
++	rldimi	rTMP2, rTMP2, 1, 0
++	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
++	and	rWORD1, rWORD1, rTMP2
++	cmpd	cr1, rWORD1, rWORD2
++	beq	cr1, L(equal)
++	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
++	neg	rNEG, rBITDIF
++	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
++	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
++	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
++	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
++	sld	rWORD2, rWORD2, rNEG
++	xor.	rBITDIF, rWORD1, rWORD2
++	sub	rRTN, rWORD1, rWORD2
++	blt-	L(highbit)
++	sradi	rRTN, rRTN, 63		/* must return an int.  */
++	ori	rRTN, rRTN, 1
++	blr
++L(equal):
++	li	rRTN, 0
++	blr
++
++L(different):
++	ld	rWORD1, -8(rSTR1)
++	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
++	neg	rNEG, rBITDIF
++	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
++	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
++	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
++	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
++	sld	rWORD2, rWORD2, rNEG
++	xor.	rBITDIF, rWORD1, rWORD2
++	sub	rRTN, rWORD1, rWORD2
++	blt-	L(highbit)
++	sradi	rRTN, rRTN, 63
++	ori	rRTN, rRTN, 1
++	blr
++L(highbit):
++	sradi	rRTN, rWORD2, 63
++	ori	rRTN, rRTN, 1
++	blr
++
++#else
++L(endstring):
++	and	rTMP, r7F7F, rWORD1
++	beq	cr1, L(equal)
++	add	rTMP, rTMP, r7F7F
++	xor.	rBITDIF, rWORD1, rWORD2
++	andc	rNEG, rNEG, rTMP
++	blt-	L(highbit)
++	cntlzd	rBITDIF, rBITDIF
++	cntlzd	rNEG, rNEG
++	addi	rNEG, rNEG, 7
++	cmpd	cr1, rNEG, rBITDIF
++	sub	rRTN, rWORD1, rWORD2
++	blt-	cr1, L(equal)
++	sradi	rRTN, rRTN, 63		/* must return an int.  */
++	ori	rRTN, rRTN, 1
++	blr
++L(equal):
++	li	rRTN, 0
++	blr
++
++L(different):
++	ld	rWORD1, -8(rSTR1)
++	xor.	rBITDIF, rWORD1, rWORD2
++	sub	rRTN, rWORD1, rWORD2
++	blt-	L(highbit)
++	sradi	rRTN, rRTN, 63
++	ori	rRTN, rRTN, 1
++	blr
++L(highbit):
++	sradi	rRTN, rWORD2, 63
++	ori	rRTN, rRTN, 1
++	blr
++#endif
++
++/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
++	.align 4
++L(unaligned):
++	lbz	rWORD1, 0(rSTR1)
++	lbz	rWORD2, 0(rSTR2)
++	b	L(u1)
++
++L(u0):	lbzu	rWORD1, 1(rSTR1)
++	bne-	L(u4)
++	lbzu	rWORD2, 1(rSTR2)
++L(u1):	cmpwi	cr1, rWORD1, 0
++	beq-	cr1, L(u3)
++	cmpd	rWORD1, rWORD2
++	bne-	L(u3)
++	lbzu	rWORD1, 1(rSTR1)
++	lbzu	rWORD2, 1(rSTR2)
++	cmpdi	cr1, rWORD1, 0
++	cmpd	rWORD1, rWORD2
++	bne+	cr1, L(u0)
++L(u3):	sub	rRTN, rWORD1, rWORD2
++	blr
++L(u4):	lbz	rWORD1, -1(rSTR1)
++	sub	rRTN, rWORD1, rWORD2
++	blr
++END (strcmp)
++libc_hidden_builtin_def (strcmp)
+diff -Naur libc-strcmp/sysdeps/powerpc/powerpc32/e5500/strcmp.S libc-strcmp-dhry/sysdeps/powerpc/powerpc32/e5500/strcmp.S
+--- libc-strcmp/sysdeps/powerpc/powerpc32/e5500/strcmp.S	2014-12-15 09:42:36.119952087 -0600
++++ libc-strcmp-dhry/sysdeps/powerpc/powerpc32/e5500/strcmp.S	2014-12-15 09:46:03.771951808 -0600
+@@ -49,9 +49,12 @@
+ 	addi	r7F7F, r7F7F, 0x7f7f
+ 	b	L(g1)
+ 
+-L(g0):	lwzu	rWORD1, 4(rSTR1)
++	.align 4
++L(g0):	lwz	rWORD1, 4(rSTR1)
++	addi	rSTR1, rSTR1, 4
+ 	bne	cr1, L(different)
+-	lwzu	rWORD2, 4(rSTR2)
++	lwz	rWORD2, 4(rSTR2)
++	addi	rSTR2, rSTR2, 4
+ L(g1):	add	rTMP, rFEFE, rWORD1
+ 	nor	rNEG, r7F7F, rWORD1
+ 	and.	rTMP, rTMP, rNEG
+diff -Naur libc/sysdeps/powerpc/powerpc64/e5500/strcmp.S libc-strcmp/sysdeps/powerpc/powerpc64/e5500/strcmp.S
+--- libc/sysdeps/powerpc/powerpc64/e5500/strcmp.S	2015-01-19 04:07:33.660173151 -0600
++++ libc-strcmp/sysdeps/powerpc/powerpc64/e5500/strcmp.S	2015-01-19 04:09:38.115175293 -0600
+@@ -56,7 +56,8 @@
+ 
+ L(g0):	ldu	rWORD1, 8(rSTR1)
+ 	bne	cr1, L(different)
+-	ldu	rWORD2, 8(rSTR2)
++	ld	rWORD2, 8(rSTR2)
++	addi	rSTR2, rSTR2, 8
+ L(g1):	add	rTMP, rFEFE, rWORD1
+ 	nor	rNEG, r7F7F, rWORD1
+ 	and.	rTMP, rTMP, rNEG
diff --git a/recipes-core/glibc/glibc-fsl/0014.glibc.fsl-strchr-e500mc-e5500.patch b/recipes-core/glibc/glibc-fsl/0014.glibc.fsl-strchr-e500mc-e5500.patch
new file mode 100755
index 0000000..f864afc
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0014.glibc.fsl-strchr-e500mc-e5500.patch
@@ -0,0 +1,659 @@
+# Problem Statement:
+  Implement target specific optimized strchr for e500mc & e5500 32-bit.
+
+# Owned by:
+  Mahesh [based on existing 'asm' implementation of eglibc strchr]
+
+# Actions:
+  * For e500mc target, default glibc implementation was reading
+    two words at a time. Current implementation unrolls the loop to 
+    read sixteen words.
+
+  * For e5500 [32-bit] target, use cmpb instruction to check the occurance
+    of NULL and expected character in a string.
+
+  * Reordered the instruction to get the better performance
+
+  * Got time out error with e5500 (32-bit) target on eglibc test suite.
+    Didn't find any degradation with our performance tests.
+    So updating TIMEOUT boundary to 10.
+
+diff -Naur vanilla/string/stratcliff.c patched/string/stratcliff.c
+--- vanilla/string/stratcliff.c	2015-03-12 05:07:11.970952217 -0500
++++ patched/string/stratcliff.c	2015-03-12 05:18:29.166952009 -0500
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #define _GNU_SOURCE 1
++#define TIMEOUT 10
+ 
+ /* Make sure we don't test the optimized inline functions if we want to
+    test the real implementation.  */
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e500mc/strchr.S patched/sysdeps/powerpc/powerpc32/e500mc/strchr.S
+--- vanilla/sysdeps/powerpc/powerpc32/e500mc/strchr.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e500mc/strchr.S	2015-03-12 06:05:35.086952070 -0500
+@@ -0,0 +1,307 @@
++/* Optimized strchr implementation for 32-bit e500mc PowerPC target.
++   Based on generic 32-bit PowerPC strchr implementation.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how this works.  */
++
++/* char * [r3] strchr (const char *s [r3] , int c [r4])  */
++
++ENTRY (strchr)
++
++#define rTMP1	r0
++#define rRTN	r3	/* outgoing result.  */
++#define rSTR	r8	/* current word pointer.  */
++#define rCHR	r4	/* byte we are looking for, spread over the
++			   whole word.  */
++#define rWORD	r5	/* the current word.  */
++#define rCLZB	rCHR	/* leading zero byte count.  */
++#define rFEFE	r6	/* constant 0xfefefeff (-0x01010101).  */
++#define r7F7F	r7	/* constant 0x7f7f7f7f.  */
++#define rTMP2	r9
++#define rIGN	r10	/* the number of bits we should ignore in the
++			   first word.  */
++#define rMASK	r11	/* mask with the bits to ignore set to rTMP1.  */
++#define rTMP3	r12
++
++	andi.	rTMP2, rRTN, 3
++	clrrwi	rSTR, rRTN, 2
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	lis	rFEFE, -0x101
++	lis	r7F7F, 0x7f7f
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	beq	L(srcalign)
++	lwz	rWORD, 0(rSTR)
++	li	rMASK, -1
++	rlwinm	rIGN, rRTN, 3, 27, 28
++	srw	rMASK, rMASK, rIGN
++	orc	rWORD, rWORD, rMASK
++	add	rTMP1, rFEFE, rWORD
++	xor	rTMP3, rCHR, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	orc	rTMP3, rTMP3, rMASK
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	b	L(loop)
++L(srcalign):
++	/* Test the first (partial?) word.  */
++	lwz	rWORD, 0(rSTR)
++	add	rTMP1, rFEFE, rWORD
++	xor	rTMP3, rCHR, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* The loop.  */
++L(loop):
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	lwzu	rWORD, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	/* Start test for the bytes we're looking for.  */
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rIGN, rFEFE, rWORD
++	/* Test for 0.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rIGN, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	beq	L(loop)
++	/* There is a zero byte in the word, but may also be a matching
++	   byte (either before or after the zero byte).  In fact, we may be
++	   looking for a zero byte, in which case we return a match.  We
++	   guess that this hasn't happened, though.  */
++L(missed):
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	li	rRTN, 0
++	beqlr
++	/* It did happen.  Decide which one was first...
++	   I'm not sure if this is actually faster than a sequence of rotates,
++	   compares, and branches (we use it anyway because it's shorter).  */
++	and	rFEFE, r7F7F, rWORD
++	or	rMASK, r7F7F, rWORD
++	and	rTMP1, r7F7F, rTMP3
++	or	rIGN, r7F7F, rTMP3
++	add	rFEFE, rFEFE, r7F7F
++	add	rTMP1, rTMP1, r7F7F
++	nor	rWORD, rMASK, rFEFE
++	nor	rTMP2, rIGN, rTMP1
++	cmplw	rWORD, rTMP2
++	cntlzw	rCLZB, rTMP2
++	bgtlr
++	srwi	rCLZB, rCLZB, 3
++	add	rRTN, rSTR, rCLZB
++	blr
++L(foundit):
++	and	rTMP1, r7F7F, rTMP3
++	or	rIGN, r7F7F, rTMP3
++	add	rTMP1, rTMP1, r7F7F
++	nor	rTMP2, rIGN, rTMP1
++	cntlzw	rCLZB, rTMP2
++	subi	rSTR, rSTR, 4
++	srwi	rCLZB, rCLZB, 3
++	add	rRTN, rSTR, rCLZB
++	blr
++
++END (strchr)
++
++weak_alias (strchr, index)
++libc_hidden_builtin_def (strchr)
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e5500/strchr.S patched/sysdeps/powerpc/powerpc32/e5500/strchr.S
+--- vanilla/sysdeps/powerpc/powerpc32/e5500/strchr.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e5500/strchr.S	2015-03-12 06:06:26.507951923 -0500
+@@ -0,0 +1,313 @@
++/* Optimized strchr implementation for 32-bit e5500 PowerPC target.
++   Based on POWER7 strchr implementation.
++
++   Copyright (C) 2010-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how this works.  */
++
++/* char * [r3] strchr (const char *s [r3] , int c [r4])  */
++
++ENTRY (strchr)
++
++#define rTMP1	r0
++#define rRTN	r3	/* outgoing result.  */
++#define rSTR	r8	/* current word pointer.  */
++#define rCHR	r4	/* byte we are looking for, spread over the
++			   whole word.  */
++#define rTMP2	r5
++#define rMASK	r6	/* calculate padding bits.  */
++#define rTMP3	r7
++#define rWORD	r12	/* the current word.  */
++#define rWORD2	r9	/* following word.  */
++#define rTMP4	r10
++#define rTMP5	r11
++
++	dcbt	0, rRTN
++	andi.	rTMP3, rRTN, 7		/* check for double word boundary.  */
++	cmpwi	cr7, rCHR, 0
++	li	rTMP1, 0
++	/* Replicate byte to double word.  */
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	beq	L(dwalign)
++	subfic	rTMP3, rTMP3, 8
++	cmplwi	cr6, rTMP3, 4
++	clrrwi	rSTR, rRTN, 2		/* Align the address to the word
++					   boundary.  */
++	beq	cr6, L(word2)
++	blt	cr6, L(LTword2)
++	lwz	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 27, 28	/* Calculate padding.  */
++	/* Now rCHR has a word of c bytes and rTMP1 has
++	   a word of null bytes.  */
++	beq	cr7, L(null_match)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte
++					   against null byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	/* Handle WORD2 of pair.  */
++	lwzu	rWORD, 4(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)			/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(LTword2):
++	lwz	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 27, 28	/* Calculate padding.  */
++	/* Now rCHR has a word of c bytes and rTMP1 has
++	   a word of null bytes.  */
++	beq	cr7, L(null_LTword2)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte
++					   against null byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	lwz	rWORD, 4(rSTR)
++	lwzu	rWORD2, 8(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpwi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check
++	   the first word and decrement the address in case the first
++	   word really contains a c/null byte.  */
++	cmpwi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 4
++	bne	cr7, L(done)
++L(word2):
++	lwz	rWORD, 0(rSTR)
++	beq	cr7, L(null_word2)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)
++L(dwalign):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	mr	rSTR, rRTN
++	lwz	rWORD, 0(rSTR)
++	lwzu	rWORD2, 4(rSTR)
++	beq	cr7, L(dwalignnull)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpwi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check
++	   the first word and decrement the address in case the first word
++	   really contains a c/null byte.  */
++	cmpwi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original
++	   word from the string.  Use that to calculate the pointer.  */
++	b	L(done)
++L(loop):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	lwz	rWORD, 4(rSTR)
++	lwzu	rWORD2, 8(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpwi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check
++	   the first word and decrement the address in case the first word
++	   really contains a c/null byte.  */
++	cmpwi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done):
++	cntlzw	rCHR, rTMP4		/* Count leading zeroes until
++					   the c matches.  */
++	cntlzw	rTMP1, rTMP5		/* Count leading zeroes until
++					   the null matches.  */
++	cmplw	cr7, rCHR, rTMP1
++	bgt	cr7, L(no_match)
++	srwi	rTMP1, rCHR, 3		/* Convert leading zeroes to bytes.  */
++	add	rRTN, rSTR, rTMP1	/* Return addr of the matching c byte
++					   or null in case c was not found.  */
++	blr
++L(no_match):
++	li	rRTN, 0
++	blr
++	/* We are here because strchr was called with a null byte.  */
++L(null_match):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are
++	   not part of the string and to bring them back as zeros.  */
++	slw	rTMP2, rTMP2, rMASK
++	srw	rTMP2, rTMP2, rMASK
++	cmpwi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	/* Handle WORD2 of pair.  */
++	lwzu	rWORD, 4(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(null_LTword2):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are
++	   not part of the string and to bring them back as zeros.  */
++	slw	rTMP2, rTMP2, rMASK
++	srw	rTMP2, rTMP2, rMASK
++	cmpwi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	b	L(loop_null)
++L(null_word2):
++	/* Handle WORD2 of pair.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(dwalignnull):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rWORD2, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpwi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpwi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original
++	   word from the string.  Use that to calculate the pointer.  */
++	b	L(done_null)
++L(loop_null):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	lwz	rWORD, 4(rSTR)
++	lwzu	rTMP5, 8(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rTMP5, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpwi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpwi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done_null):
++	cntlzw	rTMP1, rTMP2		/* Count leading zeros before the
++					   match.  */
++	srwi	rTMP1, rTMP1, 3		/* Convert leading zeros to bytes.  */
++	add	rRTN, rSTR, rTMP1	/* Return address of the matching
++					   null byte.  */
++	blr
++
++END (strchr)
++
++weak_alias (strchr, index)
++libc_hidden_builtin_def (strchr)
diff --git a/recipes-core/glibc/glibc-fsl/0015.glibc.fsl-strcpy-e500mc-e5500.patch b/recipes-core/glibc/glibc-fsl/0015.glibc.fsl-strcpy-e500mc-e5500.patch
new file mode 100755
index 0000000..17dd029
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0015.glibc.fsl-strcpy-e500mc-e5500.patch
@@ -0,0 +1,627 @@
+# Problem Statement:
+  Implement target specific optimized strcpy for e500mc,32-bit e5500,
+  64-bit e5500
+
+# Owned by:
+  Ajay [based on existing 'asm' implementation of glibc]
+
+# Actions:
+  * For e500mc and e5500 [32-bit and 64-bit] targets, there is a slight
+    improvement in the performance for aligned data.
+
+  * For e500mc and e5500 [32-bit and 64-bit] targets, there is a appreciable
+    improvement in the performance [approx. 64% in case of e500mc and 32-bit
+    e5500 and 78% in case of 64-bit e5500] for non-aligned data.
+
+  * Rev2:
+    a) e5500 64-bit: Fixed "segmentation fault" issues for strcpy with eglibc
+       v2.15 test suite for unaligned data.
+
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e500mc/strcpy.S patched/sysdeps/powerpc/powerpc32/e500mc/strcpy.S
+--- vanilla/sysdeps/powerpc/powerpc32/e500mc/strcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e500mc/strcpy.S	2015-03-14 08:14:13.094951983 -0500
+@@ -0,0 +1,186 @@
++/* Optimized strcpy implementation for PowerPC e500mc target.
++   Based on generic 32-bit PowerPC strcpy implementation.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how the end-of-string testing works.  */
++
++/* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
++
++EALIGN (strcpy, 4, 0)
++
++#define rTMP	r0
++#define rRTN	r3	/* incoming DEST arg preserved as result.  */
++#define rSRC	r4	/* pointer to previous word in src.  */
++#define rDEST	r5	/* pointer to previous word in dest.  */
++#define rWORD1	r6	/* word from src.  */
++#define rFEFE	r7	/* constant 0xfefefeff (-0x01010101).  */
++#define r7F7F	r8	/* constant 0x7f7f7f7f.  */
++#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f).  */
++#define rTMP1	r9
++#define rWORD2	r10	/* word from src.  */
++#define rWORD3	r11
++#define rWORD4	r12
++
++	andi.	rTMP, rSRC, 0x03
++	bne	L(src_unaligned)
++L(aligned):
++	addi	rDEST, rRTN, -4
++	lis	rFEFE, -0x101
++	lis	r7F7F, 0x7f7f
++	lwz	rWORD2, 0(rSRC)
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	bne	L(move_register_10)
++L(loop_for_aligned):
++	lwzu	rWORD1, 4(rSRC)
++	stwu	rWORD2, 4(rDEST)
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	bne	L(copy_rest_bytes)
++	lwzu	rWORD2, 4(rSRC)
++	stwu	rWORD1, 4(rDEST)
++L(g2):
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	beq+	L(loop_for_aligned)
++
++L(move_register_10):
++	mr	rWORD1, rWORD2
++	/* We've hit the end of the string.  Do the rest byte-by-byte.  */
++L(copy_rest_bytes):
++	rlwinm.	rTMP, rWORD1, 8, 24, 31
++	stb	rTMP, 4(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 16, 24, 31
++	stb	rTMP, 5(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 24, 24, 31
++	stb	rTMP, 6(rDEST)
++	beqlr
++	stb	rWORD1, 7(rDEST)
++	blr
++	/* end of already aligned src.  */
++L(src_got_aligned):
++	lis	r7F7F, 0x7f7f
++	lwz	rWORD1, 0(rSRC)
++	lis	rFEFE, -0x101
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	bne	L(copy_rest_bytes_for_unaligned)
++	lwzu	rWORD2, 4(rSRC)
++	stw	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_10_for_unaligned)
++L(loop_for_nonaligned):
++	lwz	rWORD1, 4(rSRC)
++	stw	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(copy_rest_bytes_for_unaligned)
++	lwzu	rWORD2, 8(rSRC)
++	stw	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_10_for_unaligned)
++	lwz	rWORD3, 4(rSRC)
++	stw	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD3
++	nor	rNEG, r7F7F, rWORD3
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_11)
++	lwzu	rWORD4, 8(rSRC)
++	stw	rWORD3, 0(rDEST)
++	add	rTMP, rFEFE, rWORD4
++	nor	rNEG, r7F7F, rWORD4
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_12)
++	lwzu	rWORD2, 4(rSRC)
++	stw	rWORD4, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	beq	L(loop_for_nonaligned)
++L(move_register_10_for_unaligned):
++	mr	rWORD1, rWORD2
++L(copy_rest_bytes_for_unaligned):
++	rlwinm.	rTMP, rWORD1, 8, 24, 31
++	stb	rTMP, 0(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 16, 24, 31
++	stb	rTMP, 1(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 24, 24, 31
++	stb	rTMP, 2(rDEST)
++	beqlr
++	stb	rWORD1, 3(rDEST)
++	blr
++L(move_register_11):
++	mr	rWORD1, rWORD3
++	b	L(copy_rest_bytes_for_unaligned)
++L(move_register_12):
++	mr	rWORD1, rWORD4
++	b	L(copy_rest_bytes_for_unaligned)
++L(src_unaligned):
++	lbz	rWORD1, 0(rSRC)
++	addi	rDEST, rRTN, 0
++	cmpwi	rWORD1, 0x0
++	stb	rWORD1, 0(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 1(rSRC)
++	cmpwi	rWORD2, 0x0
++	stb	rWORD2, 1(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD3, 2(rSRC)
++	cmpwi	rWORD3, 0x0
++	stb	rWORD3, 2(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 3(rSRC)
++	cmpwi	rWORD2, 0x0
++	beq	L(endstrcpy1)
++	li	rTMP1, 4
++	sub	rTMP1, rTMP1, rTMP
++	add	rSRC, rSRC, rTMP1
++	add	rDEST, rDEST, rTMP1
++	b	L(src_got_aligned)
++L(endstrcpy1):
++	stb	rWORD2, 3(rDEST)
++L(endstrcpy):
++	blr
++
++END (strcpy)
++libc_hidden_builtin_def (strcpy)
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e5500/strcpy.S patched/sysdeps/powerpc/powerpc32/e5500/strcpy.S
+--- vanilla/sysdeps/powerpc/powerpc32/e5500/strcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e5500/strcpy.S	2015-03-14 08:14:52.103951985 -0500
+@@ -0,0 +1,180 @@
++/* Optimized strcpy implementation for 32-bit e5500 PowerPC target.
++   Based on generic 32-bit PowerPC strcpy implementation.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how the end-of-string testing works.  */
++
++/* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
++
++EALIGN (strcpy, 4, 0)
++
++#define rTMP	r0
++#define rRTN	r3	/* incoming DEST arg preserved as result.  */
++#define rSRC	r4	/* pointer to previous word in src.  */
++#define rDEST	r5	/* pointer to previous word in dest.  */
++#define rWORD1	r6	/* word from src.  */
++#define rFEFE	r7	/* constant 0xfefefeff (-0x01010101).  */
++#define r7F7F	r8	/* constant 0x7f7f7f7f.  */
++#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f).  */
++#define rTMP1	r9
++#define rWORD2	r10	/* word from src.  */
++#define rWORD3	r11
++#define rWORD4	r12
++
++	andi.	rTMP, rSRC, 0x03
++	bne	L(src_unaligned)
++	addi	rDEST, rRTN, -4
++	lis	rFEFE, -0x101
++	lis	r7F7F, 0x7f7f
++	lwz	rWORD2, 0(rSRC)
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	b	L(g2)
++L(g0):
++	lwzu	rWORD1, 4(rSRC)
++	stwu	rWORD2, 4(rDEST)
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	bne	L(g1)
++	lwzu	rWORD2, 4(rSRC)
++	stwu	rWORD1, 4(rDEST)
++L(g2):
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	beq	L(g0)
++	mr	rWORD1, rWORD2
++	/* We've hit the end of the string.  Do the rest byte-by-byte.  */
++L(g1):
++	rlwinm.	rTMP, rWORD1, 8, 24, 31
++	stb	rTMP, 4(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 16, 24, 31
++	stb	rTMP, 5(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 24, 24, 31
++	stb	rTMP, 6(rDEST)
++	beqlr
++	stb	rWORD1, 7(rDEST)
++	blr
++	/* end of already aligned src.  */
++L(src_got_aligned):
++	lis	r7F7F, 0x7f7f
++	lwz	rWORD1, 0(rSRC)
++	lis	rFEFE, -0x101
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	bne	L(copy_rest_bytes_for_unaligned)
++	lwzu	rWORD2, 4(rSRC)
++	stw	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_10_for_unaligned)
++L(loop_for_nonaligned):
++	lwz	rWORD1, 4(rSRC)
++	stw	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(copy_rest_bytes_for_unaligned)
++	lwzu	rWORD2, 8(rSRC)
++	stw	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_10_for_unaligned)
++	lwz	rWORD3, 4(rSRC)
++	stw	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD3
++	nor	rNEG, r7F7F, rWORD3
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_11)
++	lwzu	rWORD4, 8(rSRC)
++	stw	rWORD3, 0(rDEST)
++	add	rTMP, rFEFE, rWORD4
++	nor	rNEG, r7F7F, rWORD4
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	bne	L(move_register_12)
++	lwzu	rWORD2, 4(rSRC)
++	stw	rWORD4, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 4
++	beq	L(loop_for_nonaligned)
++L(move_register_10_for_unaligned):
++	mr	rWORD1, rWORD2
++L(copy_rest_bytes_for_unaligned):
++	rlwinm.	rTMP, rWORD1, 8, 24, 31
++	stb	rTMP, 0(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 16, 24, 31
++	stb	rTMP, 1(rDEST)
++	beqlr
++	rlwinm.	rTMP, rWORD1, 24, 24, 31
++	stb	rTMP, 2(rDEST)
++	beqlr
++	stb	rWORD1, 3(rDEST)
++	blr
++L(move_register_11):
++	mr	rWORD1, rWORD3
++	b	L(copy_rest_bytes_for_unaligned)
++L(move_register_12):
++	mr	rWORD1, rWORD4
++	b	L(copy_rest_bytes_for_unaligned)
++L(src_unaligned):
++	lbz	rWORD1, 0(rSRC)
++	addi	rDEST, rRTN, 0
++	cmpwi	rWORD1, 0x0
++	stb	rWORD1, 0(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 1(rSRC)
++	cmpwi	rWORD2, 0x0
++	stb	rWORD2, 1(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD3, 2(rSRC)
++	cmpwi	rWORD3, 0x0
++	stb	rWORD3, 2(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 3(rSRC)
++	cmpwi	rWORD2, 0x0
++	beq	L(endstrcpy1)
++	li	rTMP1, 4
++	sub	rTMP1, rTMP1, rTMP
++	add	rSRC, rSRC, rTMP1
++	add	rDEST, rDEST, rTMP1
++	b	L(src_got_aligned)
++L(endstrcpy1):
++	stb	rWORD2, 3(rDEST)
++L(endstrcpy):
++	blr
++
++END (strcpy)
++libc_hidden_builtin_def (strcpy)
+diff -Naur vanilla/sysdeps/powerpc/powerpc64/e5500/strcpy.S patched/sysdeps/powerpc/powerpc64/e5500/strcpy.S
+--- vanilla/sysdeps/powerpc/powerpc64/e5500/strcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc64/e5500/strcpy.S	2015-03-14 08:16:17.828951956 -0500
+@@ -0,0 +1,230 @@
++/* Optimized strcpy implementation for 64-bit e5500 PowerPC target.
++   Based on generic 64-bit PowerPC strcpy implementation.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how the end-of-string testing works.  */
++
++/* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
++
++EALIGN (strcpy, 4, 0)
++	CALL_MCOUNT 2
++
++#define rTMP	r0
++#define rRTN	r3
++#define rSRC	r4	/* pointer to previous word in src.  */
++#define rDEST	r5	/* pointer to previous word in dest.  */
++#define rWORD1	r6	/* word from src.  */
++#define rFEFE	r7	/* constant value 0xfefefefefefefeff
++			   (-0x0101010101010101).  */
++#define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f.  */
++#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f).  */
++#define rTMP1	r9
++#define rWORD2	r10	/* word from src.  */
++#define rWORD3	r11
++#define rWORD4	r12
++
++	dcbt	0, rSRC
++	andi.	rTMP, rSRC, 0x07
++	dcbtst	0, rRTN
++	bne	L(src_unaligned)
++	addi	rDEST, rRTN, -8
++	lis	rFEFE, -0x101
++	lis	r7F7F, 0x7f7f
++	ld	rWORD1, 0(rSRC)
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	sldi	rTMP, rFEFE, 32
++	insrdi	r7F7F, r7F7F, 32, 0
++	add	rFEFE, rFEFE, rTMP
++	b	L(g2)
++L(g0):
++	ldu	rWORD2, 8(rSRC)
++	stdu	rWORD1, 8(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	bne-	L(g1)
++	ldu	rWORD1, 8(rSRC)
++	stdu	rWORD2, 8(rDEST)
++L(g2):
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	beq+	L(g0)
++	mr	rWORD2, rWORD1
++	/* We've hit the end of the string.  Do the rest byte-by-byte.  */
++L(g1):
++	extrdi.	rTMP, rWORD2, 8, 0
++	stb	rTMP, 8(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 8
++	stb	rTMP, 9(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 16
++	stb	rTMP, 10(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 24
++	stb	rTMP, 11(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 32
++	stb	rTMP, 12(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 40
++	stb	rTMP, 13(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD2, 8, 48
++	stb	rTMP, 14(rDEST)
++	beqlr
++	stb	rWORD2, 15(rDEST)
++	blr
++	/* end of already aligned src.  */
++L(src_got_aligned):
++	lis	r7F7F, 0x7f7f
++	lis	rFEFE, -0x101
++	addi	rFEFE, rFEFE, -0x101
++	ld	rWORD1, 0(rSRC)
++	addi	r7F7F, r7F7F, 0x7f7f
++	sldi	rTMP, rFEFE, 32
++	insrdi	r7F7F, r7F7F, 32, 0
++	add	rFEFE, rFEFE, rTMP
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	bne	L(copy_rest_bytes_for_unaligned)
++	ldu	rWORD2, 8(rSRC)
++	std	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	bne	L(move_register_10_for_unaligned)
++L(loop_for_nonaligned):
++	ld	rWORD1, 8(rSRC)
++	std	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD1
++	nor	rNEG, r7F7F, rWORD1
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	bne	L(copy_rest_bytes_for_unaligned)
++	ldu	rWORD2, 16(rSRC)
++	std	rWORD1, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	bne	L(move_register_10_for_unaligned)
++	ld	rWORD3, 8(rSRC)
++	std	rWORD2, 0(rDEST)
++	add	rTMP, rFEFE, rWORD3
++	nor	rNEG, r7F7F, rWORD3
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	bne	L(move_register_11)
++	ldu	rWORD4, 16(rSRC)
++	std	rWORD3, 0(rDEST)
++	add	rTMP, rFEFE, rWORD4
++	nor	rNEG, r7F7F, rWORD4
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	bne	L(move_register_12)
++	ldu	rWORD2, 8(rSRC)
++	std	rWORD4, 0(rDEST)
++	add	rTMP, rFEFE, rWORD2
++	nor	rNEG, r7F7F, rWORD2
++	and.	rTMP, rTMP, rNEG
++	addi	rDEST, rDEST, 8
++	beq	L(loop_for_nonaligned)
++L(move_register_10_for_unaligned):
++	 mr	rWORD1, rWORD2
++L(copy_rest_bytes_for_unaligned):
++	extrdi.	rTMP, rWORD1, 8, 0
++	stb	rTMP, 0(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 8
++	stb	rTMP, 1(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 16
++	stb	rTMP, 2(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 24
++	stb	rTMP, 3(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 32
++	stb	rTMP, 4(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 40
++	stb	rTMP, 5(rDEST)
++	beqlr
++	extrdi.	rTMP, rWORD1, 8, 48
++	stb	rTMP, 6(rDEST)
++	beqlr
++	stb	rWORD1, 7(rDEST)
++	blr
++L(move_register_11):
++	mr	rWORD1, rWORD3
++	b	L(copy_rest_bytes_for_unaligned)
++L(move_register_12):
++	mr	rWORD1, rWORD4
++	b	L(copy_rest_bytes_for_unaligned)
++L(src_unaligned):
++	lbz	rWORD1, 0(rSRC)
++	addi	rDEST, rRTN, 0
++	cmpwi	rWORD1, 0
++	stb	rWORD1, 0(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 1(rSRC)
++	cmpwi	rWORD2, 0
++	stb	rWORD2, 1(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD3, 2(rSRC)
++	cmpwi	rWORD3, 0
++	stb	rWORD3, 2(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 3(rSRC)
++	cmpwi	rWORD2, 0
++	stb	rWORD2, 3(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD1, 4(rSRC)
++	cmpwi	rWORD1, 0
++	stb	rWORD1, 4(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD3, 5(rSRC)
++	cmpwi	rWORD3, 0
++	stb	rWORD3, 5(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD3, 6(rSRC)
++	cmpwi	rWORD3, 0
++	stb	rWORD3, 6(rDEST)
++	beq	L(endstrcpy)
++	lbz	rWORD2, 7(rSRC)
++	cmpwi	rWORD2, 0
++	beq	L(endstrcpy1)
++	li	rTMP1, 8
++	sub	rTMP1, rTMP1, rTMP
++	add	rSRC, rSRC, rTMP1
++	add	rDEST, rDEST, rTMP1
++	b	L(src_got_aligned)
++L(endstrcpy1):
++	stb	rWORD2, 7(rDEST)
++L(endstrcpy):
++	blr
++
++END (strcpy)
++libc_hidden_builtin_def (strcpy)
diff --git a/recipes-core/glibc/glibc-fsl/0016-Remove-bash-dependency-for-nscd-init-script.patch b/recipes-core/glibc/glibc-fsl/0016-Remove-bash-dependency-for-nscd-init-script.patch
new file mode 100644
index 0000000..1d9983b
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0016-Remove-bash-dependency-for-nscd-init-script.patch
@@ -0,0 +1,75 @@
+From 69d378001adfe9a359d2f4b069c1ed2d36de4480 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem at gmail.com>
+Date: Thu, 31 Dec 2015 14:33:02 -0800
+Subject: [PATCH 16/25] Remove bash dependency for nscd init script
+
+The nscd init script uses #! /bin/bash but only really uses one bashism
+(translated strings), so remove them and switch the shell to #!/bin/sh.
+
+Upstream-Status: Pending
+
+Signed-off-by: Ross Burton <ross.burton at intel.com>
+Signed-off-by: Khem Raj <raj.khem at gmail.com>
+---
+ nscd/nscd.init | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/nscd/nscd.init b/nscd/nscd.init
+index a882da7d8b..b02986ec15 100644
+--- a/nscd/nscd.init
++++ b/nscd/nscd.init
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # nscd:		Starts the Name Switch Cache Daemon
+ #
+@@ -49,7 +49,7 @@ prog=nscd
+ start () {
+     [ -d /var/run/nscd ] || mkdir /var/run/nscd
+     [ -d /var/db/nscd ] || mkdir /var/db/nscd
+-    echo -n $"Starting $prog: "
++    echo -n "Starting $prog: "
+     daemon /usr/sbin/nscd
+     RETVAL=$?
+     echo
+@@ -58,7 +58,7 @@ start () {
+ }
+ 
+ stop () {
+-    echo -n $"Stopping $prog: "
++    echo -n "Stopping $prog: "
+     /usr/sbin/nscd -K
+     RETVAL=$?
+     if [ $RETVAL -eq 0 ]; then
+@@ -67,9 +67,9 @@ stop () {
+ 	# a non-privileged user
+ 	rm -f /var/run/nscd/nscd.pid
+ 	rm -f /var/run/nscd/socket
+-       	success $"$prog shutdown"
++	success "$prog shutdown"
+     else
+-       	failure $"$prog shutdown"
++	failure "$prog shutdown"
+     fi
+     echo
+     return $RETVAL
+@@ -103,13 +103,13 @@ case "$1" in
+ 	RETVAL=$?
+ 	;;
+     force-reload | reload)
+-    	echo -n $"Reloading $prog: "
++	echo -n "Reloading $prog: "
+ 	killproc /usr/sbin/nscd -HUP
+ 	RETVAL=$?
+ 	echo
+ 	;;
+     *)
+-	echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
++	echo "Usage: $0 {start|stop|status|restart|reload|condrestart}"
+ 	RETVAL=1
+ 	;;
+ esac
+-- 
+2.13.2
+
diff --git a/recipes-core/glibc/glibc-fsl/0016.glibc.fsl-strlen-e500mc-e5500.patch b/recipes-core/glibc/glibc-fsl/0016.glibc.fsl-strlen-e500mc-e5500.patch
new file mode 100755
index 0000000..e8844c4
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0016.glibc.fsl-strlen-e500mc-e5500.patch
@@ -0,0 +1,407 @@
+# Problem Statement:
+  Implement target specific optimized strlen for e500mc,
+  64-bit e5500
+
+# Owned by:
+  Ajay [based on existing 'asm' implementation of glibc]
+
+# Actions:
+  * For e500mc and e5500 [64-bit] targets,glibc implementation was reading
+    two words at a time,I have unrolled the loop to read four words at a time.
+
+  * Reordered the instruction to get the better performance.
+
+  * Rev2:
+    a) e500mc and e5500 64-bit: Fixed "segmentation fault" issues for strlen
+       with eglibc v2.15 test suite.
+    b) added e5500 32-bit strlen optimized library.
+    c) e5500 (32 & 64-bit) optimized strlen referenced from eglibc v2.19
+       power7 implementation
+
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e500mc/strlen.S patched/sysdeps/powerpc/powerpc32/e500mc/strlen.S
+--- vanilla/sysdeps/powerpc/powerpc32/e500mc/strlen.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e500mc/strlen.S	2015-03-12 07:37:15.310952010 -0500
+@@ -0,0 +1,168 @@
++/* Optimized strlen implementation for 32-bit e500mc PowerPC target.
++   Based on generic 32-bit PowerPC strlen implementation.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* The algorithm here uses the following techniques:
++
++   1) Given a word 'x', we can test to see if it contains any 0 bytes
++      by subtracting 0x01010101, and seeing if any of the high bits of each
++      byte changed from 0 to 1.  This works because the least significant
++      0 byte must have had no incoming carry (otherwise it's not the least
++      significant), so it is 0x00 - 0x01 == 0xff.  For all other
++      byte values, either they have the high bit set initially, or when
++      1 is subtracted you get a value in the range 0x00-0x7f, none of which
++      have their high bit set.  The expression here is
++      (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when
++      there were no 0x00 bytes in the word.  You get 0x80 in bytes that
++      match, but possibly false 0x80 matches in the next more significant
++      byte to a true match due to carries.  For little-endian this is
++      of no consequence since the least significant match is the one
++      we're interested in, but big-endian needs method 2 to find which
++      byte matches.
++
++   2) Given a word 'x', we can test to see _which_ byte was zero by
++      calculating ~(((x & 0x7f7f7f7f) + 0x7f7f7f7f) | x | 0x7f7f7f7f).
++      This produces 0x80 in each byte that was zero, and 0x00 in all
++      the other bytes.  The '| 0x7f7f7f7f' clears the low 7 bits in each
++      byte, and the '| x' part ensures that bytes with the high bit set
++      produce 0x00.  The addition will carry into the high bit of each byte
++      iff that byte had one of its low 7 bits set.  We can then just see
++      which was the most significant bit set and divide by 8 to find how
++      many to add to the index.
++      This is from the book 'The PowerPC Compiler Writer's Guide',
++      by Steve Hoxey, Faraydon Karim, Bill Hay and Hank Warren.
++
++   We deal with strings not aligned to a word boundary by taking the
++   first word and ensuring that bytes not part of the string
++   are treated as nonzero.  To allow for memory latency, we unroll the
++   loop a few times, being careful to ensure that we do not read ahead
++   across cache line boundaries.
++
++   Questions to answer:
++   1) How long are strings passed to strlen? If they're often really long,
++   we should probably use cache management instructions and/or unroll the
++   loop more.  If they're often quite short, it might be better to use
++   fact (2) in the inner loop than have to recalculate it.
++   2) How popular are bytes with the high bit set? If they are very rare,
++   on some processors it might be useful to use the simpler expression
++   ~((x - 0x01010101) | 0x7f7f7f7f) (that is, on processors with only one
++   ALU), but this fails when any character has its high bit set.  */
++
++/* Some notes on register usage: Under the SVR4 ABI, we can use registers
++   0 and 3 through 12 (so long as we don't call any procedures) without
++   saving them.  We can also use registers 14 through 31 if we save them.
++   We can't use r1 (it's the stack pointer), r2 nor r13 because the user
++   program may expect them to hold their usual value if we get sent
++   a signal.  Integer parameters are passed in r3 through r10.
++   We can use condition registers cr0, cr1, cr5, cr6, and cr7 without saving
++   them, the others we must save.  */
++
++/* int [r3] strlen (char *s [r3])  */
++
++ENTRY (strlen)
++
++#define rTMP1	r0
++#define rRTN	r3	/* incoming STR arg, outgoing result.  */
++#define rSTR	r4	/* current string position.  */
++#define rPADN	r5	/* number of padding bits we prepend to the
++			   string to make it start at a word boundary.  */
++#define rTMP3	r5
++#define rFEFE	r6	/* constant 0xfefefeff (-0x01010101).  */
++#define r7F7F	r7	/* constant 0x7f7f7f7f.  */
++#define rWORD1	r8	/* current string word.  */
++#define rWORD2	r9	/* next string word.  */
++#define rMASK	r9	/* mask for first string word.  */
++#define rTMP2	r10
++
++	clrrwi	rSTR, rRTN, 2
++	lis	r7F7F, 0x7f7f
++	rlwinm	rPADN, rRTN, 3, 27, 28
++	lwz	rWORD1, 0(rSTR)
++	li	rMASK, -1
++	addi	r7F7F, r7F7F, 0x7f7f
++	/* That's the setup done, now do the first pair of words.
++	   We make an exception and use method (2) on the first two words, to
++	   reduce overhead.  */
++	srw	rMASK, rMASK, rPADN
++	and	rTMP1, r7F7F, rWORD1
++	or	rTMP2, r7F7F, rWORD1
++	add	rTMP1, rTMP1, r7F7F
++	nor	rTMP1, rTMP2, rTMP1
++	and.	rWORD1, rTMP1, rMASK
++	mtcrf	0x01, rRTN
++	bne	L(done0)
++	lis	rFEFE, -0x101
++	addi	rFEFE, rFEFE, -0x101
++	/* Are we now aligned to a double word boundary?  */
++	bt	29, L(loop)
++	/* Handle second word of pair.  */
++	lwzu	rWORD1, 4(rSTR)
++	and	rTMP1, r7F7F, rWORD1
++	or	rTMP2, r7F7F, rWORD1
++	add	rTMP1, rTMP1, r7F7F
++	nor.	rWORD1, rTMP2, rTMP1
++	bne	L(done0)
++	/* The loop.  */
++L(loop):
++	lwz	rWORD1, 4(rSTR)
++	lwzu	rWORD2, 8(rSTR)
++	add	rTMP1, rFEFE, rWORD1
++	nor	rTMP2, r7F7F, rWORD1
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rWORD2
++	bne	L(done1)
++	nor	rTMP2, r7F7F, rWORD2
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(address)
++	lwz	rWORD1, 4(rSTR)
++	lwzu	rWORD2, 8(rSTR)
++	add	rTMP1, rFEFE, rWORD1
++	nor	rTMP2, r7F7F, rWORD1
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rWORD2
++	bne	L(done1)
++	nor	rTMP2, r7F7F, rWORD2
++	and.	rTMP1, rTMP1, rTMP2
++	beq	L(loop)
++	and	rTMP1, r7F7F, rWORD2
++	add	rTMP1, rTMP1, r7F7F
++	andc	rWORD1, rTMP2, rTMP1
++	b	L(done0)
++L(address):
++	mr	rWORD1, rWORD2
++	addi	rSTR, rSTR, 4
++L(done1):
++	and	rTMP1, r7F7F, rWORD1
++	subi	rSTR, rSTR, 4
++	add	rTMP1, rTMP1, r7F7F
++	andc	rWORD1, rTMP2, rTMP1
++	/* When we get to here, rSTR points to the first word in the string
++	   that contains a zero byte, and the most significant set bit in
++	   rWORD1 is in that byte.  */
++L(done0):
++	cntlzw	rTMP3, rWORD1
++	subf	rTMP1, rRTN, rSTR
++	srwi	rTMP3, rTMP3, 3
++	add	rRTN, rTMP1, rTMP3
++	/* GKM FIXME: check high bound.  */
++	blr
++
++END (strlen)
++libc_hidden_builtin_def (strlen)
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e5500/strlen.S patched/sysdeps/powerpc/powerpc32/e5500/strlen.S
+--- vanilla/sysdeps/powerpc/powerpc32/e5500/strlen.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e5500/strlen.S	2015-03-12 07:40:07.346952026 -0500
+@@ -0,0 +1,123 @@
++/* Optimized strlen implementation for 32-bit e5500 PowerPC target.
++   Based on POWER7 strlen implementation.
++   Copyright (C) 2010-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* int [r3] strlen (char *s [r3])  */
++
++ENTRY (strlen)
++
++	clrrwi	r4, r3, 2	/* Align the address to word boundary.  */
++	rlwinm	r6, r3, 3, 27, 28	/* Calculate padding.  */
++	li	r0, 0		/* Word with null chars to use with cmpb.  */
++	li	r5, -1		/* MASK = 0xffffffffffffffff.  */
++	lwz	r12, 0(r4)	/* Load word from memory.  */
++	srw	r5, r5, r6	/* MASK = MASK >> padding.  */
++	orc	r9, r12, r5	/* Mask bits that are
++				   not part of the string.  */
++	cmpb	r10, r9, r0	/* Check for null bytes in WORD1.  */
++	cmpwi	cr7, r10, 0	/* If r10 == 0, no null's have been found.  */
++	bne	cr7, L(done)
++	/* Are we now aligned to a four word boundary?  If so, skip to the
++	   main loop.  Otherwise, go through the alignment code.  */
++	mtcrf	0x01, r3
++	bt	28, L(if_source_aligned_by_8_or_12)
++	bt	29, L(if_source_aligned_by_4)
++	/* Handle WORD2,WORD3,WORD4 as source is aligned by 0.  */
++	lwzu	r12, 4(r4)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++	lwzu	r12, 4(r4)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++	lwzu	r12, 4(r4)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++	b	L(loop)		/* We branch here (rather than falling through)
++				   to skip the nops due to heavy alignment
++				   of the loop below.  */
++L(if_source_aligned_by_8_or_12):
++	bt	29, L(loop)	/* if source address is aligned by 12 then only
++				   one word needs to be handled to make source
++				   address as 16 byte align which we have
++				   already handled in the begining, so jump
++				   directly to main loop.  */
++	lwzu	r12, 4(r4)	/* else source is aligned by 8.  */
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++L(loop):
++	lwz	r8, 4(r4)
++	lwzu	r9, 8(r4)
++	lwz	r11, 4(r4)
++	lwzu	r12, 8(r4)
++	cmpb	r10, r8, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done1)
++	cmpb	r10, r9, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done2)
++	cmpb	r10, r11, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done3)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	beq	cr7, L(loop)
++	/* r10 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the length.  */
++	cntlzw	r0, r10
++	subf	r5, r3, r4
++	srwi	r0, r0, 3
++	add	r3, r5, r0
++	blr
++L(done1):
++	addi	r4, r4, -12	/* Adjust the address.  */
++L(done):
++	cntlzw	r0, r10		/* Count leading zeroes before the match.  */
++	subf	r5, r3, r4
++	srwi	r0, r0, 3	/* Convert leading zeroes to bytes.  */
++	add	r3, r5, r0	/* Compute final length.  */
++	blr
++L(done2):
++	addi	r4, r4, -8	/* Adjust the address.  */
++	b	L(done)
++L(done3):
++	addi	r4, r4, -4	/* Adjust the address.  */
++	b	L(done)
++	/* if source address is aligned by 4 then total three words need to
++	   be handled to make source address as 16 byte align in which we
++	   have already handled one word in the begining, so now handle next
++	   two words then jump to main loop.  */
++L(if_source_aligned_by_4):
++	lwzu	r12, 4(r4)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++	lwzu	r12, 4(r4)
++	cmpb	r10, r12, r0
++	cmpwi	cr7, r10, 0
++	bne	cr7, L(done)
++	b	L(loop)
++
++END (strlen)
++libc_hidden_builtin_def (strlen)
+diff -Naur vanilla/sysdeps/powerpc/powerpc64/e5500/strlen.S patched/sysdeps/powerpc/powerpc64/e5500/strlen.S
+--- vanilla/sysdeps/powerpc/powerpc64/e5500/strlen.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc64/e5500/strlen.S	2015-03-12 07:39:06.118952040 -0500
+@@ -0,0 +1,84 @@
++/* Optimized strlen implementation for 64-bit e5500 PowerPC target.
++   Based on POWER7 strlen implementation.
++   Copyright (C) 2010-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* int [r3] strlen (char *s [r3])  */
++
++ENTRY (strlen)
++	CALL_MCOUNT 1
++
++	dcbt	0, r3
++	clrrdi	r4, r3, 3	/* Align address to double word boundary.  */
++	rlwinm	r6, r3, 3, 26, 28	/* Calculate padding.  */
++	li	r0, 0		/* Doubleword with null chars to use
++				   with cmpb.  */
++	li	r5, -1		/* MASK = 0xffffffffffffffff.  */
++	ld	r12, 0(r4)	/* Load doubleword from memory.  */
++	srd	r5, r5, r6	/* MASK = MASK >> padding.  */
++	orc	r9, r12, r5	/* Mask bits that are not part of string.  */
++	cmpb	r10, r9, r0	/* Check for null bytes in DWORD1.  */
++	cmpdi	cr7, r10, 0	/* If r10 == 0, no null's have been found.  */
++	bne	cr7, L(done)
++	mtcrf	0x01, r4
++	/* Are we now aligned to a quad word boundary?  If so, skip to the
++	   main loop.  Otherwise, go through the alignment code.  */
++	bt	28, L(loop)
++/* Handle DWORD2 of pair.  */
++	ldu	r12, 8(r4)
++	cmpb	r10, r12, r0
++	cmpdi	cr7, r10, 0
++	bne	cr7, L(done)
++	b	L(loop)		/* We branch here (rather than falling through)
++				   to skip the nops due to heavy alignment of
++				   the loop below.  */
++L(loop):
++	/* Load two doublewords, compare and merge in a single register for
++	   speed.  This is an attempt to speed up the null-checking process
++	   for bigger strings.  */
++	ld	r12, 8(r4)
++	ldu	r11, 16(r4)
++	cmpb	r10, r12, r0
++	cmpb	r9, r11, r0
++	or	r8, r9, r10	/* Merge everything in one doubleword.  */
++	cmpdi	cr7, r8, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the doublewords contains a null byte.  Check
++	   the first doubleword and decrement the address in case the first
++	   doubleword really contains a null byte.  */
++	cmpdi	cr6, r10, 0
++	addi	r4, r4, -8
++	bne	cr6, L(done)
++	/* The null byte must be in the second doubleword.  Adjust the address
++	   again and move the result of cmpb to r10 so we can calculate the
++	   length.  */
++	mr	r10, r9
++	addi	r4, r4, 8
++	/* r10 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original
++	   doubleword from the string.  Use that to calculate the length.  */
++L(done):
++	cntlzd	r0, r10		/* Count leading zeroes before the match.  */
++	subf	r5, r3, r4
++	srdi	r0, r0, 3	/* Convert leading zeroes to bytes.  */
++	add	r3, r5, r0	/* Compute final length.  */
++	blr
++
++END (strlen)
++libc_hidden_builtin_def (strlen)
diff --git a/recipes-core/glibc/glibc-fsl/0017.glibc.fsl-strrchr-e500mc-e5500.patch b/recipes-core/glibc/glibc-fsl/0017.glibc.fsl-strrchr-e500mc-e5500.patch
new file mode 100755
index 0000000..64cec3a
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0017.glibc.fsl-strrchr-e500mc-e5500.patch
@@ -0,0 +1,1072 @@
+# Problem Statement:
+  Implement target specific optimized strrchr for e500mc, 32-bit e5500 and
+  64-bit e5500
+
+# Owned by:
+  Mahesh [based on existing 'asm' implementation of glibc strchr]
+
+# Actions:
+  * For e500mc target, default glibc implementation reads
+    two words at a time. Current implementation unrolls the loop to
+    read eight words.
+
+  * For e5500 [32-bit and 64-bit] targets, use 'cmpb' instruction to check 
+    the occurance of NULL and expected character in a string.
+
+  * Reordered the instructions to get the better performance
+
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e500mc/strrchr.S patched/sysdeps/powerpc/powerpc32/e500mc/strrchr.S
+--- vanilla/sysdeps/powerpc/powerpc32/e500mc/strrchr.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e500mc/strrchr.S	2015-03-13 03:18:38.082952006 -0500
+@@ -0,0 +1,344 @@
++/* Optimized strrchr implementation for PowerPC e500mc target.
++   Based on generic strchr implementation of 32-bit PowerPC.
++   Copyright (C) 1997-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how this works.  */
++
++/* char * [r3] strrchr (const char *s [r3] , int c [r4])  */
++
++ENTRY (strrchr)
++
++#define rTMP1	r0
++#define rRTN	r3	/* outgoing result.  */
++#define rSTR	r8	/* current word pointer.  */
++#define rCHR	r4	/* byte we are looking for, spread over the
++			   whole word.  */
++#define rWORD	r5	/* the current word.  */
++#define rFEFE	r6	/* constant 0xfefefeff (-0x01010101).  */
++#define r7F7F	r7	/* constant 0x7f7f7f7f.  */
++#define rTMP2	r9
++#define rIGN	r10	/* number of bits we should ignore in first word.  */
++#define rMASK	r11	/* mask with the bits to ignore set to rTMP1
++			   and to load preceding word.  */
++#define rTMP3	r12
++
++	andi.	rTMP2, rRTN, 3
++	cmplwi	cr7, rCHR, 0
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	lis	rFEFE, -0x101
++	lis	r7F7F, 0x7f7f
++	clrrwi	rSTR, rRTN, 2
++	addi	rFEFE, rFEFE, -0x101
++	addi	r7F7F, r7F7F, 0x7f7f
++	lwz	rWORD, 0(rSTR)
++	li	rIGN, -1
++	beq	L(srcalign)
++	rlwinm	rTMP1, rRTN, 3, 27, 28
++	srw	rMASK, rIGN, rTMP1
++	orc	rWORD, rWORD, rMASK
++	li	rRTN, 0
++	beq	cr7, L(null)
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	xor	rTMP3, rCHR, rWORD
++	orc	rTMP3, rTMP3, rMASK
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	b	L(loop)
++L(srcalign):
++	li	rRTN, 0
++	beq	cr7, L(nullwordalign)
++L(srcalign2):
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	xor	rTMP3, rCHR, rWORD
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++L(loop):
++	lwzu	rMASK, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rMASK
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rMASK
++	xor	rTMP3, rCHR, rMASK
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed1)
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit1)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	lwzu	rMASK, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rMASK
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rMASK
++	xor	rTMP3, rCHR, rMASK
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed1)
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit1)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	lwzu	rMASK, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rMASK
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rMASK
++	xor	rTMP3, rCHR, rMASK
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed1)
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit1)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rWORD
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	lwzu	rMASK, 4(rSTR)
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit)
++	add	rTMP1, rFEFE, rMASK
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rMASK
++	xor	rTMP3, rCHR, rMASK
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed1)
++	nor	rTMP2, r7F7F, rTMP3
++	lwzu	rWORD, 4(rSTR)
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundit1)
++	add	rTMP1, rFEFE, rWORD
++	/* Test for rTMP1.  */
++	nor	rTMP2, r7F7F, rWORD
++	dcbt	rTMP1, rSTR
++	xor	rTMP3, rCHR, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	add	rTMP1, rFEFE, rTMP3
++	beq	L(loop)
++L(missed):
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	beqlr
++	and	rFEFE, r7F7F, rWORD
++	or	rMASK, r7F7F, rWORD
++	and	rTMP1, r7F7F, rTMP3
++	or	rTMP2, r7F7F, rTMP3
++	add	rFEFE, rFEFE, r7F7F
++	add	rTMP1, rTMP1, r7F7F
++	nor	rWORD, rMASK, rFEFE
++	nor	rTMP2, rTMP2, rTMP1
++	cmplw	rWORD, rTMP2
++	bgtlr
++	cntlzw	rWORD, rTMP2
++	srwi	rWORD, rWORD, 3
++	add	rRTN, rSTR, rWORD
++	addi	rSTR, rRTN, 1
++	andi.	rTMP2, rSTR, 3
++	cmpwi	rFEFE, rTMP2, 2
++	bgt	rFEFE, L(b3l)
++	li	rTMP1, 24
++	srw	rCHR, rCHR, rTMP1
++	beq	rFEFE, L(b2)
++	lbz	rWORD, 0(rSTR)
++	cmpwi	rFEFE, rWORD, 0
++	beq	rFEFE, L(b3l)
++	lbzu	rTMP3, 1(rSTR)
++	cmpw	r7F7F, rWORD, rCHR
++	beq	r7F7F, L(ret1)
++	cmpwi	rFEFE, rTMP3, 0
++	beq	rFEFE, L(b3l)
++	cmpw	r7F7F, rTMP3, rCHR
++	beq	r7F7F, L(ret2)
++	blr
++L(missed1):
++	mr	rWORD,rMASK
++	nor	rTMP2, r7F7F, rTMP3
++	and.	rTMP1, rTMP1, rTMP2
++	beqlr
++	and	rFEFE, r7F7F, rWORD
++	or	rMASK, r7F7F, rWORD
++	and	rTMP1, r7F7F, rTMP3
++	or	rTMP2, r7F7F, rTMP3
++	add	rFEFE, rFEFE, r7F7F
++	add	rTMP1, rTMP1, r7F7F
++	nor	rWORD, rMASK, rFEFE
++	nor	rTMP2, rTMP2, rTMP1
++	cmplw	rWORD, rTMP2
++	bgtlr
++	cntlzw	rWORD, rTMP2
++	srwi	rWORD, rWORD, 3
++	add	rRTN, rSTR, rWORD
++	addi	rSTR, rRTN, 1
++	andi.	rTMP2, rSTR, 3
++	cmpwi	rFEFE, rTMP2, 2
++	bgt	rFEFE, L(b3l)
++	li	rTMP1, 24
++	srw	rCHR, rCHR, rTMP1
++	beq	rFEFE, L(b2)
++	lbz	rWORD, 0(rSTR)
++	cmpwi	rFEFE, rWORD, 0
++	beq	rFEFE, L(b3l)
++	lbzu	rTMP3, 1(rSTR)
++	cmpw	r7F7F, rWORD, rCHR
++	beq	r7F7F, L(ret1)
++	cmpwi	rFEFE, rTMP3, 0
++	beq	rFEFE, L(b3l)
++	cmpw	r7F7F, rTMP3, rCHR
++	beq	r7F7F, L(ret2)
++	blr
++L(ret2):
++	mr	rRTN, rSTR
++	blr
++L(ret1):
++	subi	rRTN, rSTR, 1
++	blr
++L(b2):
++	lbz	rWORD, 0(rSTR)
++	cmpwi	rFEFE, rWORD, 0
++	beq	rFEFE, L(b3l)
++	cmpw	r7F7F, rWORD, rCHR
++	beq	r7F7F, L(ret)
++	blr
++L(ret):
++	mr	rRTN, rSTR
++	blr
++L(b3l):
++	blr
++L(foundit):
++	and	rTMP1, r7F7F, rTMP3
++	or	rTMP2, r7F7F, rTMP3
++	add	rTMP1, rTMP1, r7F7F
++	nor	rTMP2, rTMP2, rTMP1
++	cntlzw	rTMP3, rTMP2
++	subi	rSTR, rSTR, 4
++	srwi	rTMP3, rTMP3, 3
++	add	rRTN, rSTR, rTMP3
++	addi	rTMP1, rRTN, 1
++L(Nextword):
++	andi.	rTMP2, rTMP1, 3
++	clrrwi	rSTR, rTMP1, 2
++	bne	L(srcalign_make)
++	mr	rWORD,rMASK
++	b	L(srcalign2)
++L(srcalign_make):
++	rlwinm	rTMP1, rTMP1, 3, 27, 28
++	slw	rWORD, rWORD, rTMP1
++	srw	rWORD, rWORD, rTMP1
++	srw	rMASK, rIGN, rTMP1
++	orc	rWORD, rWORD, rMASK
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	xor	rTMP3, rCHR, rWORD
++	orc	rTMP3, rTMP3, rMASK
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	b	L(loop)
++L(foundit1):
++	and	rTMP1, r7F7F, rTMP3
++	or	rTMP2, r7F7F, rTMP3
++	add	rTMP1, rTMP1, r7F7F
++	nor	rTMP2, rTMP2, rTMP1
++	cntlzw	rTMP3, rTMP2
++	subi	rSTR, rSTR, 4
++	srwi	rTMP3, rTMP3, 3
++	add	rRTN, rSTR, rTMP3
++	addi	rTMP1, rRTN, 1
++L(Nextword1):
++	andi.	rTMP2, rTMP1, 3
++	clrrwi	rSTR, rTMP1, 2
++	beq	L(srcalign2)
++	mr	rWORD, rMASK
++	rlwinm	rTMP1, rTMP1, rRTN, 27, 28
++	slw	rWORD, rWORD, rTMP1
++	srw	rWORD, rWORD, rTMP1
++	srw	rMASK, rIGN, rTMP1
++	orc	rWORD, rWORD, rMASK
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	xor	rTMP3, rCHR, rWORD
++	orc	rTMP3, rTMP3, rMASK
++	add	rTMP1, rFEFE, rTMP3
++	bne	L(missed)
++	b	L(loop)
++
++L(nullwordalign):
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundnull)
++	b	L(loopnull)
++L(null):
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	bne	L(foundnull)
++L(loopnull):
++	lwzu	rWORD, 4(rSTR)
++	add	rTMP1, rFEFE, rWORD
++	nor	rTMP2, r7F7F, rWORD
++	and.	rTMP1, rTMP1, rTMP2
++	beq	L(loopnull)
++L(foundnull):
++	and	rTMP1, r7F7F, rWORD
++	or	rIGN, r7F7F, rWORD
++	add	rTMP1, rTMP1, r7F7F
++	nor	rTMP2, rIGN, rTMP1
++	cntlzw	rTMP3, rTMP2
++	srwi	rTMP3, rTMP3, 3
++	add	rRTN, rSTR, rTMP3
++	blr
++END (strrchr)
++
++weak_alias (strrchr, rindex)
++libc_hidden_builtin_def (strrchr)
+diff -Naur vanilla/sysdeps/powerpc/powerpc32/e5500/strrchr.S patched/sysdeps/powerpc/powerpc32/e5500/strrchr.S
+--- vanilla/sysdeps/powerpc/powerpc32/e5500/strrchr.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc32/e5500/strrchr.S	2015-03-13 03:19:56.365952010 -0500
+@@ -0,0 +1,348 @@
++/* Optimized strrchr implementation for 32-bit e5500 PowerPC target.
++   Based on POWER7 strchr implementation.
++   Copyright (C) 2010-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how this works.  */
++
++/* char * [r3] strrchr (const char *s [r3] , int c [r4])  */
++
++ENTRY (strrchr)
++
++#define rTMP1	r0
++#define rRTN	r3	/* outgoing result.  */
++#define rSTR	r8	/* current word pointer.  */
++#define rCHR	r4	/* byte we are looking for, spread over the
++			   whole word.  */
++#define rTMP2	r5
++#define rMASK	r6	/* calculate padding bits.  */
++#define rTMP3	r7
++#define rWORD	r12	/* the current word.  */
++#define rWORD2	r9	/* following word.  */
++#define rTMP4	r10
++#define rTMP5	r11
++
++	dcbt	0, rRTN
++	andi.	rTMP3, rRTN, 7		/* check for double word boundary.  */
++	cmpwi	cr7, rCHR, 0
++	li	rTMP1, 0
++	/* Replicate byte to double word.  */
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR,rCHR, 16, 0, 15
++	beq	L(dwalign)
++	subfic	rTMP3, rTMP3, 8
++	cmplwi	cr6, rTMP3, 4
++	clrrwi	rSTR, rRTN, 2		/* Align address to word boundary.  */
++	beq	cr6, L(word2)
++	blt	cr6, L(LTword2)
++	lwz	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 27, 28	/* Calculate padding.  */
++	/* By now the rCHR has a word of c bytes and the rTMP1 has a word of
++	   null bytes.  */
++	li	rRTN, 0
++	beq	cr7, L(null_match)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte against c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against the null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	/* Handle WORD2 of pair.  */
++	lwzu	rWORD, 4(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)			/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(LTword2):
++	lwz	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 27, 28	/* Calculate padding.  */
++	/* By now the rCHR has a word of c bytes and the rTMP1 has a word
++	   of null bytes.  */
++	li	rRTN, 0
++	beq	cr7, L(null_LTword2)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against the null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	b	L(loop)
++L(word2):
++	lwz	rWORD, 0(rSTR)
++	li	rRTN, 0
++	beq	cr7, L(null_word2)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)
++L(dwalign):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	mr	rSTR, rRTN
++	li	rRTN, 0
++	lwz	rWORD, 0(rSTR)
++	lwzu	rWORD2, 4(rSTR)
++	beq	cr7, L(dwalignnull)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpwi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check
++	   the first word and decrement the address in case the first word
++	   really contains a c/null byte.  */
++	cmpwi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++	b	L(done)
++L(loop):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	lwz	rWORD, 4(rSTR)
++	lwzu	rWORD2, 8(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpwi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a c/null byte.  */
++	cmpwi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done):
++	cntlzw	rTMP3, rTMP4		/* Count leading zeroes before c
++					   matches.  */
++	cntlzw	rMASK, rTMP5		/* Count leading zeroes before null
++					   matches.  */
++	cmplw	cr7, rTMP3, rMASK
++	bgt	cr7, L(no_match)
++	srwi	rMASK, rTMP3, 3		/* Convert leading zeroes to bytes.  */
++	add	rRTN, rSTR, rMASK	/* Return addr of the matching c byte
++					   or null in case c is not found.  */
++	addi	rTMP4, rRTN, 1
++L(loop_check):
++	andi.	rTMP3, rTMP4, 7		/* check for double word boundary.  */
++	beq	L(loop)
++	subfic	rTMP3, rTMP3, 8
++	cmpwi	cr6, rTMP3, 4
++	clrrwi	rSTR, rTMP4, 2		/* Align address to word boundary.  */
++	lwz	rWORD, 0(rSTR)
++	beq	cr6, L(word2_check)
++	ble	cr6, L(LTword2_check)
++	rlwinm	rMASK, rTMP4, 3, 27, 28	/* Calculate padding.  */
++	/* By now the rCHR has a word of c bytes and the rTMP1 has a word
++	   of null bytes.  */
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	/* Handle WORD2 of pair.  */
++	lwzu	rWORD, 4(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)			/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(LTword2_check):
++	rlwinm	rMASK, rTMP4, 3, 27, 28	/* Calculate padding.  */
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP4, rTMP4, rMASK
++	slw	rTMP5, rTMP5, rMASK
++	srw	rTMP4, rTMP4, rMASK
++	srw	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpwi	cr7, rTMP2, 0		/* If rTMP2 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	b	L(loop)
++L(word2_check):
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)
++L(no_match):
++	blr
++	/* We are here because strrchr was called with a null byte.  */
++L(null_match):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP2, rTMP2, rMASK
++	srw	rTMP2, rTMP2, rMASK
++	cmpwi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	/* Handle WORD2 of pair.  */
++	lwzu	rWORD, 4(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(null_LTword2):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	slw	rTMP2, rTMP2, rMASK
++	srw	rTMP2, rTMP2, rMASK
++	cmpwi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	b	L(loop_null)
++L(null_word2):
++	/* Handle WORD2 of pair.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpwi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(dwalignnull):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for
++	   bigger strings.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rWORD2, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpwi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpwi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++	b	L(done_null)
++L(loop_null):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for bigger
++	   strings.  */
++	lwz	rWORD, 4(rSTR)
++	lwzu	rTMP5, 8(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rTMP5, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpwi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpwi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -4
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 4
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done_null):
++	cntlzw	rTMP1, rTMP2		/* Count leading zeros before match.  */
++	srwi	rTMP1, rTMP1, 3		/* Convert leading zeros to bytes.  */
++	add	rRTN, rSTR, rTMP1	/* Return address of the matching null
++					   byte.  */
++	blr
++
++END (strrchr)
++
++weak_alias (strrchr, rindex)
++libc_hidden_builtin_def (strrchr)
+diff -Naur vanilla/sysdeps/powerpc/powerpc64/e5500/strrchr.S patched/sysdeps/powerpc/powerpc64/e5500/strrchr.S
+--- vanilla/sysdeps/powerpc/powerpc64/e5500/strrchr.S	1969-12-31 18:00:00.000000000 -0600
++++ patched/sysdeps/powerpc/powerpc64/e5500/strrchr.S	2015-03-13 03:28:16.701951974 -0500
+@@ -0,0 +1,351 @@
++/* Optimized strrchr implementation for 64-bit e5500 PowerPC target.
++   Based on POWER7 strchr implementation.
++   Copyright (C) 2010-2015 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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++
++/* See strlen.s for comments on how this works.  */
++
++/* char * [r3] strrchr (const char *s [r3] , int c [r4])  */
++
++ENTRY (strrchr)
++	CALL_MCOUNT 2
++
++#define rTMP1	r0
++#define rRTN	r3	/* outgoing result.  */
++#define rSTR	r8	/* current word pointer.  */
++#define rCHR	r4	/* byte we are looking for, spread over the whole
++			   word.  */
++#define rTMP2	r5
++#define rMASK	r6	/* calculate padding bits.  */
++#define rTMP3	r7
++#define rWORD	r12	/* the current word.  */
++#define rWORD2	r9	/* following word.  */
++#define rTMP4	r10
++#define rTMP5	r11
++
++	dcbt	0, rRTN
++	andi.	rTMP3, rRTN, 15		/* check for 4 word boundary.  */
++	cmpwi	cr7, rCHR, 0
++	li	rTMP1, 0
++	/* Replicate byte to double word.  */
++	rlwimi	rCHR, rCHR, 8, 16, 23
++	rlwimi	rCHR, rCHR, 16, 0, 15
++	insrdi	rCHR, rCHR, 32, 0
++	beq	L(qwalign)
++	subfic	rTMP3, rTMP3, 16
++	cmpldi	cr6, rTMP3, 8
++	clrrdi	rSTR, rRTN, 3		/* Align the address to double word
++					   boundary.  */
++	beq	cr6, L(doubleword2)
++	blt	cr6, L(LTdoubleword2)
++	ld	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 26, 28	/* Calculate padding.  */
++	/* By now the rCHR has a word of c bytes and the rTMP1 has a word of
++	   null bytes.  */
++	li	rRTN, 0
++	beq	cr7, L(null_match)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not part
++	   of the string and to bring them back as zeros.  */
++	sld	rTMP4, rTMP4, rMASK
++	sld	rTMP5, rTMP5, rMASK
++	srd	rTMP4, rTMP4, rMASK
++	srd	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpdi	cr7, rTMP2, 0		/* If rTMP2==0,no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	/* Handle WORD2 of pair.  */
++	ldu	rWORD, 8(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)			/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(LTdoubleword2):
++	ld	rWORD, 0(rSTR)		/* Load word from memory.  */
++	rlwinm	rMASK, rRTN, 3, 26, 28	/* Calculate padding.  */
++	/* By now rCHR has a word of c bytes and rTMP1 has a word of null
++	   bytes.  */
++	li	rRTN, 0
++	beq	cr7, L(null_LTdoubleword2)
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	sld	rTMP4, rTMP4, rMASK
++	sld	rTMP5, rTMP5, rMASK
++	srd	rTMP4, rTMP4, rMASK
++	srd	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpdi	cr7, rTMP2, 0		/* If rTMP2==0,no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	b	L(loop)
++L(doubleword2):
++	ld	rWORD, 0(rSTR)
++	li	rRTN, 0
++	beq	cr7, L(null_doubleword2)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)
++L(qwalign):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for bigger
++	   strings.  */
++	mr	rSTR, rRTN
++	li	rRTN, 0
++	ld	rWORD, 0(rSTR)
++	ldu	rWORD2, 8(rSTR)
++	beq	cr7, L(qwalignnull)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpdi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a c/null byte.  */
++	cmpdi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -8
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 8
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++	b	L(done)
++L(loop):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for bigger
++	   strings.  */
++	ld	rWORD, 8(rSTR)
++	ldu	rWORD2, 16(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	cmpb	rMASK, rWORD2, rCHR
++	cmpb	rTMP3, rWORD2, rTMP1
++	or	rWORD, rTMP4, rTMP5
++	or	rWORD2, rMASK, rTMP3
++	or	rTMP2, rWORD, rWORD2
++	cmpdi	cr7, rTMP2, 0
++	beq	cr7, L(loop)
++	/* OK, one (or both) of the words contains a c/null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a c/null byte.  */
++	cmpdi	cr6, rWORD, 0
++	addi	rSTR, rSTR, -8
++	bne	cr6, L(done)
++	/* The c/null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP4, rMASK
++	mr	rTMP5, rTMP3
++	addi	rSTR, rSTR, 8
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the c/null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done):
++	cntlzd	rTMP3, rTMP4		/* Count the leading zeroes before c
++					   matches.  */
++	cntlzd	rMASK, rTMP5		/* Count the leading zeroes before
++					   null matches.  */
++	cmpld	cr7, rTMP3, rMASK
++	bgt	cr7, L(no_match)
++	srdi	rMASK, rTMP3, 3		/* Convert leading zeroes to bytes.  */
++	add	rRTN, rSTR, rMASK	/* Return addr of the matching c byte
++					   or null in case c was not found.  */
++	addi	rTMP4, rRTN, 1
++L(loop_check):
++	andi.	rTMP3, rTMP4, 15	/* check for 4 word boundary.  */
++	beq	L(loop)
++	subfic	rTMP3, rTMP3, 16
++	cmpldi	cr6, rTMP3, 8
++	clrrdi	rSTR, rTMP4, 3		/* Align the address to double word
++					   boundary.  */
++	ld	rWORD, 0(rSTR)		/* Load double word from memory.  */
++	beq	cr6, L(doubleword2_check)
++	ble	cr6, L(LTdoubleword2_check)
++	rlwinm	rMASK, rTMP4, 3, 26, 28	/* Calculate padding.  */
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	sld	rTMP4, rTMP4, rMASK
++	sld	rTMP5, rTMP5, rMASK
++	srd	rTMP4, rTMP4, rMASK
++	srd	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpdi	cr7, rTMP2, 0		/* If rTMP2==0,no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	/* Handle WORD2 of pair.  */
++	ldu	rWORD, 8(rSTR)
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)			/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(LTdoubleword2_check):
++	rlwinm	rMASK, rTMP4, 3, 26, 28	/* Calculate padding.  */
++	cmpb	rTMP4, rWORD, rCHR	/* Compare each byte with c byte.  */
++	cmpb	rTMP5, rWORD, rTMP1	/* Compare each byte against null
++					   byte.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	sld	rTMP4, rTMP4, rMASK
++	sld	rTMP5, rTMP5, rMASK
++	srd	rTMP4, rTMP4, rMASK
++	srd	rTMP5, rTMP5, rMASK
++	or	rTMP2, rTMP4, rTMP5	/* OR results to speed things up.  */
++	cmpdi	cr7, rTMP2, 0		/* If rTMP2==0,no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done)
++	b	L(loop)
++L(doubleword2_check):
++	cmpb	rTMP4, rWORD, rCHR
++	cmpb	rTMP5, rWORD, rTMP1
++	or	rTMP2, rTMP4, rTMP5
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done)
++	b	L(loop)
++L(no_match):
++	blr
++	/* We are here because strrchr was called with a null byte.  */
++L(null_match):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	sld	rTMP2, rTMP2, rMASK
++	srd	rTMP2, rTMP2, rMASK
++	cmpdi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	/* Handle WORD2 of pair.  */
++	ldu	rWORD, 8(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(null_LTdoubleword2):
++	/* rTMP1 has a word of null bytes.  */
++	cmpb	rTMP2, rWORD, rTMP1	/* Compare each byte against null
++					   bytes.  */
++	/* Move the words left and right to discard the bits that are not
++	   part of the string and to bring them back as zeros.  */
++	sld	rTMP2, rTMP2, rMASK
++	srd	rTMP2, rTMP2, rMASK
++	cmpdi	cr7, rTMP2, 0		/* If rTMP4 == 0, no c or null bytes
++					   have been found.  */
++	bne	cr7, L(done_null)
++	b	L(loop_null)
++L(null_doubleword2):
++	/* Handle WORD2 of pair.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpdi	cr7, rTMP2, 0
++	bne	cr7, L(done_null)
++	b	L(loop_null)		/* We branch here (rather than falling
++					   through) to skip the nops due to
++					   heavy alignment of loop below.  */
++L(qwalignnull):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for bigger
++	   strings.  */
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rWORD2, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpdi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpdi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -8
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 8
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++	b	L(done_null)
++L(loop_null):
++	/* Load two words, compare and merge in a single register for speed.
++	   This is an attempt to speed up the null-checking process for bigger
++	   strings.  */
++	ld	rWORD, 8(rSTR)
++	ldu	rTMP5, 16(rSTR)
++	cmpb	rTMP2, rWORD, rTMP1
++	cmpb	rTMP4, rTMP5, rTMP1
++	or	rMASK, rTMP2, rTMP4
++	cmpdi	cr7, rMASK, 0
++	beq	cr7, L(loop_null)
++	/* OK, one (or both) of the words contains a null byte.  Check the
++	   first word and decrement the address in case the first word really
++	   contains a null byte.  */
++	cmpdi	cr6, rTMP2, 0
++	addi	rSTR, rSTR, -8
++	bne	cr6, L(done_null)
++	/* The null byte must be in the second word.  Adjust the address
++	   again and move the result of cmpb to rTMP4 so we can calculate the
++	   pointer.  */
++	mr	rTMP2, rTMP4
++	addi	rSTR, rSTR, 8
++	/* rTMP2 has the output of the cmpb instruction, that is, it contains
++	   0xff in the same position as the null byte in the original word
++	   from the string.  Use that to calculate the pointer.  */
++L(done_null):
++	cntlzd	rTMP1, rTMP2		/* Count the leading zeros before the
++					   match.  */
++	srdi	rTMP1, rTMP1, 3		/* Convert leading zeros to bytes.  */
++	add	rRTN, rSTR, rTMP1	/* Return address of the matching null
++					   byte.  */
++	blr
++
++END (strrchr)
++
++weak_alias (strrchr, rindex)
++libc_hidden_builtin_def (strrchr)
diff --git a/recipes-core/glibc/glibc-fsl/0018.glibc.testsuite_remove-blocking-test.patch b/recipes-core/glibc/glibc-fsl/0018.glibc.testsuite_remove-blocking-test.patch
new file mode 100755
index 0000000..920274f
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0018.glibc.testsuite_remove-blocking-test.patch
@@ -0,0 +1,258 @@
+# Problem Statement:
+  Temporary fix for the eglibc tests to continue running without getting hanged
+
+# Owned By:
+  Ram
+
+# Actions:
+  Remove the 'rt/tst-mqueue3.c' test case, which is blocking the tests to
+  continue, from the eglibc testsuite
+
+
+diff -Naur libc/rt/tst-mqueue3.c libc_eglibc_tests/rt/tst-mqueue3.c
+--- libc/rt/tst-mqueue3.c	2014-06-11 02:44:11.000000000 -0500
++++ libc_eglibc_tests/rt/tst-mqueue3.c	1969-12-31 18:00:00.000000000 -0600
+@@ -1,243 +0,0 @@
+-/* Test SIGEV_THREAD handling for POSIX message queues.
+-   Copyright (C) 2004-2014 Free Software Foundation, Inc.
+-   This file is part of the GNU C Library.
+-   Contributed by Ulrich Drepper <drepper at redhat.com>, 2004.
+-
+-   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, see
+-   <http://www.gnu.org/licenses/>.  */
+-
+-#include <errno.h>
+-#include <mqueue.h>
+-#include <signal.h>
+-#include <stddef.h>
+-#include <stdint.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <sys/mman.h>
+-#include <sys/wait.h>
+-#include <unistd.h>
+-
+-#if _POSIX_THREADS
+-# include <pthread.h>
+-
+-static pid_t pid;
+-static mqd_t m;
+-static const char message[] = "hello";
+-
+-# define MAXMSG 10
+-# define MSGSIZE 10
+-# define UNIQUE 42
+-
+-
+-static void
+-fct (union sigval s)
+-{
+-  /* Put the mq in non-blocking mode.  */
+-  struct mq_attr attr;
+-  if (mq_getattr (m, &attr) != 0)
+-    {
+-      printf ("%s: mq_getattr failed: %m\n", __FUNCTION__);
+-      exit (1);
+-    }
+-  attr.mq_flags |= O_NONBLOCK;
+-  if (mq_setattr (m, &attr, NULL) != 0)
+-    {
+-      printf ("%s: mq_setattr failed: %m\n", __FUNCTION__);
+-      exit (1);
+-    }
+-
+-  /* Check the values.  */
+-  if (attr.mq_maxmsg != MAXMSG)
+-    {
+-      printf ("%s: mq_maxmsg wrong: is %ld, expecte %d\n",
+-	      __FUNCTION__, attr.mq_maxmsg, MAXMSG);
+-      exit (1);
+-    }
+-  if (attr.mq_msgsize != MAXMSG)
+-    {
+-      printf ("%s: mq_msgsize wrong: is %ld, expecte %d\n",
+-	      __FUNCTION__, attr.mq_msgsize, MSGSIZE);
+-      exit (1);
+-    }
+-
+-  /* Read the message.  */
+-  char buf[attr.mq_msgsize];
+-  ssize_t n = TEMP_FAILURE_RETRY (mq_receive (m, buf, attr.mq_msgsize, NULL));
+-  if (n != sizeof (message))
+-    {
+-      printf ("%s: length of message wrong: is %zd, expected %zu\n",
+-	      __FUNCTION__, n, sizeof (message));
+-      exit (1);
+-    }
+-  if (memcmp (buf, message, sizeof (message)) != 0)
+-    {
+-      printf ("%s: message wrong: is \"%s\", expected \"%s\"\n",
+-	      __FUNCTION__, buf, message);
+-      exit (1);
+-    }
+-
+-  exit (UNIQUE);
+-}
+-
+-
+-int
+-do_test (void)
+-{
+-  char tmpfname[] = "/tmp/tst-mqueue3-barrier.XXXXXX";
+-  int fd = mkstemp (tmpfname);
+-  if (fd == -1)
+-    {
+-      printf ("cannot open temporary file: %m\n");
+-      return 1;
+-    }
+-
+-  /* Make sure it is always removed.  */
+-  unlink (tmpfname);
+-
+-  /* Create one page of data.  */
+-  size_t ps = sysconf (_SC_PAGESIZE);
+-  char data[ps];
+-  memset (data, '\0', ps);
+-
+-  /* Write the data to the file.  */
+-  if (write (fd, data, ps) != (ssize_t) ps)
+-    {
+-      puts ("short write");
+-      return 1;
+-    }
+-
+-  void *mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+-  if (mem == MAP_FAILED)
+-    {
+-      printf ("mmap failed: %m\n");
+-      return 1;
+-    }
+-
+-  pthread_barrier_t *b;
+-  b = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
+-                             & ~(__alignof (pthread_barrier_t) - 1));
+-
+-  pthread_barrierattr_t a;
+-  if (pthread_barrierattr_init (&a) != 0)
+-    {
+-      puts ("barrierattr_init failed");
+-      return 1;
+-    }
+-
+-  if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+-    {
+-      puts ("barrierattr_setpshared failed, could not test");
+-      return 0;
+-    }
+-
+-  if (pthread_barrier_init (b, &a, 2) != 0)
+-    {
+-      puts ("barrier_init failed");
+-      return 1;
+-    }
+-
+-  if (pthread_barrierattr_destroy (&a) != 0)
+-    {
+-      puts ("barrierattr_destroy failed");
+-      return 1;
+-    }
+-
+-  /* Name for the message queue.  */
+-  char mqname[sizeof ("/tst-mqueue3-") + 3 * sizeof (pid_t)];
+-  snprintf (mqname, sizeof (mqname) - 1, "/tst-mqueue3-%ld",
+-	    (long int) getpid ());
+-
+-  /* Create the message queue.  */
+-  struct mq_attr attr = { .mq_maxmsg = MAXMSG, .mq_msgsize = MSGSIZE };
+-  m = mq_open (mqname, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+-  if (m == -1)
+-    {
+-      if (errno == ENOSYS)
+-	{
+-	  puts ("not implemented");
+-	  return 0;
+-	}
+-
+-      puts ("mq_open failed");
+-      return 1;
+-    }
+-
+-  /* Unlink the message queue right away.  */
+-  if (mq_unlink (mqname) != 0)
+-    {
+-      puts ("mq_unlink failed");
+-      return 1;
+-    }
+-
+-  pid = fork ();
+-  if (pid == -1)
+-    {
+-      puts ("fork failed");
+-      return 1;
+-    }
+-  if (pid == 0)
+-    {
+-      /* Request notification via thread.  */
+-      struct sigevent ev;
+-      ev.sigev_notify = SIGEV_THREAD;
+-      ev.sigev_notify_function = fct;
+-      ev.sigev_value.sival_ptr = NULL;
+-      ev.sigev_notify_attributes = NULL;
+-
+-      /* Tell the kernel.  */
+-      if (mq_notify (m,&ev) != 0)
+-	{
+-	  puts ("mq_notify failed");
+-	  exit (1);
+-	}
+-
+-      /* Tell the parent we are ready.  */
+-      (void) pthread_barrier_wait (b);
+-
+-      /* Make sure the process goes away eventually.  */
+-      alarm (10);
+-
+-      /* Do nothing forever.  */
+-      while (1)
+-	pause ();
+-    }
+-
+-  /* Wait for the child process to register to notification method.  */
+-  (void) pthread_barrier_wait (b);
+-
+-  /* Send the message.  */
+-  if (mq_send (m, message, sizeof (message), 1) != 0)
+-    {
+-      kill (pid, SIGKILL);
+-      puts ("mq_send failed");
+-      return 1;
+-    }
+-
+-  int r;
+-  if (TEMP_FAILURE_RETRY (waitpid (pid, &r, 0)) != pid)
+-    {
+-      kill (pid, SIGKILL);
+-      puts ("waitpid failed");
+-      return 1;
+-    }
+-
+-  return WIFEXITED (r) && WEXITSTATUS (r) == UNIQUE ? 0 : 1;
+-}
+-# define TEST_FUNCTION do_test ()
+-#else
+-# define TEST_FUNCTION 0
+-#endif
+-
+-#include "../test-skeleton.c"
diff --git a/recipes-core/glibc/glibc-fsl/0019.glibc.readv_proto.patch b/recipes-core/glibc/glibc-fsl/0019.glibc.readv_proto.patch
new file mode 100755
index 0000000..df9da4e
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0019.glibc.readv_proto.patch
@@ -0,0 +1,61 @@
+glibc.readv_proto
+
+Unfortunate choice of variable names. Causes syntax errors on Altivec
+enabled targets.
+
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/readv.c glibc-2.20-patch/sysdeps/unix/sysv/linux/readv.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/readv.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/readv.c	2015-02-12 10:56:11.773738962 -0600
+@@ -27,20 +27,20 @@
+ /* Consider moving to syscalls.list.  */
+ 
+ ssize_t
+-__libc_readv (fd, vector, count)
++__libc_readv (fd, vec_tor, count)
+      int fd;
+-     const struct iovec *vector;
++     const struct iovec *vec_tor;
+      int count;
+ {
+   ssize_t result;
+ 
+   if (SINGLE_THREAD_P)
+-    result = INLINE_SYSCALL (readv, 3, fd, vector, count);
++    result = INLINE_SYSCALL (readv, 3, fd, vec_tor, count);
+   else
+     {
+       int oldtype = LIBC_CANCEL_ASYNC ();
+ 
+-      result = INLINE_SYSCALL (readv, 3, fd, vector, count);
++      result = INLINE_SYSCALL (readv, 3, fd, vec_tor, count);
+ 
+       LIBC_CANCEL_RESET (oldtype);
+     }
+diff -Naur glibc-2.20/sysdeps/unix/sysv/linux/writev.c glibc-2.20-patch/sysdeps/unix/sysv/linux/writev.c
+--- glibc-2.20/sysdeps/unix/sysv/linux/writev.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/sysdeps/unix/sysv/linux/writev.c	2015-02-12 10:56:11.774738974 -0600
+@@ -28,20 +28,20 @@
+ /* Consider moving to syscalls.list.  */
+ 
+ ssize_t
+-__libc_writev (fd, vector, count)
++__libc_writev (fd, vec_tor, count)
+      int fd;
+-     const struct iovec *vector;
++     const struct iovec *vec_tor;
+      int count;
+ {
+   ssize_t result;
+ 
+   if (SINGLE_THREAD_P)
+-    result = INLINE_SYSCALL (writev, 3, fd, vector, count);
++    result = INLINE_SYSCALL (writev, 3, fd, vec_tor, count);
+   else
+     {
+       int oldtype = LIBC_CANCEL_ASYNC ();
+ 
+-      result = INLINE_SYSCALL (writev, 3, fd, vector, count);
++      result = INLINE_SYSCALL (writev, 3, fd, vec_tor, count);
+ 
+       LIBC_CANCEL_RESET (oldtype);
+     }
diff --git a/recipes-core/glibc/glibc-fsl/0020.glibc.fsl-largemcpy-e500mc-e5500-e6500.patch b/recipes-core/glibc/glibc-fsl/0020.glibc.fsl-largemcpy-e500mc-e5500-e6500.patch
new file mode 100755
index 0000000..b0097f7
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0020.glibc.fsl-largemcpy-e500mc-e5500-e6500.patch
@@ -0,0 +1,932 @@
+diff -ruN glibc-2.20-mcpy-new-large-original/include/string.h glibc-2.20-mcpy-new-large-mcpy-new/include/string.h
+--- glibc-2.20-mcpy-new-large-original/include/string.h	2015-09-02 14:28:58.404187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/include/string.h	2015-09-02 14:30:49.773187000 -0500
+@@ -70,6 +70,9 @@
+     }))
+ #endif
+ 
++#if defined (__powerpc__)
++libc_hidden_proto (largememcpy)
++#endif
+ libc_hidden_proto (__mempcpy)
+ libc_hidden_proto (__stpcpy)
+ libc_hidden_proto (__stpncpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/string/string.h glibc-2.20-mcpy-new-large-mcpy-new/string/string.h
+--- glibc-2.20-mcpy-new-large-original/string/string.h	2015-09-02 14:28:58.383187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/string/string.h	2015-09-02 14:30:49.752187000 -0500
+@@ -45,6 +45,10 @@
+ /* Copy N bytes of SRC to DEST.  */
+ extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
+ 		     size_t __n) __THROW __nonnull ((1, 2));
++#if defined (__powerpc__)
++extern void *largememcpy (void *__restrict __dest, const void *__restrict __src,
++		     size_t __n) __THROW __nonnull ((1, 2));
++#endif
+ /* Copy N bytes of SRC to DEST, guaranteeing
+    correct behavior for overlapping strings.  */
+ extern void *memmove (void *__dest, const void *__src, size_t __n)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/memcpy.c glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/memcpy.c
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/memcpy.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/memcpy.c	2015-09-02 14:30:49.590187000 -0500
+@@ -0,0 +1,4 @@
++#include <string/memcpy.c>
++
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/405/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/405/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/405/memcpy.S	2015-09-02 14:28:58.206187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/405/memcpy.S	2015-09-02 14:30:49.554187000 -0500
+@@ -128,3 +128,5 @@
+        blr
+ END (memcpy)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/a2/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/a2/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/a2/memcpy.S	2015-09-02 14:28:58.194187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/a2/memcpy.S	2015-09-02 14:30:49.541187000 -0500
+@@ -525,3 +525,5 @@
+ 
+ END (memcpy)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/cell/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/cell/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/cell/memcpy.S	2015-09-02 14:28:58.213187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/cell/memcpy.S	2015-09-02 14:30:49.561187000 -0500
+@@ -240,3 +240,5 @@
+ 
+ END (memcpy)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500/memcpy.S	2015-09-02 14:29:07.888186901 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500/memcpy.S	2015-09-02 14:30:49.539187000 -0500
+@@ -406,3 +406,8 @@
+ 
+ END (FUNCTION)
+ libc_hidden_builtin_def (FUNCTION)
++
++#ifndef __MEMMOVE__
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
++#endif
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500mc/largememcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500mc/largememcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500mc/largememcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500mc/largememcpy.S	2015-09-02 14:54:00.062186965 -0500
+@@ -0,0 +1,499 @@
++/* Optimized largememcpy implementation for e500mc 32-bit PowerPC.
++   This version uses cache management instructions.
++
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3]
++   largememcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++EALIGN (largememcpy, 5, 0)
++	cmplw	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 8 (optimal value TBD),
++	   but greater than zero, copy byte-by-byte.  */
++	cmplwi	r5, 8
++	mr	r6, r3
++	blt	L(copy_bytes)
++	neg	r0, r4
++	andi.	r11, r0, 3
++	beq	L(src_aligned4)
++        /* We have to align the src pointer by r11 bytes */
++	cmplwi  cr0, r11, 1
++	ble     L(src_1)
++	/* 2 or 3 bytes */
++	addi    r8, r11, -2
++	lhz     r9, 0(r4)
++	lhzx    r12, r4, r8
++	sth     r9, 0(r6)
++	sthx    r12, r6, r8
++	b       L(src_0)
++L(src_1):
++	lbz     r8, 0(r4)
++	stb     r8, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(src_aligned4):
++	cmplwi	7, r5, 63
++	ble	7, L(copy_remaining)
++	andi.	r10, r0, 63
++	beq	L(src_aligned64)
++	subf.	r10, r11, r10
++	beq	0, L(src_aligned64)
++	srwi	r11, r10, 2
++	subf	r5, r10, r5
++	mtctr	r11
++L(copy_salign4):
++	lwz	0, 0(r4)
++	addi	r4, r4, 4
++	stw	0, 0(r6)
++	addi	r6, r6, 4
++	bdnz	L(copy_salign4)
++L(src_aligned64):
++	srwi.	r11, r5, 6		/* No of 64 byte copy count.  */
++	beq	0, L(copy_remaining)
++	rlwinm	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	rlwinm.	r0, r6, 0, 29, 31
++	bne	0, L(src_dnalign)
++	cmplwi	7, r11, 256
++	ble	7, L(label1)
++	addi	r7, r11, -256
++	mtctr	r7
++#ifdef SHARED
++	mflr	r0
++	/* Establishes GOT addressability so we can load __cache_line_size from
++	   static.  This value was set from the aux vector during startup.  */
++	SETUP_GOT_ACCESS(r9,got_label_1)
++	addis	r9, r9, __cache_line_size-got_label_1 at ha
++	lwz	r9, __cache_line_size-got_label_1 at l(r9)
++	mtlr	r0
++#else
++	/* Load __cache_line_size from static.  This value was set from the
++	   aux vector during startup.  */
++	lis	r9, __cache_line_size at ha
++	lwz	r9, __cache_line_size at l(r9)
++#endif
++	cmplwi	5, r9, 64
++	li	r10, 256
++	li	r12, 64
++	bne	5, L(lcopy_dalign_nc)
++L(lcopy_dalign):
++	dcbt	r10, r4
++	dcbzl	r12, r6
++#ifndef _SOFT_FLOAT
++	lfd	0, 0(r4)
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	lfd	4, 32(r4)
++	lfd	5, 40(r4)
++	lfd	6, 48(r4)
++	lfd	7, 56(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	addi	r4, r4, 64
++	stfd	4, 32(r6)
++	stfd	5, 40(r6)
++	stfd	6, 48(r6)
++	stfd	7, 56(r6)
++#else
++	lwz	r0, 0(r4)
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++#endif
++	dcbf	0, r6
++	addi	r6, r6, 64
++	bdnz	L(lcopy_dalign)
++	subf	r11, r7, r11
++L(label1):
++	mtctr	r11
++L(copy_dalign):
++#ifndef _SOFT_FLOAT
++	lfd	0, 0(r4)
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	lfd	0, 32(r4)
++	lfd	1, 40(r4)
++	lfd	2, 48(r4)
++	lfd	3, 56(r4)
++	addi	r4, r4, 64
++	stfd	0, 32(r6)
++	stfd	1, 40(r6)
++	stfd	2, 48(r6)
++	stfd	3, 56(r6)
++#else
++	lwz	r0, 0(r4)
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++#endif
++	addi	r6, r6, 64
++	bdnz	L(copy_dalign)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	lwz	r0, 0(r4)		/* copy 32 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	addi	r4, r4, 32
++	stw	r9, 20(r6)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)
++	lwz	r0, 0(r4)		/* copy 16 bytes.  */
++	lwz	r7, 4(r4)
++	lwz	r8, 8(r4)
++	lwz	r9, 12(r4)
++	addi	r4, r4, 16
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	stw	r8, 8(r6)
++	stw	r9, 12(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)
++	lwz	r0, 0(r4)		/* copy 8 bytes.  */
++	lwz	r7, 4(r4)
++	addi	r4, r4, 8
++	stw	r0, 0(r6)
++	stw	r7, 4(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmplwi	cr1, r5, 4
++	cmplwi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++
++L(src_dnalign):
++	cmplwi	7, r11, 256
++	ble	7, L(label2)
++	addi	r7, r11, -256
++	mtctr	r7
++#ifdef SHARED
++	mflr	r0
++	/* Establishes GOT addressability so we can load __cache_line_size from
++	   static.  This value was set from the aux vector during startup.  */
++	SETUP_GOT_ACCESS(r9,got_label_2)
++	addis	r9, r9, __cache_line_size-got_label_2 at ha
++	lwz	r9, __cache_line_size-got_label_2 at l(r9)
++	mtlr	r0
++#else
++	/* Load __cache_line_size from static.  This value was set from the
++	   aux vector during startup.  */
++	lis	r9, __cache_line_size at ha
++	lwz	r9, __cache_line_size at l(r9)
++#endif
++	cmplwi	5, r9, 64
++	li	r10, 256
++	li	r12, 64
++	bne	5, L(lcopy_dnalign_nc)
++L(lcopy_dnalign):
++	dcbt	r10, r4
++	dcbzl	r12, r6
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++	dcbf	0, r6
++	addi	r6, r6, 64
++	bdnz	L(lcopy_dnalign)
++	li	r11, 256
++L(label2):
++	mtctr	r11
++L(copy_dnalign):
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_dnalign)
++	b	L(copy_remaining)
++
++L(lcopy_dalign_nc):
++#ifndef _SOFT_FLOAT
++	lfd	0, 0(r4)		/* copy 64 bytes.  */
++	lfd	1, 8(r4)
++	lfd	2, 16(r4)
++	lfd	3, 24(r4)
++	lfd	4, 32(r4)
++	lfd	5, 40(r4)
++	lfd	6, 48(r4)
++	lfd	7, 56(r4)
++	stfd	0, 0(r6)
++	stfd	1, 8(r6)
++	stfd	2, 16(r6)
++	stfd	3, 24(r6)
++	addi	r4, r4, 64
++	stfd	4, 32(r6)
++	stfd	5, 40(r6)
++	stfd	6, 48(r6)
++	stfd	7, 56(r6)
++#else
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++#endif
++	addi	r6, r6, 64
++	bdnz	L(lcopy_dalign_nc)
++	subf	r11, r7, r11
++	b	L(label1)
++
++L(lcopy_dnalign_nc):
++	lwz	r0, 0(r4)		/* copy 64 bytes.  */
++	lwz	r8, 4(r4)
++	lwz	r9, 8(r4)
++	stw	r0, 0(r6)
++	stw	r8, 4(r6)
++	stw	r9, 8(r6)
++	lwz	r0, 12(r4)
++	lwz	r8, 16(r4)
++	lwz	r9, 20(r4)
++	stw	r0, 12(r6)
++	stw	r8, 16(r6)
++	stw	r9, 20(r6)
++	lwz	r0, 24(r4)
++	lwz	r8, 28(r4)
++	lwz	r9, 32(r4)
++	stw	r0, 24(r6)
++	stw	r8, 28(r6)
++	stw	r9, 32(r6)
++	lwz	r0, 36(r4)
++	lwz	r8, 40(r4)
++	lwz	r9, 44(r4)
++	stw	r0, 36(r6)
++	stw	r8, 40(r6)
++	stw	r9, 44(r6)
++	lwz	r0, 48(r4)
++	lwz	r8, 52(r4)
++	lwz	r9, 56(r4)
++	stw	r0, 48(r6)
++	lwz	r0, 60(r4)
++	addi	r4, r4, 64
++	stw	r8, 52(r6)
++	stw	r9, 56(r6)
++	stw	r0, 60(r6)
++	addi	r6, r6, 64
++	bdnz	L(lcopy_dnalign_nc)
++	li	r11, 256
++	b	L(label2)
++
++END (largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500mc/Makefile glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500mc/Makefile
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e500mc/Makefile	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e500mc/Makefile	2015-09-02 14:30:49.552187000 -0500
+@@ -0,0 +1,5 @@
++#Makefile fragment for PowerPC e500mc core
++
++ifeq ($(subdir),string)
++sysdep_routines += largememcpy
++endif
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e5500/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e5500/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e5500/memcpy.S	2015-09-02 14:28:58.208187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e5500/memcpy.S	2015-09-02 14:30:49.556187000 -0500
+@@ -249,4 +249,6 @@
+ 	b	L(copy_remaining)
+ 
+ END (memcpy)
++weak_alias (memcpy, largememcpy)
+ libc_hidden_builtin_def (memcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e6500/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e6500/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/e6500/memcpy.S	2015-09-02 14:28:58.214187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/e6500/memcpy.S	2015-09-02 14:30:49.562187000 -0500
+@@ -237,3 +237,5 @@
+ 
+ END (memcpy)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power4/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power4/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power4/memcpy.S	2015-09-02 14:28:58.194187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power4/memcpy.S	2015-09-02 14:30:49.541187000 -0500
+@@ -479,3 +479,5 @@
+ END (memcpy)
+ 
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power6/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power6/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power6/memcpy.S	2015-09-02 14:28:58.211187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power6/memcpy.S	2015-09-02 14:30:49.559187000 -0500
+@@ -905,3 +905,5 @@
+ END (memcpy)
+ 
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power7/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power7/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc32/power7/memcpy.S	2015-09-02 14:28:58.207187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc32/power7/memcpy.S	2015-09-02 14:30:49.555187000 -0500
+@@ -536,3 +536,5 @@
+ 
+ END (memcpy)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/a2/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/a2/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/a2/memcpy.S	2015-09-02 14:28:58.219187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/a2/memcpy.S	2015-09-02 14:30:49.567187000 -0500
+@@ -522,3 +522,5 @@
+ 
+ END_GEN_TB (memcpy,TB_TOCLESS)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/cell/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/cell/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/cell/memcpy.S	2015-09-02 14:28:58.239187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/cell/memcpy.S	2015-09-02 14:30:49.588187000 -0500
+@@ -240,3 +240,5 @@
+ 
+ END_GEN_TB (memcpy,TB_TOCLESS)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy, largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e5500/largememcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e5500/largememcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e5500/largememcpy.S	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e5500/largememcpy.S	2015-09-02 14:56:08.056186467 -0500
+@@ -0,0 +1,221 @@
++/* Optimized largememcpy implementation for e5500 64-bit PowerPC64.
++   This version uses cache management instructions.
++
++   Copyright (C) 2015 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 <sysdep.h>
++
++/* __ptr_t [r3] largememcpy __ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]
++   Returns 'dst'.
++
++	 r3 = destination
++	 r4 = source
++	 r5 = byte count
++
++	 volatile fixed point registers usable:
++	 r0, r3-r12
++
++	 volatile floating point registers usable:
++	 f0-f13.  */
++
++	.section ".toc", "aw"
++.LC0:
++	.tc __cache_line_size[TC], __cache_line_size
++	.section ".text"
++	.align 2
++
++EALIGN (largememcpy, 5, 0)
++	CALL_MCOUNT 3
++	cmpld	cr0, r4, r3		/* if source==destination, return.  */
++	beqlr	cr0
++	/* if number of bytes is less than 8, (optimal value TBD),
++	   but greater than zero copy byte-by-byte.  */
++	cmpldi	r5, 8
++	mr	r6, r3
++	blt	L(copy_bytes)
++	neg	r0, r4
++	andi.	r11, r0, 7
++	beq	L(src_aligned)
++	/* We have to align the src pointer by r11 bytes */
++	cmplwi	cr1, r11, 4
++	cmplwi	cr0, r11, 1
++	bgt	cr1, L(src_567)
++	ble	cr0, L(src_1)
++	/* 2, 3 or 4 bytes */
++	addi	r0, r11, -2
++	lhz	r9, 0(r4)
++	lhzx	r12, r4, r0
++	sth	r9, 0(r6)
++	sthx	r12, r6, r0
++	b	L(src_0)
++L(src_567):
++	addi	r0, r11, -4
++	lwz	r9, 0(r4)
++	lwzx	r12, r4, r0
++	stw	r9, 0(r6)
++	stwx	r12, r6, r0
++	b	L(src_0)
++L(src_1):
++	lbz	r0, 0(r4)
++	stb	r0, 0(r6)
++L(src_0):
++	subf	r5, r11, r5
++	add	r4, r4, r11
++	add	r6, r6, r11
++L(src_aligned):
++	cmpldi	7, r5, 63
++	ble	7, L(copy_remaining)
++	srwi	r11, r5, 6		/* No of 64 byte copy count.  */
++	rlwinm.	r5, r5, 0, 26, 31	/* remaining bytes.  */
++	cmpldi	7, r11, 256
++	ble	7, L(2)
++	rlwinm.	r0, r6, 0, 28, 31
++	cmpldi	r0, 8
++	addi	r7, r11, -256
++	mtctr	r7
++	ble	L(copy_dnaligned)
++	ld	r9, .LC0 at toc(r2)	/* get cache line size.  */
++	lwz	r9, 0(r9)
++	cmpldi	5, r9, 64
++	li	r10, 256
++	li	r12, 64
++	bne	5, L(copy_dnaligned)
++L(lcopy_daligned):
++	dcbt	r10, r4
++	dcbzl	r12, r6
++	ld	r0, 0(r4)		/* 64-byte copy.  */
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	ld	r0, 32(r4)
++	ld	r7, 40(r4)
++	ld	r8, 48(r4)
++	ld	r9, 56(r4)
++	addi	r4, r4, 64
++	std	r0, 32(r6)
++	std	r7, 40(r6)
++	std	r8, 48(r6)
++	std	r9, 56(r6)
++	dcbf	0, r6
++	addi	r6, r6, 64
++	bdnz	L(lcopy_daligned)
++L(1):	li	r11, 256
++L(2):	mtctr	r11
++L(copy_daligned):
++	ld	r0, 0(r4)
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	ld	r0, 32(r4)
++	ld	r7, 40(r4)
++	ld	r8, 48(r4)
++	ld	r9, 56(r4)
++	addi	r4, r4, 64
++	std	r0, 32(r6)
++	std	r7, 40(r6)
++	std	r8, 48(r6)
++	std	r9, 56(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_daligned)
++L(copy_remaining):
++	srwi.	r11, r5, 3		/* No of 8 byte copy count.  */
++	rlwinm	r5, r5, 0, 29, 31	/* remaining bytes.  */
++	beq	0, L(copy_bytes)
++	mtcrf	0x01, r11
++	bf	cr7*4+1, L(cp16b)
++	ld	r0, 0(r4)		/* copy 32 bytes.  */
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	addi	r4, r4, 32
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	addi	r6, r6, 32
++L(cp16b):
++	bf	cr7*4+2, L(cp8b)	/* copy 16 bytes.  */
++	ld	r7, 0(r4)
++	ld	r8, 8(r4)
++	addi	r4, r4, 16
++	std	r7, 0(r6)
++	std	r8, 8(r6)
++	addi	r6, r6, 16
++L(cp8b):
++	bf	cr7*4+3, L(copy_bytes)	/* copy 8 bytes.  */
++	ld	r7, 0(r4)
++	addi	r4, r4, 8
++	std	r7, 0(r6)
++	addi	r6, r6, 8
++L(copy_bytes):
++	cmpldi	cr1, r5, 4
++	cmpldi	cr0, r5, 1
++	bgt	cr1, L(gt4b)		/* nb > 4?  (5, 6, 7 bytes).  */
++	ble	cr0, L(lt1b)		/* nb <= 1? (0, 1 bytes).  */
++	addi	r0, r5, -2		/* 2, 3, 4 bytes.  */
++	lhz	r9, 0(r4)
++	lhzx	r11, r4, r0
++	sth	r9, 0(r6)
++	sthx	r11, r6, r0
++	blr
++L(gt4b):
++	addi	r0, r5, -4		/* 5, 6, 7 bytes.  */
++	lwz	r9, 0(r4)
++	lwzx	r11, r4, r0
++	stw	r9, 0(r6)
++	stwx	r11, r6, r0
++	blr
++L(lt1b):
++	mtocrf	0x1, r5			/* nb == 0 ? return.  */
++	bflr	31
++	lbz	r0, 0(r4)		/* nb == 1.  */
++	stb	r0, 0(r6)
++	blr
++L(copy_dnaligned):
++	ld	r0, 0(r4)
++	ld	r7, 8(r4)
++	ld	r8, 16(r4)
++	ld	r9, 24(r4)
++	std	r0, 0(r6)
++	std	r7, 8(r6)
++	std	r8, 16(r6)
++	std	r9, 24(r6)
++	ld	r0, 32(r4)
++	ld	r7, 40(r4)
++	ld	r8, 48(r4)
++	ld	r9, 56(r4)
++	addi	r4, r4, 64
++	std	r0, 32(r6)
++	std	r7, 40(r6)
++	std	r8, 48(r6)
++	std	r9, 56(r6)
++	addi	r6, r6, 64
++	bdnz	L(copy_dnaligned)
++	b	L(1)
++
++END_GEN_TB (largememcpy,TB_TOCLESS)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e5500/Makefile glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e5500/Makefile
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e5500/Makefile	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e5500/Makefile	2015-09-02 14:30:49.572187000 -0500
+@@ -0,0 +1,5 @@
++#Makefile fragment for PowerPC e5500 64-bit core
++
++ifeq ($(subdir),string)
++sysdep_routines += largememcpy
++endif
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e6500/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e6500/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/e6500/memcpy.S	2015-09-02 14:28:58.240187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/e6500/memcpy.S	2015-09-02 14:30:49.589187000 -0500
+@@ -210,4 +210,6 @@
+ 	b	L(copy_remaining)
+ 
+ END_GEN_TB (memcpy,TB_TOCLESS)
++weak_alias (memcpy,largememcpy)
+ libc_hidden_builtin_def (memcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power4/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power4/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power4/memcpy.S	2015-09-02 14:28:58.219187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power4/memcpy.S	2015-09-02 14:30:49.567187000 -0500
+@@ -472,3 +472,5 @@
+     blr
+ END_GEN_TB (memcpy,TB_TOCLESS)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power6/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power6/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power6/memcpy.S	2015-09-02 14:28:58.238187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power6/memcpy.S	2015-09-02 14:30:49.586187000 -0500
+@@ -1494,3 +1494,5 @@
+     blr
+ END_GEN_TB (memcpy,TB_TOCLESS)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power7/memcpy.S glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power7/memcpy.S
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/powerpc64/power7/memcpy.S	2015-09-02 14:28:58.222187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/powerpc64/power7/memcpy.S	2015-09-02 14:30:49.570187000 -0500
+@@ -424,3 +424,5 @@
+ 
+ END_GEN_TB (memcpy,TB_TOCLESS)
+ libc_hidden_builtin_def (memcpy)
++weak_alias (memcpy,largememcpy)
++libc_hidden_def (largememcpy)
+diff -ruN glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/Versions glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/Versions
+--- glibc-2.20-mcpy-new-large-original/sysdeps/powerpc/Versions	2015-09-02 14:28:58.244187000 -0500
++++ glibc-2.20-mcpy-new-large-mcpy-new/sysdeps/powerpc/Versions	2015-09-02 14:30:49.593187000 -0500
+@@ -9,6 +9,7 @@
+   GLIBC_2.3.4 {
+     _longjmp; __sigsetjmp; _setjmp;
+     longjmp; setjmp;
++    largememcpy;
+   }
+   GLIBC_PRIVATE {
+     __novmx__libc_longjmp; __novmx__libc_siglongjmp;
diff --git a/recipes-core/glibc/glibc-fsl/0021.glibc.undefined_static.patch b/recipes-core/glibc/glibc-fsl/0021.glibc.undefined_static.patch
new file mode 100755
index 0000000..baad08f
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0021.glibc.undefined_static.patch
@@ -0,0 +1,37 @@
+glibc.undefined_static
+
+This works around an old binutils bug, which would delete static
+constants out of the code, thus causing undefined symbols. Not sure if
+this patch is still needed.
+
+diff -rc libc-orig/stdio-common/psiginfo-define.h libc-new/stdio-common/psiginfo-define.h
+*** libc-orig/stdio-common/psiginfo-define.h	2009-04-09 08:12:53.000000000 -0500
+--- libc-new/stdio-common/psiginfo-define.h	2009-04-09 08:20:36.000000000 -0500
+***************
+*** 1,4 ****
+! static const union C(codestrs_t_, NOW) {
+    struct {
+  #define P(n, s) char MF(__LINE__)[sizeof (s)];
+  #include "psiginfo-data.h"
+--- 1,4 ----
+! const union C(codestrs_t_, NOW) {
+    struct {
+  #define P(n, s) char MF(__LINE__)[sizeof (s)];
+  #include "psiginfo-data.h"
+***************
+*** 8,14 ****
+  #define P(n, s) s,
+  #include "psiginfo-data.h"
+    } };
+! static const uint8_t C(codes_, NOW)[] = {
+  #define P(n, s) [(n) - 1] = offsetof (union C(codestrs_t_, NOW), MF(__LINE__)),
+  #include "psiginfo-data.h"
+  };
+--- 8,14 ----
+  #define P(n, s) s,
+  #include "psiginfo-data.h"
+    } };
+! const uint8_t C(codes_, NOW)[] = {
+  #define P(n, s) [(n) - 1] = offsetof (union C(codestrs_t_, NOW), MF(__LINE__)),
+  #include "psiginfo-data.h"
+  };
diff --git a/recipes-core/glibc/glibc-fsl/0022.glibc.use-option-groups.patch b/recipes-core/glibc/glibc-fsl/0022.glibc.use-option-groups.patch
new file mode 100644
index 0000000..631013b
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/0022.glibc.use-option-groups.patch
@@ -0,0 +1,149 @@
+From d6fe2c92acf68509ee00af1145ba0cfbd714426b Mon Sep 17 00:00:00 2001
+From: Ting Liu <ting.liu at freescale.com>
+Date: Fri, 14 Aug 2015 16:49:16 +0800
+Subject: [PATCH] 0024.glibc.use-option-groups.patch new updates
+
+Signed-off-by: Ting Liu <ting.liu at freescale.com>
+---
+ elf/Makefile                   | 10 +++++++---
+ include/libc-symbols.h         |  3 +--
+ misc/sys/xattr.h               |  2 --
+ sysdeps/ieee754/dbl-64/s_sin.c | 16 ++++++----------
+ 4 files changed, 14 insertions(+), 17 deletions(-)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 25012cc..dd6b330 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -17,6 +17,8 @@
+ 
+ # Makefile for elf subdirectory of GNU C Library.
+ 
++include ../option-groups.mak
++
+ subdir		:= elf
+ 
+ include ../Makeconfig
+@@ -144,10 +146,11 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
+ 	 unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
+ 	 tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
+ 	 tst-stackguard1 tst-addr1 tst-thrlock \
+-	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
++	 tst-unique1 tst-unique2 \
+ 	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+ 	 tst-ptrguard1
+ #	 reldep9
++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-unique3 tst-unique4
+ ifeq ($(build-hardcoded-path-in-tests),yes)
+ tests += tst-dlopen-aout
+ endif
+@@ -205,8 +208,6 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+ 		tst-unique1mod1 tst-unique1mod2 \
+ 		tst-unique2mod1 tst-unique2mod2 \
+ 		tst-auditmod9a tst-auditmod9b \
+-		tst-unique3lib tst-unique3lib2 \
+-		tst-unique4lib \
+ 		tst-initordera1 tst-initorderb1 \
+ 		tst-initordera2 tst-initorderb2 \
+ 		tst-initordera3 tst-initordera4 \
+@@ -214,6 +215,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+ 		tst-initorder2d \
+ 		tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
+ 		tst-array5dep tst-null-argv-lib
++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS))
++modules-names += tst-unique3lib tst-unique3lib2 tst-unique4lib 
++endif
+ ifeq (yesyes,$(have-fpie)$(build-shared))
+ modules-names += tst-piemod1
+ tests += tst-pie1 tst-pie2
+diff --git a/include/libc-symbols.h b/include/libc-symbols.h
+index d4ab1f3..25662cb 100644
+--- a/include/libc-symbols.h
++++ b/include/libc-symbols.h
+@@ -60,8 +60,7 @@
+ /* Define these macros for the benefit of portable GNU code that wants to check
+    them.  Of course, STDC_HEADERS is never false when building libc!  */
+ #define STDC_HEADERS	1
+-#define HAVE_MBSTATE_T	1
+-#define HAVE_MBSRTOWCS	1
++
+ #define HAVE_LIBINTL_H	1
+ #define HAVE_WCTYPE_H	1
+ #define HAVE_ISWCTYPE	1
+diff --git a/misc/sys/xattr.h b/misc/sys/xattr.h
+index 796df90..929cd87 100644
+--- a/misc/sys/xattr.h
++++ b/misc/sys/xattr.h
+@@ -26,7 +26,6 @@ __BEGIN_DECLS
+ 
+ /* The following constants should be used for the fifth parameter of
+    `*setxattr'.  */
+-#ifndef __USE_KERNEL_XATTR_DEFS
+ enum
+ {
+   XATTR_CREATE = 1,	/* set value, fail if attr already exists.  */
+@@ -34,7 +33,6 @@ enum
+   XATTR_REPLACE = 2	/* set value, fail if attr does not exist.  */
+ #define XATTR_REPLACE	XATTR_REPLACE
+ };
+-#endif
+ 
+ /* Set the attribute NAME of the file pointed to by PATH to VALUE (which
+    is SIZE bytes long).  Return 0 on success, -1 for errors.  */
+diff --git a/sysdeps/ieee754/dbl-64/s_sin.c b/sysdeps/ieee754/dbl-64/s_sin.c
+index 50109b8..6105e9f 100644
+--- a/sysdeps/ieee754/dbl-64/s_sin.c
++++ b/sysdeps/ieee754/dbl-64/s_sin.c
+@@ -447,21 +447,19 @@ __sin (double x)
+ 	    }
+ 	  else
+ 	    {
+-	      double t;
+ 	      if (a > 0)
+ 		{
+ 		  m = 1;
+-		  t = a;
+ 		  db = da;
+ 		}
+ 	      else
+ 		{
+ 		  m = 0;
+-		  t = -a;
++		  a = -a;
+ 		  db = -da;
+ 		}
+-	      u.x = big + t;
+-	      y = t - (u.x - big);
++	      u.x = big + a;
++	      y = a - (u.x - big);
+ 	      res = do_sin (u, y, db, &cor);
+ 	      cor = (cor > 0) ? 1.035 * cor + eps : 1.035 * cor - eps;
+ 	      retval = ((res == res + cor) ? ((m) ? res : -res)
+@@ -673,21 +671,19 @@
+ 	    }
+ 	  else
+ 	    {
+-	      double t;
+ 	      if (a > 0)
+ 		{
+ 		  m = 1;
+-		  t = a;
+ 		  db = da;
+ 		}
+ 	      else
+ 		{
+ 		  m = 0;
+-		  t = -a;
++		  a = -a;
+ 		  db = -da;
+ 		}
+-	      u.x = big + t;
+-	      y = t - (u.x - big);
++	      u.x = big + a;
++	      y = a - (u.x - big);
+ 	      res = do_sin (u, y, db, &cor);
+ 	      cor = (cor > 0) ? 1.035 * cor + eps : 1.035 * cor - eps;
+ 	      retval = ((res == res + cor) ? ((m) ? res : -res)
+-- 
+1.9.2
+
diff --git a/recipes-core/glibc/glibc-fsl/00xx.glibc.add-option-groups-support.patch b/recipes-core/glibc/glibc-fsl/00xx.glibc.add-option-groups-support.patch
new file mode 100755
index 0000000..eff2257
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/00xx.glibc.add-option-groups-support.patch
@@ -0,0 +1,1389 @@
+# Problem Statement:
+  Port eglibc option group infrastructure to glibc v2.20.
+
+# Referred from patch by:
+  Yocto Project
+  http://git.yoctoproject.org/cgit.cgi/poky/plain/meta/recipes-core/glibc/glibc/option-groups.patch
+  Upstream-Status: Pending
+
+diff -Naur glibc-2.20/config.make.in glibc-2.20-patch/config.make.in
+--- glibc-2.20/config.make.in	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/config.make.in	2015-02-19 03:54:24.155759769 -0600
+@@ -46,6 +46,8 @@
+ c++-sysincludes = @CXX_SYSINCLUDES@
+ all-warnings = @all_warnings@
+ 
++kconfig_tools = @KCONFIG_TOOLS@
++
+ have-z-combreloc = @libc_cv_z_combreloc@
+ have-z-execstack = @libc_cv_z_execstack@
+ have-Bgroup = @libc_cv_Bgroup@
+diff -Naur glibc-2.20/configure glibc-2.20-patch/configure
+--- glibc-2.20/configure	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/configure	2015-02-19 03:54:24.157759768 -0600
+@@ -619,6 +619,7 @@
+ PERL
+ BASH_SHELL
+ libc_cv_gcc_static_libgcc
++KCONFIG_TOOLS
+ CXX_SYSINCLUDES
+ SYSINCLUDES
+ AUTOCONF
+@@ -733,6 +734,7 @@
+ with_binutils
+ with_selinux
+ with_headers
++with_kconfig
+ with_default_link
+ enable_sanity_checks
+ enable_shared
+@@ -1437,6 +1439,9 @@
+   --with-selinux          if building with SELinux support
+   --with-headers=PATH     location of system headers to use (for example
+                           /usr/src/linux/include) [default=compiler default]
++  --with-kconfig=PATH     location of kconfig tools to use (from Linux kernel
++                          builds) to re-use for configuring EGLIBC option
++                          groups
+   --with-default-link     do not use explicit linker scripts
+   --with-cpu=CPU          select code for CPU variant
+ 
+@@ -3400,6 +3405,14 @@
+ 
+ 
+ 
++# Check whether --with-kconfig was given.
++if test "${with_kconfig+set}" = set; then
++  withval=$with_kconfig; KCONFIG_TOOLS=$withval
++else
++  KCONFIG_TOOLS=''
++fi
++
++
+ 
+ # Check whether --with-default-link was given.
+ if test "${with_default_link+set}" = set; then :
+diff -Naur glibc-2.20/configure.ac glibc-2.20-patch/configure.ac
+--- glibc-2.20/configure.ac	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/configure.ac	2015-02-19 03:54:24.155759769 -0600
+@@ -127,6 +127,16 @@
+ 	    [sysheaders=''])
+ AC_SUBST(sysheaders)
+ 
++AC_ARG_WITH([kconfig],
++	    AC_HELP_STRING([--with-kconfig=PATH],
++			   [location of kconfig tools to use (from Linux
++			    kernel builds) to re-use for configuring EGLIBC
++			    option groups]),
++	    [KCONFIG_TOOLS=$withval],
++	    [KCONFIG_TOOLS=''])
++AC_SUBST(KCONFIG_TOOLS)
++
++
+ AC_SUBST(use_default_link)
+ AC_ARG_WITH([default-link],
+ 	    AC_HELP_STRING([--with-default-link],
+diff -Naur glibc-2.20/EGLIBC.option-groups glibc-2.20-patch/EGLIBC.option-groups
+--- glibc-2.20/EGLIBC.option-groups	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/EGLIBC.option-groups	2015-02-19 03:54:24.154759770 -0600
+@@ -0,0 +1,122 @@
++                                                        -*- mode: text -*-
++
++              The EGLIBC Component Configuration System
++                  Jim Blandy <jimb at codesourcery.com>
++
++Introduction
++
++The GNU C library (GLIBC) provides a broad range of functionality,
++ranging from internationalization support to transcendental
++mathematical functions.  Its website boasts that "nearly all known and
++useful functions from any other C library are available."  This
++exhaustive approach has been one of GLIBC's strengths on desktop and
++server systems, but it has also given GLIBC a large footprint, both in
++memory and on disk, making it a challenge to use in embedded systems
++with limited resources.
++
++The Embedded GNU C library (EGLIBC) is a variant of the GNU C library
++designed to work well on embedded systems.  In particular, EGLIBC's
++component configuration system allows embedded developers to build
++customized versions of the library that include only the features
++their application uses, reducing its space requirements.
++
++EGLIBC's component configuration system categorizes the library's
++functions into "option groups", and allows you to include or exclude
++option groups individually.  Some option groups depend on others;
++EGLIBC tracks these relationships, and ensures that the selected
++configuration yields a functioning library.
++
++
++Consistent and Predictable Behavior
++
++A flexible configuration system is a mixed blessing: if the options
++offered are poorly designed, it can be hard to see which choices will
++have the desired effects, and choices with obscure consequences can
++make debugging difficult.  EGLIBC's configuration follows some general
++principles to reduce these risks:
++
++- EGLIBC has a single default configuration for each target
++  architecture.
++
++- In the default configuration, all option groups are enabled, and
++  EGLIBC is upwardly API- and ABI-compatible with GLIBC.
++
++- As much as possible, configurations only affect what functions are
++  present, not how they behave.  If the system works with an option
++  group disabled, it will still work with it enabled.
++
++- As much as possible, configurations only select option groups ---
++  they do not describe characteristics of the target architecture.
++
++These rules mean that you have a simple debugging strategy available
++if you suspect that your EGLIBC configuration might be the source of a
++problem: fall back to the default configuration, re-test, and then
++disable option groups one by one, until the problem reappears.
++
++
++The Option Groups
++
++To see the current full list of implemented option groups, refer to the
++file 'option-groups.def' at the top of the source tree, or run
++'make menuconfig' from the top-level build directory.
++
++The POSIX.1-2001 specification includes a suggested partition of all
++the functions in the POSIX C API into option groups: math functions
++like 'sin' and 'cos'; networking functions like 'socket' and
++'connect'; and so on.  EGLIBC could use this partitioning as the basis
++for future option groups.
++
++
++Implementation
++
++The EGLIBC component configuration system resembles the approach used
++by the Linux kernel to select device drivers, network protocols, and
++other features.  A file named 'option-groups.config' in the top-level
++build directory contains assignments to Make variables, each of which
++enables or disables a particular option group.  If the variable's
++value is set to 'y', then the option group is enabled; if it set to
++anything else, the option group is omitted.  The file
++'option-groups.defaults', at the top of the source tree, establishes
++default values for all variables; all option groups are enabled by
++default.
++
++For example, the following 'option-groups.config' would omit locale
++data, but include mathematical functions, and everything else:
++
++   OPTION_EGLIBC_LOCALES = n
++   OPTION_EGLIBC_LIBM = y
++
++Like the Linux kernel, EGLIBC supports a similar set of '*config' make
++targets to make it easier to create 'option-groups.config', with all
++dependencies between option groups automatically satisfied.  Run
++'make help' to see the list of supported make config targets.  For
++example, 'make menuconfig' will update the current config utilising a
++menu based program.
++
++The option group names and their type (boolean, int, hex, string), help
++description, and dependencies with other option groups, are described by
++'option-groups.def' at the top of the source tree, analogous to the
++'Kconfig' files in the Linux kernel.
++
++In general, each option group variable controls whether a given set of
++object files in EGLIBC is compiled and included in the final
++libraries, or omitted from the build.
++
++Each subdirectory's Makefile categorizes its routines, libraries, and
++executables by option group.  For example, EGLIBC's 'math/Makefile'
++places the 'libm' library in the OPTION_EGLIBC_LIBM group as follows:
++
++   extra-libs-$(OPTION_EGLIBC_LIBM) := libm
++
++Finally, common code in 'Makerules' cites the value of the variable
++'extra-libs-y', selecting only those libraries that belong to enabled
++option groups to be built.
++
++
++Current Status and Future Directions
++
++The EGLIBC component configuration system described here is still
++under development.
++
++We have used the system to subset some portions of EGLIBC's
++Index: libc/configure.ac
+diff -Naur glibc-2.20/Makefile glibc-2.20-patch/Makefile
+--- glibc-2.20/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/Makefile	2015-02-19 03:54:24.154759770 -0600
+@@ -24,6 +24,7 @@
+ 
+ include Makeconfig
+ 
++include options-config/Makefile
+ 
+ # This is the default target; it makes everything except the tests.
+ .PHONY: all
+diff -Naur glibc-2.20/option-groups.def glibc-2.20-patch/option-groups.def
+--- glibc-2.20/option-groups.def	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/option-groups.def	2015-02-19 03:54:24.153759771 -0600
+@@ -0,0 +1,868 @@
++# This file documents the option groups EGLIBC currently supports, in
++# a format akin to the Linux Kconfig system's.  The syntax may change
++# over time.
++#
++# An entry of the form:
++#
++#   config GROUP_NAME
++#       bool "one-line explanation of what this option group controls"
++#       help
++#           Multi-line help explaining the option group's meaning in
++#           some detail, terminated by indentation level.
++#
++# defines an option group whose variable is GROUP_NAME, with
++# meaningful values 'y' (enabled) and 'n' (disabled).  The
++# documentation is formatted to be consumed by some sort of
++# interactive configuration interface, but EGLIBC doesn't have such an
++# interface yet.
++#
++# An option may have a 'depends on' line, indicating which other options
++# must also be enabled if this option is.  At present, EGLIBC doesn't
++# check that these dependencies are satisfied.
++#
++# Option group variables get their default values from the file
++# 'option-groups.defaults', in the top directory of the EGLIBC source
++# tree.  By default, all EGLIBC option groups are enabled --- their
++# variables are set to 'y'.
++#
++# After including 'option-groups.defaults', the EGLIBC make machinery
++# includes the file 'option-groups.config' from the top of the build
++# tree, if it is present.  Developers can place assignments to option
++# group variables in that file to override the defaults.  For example,
++# to disable an option group, place a line of the form:
++#
++#    OPTION_GROUP_NAME = n
++#
++# in 'option-groups.config' at the top of your build tree.  To
++# explicitly enable an option group, you may also write:
++#
++#    OPTION_GROUP_NAME = y
++#
++# although this simply reestablishes the value already set by
++# 'option-groups.defaults'.
++
++config EGLIBC_ADVANCED_INET6
++   bool "IPv6 Advanced Sockets API support (RFC3542)"
++   depends on EGLIBC_INET
++   help
++       This option group includes the functions specified by RFC 3542,
++       "Advanced Sockets Application Program Interface (API) for
++       IPv6".
++
++       This option group includes the following functions:
++
++         inet6_opt_append
++         inet6_opt_find
++         inet6_opt_finish
++         inet6_opt_get_val
++         inet6_opt_init
++         inet6_option_alloc
++         inet6_option_append
++         inet6_option_find
++         inet6_option_init
++         inet6_option_next
++         inet6_option_space
++         inet6_opt_next
++         inet6_opt_set_val
++         inet6_rth_add
++         inet6_rth_getaddr
++         inet6_rth_init
++         inet6_rth_reverse
++         inet6_rth_segments
++         inet6_rth_space
++
++config EGLIBC_BACKTRACE
++   bool "Functions for producing backtraces"
++   help
++       This option group includes functions for producing a list of
++       the function calls that are currently active in a thread, from
++       within the thread itself.  These functions are often used
++       within signal handlers, to produce diagnostic output.
++
++       This option group includes the following functions:
++
++         backtrace
++         backtrace_symbols
++         backtrace_symbols_fd
++
++config EGLIBC_BIG_MACROS
++   bool "Use extensive inline code"
++   help
++       This option group specifies whether certain pieces of code
++       should be inlined to achieve maximum speed.  If this option
++       group is not selected, function calls will be used instead,
++       hence reducing the library footprint.
++
++config EGLIBC_BSD
++   bool "BSD-specific functions, and their compatibility stubs"
++   help
++       This option group includes functions specific to BSD kernels.
++       A number of these functions have stub versions that are also
++       included in libraries built for non-BSD systems for
++       compatibility.
++
++       This option group includes the following functions:
++
++         chflags
++         fchflags
++         lchmod
++         revoke
++         setlogin
++
++config EGLIBC_CXX_TESTS
++   bool "Tests that link against the standard C++ library."
++   depends on POSIX_WIDE_CHAR_DEVICE_IO && EGLIBC_LIBM
++   help
++       This option group does not include any C library functions;
++       instead, it controls which EGLIBC tests an ordinary 'make
++       tests' runs.  With this group disabled, tests that would
++       normally link against the standard C++ library are not
++       run.
++
++       The standard C++ library depends on the math library 'libm' and
++       the wide character I/O functions included in EGLIBC.  So those
++       option groups must be enabled if this test is enabled.
++
++config EGLIBC_CATGETS
++   bool "Functions for accessing message catalogs"
++   depends on EGLIBC_LOCALE_CODE
++   help
++       This option group includes functions for accessing message
++       catalogs: catopen, catclose, and catgets.
++
++       This option group depends on the EGLIBC_LOCALE_CODE
++       option group.
++
++config EGLIBC_CHARSETS
++   bool "iconv/gconv character set conversion libraries"
++   help
++       This option group includes support for character sets other
++       than ASCII (ANSI_X3.4-1968) and Unicode and ISO-10646 in their
++       various encodings.  This affects both the character sets
++       supported by the wide and multibyte character functions, and
++       those supported by the 'iconv' functions.
++
++       With this option group disabled, EGLIBC supports only the
++       following character sets:
++
++          ANSI_X3.4         - ASCII
++          ANSI_X3.4-1968
++          ANSI_X3.4-1986
++          ASCII
++          CP367
++          CSASCII
++          IBM367
++          ISO-IR-6
++          ISO646-US
++          ISO_646.IRV:1991
++          OSF00010020
++          US
++          US-ASCII
++
++          10646-1:1993      - ISO 10646, in big-endian UCS4 form
++          10646-1:1993/UCS4
++          CSUCS4
++          ISO-10646
++          ISO-10646/UCS4
++          OSF00010104
++          OSF00010105
++          OSF00010106
++          UCS-4
++          UCS-4BE
++          UCS4
++
++          UCS-4LE           - ISO 10646, in little-endian UCS4 form
++
++          ISO-10646/UTF-8   - ISO 10646, in UTF-8 form
++          ISO-10646/UTF8
++          ISO-IR-193
++          OSF05010001
++          UTF-8
++          UTF8
++
++          ISO-10646/UCS2    - ISO 10646, in target-endian UCS2 form
++          OSF00010100
++          OSF00010101
++          OSF00010102
++          UCS-2
++          UCS2
++
++          UCS-2BE           - ISO 10646, in big-endian UCS2 form
++          UNICODEBIG
++
++          UCS-2LE           - ISO 10646, in little-endian UCS2 form
++          UNICODELITTLE
++
++          WCHAR_T           - EGLIBC's internal form (target-endian,
++                              32-bit ISO 10646)
++
++config EGLIBC_CRYPT
++   bool "Encryption library"
++   help
++       This option group includes the `libcrypt' library which
++       provides functions for one-way encryption.  Supported
++       encryption algorithms include MD5, SHA-256, SHA-512 and DES.
++
++config EGLIBC_CRYPT_UFC
++   bool "Ultra fast `crypt' implementation"
++   depends on EGLIBC_CRYPT
++   help
++       This option group provides ultra fast DES-based implementation of
++       the `crypt' function.  When this option group is disabled,
++       (a) the library will not provide the setkey[_r] and encrypt[_r]
++       functions and (b) the crypt[_r] function will return NULL and set the
++       errno to ENOSYS if /salt/ passed does not correspond to either MD5,
++       SHA-256 or SHA-512 algorithm.
++
++config EGLIBC_DB_ALIASES
++   bool "Functions for accessing the mail aliases database"
++   help
++       This option group includues functions for looking up mail
++       aliases in '/etc/aliases' or using nsswitch.  It includes the
++       following functions:
++
++         endaliasent
++         getaliasbyname
++         getaliasbyname_r
++         getaliasent
++         getaliasent_r
++         setaliasent
++
++       When this option group is disabled, the NSS service libraries
++       also lack support for querying their mail alias tables.
++
++config EGLIBC_ENVZ
++   bool "Functions for handling envz-style environment vectors."
++   help
++       This option group contains functions for creating and operating
++       on envz vectors.  An "envz vector" is a vector of strings in a
++       contiguous block of memory, where each element is a name-value
++       pair, and elements are separated from their neighbors by null
++       characters.
++
++       This option group includes the following functions:
++
++        envz_add        envz_merge
++        envz_entry      envz_remove
++        envz_get        envz_strip
++
++config EGLIBC_FCVT
++   bool "Functions for converting floating-point numbers to strings"
++   help
++       This option group includes functions for converting
++       floating-point numbers to strings.
++
++       This option group includes the following functions:
++
++         ecvt           qecvt
++	 ecvt_r		qecvt_r
++         fcvt		qfcvt
++	 fcvt_r		qfcvt_r
++         gcvt		qgcvt
++
++config EGLIBC_FMTMSG
++   bool "Functions for formatting messages"
++   help
++       This option group includes the following functions:
++
++         addseverity    fmtmsg
++
++config EGLIBC_FSTAB
++   bool "Access functions for 'fstab'"
++   help
++       This option group includes functions for reading the mount
++       point specification table, '/etc/fstab'.  These functions are
++       not included in the POSIX standard, which provides the
++       'getmntent' family of functions instead.
++
++       This option group includes the following functions:
++
++         endfsent       getfsspec
++         getfsent       setfsent
++         getfsfile
++
++config EGLIBC_FTRAVERSE
++   bool "Functions for traversing file hierarchies"
++   help
++       This option group includes functions for traversing file
++       UNIX file hierachies.
++
++       This option group includes the following functions:
++
++         fts_open       ftw
++	 fts_read	nftw
++         fts_children	ftw64
++	 fts_set	nftw64
++         fts_close
++
++config EGLIBC_GETLOGIN
++   bool "The getlogin function"
++   depends on EGLIBC_UTMP
++   help
++       This function group includes the 'getlogin' and 'getlogin_r'
++       functions, which return the user name associated by the login
++       activity with the current process's controlling terminal.
++
++       With this option group disabled, the 'glob' function will not
++       fall back on 'getlogin' to find the user's login name for tilde
++       expansion when the 'HOME' environment variable is not set.
++
++config EGLIBC_IDN
++   bool "International domain names support"
++   help
++       This option group includes the `libcidn' library which
++       provides support for international domain names.
++
++config EGLIBC_INET
++   bool "Networking support"
++   help
++       This option group includes networking-specific functions and
++       data.  With EGLIBC_INET disabled, the EGLIBC
++       installation and API changes as follows:
++
++       - The following libraries are not installed:
++
++         libnsl
++         libnss_compat
++         libnss_dns
++         libnss_hesiod
++         libnss_nis
++         libnss_nisplus
++         libresolv
++
++       - The following functions and variables are omitted from libc:
++
++         authdes_create           hstrerror              svc_fdset
++         authdes_getucred         htonl                  svc_getreq
++         authdes_pk_create        htons                  svc_getreq_common
++         authnone_create          if_freenameindex       svc_getreq_poll
++         authunix_create          if_indextoname         svc_getreqset
++         authunix_create_default  if_nameindex           svc_max_pollfd
++         bindresvport             if_nametoindex         svc_pollfd
++         callrpc                  in6addr_any            svcraw_create
++         cbc_crypt                in6addr_loopback       svc_register
++         clnt_broadcast           inet6_opt_append       svc_run
++         clnt_create              inet6_opt_find         svc_sendreply
++         clnt_pcreateerror        inet6_opt_finish       svctcp_create
++         clnt_perrno              inet6_opt_get_val      svcudp_bufcreate
++         clnt_perror              inet6_opt_init         svcudp_create
++         clntraw_create           inet6_option_alloc     svcudp_enablecache
++         clnt_spcreateerror       inet6_option_append    svcunix_create
++         clnt_sperrno             inet6_option_find      svcunixfd_create
++         clnt_sperror             inet6_option_init      svc_unregister
++         clnttcp_create           inet6_option_next      user2netname
++         clntudp_bufcreate        inet6_option_space     xdecrypt
++         clntudp_create           inet6_opt_next         xdr_accepted_reply
++         clntunix_create          inet6_opt_set_val      xdr_array
++         des_setparity            inet6_rth_add          xdr_authdes_cred
++         ecb_crypt                inet6_rth_getaddr      xdr_authdes_verf
++         endaliasent              inet6_rth_init         xdr_authunix_parms
++         endhostent               inet6_rth_reverse      xdr_bool
++         endnetent                inet6_rth_segments     xdr_bytes
++         endnetgrent              inet6_rth_space        xdr_callhdr
++         endprotoent              inet_addr              xdr_callmsg
++         endrpcent                inet_aton              xdr_char
++         endservent               inet_lnaof             xdr_cryptkeyarg
++         ether_aton               inet_makeaddr          xdr_cryptkeyarg2
++         ether_aton_r             inet_netof             xdr_cryptkeyres
++         ether_hostton            inet_network           xdr_des_block
++         ether_line               inet_nsap_addr         xdr_double
++         ether_ntoa               inet_nsap_ntoa         xdr_enum
++         ether_ntoa_r             inet_ntoa              xdr_float
++         ether_ntohost            inet_ntop              xdr_free
++         freeaddrinfo             inet_pton              xdr_getcredres
++         freeifaddrs              innetgr                xdr_hyper
++         gai_strerror             iruserok               xdr_int
++         getaddrinfo              iruserok_af            xdr_int16_t
++         getaliasbyname           key_decryptsession     xdr_int32_t
++         getaliasbyname_r         key_decryptsession_pk  xdr_int64_t
++         getaliasent              key_encryptsession     xdr_int8_t
++         getaliasent_r            key_encryptsession_pk  xdr_keybuf
++         gethostbyaddr            key_gendes             xdr_key_netstarg
++         gethostbyaddr_r          key_get_conv           xdr_key_netstres
++         gethostbyname            key_secretkey_is_set   xdr_keystatus
++         gethostbyname2           key_setnet             xdr_long
++         gethostbyname2_r         key_setsecret          xdr_longlong_t
++         gethostbyname_r          netname2host           xdrmem_create
++         gethostent               netname2user           xdr_netnamestr
++         gethostent_r             ntohl                  xdr_netobj
++         getifaddrs               ntohs                  xdr_opaque
++         getipv4sourcefilter      passwd2des             xdr_opaque_auth
++         get_myaddress            pmap_getmaps           xdr_pmap
++         getnameinfo              pmap_getport           xdr_pmaplist
++         getnetbyaddr             pmap_rmtcall           xdr_pointer
++         getnetbyaddr_r           pmap_set               xdr_quad_t
++         getnetbyname             pmap_unset             xdrrec_create
++         getnetbyname_r           rcmd                   xdrrec_endofrecord
++         getnetent                rcmd_af                xdrrec_eof
++         getnetent_r              registerrpc            xdrrec_skiprecord
++         getnetgrent              res_init               xdr_reference
++         getnetgrent_r            rexec                  xdr_rejected_reply
++         getnetname               rexec_af               xdr_replymsg
++         getprotobyname           rexecoptions           xdr_rmtcall_args
++         getprotobyname_r         rpc_createerr          xdr_rmtcallres
++         getprotobynumber         rresvport              xdr_short
++         getprotobynumber_r       rresvport_af           xdr_sizeof
++         getprotoent              rtime                  xdrstdio_create
++         getprotoent_r            ruserok                xdr_string
++         getpublickey             ruserok_af             xdr_u_char
++         getrpcbyname             ruserpass              xdr_u_hyper
++         getrpcbyname_r           setaliasent            xdr_u_int
++         getrpcbynumber           sethostent             xdr_uint16_t
++         getrpcbynumber_r         setipv4sourcefilter    xdr_uint32_t
++         getrpcent                setnetent              xdr_uint64_t
++         getrpcent_r              setnetgrent            xdr_uint8_t
++         getrpcport               setprotoent            xdr_u_long
++         getsecretkey             setrpcent              xdr_u_longlong_t
++         getservbyname            setservent             xdr_union
++         getservbyname_r          setsourcefilter        xdr_unixcred
++         getservbyport            svcauthdes_stats       xdr_u_quad_t
++         getservbyport_r          svcerr_auth            xdr_u_short
++         getservent               svcerr_decode          xdr_vector
++         getservent_r             svcerr_noproc          xdr_void
++         getsourcefilter          svcerr_noprog          xdr_wrapstring
++         h_errlist                svcerr_progvers        xencrypt
++         h_errno                  svcerr_systemerr       xprt_register
++         herror                   svcerr_weakauth        xprt_unregister
++         h_nerr                   svc_exit
++         host2netname             svcfd_create
++
++       - The rpcgen, nscd, and rpcinfo commands are not installed.
++
++       - The 'rpc' file (a text file listing RPC services) is not installed.
++
++       Socket-related system calls do not fall in this option group,
++       because many are also used for other inter-process
++       communication mechanisms.  For example, the 'syslog' routines
++       use Unix-domain sockets to communicate with the syslog daemon;
++       syslog is valuable in non-networked contexts.
++
++config EGLIBC_INET_ANL
++   bool "Asynchronous name lookup"
++   depends on EGLIBC_INET
++   help
++       This option group includes the `libanl' library which
++       provides support for asynchronous name lookup.
++
++config EGLIBC_LIBM
++   bool "libm (math library)"
++   help
++       This option group includes the 'libm' library, containing
++       mathematical functions.  If this option group is omitted, then
++       an EGLIBC installation does not include shared or unshared versions
++       of the math library.
++
++       Note that this does not remove all floating-point related
++       functionality from EGLIBC; for example, 'printf' and 'scanf'
++       can still print and read floating-point values with this option
++       group disabled.
++
++       Note that the ISO Standard C++ library 'libstdc++' depends on
++       EGLIBC's math library 'libm'.  If you disable this option
++       group, you will not be able to build 'libstdc++' against the
++       resulting EGLIBC installation.
++
++config EGLIBC_LOCALES
++   bool "Locale definitions"
++   help
++       This option group includes all locale definitions other than
++       that for the "C" locale.  If this option group is omitted, then
++       only the "C" locale is supported.
++
++
++config EGLIBC_LOCALE_CODE
++   bool "Locale functions"
++   depends on POSIX_C_LANG_WIDE_CHAR
++   help
++       This option group includes locale support functions, programs,
++       and libraries.  With EGLIBC_LOCALE_CODE disabled,
++       EGLIBC supports only the 'C' locale (also known as 'POSIX'),
++       and ignores the settings of the 'LANG' and 'LC_*' environment
++       variables.
++
++       With EGLIBC_LOCALE_CODE disabled, the following
++       functions are omitted from libc:
++
++         duplocale   localeconv  nl_langinfo    rpmatch  strfmon_l
++         freelocale  newlocale   nl_langinfo_l  strfmon  uselocale
++
++       Furthermore, only the LC_CTYPE and LC_TIME categories of the
++       standard "C" locale are available.
++
++       The EGLIBC_CATGETS option group depends on this option group.
++
++
++config EGLIBC_MEMUSAGE
++   bool "Memory profiling library"
++   help
++       This option group includes the `libmemusage' library and
++       the `memusage' and `memusagestat' utilities.
++       These components provide memory profiling functions.
++
++config EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
++   int "Memory profiling library buffer size"
++   depends on EGLIBC_MEMUSAGE
++   default "32768"
++   help
++       Libmemusage library buffers the profiling data in memory
++       before writing it out to disk.  By default, the library
++       allocates 1.5M buffer, which can be substantial for some
++       systems.  EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE option
++       allows to change the default buffer size.  It specifies
++       the number of entries the buffer should have.
++       On most architectures one buffer entry amounts to 48 bytes,
++       so setting this option to the value of 512 will reduce the size of
++       the memory buffer to 24K.
++
++config EGLIBC_NIS
++   bool "Support for NIS, NIS+, and the special 'compat' services."
++   depends on EGLIBC_INET && EGLIBC_SUNRPC
++   help
++       This option group includes the NIS, NIS+, and 'compat' Name
++       Service Switch service libraries.  When it is disabled, those
++       services libraries are not installed; you should remove any
++       references to them from your 'nsswitch.conf' file.
++
++       This option group depends on the EGLIBC_INET option
++       group; you must enable that to enable this option group.
++
++config EGLIBC_NSSWITCH
++   bool "Name service switch (nsswitch) support"
++   help
++       This option group includes support for the 'nsswitch' facility.
++       With this option group enabled, all EGLIBC functions for
++       accessing various system databases (passwords and groups;
++       networking; aliases; public keys; and so on) consult the
++       '/etc/nsswitch.conf' configuration file to decide how to handle
++       queries.
++
++       With this option group disabled, EGLIBC uses a fixed list of
++       services to satisfy queries on each database, as requested by
++       configuration files specified when EGLIBC is built.  Your
++       'option-groups.config' file must set the following two
++       variables:
++
++config EGLIBC_NSSWITCH_FIXED_CONFIG
++   string "Nsswitch fixed config filename"
++   depends on !EGLIBC_NSSWITCH
++   default ""
++   help
++          Set this to the name of a file whose contents observe the
++          same syntax as an ordinary '/etc/nsswitch.conf' file.  The
++          EGLIBC build process parses this file just as EGLIBC would
++          at run time if EGLIBC_NSSWITCH were enabled, and
++          produces a C library that uses the nsswitch service
++          libraries to search for database entries as this file
++          specifies, instead of consulting '/etc/nsswitch.conf' at run
++          time.
++
++          This should be an absolute filename.  The EGLIBC build
++          process may use it from several different working
++          directories.  It may include references to Makefile
++          variables like 'common-objpfx' (the top of the build tree,
++          with a trailing slash), or '..' (the top of the source tree,
++          with a trailing slash).
++
++          The EGLIBC source tree includes a sample configuration file
++          named 'nss/fixed-nsswitch.conf'; for simple configurations,
++          you will probably want to delete references to databases not
++          needed on your system.
++
++config EGLIBC_NSSWITCH_FIXED_FUNCTIONS
++   string "Nsswitch fixed functions filename"
++   depends on !EGLIBC_NSSWITCH
++   default ""
++   help
++          The EGLIBC build process uses this file to decide which
++          functions to make available from which service libraries.
++          The file 'nss/fixed-nsswitch.functions' serves as a sample
++          configuration file for this setting, and explains its syntax
++          and meaning in more detail.
++
++          This should be an absolute file name.  The EGLIBC build
++          process may use it from several different working
++          directories.  It may include references to Makefile
++          variables like 'common-objpfx' (the top of the build tree,
++          with a trailing slash), or '..' (the top of the source tree,
++          with a trailing slash).
++
++          Be sure to mention each function in each service you wish to
++          use.  If you do not mention a service's function here, the
++          EGLIBC database access functions will not find it, even if
++          it is listed in the EGLIBC_NSSWITCH_FIXED_CONFIG
++          file.
++
++          In this arrangement, EGLIBC will not use the 'dlopen' and
++          'dlsym' functions to find database access functions.  Instead,
++          libc hard-codes references to the service libraries' database
++          access functions.  You must explicitly link your program
++          against the name service libraries (those whose names start
++          with 'libnss_', in the sysroot's '/lib' directory) whose
++          functions you intend to use.  This arrangement helps
++          system-wide static analysis tools decide which functions a
++          system actually uses.
++
++          Note that some nsswitch service libraries require other option
++          groups to be enabled; for example, the EGLIBC_INET
++          option group must be enabled to use the 'libnss_dns.so.2'
++          service library, which uses the Domain Name System network
++          protocol to answer queries.
++
++config EGLIBC_RCMD
++   bool "Support for 'rcmd' and related library functions"
++   depends on EGLIBC_INET
++   help
++      This option group includes functions for running commands on
++      remote machines via the 'rsh' protocol, and doing authentication
++      related to those functions.  This also includes functions that
++      use the 'rexec' protocol.
++
++      This option group includes the following functions:
++
++        rcmd            ruserok
++        rcmd_af         ruserok_af
++        rexec           iruserok
++        rexec_af        iruserok_af
++        rresvport       ruserpass
++        rresvport_af
++
++config EGLIBC_RTLD_DEBUG
++   bool "Runtime linker debug print outs"
++   help
++      This option group enables debug output of the runtime linker
++      which is activated via LD_DEBUG and LD_TRACE_PRELINKING
++      environment variables.  Disabling this option group yields
++      a smaller runtime linker binary.
++      BEWARE: Disabling this option group is likely to break
++      the `ldd' utility which may also be used by the prelinker.
++      In particular, the `--unused' ldd option will not work correctly.
++
++config EGLIBC_SPAWN
++   bool "Support for POSIX posix_spawn functions"
++   help
++      This option group includes the POSIX functions for executing
++      programs in child processes without using 'fork' or 'vfork'.
++
++      This option group includes the following functions:
++
++        posix_spawn
++        posix_spawnattr_destroy
++        posix_spawnattr_getflags
++        posix_spawnattr_getpgroup
++        posix_spawnattr_getschedparam
++        posix_spawnattr_getschedpolicy
++        posix_spawnattr_getsigdefault
++        posix_spawnattr_getsigmask
++        posix_spawnattr_init
++        posix_spawnattr_setflags
++        posix_spawnattr_setpgroup
++        posix_spawnattr_setschedparam
++        posix_spawnattr_setschedpolicy
++        posix_spawnattr_setsigdefault
++        posix_spawnattr_setsigmask
++        posix_spawn_file_actions_addclose
++        posix_spawn_file_actions_adddup2
++        posix_spawn_file_actions_addopen
++        posix_spawn_file_actions_destroy
++        posix_spawn_file_actions_init
++        posix_spawnp
++
++      This option group also provides the ability for the iconv,
++      localedef, and locale programs to operate transparently on
++      compressed charset definitions.  When this option group is
++      disabled, those programs will only operate on uncompressed
++      charmap files.
++
++config EGLIBC_STREAMS
++   bool "Support for accessing STREAMS."
++   help
++      This option group includes functions for reading and writing
++      messages to and from STREAMS.  The STREAMS interface provides a
++      uniform mechanism for implementing networking services and other
++      character-based I/O.  (STREAMS are not to be confused with
++      <stdio.h> FILE objects, also called 'streams'.)
++
++      This option group includes the following functions:
++
++        getmsg          putpmsg
++        getpmsg         fattach
++        isastream       fdetach
++        putmsg
++
++config EGLIBC_SUNRPC
++   bool "Support for the Sun 'RPC' protocol."
++   depends on EGLIBC_INET
++   help
++      This option group includes support for the Sun RPC protocols,
++      including the 'rpcgen' and 'rpcinfo' programs.
++
++config EGLIBC_UTMP
++    bool "Older access functions for 'utmp' login records"
++    help
++       This option group includes the older 'utent' family of
++       functions for accessing user login records in the 'utmp' file.
++       POSIX omits these functions in favor of the 'utxent' family,
++       and they are obsolete on systems other than Linux.
++
++       This option group includes the following functions:
++
++         endutent
++         getutent
++         getutent_r
++         getutid
++         getutid_r
++         getutline
++         getutline_r
++         logwtmp
++         pututline
++         setutent
++         updwtmp
++         utmpname
++
++       This option group includes the following libraries:
++
++         libutil.so (and libutil.a)
++
++config EGLIBC_UTMPX
++    bool "POSIX access functions for 'utmp' login records"
++    depends on EGLIBC_UTMP
++    help
++       This option group includes the POSIX functions for reading and
++       writing user login records in the 'utmp' file (usually
++       '/var/run/utmp').  The POSIX functions operate on 'struct
++       utmpx' structures, as opposed to the family of older 'utent'
++       functions, which operate on 'struct utmp' structures.
++
++       This option group includes the following functions:
++
++         endutxent
++         getutmp
++         getutmpx
++         getutxent
++         getutxid
++         getutxline
++         pututxline
++         setutxent
++         updwtmpx
++         utmpxname
++
++config EGLIBC_WORDEXP
++    bool "Shell-style word expansion"
++    help
++        This option group includes the 'wordexp' function for
++        performing word expansion in the manner of the shell, and the
++        accompanying 'wordfree' function.
++
++config POSIX_C_LANG_WIDE_CHAR
++    bool "ISO C library wide character functions, excluding I/O"
++    help
++        This option group includes the functions defined by the ISO C
++        standard for working with wide and multibyte characters in
++        memory.  Functions for reading and writing wide and multibyte
++        characters from and to files call in the
++        POSIX_WIDE_CHAR_DEVICE_IO option group.
++
++        This option group includes the following functions:
++
++          btowc         mbsinit       wcscspn       wcstoll
++          iswalnum      mbsrtowcs     wcsftime      wcstombs
++          iswalpha      mbstowcs      wcslen        wcstoul
++          iswblank      mbtowc        wcsncat       wcstoull
++          iswcntrl      swprintf      wcsncmp       wcstoumax
++          iswctype      swscanf       wcsncpy       wcsxfrm
++          iswdigit      towctrans     wcspbrk       wctob
++          iswgraph      towlower      wcsrchr       wctomb
++          iswlower      towupper      wcsrtombs     wctrans
++          iswprint      vswprintf     wcsspn        wctype
++          iswpunct      vswscanf      wcsstr        wmemchr
++          iswspace      wcrtomb       wcstod        wmemcmp
++          iswupper      wcscat        wcstof        wmemcpy
++          iswxdigit     wcschr        wcstoimax     wmemmove
++          mblen         wcscmp        wcstok        wmemset
++          mbrlen        wcscoll       wcstol
++          mbrtowc       wcscpy        wcstold
++
++config POSIX_REGEXP
++    bool "Regular expressions"
++    help
++        This option group includes the POSIX regular expression
++        functions, and the associated non-POSIX extensions and
++        compatibility functions.
++
++        With POSIX_REGEXP disabled, the following functions are
++        omitted from libc:
++
++          re_comp                 re_max_failures         regcomp
++          re_compile_fastmap      re_search               regerror
++          re_compile_pattern      re_search_2             regexec
++          re_exec                 re_set_registers        regfree
++          re_match                re_set_syntax           rpmatch
++          re_match_2              re_syntax_options
++
++        Furthermore, the compatibility regexp interface defined in the
++        <regexp.h> header file, 'compile', 'step', and 'advance', is
++        omitted.
++
++config POSIX_REGEXP_GLIBC
++    bool "Regular expressions from GLIBC"
++    depends on POSIX_REGEXP
++    help
++	This option group specifies which regular expression
++        library to use.  The choice is between regex
++        implementation from GLIBC and regex implementation from
++        libiberty.  The GLIBC variant is fully POSIX conformant and
++        optimized for speed; regex from libiberty is more than twice
++        as small while still is enough for most practical purposes.
++
++config POSIX_WIDE_CHAR_DEVICE_IO
++    bool "Input and output functions for wide characters"
++    depends on POSIX_C_LANG_WIDE_CHAR
++    help
++        This option group includes functions for reading and writing
++        wide characters to and from <stdio.h> streams.
++
++        This option group includes the following functions:
++
++          fgetwc        fwprintf      putwchar      vwscanf
++          fgetws        fwscanf       ungetwc       wprintf
++          fputwc        getwc         vfwprintf     wscanf
++          fputws        getwchar      vfwscanf
++          fwide         putwc         vwprintf
++
++        This option group further includes the following unlocked
++        variants of the above functions:
++
++          fgetwc_unlocked           getwc_unlocked
++          fgetws_unlocked           getwchar_unlocked
++          fputwc_unlocked           putwc_unlocked
++          fputws_unlocked           putwchar_unlocked
++
++        Note that the GNU standard C++ library, 'libstdc++.so', uses
++        some of these functions; you will not be able to link or run
++        C++ programs if you disable this option group.
++
++        This option group also affects the behavior of the following
++        functions:
++
++          fdopen
++          fopen
++          fopen64
++          freopen
++          freopen64
++
++        These functions all take an OPENTYPE parameter which may
++        contain a string of the form ",ccs=CHARSET", indicating that
++        the underlying file uses the character set named CHARSET.
++        This produces a wide-oriented stream, which is only useful
++        when the functions included in this option group are present.
++        If the user attempts to open a file specifying a character set
++        in the OPENTYPE parameter, and EGLIBC was built with this
++        option group disabled, the function returns NULL, and sets
++        errno to EINVAL.
++
++
++# This helps Emacs users browse this file using the page motion commands
++# and commands like 'pages-directory'.
++# Local Variables:
++# page-delimiter: "^config\\s-"
++# End:
+diff -Naur glibc-2.20/option-groups.defaults glibc-2.20-patch/option-groups.defaults
+--- glibc-2.20/option-groups.defaults	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/option-groups.defaults	2015-02-19 03:54:24.153759771 -0600
+@@ -0,0 +1,47 @@
++# This file sets default values for all option group variables
++# mentioned in option-groups.def; see that file for a description of
++# each option group.
++#
++# Subdirectory makefiles include this file before including the user's
++# settings from option-groups.config at the top of the build tree;
++# that file need only refer to those options whose default settings
++# are to be changed.
++#
++# By default, all option groups are enabled.
++OPTION_EGLIBC_ADVANCED_INET6 = y
++OPTION_EGLIBC_BACKTRACE = y
++OPTION_EGLIBC_BIG_MACROS = y
++OPTION_EGLIBC_BSD = y
++OPTION_EGLIBC_CXX_TESTS = y
++OPTION_EGLIBC_CATGETS = y
++OPTION_EGLIBC_CHARSETS = y
++OPTION_EGLIBC_CRYPT = y
++OPTION_EGLIBC_CRYPT_UFC = y
++OPTION_EGLIBC_DB_ALIASES = y
++OPTION_EGLIBC_ENVZ = y
++OPTION_EGLIBC_FCVT = y
++OPTION_EGLIBC_FMTMSG = y
++OPTION_EGLIBC_FSTAB = y
++OPTION_EGLIBC_FTRAVERSE = y
++OPTION_EGLIBC_GETLOGIN = y
++OPTION_EGLIBC_IDN = y
++OPTION_EGLIBC_INET = y
++OPTION_EGLIBC_INET_ANL = y
++OPTION_EGLIBC_LIBM = y
++OPTION_EGLIBC_LOCALES = y
++OPTION_EGLIBC_LOCALE_CODE = y
++OPTION_EGLIBC_MEMUSAGE = y
++OPTION_EGLIBC_NIS = y
++OPTION_EGLIBC_NSSWITCH = y
++OPTION_EGLIBC_RCMD = y
++OPTION_EGLIBC_RTLD_DEBUG = y
++OPTION_EGLIBC_SPAWN = y
++OPTION_EGLIBC_STREAMS = y
++OPTION_EGLIBC_SUNRPC = y
++OPTION_EGLIBC_UTMP = y
++OPTION_EGLIBC_UTMPX = y
++OPTION_EGLIBC_WORDEXP = y
++OPTION_POSIX_C_LANG_WIDE_CHAR = y
++OPTION_POSIX_REGEXP = y
++OPTION_POSIX_REGEXP_GLIBC = y
++OPTION_POSIX_WIDE_CHAR_DEVICE_IO = y
+diff -Naur glibc-2.20/option-groups.mak glibc-2.20-patch/option-groups.mak
+--- glibc-2.20/option-groups.mak	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/option-groups.mak	2015-02-19 03:54:24.153759771 -0600
+@@ -0,0 +1,41 @@
++# Setup file for subdirectory Makefiles that define EGLIBC option groups.
++
++# EGLIBC shouldn't need to override this.  However, the
++# cross-build-friendly localedef includes this makefile to get option
++# group variable definitions; it uses a single build tree for all the
++# multilibs, and needs to be able to specify a different option group
++# configuration file for each multilib.
++option_group_config_file ?= $(objdir)/option-groups.config
++
++# Read the default settings for all options.
++# We're included before ../Rules, so we can't assume $(..) is set.
++include $(firstword $(..) ../)option-groups.defaults
++
++# Read the developer's option group selections, overriding the
++# defaults from option-groups.defaults.
++-include $(option_group_config_file)
++
++# $(call option-disabled, VAR) is 'y' if VAR is not 'y', or 'n' otherwise.
++# VAR should be a variable name, not a variable reference; this is
++# less general, but more terse for the intended use.
++# You can use it to add a file to a list if an option group is
++# disabled, like this:
++#   routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += ...
++define option-disabled
++$(firstword $(subst y,n,$(filter y,$($(strip $(1))))) y)
++endef
++
++# Establish 'routines-y', etc. as simply-expanded variables.
++aux-y	       	    :=
++extra-libs-others-y :=
++extra-libs-y   	    :=
++extra-objs-y   	    :=
++install-bin-y  	    :=
++install-others-y    :=
++install-sbin-y 	    :=
++others-y       	    :=
++others-pie-y   	    :=
++routines-y     	    :=
++test-srcs-y    	    :=
++tests-y        	    :=
++xtests-y       	    :=
+diff -Naur glibc-2.20/options-config/config-postproc.pl glibc-2.20-patch/options-config/config-postproc.pl
+--- glibc-2.20/options-config/config-postproc.pl	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/options-config/config-postproc.pl	2015-02-19 03:54:31.073759206 -0600
+@@ -0,0 +1,58 @@
++#!/usr/bin/perl
++
++$usage = "usage: $0 <default config file> <config file>\n";
++
++die "$usage" unless @ARGV;
++$defaults = shift @ARGV;
++die "$usage" unless @ARGV;
++die "Could not open $ARGV[0]" unless -T $ARGV[0];
++
++sub yank {
++    @option = grep(!($_ =~ /$_[0]\s*=/), @option);
++}
++
++open(DEFAULTS, $defaults) || die "Could not open $defaults\n";
++
++# get the full list of available options using the default config file
++$i = 0;
++while (<DEFAULTS>) {
++    if (/^\s*OPTION_(\w+\s*=.*$)/) {
++	$option[$i++] = $1;
++    }
++}
++
++# now go through the config file, making the necessary changes
++while (<>) {
++    if (/Linux Kernel Configuration/) {
++	# change title
++	s/Linux Kernel/Option Groups/;
++	print;
++    } elsif (/^\s*CONFIG_(\w+)\s*=/) {
++	# this is an explicit option set line, change CONFIG_ to OPTION_
++	# before printing and remove this option from option list
++	$opt = $1;
++	yank($opt);
++	s/CONFIG_/OPTION_/g;
++	print;
++    } elsif (/^\s*#\s+CONFIG_(\w+) is not set/) {
++	# this is a comment line for an unset boolean option, change CONFIG_
++	# to OPTION_, remove this option from option list, and convert to
++	# explicit OPTION_FOO=n
++	$opt = $1;
++	yank($opt);
++	s/CONFIG_/OPTION_/g;
++	print "OPTION_$opt=n\n";
++    } else {
++	print;
++    }
++}
++
++# any boolean options left in @options, are options that were not mentioned in
++# the config file, and implicitly that means the option must be set =n,
++# so do that here.
++foreach $opt (@option) {
++    if ($opt =~ /=\s*[yn]/) {
++	$opt =~ s/=\s*[yn]/=n/;
++	print "OPTION_$opt\n";
++    }
++}
+diff -Naur glibc-2.20/options-config/config-preproc.pl glibc-2.20-patch/options-config/config-preproc.pl
+--- glibc-2.20/options-config/config-preproc.pl	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/options-config/config-preproc.pl	2015-02-19 03:54:31.073759206 -0600
+@@ -0,0 +1,8 @@
++#!/usr/bin/perl
++
++if (@ARGV) {
++    while (<>) {
++	s/OPTION_/CONFIG_/g;
++	print;
++    }
++}
+diff -Naur glibc-2.20/options-config/Makefile glibc-2.20-patch/options-config/Makefile
+--- glibc-2.20/options-config/Makefile	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/options-config/Makefile	2015-02-19 03:54:26.748759537 -0600
+@@ -0,0 +1,55 @@
++# ===========================================================================
++# EGLIBC option-groups configuration targets
++# These targets are included from top-level makefile
++
++ifneq ($(kconfig_tools),)
++ifneq (no,$(PERL))
++
++ocdir := options-config
++
++OconfigDefaults     := option-groups.defaults
++OconfigDefaults_tmp := $(common-objpfx).tmp.defconfig
++OconfigDef          := option-groups.def
++Oconfig             := $(common-objpfx)option-groups.config
++Oconfig_tmp         := $(common-objpfx).tmp.config
++
++conf  := $(kconfig_tools)/conf
++mconf := $(kconfig_tools)/mconf
++
++preproc  := $(PERL) $(ocdir)/config-preproc.pl
++postproc := $(PERL) $(ocdir)/config-postproc.pl
++
++PHONY += defconfig config menuconfig
++
++defconfig: $(conf) $(OconfigDefaults) $(OconfigDef)
++	rm -f $(OconfigDefaults_tmp)
++	rm -f $(Oconfig_tmp)
++	$(preproc) $(OconfigDefaults) > $(OconfigDefaults_tmp)
++	KCONFIG_CONFIG=$(Oconfig_tmp) $< --defconfig=$(OconfigDefaults_tmp) \
++				$(OconfigDef)
++	$(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig)
++	rm $(Oconfig_tmp)
++	rm $(OconfigDefaults_tmp)
++
++config: $(conf) $(OconfigDefaults) $(OconfigDef)
++	rm -f $(Oconfig_tmp)
++	$(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp)
++	KCONFIG_CONFIG=$(Oconfig_tmp) $< --oldaskconfig $(OconfigDef)
++	$(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig)
++	rm $(Oconfig_tmp)
++
++menuconfig: $(mconf) $(OconfigDefaults) $(OconfigDef)
++	rm -f $(Oconfig_tmp)
++	$(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp)
++	KCONFIG_CONFIG=$(Oconfig_tmp) $< $(OconfigDef)
++	$(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig)
++	rm $(Oconfig_tmp)
++
++# Help text used by make help
++help:
++	@echo  '  defconfig	  - New config with default from default config'
++	@echo  '  config	  - Update current config utilising a line-oriented program'
++	@echo  '  menuconfig	  - Update current config utilising a menu based program'
++
++endif
++endif
+diff -Naur glibc-2.20/scripts/option-groups.awk glibc-2.20-patch/scripts/option-groups.awk
+--- glibc-2.20/scripts/option-groups.awk	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/scripts/option-groups.awk	2015-02-19 03:54:31.073759206 -0600
+@@ -0,0 +1,63 @@
++# option-groups.awk --- generate option group header file
++# Given input files containing makefile-style assignments to variables,
++# print out a header file that #defines an appropriate preprocessor
++# symbol for each variable left set to 'y'.
++
++BEGIN { FS="=" }
++
++# Trim spaces.
++{ gsub (/[[:blank:]]/, "") }
++
++# Skip comments.
++/^#/ { next }
++
++# Process assignments.
++NF == 2 {
++    vars[$1] = $2
++}
++
++# Print final values.
++END {
++    print "/* This file is automatically generated by scripts/option-groups.awk"
++    print "   in the EGLIBC source tree."
++    print ""
++    print "   It defines macros that indicate which EGLIBC option groups were"
++    print "   configured in 'option-groups.config' when this C library was"
++    print "   built.  For each option group named OPTION_foo, it #defines"
++    print "   __OPTION_foo to be 1 if the group is enabled, or #defines that"
++    print "   symbol to be 0 if the group is disabled.  */"
++    print ""
++    print "#ifndef __GNU_OPTION_GROUPS_H"
++    print "#define __GNU_OPTION_GROUPS_H"
++    print ""
++
++    # Produce a sorted list of variable names.
++    i=0
++    for (var in vars)
++        names[i++] = var
++    n = asort (names)
++
++    for (i = 1; i <= n; i++)
++    {
++        var = names[i]
++        if (var ~ /^OPTION_/)
++        {
++            if (vars[var] == "y")
++                print "#define __" var " 1"
++            else if (vars[var] == "n")
++                print "#define __" var " 0"
++	    else if (vars[var] ~ /^[0-9]+/ ||
++		     vars[var] ~ /^0x[0-9aAbBcCdDeEfF]+/ ||
++		     vars[var] ~ /^\"/)
++		 print "#define __" var " " vars[var]
++	    else
++		print "/* #undef __" var " */"
++            # Ignore variables that don't have boolean, int, hex, or
++	    # string values. Ideally, this would be driven by the types
++	    # given in option-groups.def.
++        }
++    }
++
++    print ""
++    print "#endif /* __GNU_OPTION_GROUPS_H */"
++}
diff --git a/recipes-core/glibc/glibc-fsl/00xx.glibc.rtld_debug_option_group.patch b/recipes-core/glibc/glibc-fsl/00xx.glibc.rtld_debug_option_group.patch
new file mode 100755
index 0000000..cb3deae
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/00xx.glibc.rtld_debug_option_group.patch
@@ -0,0 +1,517 @@
+# Problem Statement:
+  Remove debug print outs from the run-time linker.
+  Its controlled by __OPTION_EGLIBC_RTLD_DEBUG,
+  so we should use GLRO_dl_debug_mask
+
+# Referred from patch by:
+  Yocto Project
+  http://git.yoctoproject.org/cgit.cgi/poky/plain/meta/recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch
+  Singed-off-by: Khem Raj <raj.khem at gmail.com>
+
+diff -Naur glibc-2.20/csu/libc-start.c glibc-2.20-rtld-debug/csu/libc-start.c
+--- glibc-2.20/csu/libc-start.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/csu/libc-start.c	2015-02-19 04:00:31.552729822 -0600
+@@ -238,7 +238,7 @@
+ 
+   /* Call the initializer of the program, if any.  */
+ #ifdef SHARED
+-  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
++  if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
+     GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
+ #endif
+   if (init)
+@@ -261,7 +261,7 @@
+ #endif
+ 
+ #ifdef SHARED
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS))
+     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
+ #endif
+ 
+diff -Naur glibc-2.20/elf/dl-cache.c glibc-2.20-rtld-debug/elf/dl-cache.c
+--- glibc-2.20/elf/dl-cache.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-cache.c	2015-02-19 04:00:31.552729822 -0600
+@@ -187,7 +187,7 @@
+   const char *best;
+ 
+   /* Print a message if the loading of libs is traced.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))
+     _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
+ 
+   if (cache == NULL)
+@@ -285,7 +285,7 @@
+     }
+ 
+   /* Print our result if wanted.  */
+-  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)
++  if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, 0)
+       && best != NULL)
+     _dl_debug_printf ("  trying file=%s\n", best);
+ 
+diff -Naur glibc-2.20/elf/dl-close.c glibc-2.20-rtld-debug/elf/dl-close.c
+--- glibc-2.20/elf/dl-close.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-close.c	2015-02-19 04:00:31.553729819 -0600
+@@ -125,7 +125,7 @@
+ 	dl_close_state = rerun;
+ 
+       /* There are still references to this object.  Do nothing more.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+ 	_dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n",
+ 			  map->l_name, map->l_direct_opencount);
+ 
+@@ -257,7 +257,7 @@
+ 	  if (imap->l_init_called)
+ 	    {
+ 	      /* When debugging print a message first.  */
+-	      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
++	      if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS,
+ 				    0))
+ 		_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+ 				  imap->l_name, nsid);
+@@ -664,7 +664,7 @@
+ 	  free (imap->l_reldeps);
+ 
+ 	  /* Print debugging message.  */
+-	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++	  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+ 	    _dl_debug_printf ("\nfile=%s [%lu];  destroying link map\n",
+ 			      imap->l_name, imap->l_ns);
+ 
+diff -Naur glibc-2.20/elf/dl-conflict.c glibc-2.20-rtld-debug/elf/dl-conflict.c
+--- glibc-2.20/elf/dl-conflict.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-conflict.c	2015-02-19 04:00:31.553729819 -0600
+@@ -32,7 +32,7 @@
+ 		       ElfW(Rela) *conflictend)
+ {
+ #if ! ELF_MACHINE_NO_RELA
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC))
+     _dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
+ 
+   {
+diff -Naur glibc-2.20/elf/dl-deps.c glibc-2.20-rtld-debug/elf/dl-deps.c
+--- glibc-2.20/elf/dl-deps.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-deps.c	2015-02-19 04:00:31.553729819 -0600
+@@ -127,7 +127,7 @@
+ 	    else							      \
+ 	      {								      \
+ 		/* This is for DT_AUXILIARY.  */			      \
+-		if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))   \
++		if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))   \
+ 		  _dl_debug_printf (N_("\
+ cannot load auxiliary `%s' because of empty dynamic string token "	      \
+ 					    "substitution\n"), __str);	      \
+@@ -303,7 +303,7 @@
+ 		args.name = name;
+ 
+ 		/* Say that we are about to load an auxiliary library.  */
+-		if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
++		if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS,
+ 				      0))
+ 		  _dl_debug_printf ("load auxiliary object=%s"
+ 				    " requested by file=%s\n",
+@@ -520,7 +520,7 @@
+       runp->map->l_reserved = 0;
+     }
+ 
+-  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0
++  if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_PRELINK, 0) != 0
+       && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
+     {
+       /* If we are to compute conflicts, we have to build local scope
+diff -Naur glibc-2.20/elf/dl-error.c glibc-2.20-rtld-debug/elf/dl-error.c
+--- glibc-2.20/elf/dl-error.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-error.c	2015-02-19 04:00:31.554729815 -0600
+@@ -139,7 +139,7 @@
+ _dl_signal_cerror (int errcode, const char *objname, const char *occation,
+ 		   const char *errstring)
+ {
+-  if (__builtin_expect (GLRO(dl_debug_mask)
++  if (__builtin_expect (GLRO_dl_debug_mask
+ 			& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
+     _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
+ 		      errstring, receiver ? "continued" : "fatal");
+diff -Naur glibc-2.20/elf/dl-fini.c glibc-2.20-rtld-debug/elf/dl-fini.c
+--- glibc-2.20/elf/dl-fini.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-fini.c	2015-02-19 04:00:31.554729815 -0600
+@@ -234,7 +234,7 @@
+ 		  || l->l_info[DT_FINI] != NULL)
+ 		{
+ 		  /* When debugging print a message first.  */
+-		  if (__builtin_expect (GLRO(dl_debug_mask)
++		  if (__builtin_expect (GLRO_dl_debug_mask
+ 					& DL_DEBUG_IMPCALLS, 0))
+ 		    _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+ 				      DSO_FILENAME (l->l_name),
+@@ -286,7 +286,7 @@
+       goto again;
+     }
+ 
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS))
+     _dl_debug_printf ("\nruntime linker statistics:\n"
+ 		      "           final number of relocations: %lu\n"
+ 		      "final number of relocations from cache: %lu\n",
+diff -Naur glibc-2.20/elf/dl-init.c glibc-2.20-rtld-debug/elf/dl-init.c
+--- glibc-2.20/elf/dl-init.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-init.c	2015-02-19 04:00:31.554729815 -0600
+@@ -52,7 +52,7 @@
+     return;
+ 
+   /* Print a debug message if wanted.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS))
+     _dl_debug_printf ("\ncalling init: %s\n\n",
+ 		      DSO_FILENAME (l->l_name));
+ 
+@@ -102,7 +102,7 @@
+       ElfW(Addr) *addrs;
+       unsigned int cnt;
+ 
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS))
+ 	_dl_debug_printf ("\ncalling preinit: %s\n\n",
+ 			  DSO_FILENAME (main_map->l_name));
+ 
+diff -Naur glibc-2.20/elf/dl-load.c glibc-2.20-rtld-debug/elf/dl-load.c
+--- glibc-2.20/elf/dl-load.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-load.c	2015-02-19 04:00:31.555729814 -0600
+@@ -957,7 +957,7 @@
+     }
+ 
+   /* Print debugging message.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+     _dl_debug_printf ("file=%s [%lu];  generating link map\n", name, nsid);
+ 
+   /* This is the ELF header.  We read it in `open_verify'.  */
+@@ -1361,7 +1361,7 @@
+ 
+   l->l_entry += l->l_addr;
+ 
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+     _dl_debug_printf ("\
+   dynamic: 0x%0*lx  base: 0x%0*lx   size: 0x%0*Zx\n\
+     entry: 0x%0*lx  phdr: 0x%0*lx  phnum:   %*u\n\n",
+@@ -1787,7 +1787,7 @@
+ 
+       /* If we are debugging the search for libraries print the path
+ 	 now if it hasn't happened now.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)
+ 	  && current_what != this_dir->what)
+ 	{
+ 	  current_what = this_dir->what;
+@@ -1808,7 +1808,7 @@
+ 	     - buf);
+ 
+ 	  /* Print name we try if this is wanted.  */
+-	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
++	  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))
+ 	    _dl_debug_printf ("  trying file=%s\n", buf);
+ 
+ 	  fd = open_verify (buf, fbp, loader, whatcode, mode,
+@@ -1953,7 +1953,7 @@
+     }
+ 
+   /* Display information if we are debugging.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)
+       && loader != NULL)
+     _dl_debug_printf ((mode & __RTLD_CALLMAP) == 0
+ 		      ? "\nfile=%s [%lu];  needed by %s [%lu]\n"
+@@ -1995,7 +1995,7 @@
+ 
+       size_t namelen = strlen (name) + 1;
+ 
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))
+ 	_dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid);
+ 
+       fd = -1;
+@@ -2122,7 +2122,7 @@
+ 			&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
+ 
+       /* Add another newline when we are tracing the library loading.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))
+ 	_dl_debug_printf ("\n");
+     }
+   else
+@@ -2155,7 +2155,7 @@
+   if (__glibc_unlikely (fd == -1))
+     {
+       if (trace_mode
+-	  && __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0))
++	  && __glibc_likely ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK) == 0))
+ 	{
+ 	  /* We haven't found an appropriate library.  But since we
+ 	     are only interested in the list of libraries this isn't
+diff -Naur glibc-2.20/elf/dl-lookup.c glibc-2.20-rtld-debug/elf/dl-lookup.c
+--- glibc-2.20/elf/dl-lookup.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-lookup.c	2015-02-19 04:00:31.551729823 -0600
+@@ -300,7 +300,7 @@
+ 	 hash table.  */
+       if (__glibc_unlikely (tab->size))
+ 	{
+-	  assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
++	  assert (GLRO_dl_debug_mask & DL_DEBUG_PRELINK);
+ 	  goto success;
+ 	}
+ #endif
+@@ -375,7 +375,7 @@
+ 	continue;
+ 
+       /* Print some debugging info if wanted.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SYMBOLS))
+ 	_dl_debug_printf ("symbol=%s;  lookup in file=%s [%lu]\n",
+ 			  undef_name, DSO_FILENAME (map->l_name),
+ 			  map->l_ns);
+@@ -698,7 +698,7 @@
+ 	}
+ 
+       /* Display information if we are debugging.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+ 	_dl_debug_printf ("\
+ \nfile=%s [%lu];  needed by %s [%lu] (relocation dependency)\n\n",
+ 			  DSO_FILENAME (map->l_name),
+@@ -802,7 +802,7 @@
+     {
+       if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
+ 	  && skip_map == NULL
+-	  && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
++	  && !(GLRO_dl_debug_mask & DL_DEBUG_UNUSED))
+ 	{
+ 	  /* We could find no value for a strong reference.  */
+ 	  const char *reference_name = undef_map ? undef_map->l_name : "";
+@@ -873,7 +873,7 @@
+   if (__glibc_unlikely (current_value.m->l_used == 0))
+     current_value.m->l_used = 1;
+ 
+-  if (__glibc_unlikely (GLRO(dl_debug_mask)
++  if (__glibc_unlikely (GLRO_dl_debug_mask
+ 			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK)))
+     _dl_debug_bindings (undef_name, undef_map, ref,
+ 			&current_value, version, type_class, protected);
+@@ -938,7 +938,7 @@
+ {
+   const char *reference_name = undef_map->l_name;
+ 
+-  if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
++  if (GLRO_dl_debug_mask & DL_DEBUG_BINDINGS)
+     {
+       _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
+ 			DSO_FILENAME (reference_name),
+@@ -952,7 +952,7 @@
+ 	_dl_debug_printf_c ("\n");
+     }
+ #ifdef SHARED
+-  if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
++  if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK)
+     {
+       int conflict = 0;
+       struct sym_val val = { NULL, NULL };
+diff -Naur glibc-2.20/elf/dl-object.c glibc-2.20-rtld-debug/elf/dl-object.c
+--- glibc-2.20/elf/dl-object.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-object.c	2015-02-19 04:00:31.555729814 -0600
+@@ -98,7 +98,7 @@
+   new->l_type = type;
+   /* If we set the bit now since we know it is never used we avoid
+      dirtying the cache line later.  */
+-  if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0)
++  if ((GLRO_dl_debug_mask & DL_DEBUG_UNUSED) == 0)
+     new->l_used = 1;
+   new->l_loader = loader;
+ #if NO_TLS_OFFSET != 0
+diff -Naur glibc-2.20/elf/dl-open.c glibc-2.20-rtld-debug/elf/dl-open.c
+--- glibc-2.20/elf/dl-open.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-open.c	2015-02-19 04:00:31.549729817 -0600
+@@ -147,7 +147,7 @@
+ 	  ns->_ns_main_searchlist->r_list[new_nlist++] = map;
+ 
+ 	  /* We modify the global scope.  Report this.  */
+-	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
++	  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES))
+ 	    _dl_debug_printf ("\nadd %s [%lu] to global scope\n",
+ 			      map->l_name, map->l_ns);
+ 	}
+@@ -243,7 +243,7 @@
+   if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
+     {
+       /* Let the user know about the opencount.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+ 	_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+ 			  new->l_name, new->l_ns, new->l_direct_opencount);
+ 
+@@ -294,7 +294,7 @@
+   LIBC_PROBE (map_complete, 3, args->nsid, r, new);
+ 
+   /* Print scope information.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES))
+     _dl_show_scope (new, 0);
+ 
+   /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */
+@@ -511,7 +511,7 @@
+ 	}
+ 
+       /* Print scope information.  */
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES))
+ 	_dl_show_scope (imap, from_scope);
+     }
+ 
+@@ -584,7 +584,7 @@
+ #endif
+ 
+   /* Let the user know about the opencount.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES))
+     _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+ 		      new->l_name, new->l_ns, new->l_direct_opencount);
+ }
+diff -Naur glibc-2.20/elf/dl-reloc.c glibc-2.20-rtld-debug/elf/dl-reloc.c
+--- glibc-2.20/elf/dl-reloc.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-reloc.c	2015-02-19 04:00:31.556729815 -0600
+@@ -183,7 +183,7 @@
+       && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
+     lazy = 0;
+ 
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC))
+     _dl_debug_printf ("\nrelocation processing: %s%s\n",
+ 		      DSO_FILENAME (l->l_name), lazy ? " (lazy)" : "");
+ 
+diff -Naur glibc-2.20/elf/dl-version.c glibc-2.20-rtld-debug/elf/dl-version.c
+--- glibc-2.20/elf/dl-version.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/dl-version.c	2015-02-19 04:00:31.556729815 -0600
+@@ -82,7 +82,7 @@
+   int result = 0;
+ 
+   /* Display information about what we are doing while debugging.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_VERSIONS))
+     _dl_debug_printf ("\
+ checking for version `%s' in file %s [%lu] required by file %s [%lu]\n",
+ 		      string, DSO_FILENAME (map->l_name),
+diff -Naur glibc-2.20/elf/get-dynamic-info.h glibc-2.20-rtld-debug/elf/get-dynamic-info.h
+--- glibc-2.20/elf/get-dynamic-info.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-rtld-debug/elf/get-dynamic-info.h	2015-02-19 04:00:31.551729823 -0600
+@@ -157,7 +157,7 @@
+ 	 them. Therefore to avoid breaking existing applications the
+ 	 best we can do is add a warning during debugging with the
+ 	 intent of notifying the user of the problem.  */
+-      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)
++      if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_FILES, 0)
+ 	  && l->l_flags_1 & ~DT_1_SUPPORTED_MASK)
+ 	_dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n",
+ 			  l->l_flags_1 & ~DT_1_SUPPORTED_MASK);
+diff -Naur glibc-2.20/elf/rtld.c glibc-2.20-rtld-debug/elf/rtld.c
+--- glibc-2.20/elf/rtld.c	2015-02-19 04:00:03.365732116 -0600
++++ glibc-2.20-rtld-debug/elf/rtld.c	2015-02-19 04:00:31.550729821 -0600
+@@ -321,7 +321,7 @@
+     }
+ #endif
+ 
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS))
+     {
+ #ifndef HP_TIMING_NONAVAIL
+       print_statistics (&rtld_total_time);
+@@ -1699,7 +1699,7 @@
+ 	 after relocation.  */
+       struct link_map *l;
+ 
+-      if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
++      if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK)
+ 	{
+ 	  struct r_scope_elem *scope = &main_map->l_searchlist;
+ 
+@@ -1729,7 +1729,7 @@
+ 		_dl_printf ("\n");
+ 	    }
+ 	}
+-      else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
++      else if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED)
+ 	{
+ 	  /* Look through the dependencies of the main executable
+ 	     and determine which of them is not actually
+@@ -1837,7 +1837,7 @@
+ 		    }
+ 		}
+ 
+-	      if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
++	      if ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK)
+ 		  && rtld_multiple_ref)
+ 		{
+ 		  /* Mark the link map as not yet relocated again.  */
+@@ -1970,7 +1970,7 @@
+       if (r_list == r_listend && liblist == liblistend)
+ 	prelinked = true;
+ 
+-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
++      if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS))
+ 	_dl_debug_printf ("\nprelink checking: %s\n",
+ 			  prelinked ? "ok" : "failed");
+     }
+@@ -1988,7 +1988,7 @@
+   GLRO(dl_init_all_dirs) = GL(dl_all_dirs);
+ 
+   /* Print scope information.  */
+-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
++  if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES))
+     {
+       _dl_debug_printf ("\nInitial object scopes\n");
+ 
+@@ -2262,7 +2262,7 @@
+ 	    if (debopts[cnt].len == len
+ 		&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
+ 	      {
+-		GLRO(dl_debug_mask) |= debopts[cnt].mask;
++		GLRO_dl_debug_mask |= debopts[cnt].mask;
+ 		any_debug = 1;
+ 		break;
+ 	      }
+@@ -2283,7 +2283,7 @@
+       ++dl_debug;
+     }
+ 
+-  if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
++  if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED)
+     {
+       /* In order to get an accurate picture of whether a particular
+ 	 DT_NEEDED entry is actually used we have to process both
+@@ -2291,7 +2291,7 @@
+       GLRO(dl_lazy) = 0;
+     }
+ 
+-  if (GLRO(dl_debug_mask) & DL_DEBUG_HELP)
++  if (GLRO_dl_debug_mask & DL_DEBUG_HELP)
+     {
+       size_t cnt;
+ 
+@@ -2490,7 +2490,7 @@
+ 	    {
+ 	      mode = trace;
+ 	      GLRO(dl_verbose) = 1;
+-	      GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
++	      GLRO_dl_debug_mask |= DL_DEBUG_PRELINK;
+ 	      GLRO(dl_trace_prelink) = &envline[17];
+ 	    }
+ 	  break;
+@@ -2537,7 +2537,7 @@
+       if (__access ("/etc/suid-debug", F_OK) != 0)
+ 	{
+ 	  unsetenv ("MALLOC_CHECK_");
+-	  GLRO(dl_debug_mask) = 0;
++	  GLRO_dl_debug_mask = 0;
+ 	}
+ 
+       if (mode != normal)
diff --git a/recipes-core/glibc/glibc-fsl/00xx.glibc.use-option-groups.patch b/recipes-core/glibc/glibc-fsl/00xx.glibc.use-option-groups.patch
new file mode 100755
index 0000000..9ba413e
--- /dev/null
+++ b/recipes-core/glibc/glibc-fsl/00xx.glibc.use-option-groups.patch
@@ -0,0 +1,16551 @@
+# Problem Statement:
+  Forward port eglibc options groups support to glibc v2.20
+
+# Referred from patch by:
+  Yocto Project
+  http://git.yoctoproject.org/cgit.cgi/poky/plain/meta/recipes-core/glibc/glibc/eglibc-use-option-groups.patch
+  Upstream-Status: Pending
+
+  * Updated patch to fix glibc test suite failures.
+
+diff -Naur glibc-2.20/argp/argp-fmtstream.c glibc-2.20-patch/argp/argp-fmtstream.c
+--- glibc-2.20/argp/argp-fmtstream.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/argp/argp-fmtstream.c	2015-03-04 00:51:32.366952005 -0600
+@@ -42,6 +42,7 @@
+ #ifdef _LIBC
+ # include <wchar.h>
+ # include <libio/libioP.h>
++# include <gnu/option-groups.h>
+ # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
+ #endif
+ 
+@@ -100,7 +101,11 @@
+   __argp_fmtstream_update (fs);
+   if (fs->p > fs->buf)
+     {
++#ifdef _LIBC
+       __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
++#else
++      fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
++#endif
+     }
+   free (fs->buf);
+   free (fs);
+@@ -145,9 +150,17 @@
+ 	      size_t i;
+ 	      for (i = 0; i < pad; i++)
+ 		{
++#ifdef _LIBC
+ 		  if (_IO_fwide (fs->stream, 0) > 0)
+-		    putwc_unlocked (L' ', fs->stream);
++                    {
++#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
++                      putwc_unlocked (L' ', fs->stream);
++#else
++                      abort ();
++#endif
++                    }
+ 		  else
++#endif
+ 		    putc_unlocked (' ', fs->stream);
+ 		}
+ 	    }
+@@ -308,9 +321,17 @@
+ 	      *nl++ = ' ';
+ 	  else
+ 	    for (i = 0; i < fs->wmargin; ++i)
++#ifdef _LIBC
+ 	      if (_IO_fwide (fs->stream, 0) > 0)
+-		putwc_unlocked (L' ', fs->stream);
++                {
++#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO
++                  putwc_unlocked (L' ', fs->stream);
++#else
++                  abort ();
++#endif
++                }
+ 	      else
++#endif
+ 		putc_unlocked (' ', fs->stream);
+ 
+ 	  /* Copy the tail of the original buffer into the current buffer
+diff -Naur glibc-2.20/argp/argp-help.c glibc-2.20-patch/argp/argp-help.c
+--- glibc-2.20/argp/argp-help.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/argp/argp-help.c	2015-03-04 00:51:32.366952005 -0600
+@@ -51,6 +51,7 @@
+ #ifdef _LIBC
+ # include <../libio/libioP.h>
+ # include <wchar.h>
++# include <gnu/option-groups.h>
+ #endif
+ 
+ #ifndef _
+@@ -1702,7 +1703,7 @@
+ }
+ 
+ char *
+-__argp_short_program_name (void)
++(__argp_short_program_name) (void)
+ {
+ # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+   return program_invocation_short_name;
+@@ -1873,9 +1874,17 @@
+ #endif
+ 	    }
+ 
++#ifdef _LIBC
+ 	  if (_IO_fwide (stream, 0) > 0)
+-	    putwc_unlocked (L'\n', stream);
++            {
++#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
++              putwc_unlocked (L'\n', stream);
++#else
++              abort ();
++#endif
++            }
+ 	  else
++#endif
+ 	    putc_unlocked ('\n', stream);
+ 
+ #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+diff -Naur glibc-2.20/argp/argp-namefrob.h glibc-2.20-patch/argp/argp-namefrob.h
+--- glibc-2.20/argp/argp-namefrob.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/argp/argp-namefrob.h	2015-03-04 00:51:32.366952005 -0600
+@@ -76,10 +76,12 @@
+ #undef __argp_fmtstream_wmargin
+ #define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+ 
++#if 0
+ #include "mempcpy.h"
+ #include "strcase.h"
+ #include "strchrnul.h"
+ #include "strndup.h"
++#endif
+ 
+ /* normal libc functions we call */
+ #undef __flockfile
+diff -Naur glibc-2.20/argp/Makefile glibc-2.20-patch/argp/Makefile
+--- glibc-2.20/argp/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/argp/Makefile	2015-03-04 00:51:32.366952005 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Makefile for argp.
+ #
++include ../option-groups.mak
++
+ subdir	:= argp
+ 
+ include ../Makeconfig
+diff -Naur glibc-2.20/catgets/Makefile glibc-2.20-patch/catgets/Makefile
+--- glibc-2.20/catgets/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/catgets/Makefile	2015-03-04 00:51:32.367952004 -0600
+@@ -22,20 +22,23 @@
+ 
+ include ../Makeconfig
+ 
++include ../option-groups.mak
++
+ headers		= nl_types.h
+-routines	= catgets open_catalog
+-others		= gencat
+-install-bin	= gencat
+-extra-objs	= $(gencat-modules:=.o)
++routines-$(OPTION_EGLIBC_CATGETS)    := catgets open_catalog
++others-$(OPTION_EGLIBC_CATGETS)      := gencat
++install-bin-$(OPTION_EGLIBC_CATGETS) := gencat
++extra-objs-$(OPTION_EGLIBC_CATGETS)  := $(gencat-modules:=.o)
+ 
+-tests = tst-catgets
+-test-srcs = test-gencat
++tests-$(OPTION_EGLIBC_CATGETS)       := tst-catgets
++test-srcs-$(OPTION_EGLIBC_CATGETS)   := test-gencat
+ 
++ifeq (y,$(OPTION_EGLIBC_CATGETS))
+ ifeq ($(run-built-tests),yes)
+ tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
+ 		 $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
+ endif
+-
++endif
+ gencat-modules	= xmalloc
+ 
+ # To find xmalloc.c
+diff -Naur glibc-2.20/crypt/crypt_common.c glibc-2.20-patch/crypt/crypt_common.c
+--- glibc-2.20/crypt/crypt_common.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/crypt/crypt_common.c	2015-03-04 00:51:32.367952004 -0600
+@@ -0,0 +1,42 @@
++/*
++ * crypt: crypt(3) implementation
++ *
++ * Copyright (C) 1991-2014 Free Software Foundation, Inc.
++ *
++ * This 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.
++ *
++ * This 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 this library; see the file COPYING.LIB.  If not,
++ * see <http://www.gnu.org/licenses/>.
++ *
++ * General Support routines
++ *
++ */
++
++#include "crypt-private.h"
++
++/* Table with characters for base64 transformation.  */
++static const char b64t[64] =
++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
++
++void
++__b64_from_24bit (char **cp, int *buflen,
++		  unsigned int b2, unsigned int b1, unsigned int b0,
++		  int n)
++{
++  unsigned int w = (b2 << 16) | (b1 << 8) | b0;
++  while (n-- > 0 && (*buflen) > 0)
++    {
++      *(*cp)++ = b64t[w & 0x3f];
++      --(*buflen);
++      w >>= 6;
++    }
++}
+diff -Naur glibc-2.20/crypt/crypt-entry.c glibc-2.20-patch/crypt/crypt-entry.c
+--- glibc-2.20/crypt/crypt-entry.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/crypt/crypt-entry.c	2015-03-04 00:51:32.367952004 -0600
+@@ -27,6 +27,7 @@
+ #include <stdio.h>
+ #endif
+ #include <string.h>
++#include <gnu/option-groups.h>
+ #include <errno.h>
+ #include <fips-private.h>
+ 
+@@ -76,9 +77,11 @@
+      const char *salt;
+      struct crypt_data * __restrict data;
+ {
++#if __OPTION_EGLIBC_CRYPT_UFC
+   ufc_long res[4];
+   char ktab[9];
+   ufc_long xx = 25; /* to cope with GCC long long compiler bugs */
++#endif /*__OPTION_EGLIBC_CRYPT_UFC*/
+ 
+ #ifdef _LIBC
+   /* Try to find out whether we have to use MD5 encryption replacement.  */
+@@ -105,6 +108,7 @@
+ 			     sizeof (struct crypt_data));
+ #endif
+ 
++#if __OPTION_EGLIBC_CRYPT_UFC
+   /*
+    * Hack DES tables according to salt
+    */
+@@ -144,6 +148,10 @@
+    */
+   _ufc_output_conversion_r (res[0], res[1], salt, data);
+   return data->crypt_3_buf;
++#else /* __OPTION_EGLIBC_CRYPT_UFC */
++  __set_errno (ENOSYS);
++  return NULL;
++#endif /* __OPTION_EGLIBC_CRYPT_UFC */
+ }
+ weak_alias (__crypt_r, crypt_r)
+ 
+@@ -168,7 +176,12 @@
+     return __sha512_crypt (key, salt);
+ #endif
+ 
++#if __OPTION_EGLIBC_CRYPT_UFC
+   return __crypt_r (key, salt, &_ufc_foobar);
++#else /* __OPTION_EGLIBC_CRYPT_UFC */
++  __set_errno (ENOSYS);
++  return NULL;
++#endif /* __OPTION_EGLIBC_CRYPT_UFC */
+ }
+ 
+ 
+diff -Naur glibc-2.20/crypt/crypt_util.c glibc-2.20-patch/crypt/crypt_util.c
+--- glibc-2.20/crypt/crypt_util.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/crypt/crypt_util.c	2015-03-04 00:51:32.367952004 -0600
+@@ -242,10 +242,6 @@
+  */
+ static ufc_long efp[16][64][2];
+ 
+-/* Table with characters for base64 transformation.  */
+-static const char b64t[64] =
+-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+-
+ /*
+  * For use by the old, non-reentrant routines
+  * (crypt/encrypt/setkey)
+@@ -949,17 +945,3 @@
+ {
+   __setkey_r(__key, &_ufc_foobar);
+ }
+-
+-void
+-__b64_from_24bit (char **cp, int *buflen,
+-		  unsigned int b2, unsigned int b1, unsigned int b0,
+-		  int n)
+-{
+-  unsigned int w = (b2 << 16) | (b1 << 8) | b0;
+-  while (n-- > 0 && (*buflen) > 0)
+-    {
+-      *(*cp)++ = b64t[w & 0x3f];
+-      --(*buflen);
+-      w >>= 6;
+-    }
+-}
+diff -Naur glibc-2.20/crypt/Makefile glibc-2.20-patch/crypt/Makefile
+--- glibc-2.20/crypt/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/crypt/Makefile	2015-03-04 00:51:32.367952004 -0600
+@@ -18,21 +18,25 @@
+ #
+ #	Sub-makefile for crypt() portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= crypt
+ 
+ include ../Makeconfig
+ 
+ headers := crypt.h
+ 
+-extra-libs := libcrypt
+-extra-libs-others := $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_CRYPT) := libcrypt
++extra-libs-others-y := $(extra-libs-y)
+ 
+-libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
+-		     crypt_util
++libcrypt-routines :=crypt-entry  md5-crypt sha256-crypt sha512-crypt crypt_common
++libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt crypt_util
++libcrypt-routines += $(libcrypt-routines-y)
+ 
+-tests := cert md5c-test sha256c-test sha512c-test badsalttest
++tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest
++tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert
+ 
+-ifeq ($(crypt-in-libc),yes)
++ifeq ($(crypt-in-libc)$(OPTION_EGLIBC_CRYPT),yesy)
+ routines += $(libcrypt-routines)
+ endif
+ 
+@@ -44,7 +48,7 @@
+ else
+ libcrypt-routines += md5 sha256 sha512
+ 
+-tests += md5test sha256test sha512test
++tests-$(OPTION_EGLIBC_CRYPT) += md5test sha256test sha512test
+ 
+ # The test md5test-giant uses up to 400 MB of RSS and runs on a fast
+ # machine over a minute.
+@@ -64,8 +68,10 @@
+ $(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines))
+ endif
+ 
++ifeq ($(OPTION_EGLIBC_CRYPT),y)
+ ifeq (yes,$(build-shared))
+ $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so
+ else
+ $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a
+ endif
++endif # eglibc: OPTION_EGLIBC_CRYPT
+diff -Naur glibc-2.20/csu/Makefile glibc-2.20-patch/csu/Makefile
+--- glibc-2.20/csu/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/csu/Makefile	2015-03-04 00:51:32.368952005 -0600
+@@ -22,6 +22,8 @@
+ # crtn.o, special "initializer" and "finalizer" files used in the link
+ # to make the .init and .fini sections work right.
+ 
++include ../option-groups.mak
++
+ subdir := csu
+ 
+ include ../Makeconfig
+diff -Naur glibc-2.20/debug/Makefile glibc-2.20-patch/debug/Makefile
+--- glibc-2.20/debug/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/debug/Makefile	2015-03-04 00:51:32.368952005 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for debug portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= debug
+ 
+ include ../Makeconfig
+@@ -27,7 +29,7 @@
+ # Note that ptsname_r_chk and getlogin_r are not here, but in
+ # login/Makefile instead.  If that subdir is omitted from the
+ # build, its _FORTIFY_SOURCE support will be too.
+-routines  = backtrace backtracesyms backtracesymsfd noophooks \
++routines  = noophooks \
+ 	    memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
+ 	    strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
+ 	    sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
+@@ -36,20 +38,27 @@
+ 	    read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
+ 	    readlink_chk readlinkat_chk getwd_chk getcwd_chk \
+ 	    realpath_chk fread_chk fread_u_chk \
+-	    wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
+-	    wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
+-	    wcpncpy_chk \
+-	    swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \
+-	    vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \
+ 	    confstr_chk getgroups_chk ttyname_r_chk \
+-	    gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \
+-	    wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
+-	    wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \
++	    gethostname_chk getdomainname_chk \
++	    asprintf_chk vasprintf_chk dprintf_chk \
+ 	    vdprintf_chk obprintf_chk \
+ 	    longjmp_chk ____longjmp_chk \
+ 	    fdelt_chk poll_chk ppoll_chk \
+ 	    stack_chk_fail fortify_fail \
+ 	    $(static-only-routines)
++routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd
++routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)			\
++	 += wprintf_chk fwprintf_chk				\
++	    vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk
++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR)				\
++	 += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk	\
++	    wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk	\
++	    wcpncpy_chk							\
++	    swprintf_chk vswprintf_chk					\
++	    wcrtomb_chk mbsnrtowcs_chk					\
++	    wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk	\
++	    wcstombs_chk
++
+ static-only-routines := warning-nop stack_chk_fail_local
+ 
+ CFLAGS-backtrace.c = -fno-omit-frame-pointer
+@@ -129,11 +138,15 @@
+ LDFLAGS-tst-backtrace5 = -rdynamic
+ LDFLAGS-tst-backtrace6 = -rdynamic
+ 
+-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
+-	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
+-	tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
+-	tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
+-	tst-backtrace5 tst-backtrace6
++tests = tst-longjmp_chk test-strcpy_chk test-stpcpy_chk tst-longjmp_chk2
++tests-$(OPTION_EGLIBC_LOCALE_CODE) \
++      += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3
++tests-$(OPTION_EGLIBC_BACKTRACE) \
++      += backtrace-tst tst-backtrace2 tst-backtrace3 tst-backtrace4 \
++         tst-backtrace5 tst-backtrace6
++ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS))
++tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6
++endif
+ 
+ tests-ifunc := $(stpcpy_chk strcpy_chk:%=test-%-ifunc)
+ tests += $(tests-ifunc)
+diff -Naur glibc-2.20/debug/segfault.c glibc-2.20-patch/debug/segfault.c
+--- glibc-2.20/debug/segfault.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/debug/segfault.c	2015-03-04 00:51:32.368952005 -0600
+@@ -30,6 +30,7 @@
+ #include <unistd.h>
+ #include <_itoa.h>
+ #include <ldsodefs.h>
++#include <gnu/option-groups.h>
+ 
+ /* This file defines macros to access the content of the sigcontext element
+    passed up by the signal handler.  */
+@@ -91,6 +92,7 @@
+   REGISTER_DUMP;
+ #endif
+ 
++#if __OPTION_EGLIBC_BACKTRACE
+   WRITE_STRING ("\nBacktrace:\n");
+ 
+   /* Get the backtrace.  */
+@@ -113,6 +115,7 @@
+ 
+   /* Now generate nicely formatted output.  */
+   __backtrace_symbols_fd (arr + i, cnt - i, fd);
++#endif
+ 
+ #ifdef HAVE_PROC_SELF
+   /* Now the link map.  */
+diff -Naur glibc-2.20/debug/tst-chk1.c glibc-2.20-patch/debug/tst-chk1.c
+--- glibc-2.20/debug/tst-chk1.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/debug/tst-chk1.c	2015-03-04 00:51:32.368952005 -0600
+@@ -31,6 +31,7 @@
+ #include <sys/select.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
++#include <gnu/option-groups.h>
+ 
+ 
+ #define obstack_chunk_alloc malloc
+@@ -307,6 +308,7 @@
+   snprintf (buf + 8, l0 + 3, "%d", num2);
+   CHK_FAIL_END
+ 
++#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+   CHK_FAIL_START
+   swprintf (wbuf + 8, 3, L"%d", num1);
+   CHK_FAIL_END
+@@ -314,6 +316,7 @@
+   CHK_FAIL_START
+   swprintf (wbuf + 8, l0 + 3, L"%d", num1);
+   CHK_FAIL_END
++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
+ # endif
+ 
+   memcpy (buf, str1 + 2, l0 + 9);
+@@ -381,6 +384,7 @@
+   CHK_FAIL_END
+ #endif
+ 
++#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+ 
+   /* These ops can be done without runtime checking of object size.  */
+   wmemcpy (wbuf, L"abcdefghij", 10);
+@@ -605,6 +609,7 @@
+   CHK_FAIL_END
+ #endif
+ 
++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
+ 
+   /* Now checks for %n protection.  */
+ 
+@@ -1192,6 +1197,7 @@
+ # endif
+ #endif
+ 
++#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+   if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
+     {
+       assert (MB_CUR_MAX <= 10);
+@@ -1348,6 +1354,7 @@
+       puts ("cannot set locale");
+       ret = 1;
+     }
++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
+ 
+   int fd = posix_openpt (O_RDWR);
+   if (fd != -1)
+diff -Naur glibc-2.20/dlfcn/Makefile glibc-2.20-patch/dlfcn/Makefile
+--- glibc-2.20/dlfcn/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/dlfcn/Makefile	2015-03-04 00:51:32.368952005 -0600
+@@ -15,6 +15,8 @@
+ # License along with the GNU C Library; if not, see
+ # <http://www.gnu.org/licenses/>.
+ 
++include ../option-groups.mak
++
+ subdir		:= dlfcn
+ 
+ include ../Makeconfig
+@@ -36,14 +38,20 @@
+ ifeq (yes,$(build-shared))
+ tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
+ 	bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
+-	bug-atexit3 tstatexit bug-dl-leaf
++	tstatexit bug-dl-leaf
++
++tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3
+ endif
+ modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
+ 		defaultmod2 errmsg1mod modatexit modcxaatexit \
+ 		bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \
+-		bug-atexit2-lib bug-atexit3-lib bug-dl-leaf-lib \
++		bug-atexit2-lib bug-dl-leaf-lib \
+ 		bug-dl-leaf-lib-cb
+ 
++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS))
++modules-names += bug-atexit3-lib
++endif
++
+ failtestmod.so-no-z-defs = yes
+ glreflib2.so-no-z-defs = yes
+ errmsg1mod.so-no-z-defs = yes
+diff -Naur glibc-2.20/elf/dl-support.c glibc-2.20-patch/elf/dl-support.c
+--- glibc-2.20/elf/dl-support.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/elf/dl-support.c	2015-03-04 00:51:32.369952006 -0600
+@@ -19,6 +19,7 @@
+ /* This file defines some things that for the dynamic linker are defined in
+    rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking.  */
+ 
++#include <gnu/option-groups.h>
+ #include <errno.h>
+ #include <libintl.h>
+ #include <stdlib.h>
+@@ -42,7 +43,9 @@
+ const char *_dl_platform;
+ size_t _dl_platformlen;
+ 
++#if __OPTION_EGLIBC_RTLD_DEBUG
+ int _dl_debug_mask;
++#endif
+ int _dl_lazy;
+ ElfW(Addr) _dl_use_load_bias = -2;
+ int _dl_dynamic_weak;
+diff -Naur glibc-2.20/elf/Makefile glibc-2.20-patch/elf/Makefile
+--- glibc-2.20/elf/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/elf/Makefile	2015-03-04 00:51:32.369952006 -0600
+@@ -17,6 +17,8 @@
+ 
+ # Makefile for elf subdirectory of GNU C Library.
+ 
++include ../option-groups.mak
++
+ subdir		:= elf
+ 
+ include ../Makeconfig
+@@ -144,10 +146,11 @@
+ 	 unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
+ 	 tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
+ 	 tst-stackguard1 tst-addr1 tst-thrlock \
+-	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
++	 tst-unique1 tst-unique2 \
+ 	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+ 	 tst-ptrguard1
+ #	 reldep9
++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-unique3 tst-unique4
+ ifeq ($(build-hardcoded-path-in-tests),yes)
+ tests += tst-dlopen-aout
+ endif
+@@ -205,8 +208,6 @@
+ 		tst-unique1mod1 tst-unique1mod2 \
+ 		tst-unique2mod1 tst-unique2mod2 \
+ 		tst-auditmod9a tst-auditmod9b \
+-		tst-unique3lib tst-unique3lib2 \
+-		tst-unique4lib \
+ 		tst-initordera1 tst-initorderb1 \
+ 		tst-initordera2 tst-initorderb2 \
+ 		tst-initordera3 tst-initordera4 \
+@@ -214,6 +215,9 @@
+ 		tst-initorder2d \
+ 		tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
+ 		tst-array5dep tst-null-argv-lib
++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS))
++modules-names += tst-unique3lib tst-unique3lib2 tst-unique4lib 
++endif
+ ifeq (yesyes,$(have-fpie)$(build-shared))
+ modules-names += tst-piemod1
+ tests += tst-pie1 tst-pie2
+diff -Naur glibc-2.20/elf/rtld.c glibc-2.20-patch/elf/rtld.c
+--- glibc-2.20/elf/rtld.c	2015-03-04 00:49:59.303952005 -0600
++++ glibc-2.20-patch/elf/rtld.c	2015-03-04 00:51:32.369952006 -0600
+@@ -16,6 +16,7 @@
+    License along with the GNU C Library; if not, see
+    <http://www.gnu.org/licenses/>.  */
+ 
++#include <gnu/option-groups.h>
+ #include <errno.h>
+ #include <dlfcn.h>
+ #include <fcntl.h>
+@@ -2200,6 +2201,7 @@
+ 		    objname, errstring);
+ }
+ 
++#if __OPTION_EGLIBC_RTLD_DEBUG
+ /* Nonzero if any of the debugging options is enabled.  */
+ static int any_debug attribute_relro;
+ 
+@@ -2309,6 +2311,7 @@
+       _exit (0);
+     }
+ }
++#endif /* __OPTION_EGLIBC_RTLD_DEBUG */
+ 
+ static void
+ process_dl_audit (char *str)
+@@ -2376,12 +2379,14 @@
+ 	  break;
+ 
+ 	case 5:
++#if __OPTION_EGLIBC_RTLD_DEBUG
+ 	  /* Debugging of the dynamic linker?  */
+ 	  if (memcmp (envline, "DEBUG", 5) == 0)
+ 	    {
+ 	      process_dl_debug (&envline[6]);
+ 	      break;
+ 	    }
++#endif
+ 	  if (memcmp (envline, "AUDIT", 5) == 0)
+ 	    process_dl_audit (&envline[6]);
+ 	  break;
+@@ -2490,7 +2495,9 @@
+ 	    {
+ 	      mode = trace;
+ 	      GLRO(dl_verbose) = 1;
++#if __OPTION_EGLIBC_RTLD_DEBUG
+ 	      GLRO_dl_debug_mask |= DL_DEBUG_PRELINK;
++#endif
+ 	      GLRO(dl_trace_prelink) = &envline[17];
+ 	    }
+ 	  break;
+@@ -2537,12 +2544,15 @@
+       if (__access ("/etc/suid-debug", F_OK) != 0)
+ 	{
+ 	  unsetenv ("MALLOC_CHECK_");
++#if __OPTION_EGLIBC_RTLD_DEBUG
+ 	  GLRO_dl_debug_mask = 0;
++#endif
+ 	}
+ 
+       if (mode != normal)
+ 	_exit (5);
+     }
++#if __OPTION_EGLIBC_RTLD_DEBUG
+   /* If we have to run the dynamic linker in debugging mode and the
+      LD_DEBUG_OUTPUT environment variable is given, we write the debug
+      messages to this file.  */
+@@ -2567,6 +2577,7 @@
+ 	/* We use standard output if opening the file failed.  */
+ 	GLRO(dl_debug_fd) = STDOUT_FILENO;
+     }
++#endif /* __OPTION_EGLIBC_RTLD_DEBUG */
+ }
+ 
+ 
+diff -Naur glibc-2.20/extra-lib.mk glibc-2.20-patch/extra-lib.mk
+--- glibc-2.20/extra-lib.mk	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/extra-lib.mk	2015-03-04 00:51:32.370952006 -0600
+@@ -25,7 +25,9 @@
+ extra-objs := $(extra-objs)
+ 
+ # The modules that go in $(lib).
+-all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines)
++all-$(lib)-routines := $($(lib)-routines)		\
++	               $($(lib)-routines-y)		\
++		       $($(lib)-sysdep_routines)
+ 
+ # Add each flavor of library to the lists of things to build and install.
+ install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
+@@ -101,7 +103,7 @@
+ endif
+ 
+ # This will define `libof-ROUTINE := LIB' for each of the routines.
+-cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines)
++cpp-srcs-left := $(all-$(lib)-routines)
+ ifneq (,$(cpp-srcs-left))
+ include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
+ endif
+diff -Naur glibc-2.20/grp/Makefile glibc-2.20-patch/grp/Makefile
+--- glibc-2.20/grp/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/grp/Makefile	2015-03-04 00:51:32.370952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for grp portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= grp
+ 
+ include ../Makeconfig
+@@ -29,6 +31,9 @@
+ 	    getgrent_r getgrgid_r getgrnam_r fgetgrent_r
+ 
+ tests := testgrp
++ifneq (y,$(OPTION_EGLIBC_NSSWITCH))
++LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
++endif
+ 
+ ifeq (yes,$(build-shared))
+ test-srcs :=  tst_fgetgrent
+diff -Naur glibc-2.20/hesiod/Makefile glibc-2.20-patch/hesiod/Makefile
+--- glibc-2.20/hesiod/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/hesiod/Makefile	2015-03-04 00:51:32.370952006 -0600
+@@ -18,12 +18,14 @@
+ #
+ #	Sub-makefile for hesiod portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= hesiod
+ 
+ include ../Makeconfig
+ 
+-extra-libs := libnss_hesiod
+-extra-libs-others = $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod
++extra-libs-others-y += $(extra-libs-y)
+ 
+ subdir-dirs = nss_hesiod
+ vpath %.c nss_hesiod
+diff -Naur glibc-2.20/iconv/gconv_db.c glibc-2.20-patch/iconv/gconv_db.c
+--- glibc-2.20/iconv/gconv_db.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/iconv/gconv_db.c	2015-03-04 00:51:32.370952006 -0600
+@@ -25,6 +25,7 @@
+ #include <sys/param.h>
+ #include <bits/libc-lock.h>
+ #include <locale/localeinfo.h>
++#include <gnu/option-groups.h>
+ 
+ #include <dlfcn.h>
+ #include <gconv_int.h>
+@@ -828,9 +829,11 @@
+ /* Free all resources if necessary.  */
+ libc_freeres_fn (free_mem)
+ {
++#if __OPTION_EGLIBC_LOCALE_CODE
+   /* First free locale memory.  This needs to be done before freeing derivations,
+      as ctype cleanup functions dereference steps arrays which we free below.  */
+   _nl_locale_subfreeres ();
++#endif
+ 
+   /* finddomain.c has similar problem.  */
+   extern void _nl_finddomain_subfreeres (void) attribute_hidden;
+diff -Naur glibc-2.20/iconv/gconv_trans.c glibc-2.20-patch/iconv/gconv_trans.c
+--- glibc-2.20/iconv/gconv_trans.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/iconv/gconv_trans.c	2015-03-04 00:51:32.370952006 -0600
+@@ -23,6 +23,7 @@
+ #include <stdint.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <gnu/option-groups.h>
+ 
+ #include <bits/libc-lock.h>
+ #include "gconv_int.h"
+@@ -59,6 +60,7 @@
+     PTR_DEMANGLE (fct);
+ #endif
+ 
++#if __OPTION_EGLIBC_LOCALE_CODE
+   /* If there is no transliteration information in the locale don't do
+      anything and return the error.  */
+   size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE);
+@@ -194,6 +196,7 @@
+              sorted.  */
+ 	  break;
+     }
++#endif
+ 
+   /* One last chance: use the default replacement.  */
+   if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0)
+diff -Naur glibc-2.20/iconv/iconv_prog.c glibc-2.20-patch/iconv/iconv_prog.c
+--- glibc-2.20/iconv/iconv_prog.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/iconv/iconv_prog.c	2015-03-04 00:51:32.371952006 -0600
+@@ -35,6 +35,7 @@
+ #ifdef _POSIX_MAPPED_FILES
+ # include <sys/mman.h>
+ #endif
++#include <gnu/option-groups.h>
+ #include <charmap.h>
+ #include <gconv_int.h>
+ #include "iconv_prog.h"
+@@ -221,10 +222,17 @@
+ 	      bool to_wrong =
+ 		(iconv_open (to_code, "UTF-8") == (iconv_t) -1
+ 		 && errno == EINVAL);
++#if __OPTION_EGLIBC_LOCALE_CODE
+ 	      const char *from_pretty =
+ 		(from_code[0] ? from_code : nl_langinfo (CODESET));
+ 	      const char *to_pretty =
+ 		(orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET));
++#else
++	      const char *from_pretty =
++		(from_code[0] ? from_code : "ANSI_X3.4-1968");
++	      const char *to_pretty =
++                 (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968");
++#endif
+ 
+ 	      if (from_wrong)
+ 		{
+diff -Naur glibc-2.20/iconv/Makefile glibc-2.20-patch/iconv/Makefile
+--- glibc-2.20/iconv/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/iconv/Makefile	2015-03-04 00:51:32.371952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Makefile for iconv.
+ #
++include ../option-groups.mak
++
+ subdir	:= iconv
+ 
+ include ../Makeconfig
+@@ -57,6 +59,9 @@
+ CPPFLAGS-strtab = -DNOT_IN_libc
+ CPPFLAGS-charmap = -DNOT_IN_libc
+ CPPFLAGS-charmap-dir = -DNOT_IN_libc
++ifneq (y,$(OPTION_EGLIBC_SPAWN))
++CPPFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
++endif
+ 
+ ifeq ($(run-built-tests),yes)
+ xtests-special += $(objpfx)test-iconvconfig.out
+diff -Naur glibc-2.20/iconvdata/Makefile glibc-2.20-patch/iconvdata/Makefile
+--- glibc-2.20/iconvdata/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/iconvdata/Makefile	2015-03-04 00:51:32.371952006 -0600
+@@ -18,12 +18,15 @@
+ #
+ #	Makefile for iconv data and code.
+ #
++include ../option-groups.mak
++
+ subdir	:= iconvdata
+ 
+ include ../Makeconfig
+ 
+ # Names of all the shared objects which implement the transformations.
+-modules	:= ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5		 \
++modules-$(OPTION_EGLIBC_CHARSETS)					 \
++	:= ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5		 \
+ 	   ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10		 \
+ 	   ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16	 \
+ 	   T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE	 \
+@@ -63,11 +66,13 @@
+ 	   MAC-CENTRALEUROPE KOI8-RU ISO8859-9E				 \
+ 	   CP770 CP771 CP772 CP773 CP774
+ 
+-modules.so := $(addsuffix .so, $(modules))
++modules.so := $(addsuffix .so, $(modules-y))
+ 
+ ifeq (yes,$(build-shared))
+ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
+-	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9
++	tst-iconv6 bug-iconv5 bug-iconv8 bug-iconv9
++tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7
++
+ ifeq ($(have-thread-library),yes)
+ tests += bug-iconv3
+ endif
+@@ -130,13 +135,13 @@
+ # Rule to generate the shared objects.
+ charmaps = ../localedata/charmaps
+ -include $(objpfx)iconv-rules
+-extra-modules-left := $(modules)
++extra-modules-left := $(modules-y)
+ include extra-module.mk
+ 
+ 
+ extra-objs	+= $(modules.so)
+-install-others	= $(addprefix $(inst_gconvdir)/, $(modules.so))	\
+-		  $(inst_gconvdir)/gconv-modules
++install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so))
++install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules
+ 
+ # We can build the conversion tables for numerous charsets automatically.
+ 
+@@ -204,7 +209,7 @@
+ ifndef avoid-generated
+ $(objpfx)iconv-rules: Makefile
+ 	$(make-target-directory)
+-	{ echo $(filter-out lib%, $(modules)); \
++	{ echo $(filter-out lib%, $(modules-y)); \
+ 	  echo 8bit $(gen-8bit-modules); \
+ 	  echo 8bit-gap $(gen-8bit-gap-modules); } | \
+ 	LC_ALL=C \
+@@ -247,7 +252,7 @@
+ 	$(do-install-program)
+ $(inst_gconvdir)/gconv-modules: gconv-modules $(+force)
+ 	$(do-install)
+-ifeq (no,$(cross-compiling))
++# eglibc: ifeq (no,$(cross-compiling))
+ # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary
+ # if this libc has more gconv modules than the previously installed one.
+ 	if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \
+@@ -256,9 +261,9 @@
+ 	   $(common-objpfx)iconv/iconvconfig \
+ 	     $(addprefix --prefix=,$(install_root)); \
+ 	fi
+-else
+-	@echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
+-endif
++# eglibc: else
++# eglibc:	@echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
++# eglibc: endif
+ 
+ endif # build-shared = yes
+ 
+diff -Naur glibc-2.20/include/libc-symbols.h glibc-2.20-patch/include/libc-symbols.h
+--- glibc-2.20/include/libc-symbols.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/include/libc-symbols.h	2015-03-04 00:51:32.371952006 -0600
+@@ -60,8 +60,7 @@
+ /* Define these macros for the benefit of portable GNU code that wants to check
+    them.  Of course, STDC_HEADERS is never false when building libc!  */
+ #define STDC_HEADERS	1
+-#define HAVE_MBSTATE_T	1
+-#define HAVE_MBSRTOWCS	1
++
+ #define HAVE_LIBINTL_H	1
+ #define HAVE_WCTYPE_H	1
+ #define HAVE_ISWCTYPE	1
+diff -Naur glibc-2.20/include/netdb.h glibc-2.20-patch/include/netdb.h
+--- glibc-2.20/include/netdb.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/include/netdb.h	2015-03-04 00:51:32.372952006 -0600
+@@ -232,6 +232,10 @@
+ 		       (const char *name, int af, struct hostent *host,	      \
+ 			char *buffer, size_t buflen, int *errnop,	      \
+ 			int *h_errnop);					      \
++extern enum nss_status _nss_ ## service ## _gethostbyname3_r		      \
++		       (const char *name, int af, struct hostent *result,     \
++			char *buffer, size_t buflen, int *errnop,	      \
++			int *h_errnop, int32_t *ttlp, char **canonp);         \
+ extern enum nss_status _nss_ ## service ## _gethostbyname_r		      \
+ 		       (const char *name, struct hostent *host, char *buffer, \
+ 			size_t buflen, int *errnop, int *h_errnop);	      \
+diff -Naur glibc-2.20/inet/Makefile glibc-2.20-patch/inet/Makefile
+--- glibc-2.20/inet/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/inet/Makefile	2015-03-04 00:51:32.372952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for inet portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= inet
+ 
+ include ../Makeconfig
+@@ -27,7 +29,8 @@
+ 	   netinet/tcp.h netinet/ip.h $(wildcard arpa/*.h protocols/*.h) \
+ 	   aliases.h ifaddrs.h netinet/ip6.h netinet/icmp6.h bits/in.h
+ 
+-routines := htonl htons		\
++routines-$(OPTION_EGLIBC_INET) \
++	 += htonl htons \
+ 	    inet_lnaof inet_mkadr	\
+ 	    inet_netof inet_ntoa inet_net herrno herrno-loc \
+ 	    gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \
+@@ -41,18 +44,23 @@
+ 	    getrpcent_r getrpcbyname_r getrpcbynumber_r \
+ 	    ether_aton ether_aton_r ether_hton ether_line \
+ 	    ether_ntoa ether_ntoa_r ether_ntoh \
+-	    rcmd rexec ruserpass \
+ 	    getnetgrent_r getnetgrent \
+-	    getaliasent_r getaliasent getaliasname getaliasname_r \
+-	    in6_addr getnameinfo if_index ifaddrs inet6_option \
++	    in6_addr getnameinfo if_index ifaddrs \
+ 	    getipv4sourcefilter setipv4sourcefilter \
+-	    getsourcefilter setsourcefilter inet6_opt inet6_rth
++	    getsourcefilter setsourcefilter
++routines-$(OPTION_EGLIBC_RCMD) \
++	 += rcmd rexec ruserpass
++routines-$(OPTION_EGLIBC_DB_ALIASES) \
++	 += getaliasent_r getaliasent getaliasname getaliasname_r
++routines-$(OPTION_EGLIBC_ADVANCED_INET6) \
++	 += inet6_option inet6_opt inet6_rth
+ 
+-aux := check_pf check_native ifreq
++aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq
+ 
+ tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
+-	 tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
++	 tst-gethnm test-ifaddrs bug-if1 tst-ether_line \
+ 	 tst-getni1 tst-getni2 tst-inet6_rth tst-checks
++tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt
+ 
+ include ../Rules
+ 
+diff -Naur glibc-2.20/intl/dcigettext.c glibc-2.20-patch/intl/dcigettext.c
+--- glibc-2.20/intl/dcigettext.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/intl/dcigettext.c	2015-03-04 00:51:32.372952006 -0600
+@@ -77,6 +77,10 @@
+ #endif
+ #include "hash-string.h"
+ 
++#ifdef _LIBC
++# include <gnu/option-groups.h>
++#endif
++
+ /* Thread safetyness.  */
+ #ifdef _LIBC
+ # include <bits/libc-lock.h>
+@@ -449,9 +453,11 @@
+ #endif
+ 
+ #ifdef _LIBC
++#if __OPTION_EGLIBC_LOCALE_CODE
+   __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+   __libc_rwlock_rdlock (__libc_setlocale_lock);
+ #endif
++#endif
+ 
+   __libc_rwlock_rdlock (_nl_state_lock);
+ 
+@@ -470,7 +476,11 @@
+   search.category = category;
+ # ifdef HAVE_PER_THREAD_LOCALE
+ #  ifdef _LIBC
++#   if __OPTION_EGLIBC_LOCALE_CODE
+   localename = strdupa (__current_locale_name (category));
++#   else
++  localename = "C";
++#   endif
+ #  endif
+   search.localename = localename;
+ # endif
+@@ -494,7 +504,9 @@
+ 	retval = (char *) (*foundp)->translation;
+ 
+ # ifdef _LIBC
++#if __OPTION_EGLIBC_LOCALE_CODE
+       __libc_rwlock_unlock (__libc_setlocale_lock);
++#endif
+ # endif
+       __libc_rwlock_unlock (_nl_state_lock);
+       return retval;
+@@ -611,7 +623,9 @@
+ 	{
+ 	no_translation:
+ 	  FREE_BLOCKS (block_list);
++#if __OPTION_EGLIBC_LOCALE_CODE
+ 	  __libc_rwlock_unlock (__libc_setlocale_lock);
++#endif
+ 	  __libc_rwlock_unlock (_nl_state_lock);
+ 	  __set_errno (saved_errno);
+ 	  return (plural == 0
+@@ -730,7 +744,9 @@
+ 	      if (plural)
+ 		retval = plural_lookup (domain, n, retval, retlen);
+ 
++#if __OPTION_EGLIBC_LOCALE_CODE
+ 	      __libc_rwlock_unlock (__libc_setlocale_lock);
++#endif
+ 	      __libc_rwlock_unlock (_nl_state_lock);
+ 	      return retval;
+ 	    }
+@@ -1361,7 +1377,11 @@
+      `LC_xxx', and `LANG'.  On some systems this can be done by the
+      `setlocale' function itself.  */
+ #ifdef _LIBC
++# if __OPTION_EGLIBC_LOCALE_CODE
+   retval = __current_locale_name (category);
++# else
++  retval = "C";
++# endif
+ #else
+   retval = _nl_locale_name (category, categoryname);
+ #endif
+diff -Naur glibc-2.20/intl/Makefile glibc-2.20-patch/intl/Makefile
+--- glibc-2.20/intl/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/intl/Makefile	2015-03-04 00:51:32.372952006 -0600
+@@ -16,6 +16,7 @@
+ # <http://www.gnu.org/licenses/>.
+ 
+ # Makefile for intl subdirectory: message handling code from GNU gettext.
++include ../option-groups.mak
+ 
+ subdir = intl
+ 
+@@ -48,7 +49,7 @@
+ $(objpfx)plural.o: plural.c
+ 
+ ifeq ($(run-built-tests),yes)
+-ifeq (yes,$(build-shared))
++ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared))
+ ifneq ($(strip $(MSGFMT)),:)
+ tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \
+ 		 $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \
+diff -Naur glibc-2.20/io/Makefile glibc-2.20-patch/io/Makefile
+--- glibc-2.20/io/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/io/Makefile	2015-03-04 00:51:32.372952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for I/O portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= io
+ 
+ include ../Makeconfig
+@@ -36,7 +38,7 @@
+ 	fxstatat fxstatat64						\
+ 	statfs fstatfs statfs64 fstatfs64				\
+ 	statvfs fstatvfs statvfs64 fstatvfs64				\
+-	umask chmod fchmod lchmod fchmodat				\
++	umask chmod fchmod fchmodat					\
+ 	mkdir mkdirat							\
+ 	open open_2 open64 open64_2 openat openat_2 openat64 openat64_2	\
+ 	read write lseek lseek64 access euidaccess faccessat		\
+@@ -49,11 +51,13 @@
+ 	ttyname ttyname_r isatty					\
+ 	link linkat symlink symlinkat readlink readlinkat		\
+ 	unlink unlinkat rmdir						\
+-	ftw ftw64 fts poll ppoll					\
++	poll ppoll							\
+ 	posix_fadvise posix_fadvise64					\
+ 	posix_fallocate posix_fallocate64				\
+ 	sendfile sendfile64 \
+ 	utimensat futimens
++routines-$(OPTION_EGLIBC_BSD) += lchmod
++routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts
+ 
+ aux := have_o_cloexec
+ 
+@@ -64,18 +68,22 @@
+ 		       fstatat fstatat64 mknod mknodat
+ 
+ others		:= pwd
+-test-srcs	:= ftwtest
++test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest
+ tests		:= test-utime test-stat test-stat2 test-lfs tst-getcwd \
+-		   tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \
++		   tst-fcntl tst-statvfs \
+ 		   tst-openat tst-unlinkat tst-fstatat tst-futimesat \
+ 		   tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
+ 		   tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
+-		   tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
++		   tst-mknodat tst-mkfifoat tst-ttyname_r \
+ 		   tst-posix_fallocate
++tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \
++				    bug-ftw5
+ 
+ ifeq ($(run-built-tests),yes)
++ifeq (y,$(OPTION_EGLIBC_FTRAVERSE))
+ tests-special += $(objpfx)ftwtest.out
+ endif
++endif
+ 
+ include ../Rules
+ 
+diff -Naur glibc-2.20/libidn/Makefile glibc-2.20-patch/libidn/Makefile
+--- glibc-2.20/libidn/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libidn/Makefile	2015-03-04 00:51:32.372952006 -0600
+@@ -16,6 +16,7 @@
+ # <http://www.gnu.org/licenses/>.
+ 
+ # Makefile for libidn subdirectory of GNU C Library.
++include ../option-groups.mak
+ 
+ subdir	:= libidn
+ 
+@@ -23,8 +24,8 @@
+ 
+ routines = idn-stub
+ 
+-extra-libs		= libcidn
+-extra-libs-others	= $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_IDN) = libcidn
++extra-libs-others-y = $(extra-libs-y)
+ 
+ libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \
+ 		    iconvme
+diff -Naur glibc-2.20/libidn/toutf8.c glibc-2.20-patch/libidn/toutf8.c
+--- glibc-2.20/libidn/toutf8.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libidn/toutf8.c	2015-03-04 00:51:32.373952006 -0600
+@@ -33,6 +33,11 @@
+ /* Get strlen. */
+ #include <string.h>
+ 
++/* Get __OPTION_EGLIBC_LOCALE_CODE.  */
++#ifdef _LIBC
++# include <gnu/option-groups.h>
++#endif
++
+ /* Get iconv_string. */
+ #include "iconvme.h"
+ 
+@@ -47,7 +52,11 @@
+ #endif
+ 
+ #ifdef _LIBC
+-# define stringprep_locale_charset() nl_langinfo (CODESET)
++# if __OPTION_EGLIBC_LOCALE_CODE
++#  define stringprep_locale_charset() nl_langinfo (CODESET)
++# else
++#  define stringprep_locale_charset() "ANSI_X3.4-1968"
++# endif
+ #else
+ /**
+  * stringprep_locale_charset - return charset used in current locale
+diff -Naur glibc-2.20/libio/fileops.c glibc-2.20-patch/libio/fileops.c
+--- glibc-2.20/libio/fileops.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/fileops.c	2015-03-04 00:51:32.373952006 -0600
+@@ -38,6 +38,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <unistd.h>
++#include <gnu/option-groups.h>
+ #include <stdlib.h>
+ #if _LIBC
+ # include "../wcsmbs/wcsmbsload.h"
+@@ -174,7 +175,7 @@
+ 
+   /* Free buffer. */
+ #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
+-  if (fp->_mode > 0)
++  if (_IO_is_wide (fp))
+     {
+       if (_IO_have_wbackup (fp))
+ 	_IO_free_wbackup_area (fp);
+@@ -359,6 +360,7 @@
+       cs = strstr (last_recognized + 1, ",ccs=");
+       if (cs != NULL)
+ 	{
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+ 	  /* Yep.  Load the appropriate conversions and set the orientation
+ 	     to wide.  */
+ 	  struct gconv_fcts fcts;
+@@ -423,6 +425,12 @@
+ 
+ 	  /* Set the mode now.  */
+ 	  result->_mode = 1;
++#else
++          /* Treat this as if we couldn't find the given character set.  */
++          (void) _IO_file_close_it (fp);
++          __set_errno (EINVAL);
++          return NULL;
++#endif
+ 	}
+     }
+ 
+diff -Naur glibc-2.20/libio/__fpurge.c glibc-2.20-patch/libio/__fpurge.c
+--- glibc-2.20/libio/__fpurge.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/__fpurge.c	2015-03-04 00:51:32.373952006 -0600
+@@ -21,7 +21,7 @@
+ void
+ __fpurge (FILE *fp)
+ {
+-  if (fp->_mode > 0)
++  if (_IO_is_wide (fp))
+     {
+       /* Wide-char stream.  */
+       if (_IO_in_backup (fp))
+diff -Naur glibc-2.20/libio/iofwide.c glibc-2.20-patch/libio/iofwide.c
+--- glibc-2.20/libio/iofwide.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/iofwide.c	2015-03-04 00:51:32.373952006 -0600
+@@ -26,6 +26,7 @@
+ 
+ #include <libioP.h>
+ #ifdef _LIBC
++# include <gnu/option-groups.h>
+ # include <dlfcn.h>
+ # include <wchar.h>
+ #endif
+@@ -43,6 +44,8 @@
+ #endif
+ 
+ 
++#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR
++
+ /* Prototypes of libio's codecvt functions.  */
+ static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
+ 				     __mbstate_t *statep,
+@@ -513,3 +516,26 @@
+   return MB_CUR_MAX;
+ #endif
+ }
++
++#else
++/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled.  */
++
++#undef _IO_fwide
++int
++_IO_fwide (fp, mode)
++     _IO_FILE *fp;
++     int mode;
++{
++  /* Die helpfully if the user tries to create a wide stream; I
++     disbelieve that most users check the return value from
++     'fwide (fp, 1)'.  */
++  assert (mode <= 0);
++
++  /* We can only make streams byte-oriented, which is trivial.  */
++  if (mode < 0)
++    fp->_mode = -1;
++
++  return fp->_mode;
++}
++
++#endif
+diff -Naur glibc-2.20/libio/ioseekoff.c glibc-2.20-patch/libio/ioseekoff.c
+--- glibc-2.20/libio/ioseekoff.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/ioseekoff.c	2015-03-04 00:51:32.373952006 -0600
+@@ -60,7 +60,7 @@
+ 	  else
+ 	    abort ();
+ 	}
+-      if (_IO_fwide (fp, 0) < 0)
++      if (! _IO_is_wide (fp))
+ 	_IO_free_backup_area (fp);
+       else
+ 	_IO_free_wbackup_area (fp);
+diff -Naur glibc-2.20/libio/ioseekpos.c glibc-2.20-patch/libio/ioseekpos.c
+--- glibc-2.20/libio/ioseekpos.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/ioseekpos.c	2015-03-04 00:51:32.374952006 -0600
+@@ -35,7 +35,7 @@
+   /* If we have a backup buffer, get rid of it, since the __seekoff
+      callback may not know to do the right thing about it.
+      This may be over-kill, but it'll do for now. TODO */
+-  if (_IO_fwide (fp, 0) <= 0)
++  if (! _IO_is_wide (fp))
+     {
+       if (_IO_have_backup (fp))
+ 	_IO_free_backup_area (fp);
+diff -Naur glibc-2.20/libio/iosetbuffer.c glibc-2.20-patch/libio/iosetbuffer.c
+--- glibc-2.20/libio/iosetbuffer.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/iosetbuffer.c	2015-03-04 00:51:32.374952006 -0600
+@@ -24,6 +24,8 @@
+    This exception applies to code released by its copyright holders
+    in files containing the exception.  */
+ 
++#include <gnu/option-groups.h>
++
+ #include "libioP.h"
+ 
+ void
+@@ -38,9 +40,11 @@
+   if (!buf)
+     size = 0;
+   (void) _IO_SETBUF (fp, buf, size);
++#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+   if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp))
+     /* We also have to set the buffer using the wide char function.  */
+     (void) _IO_WSETBUF (fp, buf, size);
++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
+   _IO_release_lock (fp);
+ }
+ libc_hidden_def (_IO_setbuffer)
+diff -Naur glibc-2.20/libio/libioP.h glibc-2.20-patch/libio/libioP.h
+--- glibc-2.20/libio/libioP.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/libioP.h	2015-03-04 00:51:32.374952006 -0600
+@@ -42,6 +42,10 @@
+ /*# include <comthread.h>*/
+ #endif
+ 
++#if defined _LIBC
++# include <gnu/option-groups.h>
++#endif
++
+ #include <math_ldbl_opt.h>
+ 
+ #include "iolibio.h"
+@@ -508,8 +512,20 @@
+ 
+ 
+ #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
++
++/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0',
++   except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it
++   expands to a constant, allowing the compiler to realize that it can
++   eliminate code that references wide stream handling functions.
++   This, in turn, allows us to omit them.  */
++#if __OPTION_POSIX_C_LANG_WIDE_CHAR
++# define _IO_is_wide(_f) ((_f)->_mode > 0)
++#else
++# define _IO_is_wide(_f) (0)
++#endif
++
+ # define _IO_do_flush(_f) \
+-  ((_f)->_mode <= 0							      \
++  (! _IO_is_wide (_f)                                                         \
+    ? _IO_do_write(_f, (_f)->_IO_write_base,				      \
+ 		  (_f)->_IO_write_ptr-(_f)->_IO_write_base)		      \
+    : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base,		      \
+diff -Naur glibc-2.20/libio/Makefile glibc-2.20-patch/libio/Makefile
+--- glibc-2.20/libio/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/libio/Makefile	2015-03-04 00:51:32.375952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Specific makefile for libio.
+ #
++include ../option-groups.mak
++
+ subdir	:= libio
+ 
+ include ../Makeconfig
+@@ -27,16 +29,13 @@
+ 
+ routines	:=							      \
+ 	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
+-	iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc	      \
++	iofopncook iofputs iofread iofsetpos ioftell			      \
+ 	iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs	      \
+ 	ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc		      \
+ 	iovsprintf iovsscanf						      \
+ 	iofgetpos64 iofopen64 iofsetpos64				      \
+-	fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
+-	iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u	      \
+-	putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf      \
+-	wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops   \
+-	wstrops wfileops iofwide fwide wmemstream			      \
++	putchar putchar_u						      \
++	iofwide								      \
+ 									      \
+ 	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
+ 	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
+@@ -47,25 +46,48 @@
+ 	__fpurge __fpending __fsetlocking				      \
+ 									      \
+ 	libc_fatal fmemopen
+-
+-tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
+-	tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
+-	tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf	      \
+-	tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof          \
+-	tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \
+-	tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \
+-	tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \
+-	bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \
+-	tst-memstream1 tst-memstream2 \
+-	tst-wmemstream1 tst-wmemstream2 \
+-	bug-memstream1 bug-wmemstream1 \
+-	tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
+-	tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
+-	tst-ftell-append
++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) +=				      \
++	wfiledoalloc							      \
++	iowpadn								      \
++	swprintf							      \
++	vswprintf iovswscanf swscanf wgenops				      \
++	wstrops wfileops wmemstream
++routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) +=	      \
++	wdummyfileops
++routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) +=				      \
++	fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
++	iofputws iofputws_u iogetwline ioungetwc putwc putwc_u		      \
++	putwchar putwchar_u fwprintf vwprintf				      \
++	wprintf wscanf fwscanf vwscanf					      \
++	fwide
++
++tests = test-fmemopen tst-ext tst-ext2				\
++	tst-mmap-setvbuf tst-atime tst-eof			\
++	tst-freopen bug-ungetc bug-fseek			\
++	tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush	\
++	tst-mmap2-eofsync tst-mmap-offend bug-fopena+		\
++	bug-ungetc2 bug-ungetc3 bug-ungetc4			\
++	tst-memstream1 tst-memstream2				\
++	bug-memstream1 tst-popen1 tst-fwrite-error              \
++	tst-ftell-active-handler tst-ftell-append
++tests-$(OPTION_EGLIBC_LOCALE_CODE)				\
++     += tst-swscanf tst-fgetws tst-setvbuf1			\
++	tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2	\
++	tst-widetext
++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)		\
++     += bug-rewind bug-rewind2 bug-ungetwc1		\
++	bug-wfflush bug-wmemstream1 tst-fopenloc2	\
++	tst_getwc					\
++	tst_putwc tst_wprintf tst_wprintf2 tst_wscanf	\
++	tst-fgetwc bug-wsetpos tst-fseek tst-ftell-partial-wide
++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR)			\
++     += tst_swprintf tst_swscanf			\
++	tst-sscanf					\
++	tst-wmemstream1 tst-wmemstream2
+ ifeq (yes,$(build-shared))
+ # Add test-fopenloc only if shared library is enabled since it depends on
+ # shared localedata objects.
+-tests += tst-fopenloc
++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-fopenloc
+ endif
+ test-srcs = test-freopen
+ 
+@@ -164,13 +186,17 @@
+ 		       oldiofsetpos64
+ 
+ ifeq ($(run-built-tests),yes)
++ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
+ tests-special += $(objpfx)test-freopen.out
++endif
++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+ ifeq (yes,$(build-shared))
+ # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
+ # library is enabled since they depend on tst-fopenloc.out.
+ tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
+ endif
+ endif
++endif
+ 
+ include ../Rules
+ 
+diff -Naur glibc-2.20/libio/wdummyfileops.c glibc-2.20-patch/libio/wdummyfileops.c
+--- glibc-2.20/libio/wdummyfileops.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/libio/wdummyfileops.c	2015-03-04 00:51:32.375952006 -0600
+@@ -0,0 +1,161 @@
++/* Copyright (C) 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.
++
++   As a special exception, if you link the code in this file with
++   files compiled with a GNU compiler to produce an executable,
++   that does not cause the resulting executable to be covered by
++   the GNU Lesser General Public License.  This exception does not
++   however invalidate any other reasons why the executable file
++   might be covered by the GNU Lesser General Public License.
++   This exception applies to code released by its copyright holders
++   in files containing the exception.  */
++
++#include <assert.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <libioP.h>
++
++static void __THROW __attribute__ ((__noreturn__))
++_IO_wfile_wide_char_support_disabled (void)
++{
++  static const char errstr[]
++    = ("The application tried to use wide character I/O, but libc.so"
++       " was compiled\n"
++       "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n");
++  __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);
++  abort ();
++}
++
++static void
++_IO_wfile_disabled_void_int (_IO_FILE *fp, int x)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static int
++_IO_wfile_disabled_int_int (_IO_FILE *fp, int x)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static int
++_IO_wfile_disabled_int_none (_IO_FILE *fp)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_size_t
++_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_size_t
++_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_off64_t
++_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_off64_t
++_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_FILE *
++_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_ssize_t
++_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_ssize_t
++_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static _IO_off64_t
++_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static int
++_IO_wfile_disabled_close (_IO_FILE *fp)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static int
++_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static int
++_IO_wfile_disabled_showmanyc (_IO_FILE *fp)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static void
++_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale)
++{
++  _IO_wfile_wide_char_support_disabled ();
++}
++
++static const struct _IO_jump_t _IO_wfile_jumps_disabled =
++{
++  JUMP_INIT_DUMMY,
++  JUMP_INIT(finish, _IO_wfile_disabled_void_int),
++  JUMP_INIT(overflow, _IO_wfile_disabled_int_int),
++  JUMP_INIT(underflow, _IO_wfile_disabled_int_none),
++  JUMP_INIT(uflow, _IO_wfile_disabled_int_none),
++  JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int),
++  JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn),
++  JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn),
++  JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff),
++  JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos),
++  JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf),
++  JUMP_INIT(sync, _IO_wfile_disabled_int_none),
++  JUMP_INIT(doallocate, _IO_wfile_disabled_int_none),
++  JUMP_INIT(read, _IO_wfile_disabled_read),
++  JUMP_INIT(write, _IO_wfile_disabled_write),
++  JUMP_INIT(seek, _IO_wfile_disabled_seek),
++  JUMP_INIT(close, _IO_wfile_disabled_close),
++  JUMP_INIT(stat, _IO_wfile_disabled_stat),
++  JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc),
++  JUMP_INIT(imbue, _IO_wfile_disabled_imbue)
++};
++
++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps)
++libc_hidden_data_def (_IO_wfile_jumps)
++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap)
++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap)
+diff -Naur glibc-2.20/locale/catnames.c glibc-2.20-patch/locale/catnames.c
+--- glibc-2.20/locale/catnames.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/locale/catnames.c	2015-03-04 00:51:32.375952006 -0600
+@@ -0,0 +1,48 @@
++/* Copyright (C) 2006  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 "localeinfo.h"
++
++/* Define an array of category names (also the environment variable names).  */
++const union catnamestr_t _nl_category_names attribute_hidden =
++  {
++    {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++      category_name,
++#include "categories.def"
++#undef DEFINE_CATEGORY
++    }
++  };
++
++const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
++  {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++    [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
++#include "categories.def"
++#undef DEFINE_CATEGORY
++  };
++
++/* An array of their lengths, for convenience.  */
++const uint8_t _nl_category_name_sizes[] attribute_hidden =
++  {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++    [category] = sizeof (category_name) - 1,
++#include "categories.def"
++#undef	DEFINE_CATEGORY
++    [LC_ALL] = sizeof ("LC_ALL") - 1
++  };
+diff -Naur glibc-2.20/locale/C-ctype.c glibc-2.20-patch/locale/C-ctype.c
+--- glibc-2.20/locale/C-ctype.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/C-ctype.c	2015-03-04 00:51:32.375952006 -0600
+@@ -19,8 +19,11 @@
+ #include "localeinfo.h"
+ #include <endian.h>
+ #include <stdint.h>
++#include <gnu/option-groups.h>
+ 
++#if __OPTION_EGLIBC_LOCALE_CODE
+ #include "C-translit.h"
++#endif
+ 
+ /* This table's entries are taken from POSIX.2 Table 2-6
+    ``LC_CTYPE Category Definition in the POSIX Locale''.
+@@ -647,6 +650,7 @@
+     { .word = L'7' },
+     { .word = L'8' },
+     { .word = L'9' },
++#if __OPTION_EGLIBC_LOCALE_CODE
+     /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
+     { .word = NTRANSLIT },
+     /* _NL_CTYPE_TRANSLIT_FROM_IDX */
+@@ -657,6 +661,22 @@
+     { .wstr = translit_to_idx },
+     /* _NL_CTYPE_TRANSLIT_TO_TBL */
+     { .wstr = (uint32_t *) translit_to_tbl },
++#else
++    /* If the locale code isn't enabled, we don't have the
++       transliteration code in iconv/gconv_trans.c anyway, so there's
++       no need for the transliteration tables here.  We'll fall back
++       on the default missing replacement, '?'.  */
++    /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
++    { .word = 0 },
++    /* _NL_CTYPE_TRANSLIT_FROM_IDX */
++    { .wstr = NULL },
++    /* _NL_CTYPE_TRANSLIT_FROM_TBL */
++    { .wstr = NULL },
++    /* _NL_CTYPE_TRANSLIT_TO_IDX */
++    { .wstr = NULL },
++    /* _NL_CTYPE_TRANSLIT_TO_TBL */
++    { .wstr = NULL },
++#endif
+     /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */
+     { .word = 1 },
+     /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */
+diff -Naur glibc-2.20/locale/dummy-setlocale.c glibc-2.20-patch/locale/dummy-setlocale.c
+--- glibc-2.20/locale/dummy-setlocale.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/locale/dummy-setlocale.c	2015-03-04 00:51:32.375952006 -0600
+@@ -0,0 +1,33 @@
++/* Copyright (C) 2006  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 <string.h>
++#include <locale.h>
++
++char *
++setlocale (int category, const char *locale)
++{
++  if (! locale
++      || locale[0] == '\0'
++      || strcmp (locale, "C") == 0
++      || strcmp (locale, "POSIX") == 0)
++    return (char *) "C";
++  else
++    return NULL;
++}
++libc_hidden_def (setlocale)
+diff -Naur glibc-2.20/locale/localeinfo.h glibc-2.20-patch/locale/localeinfo.h
+--- glibc-2.20/locale/localeinfo.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/localeinfo.h	2015-03-04 00:51:32.375952006 -0600
+@@ -224,7 +224,7 @@
+    unused.  We can manage this playing some tricks with weak references.
+    But with thread-local locale settings, it becomes quite ungainly unless
+    we can use __thread variables.  So only in that case do we attempt this.  */
+-#ifndef SHARED
++#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF
+ # include <tls.h>
+ # define NL_CURRENT_INDIRECT	1
+ #endif
+diff -Naur glibc-2.20/locale/Makefile glibc-2.20-patch/locale/Makefile
+--- glibc-2.20/locale/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/Makefile	2015-03-04 00:51:32.375952006 -0600
+@@ -18,27 +18,43 @@
+ #
+ #	Makefile for locales.
+ #
++include ../option-groups.mak
++
+ subdir	:= locale
+ 
+ include ../Makeconfig
+ 
+ headers		= locale.h bits/locale.h langinfo.h xlocale.h
+-routines	= setlocale findlocale loadlocale loadarchive \
+-		  localeconv nl_langinfo nl_langinfo_l mb_cur_max \
+-		  newlocale duplocale freelocale uselocale
+-tests		= tst-C-locale tst-locname tst-duplocale
++# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code.
++# If we put the latter in an option group, too, we can omit catnames
++# when both option groups are disabled.  libstdc++-v3 needs mb_cur_max.
++routines-y      := catnames mb_cur_max
++routines-$(OPTION_EGLIBC_LOCALE_CODE) \
++		+= setlocale findlocale loadlocale loadarchive \
++		   localeconv nl_langinfo nl_langinfo_l \
++		   newlocale duplocale freelocale uselocale
++ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE))
++routines-y	+= dummy-setlocale
++endif
++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale tst-locname tst-duplocale
+ categories	= ctype messages monetary numeric time paper name \
+ 		  address telephone measurement identification collate
+-aux		= $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \
+-		  xlocale localename global-locale coll-lookup
+-others		= localedef locale
++# C-messages belongs in an intl option group.
++aux-y		:= C-ctype C-time \
++		   SYS_libc C_name xlocale global-locale coll-lookup
++aux-$(OPTION_EGLIBC_LOCALE_CODE) \
++		+= $(filter-out $(aux-y), \
++	                        $(categories:%=lc-%) $(categories:%=C-%)) \
++	           localename
++others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale
+ #others-static	= localedef locale
+-install-bin	= localedef locale
+-extra-objs	= $(localedef-modules:=.o) $(localedef-aux:=.o) \
++install-bin	= $(others-y)
++extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \
++		= $(localedef-modules:=.o) $(localedef-aux:=.o) \
+ 		  $(locale-modules:=.o) $(lib-modules:=.o)
+ 
+-extra-libs	= libBrokenLocale
+-extra-libs-others = $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale
++extra-libs-others = $(extra-libs-y)
+ 
+ libBrokenLocale-routines = broken_cur_max
+ 
+@@ -94,6 +110,9 @@
+ CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts
+ CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts
+ CFLAGS-charmap-dir.c = -Wno-write-strings
++ifneq (y,$(OPTION_EGLIBC_SPAWN))
++CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
++endif
+ 
+ # This makes sure -DNOT_IN_libc et al are passed for all these modules.
+ cpp-srcs-left := $(addsuffix .c,$(localedef-modules) $(localedef-aux) \
+diff -Naur glibc-2.20/locale/programs/charmap-dir.c glibc-2.20-patch/locale/programs/charmap-dir.c
+--- glibc-2.20/locale/programs/charmap-dir.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/charmap-dir.c	2015-03-04 00:51:32.376952006 -0600
+@@ -19,7 +19,9 @@
+ #include <error.h>
+ #include <fcntl.h>
+ #include <libintl.h>
++#ifndef NO_UNCOMPRESS
+ #include <spawn.h>
++#endif
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -156,6 +158,7 @@
+   return closedir (dir);
+ }
+ 
++#ifndef NO_UNCOMPRESS
+ /* Creates a subprocess decompressing the given pathname, and returns
+    a stream reading its output (the decompressed data).  */
+ static
+@@ -204,6 +207,7 @@
+     }
+   return NULL;
+ }
++#endif
+ 
+ /* Opens a charmap for reading, given its name (not an alias name).  */
+ FILE *
+@@ -226,6 +230,7 @@
+   if (stream != NULL)
+     return stream;
+ 
++#ifndef NO_UNCOMPRESS
+   memcpy (p, ".gz", 4);
+   stream = fopen_uncompressed (pathname, "gzip");
+   if (stream != NULL)
+@@ -235,6 +240,7 @@
+   stream = fopen_uncompressed (pathname, "bzip2");
+   if (stream != NULL)
+     return stream;
++#endif
+ 
+   return NULL;
+ }
+@@ -263,8 +269,8 @@
+       char *alias = NULL;
+       char junk[BUFSIZ];
+ 
+-      if (fscanf (stream, " <code_set_name> %ms", &alias) == 1
+-          || fscanf (stream, "%% alias %ms", &alias) == 1)
++      if (fscanf (stream, " <code_set_name> %as", &alias) == 1
++          || fscanf (stream, "%% alias %as", &alias) == 1)
+         {
+           aliases = (char **) xrealloc (aliases,
+                                         (naliases + 2) * sizeof (char *));
+diff -Naur glibc-2.20/locale/programs/ld-collate.c glibc-2.20-patch/locale/programs/ld-collate.c
+--- glibc-2.20/locale/programs/ld-collate.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/ld-collate.c	2015-03-04 00:51:32.376952006 -0600
+@@ -350,7 +350,7 @@
+     }
+   if (wcs != NULL)
+     {
+-      size_t nwcs = wcslen ((wchar_t *) wcs);
++      size_t nwcs = wcslen_uint32 (wcs);
+       uint32_t zero = 0;
+       /* Handle <U0000> as a single character.  */
+       if (nwcs == 0)
+@@ -1776,8 +1776,7 @@
+ 
+ 	      if ((*eptr)->nwcs == runp->nwcs)
+ 		{
+-		  int c = wmemcmp ((wchar_t *) (*eptr)->wcs,
+-				   (wchar_t *) runp->wcs, runp->nwcs);
++		  int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs);
+ 
+ 		  if (c == 0)
+ 		    {
+@@ -2010,9 +2009,9 @@
+ 	     one consecutive entry.  */
+ 	  if (runp->wcnext != NULL
+ 	      && runp->nwcs == runp->wcnext->nwcs
+-	      && wmemcmp ((wchar_t *) runp->wcs,
+-			  (wchar_t *)runp->wcnext->wcs,
+-			  runp->nwcs - 1) == 0
++	      && wmemcmp_uint32 (runp->wcs,
++				 runp->wcnext->wcs,
++				 runp->nwcs - 1) == 0
+ 	      && (runp->wcs[runp->nwcs - 1]
+ 		  == runp->wcnext->wcs[runp->nwcs - 1] + 1))
+ 	    {
+@@ -2036,9 +2035,9 @@
+ 		runp = runp->wcnext;
+ 	      while (runp->wcnext != NULL
+ 		     && runp->nwcs == runp->wcnext->nwcs
+-		     && wmemcmp ((wchar_t *) runp->wcs,
+-				 (wchar_t *)runp->wcnext->wcs,
+-				 runp->nwcs - 1) == 0
++		     && wmemcmp_uint32 (runp->wcs,
++					runp->wcnext->wcs,
++					runp->nwcs - 1) == 0
+ 		     && (runp->wcs[runp->nwcs - 1]
+ 			 == runp->wcnext->wcs[runp->nwcs - 1] + 1));
+ 
+diff -Naur glibc-2.20/locale/programs/ld-ctype.c glibc-2.20-patch/locale/programs/ld-ctype.c
+--- glibc-2.20/locale/programs/ld-ctype.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/ld-ctype.c	2015-03-04 00:51:32.377952006 -0600
+@@ -957,7 +957,7 @@
+   allocate_arrays (ctype, charmap, ctype->repertoire);
+ 
+   default_missing_len = (ctype->default_missing
+-			 ? wcslen ((wchar_t *) ctype->default_missing)
++			 ? wcslen_uint32 (ctype->default_missing)
+ 			 : 0);
+ 
+   init_locale_data (&file, nelems);
+@@ -1968,7 +1968,7 @@
+ 	    ignore = 1;
+ 	  else
+ 	    /* This value is usable.  */
+-	    obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4);
++	    obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4);
+ 
+ 	  first = 0;
+ 	}
+@@ -2516,8 +2516,8 @@
+ 	    }
+ 
+ 	handle_tok_digit:
+-	  class_bit = _ISwdigit;
+-	  class256_bit = _ISdigit;
++	  class_bit = BITw (tok_digit);
++	  class256_bit = BIT (tok_digit);
+ 	  handle_digits = 1;
+ 	  goto read_charclass;
+ 
+@@ -4001,8 +4001,7 @@
+ 
+ 	  while (idx < number)
+ 	    {
+-	      int res = wcscmp ((const wchar_t *) sorted[idx]->from,
+-				(const wchar_t *) runp->from);
++	      int res = wcscmp_uint32 (sorted[idx]->from, runp->from);
+ 	      if (res == 0)
+ 		{
+ 		  replace = 1;
+@@ -4039,11 +4038,11 @@
+       for (cnt = 0; cnt < number; ++cnt)
+ 	{
+ 	  struct translit_to_t *srunp;
+-	  from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
++	  from_len += wcslen_uint32 (sorted[cnt]->from) + 1;
+ 	  srunp = sorted[cnt]->to;
+ 	  while (srunp != NULL)
+ 	    {
+-	      to_len += wcslen ((const wchar_t *) srunp->str) + 1;
++	      to_len += wcslen_uint32 (srunp->str) + 1;
+ 	      srunp = srunp->next;
+ 	    }
+ 	  /* Plus one for the extra NUL character marking the end of
+@@ -4067,18 +4066,18 @@
+ 	  ctype->translit_from_idx[cnt] = from_len;
+ 	  ctype->translit_to_idx[cnt] = to_len;
+ 
+-	  len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
+-	  wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len],
+-		   (const wchar_t *) sorted[cnt]->from, len);
++	  len = wcslen_uint32 (sorted[cnt]->from) + 1;
++	  wmemcpy_uint32 (&ctype->translit_from_tbl[from_len],
++			  sorted[cnt]->from, len);
+ 	  from_len += len;
+ 
+ 	  ctype->translit_to_idx[cnt] = to_len;
+ 	  srunp = sorted[cnt]->to;
+ 	  while (srunp != NULL)
+ 	    {
+-	      len = wcslen ((const wchar_t *) srunp->str) + 1;
+-	      wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len],
+-		       (const wchar_t *) srunp->str, len);
++	      len = wcslen_uint32 (srunp->str) + 1;
++	      wmemcpy_uint32 (&ctype->translit_to_tbl[to_len],
++			      srunp->str, len);
+ 	      to_len += len;
+ 	      srunp = srunp->next;
+ 	    }
+diff -Naur glibc-2.20/locale/programs/ld-messages.c glibc-2.20-patch/locale/programs/ld-messages.c
+--- glibc-2.20/locale/programs/ld-messages.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/ld-messages.c	2015-03-04 00:51:32.377952006 -0600
+@@ -25,6 +25,7 @@
+ #include <string.h>
+ #include <stdint.h>
+ #include <sys/uio.h>
++#include <gnu/option-groups.h>
+ 
+ #include <assert.h>
+ 
+@@ -124,6 +125,7 @@
+     }
+   else
+     {
++#if __OPTION_POSIX_REGEXP
+       int result;
+       regex_t re;
+ 
+@@ -140,6 +142,7 @@
+ 	}
+       else if (result != 0)
+ 	regfree (&re);
++#endif
+     }
+ 
+   if (messages->noexpr == NULL)
+@@ -158,6 +161,7 @@
+     }
+   else
+     {
++#if __OPTION_POSIX_REGEXP
+       int result;
+       regex_t re;
+ 
+@@ -174,6 +178,7 @@
+ 	}
+       else if (result != 0)
+ 	regfree (&re);
++#endif
+     }
+ }
+ 
+diff -Naur glibc-2.20/locale/programs/ld-time.c glibc-2.20-patch/locale/programs/ld-time.c
+--- glibc-2.20/locale/programs/ld-time.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/ld-time.c	2015-03-04 00:51:32.378952006 -0600
+@@ -215,8 +215,10 @@
+ 	}
+       else
+ 	{
++	  static const uint32_t wt_fmt_ampm[]
++	    = { '%','I',':','%','M',':','%','S',' ','%','p',0 };
+ 	  time->t_fmt_ampm = "%I:%M:%S %p";
+-	  time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p";
++	  time->wt_fmt_ampm = wt_fmt_ampm;
+ 	}
+     }
+ 
+@@ -226,7 +228,7 @@
+       const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,
+ 				       31, 31, 30, 31 ,30, 31 };
+       size_t idx;
+-      wchar_t *wstr;
++      uint32_t *wstr;
+ 
+       time->era_entries =
+ 	(struct era_data *) xmalloc (time->num_era
+@@ -464,18 +466,18 @@
+ 	    }
+ 
+ 	  /* Now generate the wide character name and format.  */
+-	  wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end offset */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end start */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end end */
++	  wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */
+ 	  if (wstr != NULL)
+ 	    {
+-	      time->era_entries[idx].wname = (uint32_t *) wstr + 1;
+-	      wstr = wcschr (wstr + 1, L':');	/* end name */
++	      time->era_entries[idx].wname = wstr + 1;
++	      wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */
+ 	      if (wstr != NULL)
+ 		{
+ 		  *wstr = L'\0';
+-		  time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
++		  time->era_entries[idx].wformat = wstr + 1;
+ 		}
+ 	      else
+ 		time->era_entries[idx].wname =
+@@ -530,7 +532,16 @@
+   if (time->date_fmt == NULL)
+     time->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
+   if (time->wdate_fmt == NULL)
+-    time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y";
++    {
++      static const uint32_t wdate_fmt[] =
++	{ '%','a',' ',
++	  '%','b',' ',
++	  '%','e',' ',
++	  '%','H',':','%','M',':','%','S',' ',
++	  '%','Z',' ',
++	  '%','Y',0 };
++      time->wdate_fmt = wdate_fmt;
++    }
+ }
+ 
+ 
+diff -Naur glibc-2.20/locale/programs/linereader.c glibc-2.20-patch/locale/programs/linereader.c
+--- glibc-2.20/locale/programs/linereader.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/linereader.c	2015-03-04 00:51:32.378952006 -0600
+@@ -595,7 +595,7 @@
+ {
+   int return_widestr = lr->return_widestr;
+   char *buf;
+-  wchar_t *buf2 = NULL;
++  uint32_t *buf2 = NULL;
+   size_t bufact;
+   size_t bufmax = 56;
+ 
+diff -Naur glibc-2.20/locale/programs/localedef.c glibc-2.20-patch/locale/programs/localedef.c
+--- glibc-2.20/locale/programs/localedef.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/localedef.c	2015-03-04 00:51:32.378952006 -0600
+@@ -114,6 +114,7 @@
+ #define OPT_LIST_ARCHIVE 309
+ #define OPT_LITTLE_ENDIAN 400
+ #define OPT_BIG_ENDIAN 401
++#define OPT_UINT32_ALIGN 402
+ 
+ /* Definitions of arguments for argp functions.  */
+ static const struct argp_option options[] =
+@@ -150,6 +151,8 @@
+     N_("Generate little-endian output") },
+   { "big-endian", OPT_BIG_ENDIAN, NULL, 0,
+     N_("Generate big-endian output") },
++  { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0,
++    N_("Set the target's uint32_t alignment in bytes (default 4)") },
+   { NULL, 0, NULL, 0, NULL }
+ };
+ 
+@@ -239,12 +242,14 @@
+      ctype locale.  (P1003.2 4.35.5.2)  */
+   setlocale (LC_CTYPE, "POSIX");
+ 
++#ifndef NO_SYSCONF
+   /* Look whether the system really allows locale definitions.  POSIX
+      defines error code 3 for this situation so I think it must be
+      a fatal error (see P1003.2 4.35.8).  */
+   if (sysconf (_SC_2_LOCALEDEF) < 0)
+     WITH_CUR_LOCALE (error (3, 0, _("\
+ FATAL: system does not define `_POSIX2_LOCALEDEF'")));
++#endif
+ 
+   /* Process charmap file.  */
+   charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);
+@@ -338,6 +343,9 @@
+     case OPT_BIG_ENDIAN:
+       set_big_endian (true);
+       break;
++    case OPT_UINT32_ALIGN:
++      uint32_align_mask = strtol (arg, NULL, 0) - 1;
++      break;
+     case 'c':
+       force_output = 1;
+       break;
+diff -Naur glibc-2.20/locale/programs/locfile.c glibc-2.20-patch/locale/programs/locfile.c
+--- glibc-2.20/locale/programs/locfile.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/locfile.c	2015-03-04 00:51:32.378952006 -0600
+@@ -544,6 +544,9 @@
+    machine running localedef.  */
+ bool swap_endianness_p;
+ 
++/* The target's value of __align__(uint32_t) - 1.  */
++unsigned int uint32_align_mask = 3;
++
+ /* When called outside a start_locale_structure/end_locale_structure
+    or start_locale_prelude/end_locale_prelude block, record that the
+    next byte in FILE's obstack will be the first byte of a new element.
+@@ -621,7 +624,7 @@
+ void
+ add_locale_wstring (struct locale_file *file, const uint32_t *string)
+ {
+-  add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1);
++  add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1);
+ }
+ 
+ /* Record that FILE's next element is the 32-bit integer VALUE.  */
+diff -Naur glibc-2.20/locale/programs/locfile.h glibc-2.20-patch/locale/programs/locfile.h
+--- glibc-2.20/locale/programs/locfile.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/programs/locfile.h	2015-03-04 00:51:32.379952006 -0600
+@@ -71,6 +71,8 @@
+ 
+ extern bool swap_endianness_p;
+ 
++extern unsigned int uint32_align_mask;
++
+ /* Change the output to be big-endian if BIG_ENDIAN is true and
+    little-endian otherwise.  */
+ static inline void
+@@ -275,4 +277,49 @@
+ 				   const struct charmap_t *charmap,
+ 				   const char *output_path);
+ 
++static inline size_t
++wcslen_uint32 (const uint32_t *str)
++{
++  size_t len = 0;
++  while (str[len] != 0)
++    len++;
++  return len;
++}
++
++static inline int
++wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n)
++{
++  while (n-- != 0)
++    {
++      int diff = *s1++ - *s2++;
++      if (diff != 0)
++	return diff;
++    }
++  return 0;
++}
++
++static inline int
++wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2)
++{
++  while (*s1 != 0 && *s1 == *s2)
++    s1++, s2++;
++  return *s1 - *s2;
++}
++
++static inline uint32_t *
++wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n)
++{
++  return memcpy (s1, s2, n * sizeof (uint32_t));
++}
++
++static inline uint32_t *
++wcschr_uint32 (const uint32_t *s, uint32_t ch)
++{
++  do
++    if (*s == ch)
++      return (uint32_t *) s;
++  while (*s++ != 0);
++  return 0;
++}
++
+ #endif /* locfile.h */
+diff -Naur glibc-2.20/locale/setlocale.c glibc-2.20-patch/locale/setlocale.c
+--- glibc-2.20/locale/setlocale.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/setlocale.c	2015-03-04 00:51:32.379952006 -0600
+@@ -64,36 +64,6 @@
+ #endif
+ 
+ 
+-/* Define an array of category names (also the environment variable names).  */
+-const union catnamestr_t _nl_category_names attribute_hidden =
+-  {
+-    {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-      category_name,
+-#include "categories.def"
+-#undef DEFINE_CATEGORY
+-    }
+-  };
+-
+-const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
+-  {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-    [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
+-#include "categories.def"
+-#undef DEFINE_CATEGORY
+-  };
+-
+-/* An array of their lengths, for convenience.  */
+-const uint8_t _nl_category_name_sizes[] attribute_hidden =
+-  {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-    [category] = sizeof (category_name) - 1,
+-#include "categories.def"
+-#undef	DEFINE_CATEGORY
+-    [LC_ALL] = sizeof ("LC_ALL") - 1
+-  };
+-
+-
+ #ifdef NL_CURRENT_INDIRECT
+ # define WEAK_POSTLOAD(postload) weak_extern (postload)
+ #else
+diff -Naur glibc-2.20/locale/xlocale.c glibc-2.20-patch/locale/xlocale.c
+--- glibc-2.20/locale/xlocale.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/locale/xlocale.c	2015-03-04 00:51:32.379952006 -0600
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #include <locale.h>
++#include <gnu/option-groups.h>
+ #include "localeinfo.h"
+ 
+ #define DEFINE_CATEGORY(category, category_name, items, a) \
+@@ -25,6 +26,19 @@
+ #include "categories.def"
+ #undef	DEFINE_CATEGORY
+ 
++/* If the locale support code isn't enabled, don't generate strong
++   reference to the C locale_data structures here; let the Makefile
++   decide which ones to include.  (In the static linking case, the
++   strong reference to the 'class', 'toupper', and 'tolower' tables
++   will cause C-ctype.o to be brought in, as it should be, even when
++   the reference to _nl_C_LC_CTYPE will be weak.)  */
++#if ! __OPTION_EGLIBC_LOCALE_CODE
++# define DEFINE_CATEGORY(category, category_name, items, a) \
++  weak_extern (_nl_C_##category)
++# include "categories.def"
++# undef	DEFINE_CATEGORY
++#endif
++
+ /* Defined in locale/C-ctype.c.  */
+ extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
+ extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
+@@ -52,3 +66,26 @@
+     .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128,
+     .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128
+   };
++
++
++#if ! __OPTION_EGLIBC_LOCALE_CODE
++/* When locale code is enabled, these are each defined in the
++   appropriate lc-CATEGORY.c file, so that static links (when __thread
++   is supported) bring in only those lc-CATEGORY.o files for
++   categories the program actually uses; look for NL_CURRENT_INDIRECT
++   in localeinfo.h.
++
++   When locale code is disabled, the _nl_C_CATEGORY objects are the
++   only possible referents.  At the moment, there isn't a way to get
++   __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that
++   #includes localeinfo.h, so we can't just turn off
++   NL_CURRENT_INDIRECT.  So we'll define the _nl_current_CATEGORY
++   pointers here.  */
++#if defined (NL_CURRENT_INDIRECT)
++#define DEFINE_CATEGORY(category, category_name, items, a)      \
++  __thread struct __locale_data * const *_nl_current_##category   \
++  attribute_hidden = &_nl_C_locobj.__locales[category];
++#include "categories.def"
++#undef DEFINE_CATEGORY
++#endif
++#endif /* __OPTION_EGLIBC_LOCALE_CODE */
+diff -Naur glibc-2.20/localedata/Makefile glibc-2.20-patch/localedata/Makefile
+--- glibc-2.20/localedata/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/localedata/Makefile	2015-03-04 00:51:32.379952006 -0600
+@@ -21,12 +21,22 @@
+ 
+ include ../Makeconfig
+ 
+-# List with all available character set descriptions.
+-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*)
++include ../option-groups.mak
+ 
+ # List with all available character set descriptions.
+-locales := $(wildcard locales/*)
++all-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*)
++
++all-locales := $(wildcard locales/*)
+ 
++# If the EGLIBC_LOCALES option group is not enabled, trim the
++# list of charmap and locale source files.
++ifeq ($(OPTION_EGLIBC_LOCALES),y)
++charmaps := $(all-charmaps)
++locales  := $(all-locales)
++else
++charmaps :=
++locales  := locales/POSIX
++endif
+ 
+ subdir-dirs = tests-mbwc
+ vpath %.c tests-mbwc
+@@ -71,14 +81,20 @@
+ 		     tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans      \
+ 		     tst_wctype tst_wcwidth
+ 
+-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
++# Since these tests build their own locale files, they're not
++# dependent on the OPTION_EGLIBC_LOCALES option group.  But they do
++# need the locale functions to be present.
++tests-$(OPTION_EGLIBC_LOCALE_CODE) \
++     += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
+ 	tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
+ 	tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
+ 	tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
+ 	tst-wctype
++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+ tests-static = bug-setlocale1-static
+ tests += $(tests-static)
+-ifeq (yes,$(build-shared))
++endif
++ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE))
+ ifneq (no,$(PERL))
+ tests-special += $(objpfx)mtrace-tst-leaks.out
+ endif
+@@ -92,12 +108,14 @@
+ 
+ tests: $(objdir)/iconvdata/gconv-modules
+ 
++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+ tests-special += $(objpfx)sort-test.out $(objpfx)tst-fmon.out \
+ 		 $(objpfx)tst-locale.out $(objpfx)tst-rpmatch.out \
+ 		 $(objpfx)tst-trans.out $(objpfx)tst-ctype.out \
+ 		 $(objpfx)tst-langinfo.out $(objpfx)tst-langinfo-static.out \
+ 		 $(objpfx)tst-numeric.out
+ tests-static += tst-langinfo-static
++endif
+ 
+ ifeq ($(run-built-tests),yes)
+ # We have to generate locales
+@@ -213,6 +231,11 @@
+ 
+ include SUPPORTED
+ 
++# Only install locale data if OPTION_EGLIBC_LOCALES is selected.
++ifneq ($(OPTION_EGLIBC_LOCALES),y)
++SUPPORTED-LOCALES :=
++endif
++
+ INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES))
+ 
+ # Sometimes the whole collection of locale files should be installed.
+diff -Naur glibc-2.20/login/Makefile glibc-2.20-patch/login/Makefile
+--- glibc-2.20/login/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/login/Makefile	2015-03-04 00:51:32.379952006 -0600
+@@ -18,6 +18,7 @@
+ #
+ #	Sub-makefile for login portion of the library.
+ #
++include ../option-groups.mak
+ 
+ subdir	:= login
+ 
+@@ -25,14 +26,16 @@
+ 
+ headers	:= utmp.h bits/utmp.h lastlog.h pty.h
+ 
+-routines := getlogin getlogin_r setlogin getlogin_r_chk \
+-	    getutent getutent_r getutid getutline getutid_r getutline_r \
+-	    utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \
+-	    ptsname_r_chk
++routines := getpt grantpt unlockpt ptsname ptsname_r_chk
++routines-$(OPTION_EGLIBC_UTMP) \
++	 += getutent getutent_r getutid getutline getutid_r getutline_r \
++	    utmp_file utmpname updwtmp
++routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r getlogin_r_chk
++routines-$(OPTION_EGLIBC_BSD) += setlogin
+ 
+ CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"'
+ 
+-others = utmpdump
++others-$(OPTION_EGLIBC_UTMP) += utmpdump
+ 
+ ifeq (yes,$(build-pt-chown))
+ others += pt_chown
+@@ -46,8 +49,8 @@
+ tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname
+ 
+ # Build the -lutil library with these extra functions.
+-extra-libs      := libutil
+-extra-libs-others := $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_UTMP) := libutil
++extra-libs-others := $(extra-libs-y)
+ 
+ libutil-routines:= login login_tty logout logwtmp openpty forkpty
+ 
+diff -Naur glibc-2.20/Makeconfig glibc-2.20-patch/Makeconfig
+--- glibc-2.20/Makeconfig	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/Makeconfig	2015-03-04 00:51:32.380952006 -0600
+@@ -582,7 +582,7 @@
+ # and run on the build system, causes that program with those
+ # arguments to be run on the host for which the library is built.
+ ifndef test-wrapper
+-test-wrapper =
++test-wrapper = $(cross-test-wrapper)
+ endif
+ # Likewise, but the name of the program is preceded by
+ # <variable>=<value> assignments for environment variables.
+@@ -1057,6 +1057,24 @@
+ libm = $(common-objpfx)math/libm.a
+ endif
+ 
++# Generate a header file that #defines preprocessor symbols indicating
++# which option groups are enabled.  Note that the option-groups.config file
++# may not exist at all.
++before-compile += $(common-objpfx)gnu/option-groups.h
++common-generated += gnu/option-groups.h gnu/option-groups.stmp
++headers += gnu/option-groups.h
++$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @:
++$(common-objpfx)gnu/option-groups.stmp:					\
++		$(..)scripts/option-groups.awk				\
++		$(..)option-groups.defaults				\
++		$(wildcard $(common-objpfx)option-groups.config)
++	$(make-target-directory)
++	@rm -f ${@:stmp=T} $@
++	LC_ALL=C $(AWK) -f $^ > ${@:stmp=T}
++	$(move-if-change) ${@:stmp=T} ${@:stmp=h}
++	touch $@
++
++
+ # These are the subdirectories containing the library source.  The order
+ # is more or less arbitrary.  The sorting step will take care of the
+ # dependencies.
+diff -Naur glibc-2.20/Makerules glibc-2.20-patch/Makerules
+--- glibc-2.20/Makerules	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/Makerules	2015-03-04 00:51:32.380952006 -0600
+@@ -379,6 +379,25 @@
+ endef
+ endif
+ 
++# Include targets in the selected option groups.
++aux                  += $(aux-y)
++extra-libs           += $(extra-libs-y)
++extra-libs-others    += $(extra-libs-others-y)
++extra-objs           += $(extra-objs-y)
++install-bin          += $(install-bin-y)
++install-others       += $(install-others-y)
++install-sbin         += $(install-sbin-y)
++modules              += $(modules-y)
++others               += $(others-y)
++others-pie           += $(others-pie-y)
++routines             += $(routines-y)
++static-only-routines += $(static-only-routines-y)
++sysdep_routines      += $(sysdep_routines-y)
++test-srcs            += $(test-srcs-y)
++tests                += $(tests-y)
++xtests               += $(xtests-y)
++
++
+ # Modify the list of routines we build for different targets
+ 
+ ifeq (yes,$(build-shared))
+diff -Naur glibc-2.20/malloc/Makefile glibc-2.20-patch/malloc/Makefile
+--- glibc-2.20/malloc/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/malloc/Makefile	2015-03-04 00:51:32.380952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Makefile for malloc routines
+ #
++include ../option-groups.mak
++
+ subdir	:= malloc
+ 
+ include ../Makeconfig
+@@ -36,9 +38,15 @@
+ non-lib.a := libmcheck.a
+ 
+ # Additional library.
++ifeq ($(OPTION_EGLIBC_MEMUSAGE),y)
+ extra-libs = libmemusage
+ extra-libs-others = $(extra-libs)
+ 
++ifdef OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
++CPPFLAGS-memusage += -D__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE=$(OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE)
++endif
++endif
++
+ libmemusage-routines = memusage
+ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
+ 
+@@ -67,7 +75,7 @@
+ # Unless we get a test for the availability of libgd which also works
+ # for cross-compiling we disable the memusagestat generation in this
+ # situation.
+-ifneq ($(cross-compiling),yes)
++ifeq ($(cross-compiling)$(OPTION_EGLIBC_MEMUSAGE),noy)
+ # If the gd library is available we build the `memusagestat' program.
+ ifneq ($(LIBGD),no)
+ others: $(objpfx)memusage
+diff -Naur glibc-2.20/malloc/memusage.c glibc-2.20-patch/malloc/memusage.c
+--- glibc-2.20/malloc/memusage.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/malloc/memusage.c	2015-03-04 00:51:32.380952006 -0600
+@@ -33,6 +33,7 @@
+ #include <stdint.h>
+ #include <sys/mman.h>
+ #include <sys/time.h>
++#include <gnu/option-groups.h>
+ 
+ #include <memusage.h>
+ 
+@@ -93,7 +94,11 @@
+ #define peak_stack      peak_use[1]
+ #define peak_total      peak_use[2]
+ 
+-#define DEFAULT_BUFFER_SIZE     32768
++#ifndef __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
++# define DEFAULT_BUFFER_SIZE	32768
++#else
++# define DEFAULT_BUFFER_SIZE	__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
++#endif
+ static size_t buffer_size;
+ 
+ static int fd = -1;
+diff -Naur glibc-2.20/malloc/memusage.sh glibc-2.20-patch/malloc/memusage.sh
+--- glibc-2.20/malloc/memusage.sh	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/malloc/memusage.sh	2015-03-04 00:51:32.381952006 -0600
+@@ -35,7 +35,7 @@
+ 
+ # Print help message
+ do_help() {
+-  echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
++  printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
+ Profile memory usage of PROGRAM.
+ 
+    -n,--progname=NAME     Name of the program file to profile
+diff -Naur glibc-2.20/math/Makefile glibc-2.20-patch/math/Makefile
+--- glibc-2.20/math/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/math/Makefile	2015-03-04 00:51:32.381952006 -0600
+@@ -21,6 +21,8 @@
+ 
+ include ../Makeconfig
+ 
++include ../option-groups.mak
++
+ # Installed header files.
+ headers		:= math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \
+ 		   bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \
+@@ -33,8 +35,8 @@
+ 
+ # Build the -lm library.
+ 
+-extra-libs	:= libm
+-extra-libs-others = $(extra-libs)
++extra-libs-$(OPTION_EGLIBC_LIBM) := libm
++extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM))
+ 
+ libm-support = k_standard s_lib_version s_matherr s_signgam		\
+ 	       fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg		\
+diff -Naur glibc-2.20/misc/err.c glibc-2.20-patch/misc/err.c
+--- glibc-2.20/misc/err.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/misc/err.c	2015-03-04 00:51:32.381952006 -0600
+@@ -22,6 +22,7 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <gnu/option-groups.h>
+ 
+ #include <wchar.h>
+ #define flockfile(s) _IO_flockfile (s)
+@@ -37,6 +38,7 @@
+   va_end (ap);								      \
+ }
+ 
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+ static void
+ convert_and_print (const char *format, __gnuc_va_list ap)
+ {
+@@ -81,6 +83,7 @@
+ 
+   __vfwprintf (stderr, wformat, ap);
+ }
++#endif
+ 
+ void
+ vwarnx (const char *format, __gnuc_va_list ap)
+@@ -88,9 +91,13 @@
+   flockfile (stderr);
+   if (_IO_fwide (stderr, 0) > 0)
+     {
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+       __fwprintf (stderr, L"%s: ", __progname);
+       convert_and_print (format, ap);
+       putwc_unlocked (L'\n', stderr);
++#else
++      abort ();
++#endif
+     }
+   else
+     {
+@@ -111,6 +118,7 @@
+   flockfile (stderr);
+   if (_IO_fwide (stderr, 0) > 0)
+     {
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+       __fwprintf (stderr, L"%s: ", __progname);
+       if (format)
+ 	{
+@@ -119,6 +127,9 @@
+ 	}
+       __set_errno (error);
+       __fwprintf (stderr, L"%m\n");
++#else
++      abort ();
++#endif
+     }
+   else
+     {
+diff -Naur glibc-2.20/misc/error.c glibc-2.20-patch/misc/error.c
+--- glibc-2.20/misc/error.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/misc/error.c	2015-03-04 00:51:32.381952006 -0600
+@@ -35,6 +35,7 @@
+ #endif
+ 
+ #ifdef _LIBC
++# include <gnu/option-groups.h>
+ # include <libintl.h>
+ # include <stdbool.h>
+ # include <stdint.h>
+@@ -205,6 +206,7 @@
+ #if _LIBC
+   if (_IO_fwide (stderr, 0) > 0)
+     {
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+       size_t len = strlen (message) + 1;
+       wchar_t *wmessage = NULL;
+       mbstate_t st;
+@@ -265,6 +267,9 @@
+ 
+       if (use_malloc)
+ 	free (wmessage);
++#else
++      abort ();
++#endif
+     }
+   else
+ #endif
+diff -Naur glibc-2.20/misc/Makefile glibc-2.20-patch/misc/Makefile
+--- glibc-2.20/misc/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/misc/Makefile	2015-03-04 00:51:32.381952006 -0600
+@@ -19,6 +19,10 @@
+ #	Sub-makefile for misc portion of the library.
+ #
+ 
++# Some system-dependent implementations of these functions use option
++# groups (see sysdeps/unix/sysv/linux/Makefile, for example).
++include ../option-groups.mak
++
+ subdir	:= misc
+ 
+ include ../Makeconfig
+@@ -46,40 +50,47 @@
+ 	    select pselect \
+ 	    acct chroot fsync sync fdatasync syncfs reboot \
+ 	    gethostid sethostid \
+-	    revoke vhangup \
++	    vhangup \
+ 	    swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \
+ 	    mkostemp mkostemp64 mkstemps mkstemps64 mkostemps mkostemps64 \
+ 	    ualarm usleep \
+ 	    gtty stty \
+ 	    ptrace \
+-	    fstab mntent mntent_r \
++	    mntent mntent_r \
+ 	    utimes lutimes futimes futimesat \
+ 	    truncate ftruncate truncate64 ftruncate64 \
+-	    chflags fchflags \
+ 	    insremque getttyent getusershell getpass ttyslot \
+ 	    syslog syscall daemon \
+ 	    mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\
+ 	    mlock munlock mlockall munlockall \
+-	    efgcvt efgcvt_r qefgcvt qefgcvt_r \
+ 	    hsearch hsearch_r tsearch lsearch \
+ 	    err error ustat \
+-	    getsysstats dirname regexp \
++	    getsysstats dirname \
+ 	    getloadavg getclktck \
+ 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
+ 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
+ 	    removexattr setxattr getauxval ifunc-impl-list
+ 
++routines-$(OPTION_POSIX_REGEXP) += regexp
++routines-$(OPTION_EGLIBC_FSTAB) += fstab
++routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke
++routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r
++
+ generated += tst-error1.mtrace tst-error1-mem.out
+ 
+ aux := init-misc
+ install-lib := libg.a
+ gpl2lgpl := error.c error.h
+ 
+-tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
+-	 tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
++tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
++	 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1
++tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt
+ ifeq ($(run-built-tests),yes)
++ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
+ tests-special += $(objpfx)tst-error1-mem.out
+ endif
++endif
+ 
+ CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables
+ CFLAGS-tsearch.c = $(uses-callbacks)
+diff -Naur glibc-2.20/misc/sys/xattr.h glibc-2.20-patch/misc/sys/xattr.h
+--- glibc-2.20/misc/sys/xattr.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/misc/sys/xattr.h	2015-03-04 00:51:32.382952006 -0600
+@@ -26,7 +26,6 @@
+ 
+ /* The following constants should be used for the fifth parameter of
+    `*setxattr'.  */
+-#ifndef __USE_KERNEL_XATTR_DEFS
+ enum
+ {
+   XATTR_CREATE = 1,	/* set value, fail if attr already exists.  */
+@@ -34,7 +33,6 @@
+   XATTR_REPLACE = 2	/* set value, fail if attr does not exist.  */
+ #define XATTR_REPLACE	XATTR_REPLACE
+ };
+-#endif
+ 
+ /* Set the attribute NAME of the file pointed to by PATH to VALUE (which
+    is SIZE bytes long).  Return 0 on success, -1 for errors.  */
+diff -Naur glibc-2.20/misc/tst-efgcvt.c glibc-2.20-patch/misc/tst-efgcvt.c
+--- glibc-2.20/misc/tst-efgcvt.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/misc/tst-efgcvt.c	2015-03-04 00:51:32.382952006 -0600
+@@ -59,7 +59,7 @@
+   { 123.01, -4, 3, "" },
+   { 126.71, -4, 3, "" },
+   { 0.0, 4, 1, "0000" },
+-#if DBL_MANT_DIG == 53
++#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE)
+   { 0x1p-1074, 3, -323, "494" },
+   { -0x1p-1074, 3, -323, "494" },
+ #endif
+diff -Naur glibc-2.20/nis/Makefile glibc-2.20-patch/nis/Makefile
+--- glibc-2.20/nis/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nis/Makefile	2015-03-04 00:51:32.382952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Makefile for NIS/NIS+ part.
+ #
++include ../option-groups.mak
++
+ subdir	:= nis
+ 
+ include ../Makeconfig
+@@ -30,19 +32,26 @@
+ 
+ # These are the databases available for the nis (and perhaps later nisplus)
+ # service.  This must be a superset of the services in nss.
+-databases		= proto service hosts network grp pwd rpc ethers \
+-			  spwd netgrp alias publickey
++databases-y		:= proto service hosts network grp pwd rpc ethers \
++			   spwd netgrp publickey
++databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
+ 
+ # Specify rules for the nss_* modules.
+-services		:= nis nisplus compat
++# The 'compat' module includes nis support, and the 'nss' directory
++# includes a bare-bones "files" library, so we'll include 'compat' in
++# OPTION_EGLIBC_NIS.
++services-y		:=
++services-$(OPTION_EGLIBC_NIS) += nis nisplus compat
++
++extra-libs-$(OPTION_EGLIBC_NIS) += libnsl
++extra-libs-y		+= $(services-y:%=libnss_%)
+ 
+-extra-libs		= libnsl $(services:%=libnss_%)
+ # These libraries will be built in the `others' pass rather than
+ # the `lib' pass, because they depend on libc.so being built already.
+-extra-libs-others	= $(extra-libs)
++extra-libs-others-y	+= $(extra-libs-y)
+ 
+ # The sources are found in the appropriate subdir.
+-subdir-dirs = $(services:%=nss_%)
++subdir-dirs = $(services-y:%=nss_%)
+ vpath %.c $(subdir-dirs)
+ 
+ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
+@@ -60,11 +69,11 @@
+ libnss_compat-routines	:= $(addprefix compat-,grp pwd spwd initgroups)
+ libnss_compat-inhibit-o	= $(filter-out .os,$(object-suffixes))
+ 
+-libnss_nis-routines	:= $(addprefix nis-,$(databases)) nis-initgroups \
++libnss_nis-routines	:= $(addprefix nis-,$(databases-y)) nis-initgroups \
+ 			   nss-nis
+ libnss_nis-inhibit-o	= $(filter-out .os,$(object-suffixes))
+ 
+-libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases)) nisplus-parser \
++libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases-y)) nisplus-parser \
+ 			   nss-nisplus nisplus-initgroups
+ libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
+ 
+@@ -80,12 +89,12 @@
+ # Target-specific variable setting to link objects using deprecated
+ # RPC interfaces with the version of libc.so that makes them available
+ # for new links:
+-$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
++$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
+   libc-for-link = $(libnsl-libc)
+ 
+ 
+ ifeq ($(build-shared),yes)
+-$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
++$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
+ else
+-$(others:%=$(objpfx)%): $(objpfx)libnsl.a
++$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a
+ endif
+diff -Naur glibc-2.20/nptl/Makefile glibc-2.20-patch/nptl/Makefile
+--- glibc-2.20/nptl/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nptl/Makefile	2015-03-04 00:51:32.382952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for NPTL portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= nptl
+ 
+ include ../Makeconfig
+@@ -116,7 +118,7 @@
+ 		      pt-raise pt-system \
+ 		      flockfile ftrylockfile funlockfile \
+ 		      sigaction \
+-		      herrno res pt-allocrtsig \
++		      pt-allocrtsig \
+ 		      pthread_kill_other_threads \
+ 		      pthread_getaffinity pthread_setaffinity \
+ 		      pthread_attr_getaffinity pthread_attr_setaffinity \
+@@ -136,6 +138,8 @@
+ #		      pthread_setgid pthread_setegid pthread_setregid \
+ #		      pthread_setresgid
+ 
++libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res
++
+ libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind
+ libpthread-static-only-routines = pthread_atfork
+ 
+@@ -210,7 +214,7 @@
+ 	tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
+ 	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
+ 	tst-mutexpi9 \
+-	tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
++	tst-spin1 tst-spin2 tst-spin3 \
+ 	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
+ 	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
+ 	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
+@@ -244,14 +248,14 @@
+ 	tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
+ 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
+ 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
+-	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
++	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \
+ 	tst-cancel-self tst-cancel-self-cancelstate \
+ 	tst-cancel-self-canceltype tst-cancel-self-testcancel \
+ 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
+ 	tst-flock1 tst-flock2 \
+ 	tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
+ 	tst-signal6 tst-signal7 \
+-	tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
++	tst-exec2 tst-exec3 tst-exec4 \
+ 	tst-exit1 tst-exit2 tst-exit3 \
+ 	tst-stdio1 tst-stdio2 \
+ 	tst-stack1 tst-stack2 tst-stack3 tst-pthread-getattr \
+@@ -259,13 +263,12 @@
+ 	tst-unload \
+ 	tst-dlsym1 \
+ 	tst-sysconf \
+-	tst-locale1 tst-locale2 \
++	tst-locale2 \
+ 	tst-umask1 \
+ 	tst-popen1 \
+ 	tst-clock1 \
+ 	tst-context1 \
+ 	tst-sched1 \
+-	tst-backtrace1 \
+ 	tst-abstime \
+ 	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
+ 	tst-getpid1 tst-getpid2 tst-getpid3 \
+@@ -275,6 +278,17 @@
+ 	tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
+ test-srcs = tst-oddstacklimit
+ 
++# This test uses the posix_spawn functions.
++tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1
++
++# This test uses the 'backtrace' functions.
++tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1
++
++# This test is written in C++.
++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24
++
++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1
++
+ # Files which must not be linked with libpthread.
+ tests-nolibpthread = tst-unload
+ 
+@@ -363,12 +377,18 @@
+ 		    $(common-objpfx)libc.a
+ 
+ tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \
+-		tst-cancel21-static tst-cancel24-static tst-cond8-static \
++		tst-cancel21-static tst-cond8-static \
+ 		tst-mutex8-static tst-mutexpi8-static tst-sem11-static \
+ 		tst-sem12-static
+-tests += tst-stackguard1-static tst-cancel21-static tst-cancel24-static \
++
++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS))
++tests-static += tst-cancel24-static
++endif
++
++tests += tst-stackguard1-static tst-cancel21-static \
+ 	 tst-cond8-static tst-mutex8-static tst-mutexpi8-static \
+ 	 tst-sem11-static tst-sem12-static
++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24-static
+ xtests-static += tst-setuid1-static
+ 
+ # These tests are linked with libc before libpthread
+diff -Naur glibc-2.20/nptl/pthread_create.c glibc-2.20-patch/nptl/pthread_create.c
+--- glibc-2.20/nptl/pthread_create.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nptl/pthread_create.c	2015-03-04 00:51:32.382952006 -0600
+@@ -31,6 +31,7 @@
+ #include <kernel-features.h>
+ #include <exit-thread.h>
+ 
++#include <gnu/option-groups.h>
+ #include <shlib-compat.h>
+ 
+ #include <stap-probe.h>
+@@ -240,8 +241,10 @@
+   THREAD_SETMEM (pd, cpuclock_offset, now);
+ #endif
+ 
++#if __OPTION_EGLIBC_INET
+   /* Initialize resolver state pointer.  */
+   __resp = &pd->res;
++#endif
+ 
+   /* Initialize pointers to locale data.  */
+   __ctype_init ();
+@@ -322,8 +325,10 @@
+   /* Run the destructor for the thread-local data.  */
+   __nptl_deallocate_tsd ();
+ 
++#if __OPTION_EGLIBC_INET
+   /* Clean up any state libc stored in thread-local variables.  */
+   __libc_thread_freeres ();
++#endif
+ 
+   /* If this is the last thread we terminate the process now.  We
+      do not notify the debugger, it might just irritate it if there
+diff -Naur glibc-2.20/nscd/Makefile glibc-2.20-patch/nscd/Makefile
+--- glibc-2.20/nscd/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nscd/Makefile	2015-03-04 00:51:32.383952006 -0600
+@@ -18,14 +18,17 @@
+ #
+ #	Sub-makefile for nscd portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= nscd
+ 
+ include ../Makeconfig
+ 
+ ifneq ($(use-nscd),no)
+-routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
++routines-$(OPTION_EGLIBC_INET) += \
++	     nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
+ 	    nscd_initgroups nscd_getserv_r nscd_netgroup
+-aux	:= nscd_helper
++aux-$(OPTION_EGLIBC_INET) += nscd_helper
+ endif
+ 
+ # To find xmalloc.c
+@@ -37,14 +40,18 @@
+ 		dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
+ 		xmalloc xstrdup aicache initgrcache gai res_hconf \
+ 		netgroupcache
+-
++ifneq (y,$(OPTION_EGLIBC_NIS))
++# If we haven't build libnsl.so, then we'll need to include our
++# own copy of nis_hash.
++nscd-modules += nis_hash
++endif
+ ifeq ($(build-nscd)$(have-thread-library),yesyes)
+ 
+-others += nscd
+-others-pie += nscd
+-install-sbin := nscd
++others-$(OPTION_EGLIBC_INET) += nscd
++others-pie-$(OPTION_EGLIBC_INET) += nscd
++install-sbin-$(OPTION_EGLIBC_INET) += nscd
+ 
+-extra-objs = $(nscd-modules:=.o)
++extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o)
+ 
+ endif
+ 
+@@ -101,7 +108,15 @@
+ $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o)
+ 
+ ifeq ($(build-shared),yes)
+-$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so
++$(objpfx)nscd: $(shared-thread-library)
++else
++$(objpfx)nscd: $(static-thread-library)
++endif
++
++ifeq (y,$(OPTION_EGLIBC_NIS))
++ifeq ($(build-shared),yes)
++$(objpfx)nscd: $(common-objpfx)nis/libnsl.so
+ else
+-$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a
++$(objpfx)nscd: $(common-objpfx)nis/libnsl.a
++endif
+ endif
+diff -Naur glibc-2.20/nscd/nis_hash.c glibc-2.20-patch/nscd/nis_hash.c
+--- glibc-2.20/nscd/nis_hash.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/nscd/nis_hash.c	2015-03-04 00:51:32.383952006 -0600
+@@ -0,0 +1,3 @@
++/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so;
++   we need our own copy.  */
++#include "../nis/nis_hash.c"
+diff -Naur glibc-2.20/nss/fixed-nsswitch.conf glibc-2.20-patch/nss/fixed-nsswitch.conf
+--- glibc-2.20/nss/fixed-nsswitch.conf	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/nss/fixed-nsswitch.conf	2015-03-04 00:51:32.383952006 -0600
+@@ -0,0 +1,22 @@
++# /etc/nsswitch.conf
++#
++# Example configuration for fixed name service.
++# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def
++# for details.
++#
++
++aliases:        files
++
++passwd:         files
++group:          files
++shadow:         files
++
++hosts:          files dns
++networks:       files dns
++
++protocols:      files
++services:       files
++ethers:         files
++rpc:            files
++
++netgroup:       files
+diff -Naur glibc-2.20/nss/fixed-nsswitch.functions glibc-2.20-patch/nss/fixed-nsswitch.functions
+--- glibc-2.20/nss/fixed-nsswitch.functions	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/nss/fixed-nsswitch.functions	2015-03-04 00:51:32.383952006 -0600
+@@ -0,0 +1,121 @@
++/* List of functions defined for fixed NSS in GNU C Library.
++   Copyright (C) 1996, 1997, 1998, 2005 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.  */
++
++/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def),
++   EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for
++   database query functions in the individual name service libraries.
++   Instead, it uses a set of functions chosen at compile time, as
++   directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file.  This
++   file is a sample of what you might use there.
++
++   This file is C source code; it should only contain invocations of
++   the following macros:
++
++   - DEFINE_ENT (DATABASE, SERVICE, X)
++
++     Declare the 'setXent', 'getXent_r', and 'endXent' functions that
++     query DATABASE using the service library 'libnss_SERVICE.so.2'.
++     DATABASE should be the full name of the database as it appears in
++     'nsswitch.conf', like 'passwd' or 'aliases'.
++
++     (The non-reentrant 'getXent' functions are implemented in terms
++     of the reentrant 'getXent_r' functions, so there is no need to
++     refer to them explicitly here.)
++
++   - DEFINE_GETBY (DATABASE, SERVICE, X, KEY)
++
++     Declare the 'getXbyKEY_r' functions that query DATABASE using
++     SERVICE.  DATABASE and SERVICE are as described above.
++
++     (The non-reentrant 'getXbyKEY' functions are implemented in terms
++     of the reentrant 'getXbyKEY_r' functions, so there is no need to
++     refer to them explicitly here.)
++
++     Use the special key 'name3' for the service library function that
++     implements the 'getaddrinfo' function.
++
++   - DEFINE_GET (DATABASE, SERVICE, QUERY)
++
++     Declare the 'getQUERY_r' functions that query DATABASE using
++     SERVICE.  This is used for functions like 'getpwnam'.
++
++     (The non-reentrant 'getQUERY' functions are implemented in terms
++     of the reentrant 'getQUERY_r' functions, so there is no need to
++     refer to them explicitly here.)
++
++   This sample file only includes functions that consult the files in
++   '/etc', and the Domain Name System (DNS).  */
++
++/* aliases */
++DEFINE_ENT (aliases, files, alias)
++DEFINE_GETBY (aliases, files, alias, name)
++
++/* ethers */
++DEFINE_ENT (ethers, files, ether)
++
++/* group */
++DEFINE_ENT (group, files, gr)
++DEFINE_GET (group, files, grgid)
++DEFINE_GET (group, files, grnam)
++
++/* hosts */
++DEFINE_ENT (hosts, files, host)
++DEFINE_GETBY (hosts, files, host, addr)
++DEFINE_GETBY (hosts, files, host, name)
++DEFINE_GETBY (hosts, files, host, name2)
++DEFINE_GET (hosts, files, hostton)
++DEFINE_GET (hosts, files, ntohost)
++DEFINE_GETBY (hosts, dns, host, addr)
++DEFINE_GETBY (hosts, dns, host, name)
++DEFINE_GETBY (hosts, dns, host, name2)
++DEFINE_GETBY (hosts, dns, host, name3)
++
++/* netgroup */
++DEFINE_ENT (netgroup, files, netgr)
++
++/* networks */
++DEFINE_ENT (networks, files, net)
++DEFINE_GETBY (networks, files, net, name)
++DEFINE_GETBY (networks, files, net, addr)
++DEFINE_GETBY (networks, dns, net, name)
++DEFINE_GETBY (networks, dns, net, addr)
++
++/* protocols */
++DEFINE_ENT (protocols, files, proto)
++DEFINE_GETBY (protocols, files, proto, name)
++DEFINE_GETBY (protocols, files, proto, number)
++
++/* passwd */
++DEFINE_ENT (passwd, files, pw)
++DEFINE_GET (passwd, files, pwnam)
++DEFINE_GET (passwd, files, pwuid)
++
++/* rpc */
++DEFINE_ENT (rpc, files, rpc)
++DEFINE_GETBY (rpc, files, rpc, name)
++DEFINE_GETBY (rpc, files, rpc, number)
++
++/* services */
++DEFINE_ENT (services, files, serv)
++DEFINE_GETBY (services, files, serv, name)
++DEFINE_GETBY (services, files, serv, port)
++
++/* shadow */
++DEFINE_ENT (shadow, files, sp)
++DEFINE_GET (shadow, files, spnam)
+diff -Naur glibc-2.20/nss/gen-fixed-nsswitch.c glibc-2.20-patch/nss/gen-fixed-nsswitch.c
+--- glibc-2.20/nss/gen-fixed-nsswitch.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/nss/gen-fixed-nsswitch.c	2015-03-04 00:51:32.383952006 -0600
+@@ -0,0 +1,803 @@
++/* gen-fixed-nsswitch.c --- generate fixed name service data structures
++   Copyright (C) 1996-1999, 2001-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.  */
++
++#define _GNU_SOURCE
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#include <string.h>
++#include <stdarg.h>
++#include <assert.h>
++#include <ctype.h>
++
++#include "gnu/lib-names.h"
++#include "nss.h"
++
++/* Provide a fallback definition to allow this file to be compiled outside
++   libc.  */
++#ifndef internal_function
++# define internal_function
++#endif
++
++
++/* Simple utilities.  */
++
++void __attribute__ ((noreturn))
++error (const char *message)
++{
++  fprintf (stderr, "%s\n", message);
++  exit (1);
++}
++
++
++void *
++check_alloc (void *p)
++{
++  if (p)
++    return p;
++  else
++    error ("out of memory");
++}
++
++void *
++xmalloc (size_t size)
++{
++  return check_alloc (malloc (size));
++}
++
++
++/* Format ARGS according to FORMAT, and return the result as a
++   malloc'ed string.  */
++char *
++saprintf (const char *format, ...)
++{
++  va_list args;
++  size_t len;
++  char *buf;
++
++  va_start (args, format);
++  len = vsnprintf (NULL, 0, format, args);
++  va_end (args);
++
++  buf = xmalloc (len + 1);
++  va_start (args, format);
++  assert (len == vsnprintf (buf, len + 1, format, args));
++  va_end (args);
++
++  return buf;
++}
++
++
++
++/* Data structures representing the configuration file in memory.  */
++
++/* These are copied from nsswitch.h.
++
++   We could simply #include that file, but this program runs on the
++   build machine and links against the build machine's libraries,
++   whereas that header is meant for use by target code; it uses
++   'libc_hidden_proto', 'internal_function', and related hair.  Since
++   we've copied the parsing code, we might as well copy the data
++   structure definitions as well.  */
++
++/* Actions performed after lookup finished.  */
++typedef enum
++{
++  NSS_ACTION_CONTINUE,
++  NSS_ACTION_RETURN
++} lookup_actions;
++
++
++typedef struct service_library
++{
++  /* Name of service (`files', `dns', `nis', ...).  */
++  const char *name;
++  /* Pointer to the loaded shared library.  */
++  void *lib_handle;
++  /* And the link to the next entry.  */
++  struct service_library *next;
++} service_library;
++
++
++/* For mapping a function name to a function pointer.  It is known in
++   nsswitch.c:nss_lookup_function that a string pointer for the lookup key
++   is the first member.  */
++typedef struct
++{
++  const char *fct_name;
++  void *fct_ptr;
++} known_function;
++
++
++typedef struct service_user
++{
++  /* And the link to the next entry.  */
++  struct service_user *next;
++  /* Action according to result.  */
++  lookup_actions actions[5];
++  /* Link to the underlying library object.  */
++  service_library *library;
++  /* Collection of known functions.
++
++     With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
++     'tsearch'-style tree.
++
++     With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
++     pointers to known_function structures, NULL-terminated.  */
++  union
++  {
++    void *tree;
++    const known_function **array;
++  } known;
++  /* Name of the service (`files', `dns', `nis', ...).  */
++  const char *name;
++} service_user;
++
++/* To access the action based on the status value use this macro.  */
++#define nss_next_action(ni, status) ((ni)->actions[2 + status])
++
++
++typedef struct name_database_entry
++{
++  /* And the link to the next entry.  */
++  struct name_database_entry *next;
++  /* List of service to be used.  */
++  service_user *service;
++  /* Name of the database.  */
++  const char *name;
++} name_database_entry;
++
++
++typedef struct name_database
++{
++  /* List of all known databases.  */
++  name_database_entry *entry;
++  /* List of libraries with service implementation.  */
++  service_library *library;
++} name_database;
++
++
++
++/* Gathering the contents of the FIXED_FUNCTIONS file.  */
++
++/* It should be possible to generate this list automatically by
++   looking at the services and databases used in the nsswitch.conf
++   file, and having a hard-coded set of queries supported on each
++   database.  */
++
++/* We #include the FIXED_FUNCTIONS file several times to build an
++   array of function structures holding its data.  */
++enum function_kind {
++  fk_end = 0,                   /* Last entry.  */
++  fk_setent,                    /* Like setpwent.  */
++  fk_getent,                    /* Like getpwent.  */
++  fk_endent,                    /* Like endpwent.  */
++  fk_getby,                     /* Like gethostbyname.  */
++  fk_get                        /* Like getpwnam.  */
++};
++
++
++struct function {
++  /* What kind of function this is.  */
++  enum function_kind kind;
++
++  /* The database and service of the function being hardwired in.  */
++  char *database, *service;
++
++  /* The kind of entry being queried, for 'fk_setent', 'fk_getent',
++     'fk_endent', and 'fk_getby' functions.  */
++  char *entry;
++
++  /* The key, for 'fk_getby' entries.  */
++  char *key;
++
++  /* The value and key, for 'fk_get' entries.  */
++  char *value_and_key;
++};
++
++
++const struct function functions[] =
++  {
++
++#define DEFINE_ENT(database, service, entry)    \
++    { fk_setent, #database, #service, #entry }, \
++    { fk_getent, #database, #service, #entry }, \
++    { fk_endent, #database, #service, #entry },
++#define DEFINE_GETBY(database, service, entry, key)   \
++    { fk_getby, #database, #service, #entry, #key },
++#define DEFINE_GET(database, service, value_and_key)     \
++    { fk_get, #database, #service, NULL, NULL, #value_and_key },
++
++#include FIXED_FUNCTIONS
++
++#undef DEFINE_ENT
++#undef DEFINE_GETBY
++#undef DEFINE_GET
++
++    { fk_end }
++  };
++
++
++/* Parsing the config file.  Functions copied from nsswitch.c.  */
++
++#define __strchrnul strchrnul
++#define __getline getline
++#define __strncasecmp strncasecmp
++
++/* Prototypes for the local functions.  */
++static name_database *nss_parse_file (const char *fname) internal_function;
++static name_database_entry *nss_getline (char *line) internal_function;
++static service_user *nss_parse_service_list (const char *line)
++     internal_function;
++
++static name_database *
++internal_function
++nss_parse_file (const char *fname)
++{
++  FILE *fp;
++  name_database *result;
++  name_database_entry *last;
++  char *line;
++  size_t len;
++
++  /* Open the configuration file.  */
++  fp = fopen (fname, "rc");
++  if (fp == NULL)
++    return NULL;
++
++  // /* No threads use this stream.  */
++  // __fsetlocking (fp, FSETLOCKING_BYCALLER);
++
++  result = (name_database *) xmalloc (sizeof (name_database));
++
++  result->entry = NULL;
++  result->library = NULL;
++  last = NULL;
++  line = NULL;
++  len = 0;
++  do
++    {
++      name_database_entry *this;
++      ssize_t n;
++
++      n = __getline (&line, &len, fp);
++      if (n < 0)
++	break;
++      if (line[n - 1] == '\n')
++	line[n - 1] = '\0';
++
++      /* Because the file format does not know any form of quoting we
++	 can search forward for the next '#' character and if found
++	 make it terminating the line.  */
++      *__strchrnul (line, '#') = '\0';
++
++      /* If the line is blank it is ignored.  */
++      if (line[0] == '\0')
++	continue;
++
++      /* Each line completely specifies the actions for a database.  */
++      this = nss_getline (line);
++      if (this != NULL)
++	{
++	  if (last != NULL)
++	    last->next = this;
++	  else
++	    result->entry = this;
++
++	  last = this;
++	}
++    }
++  while (!feof_unlocked (fp));
++
++  /* Free the buffer.  */
++  free (line);
++  /* Close configuration file.  */
++  fclose (fp);
++
++  return result;
++}
++
++
++/* Read the source names:
++	`( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
++   */
++static service_user *
++internal_function
++nss_parse_service_list (const char *line)
++{
++  service_user *result = NULL, **nextp = &result;
++
++  while (1)
++    {
++      service_user *new_service;
++      const char *name;
++
++      while (isspace (line[0]))
++	++line;
++      if (line[0] == '\0')
++	/* No source specified.  */
++	return result;
++
++      /* Read <source> identifier.  */
++      name = line;
++      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
++	++line;
++      if (name == line)
++	return result;
++
++
++      new_service = (service_user *) xmalloc (sizeof (*new_service));
++      new_service->name = (char *) xmalloc (line - name + 1);
++
++      *((char *) __mempcpy ((char *) new_service->name, name, line - name))
++        = '\0';
++
++      /* Set default actions.  */
++      new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
++      new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE;
++      new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE;
++      new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
++      new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
++      new_service->library = NULL;
++      new_service->known.tree = NULL;
++      new_service->next = NULL;
++
++      while (isspace (line[0]))
++	++line;
++
++      if (line[0] == '[')
++	{
++	  /* Read criterions.  */
++	  do
++	    ++line;
++	  while (line[0] != '\0' && isspace (line[0]));
++
++	  do
++	    {
++	      int not;
++	      enum nss_status status;
++	      lookup_actions action;
++
++	      /* Grok ! before name to mean all statii but that one.  */
++	      not = line[0] == '!';
++	      if (not)
++		++line;
++
++	      /* Read status name.  */
++	      name = line;
++	      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
++		     && line[0] != ']')
++		++line;
++
++	      /* Compare with known statii.  */
++	      if (line - name == 7)
++		{
++		  if (__strncasecmp (name, "SUCCESS", 7) == 0)
++		    status = NSS_STATUS_SUCCESS;
++		  else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
++		    status = NSS_STATUS_UNAVAIL;
++		  else
++		    return result;
++		}
++	      else if (line - name == 8)
++		{
++		  if (__strncasecmp (name, "NOTFOUND", 8) == 0)
++		    status = NSS_STATUS_NOTFOUND;
++		  else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
++		    status = NSS_STATUS_TRYAGAIN;
++		  else
++		    return result;
++		}
++	      else
++		return result;
++
++	      while (isspace (line[0]))
++		++line;
++	      if (line[0] != '=')
++		return result;
++	      do
++		++line;
++	      while (isspace (line[0]));
++
++	      name = line;
++	      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
++		     && line[0] != ']')
++		++line;
++
++	      if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
++		action = NSS_ACTION_RETURN;
++	      else if (line - name == 8
++		       && __strncasecmp (name, "CONTINUE", 8) == 0)
++		action = NSS_ACTION_CONTINUE;
++	      else
++		return result;
++
++	      if (not)
++		{
++		  /* Save the current action setting for this status,
++		     set them all to the given action, and reset this one.  */
++		  const lookup_actions save = new_service->actions[2 + status];
++		  new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action;
++		  new_service->actions[2 + NSS_STATUS_UNAVAIL] = action;
++		  new_service->actions[2 + NSS_STATUS_NOTFOUND] = action;
++		  new_service->actions[2 + NSS_STATUS_SUCCESS] = action;
++		  new_service->actions[2 + status] = save;
++		}
++	      else
++		new_service->actions[2 + status] = action;
++
++	      /* Skip white spaces.  */
++	      while (isspace (line[0]))
++		++line;
++	    }
++	  while (line[0] != ']');
++
++	  /* Skip the ']'.  */
++	  ++line;
++	}
++
++      *nextp = new_service;
++      nextp = &new_service->next;
++    }
++}
++
++static name_database_entry *
++internal_function
++nss_getline (char *line)
++{
++  const char *name;
++  name_database_entry *result;
++  size_t len;
++
++  /* Ignore leading white spaces.  ATTENTION: this is different from
++     what is implemented in Solaris.  The Solaris man page says a line
++     beginning with a white space character is ignored.  We regard
++     this as just another misfeature in Solaris.  */
++  while (isspace (line[0]))
++    ++line;
++
++  /* Recognize `<database> ":"'.  */
++  name = line;
++  while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':')
++    ++line;
++  if (line[0] == '\0' || name == line)
++    /* Syntax error.  */
++    return NULL;
++  *line++ = '\0';
++
++  len = strlen (name) + 1;
++
++  result = (name_database_entry *) xmalloc (sizeof (*result));
++  result->name = (char *) xmalloc (len);
++
++  /* Save the database name.  */
++  memcpy ((char *) result->name, name, len);
++
++  /* Parse the list of services.  */
++  result->service = nss_parse_service_list (line);
++
++  result->next = NULL;
++  return result;
++}
++
++
++
++/* Generating code for statically initialized nsswitch structures.  */
++
++
++/* Return the service-neutral suffix of the name of the service
++   library function referred to by the function F.  The result is
++   allocated with malloc.  */
++char *
++known_function_suffix (const struct function *f)
++{
++  switch (f->kind)
++    {
++    case fk_setent:
++      return saprintf ("set%sent", f->entry);
++
++    case fk_getent:
++      return saprintf ("get%sent_r", f->entry);
++
++    case fk_endent:
++      return saprintf ("end%sent", f->entry);
++
++    case fk_getby:
++      return saprintf ("get%sby%s_r", f->entry, f->key);
++
++    case fk_get:
++      return saprintf ("get%s_r", f->value_and_key);
++
++    default:
++      abort ();
++    }
++}
++
++
++/* Return the name of the service library function referred to by the
++   function F.  The result is allocated with malloc.  */
++char *
++known_function_name (const struct function *f)
++{
++  return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f));
++}
++
++
++/* Write initialized known_function structures to OUT for
++   all the functions we'll use.  */
++void
++generate_known_functions (FILE *out)
++{
++  int i;
++
++  /* First, generate weak references to the functions.  The service
++     libraries depend on libc, and if these references weren't weak,
++     we'd be making libc depend circularly on the service
++     libraries.  */
++  for (i = 0; functions[i].kind; i++)
++    {
++      char *name = known_function_name (&functions[i]);
++      fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n",
++               name, name);
++    }
++  fputs ("\n", out);
++
++  /* Then, a table mapping names to functions.  */
++  fputs ("static const known_function fixed_known_functions[] = {\n",
++         out);
++  for (i = 0; functions[i].kind; i++)
++    {
++      const struct function *f = &functions[i];
++      char *suffix = known_function_suffix (f);
++
++      fprintf (out, "  /* %2d */ { \"%s\", _nss_%s_%s },\n",
++               i, suffix, f->service, suffix);
++    }
++  fputs ("};\n", out);
++  fputs ("\n", out);
++}
++
++
++/* Print code to OUT for an initialized array of pointers to the
++   'known_function' structures needed for USER, which is for
++   DATABASE.  Return its name, allocated with malloc.  */
++char *
++generate_known_function_list (FILE *out,
++                              const name_database_entry *database,
++                              const service_user *user)
++{
++  char *list_name = saprintf ("fixed_%s_%s_known_funcs",
++                              database->name, user->name);
++  fprintf (out, "static const known_function *%s[] = {\n",
++           list_name);
++  int i;
++  for (i = 0; functions[i].kind; i++)
++    if (strcmp (functions[i].database, database->name) == 0
++        && strcmp (functions[i].service, user->name) == 0)
++      fprintf (out, "  &fixed_known_functions[%d], /* %s */\n",
++               i, known_function_name (&functions[i]));
++  fputs ("  NULL\n", out);
++  fputs ("};\n", out);
++  fputs ("\n", out);
++
++  return list_name;
++}
++
++
++/* Return the name of the status value STATUS, as a statically
++   allocated string.  */
++const char *
++lookup_status_name (enum nss_status status)
++{
++  switch (status)
++    {
++    case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN";
++    case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL";
++    case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND";
++    case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS";
++    case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN";
++    default: abort ();
++    };
++}
++
++
++/* Return the name of ACTION as a statically allocated string.  */
++const char *
++lookup_action_name (lookup_actions action)
++{
++  switch (action)
++    {
++    case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE";
++    case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN";
++    default: abort ();
++    }
++}
++
++
++/* Print code to OUT for the list of service_user structures starting
++   with USER, which are all for DATABASE.  Return the name of the
++   first structure in that list, or zero if USER is NULL.  */
++char *
++generate_service_user_list (FILE *out,
++                            name_database_entry *database,
++                            service_user *user)
++{
++  if (user)
++    {
++      /* Generate the tail of the list.  */
++      char *next_name = generate_service_user_list (out, database, user->next);
++      /* Generate our known function list.  */
++      char *known_function_list_name =
++        generate_known_function_list (out, database, user);
++
++      char *name = saprintf ("fixed_%s_%s_user", database->name, user->name);
++
++      fprintf (out, "static const service_user %s = {\n", name);
++      if (next_name)
++        fprintf (out, "  (service_user *) &%s,\n", next_name);
++      else
++        fprintf (out, "  NULL, /* no next entry */\n");
++      fputs ("  {\n", out);
++      int i;
++      for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++)
++        fprintf (out, "    %s, /* %s */\n",
++                 lookup_action_name (user->actions[i]),
++                 lookup_status_name (i - 2));
++      fputs ("  },\n", out);
++      fprintf (out, "  NULL,  /* we never need the service library */\n");
++      fprintf (out, "  { .array = %s },\n", known_function_list_name);
++      fprintf (out, "  \"%s\"\n", user->name);
++      fputs ("};\n", out);
++      fputs ("\n", out);
++
++      return name;
++    }
++  else
++    return NULL;
++}
++
++
++/* Print code to OUT for the list of name_database_entry structures
++   starting with DATABASE.  Return the name of the first structure
++   in that list, or zero if DATABASE is NULL.  */
++char *
++generate_name_database_entries (FILE *out, name_database_entry *database)
++{
++  if (database)
++    {
++      char *next_name = generate_name_database_entries (out, database->next);
++      char *service_user_name
++        = generate_service_user_list (out, database, database->service);
++      char *name = saprintf ("fixed_%s_name_database", database->name);
++
++      fprintf (out, "static const name_database_entry %s = {\n", name);
++
++      if (next_name)
++        fprintf (out, "  (name_database_entry *) &%s,\n", next_name);
++      else
++        fprintf (out, "  NULL,\n");
++
++      if (service_user_name)
++        fprintf (out, "  (service_user *) &%s,\n", service_user_name);
++      else
++        fprintf (out, "  NULL,\n");
++
++      fprintf (out, "  \"%s\"\n", database->name);
++      fprintf (out, "};\n");
++      fputs ("\n", out);
++
++      return name;
++    }
++  else
++    return NULL;
++}
++
++
++void
++generate_name_database (FILE *out, name_database *service_table)
++{
++  /* Produce a linked list of the known name_database_entry
++     structures.  */
++  char *entries = generate_name_database_entries (out, service_table->entry);
++
++  /* Now produce the main structure that points to them all.  */
++  fprintf (out, "static const name_database fixed_name_database = {\n");
++  if (entries)
++    fprintf (out, "  (name_database_entry *) &%s,\n", entries);
++  else
++    fprintf (out, "  NULL,\n");
++  fputs ("  NULL /* we don't need the libraries */\n"
++         "};\n",
++         out);
++}
++
++
++
++/* Generating the list of service libraries we generate references to.  */
++
++/* String with revision number of the shared object files.  */
++static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15;
++
++void
++generate_service_lib_list (FILE *out, name_database *service_table)
++{
++  int i, j;
++  int printed_any = 0;
++
++  for (i = 0; functions[i].kind; i++)
++    {
++      /* Mention each service library only once.  */
++      for (j = 0; j < i; j++)
++        if (strcmp (functions[i].service, functions[j].service) == 0)
++          break;
++
++      if (j >= i)
++        {
++          if (printed_any)
++            putc (' ', out);
++          fprintf (out, "-lnss_%s",
++                   functions[i].service,
++                   nss_shlib_revision);
++          printed_any = 1;
++        }
++    }
++}
++
++
++/* Main.  */
++
++int
++main (int argc, char **argv)
++{
++  if (argc != 4)
++    {
++      fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n");
++      exit (1);
++    }
++
++  name_database *service_table = nss_parse_file (argv[3]);
++
++  FILE *header = fopen (argv[1], "w");
++  if (! header)
++    {
++      fprintf (stderr,
++               "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
++               argv[1], strerror (errno));
++      exit (1);
++    }
++  fputs ("/* Generated by nss/gen-fixed-nsswitch.c.  */\n", header);
++  fputs ("\n", header);
++  generate_known_functions (header);
++  generate_name_database (header, service_table);
++  fclose (header);
++
++  FILE *service_lib_list = fopen (argv[2], "w");
++  if (! service_lib_list)
++    {
++      fprintf (stderr,
++               "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
++               argv[2], strerror (errno));
++      exit (1);
++    }
++  generate_service_lib_list (service_lib_list, service_table);
++  fclose (service_lib_list);
++
++  return 0;
++}
+diff -Naur glibc-2.20/nss/getent.c glibc-2.20-patch/nss/getent.c
+--- glibc-2.20/nss/getent.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nss/getent.c	2015-03-04 00:51:32.384952006 -0600
+@@ -39,6 +39,7 @@
+ #include <netinet/ether.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>
++#include <gnu/option-groups.h>
+ 
+ /* Get libc version number.  */
+ #include <version.h>
+@@ -91,6 +92,7 @@
+   fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
+ }
+ 
++#if __OPTION_EGLIBC_DB_ALIASES
+ /* This is for aliases */
+ static void
+ print_aliases (struct aliasent *alias)
+@@ -135,7 +137,9 @@
+ 
+   return result;
+ }
++#endif /* __OPTION_EGLIBC_DB_ALIASES */
+ 
++#if __OPTION_EGLIBC_INET
+ /* This is for ethers */
+ static int
+ ethers_keys (int number, char *key[])
+@@ -179,6 +183,7 @@
+ 
+   return result;
+ }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+ /* This is for group */
+ static void
+@@ -301,6 +306,7 @@
+   return result;
+ }
+ 
++#if __OPTION_EGLIBC_INET
+ /* This is for hosts */
+ static void
+ print_hosts (struct hostent *host)
+@@ -598,6 +604,7 @@
+ 
+   return result;
+ }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+ /* Now is all for passwd */
+ static void
+@@ -650,6 +657,7 @@
+   return result;
+ }
+ 
++#if __OPTION_EGLIBC_INET
+ /* This is for protocols */
+ static void
+ print_protocols (struct protoent *proto)
+@@ -805,6 +813,7 @@
+ 
+   return result;
+ }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+ /* This is for shadow */
+ static void
+@@ -871,21 +880,34 @@
+   } databases[] =
+   {
+ #define D(name) { #name, name ## _keys },
+-D(ahosts)
+-D(ahostsv4)
+-D(ahostsv6)
+-D(aliases)
+-D(ethers)
++
++#if __OPTION_EGLIBC_INET
++#define DN(name) D(name)
++#else
++#define DN(name)
++#endif
++
++#if __OPTION_EGLIBC_DB_ALIASES
++#define DA(name) D(name)
++#else
++#define DA(name)
++#endif
++
++DN(ahosts)
++DN(ahostsv4)
++DN(ahostsv6)
++DA(aliases)
++DN(ethers)
+ D(group)
+ D(gshadow)
+-D(hosts)
++DN(hosts)
+ D(initgroups)
+-D(netgroup)
+-D(networks)
++DN(netgroup)
++DN(networks)
+ D(passwd)
+-D(protocols)
+-D(rpc)
+-D(services)
++DN(protocols)
++DN(rpc)
++DN(services)
+ D(shadow)
+ #undef D
+     { NULL, NULL }
+diff -Naur glibc-2.20/nss/getnssent_r.c glibc-2.20-patch/nss/getnssent_r.c
+--- glibc-2.20/nss/getnssent_r.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nss/getnssent_r.c	2015-03-04 00:51:32.384952006 -0600
+@@ -16,6 +16,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #include <errno.h>
++#include <gnu/option-groups.h>
+ #include <netdb.h>
+ #include "nsswitch.h"
+ 
+@@ -59,11 +60,13 @@
+   } fct;
+   int no_more;
+ 
++#if __OPTION_EGLIBC_INET
+   if (res && __res_maybe_init (&_res, 0) == -1)
+     {
+       __set_h_errno (NETDB_INTERNAL);
+       return;
+     }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+   /* Cycle through the services and run their `setXXent' functions until
+      we find an available service.  */
+@@ -101,11 +104,13 @@
+   } fct;
+   int no_more;
+ 
++#if __OPTION_EGLIBC_INET
+   if (res && __res_maybe_init (&_res, 0) == -1)
+     {
+       __set_h_errno (NETDB_INTERNAL);
+       return;
+     }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+   /* Cycle through all the services and run their endXXent functions.  */
+   no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1);
+@@ -141,12 +146,14 @@
+   int no_more;
+   enum nss_status status;
+ 
++#if __OPTION_EGLIBC_INET
+   if (res && __res_maybe_init (&_res, 0) == -1)
+     {
+       *h_errnop = NETDB_INTERNAL;
+       *result = NULL;
+       return errno;
+     }
++#endif /* __OPTION_EGLIBC_INET */
+ 
+   /* Initialize status to return if no more functions are found.  */
+   status = NSS_STATUS_NOTFOUND;
+@@ -161,7 +168,7 @@
+       int is_last_nip = *nip == *last_nip;
+ 
+       status = DL_CALL_FCT (fct.f,
+-			    (resbuf, buffer, buflen, &errno, &h_errno));
++			    (resbuf, buffer, buflen, &errno, h_errnop));
+ 
+       /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
+ 	 provided buffer is too small.  In this case we should give
+diff -Naur glibc-2.20/nss/Makefile glibc-2.20-patch/nss/Makefile
+--- glibc-2.20/nss/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nss/Makefile	2015-03-04 00:51:32.384952006 -0600
+@@ -18,29 +18,36 @@
+ #
+ #	Makefile for name service switch.
+ #
++include ../option-groups.mak
++
+ subdir	:= nss
+ 
+ include ../Makeconfig
+ 
+ headers			:= nss.h
+ 
+-# This is the trivial part which goes into libc itself.
+-routines		= nsswitch getnssent getnssent_r digits_dots \
+-			  $(addsuffix -lookup,$(databases))
+-
+ # These are the databases that go through nss dispatch.
+ # Caution: if you add a database here, you must add its real name
+ # in databases.def, too.
+-databases		= proto service hosts network grp pwd rpc ethers \
+-			  spwd netgrp key alias sgrp
++databases-y		= grp pwd spwd sgrp
++databases-$(OPTION_EGLIBC_INET) \
++			+= proto service hosts network rpc ethers \
++			   netgrp key
++databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
++
++# This is the trivial part which goes into libc itself.
++routines-y		+= nsswitch getnssent getnssent_r \
++			  $(addsuffix -lookup,$(databases-y))
++routines-$(OPTION_EGLIBC_INET) += digits_dots
+ 
+ others                  := getent makedb
+ install-bin             := getent makedb
+ makedb-modules = xmalloc hash-string
+ extra-objs		+= $(makedb-modules:=.o)
+ 
+-tests			= test-netdb tst-nss-test1 test-digits-dots
+-xtests			= bug-erange
++tests			= tst-nss-test1
++tests-$(OPTION_EGLIBC_INET) += test-netdb test-digits-dots
++xtests-$(OPTION_EGLIBC_INET) += bug-erange
+ 
+ # Specify rules for the nss_* modules.  We have some services.
+ services		:= files db
+@@ -55,7 +62,7 @@
+ vpath %.c $(subdir-dirs) ../locale/programs ../intl
+ 
+ 
+-libnss_files-routines	:= $(addprefix files-,$(databases)) \
++libnss_files-routines	:= $(addprefix files-,$(databases-y)) \
+ 			   files-initgroups files-have_o_cloexec files-init
+ 
+ libnss_db-dbs		:= $(addprefix db-,\
+@@ -78,6 +85,45 @@
+ tests			+= $(tests-static)
+ endif
+ 
++ifneq ($(OPTION_EGLIBC_NSSWITCH),y)
++
++ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG
++$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset)
++endif
++
++ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS
++$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset)
++endif
++
++ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)))
++$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file)
++$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))
++endif
++
++ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)))
++$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file)
++$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))
++endif
++
++before-compile := $(objpfx)fixed-nsswitch.h
++generated := fixed-nsswitch.h
++$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs:	\
++    $(objpfx)gen-fixed-nsswitch				\
++    $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
++	$< $(objpfx)fixed-nsswitch.h			\
++	   $(objpfx)fixed-nsswitch-libs			\
++	   $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
++
++$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c	\
++    $(common-objpfx)option-groups.config		\
++    $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)
++	$(native-compile)
++gen-fixed-nsswitch-CFLAGS =						\
++	-g3 -O -Wall							\
++	-I $(objpfx)							\
++	-DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"'
++endif
++
+ include ../Rules
+ 
+ ifeq (yes,$(have-selinux))
+diff -Naur glibc-2.20/nss/nsswitch.c glibc-2.20-patch/nss/nsswitch.c
+--- glibc-2.20/nss/nsswitch.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nss/nsswitch.c	2015-03-04 00:51:32.384952006 -0600
+@@ -26,6 +26,7 @@
+ #include <stdio_ext.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <gnu/option-groups.h>
+ 
+ #include <aliases.h>
+ #include <grp.h>
+@@ -41,6 +42,15 @@
+ #include "../nscd/nscd_proto.h"
+ #include <sysdep.h>
+ 
++/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of
++   databases and services, generated at library build time.  Thus:
++   - We can't reconfigure individual databases, so we don't need a
++     name-to-database map.
++   - We never add databases or service libraries, or look up functions
++     at runtime, so there's no need for a lock to protect our tables.
++   See ../option-groups.def for the details.  */
++#if __OPTION_EGLIBC_NSSWITCH
++
+ /* Prototypes for the local functions.  */
+ static name_database *nss_parse_file (const char *fname) internal_function;
+ static name_database_entry *nss_getline (char *line) internal_function;
+@@ -79,6 +89,9 @@
+ 
+ __libc_lock_define_initialized (static, lock)
+ 
++#define lock_nsswitch __libc_lock_lock (lock)
++#define unlock_nsswitch __libc_lock_unlock (lock)
++
+ #if !defined DO_STATIC_NSS || defined SHARED
+ /* String with revision number of the shared object files.  */
+ static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
+@@ -93,6 +106,20 @@
+    __libc_freeres.  */
+ static name_database_entry *defconfig_entries;
+ 
++#else /* __OPTION_EGLIBC_NSSWITCH */
++
++/* Bring in the statically initialized service table we generated at
++   build time.  */
++#include "fixed-nsswitch.h"
++
++const static name_database *service_table = &fixed_name_database;
++
++/* Nothing ever changes, so there's no need to lock anything.  */
++#define lock_nsswitch (0)
++#define unlock_nsswitch (0)
++
++#endif /* __OPTION_EGLIBC_NSSWITCH */
++
+ 
+ #ifdef USE_NSCD
+ /* Nonzero if this is the nscd process.  */
+@@ -109,20 +136,22 @@
+ 		       const char *defconfig, service_user **ni)
+ {
+   /* Prevent multiple threads to change the service table.  */
+-  __libc_lock_lock (lock);
++  lock_nsswitch;
+ 
+   /* Reconsider database variable in case some other thread called
+      `__nss_configure_lookup' while we waited for the lock.  */
+   if (*ni != NULL)
+     {
+-      __libc_lock_unlock (lock);
++      unlock_nsswitch;
+       return 0;
+     }
+ 
++#if __OPTION_EGLIBC_NSSWITCH
+   /* Are we initialized yet?  */
+   if (service_table == NULL)
+     /* Read config file.  */
+     service_table = nss_parse_file (_PATH_NSSWITCH_CONF);
++#endif
+ 
+   /* Test whether configuration data is available.  */
+   if (service_table != NULL)
+@@ -144,6 +173,7 @@
+ 	    *ni = entry->service;
+     }
+ 
++#if __OPTION_EGLIBC_NSSWITCH
+   /* No configuration data is available, either because nsswitch.conf
+      doesn't exist or because it doesn't have a line for this database.
+ 
+@@ -166,13 +196,23 @@
+ 	    {
+ 	      entry->next = defconfig_entries;
+ 	      entry->service = *ni;
+-	      entry->name[0] = '\0';
++	      entry->name = "";
+ 	      defconfig_entries = entry;
+ 	    }
+ 	}
+     }
++#else
++  /* Without the dynamic behavior, we can't process defconfig.  The
++     databases the user specified at library build time are all you
++     get.  */
++  if (*ni == NULL)
++    {
++      unlock_nsswitch;
++      return -1;
++    }
++#endif
+ 
+-  __libc_lock_unlock (lock);
++  unlock_nsswitch;
+ 
+   return *ni != NULL ? 0 : -1;
+ }
+@@ -252,6 +292,7 @@
+ libc_hidden_def (__nss_next2)
+ 
+ 
++#if __OPTION_EGLIBC_NSSWITCH
+ int
+ attribute_compat_text_section
+ __nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
+@@ -300,13 +341,13 @@
+     }
+ 
+   /* Prevent multiple threads to change the service table.  */
+-  __libc_lock_lock (lock);
++  lock_nsswitch;
+ 
+   /* Install new rules.  */
+   *databases[cnt].dbp = new_db;
+   __nss_database_custom[cnt] = true;
+ 
+-  __libc_lock_unlock (lock);
++  unlock_nsswitch;
+ 
+   return 0;
+ }
+@@ -402,7 +443,7 @@
+   void **found, *result;
+ 
+   /* We now modify global data.  Protect it.  */
+-  __libc_lock_lock (lock);
++  lock_nsswitch;
+ 
+   /* Search the tree of functions previously requested.  Data in the
+      tree are `known_function' structures, whose first member is a
+@@ -413,7 +454,7 @@
+      enough to a pointer to our structure to use as a lookup key that
+      will be passed to `known_compare' (above).  */
+ 
+-  found = __tsearch (&fct_name, &ni->known, &known_compare);
++  found = __tsearch (&fct_name, &ni->known.tree, &known_compare);
+   if (found == NULL)
+     /* This means out-of-memory.  */
+     result = NULL;
+@@ -440,7 +481,7 @@
+ #endif
+ 	  /* Oops.  We can't instantiate this node properly.
+ 	     Remove it from the tree.  */
+-	  __tdelete (&fct_name, &ni->known, &known_compare);
++	  __tdelete (&fct_name, &ni->known.tree, &known_compare);
+ 	  free (known);
+ 	  result = NULL;
+ 	}
+@@ -520,13 +561,43 @@
+     }
+ 
+   /* Remove the lock.  */
+-  __libc_lock_unlock (lock);
++  unlock_nsswitch;
+ 
+   return result;
+ }
+ libc_hidden_def (__nss_lookup_function)
+ 
+ 
++#else /* below if ! __OPTION_EGLIBC_NSSWITCH */
++
++
++int
++__nss_configure_lookup (const char *dbname, const char *service_line)
++{
++  /* We can't dynamically configure lookup without
++     OPTION_EGLIBC_NSSWITCH.  */
++  __set_errno (EINVAL);
++  return -1;
++}
++
++
++void *
++__nss_lookup_function (service_user *ni, const char *fct_name)
++{
++  int i;
++  const known_function **known = ni->known.array;
++
++  for (i = 0; known[i]; i++)
++    if (strcmp (fct_name, known[i]->fct_name) == 0)
++      return known[i]->fct_ptr;
++
++  return NULL;
++}
++libc_hidden_def (__nss_lookup_function)
++#endif
++
++
++#if __OPTION_EGLIBC_NSSWITCH
+ static name_database *
+ internal_function
+ nss_parse_file (const char *fname)
+@@ -632,8 +703,10 @@
+ 					     + (line - name + 1));
+       if (new_service == NULL)
+ 	return result;
++      new_service->name = (char *) (new_service + 1);
+ 
+-      *((char *) __mempcpy (new_service->name, name, line - name)) = '\0';
++      *((char *) __mempcpy ((char *) new_service->name, name, line - name))
++        = '\0';
+ 
+       /* Set default actions.  */
+       new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
+@@ -642,7 +715,7 @@
+       new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
+       new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
+       new_service->library = NULL;
+-      new_service->known = NULL;
++      new_service->known.tree = NULL;
+       new_service->next = NULL;
+ 
+       while (isspace (line[0]))
+@@ -778,9 +851,10 @@
+   result = (name_database_entry *) malloc (sizeof (name_database_entry) + len);
+   if (result == NULL)
+     return NULL;
++  result->name = (char *) (result + 1);
+ 
+   /* Save the database name.  */
+-  memcpy (result->name, name, len);
++  memcpy ((char *) result->name, name, len);
+ 
+   /* Parse the list of services.  */
+   result->service = nss_parse_service_list (line);
+@@ -816,6 +890,7 @@
+   return *currentp;
+ }
+ #endif
++#endif /* __OPTION_EGLIBC_NSSWITCH */
+ 
+ 
+ #if defined SHARED && defined USE_NSCD
+@@ -834,6 +909,7 @@
+ }
+ 
+ 
++#if __OPTION_EGLIBC_INET
+ /* Called by nscd and nscd alone.  */
+ void
+ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
+@@ -857,8 +933,10 @@
+   __nss_not_use_nscd_services = -1;
+   __nss_not_use_nscd_netgroup = -1;
+ }
++#endif /* __OPTION_EGLIBC_INET */
+ #endif
+ 
++#if __OPTION_EGLIBC_NSSWITCH
+ static void
+ free_database_entries (name_database_entry *entry)
+ {
+@@ -871,8 +949,8 @@
+ 	{
+ 	  service_user *olds = service;
+ 
+-	  if (service->known != NULL)
+-	    __tdestroy (service->known, free);
++	  if (service->known.tree != NULL)
++	    __tdestroy (service->known.tree, free);
+ 
+ 	  service = service->next;
+ 	  free (olds);
+@@ -926,3 +1004,4 @@
+ 
+   free (top);
+ }
++#endif /* __OPTION_EGLIBC_NSSWITCH */
+diff -Naur glibc-2.20/nss/nsswitch.h glibc-2.20-patch/nss/nsswitch.h
+--- glibc-2.20/nss/nsswitch.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/nss/nsswitch.h	2015-03-04 00:51:32.385952006 -0600
+@@ -65,10 +65,20 @@
+   lookup_actions actions[5];
+   /* Link to the underlying library object.  */
+   service_library *library;
+-  /* Collection of known functions.  */
+-  void *known;
++  /* Collection of known functions.
++
++     With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
++     'tsearch'-style tree.
++
++     With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
++     pointers to known_function structures, NULL-terminated.  */
++  union
++  {
++    void *tree;
++    const known_function **array;
++  } known;
+   /* Name of the service (`files', `dns', `nis', ...).  */
+-  char name[0];
++  const char *name;
+ } service_user;
+ 
+ /* To access the action based on the status value use this macro.  */
+@@ -82,7 +92,7 @@
+   /* List of service to be used.  */
+   service_user *service;
+   /* Name of the database.  */
+-  char name[0];
++  const char *name;
+ } name_database_entry;
+ 
+ 
+diff -Naur glibc-2.20/posix/bug-regex1.c glibc-2.20-patch/posix/bug-regex1.c
+--- glibc-2.20/posix/bug-regex1.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/bug-regex1.c	2015-03-04 00:51:32.385952006 -0600
+@@ -4,6 +4,7 @@
+ #include <string.h>
+ #include <regex.h>
+ #include <wchar.h>
++#include <gnu/option-groups.h>
+ 
+ int
+ main (void)
+@@ -17,7 +18,9 @@
+   memset (&regex, '\0', sizeof (regex));
+ 
+   setlocale (LC_ALL, "de_DE.ISO-8859-1");
++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+   fwide (stdout, -1);
++#endif
+ 
+   re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG);
+ 
+diff -Naur glibc-2.20/posix/bug-regex6.c glibc-2.20-patch/posix/bug-regex6.c
+--- glibc-2.20/posix/bug-regex6.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/bug-regex6.c	2015-03-04 00:51:32.385952006 -0600
+@@ -22,6 +22,7 @@
+ #include <string.h>
+ #include <sys/types.h>
+ #include <regex.h>
++#include <gnu/option-groups.h>
+ 
+ 
+ int
+@@ -30,7 +31,12 @@
+   regex_t re;
+   regmatch_t mat[10];
+   int i, j, ret = 0;
+-  const char *locales[] = { "C", "de_DE.UTF-8" };
++  const char *locales[] = {
++    "C",
++#if __OPTION_EGLIBC_LOCALE_CODE
++    "de_DE.UTF-8"
++#endif
++  };
+   const char *string = "http://www.regex.com/pattern/matching.html#intro";
+   regmatch_t expect[10] = {
+     { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 },
+diff -Naur glibc-2.20/posix/fnmatch.c glibc-2.20-patch/posix/fnmatch.c
+--- glibc-2.20/posix/fnmatch.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/fnmatch.c	2015-03-04 00:51:32.385952006 -0600
+@@ -30,6 +30,10 @@
+ #include <ctype.h>
+ #include <string.h>
+ 
++#if defined _LIBC
++# include <gnu/option-groups.h>
++#endif
++
+ #if defined STDC_HEADERS || defined _LIBC
+ # include <stdlib.h>
+ #endif
+@@ -131,7 +135,7 @@
+ #   define ISWCTYPE(WC, WT)	iswctype (WC, WT)
+ #  endif
+ 
+-#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
++#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || (_LIBC && __OPTION_EGLIBC_LOCALE_CODE)
+ /* In this case we are implementing the multibyte character handling.  */
+ #   define HANDLE_MULTIBYTE	1
+ #  endif
+diff -Naur glibc-2.20/posix/fnmatch_loop.c glibc-2.20-patch/posix/fnmatch_loop.c
+--- glibc-2.20/posix/fnmatch_loop.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/fnmatch_loop.c	2015-03-04 00:51:32.385952006 -0600
+@@ -15,6 +15,8 @@
+    License along with the GNU C Library; if not, see
+    <http://www.gnu.org/licenses/>.  */
+ 
++#include <gnu/option-groups.h>
++
+ #include <stdint.h>
+ 
+ struct STRUCT
+@@ -54,10 +56,15 @@
+   const char *collseq = (const char *)
+     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+ # else
++#  if __OPTION_EGLIBC_LOCALE_CODE
+   const UCHAR *collseq = (const UCHAR *)
+     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+-# endif
+-#endif
++#   define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)])
++#  else
++#   define COLLSEQ_BYTE_LOOKUP(ix) (ix)
++#  endif /* __OPTION_EGLIBC_LOCALE_CODE */
++# endif /* WIDE_CHAR_VERSION */
++#endif /* _LIBC */
+ 
+   while ((c = *p++) != L('\0'))
+     {
+@@ -277,7 +284,7 @@
+ 		    /* Leave room for the null.  */
+ 		    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+ 		    size_t c1 = 0;
+-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
++#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+ 		    wctype_t wt;
+ #endif
+ 		    const CHAR *startp = p;
+@@ -307,7 +314,7 @@
+ 		      }
+ 		    str[c1] = L('\0');
+ 
+-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
++#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+ 		    wt = IS_CHAR_CLASS (str);
+ 		    if (wt == 0)
+ 		      /* Invalid character class name.  */
+@@ -681,8 +688,10 @@
+ 			else
+ 			  lcollseq = __collseq_table_lookup (collseq, cold);
+ # else
+-			fcollseq = collseq[fn];
+-			lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
++			fcollseq = COLLSEQ_BYTE_LOOKUP (fn);
++			lcollseq = (is_seqval
++                                    ? cold
++                                    : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold));
+ # endif
+ 
+ 			is_seqval = 0;
+@@ -858,7 +867,7 @@
+ 				    goto matched;
+ 				  }
+ # else
+-				hcollseq = collseq[cend];
++				hcollseq = COLLSEQ_BYTE_LOOKUP (cend);
+ # endif
+ 			      }
+ 
+diff -Naur glibc-2.20/posix/glob.c glibc-2.20-patch/posix/glob.c
+--- glibc-2.20/posix/glob.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/glob.c	2015-03-04 00:51:32.386952006 -0600
+@@ -25,6 +25,9 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stddef.h>
++#ifdef _LIBC
++# include <gnu/option-groups.h>
++#endif
+ 
+ /* Outcomment the following line for production quality code.  */
+ /* #define NDEBUG 1 */
+@@ -607,6 +610,7 @@
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    home_dir = "c:/users/default"; /* poor default */
+ #  else
++#   if ! _LIBC || __OPTION_EGLIBC_GETLOGIN
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    {
+ 	      int success;
+@@ -623,19 +627,19 @@
+ 	      if (success)
+ 		{
+ 		  struct passwd *p;
+-#   if defined HAVE_GETPWNAM_R || defined _LIBC
++#    if defined HAVE_GETPWNAM_R || defined _LIBC
+ 		  long int pwbuflen = GETPW_R_SIZE_MAX ();
+ 		  char *pwtmpbuf;
+ 		  struct passwd pwbuf;
+ 		  int malloc_pwtmpbuf = 0;
+ 		  int save = errno;
+ 
+-#    ifndef _LIBC
++#     ifndef _LIBC
+ 		  if (pwbuflen == -1)
+ 		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
+ 		       Try a moderate value.  */
+ 		    pwbuflen = 1024;
+-#    endif
++#     endif
+ 		  if (__libc_use_alloca (alloca_used + pwbuflen))
+ 		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
+ 		  else
+@@ -682,9 +686,9 @@
+ 			}
+ 		      __set_errno (save);
+ 		    }
+-#   else
++#    else
+ 		  p = getpwnam (name);
+-#   endif
++#    endif
+ 		  if (p != NULL)
+ 		    {
+ 		      if (!malloc_pwtmpbuf)
+@@ -713,6 +717,7 @@
+ 		    }
+ 		}
+ 	    }
++#   endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    {
+ 	      if (flags & GLOB_TILDE_CHECK)
+diff -Naur glibc-2.20/posix/Makefile glibc-2.20-patch/posix/Makefile
+--- glibc-2.20/posix/Makefile	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/Makefile	2015-03-04 00:51:32.386952006 -0600
+@@ -18,6 +18,8 @@
+ #
+ #	Sub-makefile for POSIX portion of the library.
+ #
++include ../option-groups.mak
++
+ subdir	:= posix
+ 
+ include ../Makeconfig
+@@ -43,13 +45,24 @@
+ 	getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid	      \
+ 	getresuid getresgid setresuid setresgid				      \
+ 	pathconf sysconf fpathconf					      \
+-	glob glob64 fnmatch regex					      \
++	glob glob64 fnmatch						      \
+ 	confstr								      \
+ 	getopt getopt1 getopt_init					      \
+ 	sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax  \
+ 	sched_primin sched_rr_gi sched_getaffinity sched_setaffinity	      \
+-	getaddrinfo gai_strerror wordexp				      \
+ 	pread pwrite pread64 pwrite64					      \
++	posix_madvise							      \
++	get_child_max sched_cpucount sched_cpualloc sched_cpufree
++
++routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror
++
++ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC))
++routines-$(OPTION_POSIX_REGEXP) += regex
++else
++routines-$(OPTION_POSIX_REGEXP) += xregex
++endif
++
++routines-$(OPTION_EGLIBC_SPAWN) +=					      \
+ 	spawn_faction_init spawn_faction_destroy spawn_faction_addclose	      \
+ 	spawn_faction_addopen spawn_faction_adddup2			      \
+ 	spawnattr_init spawnattr_destroy				      \
+@@ -57,41 +70,53 @@
+ 	spawnattr_getflags spawnattr_setflags				      \
+ 	spawnattr_getpgroup spawnattr_setpgroup spawn spawnp spawni	      \
+ 	spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
+-	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
+-	posix_madvise							      \
+-	get_child_max sched_cpucount sched_cpualloc sched_cpufree
++	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam
++routines-$(OPTION_EGLIBC_WORDEXP) += wordexp
+ 
+ aux		:= init-posix environ
+-tests		:= tstgetopt testfnm runtests runptests	     \
++tests		:= tstgetopt testfnm runtests	     \
+ 		   tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \
+-		   tst-getlogin tst-mmap tst-getaddrinfo tst-truncate \
+-		   tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
+-		   tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
+-		   tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \
+-		   bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
+-		   bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
+-		   bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+-		   bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
+-		   bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
+-		   bug-regex29 bug-regex30 bug-regex31 bug-regex32 \
+-		   bug-regex33 tst-nice tst-nanosleep tst-regex2 \
+-		   transbug tst-rxspencer tst-pcre tst-boost \
+-		   bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
+-		   tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
++		   tst-getlogin tst-mmap tst-truncate \
++		   tst-truncate64 tst-fork tst-dir \
++		   tst-chmod bug-regex2 bug-regex3 bug-regex4 \
++		   tst-gnuglob bug-regex6 bug-regex7 \
++		   bug-regex8 bug-regex9 bug-regex10 bug-regex12 \
++		   bug-regex14 bug-regex15 \
++		   bug-regex21 bug-regex24 \
++		   bug-regex27 bug-regex28 bug-regex29 bug-regex30 \
++		   bug-regex31 \
++		   tst-nice tst-nanosleep \
++		   transbug \
++		   tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
++		   bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
+ 		   tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
+ 		   tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
+ 		   tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
+-		   tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
+-		   tst-rfc3484-3 \
+-		   tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
++		   tst-execvp3 tst-execvp4 \
++		   tst-fnmatch2 tst-cpucount tst-cpuset \
+ 		   bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
+ 		   bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
+ 		   tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
+ 		   tst-fnmatch3 bug-regex36
+-xtests		:= bug-ga2
++tests-$(OPTION_EGLIBC_LOCALE_CODE)					    \
++		+= tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \
++		   bug-regex23 bug-regex25 bug-regex32 bug-regex33
++tests-$(OPTION_EGLIBC_INET) \
++	        += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \
++		   tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3
++tests-$(OPTION_POSIX_REGEXP_GLIBC) \
++		+= runptests bug-regex11 bug-regex13 bug-regex16 \
++		   tst-regex2 tst-rxspencer tst-pcre tst-boost
++ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC))
++tests           += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
++		   bug-regex22 bug-regex26
++endif
++xtests-$(OPTION_EGLIBC_INET) += bug-ga2
+ ifeq (yes,$(build-shared))
+ test-srcs	:= globtest
+-tests           += wordexp-test tst-exec tst-spawn
++tests           += tst-exec
++tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn
++tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test
+ endif
+ tests-static	= tst-exec-static tst-spawn-static
+ tests		+= $(tests-static)
+@@ -117,7 +142,10 @@
+ 
+ ifeq ($(run-built-tests),yes)
+ ifeq (yes,$(build-shared))
+-tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out
++tests-special += $(objpfx)globtest.out
++ifeq (y,$(OPTION_EGLIBC_WORDEXP))
++tests-special += $(objpfx)wordexp-tst.out
++endif
+ endif
+ endif
+ 
+@@ -125,12 +153,16 @@
+ # XXX Please note that for now we ignore the result of this test.
+ tests-special += $(objpfx)annexc.out
+ ifeq ($(run-built-tests),yes)
+-tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
++tests-special += $(objpfx)bug-regex2-mem.out \
+ 		 $(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \
+-		 $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
+-		 $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
++		 $(objpfx)tst-getconf.out \
+ 		 $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
+ 		 $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
++ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC))
++tests-special += $(objpfx)bug-regex14-mem.out $(objpfx)tst-rxspencer-no-utf8-mem.out \
++  		 $(objpfx)tst-pcre-mem.out $(objpfx)tst-boost-mem.out
++endif
++
+ xtests-special += $(objpfx)bug-ga2-mem.out
+ endif
+ 
+@@ -143,6 +175,8 @@
+ 	$(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \
+ 		'$(test-program-prefix)' '$(test-wrapper-env)'; \
+ 	$(evaluate-test)
++LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
++
+ $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test
+ 	$(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
+ 		 '$(run-program-env)' '$(test-program-prefix-after-env)'; \
+@@ -205,7 +239,10 @@
+ tst-chmod-ARGS = $(objdir)
+ tst-vfork3-ARGS = --test-dir=$(objpfx)
+ 
+-tst-rxspencer-ARGS = --utf8 rxspencer/tests
++tst-rxspencer-ARGS = rxspencer/tests
++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
++tst-rxspencer-ARGS += --utf8
++endif
+ tst-rxspencer-no-utf8-ARGS = rxspencer/tests
+ tst-pcre-ARGS = PCRE.tests
+ tst-boost-ARGS = BOOST.tests
+diff -Naur glibc-2.20/posix/regcomp.c glibc-2.20-patch/posix/regcomp.c
+--- glibc-2.20/posix/regcomp.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/regcomp.c	2015-03-04 00:51:32.387952006 -0600
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #include <stdint.h>
++#include <gnu/option-groups.h>
+ 
+ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
+ 					  size_t length, reg_syntax_t syntax);
+@@ -305,7 +306,7 @@
+ {
+   re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+   int node_cnt;
+-  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
++  int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE));
+   for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
+     {
+       int node = init_state->nodes.elems[node_cnt];
+@@ -315,9 +316,9 @@
+ 	{
+ 	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
+ #ifdef RE_ENABLE_I18N
+-	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
++	  if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
+ 	    {
+-	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;
++	      unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p;
+ 	      wchar_t wc;
+ 	      mbstate_t state;
+ 
+@@ -348,7 +349,11 @@
+ 		  re_set_fastmap (fastmap, icase, ch);
+ 	    }
+ 	}
+-#ifdef RE_ENABLE_I18N
++
++      /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current
++         locale is always C, which has no rules and no multi-byte
++         characters.  */
++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
+       else if (type == COMPLEX_BRACKET)
+ 	{
+ 	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;
+@@ -376,7 +381,7 @@
+ 	     i.e. where we would not find an invalid sequence.  This only
+ 	     applies to multibyte character sets; for single byte character
+ 	     sets, the SIMPLE_BRACKET again suffices.  */
+-	  if (dfa->mb_cur_max > 1
++	  if (dfa_mb_cur_max (dfa) > 1
+ 	      && (cset->nchar_classes || cset->non_match || cset->nranges
+ # ifdef _LIBC
+ 		  || cset->nequiv_classes
+@@ -404,7 +409,7 @@
+ 		  memset (&state, '\0', sizeof (state));
+ 		  if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+ 		    re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+-		  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
++		  if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
+ 		    {
+ 		      if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
+ 			  != (size_t) -1)
+@@ -413,7 +418,7 @@
+ 		}
+ 	    }
+ 	}
+-#endif /* RE_ENABLE_I18N */
++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
+       else if (type == OP_PERIOD
+ #ifdef RE_ENABLE_I18N
+ 	       || type == OP_UTF8_PERIOD
+@@ -856,11 +861,15 @@
+ 
+   dfa->mb_cur_max = MB_CUR_MAX;
+ #ifdef _LIBC
+-  if (dfa->mb_cur_max == 6
++  if (dfa_mb_cur_max (dfa) == 6
+       && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
+     dfa->is_utf8 = 1;
++# if __OPTION_EGLIBC_LOCALE_CODE
+   dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
+ 		       != 0);
++# else
++  dfa->map_notascii = 0;
++# endif
+ #else
+ # ifdef HAVE_LANGINFO_CODESET
+   codeset_name = nl_langinfo (CODESET);
+@@ -886,7 +895,7 @@
+ #endif
+ 
+ #ifdef RE_ENABLE_I18N
+-  if (dfa->mb_cur_max > 1)
++  if (dfa_mb_cur_max (dfa) > 1)
+     {
+       if (dfa->is_utf8)
+ 	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
+@@ -1784,7 +1793,7 @@
+   token->word_char = 0;
+ #ifdef RE_ENABLE_I18N
+   token->mb_partial = 0;
+-  if (input->mb_cur_max > 1 &&
++  if (string_mb_cur_max (input) > 1 &&
+       !re_string_first_byte (input, re_string_cur_idx (input)))
+     {
+       token->type = CHARACTER;
+@@ -1805,7 +1814,7 @@
+       token->opr.c = c2;
+       token->type = CHARACTER;
+ #ifdef RE_ENABLE_I18N
+-      if (input->mb_cur_max > 1)
++      if (string_mb_cur_max (input) > 1)
+ 	{
+ 	  wint_t wc = re_string_wchar_at (input,
+ 					  re_string_cur_idx (input) + 1);
+@@ -1919,7 +1928,7 @@
+ 
+   token->type = CHARACTER;
+ #ifdef RE_ENABLE_I18N
+-  if (input->mb_cur_max > 1)
++  if (string_mb_cur_max (input) > 1)
+     {
+       wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
+       token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+@@ -2019,7 +2028,7 @@
+   token->opr.c = c;
+ 
+ #ifdef RE_ENABLE_I18N
+-  if (input->mb_cur_max > 1 &&
++  if (string_mb_cur_max (input) > 1 &&
+       !re_string_first_byte (input, re_string_cur_idx (input)))
+     {
+       token->type = CHARACTER;
+@@ -2242,7 +2251,7 @@
+ 	  return NULL;
+ 	}
+ #ifdef RE_ENABLE_I18N
+-      if (dfa->mb_cur_max > 1)
++      if (dfa_mb_cur_max (dfa) > 1)
+ 	{
+ 	  while (!re_string_eoi (regexp)
+ 		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
+@@ -2380,7 +2389,7 @@
+ 	  *err = REG_ESPACE;
+ 	  return NULL;
+ 	}
+-      if (dfa->mb_cur_max > 1)
++      if (dfa_mb_cur_max (dfa) > 1)
+ 	dfa->has_mb_node = 1;
+       break;
+     case OP_WORD:
+@@ -2686,7 +2695,7 @@
+        However, for !_LIBC we have no collation elements: if the
+        character set is single byte, the single byte character set
+        that we build below suffices.  parse_bracket_exp passes
+-       no MBCSET if dfa->mb_cur_max == 1.  */
++       no MBCSET if dfa_mb_cur_max (dfa) == 1.  */
+     if (mbcset)
+       {
+ 	/* Check the space of the arrays.  */
+@@ -2782,7 +2791,13 @@
+ 		   reg_syntax_t syntax, reg_errcode_t *err)
+ {
+ #ifdef _LIBC
++#if __OPTION_EGLIBC_LOCALE_CODE
+   const unsigned char *collseqmb;
++# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)])
++#else
++# define COLLSEQMB_LOOKUP(ix) (ix)
++#endif
++
+   const char *collseqwc;
+   uint32_t nrules;
+   int32_t table_size;
+@@ -2830,18 +2845,20 @@
+ 	  if (MB_CUR_MAX == 1)
+ 	  */
+ 	  if (nrules == 0)
+-	    return collseqmb[br_elem->opr.ch];
++	    return COLLSEQMB_LOOKUP (br_elem->opr.ch);
+ 	  else
+ 	    {
+ 	      wint_t wc = __btowc (br_elem->opr.ch);
+ 	      return __collseq_table_lookup (collseqwc, wc);
+ 	    }
+ 	}
++#if __OPTION_EGLIBC_LOCALE_CODE
+       else if (br_elem->type == MB_CHAR)
+ 	{
+ 	  if (nrules != 0)
+ 	    return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
+ 	}
++#endif
+       else if (br_elem->type == COLL_SYM)
+ 	{
+ 	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
+@@ -2872,11 +2889,11 @@
+ 		{
+ 		  /* No valid character.  Match it as a single byte
+ 		     character.  */
+-		  return collseqmb[br_elem->opr.name[0]];
++		  return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
+ 		}
+ 	    }
+ 	  else if (sym_name_len == 1)
+-	    return collseqmb[br_elem->opr.name[0]];
++	    return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
+ 	}
+       return UINT_MAX;
+     }
+@@ -2916,7 +2933,7 @@
+ 	 However, if we have no collation elements, and the character set
+ 	 is single byte, the single byte character set that we
+ 	 build below suffices. */
+-      if (nrules > 0 || dfa->mb_cur_max > 1)
++      if (nrules > 0 || dfa_mb_cur_max (dfa) > 1)
+ 	{
+ 	  /* Check the space of the arrays.  */
+ 	  if (BE (*range_alloc == mbcset->nranges, 0))
+@@ -2953,7 +2970,7 @@
+ 	  if (MB_CUR_MAX == 1)
+ 	  */
+ 	  if (nrules == 0)
+-	    ch_collseq = collseqmb[ch];
++	    ch_collseq = COLLSEQMB_LOOKUP (ch);
+ 	  else
+ 	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
+ 	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
+@@ -3031,7 +3048,10 @@
+   re_bitset_ptr_t sbcset;
+ #ifdef RE_ENABLE_I18N
+   re_charset_t *mbcset;
+-  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
++  int coll_sym_alloc = 0, range_alloc = 0;
++#if __OPTION_EGLIBC_LOCALE_CODE
++  int mbchar_alloc = 0;
++#endif
+   int equiv_class_alloc = 0, char_class_alloc = 0;
+ #endif /* not RE_ENABLE_I18N */
+   int non_match = 0;
+@@ -3039,9 +3059,15 @@
+   int token_len;
+   int first_round = 1;
+ #ifdef _LIBC
++#if __OPTION_EGLIBC_LOCALE_CODE
+   collseqmb = (const unsigned char *)
+     _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+   nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++#else
++  /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the
++     compiler can't figure that out.  */
++  nrules = 0;
++#endif
+   if (nrules)
+     {
+       /*
+@@ -3169,7 +3195,7 @@
+ #else
+ # ifdef RE_ENABLE_I18N
+ 	  *err = build_range_exp (sbcset,
+-				  dfa->mb_cur_max > 1 ? mbcset : NULL,
++				  dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL,
+ 				  &range_alloc, &start_elem, &end_elem);
+ # else
+ 	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
+@@ -3185,7 +3211,7 @@
+ 	    case SB_CHAR:
+ 	      bitset_set (sbcset, start_elem.opr.ch);
+ 	      break;
+-#ifdef RE_ENABLE_I18N
++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
+ 	    case MB_CHAR:
+ 	      /* Check whether the array has enough space.  */
+ 	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
+@@ -3203,7 +3229,7 @@
+ 		}
+ 	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
+ 	      break;
+-#endif /* RE_ENABLE_I18N */
++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
+ 	    case EQUIV_CLASS:
+ 	      *err = build_equiv_class (sbcset,
+ #ifdef RE_ENABLE_I18N
+@@ -3253,11 +3279,11 @@
+ 
+ #ifdef RE_ENABLE_I18N
+   /* Ensure only single byte characters are set.  */
+-  if (dfa->mb_cur_max > 1)
++  if (dfa_mb_cur_max (dfa) > 1)
+     bitset_mask (sbcset, dfa->sb_char);
+ 
+   if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
+-      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
++      || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes
+ 						     || mbcset->non_match)))
+     {
+       bin_tree_t *mbc_tree;
+@@ -3326,7 +3352,7 @@
+ 		       re_token_t *token, int token_len, re_dfa_t *dfa,
+ 		       reg_syntax_t syntax, int accept_hyphen)
+ {
+-#ifdef RE_ENABLE_I18N
++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
+   int cur_char_size;
+   cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
+   if (cur_char_size > 1)
+@@ -3336,7 +3362,7 @@
+       re_string_skip_bytes (regexp, cur_char_size);
+       return REG_NOERROR;
+     }
+-#endif /* RE_ENABLE_I18N */
++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
+   re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+   if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
+       || token->type == OP_OPEN_EQUIV_CLASS)
+@@ -3416,7 +3442,9 @@
+ build_equiv_class (bitset_t sbcset, const unsigned char *name)
+ #endif /* not RE_ENABLE_I18N */
+ {
+-#ifdef _LIBC
++  /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale
++     is supported; it has no collation rules.  */
++#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
+   uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+   if (nrules != 0)
+     {
+@@ -3488,7 +3516,7 @@
+       mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
+     }
+   else
+-#endif /* _LIBC */
++#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
+     {
+       if (BE (strlen ((const char *) name) != 1, 0))
+ 	return REG_ECOLLATE;
+@@ -3522,7 +3550,7 @@
+       && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
+     name = "alpha";
+ 
+-#ifdef RE_ENABLE_I18N
++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
+   /* Check the space of the arrays.  */
+   if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
+     {
+@@ -3538,7 +3566,7 @@
+       *char_class_alloc = new_char_class_alloc;
+     }
+   mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
+-#endif /* RE_ENABLE_I18N */
++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
+ 
+ #define BUILD_CHARCLASS_LOOP(ctype_func)	\
+   do {						\
+@@ -3649,7 +3677,7 @@
+ 
+ #ifdef RE_ENABLE_I18N
+   /* Ensure only single byte characters are set.  */
+-  if (dfa->mb_cur_max > 1)
++  if (dfa_mb_cur_max (dfa) > 1)
+     bitset_mask (sbcset, dfa->sb_char);
+ #endif
+ 
+@@ -3661,7 +3689,7 @@
+     goto build_word_op_espace;
+ 
+ #ifdef RE_ENABLE_I18N
+-  if (dfa->mb_cur_max > 1)
++  if (dfa_mb_cur_max (dfa) > 1)
+     {
+       bin_tree_t *mbc_tree;
+       /* Build a tree for complex bracket.  */
+diff -Naur glibc-2.20/posix/regexec.c glibc-2.20-patch/posix/regexec.c
+--- glibc-2.20/posix/regexec.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/regexec.c	2015-03-04 00:51:32.387952006 -0600
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #include <stdint.h>
++#include <gnu/option-groups.h>
+ 
+ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
+ 				     int n) internal_function;
+@@ -186,11 +187,11 @@
+ static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
+ 				    const re_string_t *input, int idx)
+      internal_function;
+-# ifdef _LIBC
++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
+ static unsigned int find_collation_sequence_value (const unsigned char *mbs,
+ 						   size_t name_len)
+      internal_function;
+-# endif /* _LIBC */
++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
+ #endif /* RE_ENABLE_I18N */
+ static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
+ 				       const re_dfastate_t *state,
+@@ -255,25 +256,9 @@
+   return err != REG_NOERROR;
+ }
+ 
+-#ifdef _LIBC
+-# include <shlib-compat.h>
+-versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+-
+-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+-__typeof__ (__regexec) __compat_regexec;
+-
+-int
+-attribute_compat_text_section
+-__compat_regexec (const regex_t *__restrict preg,
+-		  const char *__restrict string, size_t nmatch,
+-		  regmatch_t pmatch[], int eflags)
+-{
+-  return regexec (preg, string, nmatch, pmatch,
+-		  eflags & (REG_NOTBOL | REG_NOTEOL));
+-}
+-compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
+-# endif
+-#endif
++/* EGLIBC: The code that used to be here was move to a separate file
++   so that it can be shared with xregex.c.  */
++#include "regexec-compat.c"
+ 
+ /* Entry points for GNU code.  */
+ 
+@@ -728,7 +713,7 @@
+   incr = (range < 0) ? -1 : 1;
+   left_lim = (range < 0) ? start + range : start;
+   right_lim = (range < 0) ? start : start + range;
+-  sb = dfa->mb_cur_max == 1;
++  sb = dfa_mb_cur_max (dfa) == 1;
+   match_kind =
+     (fastmap
+      ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
+@@ -3448,7 +3433,7 @@
+ 	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
+ 	    goto out_free;
+ 
+-	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
++	  if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1)
+ 	    need_word_trtable = 1;
+ 
+ 	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
+@@ -3590,7 +3575,7 @@
+       else if (type == OP_PERIOD)
+ 	{
+ #ifdef RE_ENABLE_I18N
+-	  if (dfa->mb_cur_max > 1)
++	  if (dfa_mb_cur_max (dfa) > 1)
+ 	    bitset_merge (accepts, dfa->sb_char);
+ 	  else
+ #endif
+@@ -3641,7 +3626,7 @@
+ 		  continue;
+ 		}
+ #ifdef RE_ENABLE_I18N
+-	      if (dfa->mb_cur_max > 1)
++	      if (dfa_mb_cur_max (dfa) > 1)
+ 		for (j = 0; j < BITSET_WORDS; ++j)
+ 		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
+ 	      else
+@@ -3660,7 +3645,7 @@
+ 		  continue;
+ 		}
+ #ifdef RE_ENABLE_I18N
+-	      if (dfa->mb_cur_max > 1)
++	      if (dfa_mb_cur_max (dfa) > 1)
+ 		for (j = 0; j < BITSET_WORDS; ++j)
+ 		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
+ 	      else
+@@ -3832,12 +3817,6 @@
+   if (node->type == COMPLEX_BRACKET)
+     {
+       const re_charset_t *cset = node->opr.mbcset;
+-# ifdef _LIBC
+-      const unsigned char *pin
+-	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+-      int j;
+-      uint32_t nrules;
+-# endif /* _LIBC */
+       int match_len = 0;
+       wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
+ 		    ? re_string_wchar_at (input, str_idx) : 0);
+@@ -3849,6 +3828,7 @@
+ 	    match_len = char_len;
+ 	    goto check_node_accept_bytes_match;
+ 	  }
++#if __OPTION_EGLIBC_LOCALE_CODE
+       /* match with character_class?  */
+       for (i = 0; i < cset->nchar_classes; ++i)
+ 	{
+@@ -3859,8 +3839,16 @@
+ 	      goto check_node_accept_bytes_match;
+ 	    }
+ 	}
++#endif
++
++      /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C
++         locale is supported; it has no collation rules.  */
++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
++      const unsigned char *pin
++	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
++      int j;
++      uint32_t nrules;
+ 
+-# ifdef _LIBC
+       nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+       if (nrules != 0)
+ 	{
+@@ -3953,8 +3941,12 @@
+ 	    }
+ 	}
+       else
+-# endif /* _LIBC */
++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
+ 	{
++          /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is
++             disabled, there can be no multibyte range endpoints, and
++             cset->nranges is always zero.  */
++#if __OPTION_EGLIBC_LOCALE_CODE
+ 	  /* match with range expression?  */
+ #if __GNUC__ >= 2
+ 	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
+@@ -3973,6 +3965,7 @@
+ 		  goto check_node_accept_bytes_match;
+ 		}
+ 	    }
++#endif /* __OPTION_EGLIBC_LOCALE_CODE */
+ 	}
+     check_node_accept_bytes_match:
+       if (!cset->non_match)
+@@ -3988,7 +3981,7 @@
+   return 0;
+ }
+ 
+-# ifdef _LIBC
++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
+ static unsigned int
+ internal_function
+ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
+@@ -4046,7 +4039,7 @@
+       return UINT_MAX;
+     }
+ }
+-# endif /* _LIBC */
++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
+ #endif /* RE_ENABLE_I18N */
+ 
+ /* Check whether the node accepts the byte which is IDX-th
+@@ -4137,7 +4130,7 @@
+   if (pstr->icase)
+     {
+ #ifdef RE_ENABLE_I18N
+-      if (pstr->mb_cur_max > 1)
++      if (string_mb_cur_max (pstr) > 1)
+ 	{
+ 	  ret = build_wcs_upper_buffer (pstr);
+ 	  if (BE (ret != REG_NOERROR, 0))
+@@ -4150,7 +4143,7 @@
+   else
+     {
+ #ifdef RE_ENABLE_I18N
+-      if (pstr->mb_cur_max > 1)
++      if (string_mb_cur_max (pstr) > 1)
+ 	build_wcs_buffer (pstr);
+       else
+ #endif /* RE_ENABLE_I18N  */
+diff -Naur glibc-2.20/posix/regexec-compat.c glibc-2.20-patch/posix/regexec-compat.c
+--- glibc-2.20/posix/regexec-compat.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/posix/regexec-compat.c	2015-03-04 00:51:32.388952006 -0600
+@@ -0,0 +1,39 @@
++/* Extended regular expression matching and search library.
++   Copyright (C) 2008 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Isamu Hasegawa <isamu at yamato.ibm.com>.
++
++   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.  */
++
++#ifdef _LIBC
++# include <shlib-compat.h>
++versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
++
++# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
++__typeof__ (__regexec) __compat_regexec;
++
++int
++attribute_compat_text_section
++__compat_regexec (const regex_t *__restrict preg,
++		  const char *__restrict string, size_t nmatch,
++		  regmatch_t pmatch[], int eflags)
++{
++  return regexec (preg, string, nmatch, pmatch,
++		  eflags & (REG_NOTBOL | REG_NOTEOL));
++}
++compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
++# endif
++#endif
+diff -Naur glibc-2.20/posix/regex.h glibc-2.20-patch/posix/regex.h
+--- glibc-2.20/posix/regex.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/regex.h	2015-03-04 00:51:32.388952006 -0600
+@@ -21,6 +21,7 @@
+ #define _REGEX_H 1
+ 
+ #include <sys/types.h>
++#include <gnu/option-groups.h>
+ 
+ /* Allow the use in C++ code.  */
+ #ifdef __cplusplus
+@@ -156,6 +157,8 @@
+    treated as 'a\{1'.  */
+ # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
+ 
++/* EGLIBC: Old regex implementation does not support these.  */
++# ifdef __OPTION_POSIX_REGEXP_GLIBC
+ /* If this bit is set, then ignore case when matching.
+    If not set, then case is significant.  */
+ # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
+@@ -172,6 +175,7 @@
+ /* If this bit is set, then no_sub will be set to 1 during
+    re_compile_pattern.  */
+ # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
++# endif /* __OPTION_POSIX_REGEXP_GLIBC */
+ #endif
+ 
+ /* This global variable defines the particular regexp syntax to use (for
+@@ -231,8 +235,13 @@
+   (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+    | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+ 
++#ifdef __OPTION_POSIX_REGEXP_GLIBC
+ #define RE_SYNTAX_POSIX_BASIC						\
+   (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
++#else
++#define RE_SYNTAX_POSIX_BASIC						\
++  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
++#endif
+ 
+ /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+    RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+@@ -298,9 +307,11 @@
+ /* Like REG_NOTBOL, except for the end-of-line.  */
+ #define REG_NOTEOL (1 << 1)
+ 
++#ifdef __OPTION_POSIX_REGEXP_GLIBC
+ /* Use PMATCH[0] to delimit the start and end of the search in the
+    buffer.  */
+ #define REG_STARTEND (1 << 2)
++#endif
+ 
+ 
+ /* If any error codes are removed, changed, or added, update the
+diff -Naur glibc-2.20/posix/regex_internal.c glibc-2.20-patch/posix/regex_internal.c
+--- glibc-2.20/posix/regex_internal.c	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/regex_internal.c	2015-03-04 00:51:32.388952006 -0600
+@@ -43,8 +43,8 @@
+   int init_buf_len;
+ 
+   /* Ensure at least one character fits into the buffers.  */
+-  if (init_len < dfa->mb_cur_max)
+-    init_len = dfa->mb_cur_max;
++  if (init_len < dfa_mb_cur_max (dfa))
++    init_len = dfa_mb_cur_max (dfa);
+   init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
+   re_string_construct_common (str, len, pstr, trans, icase, dfa);
+ 
+@@ -55,7 +55,7 @@
+   pstr->word_char = dfa->word_char;
+   pstr->word_ops_used = dfa->word_ops_used;
+   pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+-  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
++  pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len;
+   pstr->valid_raw_len = pstr->valid_len;
+   return REG_NOERROR;
+ }
+@@ -82,7 +82,7 @@
+   if (icase)
+     {
+ #ifdef RE_ENABLE_I18N
+-      if (dfa->mb_cur_max > 1)
++      if (dfa_mb_cur_max (dfa) > 1)
+ 	{
+ 	  while (1)
+ 	    {
+@@ -91,7 +91,7 @@
+ 		return ret;
+ 	      if (pstr->valid_raw_len >= len)
+ 		break;
+-	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
++	      if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa))
+ 		break;
+ 	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+ 	      if (BE (ret != REG_NOERROR, 0))
+@@ -105,7 +105,7 @@
+   else
+     {
+ #ifdef RE_ENABLE_I18N
+-      if (dfa->mb_cur_max > 1)
++      if (dfa_mb_cur_max (dfa) > 1)
+ 	build_wcs_buffer (pstr);
+       else
+ #endif /* RE_ENABLE_I18N  */
+@@ -130,7 +130,7 @@
+ re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
+ {
+ #ifdef RE_ENABLE_I18N
+-  if (pstr->mb_cur_max > 1)
++  if (string_mb_cur_max (pstr) > 1)
+     {
+       wint_t *new_wcs;
+ 
+@@ -177,7 +177,7 @@
+   pstr->trans = trans;
+   pstr->icase = icase ? 1 : 0;
+   pstr->mbs_allocated = (trans != NULL || icase);
+-  pstr->mb_cur_max = dfa->mb_cur_max;
++  pstr->mb_cur_max = dfa_mb_cur_max (dfa);
+   pstr->is_utf8 = dfa->is_utf8;
+   pstr->map_notascii = dfa->map_notascii;
+   pstr->stop = pstr->len;
+@@ -203,7 +203,7 @@
+ {
+ #ifdef _LIBC
+   unsigned char buf[MB_LEN_MAX];
+-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
++  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
+ #else
+   unsigned char buf[64];
+ #endif
+@@ -226,7 +226,7 @@
+ 	{
+ 	  int i, ch;
+ 
+-	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
++	  for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
+ 	    {
+ 	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
+ 	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
+@@ -275,7 +275,7 @@
+   size_t mbclen;
+ #ifdef _LIBC
+   char buf[MB_LEN_MAX];
+-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
++  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
+ #else
+   char buf[64];
+ #endif
+@@ -369,7 +369,7 @@
+ 	  {
+ 	    int i, ch;
+ 
+-	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
++	    for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
+ 	      {
+ 		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
+ 		buf[i] = pstr->trans[ch];
+@@ -567,8 +567,9 @@
+ }
+ 
+ /* This function re-construct the buffers.
+-   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
+-   convert to upper case in case of REG_ICASE, apply translation.  */
++   Concretely, convert to wide character in case of
++   string_mb_cur_max (pstr) > 1, convert to upper case in case of
++   REG_ICASE, apply translation.  */
+ 
+ static reg_errcode_t
+ internal_function __attribute_warn_unused_result__
+@@ -579,7 +580,7 @@
+     {
+       /* Reset buffer.  */
+ #ifdef RE_ENABLE_I18N
+-      if (pstr->mb_cur_max > 1)
++      if (string_mb_cur_max (pstr) > 1)
+ 	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+ #endif /* RE_ENABLE_I18N */
+       pstr->len = pstr->raw_len;
+@@ -670,7 +671,7 @@
+ 	      pstr->tip_context = re_string_context_at (pstr, offset - 1,
+ 							eflags);
+ #ifdef RE_ENABLE_I18N
+-	      if (pstr->mb_cur_max > 1)
++	      if (string_mb_cur_max (pstr) > 1)
+ 		memmove (pstr->wcs, pstr->wcs + offset,
+ 			 (pstr->valid_len - offset) * sizeof (wint_t));
+ #endif /* RE_ENABLE_I18N */
+@@ -699,7 +700,7 @@
+ #endif
+ 	  pstr->valid_len = 0;
+ #ifdef RE_ENABLE_I18N
+-	  if (pstr->mb_cur_max > 1)
++	  if (string_mb_cur_max (pstr) > 1)
+ 	    {
+ 	      int wcs_idx;
+ 	      wint_t wc = WEOF;
+@@ -711,7 +712,7 @@
+ 		  /* Special case UTF-8.  Multi-byte chars start with any
+ 		     byte other than 0x80 - 0xbf.  */
+ 		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+-		  end = raw + (offset - pstr->mb_cur_max);
++		  end = raw + (offset - string_mb_cur_max (pstr));
+ 		  if (end < pstr->raw_mbs)
+ 		    end = pstr->raw_mbs;
+ 		  p = raw + offset - 1;
+@@ -803,7 +804,7 @@
+ 
+   /* Then build the buffers.  */
+ #ifdef RE_ENABLE_I18N
+-  if (pstr->mb_cur_max > 1)
++  if (string_mb_cur_max (pstr) > 1)
+     {
+       if (pstr->icase)
+ 	{
+@@ -841,7 +842,7 @@
+     return re_string_peek_byte (pstr, idx);
+ 
+ #ifdef RE_ENABLE_I18N
+-  if (pstr->mb_cur_max > 1
++  if (string_mb_cur_max (pstr) > 1
+       && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
+     return re_string_peek_byte (pstr, idx);
+ #endif
+@@ -930,7 +931,7 @@
+     return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+ 	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
+ #ifdef RE_ENABLE_I18N
+-  if (input->mb_cur_max > 1)
++  if (string_mb_cur_max (input) > 1)
+     {
+       wint_t wc;
+       int wc_idx = idx;
+@@ -1444,7 +1445,7 @@
+   dfa->nodes[dfa->nodes_len].constraint = 0;
+ #ifdef RE_ENABLE_I18N
+   dfa->nodes[dfa->nodes_len].accept_mb =
+-    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
++    (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET;
+ #endif
+   dfa->nexts[dfa->nodes_len] = -1;
+   re_node_set_init_empty (dfa->edests + dfa->nodes_len);
+diff -Naur glibc-2.20/posix/regex_internal.h glibc-2.20-patch/posix/regex_internal.h
+--- glibc-2.20/posix/regex_internal.h	2014-09-07 03:09:09.000000000 -0500
++++ glibc-2.20-patch/posix/regex_internal.h	2015-03-04 00:51:32.388952006 -0600
+@@ -26,6 +26,10 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
++#if defined _LIBC
++# include <gnu/option-groups.h>
++#endif
++
+ #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
+ # include <langinfo.h>
+ #endif
+@@ -370,6 +374,13 @@
+ };
+ typedef struct re_string_t re_string_t;
+ 
++/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
++   help the compiler make use of that fact.  */
++#if __OPTION_EGLIBC_LOCALE_CODE
++# define string_mb_cur_max(str) ((str)->mb_cur_max + 0)
++#else
++# define string_mb_cur_max(str) (1)
++#endif
+ 
+ struct re_dfa_t;
+ typedef struct re_dfa_t re_dfa_t;
+@@ -655,6 +666,14 @@
+   __libc_lock_define (, lock)
+ };
+ 
++/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
++   help the compiler make use of that fact.  */
++#if __OPTION_EGLIBC_LOCALE_CODE
++# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0)
++#else
++# define dfa_mb_cur_max(dfa) (1)
++#endif
++
+ #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
+ #define re_node_set_remove(set,id) \
+   (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
+@@ -715,7 +734,7 @@
+ re_string_char_size_at (const re_string_t *pstr, int idx)
+ {
+   int byte_idx;
+-  if (pstr->mb_cur_max == 1)
++  if (string_mb_cur_max (pstr) == 1)
+     return 1;
+   for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
+     if (pstr->wcs[idx + byte_idx] != WEOF)
+@@ -727,7 +746,7 @@
+ internal_function __attribute__ ((pure, unused))
+ re_string_wchar_at (const re_string_t *pstr, int idx)
+ {
+-  if (pstr->mb_cur_max == 1)
++  if (string_mb_cur_max (pstr) == 1)
+     return (wint_t) pstr->mbs[idx];
+   return (wint_t) pstr->wcs[idx];
+ }
+diff -Naur glibc-2.20/posix/xregex.c glibc-2.20-patch/posix/xregex.c
+--- glibc-2.20/posix/xregex.c	1969-12-31 18:00:00.000000000 -0600
++++ glibc-2.20-patch/posix/xregex.c	2015-03-04 00:51:32.416952006 -0600
+@@ -0,0 +1,8212 @@
++/* Extended regular expression matching and search library,
++   version 0.12.
++   (Implements POSIX draft P1003.2/D11.2, except for some of the
++   internationalization features.)
++
++   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
++   2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
++   02110-1301 USA.  */
++
++/* AIX requires this to be the first thing in the file. */
++#if defined _AIX && !defined __GNUC__ && !defined REGEX_MALLOC
++  #pragma alloca
++#endif
++
++#undef	_GNU_SOURCE
++#define _GNU_SOURCE
++
++#ifndef INSIDE_RECURSION
++# ifdef HAVE_CONFIG_H
++#  include <config.h>
++# endif
++#endif
++
++/*#include <ansidecl.h>*/
++
++#ifndef INSIDE_RECURSION
++
++# if defined STDC_HEADERS && !defined emacs
++#  include <stddef.h>
++# else
++/* We need this for `regex.h', and perhaps for the Emacs include files.  */
++#  include <sys/types.h>
++# endif
++
++# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
++
++/* For platform which support the ISO C amendement 1 functionality we
++   support user defined character classes.  */
++# if WIDE_CHAR_SUPPORT
++/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
++#  include <wchar.h>
++#  include <wctype.h>
++# endif
++
++# ifdef _LIBC
++/* We have to keep the namespace clean.  */
++#  define regfree(preg) __regfree (preg)
++#  define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
++#  define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
++#  define regerror(errcode, preg, errbuf, errbuf_size) \
++	__regerror(errcode, preg, errbuf, errbuf_size)
++#  define re_set_registers(bu, re, nu, st, en) \
++	__re_set_registers (bu, re, nu, st, en)
++#  define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
++	__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
++#  define re_match(bufp, string, size, pos, regs) \
++	__re_match (bufp, string, size, pos, regs)
++#  define re_search(bufp, string, size, startpos, range, regs) \
++	__re_search (bufp, string, size, startpos, range, regs)
++#  define re_compile_pattern(pattern, length, bufp) \
++	__re_compile_pattern (pattern, length, bufp)
++#  define re_set_syntax(syntax) __re_set_syntax (syntax)
++#  define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
++	__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
++#  define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
++
++#  define btowc __btowc
++
++/* We are also using some library internals.  */
++#  include <locale/localeinfo.h>
++#  include <locale/elem-hash.h>
++#  include <langinfo.h>
++#  include <locale/coll-lookup.h>
++# endif
++
++/* This is for other GNU distributions with internationalized messages.  */
++# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
++#  include <libintl.h>
++#  ifdef _LIBC
++#   undef gettext
++#   define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES)
++#  endif
++# else
++#  define gettext(msgid) (msgid)
++# endif
++
++# ifndef gettext_noop
++/* This define is so xgettext can find the internationalizable
++   strings.  */
++#  define gettext_noop(String) String
++# endif
++
++/* The `emacs' switch turns on certain matching commands
++   that make sense only in Emacs. */
++# ifdef emacs
++
++#  include "lisp.h"
++#  include "buffer.h"
++#  include "syntax.h"
++
++# else  /* not emacs */
++
++/* If we are not linking with Emacs proper,
++   we can't use the relocating allocator
++   even if config.h says that we can.  */
++#  undef REL_ALLOC
++
++#  if defined STDC_HEADERS || defined _LIBC
++#   include <stdlib.h>
++#  else
++char *malloc ();
++char *realloc ();
++#  endif
++
++/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
++   If nothing else has been done, use the method below.  */
++#  ifdef INHIBIT_STRING_HEADER
++#   if !(defined HAVE_BZERO && defined HAVE_BCOPY)
++#    if !defined bzero && !defined bcopy
++#     undef INHIBIT_STRING_HEADER
++#    endif
++#   endif
++#  endif
++
++/* This is the normal way of making sure we have a bcopy and a bzero.
++   This is used in most programs--a few other programs avoid this
++   by defining INHIBIT_STRING_HEADER.  */
++#  ifndef INHIBIT_STRING_HEADER
++#   if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
++#    include <string.h>
++#    ifndef bzero
++#     ifndef _LIBC
++#      define bzero(s, n)	(memset (s, '\0', n), (s))
++#     else
++#      define bzero(s, n)	__bzero (s, n)
++#     endif
++#    endif
++#   else
++#    include <strings.h>
++#    ifndef memcmp
++#     define memcmp(s1, s2, n)	bcmp (s1, s2, n)
++#    endif
++#    ifndef memcpy
++#     define memcpy(d, s, n)	(bcopy (s, d, n), (d))
++#    endif
++#   endif
++#  endif
++
++/* Define the syntax stuff for \<, \>, etc.  */
++
++/* This must be nonzero for the wordchar and notwordchar pattern
++   commands in re_match_2.  */
++#  ifndef Sword
++#   define Sword 1
++#  endif
++
++#  ifdef SWITCH_ENUM_BUG
++#   define SWITCH_ENUM_CAST(x) ((int)(x))
++#  else
++#   define SWITCH_ENUM_CAST(x) (x)
++#  endif
++
++# endif /* not emacs */
++
++# if defined _LIBC || HAVE_LIMITS_H
++#  include <limits.h>
++# endif
++
++# ifndef MB_LEN_MAX
++#  define MB_LEN_MAX 1
++# endif
++
++/* Get the interface, including the syntax bits.  */
++# include "regex.h"
++
++/* isalpha etc. are used for the character classes.  */
++# include <ctype.h>
++
++/* Jim Meyering writes:
++
++   "... Some ctype macros are valid only for character codes that
++   isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
++   using /bin/cc or gcc but without giving an ansi option).  So, all
++   ctype uses should be through macros like ISPRINT...  If
++   STDC_HEADERS is defined, then autoconf has verified that the ctype
++   macros don't need to be guarded with references to isascii. ...
++   Defining isascii to 1 should let any compiler worth its salt
++   eliminate the && through constant folding."
++   Solaris defines some of these symbols so we must undefine them first.  */
++
++# undef ISASCII
++# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
++#  define ISASCII(c) 1
++# else
++#  define ISASCII(c) isascii(c)
++# endif
++
++# ifdef isblank
++#  define ISBLANK(c) (ISASCII (c) && isblank (c))
++# else
++#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
++# endif
++# ifdef isgraph
++#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
++# else
++#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
++# endif
++
++# undef ISPRINT
++# define ISPRINT(c) (ISASCII (c) && isprint (c))
++# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
++# define ISALNUM(c) (ISASCII (c) && isalnum (c))
++# define ISALPHA(c) (ISASCII (c) && isalpha (c))
++# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
++# define ISLOWER(c) (ISASCII (c) && islower (c))
++# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
++# define ISSPACE(c) (ISASCII (c) && isspace (c))
++# define ISUPPER(c) (ISASCII (c) && isupper (c))
++# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
++
++# ifdef _tolower
++#  define TOLOWER(c) _tolower(c)
++# else
++#  define TOLOWER(c) tolower(c)
++# endif
++
++# ifndef NULL
++#  define NULL (void *)0
++# endif
++
++/* We remove any previous definition of `SIGN_EXTEND_CHAR',
++   since ours (we hope) works properly with all combinations of
++   machines, compilers, `char' and `unsigned char' argument types.
++   (Per Bothner suggested the basic approach.)  */
++# undef SIGN_EXTEND_CHAR
++# if __STDC__
++#  define SIGN_EXTEND_CHAR(c) ((signed char) (c))
++# else  /* not __STDC__ */
++/* As in Harbison and Steele.  */
++#  define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
++# endif
++
++# ifndef emacs
++/* How many characters in the character set.  */
++#  define CHAR_SET_SIZE 256
++
++#  ifdef SYNTAX_TABLE
++
++extern char *re_syntax_table;
++
++#  else /* not SYNTAX_TABLE */
++
++static char re_syntax_table[CHAR_SET_SIZE];
++
++static void init_syntax_once (void);
++
++static void
++init_syntax_once (void)
++{
++   register int c;
++   static int done = 0;
++
++   if (done)
++     return;
++   bzero (re_syntax_table, sizeof re_syntax_table);
++
++   for (c = 0; c < CHAR_SET_SIZE; ++c)
++     if (ISALNUM (c))
++	re_syntax_table[c] = Sword;
++
++   re_syntax_table['_'] = Sword;
++
++   done = 1;
++}
++
++#  endif /* not SYNTAX_TABLE */
++
++#  define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
++
++# endif /* emacs */
++
++/* Integer type for pointers.  */
++# if !defined _LIBC && !defined HAVE_UINTPTR_T
++typedef unsigned long int uintptr_t;
++# endif
++
++/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
++   use `alloca' instead of `malloc'.  This is because using malloc in
++   re_search* or re_match* could cause memory leaks when C-g is used in
++   Emacs; also, malloc is slower and causes storage fragmentation.  On
++   the other hand, malloc is more portable, and easier to debug.
++
++   Because we sometimes use alloca, some routines have to be macros,
++   not functions -- `alloca'-allocated space disappears at the end of the
++   function it is called in.  */
++
++# ifdef REGEX_MALLOC
++
++#  define REGEX_ALLOCATE malloc
++#  define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
++#  define REGEX_FREE free
++
++# else /* not REGEX_MALLOC  */
++
++/* Emacs already defines alloca, sometimes.  */
++#  ifndef alloca
++
++/* Make alloca work the best possible way.  */
++#   ifdef __GNUC__
++#    define alloca __builtin_alloca
++#   else /* not __GNUC__ */
++#    if HAVE_ALLOCA_H
++#     include <alloca.h>
++#    endif /* HAVE_ALLOCA_H */
++#   endif /* not __GNUC__ */
++
++#  endif /* not alloca */
++
++#  define REGEX_ALLOCATE alloca
++
++/* Assumes a `char *destination' variable.  */
++#  define REGEX_REALLOCATE(source, osize, nsize)			\
++  (destination = (char *) alloca (nsize),				\
++   memcpy (destination, source, osize))
++
++/* No need to do anything to free, after alloca.  */
++#  define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
++
++# endif /* not REGEX_MALLOC */
++
++/* Define how to allocate the failure stack.  */
++
++# if defined REL_ALLOC && defined REGEX_MALLOC
++
++#  define REGEX_ALLOCATE_STACK(size)				\
++  r_alloc (&failure_stack_ptr, (size))
++#  define REGEX_REALLOCATE_STACK(source, osize, nsize)		\
++  r_re_alloc (&failure_stack_ptr, (nsize))
++#  define REGEX_FREE_STACK(ptr)					\
++  r_alloc_free (&failure_stack_ptr)
++
++# else /* not using relocating allocator */
++
++#  ifdef REGEX_MALLOC
++
++#   define REGEX_ALLOCATE_STACK malloc
++#   define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
++#   define REGEX_FREE_STACK free
++
++#  else /* not REGEX_MALLOC */
++
++#   define REGEX_ALLOCATE_STACK alloca
++
++#   define REGEX_REALLOCATE_STACK(source, osize, nsize)			\
++   REGEX_REALLOCATE (source, osize, nsize)
++/* No need to explicitly free anything.  */
++#   define REGEX_FREE_STACK(arg)
++
++#  endif /* not REGEX_MALLOC */
++# endif /* not using relocating allocator */
++
++
++/* True if `size1' is non-NULL and PTR is pointing anywhere inside
++   `string1' or just past its end.  This works if PTR is NULL, which is
++   a good thing.  */
++# define FIRST_STRING_P(ptr) 					\
++  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
++
++/* (Re)Allocate N items of type T using malloc, or fail.  */
++# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
++# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
++# define RETALLOC_IF(addr, n, t) \
++  if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
++# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
++
++# define BYTEWIDTH 8 /* In bits.  */
++
++# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
++
++# undef MAX
++# undef MIN
++# define MAX(a, b) ((a) > (b) ? (a) : (b))
++# define MIN(a, b) ((a) < (b) ? (a) : (b))
++
++typedef char boolean;
++# define false 0
++# define true 1
++
++static reg_errcode_t byte_regex_compile (const char *pattern, size_t size,
++                                         reg_syntax_t syntax,
++                                         struct re_pattern_buffer *bufp);
++
++static int byte_re_match_2_internal (struct re_pattern_buffer *bufp,
++                                     const char *string1, int size1,
++                                     const char *string2, int size2,
++                                     int pos,
++                                     struct re_registers *regs,
++                                     int stop);
++static int byte_re_search_2 (struct re_pattern_buffer *bufp,
++                             const char *string1, int size1,
++                             const char *string2, int size2,
++                             int startpos, int range,
++                             struct re_registers *regs, int stop);
++static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp);
++
++#ifdef MBS_SUPPORT
++static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size,
++                                        reg_syntax_t syntax,
++                                        struct re_pattern_buffer *bufp);
++
++
++static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
++                                    const char *cstring1, int csize1,
++                                    const char *cstring2, int csize2,
++                                    int pos,
++                                    struct re_registers *regs,
++                                    int stop,
++                                    wchar_t *string1, int size1,
++                                    wchar_t *string2, int size2,
++                                    int *mbs_offset1, int *mbs_offset2);
++static int wcs_re_search_2 (struct re_pattern_buffer *bufp,
++                            const char *string1, int size1,
++                            const char *string2, int size2,
++                            int startpos, int range,
++                            struct re_registers *regs, int stop);
++static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp);
++#endif
++
++/* These are the command codes that appear in compiled regular
++   expressions.  Some opcodes are followed by argument bytes.  A
++   command code can specify any interpretation whatsoever for its
++   arguments.  Zero bytes may appear in the compiled regular expression.  */
++
++typedef enum
++{
++  no_op = 0,
++
++  /* Succeed right away--no more backtracking.  */
++  succeed,
++
++        /* Followed by one byte giving n, then by n literal bytes.  */
++  exactn,
++
++# ifdef MBS_SUPPORT
++	/* Same as exactn, but contains binary data.  */
++  exactn_bin,
++# endif
++
++        /* Matches any (more or less) character.  */
++  anychar,
++
++        /* Matches any one char belonging to specified set.  First
++           following byte is number of bitmap bytes.  Then come bytes
++           for a bitmap saying which chars are in.  Bits in each byte
++           are ordered low-bit-first.  A character is in the set if its
++           bit is 1.  A character too large to have a bit in the map is
++           automatically not in the set.  */
++        /* ifdef MBS_SUPPORT, following element is length of character
++	   classes, length of collating symbols, length of equivalence
++	   classes, length of character ranges, and length of characters.
++	   Next, character class element, collating symbols elements,
++	   equivalence class elements, range elements, and character
++	   elements follow.
++	   See regex_compile function.  */
++  charset,
++
++        /* Same parameters as charset, but match any character that is
++           not one of those specified.  */
++  charset_not,
++
++        /* Start remembering the text that is matched, for storing in a
++           register.  Followed by one byte with the register number, in
++           the range 0 to one less than the pattern buffer's re_nsub
++           field.  Then followed by one byte with the number of groups
++           inner to this one.  (This last has to be part of the
++           start_memory only because we need it in the on_failure_jump
++           of re_match_2.)  */
++  start_memory,
++
++        /* Stop remembering the text that is matched and store it in a
++           memory register.  Followed by one byte with the register
++           number, in the range 0 to one less than `re_nsub' in the
++           pattern buffer, and one byte with the number of inner groups,
++           just like `start_memory'.  (We need the number of inner
++           groups here because we don't have any easy way of finding the
++           corresponding start_memory when we're at a stop_memory.)  */
++  stop_memory,
++
++        /* Match a duplicate of something remembered. Followed by one
++           byte containing the register number.  */
++  duplicate,
++
++        /* Fail unless at beginning of line.  */
++  begline,
++
++        /* Fail unless at end of line.  */
++  endline,
++
++        /* Succeeds if at beginning of buffer (if emacs) or at beginning
++           of string to be matched (if not).  */
++  begbuf,
++
++        /* Analogously, for end of buffer/string.  */
++  endbuf,
++
++        /* Followed by two byte relative address to which to jump.  */
++  jump,
++
++	/* Same as jump, but marks the end of an alternative.  */
++  jump_past_alt,
++
++        /* Followed by two-byte relative address of place to resume at
++           in case of failure.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  on_failure_jump,
++
++        /* Like on_failure_jump, but pushes a placeholder instead of the
++           current string position when executed.  */
++  on_failure_keep_string_jump,
++
++        /* Throw away latest failure point and then jump to following
++           two-byte relative address.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  pop_failure_jump,
++
++        /* Change to pop_failure_jump if know won't have to backtrack to
++           match; otherwise change to jump.  This is used to jump
++           back to the beginning of a repeat.  If what follows this jump
++           clearly won't match what the repeat does, such that we can be
++           sure that there is no use backtracking out of repetitions
++           already matched, then we change it to a pop_failure_jump.
++           Followed by two-byte address.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  maybe_pop_jump,
++
++        /* Jump to following two-byte address, and push a dummy failure
++           point. This failure point will be thrown away if an attempt
++           is made to use it for a failure.  A `+' construct makes this
++           before the first repeat.  Also used as an intermediary kind
++           of jump when compiling an alternative.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  dummy_failure_jump,
++
++	/* Push a dummy failure point and continue.  Used at the end of
++	   alternatives.  */
++  push_dummy_failure,
++
++        /* Followed by two-byte relative address and two-byte number n.
++           After matching N times, jump to the address upon failure.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  succeed_n,
++
++        /* Followed by two-byte relative address, and two-byte number n.
++           Jump to the address N times, then fail.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  jump_n,
++
++        /* Set the following two-byte relative address to the
++           subsequent two-byte number.  The address *includes* the two
++           bytes of number.  */
++        /* ifdef MBS_SUPPORT, the size of address is 1.  */
++  set_number_at,
++
++  wordchar,	/* Matches any word-constituent character.  */
++  notwordchar,	/* Matches any char that is not a word-constituent.  */
++
++  wordbeg,	/* Succeeds if at word beginning.  */
++  wordend,	/* Succeeds if at word end.  */
++
++  wordbound,	/* Succeeds if at a word boundary.  */
++  notwordbound	/* Succeeds if not at a word boundary.  */
++
++# ifdef emacs
++  ,before_dot,	/* Succeeds if before point.  */
++  at_dot,	/* Succeeds if at point.  */
++  after_dot,	/* Succeeds if after point.  */
++
++	/* Matches any character whose syntax is specified.  Followed by
++           a byte which contains a syntax code, e.g., Sword.  */
++  syntaxspec,
++
++	/* Matches any character whose syntax is not that specified.  */
++  notsyntaxspec
++# endif /* emacs */
++} re_opcode_t;
++#endif /* not INSIDE_RECURSION */
++
++
++#ifdef BYTE
++# define CHAR_T char
++# define UCHAR_T unsigned char
++# define COMPILED_BUFFER_VAR bufp->buffer
++# define OFFSET_ADDRESS_SIZE 2
++# define PREFIX(name) byte_##name
++# define ARG_PREFIX(name) name
++# define PUT_CHAR(c) putchar (c)
++#else
++# ifdef WCHAR
++#  define CHAR_T wchar_t
++#  define UCHAR_T wchar_t
++#  define COMPILED_BUFFER_VAR wc_buffer
++#  define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */
++#  define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1)
++#  define PREFIX(name) wcs_##name
++#  define ARG_PREFIX(name) c##name
++/* Should we use wide stream??  */
++#  define PUT_CHAR(c) printf ("%C", c);
++#  define TRUE 1
++#  define FALSE 0
++# else
++#  ifdef MBS_SUPPORT
++#   define WCHAR
++#   define INSIDE_RECURSION
++#   include "xregex.c"
++#   undef INSIDE_RECURSION
++#  endif
++#  define BYTE
++#  define INSIDE_RECURSION
++#  include "xregex.c"
++#  undef INSIDE_RECURSION
++# endif
++#endif
++
++#ifdef INSIDE_RECURSION
++/* Common operations on the compiled pattern.  */
++
++/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
++
++# ifdef WCHAR
++#  define STORE_NUMBER(destination, number)				\
++  do {									\
++    *(destination) = (UCHAR_T)(number);				\
++  } while (0)
++# else /* BYTE */
++#  define STORE_NUMBER(destination, number)				\
++  do {									\
++    (destination)[0] = (number) & 0377;					\
++    (destination)[1] = (number) >> 8;					\
++  } while (0)
++# endif /* WCHAR */
++
++/* Same as STORE_NUMBER, except increment DESTINATION to
++   the byte after where the number is stored.  Therefore, DESTINATION
++   must be an lvalue.  */
++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
++
++# define STORE_NUMBER_AND_INCR(destination, number)			\
++  do {									\
++    STORE_NUMBER (destination, number);					\
++    (destination) += OFFSET_ADDRESS_SIZE;				\
++  } while (0)
++
++/* Put into DESTINATION a number stored in two contiguous bytes starting
++   at SOURCE.  */
++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element.  */
++
++# ifdef WCHAR
++#  define EXTRACT_NUMBER(destination, source)				\
++  do {									\
++    (destination) = *(source);						\
++  } while (0)
++# else /* BYTE */
++#  define EXTRACT_NUMBER(destination, source)				\
++  do {									\
++    (destination) = *(source) & 0377;					\
++    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;		\
++  } while (0)
++# endif
++
++# ifdef DEBUG
++static void PREFIX(extract_number) (int *dest, UCHAR_T *source);
++static void
++PREFIX(extract_number) (int *dest, UCHAR_T *source)
++{
++#  ifdef WCHAR
++  *dest = *source;
++#  else /* BYTE */
++  int temp = SIGN_EXTEND_CHAR (*(source + 1));
++  *dest = *source & 0377;
++  *dest += temp << 8;
++#  endif
++}
++
++#  ifndef EXTRACT_MACROS /* To debug the macros.  */
++#   undef EXTRACT_NUMBER
++#   define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src)
++#  endif /* not EXTRACT_MACROS */
++
++# endif /* DEBUG */
++
++/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
++   SOURCE must be an lvalue.  */
++
++# define EXTRACT_NUMBER_AND_INCR(destination, source)			\
++  do {									\
++    EXTRACT_NUMBER (destination, source);				\
++    (source) += OFFSET_ADDRESS_SIZE; 					\
++  } while (0)
++
++# ifdef DEBUG
++static void PREFIX(extract_number_and_incr) (int *destination,
++                                             UCHAR_T **source);
++static void
++PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source)
++{
++  PREFIX(extract_number) (destination, *source);
++  *source += OFFSET_ADDRESS_SIZE;
++}
++
++#  ifndef EXTRACT_MACROS
++#   undef EXTRACT_NUMBER_AND_INCR
++#   define EXTRACT_NUMBER_AND_INCR(dest, src) \
++  PREFIX(extract_number_and_incr) (&dest, &src)
++#  endif /* not EXTRACT_MACROS */
++
++# endif /* DEBUG */
++
++
++
++/* If DEBUG is defined, Regex prints many voluminous messages about what
++   it is doing (if the variable `debug' is nonzero).  If linked with the
++   main program in `iregex.c', you can enter patterns and strings
++   interactively.  And if linked with the main program in `main.c' and
++   the other test files, you can run the already-written tests.  */
++
++# ifdef DEBUG
++
++#  ifndef DEFINED_ONCE
++
++/* We use standard I/O for debugging.  */
++#   include <stdio.h>
++
++/* It is useful to test things that ``must'' be true when debugging.  */
++#   include <assert.h>
++
++static int debug;
++
++#   define DEBUG_STATEMENT(e) e
++#   define DEBUG_PRINT1(x) if (debug) printf (x)
++#   define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
++#   define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
++#   define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
++#  endif /* not DEFINED_ONCE */
++
++#  define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 			\
++  if (debug) PREFIX(print_partial_compiled_pattern) (s, e)
++#  define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)		\
++  if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2)
++
++
++/* Print the fastmap in human-readable form.  */
++
++#  ifndef DEFINED_ONCE
++void
++print_fastmap (char *fastmap)
++{
++  unsigned was_a_range = 0;
++  unsigned i = 0;
++
++  while (i < (1 << BYTEWIDTH))
++    {
++      if (fastmap[i++])
++	{
++	  was_a_range = 0;
++          putchar (i - 1);
++          while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
++            {
++              was_a_range = 1;
++              i++;
++            }
++	  if (was_a_range)
++            {
++              printf ("-");
++              putchar (i - 1);
++            }
++        }
++    }
++  putchar ('\n');
++}
++#  endif /* not DEFINED_ONCE */
++
++
++/* Print a compiled pattern string in human-readable form, starting at
++   the START pointer into it and ending just before the pointer END.  */
++
++void
++PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end)
++{
++  int mcnt, mcnt2;
++  UCHAR_T *p1;
++  UCHAR_T *p = start;
++  UCHAR_T *pend = end;
++
++  if (start == NULL)
++    {
++      printf ("(null)\n");
++      return;
++    }
++
++  /* Loop over pattern commands.  */
++  while (p < pend)
++    {
++#  ifdef _LIBC
++      printf ("%td:\t", p - start);
++#  else
++      printf ("%ld:\t", (long int) (p - start));
++#  endif
++
++      switch ((re_opcode_t) *p++)
++	{
++        case no_op:
++          printf ("/no_op");
++          break;
++
++	case exactn:
++	  mcnt = *p++;
++          printf ("/exactn/%d", mcnt);
++          do
++	    {
++              putchar ('/');
++	      PUT_CHAR (*p++);
++            }
++          while (--mcnt);
++          break;
++
++#  ifdef MBS_SUPPORT
++	case exactn_bin:
++	  mcnt = *p++;
++	  printf ("/exactn_bin/%d", mcnt);
++          do
++	    {
++	      printf("/%lx", (long int) *p++);
++            }
++          while (--mcnt);
++          break;
++#  endif /* MBS_SUPPORT */
++
++	case start_memory:
++          mcnt = *p++;
++          printf ("/start_memory/%d/%ld", mcnt, (long int) *p++);
++          break;
++
++	case stop_memory:
++          mcnt = *p++;
++	  printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++);
++          break;
++
++	case duplicate:
++	  printf ("/duplicate/%ld", (long int) *p++);
++	  break;
++
++	case anychar:
++	  printf ("/anychar");
++	  break;
++
++	case charset:
++        case charset_not:
++          {
++#  ifdef WCHAR
++	    int i, length;
++	    wchar_t *workp = p;
++	    printf ("/charset [%s",
++	            (re_opcode_t) *(workp - 1) == charset_not ? "^" : "");
++	    p += 5;
++	    length = *workp++; /* the length of char_classes */
++	    for (i=0 ; i<length ; i++)
++	      printf("[:%lx:]", (long int) *p++);
++	    length = *workp++; /* the length of collating_symbol */
++	    for (i=0 ; i<length ;)
++	      {
++		printf("[.");
++		while(*p != 0)
++		  PUT_CHAR((i++,*p++));
++		i++,p++;
++		printf(".]");
++	      }
++	    length = *workp++; /* the length of equivalence_class */
++	    for (i=0 ; i<length ;)
++	      {
++		printf("[=");
++		while(*p != 0)
++		  PUT_CHAR((i++,*p++));
++		i++,p++;
++		printf("=]");
++	      }
++	    length = *workp++; /* the length of char_range */
++	    for (i=0 ; i<length ; i++)
++	      {
++		wchar_t range_start = *p++;
++		wchar_t range_end = *p++;
++		printf("%C-%C", range_start, range_end);
++	      }
++	    length = *workp++; /* the length of char */
++	    for (i=0 ; i<length ; i++)
++	      printf("%C", *p++);
++	    putchar (']');
++#  else
++            register int c, last = -100;
++	    register int in_range = 0;
++
++	    printf ("/charset [%s",
++	            (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
++
++            assert (p + *p < pend);
++
++            for (c = 0; c < 256; c++)
++	      if (c / 8 < *p
++		  && (p[1 + (c/8)] & (1 << (c % 8))))
++		{
++		  /* Are we starting a range?  */
++		  if (last + 1 == c && ! in_range)
++		    {
++		      putchar ('-');
++		      in_range = 1;
++		    }
++		  /* Have we broken a range?  */
++		  else if (last + 1 != c && in_range)
++              {
++		      putchar (last);
++		      in_range = 0;
++		    }
++
++		  if (! in_range)
++		    putchar (c);
++
++		  last = c;
++              }
++
++	    if (in_range)
++	      putchar (last);
++
++	    putchar (']');
++
++	    p += 1 + *p;
++#  endif /* WCHAR */
++	  }
++	  break;
++
++	case begline:
++	  printf ("/begline");
++          break;
++
++	case endline:
++          printf ("/endline");
++          break;
++
++	case on_failure_jump:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/on_failure_jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
++#  endif
++          break;
++
++	case on_failure_keep_string_jump:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/on_failure_keep_string_jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/on_failure_keep_string_jump to %ld",
++		  (long int) (p + mcnt - start));
++#  endif
++          break;
++
++	case dummy_failure_jump:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/dummy_failure_jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
++#  endif
++          break;
++
++	case push_dummy_failure:
++          printf ("/push_dummy_failure");
++          break;
++
++        case maybe_pop_jump:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/maybe_pop_jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
++#  endif
++	  break;
++
++        case pop_failure_jump:
++	  PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/pop_failure_jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
++#  endif
++	  break;
++
++        case jump_past_alt:
++	  PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/jump_past_alt to %td", p + mcnt - start);
++#  else
++  	  printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
++#  endif
++	  break;
++
++        case jump:
++	  PREFIX(extract_number_and_incr) (&mcnt, &p);
++#  ifdef _LIBC
++  	  printf ("/jump to %td", p + mcnt - start);
++#  else
++  	  printf ("/jump to %ld", (long int) (p + mcnt - start));
++#  endif
++	  break;
++
++        case succeed_n:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++	  p1 = p + mcnt;
++          PREFIX(extract_number_and_incr) (&mcnt2, &p);
++#  ifdef _LIBC
++	  printf ("/succeed_n to %td, %d times", p1 - start, mcnt2);
++#  else
++	  printf ("/succeed_n to %ld, %d times",
++		  (long int) (p1 - start), mcnt2);
++#  endif
++          break;
++
++        case jump_n:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++	  p1 = p + mcnt;
++          PREFIX(extract_number_and_incr) (&mcnt2, &p);
++	  printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
++          break;
++
++        case set_number_at:
++          PREFIX(extract_number_and_incr) (&mcnt, &p);
++	  p1 = p + mcnt;
++          PREFIX(extract_number_and_incr) (&mcnt2, &p);
++#  ifdef _LIBC
++	  printf ("/set_number_at location %td to %d", p1 - start, mcnt2);
++#  else
++	  printf ("/set_number_at location %ld to %d",
++		  (long int) (p1 - start), mcnt2);
++#  endif
++          break;
++
++        case wordbound:
++	  printf ("/wordbound");
++	  break;
++
++	case notwordbound:
++	  printf ("/notwordbound");
++          break;
++
++	case wordbeg:
++	  printf ("/wordbeg");
++	  break;
++
++	case wordend:
++	  printf ("/wordend");
++	  break;
++
++#  ifdef emacs
++	case before_dot:
++	  printf ("/before_dot");
++          break;
++
++	case at_dot:
++	  printf ("/at_dot");
++          break;
++
++	case after_dot:
++	  printf ("/after_dot");
++          break;
++
++	case syntaxspec:
++          printf ("/syntaxspec");
++	  mcnt = *p++;
++	  printf ("/%d", mcnt);
++          break;
++
++	case notsyntaxspec:
++          printf ("/notsyntaxspec");
++	  mcnt = *p++;
++	  printf ("/%d", mcnt);
++	  break;
++#  endif /* emacs */
++
++	case wordchar:
++	  printf ("/wordchar");
++          break;
++
++	case notwordchar:
++	  printf ("/notwordchar");
++          break;
++
++	case begbuf:
++	  printf ("/begbuf");
++          break;
++
++	case endbuf:
++	  printf ("/endbuf");
++          break;
++
++        default:
++          printf ("?%ld", (long int) *(p-1));
++	}
++
++      putchar ('\n');
++    }
++
++#  ifdef _LIBC
++  printf ("%td:\tend of pattern.\n", p - start);
++#  else
++  printf ("%ld:\tend of pattern.\n", (long int) (p - start));
++#  endif
++}
++
++
++void
++PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp)
++{
++  UCHAR_T *buffer = (UCHAR_T*) bufp->buffer;
++
++  PREFIX(print_partial_compiled_pattern) (buffer, buffer
++				  + bufp->used / sizeof(UCHAR_T));
++  printf ("%ld bytes used/%ld bytes allocated.\n",
++	  bufp->used, bufp->allocated);
++
++  if (bufp->fastmap_accurate && bufp->fastmap)
++    {
++      printf ("fastmap: ");
++      print_fastmap (bufp->fastmap);
++    }
++
++#  ifdef _LIBC
++  printf ("re_nsub: %Zd\t", bufp->re_nsub);
++#  else
++  printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
++#  endif
++  printf ("regs_alloc: %d\t", bufp->regs_allocated);
++  printf ("can_be_null: %d\t", bufp->can_be_null);
++  printf ("newline_anchor: %d\n", bufp->newline_anchor);
++  printf ("no_sub: %d\t", bufp->no_sub);
++  printf ("not_bol: %d\t", bufp->not_bol);
++  printf ("not_eol: %d\t", bufp->not_eol);
++  printf ("syntax: %lx\n", bufp->syntax);
++  /* Perhaps we should print the translate table?  */
++}
++
++
++void
++PREFIX(print_double_string) (const CHAR_T *where, const CHAR_T *string1,
++                             int size1, const CHAR_T *string2, int size2)
++{
++  int this_char;
++
++  if (where == NULL)
++    printf ("(null)");
++  else
++    {
++      int cnt;
++
++      if (FIRST_STRING_P (where))
++        {
++          for (this_char = where - string1; this_char < size1; this_char++)
++	    PUT_CHAR (string1[this_char]);
++
++          where = string2;
++        }
++
++      cnt = 0;
++      for (this_char = where - string2; this_char < size2; this_char++)
++	{
++	  PUT_CHAR (string2[this_char]);
++	  if (++cnt > 100)
++	    {
++	      fputs ("...", stdout);
++	      break;
++	    }
++	}
++    }
++}
++
++#  ifndef DEFINED_ONCE
++void
++printchar (int c)
++{
++  putc (c, stderr);
++}
++#  endif
++
++# else /* not DEBUG */
++
++#  ifndef DEFINED_ONCE
++#   undef assert
++#   define assert(e)
++
++#   define DEBUG_STATEMENT(e)
++#   define DEBUG_PRINT1(x)
++#   define DEBUG_PRINT2(x1, x2)
++#   define DEBUG_PRINT3(x1, x2, x3)
++#   define DEBUG_PRINT4(x1, x2, x3, x4)
++#  endif /* not DEFINED_ONCE */
++#  define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
++#  define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
++
++# endif /* not DEBUG */
++
++
++
++# ifdef WCHAR
++/* This  convert a multibyte string to a wide character string.
++   And write their correspondances to offset_buffer(see below)
++   and write whether each wchar_t is binary data to is_binary.
++   This assume invalid multibyte sequences as binary data.
++   We assume offset_buffer and is_binary is already allocated
++   enough space.  */
++
++static size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src,
++				  size_t len, int *offset_buffer,
++				  char *is_binary);
++static size_t
++convert_mbs_to_wcs (CHAR_T *dest, const unsigned char*src, size_t len,
++                    int *offset_buffer, char *is_binary)
++     /* It hold correspondances between src(char string) and
++	dest(wchar_t string) for optimization.
++	e.g. src  = "xxxyzz"
++             dest = {'X', 'Y', 'Z'}
++	      (each "xxx", "y" and "zz" represent one multibyte character
++	       corresponding to 'X', 'Y' and 'Z'.)
++	  offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")}
++	  	        = {0, 3, 4, 6}
++     */
++{
++  wchar_t *pdest = dest;
++  const unsigned char *psrc = src;
++  size_t wc_count = 0;
++
++  mbstate_t mbs;
++  int i, consumed;
++  size_t mb_remain = len;
++  size_t mb_count = 0;
++
++  /* Initialize the conversion state.  */
++  memset (&mbs, 0, sizeof (mbstate_t));
++
++  offset_buffer[0] = 0;
++  for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed,
++	 psrc += consumed)
++    {
++#ifdef _LIBC
++      consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs);
++#else
++      consumed = mbrtowc (pdest, psrc, mb_remain, &mbs);
++#endif
++
++      if (consumed <= 0)
++	/* failed to convert. maybe src contains binary data.
++	   So we consume 1 byte manualy.  */
++	{
++	  *pdest = *psrc;
++	  consumed = 1;
++	  is_binary[wc_count] = TRUE;
++	}
++      else
++	is_binary[wc_count] = FALSE;
++      /* In sjis encoding, we use yen sign as escape character in
++	 place of reverse solidus. So we convert 0x5c(yen sign in
++	 sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse
++	 solidus in UCS2).  */
++      if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5)
++	*pdest = (wchar_t) *psrc;
++
++      offset_buffer[wc_count + 1] = mb_count += consumed;
++    }
++
++  /* Fill remain of the buffer with sentinel.  */
++  for (i = wc_count + 1 ; i <= len ; i++)
++    offset_buffer[i] = mb_count + 1;
++
++  return wc_count;
++}
++
++# endif /* WCHAR */
++
++#else /* not INSIDE_RECURSION */
++
++/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
++   also be assigned to arbitrarily: each pattern buffer stores its own
++   syntax, so it can be changed between regex compilations.  */
++/* This has no initializer because initialized variables in Emacs
++   become read-only after dumping.  */
++reg_syntax_t re_syntax_options;
++
++
++/* Specify the precise syntax of regexps for compilation.  This provides
++   for compatibility for various utilities which historically have
++   different, incompatible syntaxes.
++
++   The argument SYNTAX is a bit mask comprised of the various bits
++   defined in regex.h.  We return the old syntax.  */
++
++reg_syntax_t
++re_set_syntax (reg_syntax_t syntax)
++{
++  reg_syntax_t ret = re_syntax_options;
++
++  re_syntax_options = syntax;
++# ifdef DEBUG
++  if (syntax & RE_DEBUG)
++    debug = 1;
++  else if (debug) /* was on but now is not */
++    debug = 0;
++# endif /* DEBUG */
++  return ret;
++}
++# ifdef _LIBC
++weak_alias (__re_set_syntax, re_set_syntax)
++# endif
++
++/* This table gives an error message for each of the error codes listed
++   in regex.h.  Obviously the order here has to be same as there.
++   POSIX doesn't require that we do anything for REG_NOERROR,
++   but why not be nice?  */
++
++static const char *re_error_msgid[] =
++  {
++    gettext_noop ("Success"),	/* REG_NOERROR */
++    gettext_noop ("No match"),	/* REG_NOMATCH */
++    gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
++    gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
++    gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
++    gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
++    gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
++    gettext_noop ("Unmatched [ or [^"),	/* REG_EBRACK */
++    gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
++    gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
++    gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
++    gettext_noop ("Invalid range end"),	/* REG_ERANGE */
++    gettext_noop ("Memory exhausted"), /* REG_ESPACE */
++    gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
++    gettext_noop ("Premature end of regular expression"), /* REG_EEND */
++    gettext_noop ("Regular expression too big"), /* REG_ESIZE */
++    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
++  };
++
++#endif /* INSIDE_RECURSION */
++
++#ifndef DEFINED_ONCE
++/* Avoiding alloca during matching, to placate r_alloc.  */
++
++/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
++   searching and matching functions should not call alloca.  On some
++   systems, alloca is implemented in terms of malloc, and if we're
++   using the relocating allocator routines, then malloc could cause a
++   relocation, which might (if the strings being searched are in the
++   ralloc heap) shift the data out from underneath the regexp
++   routines.
++
++   Here's another reason to avoid allocation: Emacs
++   processes input from X in a signal handler; processing X input may
++   call malloc; if input arrives while a matching routine is calling
++   malloc, then we're scrod.  But Emacs can't just block input while
++   calling matching routines; then we don't notice interrupts when
++   they come in.  So, Emacs blocks input around all regexp calls
++   except the matching calls, which it leaves unprotected, in the
++   faith that they will not malloc.  */
++
++/* Normally, this is fine.  */
++# define MATCH_MAY_ALLOCATE
++
++/* When using GNU C, we are not REALLY using the C alloca, no matter
++   what config.h may say.  So don't take precautions for it.  */
++# ifdef __GNUC__
++#  undef C_ALLOCA
++# endif
++
++/* The match routines may not allocate if (1) they would do it with malloc
++   and (2) it's not safe for them to use malloc.
++   Note that if REL_ALLOC is defined, matching would not use malloc for the
++   failure stack, but we would still use it for the register vectors;
++   so REL_ALLOC should not affect this.  */
++# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
++#  undef MATCH_MAY_ALLOCATE
++# endif
++#endif /* not DEFINED_ONCE */
++
++#ifdef INSIDE_RECURSION
++/* Failure stack declarations and macros; both re_compile_fastmap and
++   re_match_2 use a failure stack.  These have to be macros because of
++   REGEX_ALLOCATE_STACK.  */
++
++
++/* Number of failure points for which to initially allocate space
++   when matching.  If this number is exceeded, we allocate more
++   space, so it is not a hard limit.  */
++# ifndef INIT_FAILURE_ALLOC
++#  define INIT_FAILURE_ALLOC 5
++# endif
++
++/* Roughly the maximum number of failure points on the stack.  Would be
++   exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
++   This is a variable only so users of regex can assign to it; we never
++   change it ourselves.  */
++
++
++# ifndef DEFINED_ONCE
++
++#  ifdef INT_IS_16BIT
++#   define RE_M_F_TYPE long int
++#  else
++#   define RE_M_F_TYPE int
++#  endif /* INT_IS_16BIT */
++
++#  ifdef MATCH_MAY_ALLOCATE
++/* 4400 was enough to cause a crash on Alpha OSF/1,
++   whose default stack limit is 2mb.  */
++#   define RE_M_F_DEFAULT 4000
++#  else
++#   define RE_M_F_DEFAULT 2000
++#  endif /* MATCH_MAY_ALLOCATE */
++
++#  include <shlib-compat.h>
++
++#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
++link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
++RE_M_F_TYPE re_max_failures = RE_M_F_DEFAULT;
++#  else
++RE_M_F_TYPE re_max_failures attribute_hidden = RE_M_F_DEFAULT;
++#  endif /* SHLIB_COMPAT */
++
++#  undef RE_M_F_TYPE
++#  undef RE_M_F_DEFAULT
++
++# endif /* DEFINED_ONCE */
++
++# ifdef INT_IS_16BIT
++
++union PREFIX(fail_stack_elt)
++{
++  UCHAR_T *pointer;
++  long int integer;
++};
++
++typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
++
++typedef struct
++{
++  PREFIX(fail_stack_elt_t) *stack;
++  unsigned long int size;
++  unsigned long int avail;		/* Offset of next open position.  */
++} PREFIX(fail_stack_type);
++
++# else /* not INT_IS_16BIT */
++
++union PREFIX(fail_stack_elt)
++{
++  UCHAR_T *pointer;
++  int integer;
++};
++
++typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
++
++typedef struct
++{
++  PREFIX(fail_stack_elt_t) *stack;
++  unsigned size;
++  unsigned avail;			/* Offset of next open position.  */
++} PREFIX(fail_stack_type);
++
++# endif /* INT_IS_16BIT */
++
++# ifndef DEFINED_ONCE
++#  define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
++#  define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
++#  define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
++# endif
++
++
++/* Define macros to initialize and free the failure stack.
++   Do `return -2' if the alloc fails.  */
++
++# ifdef MATCH_MAY_ALLOCATE
++#  define INIT_FAIL_STACK()						\
++  do {									\
++    fail_stack.stack = (PREFIX(fail_stack_elt_t) *)		\
++      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \
++									\
++    if (fail_stack.stack == NULL)				\
++      return -2;							\
++									\
++    fail_stack.size = INIT_FAILURE_ALLOC;			\
++    fail_stack.avail = 0;					\
++  } while (0)
++
++#  define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
++# else
++#  define INIT_FAIL_STACK()						\
++  do {									\
++    fail_stack.avail = 0;					\
++  } while (0)
++
++#  define RESET_FAIL_STACK()
++# endif
++
++
++/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
++
++   Return 1 if succeeds, and 0 if either ran out of memory
++   allocating space for it or it was already too large.
++
++   REGEX_REALLOCATE_STACK requires `destination' be declared.   */
++
++# define DOUBLE_FAIL_STACK(fail_stack)					\
++  ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS)	\
++   ? 0									\
++   : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *)			\
++        REGEX_REALLOCATE_STACK ((fail_stack).stack, 			\
++          (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)),	\
++          ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\
++									\
++      (fail_stack).stack == NULL					\
++      ? 0								\
++      : ((fail_stack).size <<= 1, 					\
++         1)))
++
++
++/* Push pointer POINTER on FAIL_STACK.
++   Return 1 if was able to do so and 0 if ran out of memory allocating
++   space to do so.  */
++# define PUSH_PATTERN_OP(POINTER, FAIL_STACK)				\
++  ((FAIL_STACK_FULL ()							\
++    && !DOUBLE_FAIL_STACK (FAIL_STACK))					\
++   ? 0									\
++   : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER,	\
++      1))
++
++/* Push a pointer value onto the failure stack.
++   Assumes the variable `fail_stack'.  Probably should only
++   be called from within `PUSH_FAILURE_POINT'.  */
++# define PUSH_FAILURE_POINTER(item)					\
++  fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item)
++
++/* This pushes an integer-valued item onto the failure stack.
++   Assumes the variable `fail_stack'.  Probably should only
++   be called from within `PUSH_FAILURE_POINT'.  */
++# define PUSH_FAILURE_INT(item)					\
++  fail_stack.stack[fail_stack.avail++].integer = (item)
++
++/* Push a fail_stack_elt_t value onto the failure stack.
++   Assumes the variable `fail_stack'.  Probably should only
++   be called from within `PUSH_FAILURE_POINT'.  */
++# define PUSH_FAILURE_ELT(item)					\
++  fail_stack.stack[fail_stack.avail++] =  (item)
++
++/* These three POP... operations complement the three PUSH... operations.
++   All assume that `fail_stack' is nonempty.  */
++# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
++# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
++# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
++
++/* Used to omit pushing failure point id's when we're not debugging.  */
++# ifdef DEBUG
++#  define DEBUG_PUSH PUSH_FAILURE_INT
++#  define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
++# else
++#  define DEBUG_PUSH(item)
++#  define DEBUG_POP(item_addr)
++# endif
++
++
++/* Push the information about the state we will need
++   if we ever fail back to it.
++
++   Requires variables fail_stack, regstart, regend, reg_info, and
++   num_regs_pushed be declared.  DOUBLE_FAIL_STACK requires `destination'
++   be declared.
++
++   Does `return FAILURE_CODE' if runs out of memory.  */
++
++# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)	\
++  do {									\
++    char *destination;							\
++    /* Must be int, so when we don't save any registers, the arithmetic	\
++       of 0 + -1 isn't done as unsigned.  */				\
++    /* Can't be int, since there is not a shred of a guarantee that int	\
++       is wide enough to hold a value of something to which pointer can	\
++       be assigned */							\
++    active_reg_t this_reg;						\
++    									\
++    DEBUG_STATEMENT (failure_id++);					\
++    DEBUG_STATEMENT (nfailure_points_pushed++);				\
++    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
++    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
++    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
++									\
++    DEBUG_PRINT2 ("  slots needed: %ld\n", NUM_FAILURE_ITEMS);		\
++    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);	\
++									\
++    /* Ensure we have enough space allocated for what we will push.  */	\
++    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)			\
++      {									\
++        if (!DOUBLE_FAIL_STACK (fail_stack))				\
++          return failure_code;						\
++									\
++        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",		\
++		       (fail_stack).size);				\
++        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
++      }									\
++									\
++    /* Push the info, starting with the registers.  */			\
++    DEBUG_PRINT1 ("\n");						\
++									\
++    if (1)								\
++      for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
++	   this_reg++)							\
++	{								\
++	  DEBUG_PRINT2 ("  Pushing reg: %lu\n", this_reg);		\
++	  DEBUG_STATEMENT (num_regs_pushed++);				\
++									\
++	  DEBUG_PRINT2 ("    start: %p\n", regstart[this_reg]);		\
++	  PUSH_FAILURE_POINTER (regstart[this_reg]);			\
++									\
++	  DEBUG_PRINT2 ("    end: %p\n", regend[this_reg]);		\
++	  PUSH_FAILURE_POINTER (regend[this_reg]);			\
++									\
++	  DEBUG_PRINT2 ("    info: %p\n      ",				\
++			reg_info[this_reg].word.pointer);		\
++	  DEBUG_PRINT2 (" match_null=%d",				\
++			REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
++	  DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
++	  DEBUG_PRINT2 (" matched_something=%d",			\
++			MATCHED_SOMETHING (reg_info[this_reg]));	\
++	  DEBUG_PRINT2 (" ever_matched=%d",				\
++			EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
++	  DEBUG_PRINT1 ("\n");						\
++	  PUSH_FAILURE_ELT (reg_info[this_reg].word);			\
++	}								\
++									\
++    DEBUG_PRINT2 ("  Pushing  low active reg: %ld\n", lowest_active_reg);\
++    PUSH_FAILURE_INT (lowest_active_reg);				\
++									\
++    DEBUG_PRINT2 ("  Pushing high active reg: %ld\n", highest_active_reg);\
++    PUSH_FAILURE_INT (highest_active_reg);				\
++									\
++    DEBUG_PRINT2 ("  Pushing pattern %p:\n", pattern_place);		\
++    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
++    PUSH_FAILURE_POINTER (pattern_place);				\
++									\
++    DEBUG_PRINT2 ("  Pushing string %p: `", string_place);		\
++    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
++				 size2);				\
++    DEBUG_PRINT1 ("'\n");						\
++    PUSH_FAILURE_POINTER (string_place);				\
++									\
++    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
++    DEBUG_PUSH (failure_id);						\
++  } while (0)
++
++# ifndef DEFINED_ONCE
++/* This is the number of items that are pushed and popped on the stack
++   for each register.  */
++#  define NUM_REG_ITEMS  3
++
++/* Individual items aside from the registers.  */
++#  ifdef DEBUG
++#   define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
++#  else
++#   define NUM_NONREG_ITEMS 4
++#  endif
++
++/* We push at most this many items on the stack.  */
++/* We used to use (num_regs - 1), which is the number of registers
++   this regexp will save; but that was changed to 5
++   to avoid stack overflow for a regexp with lots of parens.  */
++#  define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
++
++/* We actually push this many items.  */
++#  define NUM_FAILURE_ITEMS				\
++  (((0							\
++     ? 0 : highest_active_reg - lowest_active_reg + 1)	\
++    * NUM_REG_ITEMS)					\
++   + NUM_NONREG_ITEMS)
++
++/* How many items can still be added to the stack without overflowing it.  */
++#  define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
++# endif /* not DEFINED_ONCE */
++
++
++/* Pops what PUSH_FAIL_STACK pushes.
++
++   We restore into the parameters, all of which should be lvalues:
++     STR -- the saved data position.
++     PAT -- the saved pattern position.
++     LOW_REG, HIGH_REG -- the highest and lowest active registers.
++     REGSTART, REGEND -- arrays of string positions.
++     REG_INFO -- array of information about each subexpression.
++
++   Also assumes the variables `fail_stack' and (if debugging), `bufp',
++   `pend', `string1', `size1', `string2', and `size2'.  */
++# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
++{									\
++  DEBUG_STATEMENT (unsigned failure_id;)				\
++  active_reg_t this_reg;						\
++  const UCHAR_T *string_temp;						\
++									\
++  assert (!FAIL_STACK_EMPTY ());					\
++									\
++  /* Remove failure points and point to how many regs pushed.  */	\
++  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
++  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);	\
++  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);	\
++									\
++  assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
++									\
++  DEBUG_POP (&failure_id);						\
++  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);		\
++									\
++  /* If the saved string location is NULL, it came from an		\
++     on_failure_keep_string_jump opcode, and we want to throw away the	\
++     saved NULL, thus retaining our current position in the string.  */	\
++  string_temp = POP_FAILURE_POINTER ();					\
++  if (string_temp != NULL)						\
++    str = (const CHAR_T *) string_temp;					\
++									\
++  DEBUG_PRINT2 ("  Popping string %p: `", str);				\
++  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
++  DEBUG_PRINT1 ("'\n");							\
++									\
++  pat = (UCHAR_T *) POP_FAILURE_POINTER ();				\
++  DEBUG_PRINT2 ("  Popping pattern %p:\n", pat);			\
++  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
++									\
++  /* Restore register info.  */						\
++  high_reg = (active_reg_t) POP_FAILURE_INT ();				\
++  DEBUG_PRINT2 ("  Popping high active reg: %ld\n", high_reg);		\
++									\
++  low_reg = (active_reg_t) POP_FAILURE_INT ();				\
++  DEBUG_PRINT2 ("  Popping  low active reg: %ld\n", low_reg);		\
++									\
++  if (1)								\
++    for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
++      {									\
++	DEBUG_PRINT2 ("    Popping reg: %ld\n", this_reg);		\
++									\
++	reg_info[this_reg].word = POP_FAILURE_ELT ();			\
++	DEBUG_PRINT2 ("      info: %p\n",				\
++		      reg_info[this_reg].word.pointer);			\
++									\
++	regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER ();	\
++	DEBUG_PRINT2 ("      end: %p\n", regend[this_reg]);		\
++									\
++	regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER ();	\
++	DEBUG_PRINT2 ("      start: %p\n", regstart[this_reg]);		\
++      }									\
++  else									\
++    {									\
++      for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
++	{								\
++	  reg_info[this_reg].word.integer = 0;				\
++	  regend[this_reg] = 0;						\
++	  regstart[this_reg] = 0;					\
++	}								\
++      highest_active_reg = high_reg;					\
++    }									\
++									\
++  set_regs_matched_done = 0;						\
++  DEBUG_STATEMENT (nfailure_points_popped++);				\
++} /* POP_FAILURE_POINT */
++
++/* Structure for per-register (a.k.a. per-group) information.
++   Other register information, such as the
++   starting and ending positions (which are addresses), and the list of
++   inner groups (which is a bits list) are maintained in separate
++   variables.
++
++   We are making a (strictly speaking) nonportable assumption here: that
++   the compiler will pack our bit fields into something that fits into
++   the type of `word', i.e., is something that fits into one item on the
++   failure stack.  */
++
++
++/* Declarations and macros for re_match_2.  */
++
++typedef union
++{
++  PREFIX(fail_stack_elt_t) word;
++  struct
++  {
++      /* This field is one if this group can match the empty string,
++         zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
++# define MATCH_NULL_UNSET_VALUE 3
++    unsigned match_null_string_p : 2;
++    unsigned is_active : 1;
++    unsigned matched_something : 1;
++    unsigned ever_matched_something : 1;
++  } bits;
++} PREFIX(register_info_type);
++
++# ifndef DEFINED_ONCE
++#  define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
++#  define IS_ACTIVE(R)  ((R).bits.is_active)
++#  define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
++#  define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
++
++
++/* Call this when have matched a real character; it sets `matched' flags
++   for the subexpressions which we are currently inside.  Also records
++   that those subexprs have matched.  */
++#  define SET_REGS_MATCHED()						\
++  do									\
++    {									\
++      if (!set_regs_matched_done)					\
++	{								\
++	  active_reg_t r;						\
++	  set_regs_matched_done = 1;					\
++	  for (r = lowest_active_reg; r <= highest_active_reg; r++)	\
++	    {								\
++	      MATCHED_SOMETHING (reg_info[r])				\
++		= EVER_MATCHED_SOMETHING (reg_info[r])			\
++		= 1;							\
++	    }								\
++	}								\
++    }									\
++  while (0)
++# endif /* not DEFINED_ONCE */
++
++/* Registers are set to a sentinel when they haven't yet matched.  */
++static CHAR_T PREFIX(reg_unset_dummy);
++# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy))
++# define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
++
++/* Subroutine declarations and macros for regex_compile.  */
++static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg);
++static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc,
++                               int arg1, int arg2);
++static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc,
++                                int arg, UCHAR_T *end);
++static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc,
++                                int arg1, int arg2, UCHAR_T *end);
++static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern,
++                                         const CHAR_T *p,
++                                         reg_syntax_t syntax);
++static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p,
++                                         const CHAR_T *pend,
++                                         reg_syntax_t syntax);
++# ifdef WCHAR
++static reg_errcode_t wcs_compile_range (CHAR_T range_start,
++                                        const CHAR_T **p_ptr,
++                                        const CHAR_T *pend,
++                                        char *translate,
++                                        reg_syntax_t syntax,
++                                        UCHAR_T *b,
++                                        CHAR_T *char_set);
++static void insert_space (int num, CHAR_T *loc, CHAR_T *end);
++# else /* BYTE */
++static reg_errcode_t byte_compile_range (unsigned int range_start,
++                                         const char **p_ptr,
++                                         const char *pend,
++                                         RE_TRANSLATE_TYPE translate,
++                                         reg_syntax_t syntax,
++                                         unsigned char *b);
++# endif /* WCHAR */
++
++/* Fetch the next character in the uncompiled pattern---translating it
++   if necessary.  Also cast from a signed character in the constant
++   string passed to us by the user to an unsigned char that we can use
++   as an array index (in, e.g., `translate').  */
++/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
++   because it is impossible to allocate 4GB array for some encodings
++   which have 4 byte character_set like UCS4.  */
++# ifndef PATFETCH
++#  ifdef WCHAR
++#   define PATFETCH(c)							\
++  do {if (p == pend) return REG_EEND;					\
++    c = (UCHAR_T) *p++;							\
++    if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c];		\
++  } while (0)
++#  else /* BYTE */
++#   define PATFETCH(c)							\
++  do {if (p == pend) return REG_EEND;					\
++    c = (unsigned char) *p++;						\
++    if (translate) c = (unsigned char) translate[c];			\
++  } while (0)
++#  endif /* WCHAR */
++# endif
++
++/* Fetch the next character in the uncompiled pattern, with no
++   translation.  */
++# define PATFETCH_RAW(c)						\
++  do {if (p == pend) return REG_EEND;					\
++    c = (UCHAR_T) *p++; 	       					\
++  } while (0)
++
++/* Go backwards one character in the pattern.  */
++# define PATUNFETCH p--
++
++
++/* If `translate' is non-null, return translate[D], else just D.  We
++   cast the subscript to translate because some data is declared as
++   `char *', to avoid warnings when a string constant is passed.  But
++   when we use a character as a subscript we must make it unsigned.  */
++/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
++   because it is impossible to allocate 4GB array for some encodings
++   which have 4 byte character_set like UCS4.  */
++
++# ifndef TRANSLATE
++#  ifdef WCHAR
++#   define TRANSLATE(d) \
++  ((translate && ((UCHAR_T) (d)) <= 0xff) \
++   ? (char) translate[(unsigned char) (d)] : (d))
++# else /* BYTE */
++#   define TRANSLATE(d) \
++  (translate ? (char) translate[(unsigned char) (d)] : (char) (d))
++#  endif /* WCHAR */
++# endif
++
++
++/* Macros for outputting the compiled pattern into `buffer'.  */
++
++/* If the buffer isn't allocated when it comes in, use this.  */
++# define INIT_BUF_SIZE  (32 * sizeof(UCHAR_T))
++
++/* Make sure we have at least N more bytes of space in buffer.  */
++# ifdef WCHAR
++#  define GET_BUFFER_SPACE(n)						\
++    while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR	\
++            + (n)*sizeof(CHAR_T)) > bufp->allocated)			\
++      EXTEND_BUFFER ()
++# else /* BYTE */
++#  define GET_BUFFER_SPACE(n)						\
++    while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated)	\
++      EXTEND_BUFFER ()
++# endif /* WCHAR */
++
++/* Make sure we have one more byte of buffer space and then add C to it.  */
++# define BUF_PUSH(c)							\
++  do {									\
++    GET_BUFFER_SPACE (1);						\
++    *b++ = (UCHAR_T) (c);						\
++  } while (0)
++
++
++/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
++# define BUF_PUSH_2(c1, c2)						\
++  do {									\
++    GET_BUFFER_SPACE (2);						\
++    *b++ = (UCHAR_T) (c1);						\
++    *b++ = (UCHAR_T) (c2);						\
++  } while (0)
++
++
++/* As with BUF_PUSH_2, except for three bytes.  */
++# define BUF_PUSH_3(c1, c2, c3)						\
++  do {									\
++    GET_BUFFER_SPACE (3);						\
++    *b++ = (UCHAR_T) (c1);						\
++    *b++ = (UCHAR_T) (c2);						\
++    *b++ = (UCHAR_T) (c3);						\
++  } while (0)
++
++/* Store a jump with opcode OP at LOC to location TO.  We store a
++   relative address offset by the three bytes the jump itself occupies.  */
++# define STORE_JUMP(op, loc, to) \
++ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)))
++
++/* Likewise, for a two-argument jump.  */
++# define STORE_JUMP2(op, loc, to, arg) \
++  PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg)
++
++/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
++# define INSERT_JUMP(op, loc, to) \
++  PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b)
++
++/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
++# define INSERT_JUMP2(op, loc, to, arg) \
++  PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\
++	      arg, b)
++
++/* This is not an arbitrary limit: the arguments which represent offsets
++   into the pattern are two bytes long.  So if 2^16 bytes turns out to
++   be too small, many things would have to change.  */
++/* Any other compiler which, like MSC, has allocation limit below 2^16
++   bytes will have to use approach similar to what was done below for
++   MSC and drop MAX_BUF_SIZE a bit.  Otherwise you may end up
++   reallocating to 0 bytes.  Such thing is not going to work too well.
++   You have been warned!!  */
++# ifndef DEFINED_ONCE
++#  if defined _MSC_VER  && !defined WIN32
++/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
++   The REALLOC define eliminates a flurry of conversion warnings,
++   but is not required. */
++#   define MAX_BUF_SIZE  65500L
++#   define REALLOC(p,s) realloc ((p), (size_t) (s))
++#  else
++#   define MAX_BUF_SIZE (1L << 16)
++#   define REALLOC(p,s) realloc ((p), (s))
++#  endif
++
++/* Extend the buffer by twice its current size via realloc and
++   reset the pointers that pointed into the old block to point to the
++   correct places in the new one.  If extending the buffer results in it
++   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
++#  if __BOUNDED_POINTERS__
++#   define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
++#   define MOVE_BUFFER_POINTER(P) \
++  (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
++#   define ELSE_EXTEND_BUFFER_HIGH_BOUND	\
++  else						\
++    {						\
++      SET_HIGH_BOUND (b);			\
++      SET_HIGH_BOUND (begalt);			\
++      if (fixup_alt_jump)			\
++	SET_HIGH_BOUND (fixup_alt_jump);	\
++      if (laststart)				\
++	SET_HIGH_BOUND (laststart);		\
++      if (pending_exact)			\
++	SET_HIGH_BOUND (pending_exact);		\
++    }
++#  else
++#   define MOVE_BUFFER_POINTER(P) (P) += incr
++#   define ELSE_EXTEND_BUFFER_HIGH_BOUND
++#  endif
++# endif /* not DEFINED_ONCE */
++
++# ifdef WCHAR
++#  define EXTEND_BUFFER()						\
++  do {									\
++    UCHAR_T *old_buffer = COMPILED_BUFFER_VAR;				\
++    int wchar_count;							\
++    if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE)		\
++      return REG_ESIZE;							\
++    bufp->allocated <<= 1;						\
++    if (bufp->allocated > MAX_BUF_SIZE)					\
++      bufp->allocated = MAX_BUF_SIZE;					\
++    /* How many characters the new buffer can have?  */			\
++    wchar_count = bufp->allocated / sizeof(UCHAR_T);			\
++    if (wchar_count == 0) wchar_count = 1;				\
++    /* Truncate the buffer to CHAR_T align.  */			\
++    bufp->allocated = wchar_count * sizeof(UCHAR_T);			\
++    RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T);		\
++    bufp->buffer = (char*)COMPILED_BUFFER_VAR;				\
++    if (COMPILED_BUFFER_VAR == NULL)					\
++      return REG_ESPACE;						\
++    /* If the buffer moved, move all the pointers into it.  */		\
++    if (old_buffer != COMPILED_BUFFER_VAR)				\
++      {									\
++	int incr = COMPILED_BUFFER_VAR - old_buffer;			\
++	MOVE_BUFFER_POINTER (b);					\
++	MOVE_BUFFER_POINTER (begalt);					\
++	if (fixup_alt_jump)						\
++	  MOVE_BUFFER_POINTER (fixup_alt_jump);				\
++	if (laststart)							\
++	  MOVE_BUFFER_POINTER (laststart);				\
++	if (pending_exact)						\
++	  MOVE_BUFFER_POINTER (pending_exact);				\
++      }									\
++    ELSE_EXTEND_BUFFER_HIGH_BOUND					\
++  } while (0)
++# else /* BYTE */
++#  define EXTEND_BUFFER()						\
++  do {									\
++    UCHAR_T *old_buffer = COMPILED_BUFFER_VAR;				\
++    if (bufp->allocated == MAX_BUF_SIZE)				\
++      return REG_ESIZE;							\
++    bufp->allocated <<= 1;						\
++    if (bufp->allocated > MAX_BUF_SIZE)					\
++      bufp->allocated = MAX_BUF_SIZE;					\
++    bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR,		\
++						bufp->allocated);	\
++    if (COMPILED_BUFFER_VAR == NULL)					\
++      return REG_ESPACE;						\
++    /* If the buffer moved, move all the pointers into it.  */		\
++    if (old_buffer != COMPILED_BUFFER_VAR)				\
++      {									\
++	int incr = COMPILED_BUFFER_VAR - old_buffer;			\
++	MOVE_BUFFER_POINTER (b);					\
++	MOVE_BUFFER_POINTER (begalt);					\
++	if (fixup_alt_jump)						\
++	  MOVE_BUFFER_POINTER (fixup_alt_jump);				\
++	if (laststart)							\
++	  MOVE_BUFFER_POINTER (laststart);				\
++	if (pending_exact)						\
++	  MOVE_BUFFER_POINTER (pending_exact);				\
++      }									\
++    ELSE_EXTEND_BUFFER_HIGH_BOUND					\
++  } while (0)
++# endif /* WCHAR */
++
++# ifndef DEFINED_ONCE
++/* Since we have one byte reserved for the register number argument to
++   {start,stop}_memory, the maximum number of groups we can report
++   things about is what fits in that byte.  */
++#  define MAX_REGNUM 255
++
++/* But patterns can have more than `MAX_REGNUM' registers.  We just
++   ignore the excess.  */
++typedef unsigned regnum_t;
++
++
++/* Macros for the compile stack.  */
++
++/* Since offsets can go either forwards or backwards, this type needs to
++   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
++/* int may be not enough when sizeof(int) == 2.  */
++typedef long pattern_offset_t;
++
++typedef struct
++{
++  pattern_offset_t begalt_offset;
++  pattern_offset_t fixup_alt_jump;
++  pattern_offset_t inner_group_offset;
++  pattern_offset_t laststart_offset;
++  regnum_t regnum;
++} compile_stack_elt_t;
++
++
++typedef struct
++{
++  compile_stack_elt_t *stack;
++  unsigned size;
++  unsigned avail;			/* Offset of next open position.  */
++} compile_stack_type;
++
++
++#  define INIT_COMPILE_STACK_SIZE 32
++
++#  define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
++#  define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
++
++/* The next available element.  */
++#  define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
++
++# endif /* not DEFINED_ONCE */
++
++/* Set the bit for character C in a list.  */
++# ifndef DEFINED_ONCE
++#  define SET_LIST_BIT(c)                               \
++  (b[((unsigned char) (c)) / BYTEWIDTH]               \
++   |= 1 << (((unsigned char) c) % BYTEWIDTH))
++# endif /* DEFINED_ONCE */
++
++/* Get the next unsigned number in the uncompiled pattern.  */
++# define GET_UNSIGNED_NUMBER(num) \
++  {									\
++    while (p != pend)							\
++      {									\
++	PATFETCH (c);							\
++	if (c < '0' || c > '9')						\
++	  break;							\
++	if (num <= RE_DUP_MAX)						\
++	  {								\
++	    if (num < 0)						\
++	      num = 0;							\
++	    num = num * 10 + c - '0';					\
++	  }								\
++      }									\
++  }
++
++# ifndef DEFINED_ONCE
++#  if WIDE_CHAR_SUPPORT
++/* The GNU C library provides support for user-defined character classes
++   and the functions from ISO C amendement 1.  */
++#   ifdef CHARCLASS_NAME_MAX
++#    define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
++#   else
++/* This shouldn't happen but some implementation might still have this
++   problem.  Use a reasonable default value.  */
++#    define CHAR_CLASS_MAX_LENGTH 256
++#   endif
++
++#   ifdef _LIBC
++#    define IS_CHAR_CLASS(string) __wctype (string)
++#   else
++#    define IS_CHAR_CLASS(string) wctype (string)
++#   endif
++#  else
++#   define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
++
++#   define IS_CHAR_CLASS(string)					\
++   (STREQ (string, "alpha") || STREQ (string, "upper")			\
++    || STREQ (string, "lower") || STREQ (string, "digit")		\
++    || STREQ (string, "alnum") || STREQ (string, "xdigit")		\
++    || STREQ (string, "space") || STREQ (string, "print")		\
++    || STREQ (string, "punct") || STREQ (string, "graph")		\
++    || STREQ (string, "cntrl") || STREQ (string, "blank"))
++#  endif
++# endif /* DEFINED_ONCE */
++
++# ifndef MATCH_MAY_ALLOCATE
++
++/* If we cannot allocate large objects within re_match_2_internal,
++   we make the fail stack and register vectors global.
++   The fail stack, we grow to the maximum size when a regexp
++   is compiled.
++   The register vectors, we adjust in size each time we
++   compile a regexp, according to the number of registers it needs.  */
++
++static PREFIX(fail_stack_type) fail_stack;
++
++/* Size with which the following vectors are currently allocated.
++   That is so we can make them bigger as needed,
++   but never make them smaller.  */
++#  ifdef DEFINED_ONCE
++static int regs_allocated_size;
++
++static const char **     regstart, **     regend;
++static const char ** old_regstart, ** old_regend;
++static const char **best_regstart, **best_regend;
++static const char **reg_dummy;
++#  endif /* DEFINED_ONCE */
++
++static PREFIX(register_info_type) *PREFIX(reg_info);
++static PREFIX(register_info_type) *PREFIX(reg_info_dummy);
++
++/* Make the register vectors big enough for NUM_REGS registers,
++   but don't make them smaller.  */
++
++static void
++PREFIX(regex_grow_registers) (int num_regs)
++{
++  if (num_regs > regs_allocated_size)
++    {
++      RETALLOC_IF (regstart,	 num_regs, const char *);
++      RETALLOC_IF (regend,	 num_regs, const char *);
++      RETALLOC_IF (old_regstart, num_regs, const char *);
++      RETALLOC_IF (old_regend,	 num_regs, const char *);
++      RETALLOC_IF (best_regstart, num_regs, const char *);
++      RETALLOC_IF (best_regend,	 num_regs, const char *);
++      RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type));
++      RETALLOC_IF (reg_dummy,	 num_regs, const char *);
++      RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type));
++
++      regs_allocated_size = num_regs;
++    }
++}
++
++# endif /* not MATCH_MAY_ALLOCATE */
++
++# ifndef DEFINED_ONCE
++static boolean group_in_compile_stack (compile_stack_type compile_stack,
++                                       regnum_t regnum);
++# endif /* not DEFINED_ONCE */
++
++/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
++   Returns one of error codes defined in `regex.h', or zero for success.
++
++   Assumes the `allocated' (and perhaps `buffer') and `translate'
++   fields are set in BUFP on entry.
++
++   If it succeeds, results are put in BUFP (if it returns an error, the
++   contents of BUFP are undefined):
++     `buffer' is the compiled pattern;
++     `syntax' is set to SYNTAX;
++     `used' is set to the length of the compiled pattern;
++     `fastmap_accurate' is zero;
++     `re_nsub' is the number of subexpressions in PATTERN;
++     `not_bol' and `not_eol' are zero;
++
++   The `fastmap' and `newline_anchor' fields are neither
++   examined nor set.  */
++
++/* Return, freeing storage we allocated.  */
++# ifdef WCHAR
++#  define FREE_STACK_RETURN(value)		\
++  return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value)
++# else
++#  define FREE_STACK_RETURN(value)		\
++  return (free (compile_stack.stack), value)
++# endif /* WCHAR */
++
++static reg_errcode_t
++PREFIX(regex_compile) (const char *ARG_PREFIX(pattern),
++                       size_t ARG_PREFIX(size), reg_syntax_t syntax,
++                       struct re_pattern_buffer *bufp)
++{
++  /* We fetch characters from PATTERN here.  Even though PATTERN is
++     `char *' (i.e., signed), we declare these variables as unsigned, so
++     they can be reliably used as array indices.  */
++  register UCHAR_T c, c1;
++
++#ifdef WCHAR
++  /* A temporary space to keep wchar_t pattern and compiled pattern.  */
++  CHAR_T *pattern, *COMPILED_BUFFER_VAR;
++  size_t size;
++  /* offset buffer for optimization. See convert_mbs_to_wc.  */
++  int *mbs_offset = NULL;
++  /* It hold whether each wchar_t is binary data or not.  */
++  char *is_binary = NULL;
++  /* A flag whether exactn is handling binary data or not.  */
++  char is_exactn_bin = FALSE;
++#endif /* WCHAR */
++
++  /* A random temporary spot in PATTERN.  */
++  const CHAR_T *p1;
++
++  /* Points to the end of the buffer, where we should append.  */
++  register UCHAR_T *b;
++
++  /* Keeps track of unclosed groups.  */
++  compile_stack_type compile_stack;
++
++  /* Points to the current (ending) position in the pattern.  */
++#ifdef WCHAR
++  const CHAR_T *p;
++  const CHAR_T *pend;
++#else /* BYTE */
++  const CHAR_T *p = pattern;
++  const CHAR_T *pend = pattern + size;
++#endif /* WCHAR */
++
++  /* How to translate the characters in the pattern.  */
++  RE_TRANSLATE_TYPE translate = bufp->translate;
++
++  /* Address of the count-byte of the most recently inserted `exactn'
++     command.  This makes it possible to tell if a new exact-match
++     character can be added to that command or if the character requires
++     a new `exactn' command.  */
++  UCHAR_T *pending_exact = 0;
++
++  /* Address of start of the most recently finished expression.
++     This tells, e.g., postfix * where to find the start of its
++     operand.  Reset at the beginning of groups and alternatives.  */
++  UCHAR_T *laststart = 0;
++
++  /* Address of beginning of regexp, or inside of last group.  */
++  UCHAR_T *begalt;
++
++  /* Address of the place where a forward jump should go to the end of
++     the containing expression.  Each alternative of an `or' -- except the
++     last -- ends with a forward jump of this sort.  */
++  UCHAR_T *fixup_alt_jump = 0;
++
++  /* Counts open-groups as they are encountered.  Remembered for the
++     matching close-group on the compile stack, so the same register
++     number is put in the stop_memory as the start_memory.  */
++  regnum_t regnum = 0;
++
++#ifdef WCHAR
++  /* Initialize the wchar_t PATTERN and offset_buffer.  */
++  p = pend = pattern = TALLOC(csize + 1, CHAR_T);
++  mbs_offset = TALLOC(csize + 1, int);
++  is_binary = TALLOC(csize + 1, char);
++  if (pattern == NULL || mbs_offset == NULL || is_binary == NULL)
++    {
++      free(pattern);
++      free(mbs_offset);
++      free(is_binary);
++      return REG_ESPACE;
++    }
++  pattern[csize] = L'\0';	/* sentinel */
++  size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary);
++  pend = p + size;
++  if (size < 0)
++    {
++      free(pattern);
++      free(mbs_offset);
++      free(is_binary);
++      return REG_BADPAT;
++    }
++#endif
++
++#ifdef DEBUG
++  DEBUG_PRINT1 ("\nCompiling pattern: ");
++  if (debug)
++    {
++      unsigned debug_count;
++
++      for (debug_count = 0; debug_count < size; debug_count++)
++        PUT_CHAR (pattern[debug_count]);
++      putchar ('\n');
++    }
++#endif /* DEBUG */
++
++  /* Initialize the compile stack.  */
++  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
++  if (compile_stack.stack == NULL)
++    {
++#ifdef WCHAR
++      free(pattern);
++      free(mbs_offset);
++      free(is_binary);
++#endif
++      return REG_ESPACE;
++    }
++
++  compile_stack.size = INIT_COMPILE_STACK_SIZE;
++  compile_stack.avail = 0;
++
++  /* Initialize the pattern buffer.  */
++  bufp->syntax = syntax;
++  bufp->fastmap_accurate = 0;
++  bufp->not_bol = bufp->not_eol = 0;
++
++  /* Set `used' to zero, so that if we return an error, the pattern
++     printer (for debugging) will think there's no pattern.  We reset it
++     at the end.  */
++  bufp->used = 0;
++
++  /* Always count groups, whether or not bufp->no_sub is set.  */
++  bufp->re_nsub = 0;
++
++#if !defined emacs && !defined SYNTAX_TABLE
++  /* Initialize the syntax table.  */
++   init_syntax_once ();
++#endif
++
++  if (bufp->allocated == 0)
++    {
++      if (bufp->buffer)
++	{ /* If zero allocated, but buffer is non-null, try to realloc
++             enough space.  This loses if buffer's address is bogus, but
++             that is the user's responsibility.  */
++#ifdef WCHAR
++	  /* Free bufp->buffer and allocate an array for wchar_t pattern
++	     buffer.  */
++          free(bufp->buffer);
++          COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T),
++					UCHAR_T);
++#else
++          RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T);
++#endif /* WCHAR */
++        }
++      else
++        { /* Caller did not allocate a buffer.  Do it for them.  */
++          COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T),
++					UCHAR_T);
++        }
++
++      if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE);
++#ifdef WCHAR
++      bufp->buffer = (char*)COMPILED_BUFFER_VAR;
++#endif /* WCHAR */
++      bufp->allocated = INIT_BUF_SIZE;
++    }
++#ifdef WCHAR
++  else
++    COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer;
++#endif
++
++  begalt = b = COMPILED_BUFFER_VAR;
++
++  /* Loop through the uncompiled pattern until we're at the end.  */
++  while (p != pend)
++    {
++      PATFETCH (c);
++
++      switch (c)
++        {
++        case '^':
++          {
++            if (   /* If at start of pattern, it's an operator.  */
++                   p == pattern + 1
++                   /* If context independent, it's an operator.  */
++                || syntax & RE_CONTEXT_INDEP_ANCHORS
++                   /* Otherwise, depends on what's come before.  */
++                || PREFIX(at_begline_loc_p) (pattern, p, syntax))
++              BUF_PUSH (begline);
++            else
++              goto normal_char;
++          }
++          break;
++
++
++        case '$':
++          {
++            if (   /* If at end of pattern, it's an operator.  */
++                   p == pend
++                   /* If context independent, it's an operator.  */
++                || syntax & RE_CONTEXT_INDEP_ANCHORS
++                   /* Otherwise, depends on what's next.  */
++                || PREFIX(at_endline_loc_p) (p, pend, syntax))
++               BUF_PUSH (endline);
++             else
++               goto normal_char;
++           }
++           break;
++
++
++	case '+':
++        case '?':
++          if ((syntax & RE_BK_PLUS_QM)
++              || (syntax & RE_LIMITED_OPS))
++            goto normal_char;
++        handle_plus:
++        case '*':
++          /* If there is no previous pattern... */
++          if (!laststart)
++            {
++              if (syntax & RE_CONTEXT_INVALID_OPS)
++                FREE_STACK_RETURN (REG_BADRPT);
++              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
++                goto normal_char;
++            }
++
++          {
++            /* Are we optimizing this jump?  */
++            boolean keep_string_p = false;
++
++            /* 1 means zero (many) matches is allowed.  */
++            char zero_times_ok = 0, many_times_ok = 0;
++
++            /* If there is a sequence of repetition chars, collapse it
++               down to just one (the right one).  We can't combine
++               interval operators with these because of, e.g., `a{2}*',
++               which should only match an even number of `a's.  */
++
++            for (;;)
++              {
++                zero_times_ok |= c != '+';
++                many_times_ok |= c != '?';
++
++                if (p == pend)
++                  break;
++
++                PATFETCH (c);
++
++                if (c == '*'
++                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
++                  ;
++
++                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
++                  {
++                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
++
++                    PATFETCH (c1);
++                    if (!(c1 == '+' || c1 == '?'))
++                      {
++                        PATUNFETCH;
++                        PATUNFETCH;
++                        break;
++                      }
++
++                    c = c1;
++                  }
++                else
++                  {
++                    PATUNFETCH;
++                    break;
++                  }
++
++                /* If we get here, we found another repeat character.  */
++               }
++
++            /* Star, etc. applied to an empty pattern is equivalent
++               to an empty pattern.  */
++            if (!laststart)
++              break;
++
++            /* Now we know whether or not zero matches is allowed
++               and also whether or not two or more matches is allowed.  */
++            if (many_times_ok)
++              { /* More than one repetition is allowed, so put in at the
++                   end a backward relative jump from `b' to before the next
++                   jump we're going to put in below (which jumps from
++                   laststart to after this jump).
++
++                   But if we are at the `*' in the exact sequence `.*\n',
++                   insert an unconditional jump backwards to the .,
++                   instead of the beginning of the loop.  This way we only
++                   push a failure point once, instead of every time
++                   through the loop.  */
++                assert (p - 1 > pattern);
++
++                /* Allocate the space for the jump.  */
++                GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++
++                /* We know we are not at the first character of the pattern,
++                   because laststart was nonzero.  And we've already
++                   incremented `p', by the way, to be the character after
++                   the `*'.  Do we have to do something analogous here
++                   for null bytes, because of RE_DOT_NOT_NULL?  */
++                if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
++		    && zero_times_ok
++                    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
++                    && !(syntax & RE_DOT_NEWLINE))
++                  { /* We have .*\n.  */
++                    STORE_JUMP (jump, b, laststart);
++                    keep_string_p = true;
++                  }
++                else
++                  /* Anything else.  */
++                  STORE_JUMP (maybe_pop_jump, b, laststart -
++			      (1 + OFFSET_ADDRESS_SIZE));
++
++                /* We've added more stuff to the buffer.  */
++                b += 1 + OFFSET_ADDRESS_SIZE;
++              }
++
++            /* On failure, jump from laststart to b + 3, which will be the
++               end of the buffer after this jump is inserted.  */
++	    /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of
++	       'b + 3'.  */
++            GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++            INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
++                                       : on_failure_jump,
++                         laststart, b + 1 + OFFSET_ADDRESS_SIZE);
++            pending_exact = 0;
++            b += 1 + OFFSET_ADDRESS_SIZE;
++
++            if (!zero_times_ok)
++              {
++                /* At least one repetition is required, so insert a
++                   `dummy_failure_jump' before the initial
++                   `on_failure_jump' instruction of the loop. This
++                   effects a skip over that instruction the first time
++                   we hit that loop.  */
++                GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++                INSERT_JUMP (dummy_failure_jump, laststart, laststart +
++			     2 + 2 * OFFSET_ADDRESS_SIZE);
++                b += 1 + OFFSET_ADDRESS_SIZE;
++              }
++            }
++	  break;
++
++
++	case '.':
++          laststart = b;
++          BUF_PUSH (anychar);
++          break;
++
++
++        case '[':
++          {
++            boolean had_char_class = false;
++#ifdef WCHAR
++	    CHAR_T range_start = 0xffffffff;
++#else
++	    unsigned int range_start = 0xffffffff;
++#endif
++            if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++#ifdef WCHAR
++	    /* We assume a charset(_not) structure as a wchar_t array.
++	       charset[0] = (re_opcode_t) charset(_not)
++               charset[1] = l (= length of char_classes)
++               charset[2] = m (= length of collating_symbols)
++               charset[3] = n (= length of equivalence_classes)
++	       charset[4] = o (= length of char_ranges)
++	       charset[5] = p (= length of chars)
++
++               charset[6] = char_class (wctype_t)
++               charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t)
++                         ...
++               charset[l+5]  = char_class (wctype_t)
++
++               charset[l+6]  = collating_symbol (wchar_t)
++                            ...
++               charset[l+m+5]  = collating_symbol (wchar_t)
++					ifdef _LIBC we use the index if
++					_NL_COLLATE_SYMB_EXTRAMB instead of
++					wchar_t string.
++
++               charset[l+m+6]  = equivalence_classes (wchar_t)
++                              ...
++               charset[l+m+n+5]  = equivalence_classes (wchar_t)
++					ifdef _LIBC we use the index in
++					_NL_COLLATE_WEIGHT instead of
++					wchar_t string.
++
++	       charset[l+m+n+6] = range_start
++	       charset[l+m+n+7] = range_end
++	                       ...
++	       charset[l+m+n+2o+4] = range_start
++	       charset[l+m+n+2o+5] = range_end
++					ifdef _LIBC we use the value looked up
++					in _NL_COLLATE_COLLSEQ instead of
++					wchar_t character.
++
++	       charset[l+m+n+2o+6] = char
++	                          ...
++	       charset[l+m+n+2o+p+5] = char
++
++	     */
++
++	    /* We need at least 6 spaces: the opcode, the length of
++               char_classes, the length of collating_symbols, the length of
++               equivalence_classes, the length of char_ranges, the length of
++               chars.  */
++	    GET_BUFFER_SPACE (6);
++
++	    /* Save b as laststart. And We use laststart as the pointer
++	       to the first element of the charset here.
++	       In other words, laststart[i] indicates charset[i].  */
++            laststart = b;
++
++            /* We test `*p == '^' twice, instead of using an if
++               statement, so we only need one BUF_PUSH.  */
++            BUF_PUSH (*p == '^' ? charset_not : charset);
++            if (*p == '^')
++              p++;
++
++            /* Push the length of char_classes, the length of
++               collating_symbols, the length of equivalence_classes, the
++               length of char_ranges and the length of chars.  */
++            BUF_PUSH_3 (0, 0, 0);
++            BUF_PUSH_2 (0, 0);
++
++            /* Remember the first position in the bracket expression.  */
++            p1 = p;
++
++            /* charset_not matches newline according to a syntax bit.  */
++            if ((re_opcode_t) b[-6] == charset_not
++                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
++	      {
++		BUF_PUSH('\n');
++		laststart[5]++; /* Update the length of characters  */
++	      }
++
++            /* Read in characters and ranges, setting map bits.  */
++            for (;;)
++              {
++                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                PATFETCH (c);
++
++                /* \ might escape characters inside [...] and [^...].  */
++                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
++                  {
++                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
++
++                    PATFETCH (c1);
++		    BUF_PUSH(c1);
++		    laststart[5]++; /* Update the length of chars  */
++		    range_start = c1;
++                    continue;
++                  }
++
++                /* Could be the end of the bracket expression.  If it's
++                   not (i.e., when the bracket expression is `[]' so
++                   far), the ']' character bit gets set way below.  */
++                if (c == ']' && p != p1 + 1)
++                  break;
++
++                /* Look ahead to see if it's a range when the last thing
++                   was a character class.  */
++                if (had_char_class && c == '-' && *p != ']')
++                  FREE_STACK_RETURN (REG_ERANGE);
++
++                /* Look ahead to see if it's a range when the last thing
++                   was a character: if this is a hyphen not at the
++                   beginning or the end of a list, then it's the range
++                   operator.  */
++                if (c == '-'
++                    && !(p - 2 >= pattern && p[-2] == '[')
++                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
++                    && *p != ']')
++                  {
++                    reg_errcode_t ret;
++		    /* Allocate the space for range_start and range_end.  */
++		    GET_BUFFER_SPACE (2);
++		    /* Update the pointer to indicate end of buffer.  */
++                    b += 2;
++                    ret = wcs_compile_range (range_start, &p, pend, translate,
++                                         syntax, b, laststart);
++                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
++                    range_start = 0xffffffff;
++                  }
++                else if (p[0] == '-' && p[1] != ']')
++                  { /* This handles ranges made up of characters only.  */
++                    reg_errcode_t ret;
++
++		    /* Move past the `-'.  */
++                    PATFETCH (c1);
++		    /* Allocate the space for range_start and range_end.  */
++		    GET_BUFFER_SPACE (2);
++		    /* Update the pointer to indicate end of buffer.  */
++                    b += 2;
++                    ret = wcs_compile_range (c, &p, pend, translate, syntax, b,
++                                         laststart);
++                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
++		    range_start = 0xffffffff;
++                  }
++
++                /* See if we're at the beginning of a possible character
++                   class.  */
++                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
++                  { /* Leave room for the null.  */
++                    char str[CHAR_CLASS_MAX_LENGTH + 1];
++
++                    PATFETCH (c);
++                    c1 = 0;
++
++                    /* If pattern is `[[:'.  */
++                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                    for (;;)
++                      {
++                        PATFETCH (c);
++                        if ((c == ':' && *p == ']') || p == pend)
++                          break;
++			if (c1 < CHAR_CLASS_MAX_LENGTH)
++			  str[c1++] = c;
++			else
++			  /* This is in any case an invalid class name.  */
++			  str[0] = '\0';
++                      }
++                    str[c1] = '\0';
++
++                    /* If isn't a word bracketed by `[:' and `:]':
++                       undo the ending character, the letters, and leave
++                       the leading `:' and `[' (but store them as character).  */
++                    if (c == ':' && *p == ']')
++                      {
++			wctype_t wt;
++			uintptr_t alignedp;
++
++			/* Query the character class as wctype_t.  */
++			wt = IS_CHAR_CLASS (str);
++			if (wt == 0)
++			  FREE_STACK_RETURN (REG_ECTYPE);
++
++                        /* Throw away the ] at the end of the character
++                           class.  */
++                        PATFETCH (c);
++
++                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++			/* Allocate the space for character class.  */
++                        GET_BUFFER_SPACE(CHAR_CLASS_SIZE);
++			/* Update the pointer to indicate end of buffer.  */
++                        b += CHAR_CLASS_SIZE;
++			/* Move data which follow character classes
++			    not to violate the data.  */
++                        insert_space(CHAR_CLASS_SIZE,
++				     laststart + 6 + laststart[1],
++				     b - 1);
++			alignedp = ((uintptr_t)(laststart + 6 + laststart[1])
++				    + __alignof__(wctype_t) - 1)
++			  	    & ~(uintptr_t)(__alignof__(wctype_t) - 1);
++			/* Store the character class.  */
++                        *((wctype_t*)alignedp) = wt;
++                        /* Update length of char_classes */
++                        laststart[1] += CHAR_CLASS_SIZE;
++
++                        had_char_class = true;
++                      }
++                    else
++                      {
++                        c1++;
++                        while (c1--)
++                          PATUNFETCH;
++                        BUF_PUSH ('[');
++                        BUF_PUSH (':');
++                        laststart[5] += 2; /* Update the length of characters  */
++			range_start = ':';
++                        had_char_class = false;
++                      }
++                  }
++                else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '='
++							  || *p == '.'))
++		  {
++		    CHAR_T str[128];	/* Should be large enough.  */
++		    CHAR_T delim = *p; /* '=' or '.'  */
++# ifdef _LIBC
++		    uint32_t nrules =
++		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++# endif
++		    PATFETCH (c);
++		    c1 = 0;
++
++		    /* If pattern is `[[=' or '[[.'.  */
++		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++		    for (;;)
++		      {
++			PATFETCH (c);
++			if ((c == delim && *p == ']') || p == pend)
++			  break;
++			if (c1 < sizeof (str) - 1)
++			  str[c1++] = c;
++			else
++			  /* This is in any case an invalid class name.  */
++			  str[0] = '\0';
++                      }
++		    str[c1] = '\0';
++
++		    if (c == delim && *p == ']' && str[0] != '\0')
++		      {
++                        unsigned int i, offset;
++			/* If we have no collation data we use the default
++			   collation in which each character is in a class
++			   by itself.  It also means that ASCII is the
++			   character set and therefore we cannot have character
++			   with more than one byte in the multibyte
++			   representation.  */
++
++                        /* If not defined _LIBC, we push the name and
++			   `\0' for the sake of matching performance.  */
++			int datasize = c1 + 1;
++
++# ifdef _LIBC
++			int32_t idx = 0;
++			if (nrules == 0)
++# endif
++			  {
++			    if (c1 != 1)
++			      FREE_STACK_RETURN (REG_ECOLLATE);
++			  }
++# ifdef _LIBC
++			else
++			  {
++			    const int32_t *table;
++			    const int32_t *weights;
++			    const int32_t *extra;
++			    const int32_t *indirect;
++			    wint_t *cp;
++
++			    /* This #include defines a local function!  */
++#  include <locale/weightwc.h>
++
++			    if(delim == '=')
++			      {
++				/* We push the index for equivalence class.  */
++				cp = (wint_t*)str;
++
++				table = (const int32_t *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_TABLEWC);
++				weights = (const int32_t *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_WEIGHTWC);
++				extra = (const int32_t *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_EXTRAWC);
++				indirect = (const int32_t *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_INDIRECTWC);
++
++				idx = findidx ((const wint_t**)&cp, c1);
++				if (idx == 0 || cp < (wint_t*) str + c1)
++				  /* This is no valid character.  */
++				  FREE_STACK_RETURN (REG_ECOLLATE);
++
++				str[0] = (wchar_t)idx;
++			      }
++			    else /* delim == '.' */
++			      {
++				/* We push collation sequence value
++				   for collating symbol.  */
++				int32_t table_size;
++				const int32_t *symb_table;
++				const unsigned char *extra;
++				int32_t idx;
++				int32_t elem;
++				int32_t second;
++				int32_t hash;
++				char char_str[c1];
++
++				/* We have to convert the name to a single-byte
++				   string.  This is possible since the names
++				   consist of ASCII characters and the internal
++				   representation is UCS4.  */
++				for (i = 0; i < c1; ++i)
++				  char_str[i] = str[i];
++
++				table_size =
++				  _NL_CURRENT_WORD (LC_COLLATE,
++						    _NL_COLLATE_SYMB_HASH_SIZEMB);
++				symb_table = (const int32_t *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_SYMB_TABLEMB);
++				extra = (const unsigned char *)
++				  _NL_CURRENT (LC_COLLATE,
++					       _NL_COLLATE_SYMB_EXTRAMB);
++
++				/* Locate the character in the hashing table.  */
++				hash = elem_hash (char_str, c1);
++
++				idx = 0;
++				elem = hash % table_size;
++				second = hash % (table_size - 2);
++				while (symb_table[2 * elem] != 0)
++				  {
++				    /* First compare the hashing value.  */
++				    if (symb_table[2 * elem] == hash
++					&& c1 == extra[symb_table[2 * elem + 1]]
++					&& memcmp (char_str,
++						   &extra[symb_table[2 * elem + 1]
++							 + 1], c1) == 0)
++				      {
++					/* Yep, this is the entry.  */
++					idx = symb_table[2 * elem + 1];
++					idx += 1 + extra[idx];
++					break;
++				      }
++
++				    /* Next entry.  */
++				    elem += second;
++				  }
++
++				if (symb_table[2 * elem] != 0)
++				  {
++				    /* Compute the index of the byte sequence
++				       in the table.  */
++				    idx += 1 + extra[idx];
++				    /* Adjust for the alignment.  */
++				    idx = (idx + 3) & ~3;
++
++				    str[0] = (wchar_t) idx + 4;
++				  }
++				else if (symb_table[2 * elem] == 0 && c1 == 1)
++				  {
++				    /* No valid character.  Match it as a
++				       single byte character.  */
++				    had_char_class = false;
++				    BUF_PUSH(str[0]);
++				    /* Update the length of characters  */
++				    laststart[5]++;
++				    range_start = str[0];
++
++				    /* Throw away the ] at the end of the
++				       collating symbol.  */
++				    PATFETCH (c);
++				    /* exit from the switch block.  */
++				    continue;
++				  }
++				else
++				  FREE_STACK_RETURN (REG_ECOLLATE);
++			      }
++			    datasize = 1;
++			  }
++# endif
++                        /* Throw away the ] at the end of the equivalence
++                           class (or collating symbol).  */
++                        PATFETCH (c);
++
++			/* Allocate the space for the equivalence class
++			   (or collating symbol) (and '\0' if needed).  */
++                        GET_BUFFER_SPACE(datasize);
++			/* Update the pointer to indicate end of buffer.  */
++                        b += datasize;
++
++			if (delim == '=')
++			  { /* equivalence class  */
++			    /* Calculate the offset of char_ranges,
++			       which is next to equivalence_classes.  */
++			    offset = laststart[1] + laststart[2]
++			      + laststart[3] +6;
++			    /* Insert space.  */
++			    insert_space(datasize, laststart + offset, b - 1);
++
++			    /* Write the equivalence_class and \0.  */
++			    for (i = 0 ; i < datasize ; i++)
++			      laststart[offset + i] = str[i];
++
++			    /* Update the length of equivalence_classes.  */
++			    laststart[3] += datasize;
++			    had_char_class = true;
++			  }
++			else /* delim == '.' */
++			  { /* collating symbol  */
++			    /* Calculate the offset of the equivalence_classes,
++			       which is next to collating_symbols.  */
++			    offset = laststart[1] + laststart[2] + 6;
++			    /* Insert space and write the collationg_symbol
++			       and \0.  */
++			    insert_space(datasize, laststart + offset, b-1);
++			    for (i = 0 ; i < datasize ; i++)
++			      laststart[offset + i] = str[i];
++
++			    /* In re_match_2_internal if range_start < -1, we
++			       assume -range_start is the offset of the
++			       collating symbol which is specified as
++			       the character of the range start.  So we assign
++			       -(laststart[1] + laststart[2] + 6) to
++			       range_start.  */
++			    range_start = -(laststart[1] + laststart[2] + 6);
++			    /* Update the length of collating_symbol.  */
++			    laststart[2] += datasize;
++			    had_char_class = false;
++			  }
++		      }
++                    else
++                      {
++                        c1++;
++                        while (c1--)
++                          PATUNFETCH;
++                        BUF_PUSH ('[');
++                        BUF_PUSH (delim);
++                        laststart[5] += 2; /* Update the length of characters  */
++			range_start = delim;
++                        had_char_class = false;
++                      }
++		  }
++                else
++                  {
++                    had_char_class = false;
++		    BUF_PUSH(c);
++		    laststart[5]++;  /* Update the length of characters  */
++		    range_start = c;
++                  }
++	      }
++
++#else /* BYTE */
++            /* Ensure that we have enough space to push a charset: the
++               opcode, the length count, and the bitset; 34 bytes in all.  */
++	    GET_BUFFER_SPACE (34);
++
++            laststart = b;
++
++            /* We test `*p == '^' twice, instead of using an if
++               statement, so we only need one BUF_PUSH.  */
++            BUF_PUSH (*p == '^' ? charset_not : charset);
++            if (*p == '^')
++              p++;
++
++            /* Remember the first position in the bracket expression.  */
++            p1 = p;
++
++            /* Push the number of bytes in the bitmap.  */
++            BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
++
++            /* Clear the whole map.  */
++            bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
++
++            /* charset_not matches newline according to a syntax bit.  */
++            if ((re_opcode_t) b[-2] == charset_not
++                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
++              SET_LIST_BIT ('\n');
++
++            /* Read in characters and ranges, setting map bits.  */
++            for (;;)
++              {
++                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                PATFETCH (c);
++
++                /* \ might escape characters inside [...] and [^...].  */
++                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
++                  {
++                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
++
++                    PATFETCH (c1);
++                    SET_LIST_BIT (c1);
++		    range_start = c1;
++                    continue;
++                  }
++
++                /* Could be the end of the bracket expression.  If it's
++                   not (i.e., when the bracket expression is `[]' so
++                   far), the ']' character bit gets set way below.  */
++                if (c == ']' && p != p1 + 1)
++                  break;
++
++                /* Look ahead to see if it's a range when the last thing
++                   was a character class.  */
++                if (had_char_class && c == '-' && *p != ']')
++                  FREE_STACK_RETURN (REG_ERANGE);
++
++                /* Look ahead to see if it's a range when the last thing
++                   was a character: if this is a hyphen not at the
++                   beginning or the end of a list, then it's the range
++                   operator.  */
++                if (c == '-'
++                    && !(p - 2 >= pattern && p[-2] == '[')
++                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
++                    && *p != ']')
++                  {
++                    reg_errcode_t ret
++                      = byte_compile_range (range_start, &p, pend, translate,
++					    syntax, b);
++                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
++		    range_start = 0xffffffff;
++                  }
++
++                else if (p[0] == '-' && p[1] != ']')
++                  { /* This handles ranges made up of characters only.  */
++                    reg_errcode_t ret;
++
++		    /* Move past the `-'.  */
++                    PATFETCH (c1);
++
++                    ret = byte_compile_range (c, &p, pend, translate, syntax, b);
++                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
++		    range_start = 0xffffffff;
++                  }
++
++                /* See if we're at the beginning of a possible character
++                   class.  */
++
++                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
++                  { /* Leave room for the null.  */
++                    char str[CHAR_CLASS_MAX_LENGTH + 1];
++
++                    PATFETCH (c);
++                    c1 = 0;
++
++                    /* If pattern is `[[:'.  */
++                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                    for (;;)
++                      {
++                        PATFETCH (c);
++                        if ((c == ':' && *p == ']') || p == pend)
++                          break;
++			if (((int) c1) < CHAR_CLASS_MAX_LENGTH)
++			  str[c1++] = c;
++			else
++			  /* This is in any case an invalid class name.  */
++			  str[0] = '\0';
++                      }
++                    str[c1] = '\0';
++
++                    /* If isn't a word bracketed by `[:' and `:]':
++                       undo the ending character, the letters, and leave
++                       the leading `:' and `[' (but set bits for them).  */
++                    if (c == ':' && *p == ']')
++                      {
++# if WIDE_CHAR_SUPPORT
++                        boolean is_lower = STREQ (str, "lower");
++                        boolean is_upper = STREQ (str, "upper");
++			wctype_t wt;
++                        int ch;
++
++			wt = IS_CHAR_CLASS (str);
++			if (wt == 0)
++			  FREE_STACK_RETURN (REG_ECTYPE);
++
++                        /* Throw away the ] at the end of the character
++                           class.  */
++                        PATFETCH (c);
++
++                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                        for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
++			  {
++#  ifdef _LIBC
++			    if (__iswctype (__btowc (ch), wt))
++			      SET_LIST_BIT (ch);
++#  else
++			    if (iswctype (btowc (ch), wt))
++			      SET_LIST_BIT (ch);
++#  endif
++
++			    if (translate && (is_upper || is_lower)
++				&& (ISUPPER (ch) || ISLOWER (ch)))
++			      SET_LIST_BIT (ch);
++			  }
++
++                        had_char_class = true;
++# else
++                        int ch;
++                        boolean is_alnum = STREQ (str, "alnum");
++                        boolean is_alpha = STREQ (str, "alpha");
++                        boolean is_blank = STREQ (str, "blank");
++                        boolean is_cntrl = STREQ (str, "cntrl");
++                        boolean is_digit = STREQ (str, "digit");
++                        boolean is_graph = STREQ (str, "graph");
++                        boolean is_lower = STREQ (str, "lower");
++                        boolean is_print = STREQ (str, "print");
++                        boolean is_punct = STREQ (str, "punct");
++                        boolean is_space = STREQ (str, "space");
++                        boolean is_upper = STREQ (str, "upper");
++                        boolean is_xdigit = STREQ (str, "xdigit");
++
++                        if (!IS_CHAR_CLASS (str))
++			  FREE_STACK_RETURN (REG_ECTYPE);
++
++                        /* Throw away the ] at the end of the character
++                           class.  */
++                        PATFETCH (c);
++
++                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++                        for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
++                          {
++			    /* This was split into 3 if's to
++			       avoid an arbitrary limit in some compiler.  */
++                            if (   (is_alnum  && ISALNUM (ch))
++                                || (is_alpha  && ISALPHA (ch))
++                                || (is_blank  && ISBLANK (ch))
++                                || (is_cntrl  && ISCNTRL (ch)))
++			      SET_LIST_BIT (ch);
++			    if (   (is_digit  && ISDIGIT (ch))
++                                || (is_graph  && ISGRAPH (ch))
++                                || (is_lower  && ISLOWER (ch))
++                                || (is_print  && ISPRINT (ch)))
++			      SET_LIST_BIT (ch);
++			    if (   (is_punct  && ISPUNCT (ch))
++                                || (is_space  && ISSPACE (ch))
++                                || (is_upper  && ISUPPER (ch))
++                                || (is_xdigit && ISXDIGIT (ch)))
++			      SET_LIST_BIT (ch);
++			    if (   translate && (is_upper || is_lower)
++				&& (ISUPPER (ch) || ISLOWER (ch)))
++			      SET_LIST_BIT (ch);
++                          }
++                        had_char_class = true;
++# endif	/* libc || wctype.h */
++                      }
++                    else
++                      {
++                        c1++;
++                        while (c1--)
++                          PATUNFETCH;
++                        SET_LIST_BIT ('[');
++                        SET_LIST_BIT (':');
++			range_start = ':';
++                        had_char_class = false;
++                      }
++                  }
++                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
++		  {
++		    unsigned char str[MB_LEN_MAX + 1];
++# ifdef _LIBC
++		    uint32_t nrules =
++		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++# endif
++
++		    PATFETCH (c);
++		    c1 = 0;
++
++		    /* If pattern is `[[='.  */
++		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++		    for (;;)
++		      {
++			PATFETCH (c);
++			if ((c == '=' && *p == ']') || p == pend)
++			  break;
++			if (c1 < MB_LEN_MAX)
++			  str[c1++] = c;
++			else
++			  /* This is in any case an invalid class name.  */
++			  str[0] = '\0';
++                      }
++		    str[c1] = '\0';
++
++		    if (c == '=' && *p == ']' && str[0] != '\0')
++		      {
++			/* If we have no collation data we use the default
++			   collation in which each character is in a class
++			   by itself.  It also means that ASCII is the
++			   character set and therefore we cannot have character
++			   with more than one byte in the multibyte
++			   representation.  */
++# ifdef _LIBC
++			if (nrules == 0)
++# endif
++			  {
++			    if (c1 != 1)
++			      FREE_STACK_RETURN (REG_ECOLLATE);
++
++			    /* Throw away the ] at the end of the equivalence
++			       class.  */
++			    PATFETCH (c);
++
++			    /* Set the bit for the character.  */
++			    SET_LIST_BIT (str[0]);
++			  }
++# ifdef _LIBC
++			else
++			  {
++			    /* Try to match the byte sequence in `str' against
++			       those known to the collate implementation.
++			       First find out whether the bytes in `str' are
++			       actually from exactly one character.  */
++			    const int32_t *table;
++			    const unsigned char *weights;
++			    const unsigned char *extra;
++			    const int32_t *indirect;
++			    int32_t idx;
++			    const unsigned char *cp = str;
++			    int ch;
++
++			    /* This #include defines a local function!  */
++#  include <locale/weight.h>
++
++			    table = (const int32_t *)
++			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
++			    weights = (const unsigned char *)
++			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
++			    extra = (const unsigned char *)
++			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
++			    indirect = (const int32_t *)
++			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
++
++			    idx = findidx (&cp, c1);
++			    if (idx == 0 || cp < str + c1)
++			      /* This is no valid character.  */
++			      FREE_STACK_RETURN (REG_ECOLLATE);
++
++			    /* Throw away the ] at the end of the equivalence
++			       class.  */
++			    PATFETCH (c);
++
++			    /* Now we have to go throught the whole table
++			       and find all characters which have the same
++			       first level weight.
++
++			       XXX Note that this is not entirely correct.
++			       we would have to match multibyte sequences
++			       but this is not possible with the current
++			       implementation.  */
++			    for (ch = 1; ch < 256; ++ch)
++			      /* XXX This test would have to be changed if we
++				 would allow matching multibyte sequences.  */
++			      if (table[ch] > 0)
++				{
++				  int32_t idx2 = table[ch];
++				  size_t len = weights[idx2];
++
++				  /* Test whether the lenghts match.  */
++				  if (weights[idx] == len)
++				    {
++				      /* They do.  New compare the bytes of
++					 the weight.  */
++				      size_t cnt = 0;
++
++				      while (cnt < len
++					     && (weights[idx + 1 + cnt]
++						 == weights[idx2 + 1 + cnt]))
++					++cnt;
++
++				      if (cnt == len)
++					/* They match.  Mark the character as
++					   acceptable.  */
++					SET_LIST_BIT (ch);
++				    }
++				}
++			  }
++# endif
++			had_char_class = true;
++		      }
++                    else
++                      {
++                        c1++;
++                        while (c1--)
++                          PATUNFETCH;
++                        SET_LIST_BIT ('[');
++                        SET_LIST_BIT ('=');
++			range_start = '=';
++                        had_char_class = false;
++                      }
++		  }
++                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
++		  {
++		    unsigned char str[128];	/* Should be large enough.  */
++# ifdef _LIBC
++		    uint32_t nrules =
++		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++# endif
++
++		    PATFETCH (c);
++		    c1 = 0;
++
++		    /* If pattern is `[[.'.  */
++		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
++
++		    for (;;)
++		      {
++			PATFETCH (c);
++			if ((c == '.' && *p == ']') || p == pend)
++			  break;
++			if (c1 < sizeof (str))
++			  str[c1++] = c;
++			else
++			  /* This is in any case an invalid class name.  */
++			  str[0] = '\0';
++                      }
++		    str[c1] = '\0';
++
++		    if (c == '.' && *p == ']' && str[0] != '\0')
++		      {
++			/* If we have no collation data we use the default
++			   collation in which each character is the name
++			   for its own class which contains only the one
++			   character.  It also means that ASCII is the
++			   character set and therefore we cannot have character
++			   with more than one byte in the multibyte
++			   representation.  */
++# ifdef _LIBC
++			if (nrules == 0)
++# endif
++			  {
++			    if (c1 != 1)
++			      FREE_STACK_RETURN (REG_ECOLLATE);
++
++			    /* Throw away the ] at the end of the equivalence
++			       class.  */
++			    PATFETCH (c);
++
++			    /* Set the bit for the character.  */
++			    SET_LIST_BIT (str[0]);
++			    range_start = ((const unsigned char *) str)[0];
++			  }
++# ifdef _LIBC
++			else
++			  {
++			    /* Try to match the byte sequence in `str' against
++			       those known to the collate implementation.
++			       First find out whether the bytes in `str' are
++			       actually from exactly one character.  */
++			    int32_t table_size;
++			    const int32_t *symb_table;
++			    const unsigned char *extra;
++			    int32_t idx;
++			    int32_t elem;
++			    int32_t second;
++			    int32_t hash;
++
++			    table_size =
++			      _NL_CURRENT_WORD (LC_COLLATE,
++						_NL_COLLATE_SYMB_HASH_SIZEMB);
++			    symb_table = (const int32_t *)
++			      _NL_CURRENT (LC_COLLATE,
++					   _NL_COLLATE_SYMB_TABLEMB);
++			    extra = (const unsigned char *)
++			      _NL_CURRENT (LC_COLLATE,
++					   _NL_COLLATE_SYMB_EXTRAMB);
++
++			    /* Locate the character in the hashing table.  */
++			    hash = elem_hash ((const char *) str, c1);
++
++			    idx = 0;
++			    elem = hash % table_size;
++			    second = hash % (table_size - 2);
++			    while (symb_table[2 * elem] != 0)
++			      {
++				/* First compare the hashing value.  */
++				if (symb_table[2 * elem] == hash
++				    && c1 == extra[symb_table[2 * elem + 1]]
++				    && memcmp (str,
++					       &extra[symb_table[2 * elem + 1]
++						     + 1],
++					       c1) == 0)
++				  {
++				    /* Yep, this is the entry.  */
++				    idx = symb_table[2 * elem + 1];
++				    idx += 1 + extra[idx];
++				    break;
++				  }
++
++				/* Next entry.  */
++				elem += second;
++			      }
++
++			    if (symb_table[2 * elem] == 0)
++			      /* This is no valid character.  */
++			      FREE_STACK_RETURN (REG_ECOLLATE);
++
++			    /* Throw away the ] at the end of the equivalence
++			       class.  */
++			    PATFETCH (c);
++
++			    /* Now add the multibyte character(s) we found
++			       to the accept list.
++
++			       XXX Note that this is not entirely correct.
++			       we would have to match multibyte sequences
++			       but this is not possible with the current
++			       implementation.  Also, we have to match
++			       collating symbols, which expand to more than
++			       one file, as a whole and not allow the
++			       individual bytes.  */
++			    c1 = extra[idx++];
++			    if (c1 == 1)
++			      range_start = extra[idx];
++			    while (c1-- > 0)
++			      {
++				SET_LIST_BIT (extra[idx]);
++				++idx;
++			      }
++			  }
++# endif
++			had_char_class = false;
++		      }
++                    else
++                      {
++                        c1++;
++                        while (c1--)
++                          PATUNFETCH;
++                        SET_LIST_BIT ('[');
++                        SET_LIST_BIT ('.');
++			range_start = '.';
++                        had_char_class = false;
++                      }
++		  }
++                else
++                  {
++                    had_char_class = false;
++                    SET_LIST_BIT (c);
++		    range_start = c;
++                  }
++              }
++
++            /* Discard any (non)matching list bytes that are all 0 at the
++               end of the map.  Decrease the map-length byte too.  */
++            while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
++              b[-1]--;
++            b += b[-1];
++#endif /* WCHAR */
++          }
++          break;
++
++
++	case '(':
++          if (syntax & RE_NO_BK_PARENS)
++            goto handle_open;
++          else
++            goto normal_char;
++
++
++        case ')':
++          if (syntax & RE_NO_BK_PARENS)
++            goto handle_close;
++          else
++            goto normal_char;
++
++
++        case '\n':
++          if (syntax & RE_NEWLINE_ALT)
++            goto handle_alt;
++          else
++            goto normal_char;
++
++
++	case '|':
++          if (syntax & RE_NO_BK_VBAR)
++            goto handle_alt;
++          else
++            goto normal_char;
++
++
++        case '{':
++           if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
++             goto handle_interval;
++           else
++             goto normal_char;
++
++
++        case '\\':
++          if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
++
++          /* Do not translate the character after the \, so that we can
++             distinguish, e.g., \B from \b, even if we normally would
++             translate, e.g., B to b.  */
++          PATFETCH_RAW (c);
++
++          switch (c)
++            {
++            case '(':
++              if (syntax & RE_NO_BK_PARENS)
++                goto normal_backslash;
++
++            handle_open:
++              bufp->re_nsub++;
++              regnum++;
++
++              if (COMPILE_STACK_FULL)
++                {
++                  RETALLOC (compile_stack.stack, compile_stack.size << 1,
++                            compile_stack_elt_t);
++                  if (compile_stack.stack == NULL) return REG_ESPACE;
++
++                  compile_stack.size <<= 1;
++                }
++
++              /* These are the values to restore when we hit end of this
++                 group.  They are all relative offsets, so that if the
++                 whole pattern moves because of realloc, they will still
++                 be valid.  */
++              COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR;
++              COMPILE_STACK_TOP.fixup_alt_jump
++                = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0;
++              COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR;
++              COMPILE_STACK_TOP.regnum = regnum;
++
++              /* We will eventually replace the 0 with the number of
++                 groups inner to this one.  But do not push a
++                 start_memory for groups beyond the last one we can
++                 represent in the compiled pattern.  */
++              if (regnum <= MAX_REGNUM)
++                {
++                  COMPILE_STACK_TOP.inner_group_offset = b
++		    - COMPILED_BUFFER_VAR + 2;
++                  BUF_PUSH_3 (start_memory, regnum, 0);
++                }
++
++              compile_stack.avail++;
++
++              fixup_alt_jump = 0;
++              laststart = 0;
++              begalt = b;
++	      /* If we've reached MAX_REGNUM groups, then this open
++		 won't actually generate any code, so we'll have to
++		 clear pending_exact explicitly.  */
++	      pending_exact = 0;
++              break;
++
++
++            case ')':
++              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
++
++              if (COMPILE_STACK_EMPTY)
++		{
++		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
++		    goto normal_backslash;
++		  else
++		    FREE_STACK_RETURN (REG_ERPAREN);
++		}
++
++            handle_close:
++              if (fixup_alt_jump)
++                { /* Push a dummy failure point at the end of the
++                     alternative for a possible future
++                     `pop_failure_jump' to pop.  See comments at
++                     `push_dummy_failure' in `re_match_2'.  */
++                  BUF_PUSH (push_dummy_failure);
++
++                  /* We allocated space for this jump when we assigned
++                     to `fixup_alt_jump', in the `handle_alt' case below.  */
++                  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
++                }
++
++              /* See similar code for backslashed left paren above.  */
++              if (COMPILE_STACK_EMPTY)
++		{
++		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
++		    goto normal_char;
++		  else
++		    FREE_STACK_RETURN (REG_ERPAREN);
++		}
++
++              /* Since we just checked for an empty stack above, this
++                 ``can't happen''.  */
++              assert (compile_stack.avail != 0);
++              {
++                /* We don't just want to restore into `regnum', because
++                   later groups should continue to be numbered higher,
++                   as in `(ab)c(de)' -- the second group is #2.  */
++                regnum_t this_group_regnum;
++
++                compile_stack.avail--;
++                begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset;
++                fixup_alt_jump
++                  = COMPILE_STACK_TOP.fixup_alt_jump
++                    ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1
++                    : 0;
++                laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset;
++                this_group_regnum = COMPILE_STACK_TOP.regnum;
++		/* If we've reached MAX_REGNUM groups, then this open
++		   won't actually generate any code, so we'll have to
++		   clear pending_exact explicitly.  */
++		pending_exact = 0;
++
++                /* We're at the end of the group, so now we know how many
++                   groups were inside this one.  */
++                if (this_group_regnum <= MAX_REGNUM)
++                  {
++		    UCHAR_T *inner_group_loc
++                      = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset;
++
++                    *inner_group_loc = regnum - this_group_regnum;
++                    BUF_PUSH_3 (stop_memory, this_group_regnum,
++                                regnum - this_group_regnum);
++                  }
++              }
++              break;
++
++
++            case '|':					/* `\|'.  */
++              if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
++                goto normal_backslash;
++            handle_alt:
++              if (syntax & RE_LIMITED_OPS)
++                goto normal_char;
++
++              /* Insert before the previous alternative a jump which
++                 jumps to this alternative if the former fails.  */
++              GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++              INSERT_JUMP (on_failure_jump, begalt,
++			   b + 2 + 2 * OFFSET_ADDRESS_SIZE);
++              pending_exact = 0;
++              b += 1 + OFFSET_ADDRESS_SIZE;
++
++              /* The alternative before this one has a jump after it
++                 which gets executed if it gets matched.  Adjust that
++                 jump so it will jump to this alternative's analogous
++                 jump (put in below, which in turn will jump to the next
++                 (if any) alternative's such jump, etc.).  The last such
++                 jump jumps to the correct final destination.  A picture:
++                          _____ _____
++                          |   | |   |
++                          |   v |   v
++                         a | b   | c
++
++                 If we are at `b', then fixup_alt_jump right now points to a
++                 three-byte space after `a'.  We'll put in the jump, set
++                 fixup_alt_jump to right after `b', and leave behind three
++                 bytes which we'll fill in when we get to after `c'.  */
++
++              if (fixup_alt_jump)
++                STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
++
++              /* Mark and leave space for a jump after this alternative,
++                 to be filled in later either by next alternative or
++                 when know we're at the end of a series of alternatives.  */
++              fixup_alt_jump = b;
++              GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++              b += 1 + OFFSET_ADDRESS_SIZE;
++
++              laststart = 0;
++              begalt = b;
++              break;
++
++
++            case '{':
++              /* If \{ is a literal.  */
++              if (!(syntax & RE_INTERVALS)
++                     /* If we're at `\{' and it's not the open-interval
++                        operator.  */
++		  || (syntax & RE_NO_BK_BRACES))
++                goto normal_backslash;
++
++            handle_interval:
++              {
++                /* If got here, then the syntax allows intervals.  */
++
++                /* At least (most) this many matches must be made.  */
++                int lower_bound = -1, upper_bound = -1;
++
++		/* Place in the uncompiled pattern (i.e., just after
++		   the '{') to go back to if the interval is invalid.  */
++		const CHAR_T *beg_interval = p;
++
++                if (p == pend)
++		  goto invalid_interval;
++
++                GET_UNSIGNED_NUMBER (lower_bound);
++
++                if (c == ',')
++                  {
++                    GET_UNSIGNED_NUMBER (upper_bound);
++		    if (upper_bound < 0)
++		      upper_bound = RE_DUP_MAX;
++                  }
++                else
++                  /* Interval such as `{1}' => match exactly once. */
++                  upper_bound = lower_bound;
++
++                if (! (0 <= lower_bound && lower_bound <= upper_bound))
++		  goto invalid_interval;
++
++                if (!(syntax & RE_NO_BK_BRACES))
++                  {
++		    if (c != '\\' || p == pend)
++		      goto invalid_interval;
++                    PATFETCH (c);
++                  }
++
++                if (c != '}')
++		  goto invalid_interval;
++
++                /* If it's invalid to have no preceding re.  */
++                if (!laststart)
++                  {
++		    if (syntax & RE_CONTEXT_INVALID_OPS
++			&& !(syntax & RE_INVALID_INTERVAL_ORD))
++                      FREE_STACK_RETURN (REG_BADRPT);
++                    else if (syntax & RE_CONTEXT_INDEP_OPS)
++                      laststart = b;
++                    else
++                      goto unfetch_interval;
++                  }
++
++                /* We just parsed a valid interval.  */
++
++                if (RE_DUP_MAX < upper_bound)
++		  FREE_STACK_RETURN (REG_BADBR);
++
++                /* If the upper bound is zero, don't want to succeed at
++                   all; jump from `laststart' to `b + 3', which will be
++		   the end of the buffer after we insert the jump.  */
++		/* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE'
++		   instead of 'b + 3'.  */
++                 if (upper_bound == 0)
++                   {
++                     GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
++                     INSERT_JUMP (jump, laststart, b + 1
++				  + OFFSET_ADDRESS_SIZE);
++                     b += 1 + OFFSET_ADDRESS_SIZE;
++                   }
++
++                 /* Otherwise, we have a nontrivial interval.  When
++                    we're all done, the pattern will look like:
++                      set_number_at <jump count> <upper bound>
++                      set_number_at <succeed_n count> <lower bound>
++                      succeed_n <after jump addr> <succeed_n count>
++                      <body of loop>
++                      jump_n <succeed_n addr> <jump count>
++                    (The upper bound and `jump_n' are omitted if
++                    `upper_bound' is 1, though.)  */
++                 else
++                   { /* If the upper bound is > 1, we need to insert
++                        more at the end of the loop.  */
++                     unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE +
++		       (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE);
++
++                     GET_BUFFER_SPACE (nbytes);
++
++                     /* Initialize lower bound of the `succeed_n', even
++                        though it will be set during matching by its
++                        attendant `set_number_at' (inserted next),
++                        because `re_compile_fastmap' needs to know.
++                        Jump to the `jump_n' we might insert below.  */
++                     INSERT_JUMP2 (succeed_n, laststart,
++                                   b + 1 + 2 * OFFSET_ADDRESS_SIZE
++				   + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE)
++				   , lower_bound);
++                     b += 1 + 2 * OFFSET_ADDRESS_SIZE;
++
++                     /* Code to initialize the lower bound.  Insert
++                        before the `succeed_n'.  The `5' is the last two
++                        bytes of this `set_number_at', plus 3 bytes of
++                        the following `succeed_n'.  */
++		     /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE'
++			is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE'
++			of the following `succeed_n'.  */
++                     PREFIX(insert_op2) (set_number_at, laststart, 1
++				 + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b);
++                     b += 1 + 2 * OFFSET_ADDRESS_SIZE;
++
++                     if (upper_bound > 1)
++                       { /* More than one repetition is allowed, so
++                            append a backward jump to the `succeed_n'
++                            that starts this interval.
++
++                            When we've reached this during matching,
++                            we'll have matched the interval once, so
++                            jump back only `upper_bound - 1' times.  */
++                         STORE_JUMP2 (jump_n, b, laststart
++				      + 2 * OFFSET_ADDRESS_SIZE + 1,
++                                      upper_bound - 1);
++                         b += 1 + 2 * OFFSET_ADDRESS_SIZE;
++
++                         /* The location we want to set is the second
++                            parameter of the `jump_n'; that is `b-2' as
++                            an absolute address.  `laststart' will be
++                            the `set_number_at' we're about to insert;
++                            `laststart+3' the number to set, the source
++                            for the relative address.  But we are
++                            inserting into the middle of the pattern --
++                            so everything is getting moved up by 5.
++                            Conclusion: (b - 2) - (laststart + 3) + 5,
++                            i.e., b - laststart.
++
++                            We insert this at the beginning of the loop
++                            so that if we fail during matching, we'll
++                            reinitialize the bounds.  */
++                         PREFIX(insert_op2) (set_number_at, laststart,
++					     b - laststart,
++					     upper_bound - 1, b);
++                         b += 1 + 2 * OFFSET_ADDRESS_SIZE;
++                       }
++                   }
++                pending_exact = 0;
++		break;
++
++	      invalid_interval:
++		if (!(syntax & RE_INVALID_INTERVAL_ORD))
++		  FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR);
++	      unfetch_interval:
++		/* Match the characters as literals.  */
++		p = beg_interval;
++		c = '{';
++		if (syntax & RE_NO_BK_BRACES)
++		  goto normal_char;
++		else
++		  goto normal_backslash;
++	      }
++
++#ifdef emacs
++            /* There is no way to specify the before_dot and after_dot
++               operators.  rms says this is ok.  --karl  */
++            case '=':
++              BUF_PUSH (at_dot);
++              break;
++
++            case 's':
++              laststart = b;
++              PATFETCH (c);
++              BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
++              break;
++
++            case 'S':
++              laststart = b;
++              PATFETCH (c);
++              BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
++              break;
++#endif /* emacs */
++
++
++            case 'w':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              laststart = b;
++              BUF_PUSH (wordchar);
++              break;
++
++
++            case 'W':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              laststart = b;
++              BUF_PUSH (notwordchar);
++              break;
++
++
++            case '<':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (wordbeg);
++              break;
++
++            case '>':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (wordend);
++              break;
++
++            case 'b':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (wordbound);
++              break;
++
++            case 'B':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (notwordbound);
++              break;
++
++            case '`':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (begbuf);
++              break;
++
++            case '\'':
++	      if (syntax & RE_NO_GNU_OPS)
++		goto normal_char;
++              BUF_PUSH (endbuf);
++              break;
++
++            case '1': case '2': case '3': case '4': case '5':
++            case '6': case '7': case '8': case '9':
++              if (syntax & RE_NO_BK_REFS)
++                goto normal_char;
++
++              c1 = c - '0';
++
++              if (c1 > regnum)
++                FREE_STACK_RETURN (REG_ESUBREG);
++
++              /* Can't back reference to a subexpression if inside of it.  */
++              if (group_in_compile_stack (compile_stack, (regnum_t) c1))
++                goto normal_char;
++
++              laststart = b;
++              BUF_PUSH_2 (duplicate, c1);
++              break;
++
++
++            case '+':
++            case '?':
++              if (syntax & RE_BK_PLUS_QM)
++                goto handle_plus;
++              else
++                goto normal_backslash;
++
++            default:
++            normal_backslash:
++              /* You might think it would be useful for \ to mean
++                 not to translate; but if we don't translate it
++                 it will never match anything.  */
++              c = TRANSLATE (c);
++              goto normal_char;
++            }
++          break;
++
++
++	default:
++        /* Expects the character in `c'.  */
++	normal_char:
++	      /* If no exactn currently being built.  */
++          if (!pending_exact
++#ifdef WCHAR
++	      /* If last exactn handle binary(or character) and
++		 new exactn handle character(or binary).  */
++	      || is_exactn_bin != is_binary[p - 1 - pattern]
++#endif /* WCHAR */
++
++              /* If last exactn not at current position.  */
++              || pending_exact + *pending_exact + 1 != b
++
++              /* We have only one byte following the exactn for the count.  */
++	      || *pending_exact == (1 << BYTEWIDTH) - 1
++
++              /* If followed by a repetition operator.  */
++              || *p == '*' || *p == '^'
++	      || ((syntax & RE_BK_PLUS_QM)
++		  ? *p == '\\' && (p[1] == '+' || p[1] == '?')
++		  : (*p == '+' || *p == '?'))
++	      || ((syntax & RE_INTERVALS)
++                  && ((syntax & RE_NO_BK_BRACES)
++		      ? *p == '{'
++                      : (p[0] == '\\' && p[1] == '{'))))
++	    {
++	      /* Start building a new exactn.  */
++
++              laststart = b;
++
++#ifdef WCHAR
++	      /* Is this exactn binary data or character? */
++	      is_exactn_bin = is_binary[p - 1 - pattern];
++	      if (is_exactn_bin)
++		  BUF_PUSH_2 (exactn_bin, 0);
++	      else
++		  BUF_PUSH_2 (exactn, 0);
++#else
++	      BUF_PUSH_2 (exactn, 0);
++#endif /* WCHAR */
++	      pending_exact = b - 1;
++            }
++
++	  BUF_PUSH (c);
++          (*pending_exact)++;
++	  break;
++        } /* switch (c) */
++    } /* while p != pend */
++
++
++  /* Through the pattern now.  */
++
++  if (fixup_alt_jump)
++    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
++
++  if (!COMPILE_STACK_EMPTY)
++    FREE_STACK_RETURN (REG_EPAREN);
++
++  /* If we don't want backtracking, force success
++     the first time we reach the end of the compiled pattern.  */
++  if (syntax & RE_NO_POSIX_BACKTRACKING)
++    BUF_PUSH (succeed);
++
++#ifdef WCHAR
++  free (pattern);
++  free (mbs_offset);
++  free (is_binary);
++#endif
++  free (compile_stack.stack);
++
++  /* We have succeeded; set the length of the buffer.  */
++#ifdef WCHAR
++  bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR;
++#else
++  bufp->used = b - bufp->buffer;
++#endif
++
++#ifdef DEBUG
++  if (debug)
++    {
++      DEBUG_PRINT1 ("\nCompiled pattern: \n");
++      PREFIX(print_compiled_pattern) (bufp);
++    }
++#endif /* DEBUG */
++
++#ifndef MATCH_MAY_ALLOCATE
++  /* Initialize the failure stack to the largest possible stack.  This
++     isn't necessary unless we're trying to avoid calling alloca in
++     the search and match routines.  */
++  {
++    int num_regs = bufp->re_nsub + 1;
++
++    /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
++       is strictly greater than re_max_failures, the largest possible stack
++       is 2 * re_max_failures failure points.  */
++    if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
++      {
++	fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
++
++# ifdef emacs
++	if (! fail_stack.stack)
++	  fail_stack.stack
++	    = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size
++				    * sizeof (PREFIX(fail_stack_elt_t)));
++	else
++	  fail_stack.stack
++	    = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack,
++				     (fail_stack.size
++				      * sizeof (PREFIX(fail_stack_elt_t))));
++# else /* not emacs */
++	if (! fail_stack.stack)
++	  fail_stack.stack
++	    = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size
++				   * sizeof (PREFIX(fail_stack_elt_t)));
++	else
++	  fail_stack.stack
++	    = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack,
++					    (fail_stack.size
++				     * sizeof (PREFIX(fail_stack_elt_t))));
++# endif /* not emacs */
++      }
++
++   PREFIX(regex_grow_registers) (num_regs);
++  }
++#endif /* not MATCH_MAY_ALLOCATE */
++
++  return REG_NOERROR;
++} /* regex_compile */
++
++/* Subroutines for `regex_compile'.  */
++
++/* Store OP at LOC followed by two-byte integer parameter ARG.  */
++/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
++
++static void
++PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg)
++{
++  *loc = (UCHAR_T) op;
++  STORE_NUMBER (loc + 1, arg);
++}
++
++
++/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
++/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
++
++static void
++PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2)
++{
++  *loc = (UCHAR_T) op;
++  STORE_NUMBER (loc + 1, arg1);
++  STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2);
++}
++
++
++/* Copy the bytes from LOC to END to open up three bytes of space at LOC
++   for OP followed by two-byte integer parameter ARG.  */
++/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
++
++static void
++PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end)
++{
++  register UCHAR_T *pfrom = end;
++  register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE;
++
++  while (pfrom != loc)
++    *--pto = *--pfrom;
++
++  PREFIX(store_op1) (op, loc, arg);
++}
++
++
++/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
++/* ifdef WCHAR, integer parameter is 1 wchar_t.  */
++
++static void
++PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1,
++                    int arg2, UCHAR_T *end)
++{
++  register UCHAR_T *pfrom = end;
++  register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE;
++
++  while (pfrom != loc)
++    *--pto = *--pfrom;
++
++  PREFIX(store_op2) (op, loc, arg1, arg2);
++}
++
++
++/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
++   after an alternative or a begin-subexpression.  We assume there is at
++   least one character before the ^.  */
++
++static boolean
++PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p,
++                          reg_syntax_t syntax)
++{
++  const CHAR_T *prev = p - 2;
++  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
++
++  return
++       /* After a subexpression?  */
++       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
++       /* After an alternative?  */
++    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
++}
++
++
++/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
++   at least one character after the $, i.e., `P < PEND'.  */
++
++static boolean
++PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend,
++                          reg_syntax_t syntax)
++{
++  const CHAR_T *next = p;
++  boolean next_backslash = *next == '\\';
++  const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0;
++
++  return
++       /* Before a subexpression?  */
++       (syntax & RE_NO_BK_PARENS ? *next == ')'
++        : next_backslash && next_next && *next_next == ')')
++       /* Before an alternative?  */
++    || (syntax & RE_NO_BK_VBAR ? *next == '|'
++        : next_backslash && next_next && *next_next == '|');
++}
++
++#else /* not INSIDE_RECURSION */
++
++/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
++   false if it's not.  */
++
++static boolean
++group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
++{
++  int this_element;
++
++  for (this_element = compile_stack.avail - 1;
++       this_element >= 0;
++       this_element--)
++    if (compile_stack.stack[this_element].regnum == regnum)
++      return true;
++
++  return false;
++}
++#endif /* not INSIDE_RECURSION */
++
++#ifdef INSIDE_RECURSION
++
++#ifdef WCHAR
++/* This insert space, which size is "num", into the pattern at "loc".
++   "end" must point the end of the allocated buffer.  */
++static void
++insert_space (int num, CHAR_T *loc, CHAR_T *end)
++{
++  register CHAR_T *pto = end;
++  register CHAR_T *pfrom = end - num;
++
++  while (pfrom >= loc)
++    *pto-- = *pfrom--;
++}
++#endif /* WCHAR */
++
++#ifdef WCHAR
++static reg_errcode_t
++wcs_compile_range (CHAR_T range_start_char, const CHAR_T **p_ptr,
++                   const CHAR_T *pend, RE_TRANSLATE_TYPE translate,
++                   reg_syntax_t syntax, CHAR_T *b, CHAR_T *char_set)
++{
++  const CHAR_T *p = *p_ptr;
++  CHAR_T range_start, range_end;
++  reg_errcode_t ret;
++# ifdef _LIBC
++  uint32_t nrules;
++  uint32_t start_val, end_val;
++# endif
++  if (p == pend)
++    return REG_ERANGE;
++
++# ifdef _LIBC
++  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++  if (nrules != 0)
++    {
++      const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE,
++						       _NL_COLLATE_COLLSEQWC);
++      const unsigned char *extra = (const unsigned char *)
++	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
++
++      if (range_start_char < -1)
++	{
++	  /* range_start is a collating symbol.  */
++	  int32_t *wextra;
++	  /* Retreive the index and get collation sequence value.  */
++	  wextra = (int32_t*)(extra + char_set[-range_start_char]);
++	  start_val = wextra[1 + *wextra];
++	}
++      else
++	start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char));
++
++      end_val = collseq_table_lookup (collseq, TRANSLATE (p[0]));
++
++      /* Report an error if the range is empty and the syntax prohibits
++	 this.  */
++      ret = ((syntax & RE_NO_EMPTY_RANGES)
++	     && (start_val > end_val))? REG_ERANGE : REG_NOERROR;
++
++      /* Insert space to the end of the char_ranges.  */
++      insert_space(2, b - char_set[5] - 2, b - 1);
++      *(b - char_set[5] - 2) = (wchar_t)start_val;
++      *(b - char_set[5] - 1) = (wchar_t)end_val;
++      char_set[4]++; /* ranges_index */
++    }
++  else
++# endif
++    {
++      range_start = (range_start_char >= 0)? TRANSLATE (range_start_char):
++	range_start_char;
++      range_end = TRANSLATE (p[0]);
++      /* Report an error if the range is empty and the syntax prohibits
++	 this.  */
++      ret = ((syntax & RE_NO_EMPTY_RANGES)
++	     && (range_start > range_end))? REG_ERANGE : REG_NOERROR;
++
++      /* Insert space to the end of the char_ranges.  */
++      insert_space(2, b - char_set[5] - 2, b - 1);
++      *(b - char_set[5] - 2) = range_start;
++      *(b - char_set[5] - 1) = range_end;
++      char_set[4]++; /* ranges_index */
++    }
++  /* Have to increment the pointer into the pattern string, so the
++     caller isn't still at the ending character.  */
++  (*p_ptr)++;
++
++  return ret;
++}
++#else /* BYTE */
++/* Read the ending character of a range (in a bracket expression) from the
++   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
++   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
++   Then we set the translation of all bits between the starting and
++   ending characters (inclusive) in the compiled pattern B.
++
++   Return an error code.
++
++   We use these short variable names so we can use the same macros as
++   `regex_compile' itself.  */
++
++static reg_errcode_t
++byte_compile_range (unsigned int range_start_char, const char **p_ptr,
++                    const char *pend, RE_TRANSLATE_TYPE translate,
++                    reg_syntax_t syntax, unsigned char *b)
++{
++  unsigned this_char;
++  const char *p = *p_ptr;
++  reg_errcode_t ret;
++# if _LIBC
++  const unsigned char *collseq;
++  unsigned int start_colseq;
++  unsigned int end_colseq;
++# else
++  unsigned end_char;
++# endif
++
++  if (p == pend)
++    return REG_ERANGE;
++
++  /* Have to increment the pointer into the pattern string, so the
++     caller isn't still at the ending character.  */
++  (*p_ptr)++;
++
++  /* Report an error if the range is empty and the syntax prohibits this.  */
++  ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
++
++# if _LIBC
++  collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
++						 _NL_COLLATE_COLLSEQMB);
++
++  start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)];
++  end_colseq = collseq[(unsigned char) TRANSLATE (p[0])];
++  for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
++    {
++      unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)];
++
++      if (start_colseq <= this_colseq && this_colseq <= end_colseq)
++	{
++	  SET_LIST_BIT (TRANSLATE (this_char));
++	  ret = REG_NOERROR;
++	}
++    }
++# else
++  /* Here we see why `this_char' has to be larger than an `unsigned
++     char' -- we would otherwise go into an infinite loop, since all
++     characters <= 0xff.  */
++  range_start_char = TRANSLATE (range_start_char);
++  /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE,
++     and some compilers cast it to int implicitly, so following for_loop
++     may fall to (almost) infinite loop.
++     e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff.
++     To avoid this, we cast p[0] to unsigned int and truncate it.  */
++  end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1));
++
++  for (this_char = range_start_char; this_char <= end_char; ++this_char)
++    {
++      SET_LIST_BIT (TRANSLATE (this_char));
++      ret = REG_NOERROR;
++    }
++# endif
++
++  return ret;
++}
++#endif /* WCHAR */
++
++/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
++   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
++   characters can start a string that matches the pattern.  This fastmap
++   is used by re_search to skip quickly over impossible starting points.
++
++   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
++   area as BUFP->fastmap.
++
++   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
++   the pattern buffer.
++
++   Returns 0 if we succeed, -2 if an internal error.   */
++
++#ifdef WCHAR
++/* local function for re_compile_fastmap.
++   truncate wchar_t character to char.  */
++static unsigned char truncate_wchar (CHAR_T c);
++
++static unsigned char
++truncate_wchar (CHAR_T c)
++{
++  unsigned char buf[MB_CUR_MAX];
++  mbstate_t state;
++  int retval;
++  memset (&state, '\0', sizeof (state));
++# ifdef _LIBC
++  retval = __wcrtomb (buf, c, &state);
++# else
++  retval = wcrtomb (buf, c, &state);
++# endif
++  return retval > 0 ? buf[0] : (unsigned char) c;
++}
++#endif /* WCHAR */
++
++static int
++PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp)
++{
++  int j, k;
++#ifdef MATCH_MAY_ALLOCATE
++  PREFIX(fail_stack_type) fail_stack;
++#endif
++#ifndef REGEX_MALLOC
++  char *destination;
++#endif
++
++  register char *fastmap = bufp->fastmap;
++
++#ifdef WCHAR
++  /* We need to cast pattern to (wchar_t*), because we casted this compiled
++     pattern to (char*) in regex_compile.  */
++  UCHAR_T *pattern = (UCHAR_T*)bufp->buffer;
++  register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used);
++#else /* BYTE */
++  UCHAR_T *pattern = bufp->buffer;
++  register UCHAR_T *pend = pattern + bufp->used;
++#endif /* WCHAR */
++  UCHAR_T *p = pattern;
++
++#ifdef REL_ALLOC
++  /* This holds the pointer to the failure stack, when
++     it is allocated relocatably.  */
++  fail_stack_elt_t *failure_stack_ptr;
++#endif
++
++  /* Assume that each path through the pattern can be null until
++     proven otherwise.  We set this false at the bottom of switch
++     statement, to which we get only if a particular path doesn't
++     match the empty string.  */
++  boolean path_can_be_null = true;
++
++  /* We aren't doing a `succeed_n' to begin with.  */
++  boolean succeed_n_p = false;
++
++  assert (fastmap != NULL && p != NULL);
++
++  INIT_FAIL_STACK ();
++  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
++  bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
++  bufp->can_be_null = 0;
++
++  while (1)
++    {
++      if (p == pend || *p == (UCHAR_T) succeed)
++	{
++	  /* We have reached the (effective) end of pattern.  */
++	  if (!FAIL_STACK_EMPTY ())
++	    {
++	      bufp->can_be_null |= path_can_be_null;
++
++	      /* Reset for next path.  */
++	      path_can_be_null = true;
++
++	      p = fail_stack.stack[--fail_stack.avail].pointer;
++
++	      continue;
++	    }
++	  else
++	    break;
++	}
++
++      /* We should never be about to go beyond the end of the pattern.  */
++      assert (p < pend);
++
++      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
++	{
++
++        /* I guess the idea here is to simply not bother with a fastmap
++           if a backreference is used, since it's too hard to figure out
++           the fastmap for the corresponding group.  Setting
++           `can_be_null' stops `re_search_2' from using the fastmap, so
++           that is all we do.  */
++	case duplicate:
++	  bufp->can_be_null = 1;
++          goto done;
++
++
++      /* Following are the cases which match a character.  These end
++         with `break'.  */
++
++#ifdef WCHAR
++	case exactn:
++          fastmap[truncate_wchar(p[1])] = 1;
++	  break;
++#else /* BYTE */
++	case exactn:
++          fastmap[p[1]] = 1;
++	  break;
++#endif /* WCHAR */
++#ifdef MBS_SUPPORT
++	case exactn_bin:
++	  fastmap[p[1]] = 1;
++	  break;
++#endif
++
++#ifdef WCHAR
++        /* It is hard to distinguish fastmap from (multi byte) characters
++           which depends on current locale.  */
++        case charset:
++	case charset_not:
++	case wordchar:
++	case notwordchar:
++          bufp->can_be_null = 1;
++          goto done;
++#else /* BYTE */
++        case charset:
++          for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
++	    if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
++              fastmap[j] = 1;
++	  break;
++
++
++	case charset_not:
++	  /* Chars beyond end of map must be allowed.  */
++	  for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
++            fastmap[j] = 1;
++
++	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
++	    if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
++              fastmap[j] = 1;
++          break;
++
++
++	case wordchar:
++	  for (j = 0; j < (1 << BYTEWIDTH); j++)
++	    if (SYNTAX (j) == Sword)
++	      fastmap[j] = 1;
++	  break;
++
++
++	case notwordchar:
++	  for (j = 0; j < (1 << BYTEWIDTH); j++)
++	    if (SYNTAX (j) != Sword)
++	      fastmap[j] = 1;
++	  break;
++#endif /* WCHAR */
++
++        case anychar:
++	  {
++	    int fastmap_newline = fastmap['\n'];
++
++	    /* `.' matches anything ...  */
++	    for (j = 0; j < (1 << BYTEWIDTH); j++)
++	      fastmap[j] = 1;
++
++	    /* ... except perhaps newline.  */
++	    if (!(bufp->syntax & RE_DOT_NEWLINE))
++	      fastmap['\n'] = fastmap_newline;
++
++	    /* Return if we have already set `can_be_null'; if we have,
++	       then the fastmap is irrelevant.  Something's wrong here.  */
++	    else if (bufp->can_be_null)
++	      goto done;
++
++	    /* Otherwise, have to check alternative paths.  */
++	    break;
++	  }
++
++#ifdef emacs
++        case syntaxspec:
++	  k = *p++;
++	  for (j = 0; j < (1 << BYTEWIDTH); j++)
++	    if (SYNTAX (j) == (enum syntaxcode) k)
++	      fastmap[j] = 1;
++	  break;
++
++
++	case notsyntaxspec:
++	  k = *p++;
++	  for (j = 0; j < (1 << BYTEWIDTH); j++)
++	    if (SYNTAX (j) != (enum syntaxcode) k)
++	      fastmap[j] = 1;
++	  break;
++
++
++      /* All cases after this match the empty string.  These end with
++         `continue'.  */
++
++
++	case before_dot:
++	case at_dot:
++	case after_dot:
++          continue;
++#endif /* emacs */
++
++
++        case no_op:
++        case begline:
++        case endline:
++	case begbuf:
++	case endbuf:
++	case wordbound:
++	case notwordbound:
++	case wordbeg:
++	case wordend:
++        case push_dummy_failure:
++          continue;
++
++
++	case jump_n:
++        case pop_failure_jump:
++	case maybe_pop_jump:
++	case jump:
++        case jump_past_alt:
++	case dummy_failure_jump:
++          EXTRACT_NUMBER_AND_INCR (j, p);
++	  p += j;
++	  if (j > 0)
++	    continue;
++
++          /* Jump backward implies we just went through the body of a
++             loop and matched nothing.  Opcode jumped to should be
++             `on_failure_jump' or `succeed_n'.  Just treat it like an
++             ordinary jump.  For a * loop, it has pushed its failure
++             point already; if so, discard that as redundant.  */
++          if ((re_opcode_t) *p != on_failure_jump
++	      && (re_opcode_t) *p != succeed_n)
++	    continue;
++
++          p++;
++          EXTRACT_NUMBER_AND_INCR (j, p);
++          p += j;
++
++          /* If what's on the stack is where we are now, pop it.  */
++          if (!FAIL_STACK_EMPTY ()
++	      && fail_stack.stack[fail_stack.avail - 1].pointer == p)
++            fail_stack.avail--;
++
++          continue;
++
++
++        case on_failure_jump:
++        case on_failure_keep_string_jump:
++	handle_on_failure_jump:
++          EXTRACT_NUMBER_AND_INCR (j, p);
++
++          /* For some patterns, e.g., `(a?)?', `p+j' here points to the
++             end of the pattern.  We don't want to push such a point,
++             since when we restore it above, entering the switch will
++             increment `p' past the end of the pattern.  We don't need
++             to push such a point since we obviously won't find any more
++             fastmap entries beyond `pend'.  Such a pattern can match
++             the null string, though.  */
++          if (p + j < pend)
++            {
++              if (!PUSH_PATTERN_OP (p + j, fail_stack))
++		{
++		  RESET_FAIL_STACK ();
++		  return -2;
++		}
++            }
++          else
++            bufp->can_be_null = 1;
++
++          if (succeed_n_p)
++            {
++              EXTRACT_NUMBER_AND_INCR (k, p);	/* Skip the n.  */
++              succeed_n_p = false;
++	    }
++
++          continue;
++
++
++	case succeed_n:
++          /* Get to the number of times to succeed.  */
++          p += OFFSET_ADDRESS_SIZE;
++
++          /* Increment p past the n for when k != 0.  */
++          EXTRACT_NUMBER_AND_INCR (k, p);
++          if (k == 0)
++	    {
++              p -= 2 * OFFSET_ADDRESS_SIZE;
++  	      succeed_n_p = true;  /* Spaghetti code alert.  */
++              goto handle_on_failure_jump;
++            }
++          continue;
++
++
++	case set_number_at:
++          p += 2 * OFFSET_ADDRESS_SIZE;
++          continue;
++
++
++	case start_memory:
++        case stop_memory:
++	  p += 2;
++	  continue;
++
++
++	default:
++          abort (); /* We have listed all the cases.  */
++        } /* switch *p++ */
++
++      /* Getting here means we have found the possible starting
++         characters for one path of the pattern -- and that the empty
++         string does not match.  We need not follow this path further.
++         Instead, look at the next alternative (remembered on the
++         stack), or quit if no more.  The test at the top of the loop
++         does these things.  */
++      path_can_be_null = false;
++      p = pend;
++    } /* while p */
++
++  /* Set `can_be_null' for the last path (also the first path, if the
++     pattern is empty).  */
++  bufp->can_be_null |= path_can_be_null;
++
++ done:
++  RESET_FAIL_STACK ();
++  return 0;
++}
++
++#else /* not INSIDE_RECURSION */
++
++int
++re_compile_fastmap (struct re_pattern_buffer *bufp)
++{
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    return wcs_re_compile_fastmap(bufp);
++  else
++# endif
++    return byte_re_compile_fastmap(bufp);
++} /* re_compile_fastmap */
++#ifdef _LIBC
++weak_alias (__re_compile_fastmap, re_compile_fastmap)
++#endif
++
++
++/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
++   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
++   this memory for recording register information.  STARTS and ENDS
++   must be allocated using the malloc library routine, and must each
++   be at least NUM_REGS * sizeof (regoff_t) bytes long.
++
++   If NUM_REGS == 0, then subsequent matches should allocate their own
++   register data.
++
++   Unless this function is called, the first search or match using
++   PATTERN_BUFFER will allocate its own register data, without
++   freeing the old data.  */
++
++void
++re_set_registers (struct re_pattern_buffer *bufp,
++                  struct re_registers *regs, unsigned num_regs,
++                  regoff_t *starts, regoff_t *ends)
++{
++  if (num_regs)
++    {
++      bufp->regs_allocated = REGS_REALLOCATE;
++      regs->num_regs = num_regs;
++      regs->start = starts;
++      regs->end = ends;
++    }
++  else
++    {
++      bufp->regs_allocated = REGS_UNALLOCATED;
++      regs->num_regs = 0;
++      regs->start = regs->end = (regoff_t *) 0;
++    }
++}
++#ifdef _LIBC
++weak_alias (__re_set_registers, re_set_registers)
++#endif
++
++/* Searching routines.  */
++
++/* Like re_search_2, below, but only one string is specified, and
++   doesn't let you say where to stop matching.  */
++
++int
++re_search (struct re_pattern_buffer *bufp, const char *string, int size,
++           int startpos, int range, struct re_registers *regs)
++{
++  return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
++		      regs, size);
++}
++#ifdef _LIBC
++weak_alias (__re_search, re_search)
++#endif
++
++
++/* Using the compiled pattern in BUFP->buffer, first tries to match the
++   virtual concatenation of STRING1 and STRING2, starting first at index
++   STARTPOS, then at STARTPOS + 1, and so on.
++
++   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
++
++   RANGE is how far to scan while trying to match.  RANGE = 0 means try
++   only at STARTPOS; in general, the last start tried is STARTPOS +
++   RANGE.
++
++   In REGS, return the indices of the virtual concatenation of STRING1
++   and STRING2 that matched the entire BUFP->buffer and its contained
++   subexpressions.
++
++   Do not consider matching one past the index STOP in the virtual
++   concatenation of STRING1 and STRING2.
++
++   We return either the position in the strings at which the match was
++   found, -1 if no match, or -2 if error (such as failure
++   stack overflow).  */
++
++int
++re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1,
++             const char *string2, int size2, int startpos, int range,
++             struct re_registers *regs, int stop)
++{
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos,
++			    range, regs, stop);
++  else
++# endif
++    return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos,
++			     range, regs, stop);
++} /* re_search_2 */
++#ifdef _LIBC
++weak_alias (__re_search_2, re_search_2)
++#endif
++
++#endif /* not INSIDE_RECURSION */
++
++#ifdef INSIDE_RECURSION
++
++#ifdef MATCH_MAY_ALLOCATE
++# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
++#else
++# define FREE_VAR(var) if (var) free (var); var = NULL
++#endif
++
++#ifdef WCHAR
++# define MAX_ALLOCA_SIZE	2000
++
++# define FREE_WCS_BUFFERS() \
++  do {									      \
++    if (size1 > MAX_ALLOCA_SIZE)					      \
++      {									      \
++	free (wcs_string1);						      \
++	free (mbs_offset1);						      \
++      }									      \
++    else								      \
++      {									      \
++	FREE_VAR (wcs_string1);						      \
++	FREE_VAR (mbs_offset1);						      \
++      }									      \
++    if (size2 > MAX_ALLOCA_SIZE) 					      \
++      {									      \
++	free (wcs_string2);						      \
++	free (mbs_offset2);						      \
++      }									      \
++    else								      \
++      {									      \
++	FREE_VAR (wcs_string2);						      \
++	FREE_VAR (mbs_offset2);						      \
++      }									      \
++  } while (0)
++
++#endif
++
++
++static int
++PREFIX(re_search_2) (struct re_pattern_buffer *bufp, const char *string1,
++                     int size1, const char *string2, int size2,
++                     int startpos, int range,
++                     struct re_registers *regs, int stop)
++{
++  int val;
++  register char *fastmap = bufp->fastmap;
++  register RE_TRANSLATE_TYPE translate = bufp->translate;
++  int total_size = size1 + size2;
++  int endpos = startpos + range;
++#ifdef WCHAR
++  /* We need wchar_t* buffers correspond to cstring1, cstring2.  */
++  wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL;
++  /* We need the size of wchar_t buffers correspond to csize1, csize2.  */
++  int wcs_size1 = 0, wcs_size2 = 0;
++  /* offset buffer for optimizatoin. See convert_mbs_to_wc.  */
++  int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
++  /* They hold whether each wchar_t is binary data or not.  */
++  char *is_binary = NULL;
++#endif /* WCHAR */
++
++  /* Check for out-of-range STARTPOS.  */
++  if (startpos < 0 || startpos > total_size)
++    return -1;
++
++  /* Fix up RANGE if it might eventually take us outside
++     the virtual concatenation of STRING1 and STRING2.
++     Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE.  */
++  if (endpos < 0)
++    range = 0 - startpos;
++  else if (endpos > total_size)
++    range = total_size - startpos;
++
++  /* If the search isn't to be a backwards one, don't waste time in a
++     search for a pattern that must be anchored.  */
++  if (bufp->used > 0 && range > 0
++      && ((re_opcode_t) bufp->buffer[0] == begbuf
++	  /* `begline' is like `begbuf' if it cannot match at newlines.  */
++	  || ((re_opcode_t) bufp->buffer[0] == begline
++	      && !bufp->newline_anchor)))
++    {
++      if (startpos > 0)
++	return -1;
++      else
++	range = 1;
++    }
++
++#ifdef emacs
++  /* In a forward search for something that starts with \=.
++     don't keep searching past point.  */
++  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
++    {
++      range = PT - startpos;
++      if (range <= 0)
++	return -1;
++    }
++#endif /* emacs */
++
++  /* Update the fastmap now if not correct already.  */
++  if (fastmap && !bufp->fastmap_accurate)
++    if (re_compile_fastmap (bufp) == -2)
++      return -2;
++
++#ifdef WCHAR
++  /* Allocate wchar_t array for wcs_string1 and wcs_string2 and
++     fill them with converted string.  */
++  if (size1 != 0)
++    {
++      if (size1 > MAX_ALLOCA_SIZE)
++	{
++	  wcs_string1 = TALLOC (size1 + 1, CHAR_T);
++	  mbs_offset1 = TALLOC (size1 + 1, int);
++	  is_binary = TALLOC (size1 + 1, char);
++	}
++      else
++	{
++	  wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T);
++	  mbs_offset1 = REGEX_TALLOC (size1 + 1, int);
++	  is_binary = REGEX_TALLOC (size1 + 1, char);
++	}
++      if (!wcs_string1 || !mbs_offset1 || !is_binary)
++	{
++	  if (size1 > MAX_ALLOCA_SIZE)
++	    {
++	      free (wcs_string1);
++	      free (mbs_offset1);
++	      free (is_binary);
++	    }
++	  else
++	    {
++	      FREE_VAR (wcs_string1);
++	      FREE_VAR (mbs_offset1);
++	      FREE_VAR (is_binary);
++	    }
++	  return -2;
++	}
++      wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1,
++				     mbs_offset1, is_binary);
++      wcs_string1[wcs_size1] = L'\0'; /* for a sentinel  */
++      if (size1 > MAX_ALLOCA_SIZE)
++	free (is_binary);
++      else
++	FREE_VAR (is_binary);
++    }
++  if (size2 != 0)
++    {
++      if (size2 > MAX_ALLOCA_SIZE)
++	{
++	  wcs_string2 = TALLOC (size2 + 1, CHAR_T);
++	  mbs_offset2 = TALLOC (size2 + 1, int);
++	  is_binary = TALLOC (size2 + 1, char);
++	}
++      else
++	{
++	  wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T);
++	  mbs_offset2 = REGEX_TALLOC (size2 + 1, int);
++	  is_binary = REGEX_TALLOC (size2 + 1, char);
++	}
++      if (!wcs_string2 || !mbs_offset2 || !is_binary)
++	{
++	  FREE_WCS_BUFFERS ();
++	  if (size2 > MAX_ALLOCA_SIZE)
++	    free (is_binary);
++	  else
++	    FREE_VAR (is_binary);
++	  return -2;
++	}
++      wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2,
++				     mbs_offset2, is_binary);
++      wcs_string2[wcs_size2] = L'\0'; /* for a sentinel  */
++      if (size2 > MAX_ALLOCA_SIZE)
++	free (is_binary);
++      else
++	FREE_VAR (is_binary);
++    }
++#endif /* WCHAR */
++
++
++  /* Loop through the string, looking for a place to start matching.  */
++  for (;;)
++    {
++      /* If a fastmap is supplied, skip quickly over characters that
++         cannot be the start of a match.  If the pattern can match the
++         null string, however, we don't need to skip characters; we want
++         the first null string.  */
++      if (fastmap && startpos < total_size && !bufp->can_be_null)
++	{
++	  if (range > 0)	/* Searching forwards.  */
++	    {
++	      register const char *d;
++	      register int lim = 0;
++	      int irange = range;
++
++              if (startpos < size1 && startpos + range >= size1)
++                lim = range - (size1 - startpos);
++
++	      d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
++
++              /* Written out as an if-else to avoid testing `translate'
++                 inside the loop.  */
++	      if (translate)
++                while (range > lim
++                       && !fastmap[(unsigned char)
++				   translate[(unsigned char) *d++]])
++                  range--;
++	      else
++                while (range > lim && !fastmap[(unsigned char) *d++])
++                  range--;
++
++	      startpos += irange - range;
++	    }
++	  else				/* Searching backwards.  */
++	    {
++	      register CHAR_T c = (size1 == 0 || startpos >= size1
++				      ? string2[startpos - size1]
++				      : string1[startpos]);
++
++	      if (!fastmap[(unsigned char) TRANSLATE (c)])
++		goto advance;
++	    }
++	}
++
++      /* If can't match the null string, and that's all we have left, fail.  */
++      if (range >= 0 && startpos == total_size && fastmap
++          && !bufp->can_be_null)
++       {
++#ifdef WCHAR
++         FREE_WCS_BUFFERS ();
++#endif
++         return -1;
++       }
++
++#ifdef WCHAR
++      val = wcs_re_match_2_internal (bufp, string1, size1, string2,
++				     size2, startpos, regs, stop,
++				     wcs_string1, wcs_size1,
++				     wcs_string2, wcs_size2,
++				     mbs_offset1, mbs_offset2);
++#else /* BYTE */
++      val = byte_re_match_2_internal (bufp, string1, size1, string2,
++				      size2, startpos, regs, stop);
++#endif /* BYTE */
++
++#ifndef REGEX_MALLOC
++# ifdef C_ALLOCA
++      alloca (0);
++# endif
++#endif
++
++      if (val >= 0)
++	{
++#ifdef WCHAR
++	  FREE_WCS_BUFFERS ();
++#endif
++	  return startpos;
++	}
++
++      if (val == -2)
++	{
++#ifdef WCHAR
++	  FREE_WCS_BUFFERS ();
++#endif
++	  return -2;
++	}
++
++    advance:
++      if (!range)
++        break;
++      else if (range > 0)
++        {
++          range--;
++          startpos++;
++        }
++      else
++        {
++          range++;
++          startpos--;
++        }
++    }
++#ifdef WCHAR
++  FREE_WCS_BUFFERS ();
++#endif
++  return -1;
++}
++
++#ifdef WCHAR
++/* This converts PTR, a pointer into one of the search wchar_t strings
++   `string1' and `string2' into an multibyte string offset from the
++   beginning of that string. We use mbs_offset to optimize.
++   See convert_mbs_to_wcs.  */
++# define POINTER_TO_OFFSET(ptr)						\
++  (FIRST_STRING_P (ptr)							\
++   ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0))	\
++   : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0)	\
++		 + csize1)))
++#else /* BYTE */
++/* This converts PTR, a pointer into one of the search strings `string1'
++   and `string2' into an offset from the beginning of that string.  */
++# define POINTER_TO_OFFSET(ptr)			\
++  (FIRST_STRING_P (ptr)				\
++   ? ((regoff_t) ((ptr) - string1))		\
++   : ((regoff_t) ((ptr) - string2 + size1)))
++#endif /* WCHAR */
++
++/* Macros for dealing with the split strings in re_match_2.  */
++
++#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
++
++/* Call before fetching a character with *d.  This switches over to
++   string2 if necessary.  */
++#define PREFETCH()							\
++  while (d == dend)						    	\
++    {									\
++      /* End of string2 => fail.  */					\
++      if (dend == end_match_2) 						\
++        goto fail;							\
++      /* End of string1 => advance to string2.  */ 			\
++      d = string2;						        \
++      dend = end_match_2;						\
++    }
++
++/* Test if at very beginning or at very end of the virtual concatenation
++   of `string1' and `string2'.  If only one string, it's `string2'.  */
++#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
++#define AT_STRINGS_END(d) ((d) == end2)
++
++
++/* Test if D points to a character which is word-constituent.  We have
++   two special cases to check for: if past the end of string1, look at
++   the first character in string2; and if before the beginning of
++   string2, look at the last character in string1.  */
++#ifdef WCHAR
++/* Use internationalized API instead of SYNTAX.  */
++# define WORDCHAR_P(d)							\
++  (iswalnum ((wint_t)((d) == end1 ? *string2				\
++           : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0		\
++   || ((d) == end1 ? *string2						\
++       : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_')
++#else /* BYTE */
++# define WORDCHAR_P(d)							\
++  (SYNTAX ((d) == end1 ? *string2					\
++           : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
++   == Sword)
++#endif /* WCHAR */
++
++/* Disabled due to a compiler bug -- see comment at case wordbound */
++#if 0
++/* Test if the character before D and the one at D differ with respect
++   to being word-constituent.  */
++#define AT_WORD_BOUNDARY(d)						\
++  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)				\
++   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
++#endif
++
++/* Free everything we malloc.  */
++#ifdef MATCH_MAY_ALLOCATE
++# ifdef WCHAR
++#  define FREE_VARIABLES()						\
++  do {									\
++    REGEX_FREE_STACK (fail_stack.stack);				\
++    FREE_VAR (regstart);						\
++    FREE_VAR (regend);							\
++    FREE_VAR (old_regstart);						\
++    FREE_VAR (old_regend);						\
++    FREE_VAR (best_regstart);						\
++    FREE_VAR (best_regend);						\
++    FREE_VAR (reg_info);						\
++    FREE_VAR (reg_dummy);						\
++    FREE_VAR (reg_info_dummy);						\
++    if (!cant_free_wcs_buf)						\
++      {									\
++        FREE_VAR (string1);						\
++        FREE_VAR (string2);						\
++        FREE_VAR (mbs_offset1);						\
++        FREE_VAR (mbs_offset2);						\
++      }									\
++  } while (0)
++# else /* BYTE */
++#  define FREE_VARIABLES()						\
++  do {									\
++    REGEX_FREE_STACK (fail_stack.stack);				\
++    FREE_VAR (regstart);						\
++    FREE_VAR (regend);							\
++    FREE_VAR (old_regstart);						\
++    FREE_VAR (old_regend);						\
++    FREE_VAR (best_regstart);						\
++    FREE_VAR (best_regend);						\
++    FREE_VAR (reg_info);						\
++    FREE_VAR (reg_dummy);						\
++    FREE_VAR (reg_info_dummy);						\
++  } while (0)
++# endif /* WCHAR */
++#else
++# ifdef WCHAR
++#  define FREE_VARIABLES()						\
++  do {									\
++    if (!cant_free_wcs_buf)						\
++      {									\
++        FREE_VAR (string1);						\
++        FREE_VAR (string2);						\
++        FREE_VAR (mbs_offset1);						\
++        FREE_VAR (mbs_offset2);						\
++      }									\
++  } while (0)
++# else /* BYTE */
++#  define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning. */
++# endif /* WCHAR */
++#endif /* not MATCH_MAY_ALLOCATE */
++
++/* These values must meet several constraints.  They must not be valid
++   register values; since we have a limit of 255 registers (because
++   we use only one byte in the pattern for the register number), we can
++   use numbers larger than 255.  They must differ by 1, because of
++   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
++   be larger than the value for the highest register, so we do not try
++   to actually save any registers when none are active.  */
++#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
++#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
++
++#else /* not INSIDE_RECURSION */
++/* Matching routines.  */
++
++#ifndef emacs   /* Emacs never uses this.  */
++/* re_match is like re_match_2 except it takes only a single string.  */
++
++int
++re_match (struct re_pattern_buffer *bufp, const char *string,
++          int size, int pos, struct re_registers *regs)
++{
++  int result;
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    result = wcs_re_match_2_internal (bufp, NULL, 0, string, size,
++				      pos, regs, size,
++				      NULL, 0, NULL, 0, NULL, NULL);
++  else
++# endif
++    result = byte_re_match_2_internal (bufp, NULL, 0, string, size,
++				  pos, regs, size);
++# ifndef REGEX_MALLOC
++#  ifdef C_ALLOCA
++  alloca (0);
++#  endif
++# endif
++  return result;
++}
++# ifdef _LIBC
++weak_alias (__re_match, re_match)
++# endif
++#endif /* not emacs */
++
++#endif /* not INSIDE_RECURSION */
++
++#ifdef INSIDE_RECURSION
++static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p,
++                                                  UCHAR_T *end,
++					PREFIX(register_info_type) *reg_info);
++static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p,
++                                                UCHAR_T *end,
++					PREFIX(register_info_type) *reg_info);
++static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p,
++                                                      UCHAR_T *end,
++					PREFIX(register_info_type) *reg_info);
++static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2,
++                                   register int len,
++				   RE_TRANSLATE_TYPE translate);
++#else /* not INSIDE_RECURSION */
++
++/* re_match_2 matches the compiled pattern in BUFP against the
++   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
++   and SIZE2, respectively).  We start matching at POS, and stop
++   matching at STOP.
++
++   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
++   store offsets for the substring each group matched in REGS.  See the
++   documentation for exactly how many groups we fill.
++
++   We return -1 if no match, -2 if an internal error (such as the
++   failure stack overflowing).  Otherwise, we return the length of the
++   matched substring.  */
++
++int
++re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1,
++            const char *string2, int size2, int pos,
++            struct re_registers *regs, int stop)
++{
++  int result;
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2,
++				      pos, regs, stop,
++				      NULL, 0, NULL, 0, NULL, NULL);
++  else
++# endif
++    result = byte_re_match_2_internal (bufp, string1, size1, string2, size2,
++				  pos, regs, stop);
++
++#ifndef REGEX_MALLOC
++# ifdef C_ALLOCA
++  alloca (0);
++# endif
++#endif
++  return result;
++}
++#ifdef _LIBC
++weak_alias (__re_match_2, re_match_2)
++#endif
++
++#endif /* not INSIDE_RECURSION */
++
++#ifdef INSIDE_RECURSION
++
++#ifdef WCHAR
++static int count_mbs_length (int *, int);
++
++/* This check the substring (from 0, to length) of the multibyte string,
++   to which offset_buffer correspond. And count how many wchar_t_characters
++   the substring occupy. We use offset_buffer to optimization.
++   See convert_mbs_to_wcs.  */
++
++static int
++count_mbs_length(int *offset_buffer, int length)
++{
++  int upper, lower;
++
++  /* Check whether the size is valid.  */
++  if (length < 0)
++    return -1;
++
++  if (offset_buffer == NULL)
++    return 0;
++
++  /* If there are no multibyte character, offset_buffer[i] == i.
++   Optmize for this case.  */
++  if (offset_buffer[length] == length)
++    return length;
++
++  /* Set up upper with length. (because for all i, offset_buffer[i] >= i)  */
++  upper = length;
++  lower = 0;
++
++  while (true)
++    {
++      int middle = (lower + upper) / 2;
++      if (middle == lower || middle == upper)
++	break;
++      if (offset_buffer[middle] > length)
++	upper = middle;
++      else if (offset_buffer[middle] < length)
++	lower = middle;
++      else
++	return middle;
++    }
++
++  return -1;
++}
++#endif /* WCHAR */
++
++/* This is a separate function so that we can force an alloca cleanup
++   afterwards.  */
++#ifdef WCHAR
++static int
++wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
++                         const char *cstring1, int csize1,
++                         const char *cstring2, int csize2,
++                         int pos,
++			 struct re_registers *regs,
++                         int stop,
++     /* string1 == string2 == NULL means string1/2, size1/2 and
++	mbs_offset1/2 need seting up in this function.  */
++     /* We need wchar_t* buffers correspond to cstring1, cstring2.  */
++                         wchar_t *string1, int size1,
++                         wchar_t *string2, int size2,
++     /* offset buffer for optimizatoin. See convert_mbs_to_wc.  */
++			 int *mbs_offset1, int *mbs_offset2)
++#else /* BYTE */
++static int
++byte_re_match_2_internal (struct re_pattern_buffer *bufp,
++                          const char *string1, int size1,
++                          const char *string2, int size2,
++                          int pos,
++			  struct re_registers *regs, int stop)
++#endif /* BYTE */
++{
++  /* General temporaries.  */
++  int mcnt;
++  UCHAR_T *p1;
++#ifdef WCHAR
++  /* They hold whether each wchar_t is binary data or not.  */
++  char *is_binary = NULL;
++  /* If true, we can't free string1/2, mbs_offset1/2.  */
++  int cant_free_wcs_buf = 1;
++#endif /* WCHAR */
++
++  /* Just past the end of the corresponding string.  */
++  const CHAR_T *end1, *end2;
++
++  /* Pointers into string1 and string2, just past the last characters in
++     each to consider matching.  */
++  const CHAR_T *end_match_1, *end_match_2;
++
++  /* Where we are in the data, and the end of the current string.  */
++  const CHAR_T *d, *dend;
++
++  /* Where we are in the pattern, and the end of the pattern.  */
++#ifdef WCHAR
++  UCHAR_T *pattern, *p;
++  register UCHAR_T *pend;
++#else /* BYTE */
++  UCHAR_T *p = bufp->buffer;
++  register UCHAR_T *pend = p + bufp->used;
++#endif /* WCHAR */
++
++  /* Mark the opcode just after a start_memory, so we can test for an
++     empty subpattern when we get to the stop_memory.  */
++  UCHAR_T *just_past_start_mem = 0;
++
++  /* We use this to map every character in the string.  */
++  RE_TRANSLATE_TYPE translate = bufp->translate;
++
++  /* Failure point stack.  Each place that can handle a failure further
++     down the line pushes a failure point on this stack.  It consists of
++     restart, regend, and reg_info for all registers corresponding to
++     the subexpressions we're currently inside, plus the number of such
++     registers, and, finally, two char *'s.  The first char * is where
++     to resume scanning the pattern; the second one is where to resume
++     scanning the strings.  If the latter is zero, the failure point is
++     a ``dummy''; if a failure happens and the failure point is a dummy,
++     it gets discarded and the next next one is tried.  */
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
++  PREFIX(fail_stack_type) fail_stack;
++#endif
++#ifdef DEBUG
++  static unsigned failure_id;
++  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
++#endif
++
++#ifdef REL_ALLOC
++  /* This holds the pointer to the failure stack, when
++     it is allocated relocatably.  */
++  fail_stack_elt_t *failure_stack_ptr;
++#endif
++
++  /* We fill all the registers internally, independent of what we
++     return, for use in backreferences.  The number here includes
++     an element for register zero.  */
++  size_t num_regs = bufp->re_nsub + 1;
++
++  /* The currently active registers.  */
++  active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
++  active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
++
++  /* Information on the contents of registers. These are pointers into
++     the input strings; they record just what was matched (on this
++     attempt) by a subexpression part of the pattern, that is, the
++     regnum-th regstart pointer points to where in the pattern we began
++     matching and the regnum-th regend points to right after where we
++     stopped matching the regnum-th subexpression.  (The zeroth register
++     keeps track of what the whole pattern matches.)  */
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
++  const CHAR_T **regstart, **regend;
++#endif
++
++  /* If a group that's operated upon by a repetition operator fails to
++     match anything, then the register for its start will need to be
++     restored because it will have been set to wherever in the string we
++     are when we last see its open-group operator.  Similarly for a
++     register's end.  */
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
++  const CHAR_T **old_regstart, **old_regend;
++#endif
++
++  /* The is_active field of reg_info helps us keep track of which (possibly
++     nested) subexpressions we are currently in. The matched_something
++     field of reg_info[reg_num] helps us tell whether or not we have
++     matched any of the pattern so far this time through the reg_num-th
++     subexpression.  These two fields get reset each time through any
++     loop their register is in.  */
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
++  PREFIX(register_info_type) *reg_info;
++#endif
++
++  /* The following record the register info as found in the above
++     variables when we find a match better than any we've seen before.
++     This happens as we backtrack through the failure points, which in
++     turn happens only if we have not yet matched the entire string. */
++  unsigned best_regs_set = false;
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
++  const CHAR_T **best_regstart, **best_regend;
++#endif
++
++  /* Logically, this is `best_regend[0]'.  But we don't want to have to
++     allocate space for that if we're not allocating space for anything
++     else (see below).  Also, we never need info about register 0 for
++     any of the other register vectors, and it seems rather a kludge to
++     treat `best_regend' differently than the rest.  So we keep track of
++     the end of the best match so far in a separate variable.  We
++     initialize this to NULL so that when we backtrack the first time
++     and need to test it, it's not garbage.  */
++  const CHAR_T *match_end = NULL;
++
++  /* This helps SET_REGS_MATCHED avoid doing redundant work.  */
++  int set_regs_matched_done = 0;
++
++  /* Used when we pop values we don't care about.  */
++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
++  const CHAR_T **reg_dummy;
++  PREFIX(register_info_type) *reg_info_dummy;
++#endif
++
++#ifdef DEBUG
++  /* Counts the total number of registers pushed.  */
++  unsigned num_regs_pushed = 0;
++#endif
++
++  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
++
++  INIT_FAIL_STACK ();
++
++#ifdef MATCH_MAY_ALLOCATE
++  /* Do not bother to initialize all the register variables if there are
++     no groups in the pattern, as it takes a fair amount of time.  If
++     there are groups, we include space for register 0 (the whole
++     pattern), even though we never use it, since it simplifies the
++     array indexing.  We should fix this.  */
++  if (bufp->re_nsub)
++    {
++      regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
++      regend = REGEX_TALLOC (num_regs, const CHAR_T *);
++      old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
++      old_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
++      best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
++      best_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
++      reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
++      reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *);
++      reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
++
++      if (!(regstart && regend && old_regstart && old_regend && reg_info
++            && best_regstart && best_regend && reg_dummy && reg_info_dummy))
++        {
++          FREE_VARIABLES ();
++          return -2;
++        }
++    }
++  else
++    {
++      /* We must initialize all our variables to NULL, so that
++         `FREE_VARIABLES' doesn't try to free them.  */
++      regstart = regend = old_regstart = old_regend = best_regstart
++        = best_regend = reg_dummy = NULL;
++      reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL;
++    }
++#endif /* MATCH_MAY_ALLOCATE */
++
++  /* The starting position is bogus.  */
++#ifdef WCHAR
++  if (pos < 0 || pos > csize1 + csize2)
++#else /* BYTE */
++  if (pos < 0 || pos > size1 + size2)
++#endif
++    {
++      FREE_VARIABLES ();
++      return -1;
++    }
++
++#ifdef WCHAR
++  /* Allocate wchar_t array for string1 and string2 and
++     fill them with converted string.  */
++  if (string1 == NULL && string2 == NULL)
++    {
++      /* We need seting up buffers here.  */
++
++      /* We must free wcs buffers in this function.  */
++      cant_free_wcs_buf = 0;
++
++      if (csize1 != 0)
++	{
++	  string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
++	  mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
++	  is_binary = REGEX_TALLOC (csize1 + 1, char);
++	  if (!string1 || !mbs_offset1 || !is_binary)
++	    {
++	      FREE_VAR (string1);
++	      FREE_VAR (mbs_offset1);
++	      FREE_VAR (is_binary);
++	      return -2;
++	    }
++	}
++      if (csize2 != 0)
++	{
++	  string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
++	  mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
++	  is_binary = REGEX_TALLOC (csize2 + 1, char);
++	  if (!string2 || !mbs_offset2 || !is_binary)
++	    {
++	      FREE_VAR (string1);
++	      FREE_VAR (mbs_offset1);
++	      FREE_VAR (string2);
++	      FREE_VAR (mbs_offset2);
++	      FREE_VAR (is_binary);
++	      return -2;
++	    }
++	  size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
++				     mbs_offset2, is_binary);
++	  string2[size2] = L'\0'; /* for a sentinel  */
++	  FREE_VAR (is_binary);
++	}
++    }
++
++  /* We need to cast pattern to (wchar_t*), because we casted this compiled
++     pattern to (char*) in regex_compile.  */
++  p = pattern = (CHAR_T*)bufp->buffer;
++  pend = (CHAR_T*)(bufp->buffer + bufp->used);
++
++#endif /* WCHAR */
++
++  /* Initialize subexpression text positions to -1 to mark ones that no
++     start_memory/stop_memory has been seen for. Also initialize the
++     register information struct.  */
++  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
++    {
++      regstart[mcnt] = regend[mcnt]
++        = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
++
++      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
++      IS_ACTIVE (reg_info[mcnt]) = 0;
++      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
++      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
++    }
++
++  /* We move `string1' into `string2' if the latter's empty -- but not if
++     `string1' is null.  */
++  if (size2 == 0 && string1 != NULL)
++    {
++      string2 = string1;
++      size2 = size1;
++      string1 = 0;
++      size1 = 0;
++#ifdef WCHAR
++      mbs_offset2 = mbs_offset1;
++      csize2 = csize1;
++      mbs_offset1 = NULL;
++      csize1 = 0;
++#endif
++    }
++  end1 = string1 + size1;
++  end2 = string2 + size2;
++
++  /* Compute where to stop matching, within the two strings.  */
++#ifdef WCHAR
++  if (stop <= csize1)
++    {
++      mcnt = count_mbs_length(mbs_offset1, stop);
++      end_match_1 = string1 + mcnt;
++      end_match_2 = string2;
++    }
++  else
++    {
++      if (stop > csize1 + csize2)
++	stop = csize1 + csize2;
++      end_match_1 = end1;
++      mcnt = count_mbs_length(mbs_offset2, stop-csize1);
++      end_match_2 = string2 + mcnt;
++    }
++  if (mcnt < 0)
++    { /* count_mbs_length return error.  */
++      FREE_VARIABLES ();
++      return -1;
++    }
++#else
++  if (stop <= size1)
++    {
++      end_match_1 = string1 + stop;
++      end_match_2 = string2;
++    }
++  else
++    {
++      end_match_1 = end1;
++      end_match_2 = string2 + stop - size1;
++    }
++#endif /* WCHAR */
++
++  /* `p' scans through the pattern as `d' scans through the data.
++     `dend' is the end of the input string that `d' points within.  `d'
++     is advanced into the following input string whenever necessary, but
++     this happens before fetching; therefore, at the beginning of the
++     loop, `d' can be pointing at the end of a string, but it cannot
++     equal `string2'.  */
++#ifdef WCHAR
++  if (size1 > 0 && pos <= csize1)
++    {
++      mcnt = count_mbs_length(mbs_offset1, pos);
++      d = string1 + mcnt;
++      dend = end_match_1;
++    }
++  else
++    {
++      mcnt = count_mbs_length(mbs_offset2, pos-csize1);
++      d = string2 + mcnt;
++      dend = end_match_2;
++    }
++
++  if (mcnt < 0)
++    { /* count_mbs_length return error.  */
++      FREE_VARIABLES ();
++      return -1;
++    }
++#else
++  if (size1 > 0 && pos <= size1)
++    {
++      d = string1 + pos;
++      dend = end_match_1;
++    }
++  else
++    {
++      d = string2 + pos - size1;
++      dend = end_match_2;
++    }
++#endif /* WCHAR */
++
++  DEBUG_PRINT1 ("The compiled pattern is:\n");
++  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
++  DEBUG_PRINT1 ("The string to match is: `");
++  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
++  DEBUG_PRINT1 ("'\n");
++
++  /* This loops over pattern commands.  It exits by returning from the
++     function if the match is complete, or it drops through if the match
++     fails at this starting point in the input data.  */
++  for (;;)
++    {
++#ifdef _LIBC
++      DEBUG_PRINT2 ("\n%p: ", p);
++#else
++      DEBUG_PRINT2 ("\n0x%x: ", p);
++#endif
++
++      if (p == pend)
++	{ /* End of pattern means we might have succeeded.  */
++          DEBUG_PRINT1 ("end of pattern ... ");
++
++	  /* If we haven't matched the entire string, and we want the
++             longest match, try backtracking.  */
++          if (d != end_match_2)
++	    {
++	      /* 1 if this match ends in the same string (string1 or string2)
++		 as the best previous match.  */
++	      boolean same_str_p = (FIRST_STRING_P (match_end)
++				    == MATCHING_IN_FIRST_STRING);
++	      /* 1 if this match is the best seen so far.  */
++	      boolean best_match_p;
++
++	      /* AIX compiler got confused when this was combined
++		 with the previous declaration.  */
++	      if (same_str_p)
++		best_match_p = d > match_end;
++	      else
++		best_match_p = !MATCHING_IN_FIRST_STRING;
++
++              DEBUG_PRINT1 ("backtracking.\n");
++
++              if (!FAIL_STACK_EMPTY ())
++                { /* More failure points to try.  */
++
++                  /* If exceeds best match so far, save it.  */
++                  if (!best_regs_set || best_match_p)
++                    {
++                      best_regs_set = true;
++                      match_end = d;
++
++                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
++
++                      for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
++                        {
++                          best_regstart[mcnt] = regstart[mcnt];
++                          best_regend[mcnt] = regend[mcnt];
++                        }
++                    }
++                  goto fail;
++                }
++
++              /* If no failure points, don't restore garbage.  And if
++                 last match is real best match, don't restore second
++                 best one. */
++              else if (best_regs_set && !best_match_p)
++                {
++  	        restore_best_regs:
++                  /* Restore best match.  It may happen that `dend ==
++                     end_match_1' while the restored d is in string2.
++                     For example, the pattern `x.*y.*z' against the
++                     strings `x-' and `y-z-', if the two strings are
++                     not consecutive in memory.  */
++                  DEBUG_PRINT1 ("Restoring best registers.\n");
++
++                  d = match_end;
++                  dend = ((d >= string1 && d <= end1)
++		           ? end_match_1 : end_match_2);
++
++		  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
++		    {
++		      regstart[mcnt] = best_regstart[mcnt];
++		      regend[mcnt] = best_regend[mcnt];
++		    }
++                }
++            } /* d != end_match_2 */
++
++	succeed_label:
++          DEBUG_PRINT1 ("Accepting match.\n");
++          /* If caller wants register contents data back, do it.  */
++          if (regs && !bufp->no_sub)
++	    {
++	      /* Have the register data arrays been allocated?  */
++              if (bufp->regs_allocated == REGS_UNALLOCATED)
++                { /* No.  So allocate them with malloc.  We need one
++                     extra element beyond `num_regs' for the `-1' marker
++                     GNU code uses.  */
++                  regs->num_regs = MAX (RE_NREGS, num_regs + 1);
++                  regs->start = TALLOC (regs->num_regs, regoff_t);
++                  regs->end = TALLOC (regs->num_regs, regoff_t);
++                  if (regs->start == NULL || regs->end == NULL)
++		    {
++		      FREE_VARIABLES ();
++		      return -2;
++		    }
++                  bufp->regs_allocated = REGS_REALLOCATE;
++                }
++              else if (bufp->regs_allocated == REGS_REALLOCATE)
++                { /* Yes.  If we need more elements than were already
++                     allocated, reallocate them.  If we need fewer, just
++                     leave it alone.  */
++                  if (regs->num_regs < num_regs + 1)
++                    {
++                      regs->num_regs = num_regs + 1;
++                      RETALLOC (regs->start, regs->num_regs, regoff_t);
++                      RETALLOC (regs->end, regs->num_regs, regoff_t);
++                      if (regs->start == NULL || regs->end == NULL)
++			{
++			  FREE_VARIABLES ();
++			  return -2;
++			}
++                    }
++                }
++              else
++		{
++		  /* These braces fend off a "empty body in an else-statement"
++		     warning under GCC when assert expands to nothing.  */
++		  assert (bufp->regs_allocated == REGS_FIXED);
++		}
++
++              /* Convert the pointer data in `regstart' and `regend' to
++                 indices.  Register zero has to be set differently,
++                 since we haven't kept track of any info for it.  */
++              if (regs->num_regs > 0)
++                {
++                  regs->start[0] = pos;
++#ifdef WCHAR
++		  if (MATCHING_IN_FIRST_STRING)
++		    regs->end[0] = mbs_offset1 != NULL ?
++					mbs_offset1[d-string1] : 0;
++		  else
++		    regs->end[0] = csize1 + (mbs_offset2 != NULL ?
++					     mbs_offset2[d-string2] : 0);
++#else
++                  regs->end[0] = (MATCHING_IN_FIRST_STRING
++				  ? ((regoff_t) (d - string1))
++			          : ((regoff_t) (d - string2 + size1)));
++#endif /* WCHAR */
++                }
++
++              /* Go through the first `min (num_regs, regs->num_regs)'
++                 registers, since that is all we initialized.  */
++	      for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
++		   mcnt++)
++		{
++                  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
++                    regs->start[mcnt] = regs->end[mcnt] = -1;
++                  else
++                    {
++		      regs->start[mcnt]
++			= (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
++                      regs->end[mcnt]
++			= (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
++                    }
++		}
++
++              /* If the regs structure we return has more elements than
++                 were in the pattern, set the extra elements to -1.  If
++                 we (re)allocated the registers, this is the case,
++                 because we always allocate enough to have at least one
++                 -1 at the end.  */
++              for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
++                regs->start[mcnt] = regs->end[mcnt] = -1;
++	    } /* regs && !bufp->no_sub */
++
++          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
++                        nfailure_points_pushed, nfailure_points_popped,
++                        nfailure_points_pushed - nfailure_points_popped);
++          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
++
++#ifdef WCHAR
++	  if (MATCHING_IN_FIRST_STRING)
++	    mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0;
++	  else
++	    mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) +
++			csize1;
++          mcnt -= pos;
++#else
++          mcnt = d - pos - (MATCHING_IN_FIRST_STRING
++			    ? string1
++			    : string2 - size1);
++#endif /* WCHAR */
++
++          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
++
++          FREE_VARIABLES ();
++          return mcnt;
++        }
++
++      /* Otherwise match next pattern command.  */
++      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
++	{
++        /* Ignore these.  Used to ignore the n of succeed_n's which
++           currently have n == 0.  */
++        case no_op:
++          DEBUG_PRINT1 ("EXECUTING no_op.\n");
++          break;
++
++	case succeed:
++          DEBUG_PRINT1 ("EXECUTING succeed.\n");
++	  goto succeed_label;
++
++        /* Match the next n pattern characters exactly.  The following
++           byte in the pattern defines n, and the n bytes after that
++           are the characters to match.  */
++	case exactn:
++#ifdef MBS_SUPPORT
++	case exactn_bin:
++#endif
++	  mcnt = *p++;
++          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
++
++          /* This is written out as an if-else so we don't waste time
++             testing `translate' inside the loop.  */
++          if (translate)
++	    {
++	      do
++		{
++		  PREFETCH ();
++#ifdef WCHAR
++		  if (*d <= 0xff)
++		    {
++		      if ((UCHAR_T) translate[(unsigned char) *d++]
++			  != (UCHAR_T) *p++)
++			goto fail;
++		    }
++		  else
++		    {
++		      if (*d++ != (CHAR_T) *p++)
++			goto fail;
++		    }
++#else
++		  if ((UCHAR_T) translate[(unsigned char) *d++]
++		      != (UCHAR_T) *p++)
++                    goto fail;
++#endif /* WCHAR */
++		}
++	      while (--mcnt);
++	    }
++	  else
++	    {
++	      do
++		{
++		  PREFETCH ();
++		  if (*d++ != (CHAR_T) *p++) goto fail;
++		}
++	      while (--mcnt);
++	    }
++	  SET_REGS_MATCHED ();
++          break;
++
++
++        /* Match any character except possibly a newline or a null.  */
++	case anychar:
++          DEBUG_PRINT1 ("EXECUTING anychar.\n");
++
++          PREFETCH ();
++
++          if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
++              || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
++	    goto fail;
++
++          SET_REGS_MATCHED ();
++          DEBUG_PRINT2 ("  Matched `%ld'.\n", (long int) *d);
++          d++;
++	  break;
++
++
++	case charset:
++	case charset_not:
++	  {
++	    register UCHAR_T c;
++#ifdef WCHAR
++	    unsigned int i, char_class_length, coll_symbol_length,
++              equiv_class_length, ranges_length, chars_length, length;
++	    CHAR_T *workp, *workp2, *charset_top;
++#define WORK_BUFFER_SIZE 128
++            CHAR_T str_buf[WORK_BUFFER_SIZE];
++# ifdef _LIBC
++	    uint32_t nrules;
++# endif /* _LIBC */
++#endif /* WCHAR */
++	    boolean negate = (re_opcode_t) *(p - 1) == charset_not;
++
++            DEBUG_PRINT2 ("EXECUTING charset%s.\n", negate ? "_not" : "");
++	    PREFETCH ();
++	    c = TRANSLATE (*d); /* The character to match.  */
++#ifdef WCHAR
++# ifdef _LIBC
++	    nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
++# endif /* _LIBC */
++	    charset_top = p - 1;
++	    char_class_length = *p++;
++	    coll_symbol_length = *p++;
++	    equiv_class_length = *p++;
++	    ranges_length = *p++;
++	    chars_length = *p++;
++	    /* p points charset[6], so the address of the next instruction
++	       (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'],
++	       where l=length of char_classes, m=length of collating_symbol,
++	       n=equivalence_class, o=length of char_range,
++	       p'=length of character.  */
++	    workp = p;
++	    /* Update p to indicate the next instruction.  */
++	    p += char_class_length + coll_symbol_length+ equiv_class_length +
++              2*ranges_length + chars_length;
++
++            /* match with char_class?  */
++	    for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE)
++	      {
++		wctype_t wctype;
++		uintptr_t alignedp = ((uintptr_t)workp
++				      + __alignof__(wctype_t) - 1)
++		  		      & ~(uintptr_t)(__alignof__(wctype_t) - 1);
++		wctype = *((wctype_t*)alignedp);
++		workp += CHAR_CLASS_SIZE;
++# ifdef _LIBC
++		if (__iswctype((wint_t)c, wctype))
++		  goto char_set_matched;
++# else
++		if (iswctype((wint_t)c, wctype))
++		  goto char_set_matched;
++# endif
++	      }
++
++            /* match with collating_symbol?  */
++# ifdef _LIBC
++	    if (nrules != 0)
++	      {
++		const unsigned char *extra = (const unsigned char *)
++		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
++
++		for (workp2 = workp + coll_symbol_length ; workp < workp2 ;
++		     workp++)
++		  {
++		    int32_t *wextra;
++		    wextra = (int32_t*)(extra + *workp++);
++		    for (i = 0; i < *wextra; ++i)
++		      if (TRANSLATE(d[i]) != wextra[1 + i])
++			break;
++
++		    if (i == *wextra)
++		      {
++			/* Update d, however d will be incremented at
++			   char_set_matched:, we decrement d here.  */
++			d += i - 1;
++			goto char_set_matched;
++		      }
++		  }
++	      }
++	    else /* (nrules == 0) */
++# endif
++	      /* If we can't look up collation data, we use wcscoll
++		 instead.  */
++	      {
++		for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
++		  {
++		    const CHAR_T *backup_d = d, *backup_dend = dend;
++# ifdef _LIBC
++		    length = __wcslen (workp);
++# else
++		    length = wcslen (workp);
++# endif
++
++		    /* If wcscoll(the collating symbol, whole string) > 0,
++		       any substring of the string never match with the
++		       collating symbol.  */
++# ifdef _LIBC
++		    if (__wcscoll (workp, d) > 0)
++# else
++		    if (wcscoll (workp, d) > 0)
++# endif
++		      {
++			workp += length + 1;
++			continue;
++		      }
++
++		    /* First, we compare the collating symbol with
++		       the first character of the string.
++		       If it don't match, we add the next character to
++		       the compare buffer in turn.  */
++		    for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++)
++		      {
++			int match;
++			if (d == dend)
++			  {
++			    if (dend == end_match_2)
++			      break;
++			    d = string2;
++			    dend = end_match_2;
++			  }
++
++			/* add next character to the compare buffer.  */
++			str_buf[i] = TRANSLATE(*d);
++			str_buf[i+1] = '\0';
++
++# ifdef _LIBC
++			match = __wcscoll (workp, str_buf);
++# else
++			match = wcscoll (workp, str_buf);
++# endif
++			if (match == 0)
++			  goto char_set_matched;
++
++			if (match < 0)
++			  /* (str_buf > workp) indicate (str_buf + X > workp),
++			     because for all X (str_buf + X > str_buf).
++			     So we don't need continue this loop.  */
++			  break;
++
++			/* Otherwise(str_buf < workp),
++			   (str_buf+next_character) may equals (workp).
++			   So we continue this loop.  */
++		      }
++		    /* not matched */
++		    d = backup_d;
++		    dend = backup_dend;
++		    workp += length + 1;
++		  }
++              }
++            /* match with equivalence_class?  */
++# ifdef _LIBC
++	    if (nrules != 0)
++	      {
++                const CHAR_T *backup_d = d, *backup_dend = dend;
++		/* Try to match the equivalence class against
++		   those known to the collate implementation.  */
++		const int32_t *table;
++		const int32_t *weights;
++		const int32_t *extra;
++		const int32_t *indirect;
++		int32_t idx, idx2;
++		wint_t *cp;
++		size_t len;
++
++		/* This #include defines a local function!  */
++#  include <locale/weightwc.h>
++
++		table = (const int32_t *)
++		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
++		weights = (const wint_t *)
++		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
++		extra = (const wint_t *)
++		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
++		indirect = (const int32_t *)
++		  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
++
++		/* Write 1 collating element to str_buf, and
++		   get its index.  */
++		idx2 = 0;
++
++		for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++)
++		  {
++		    cp = (wint_t*)str_buf;
++		    if (d == dend)
++		      {
++			if (dend == end_match_2)
++			  break;
++			d = string2;
++			dend = end_match_2;
++		      }
++		    str_buf[i] = TRANSLATE(*(d+i));
++		    str_buf[i+1] = '\0'; /* sentinel */
++		    idx2 = findidx ((const wint_t**)&cp, i);
++		  }
++
++		/* Update d, however d will be incremented at
++		   char_set_matched:, we decrement d here.  */
++		d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1);
++		if (d >= dend)
++		  {
++		    if (dend == end_match_2)
++			d = dend;
++		    else
++		      {
++			d = string2;
++			dend = end_match_2;
++		      }
++		  }
++
++		len = weights[idx2];
++
++		for (workp2 = workp + equiv_class_length ; workp < workp2 ;
++		     workp++)
++		  {
++		    idx = (int32_t)*workp;
++		    /* We already checked idx != 0 in regex_compile. */
++
++		    if (idx2 != 0 && len == weights[idx])
++		      {
++			int cnt = 0;
++			while (cnt < len && (weights[idx + 1 + cnt]
++					     == weights[idx2 + 1 + cnt]))
++			  ++cnt;
++
++			if (cnt == len)
++			  goto char_set_matched;
++		      }
++		  }
++		/* not matched */
++                d = backup_d;
++                dend = backup_dend;
++	      }
++	    else /* (nrules == 0) */
++# endif
++	      /* If we can't look up collation data, we use wcscoll
++		 instead.  */
++	      {
++		for (workp2 = workp + equiv_class_length ; workp < workp2 ;)
++		  {
++		    const CHAR_T *backup_d = d, *backup_dend = dend;
++# ifdef _LIBC
++		    length = __wcslen (workp);
++# else
++		    length = wcslen (workp);
++# endif
++
++		    /* If wcscoll(the collating symbol, whole string) > 0,
++		       any substring of the string never match with the
++		       collating symbol.  */
++# ifdef _LIBC
++		    if (__wcscoll (workp, d) > 0)
++# else
++		    if (wcscoll (workp, d) > 0)
++# endif
++		      {
++			workp += length + 1;
++			break;
++		      }
++
++		    /* First, we compare the equivalence class with
++		       the first character of the string.
++		       If it don't match, we add the next character to
++		       the compare buffer in turn.  */
++		    for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++)
++		      {
++			int match;
++			if (d == dend)
++			  {
++			    if (dend == end_match_2)
++			      break;
++			    d = string2;
++			    dend = end_match_2;
++			  }
++
++			/* add next character to the compare buffer.  */
++			str_buf[i] = TRANSLATE(*d);
++			str_buf[i+1] = '\0';
++
++# ifdef _LIBC
++			match = __wcscoll (workp, str_buf);
++# else
++			match = wcscoll (workp, str_buf);
++# endif
++
++			if (match == 0)
++			  goto char_set_matched;
++
++			if (match < 0)
++			/* (str_buf > workp) indicate (str_buf + X > workp),
++			   because for all X (str_buf + X > str_buf).
++			   So we don't need continue this loop.  */
++			  break;
++
++			/* Otherwise(str_buf < workp),
++			   (str_buf+next_character) may equals (workp).
++			   So we continue this loop.  */
++		      }
++		    /* not matched */
++		    d = backup_d;
++		    dend = backup_dend;
++		    workp += length + 1;
++		  }
++	      }
++
++            /* match with char_range?  */
++# ifdef _LIBC
++	    if (nrules != 0)
++	      {
++		uint32_t collseqval;
++		const char *collseq = (const char *)
++		  _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
++
++		collseqval = collseq_table_lookup (collseq, c);
++
++		for (; workp < p - chars_length ;)
++		  {
++		    uint32_t start_val, end_val;
++
++		    /* We already compute the collation sequence value
++		       of the characters (or collating symbols).  */
++		    start_val = (uint32_t) *workp++; /* range_start */
++		    end_val = (uint32_t) *workp++; /* range_end */
++
++		    if (start_val <= collseqval && collseqval <= end_val)
++		      goto char_set_matched;
++		  }
++	      }
++	    else
++# endif
++	      {
++		/* We set range_start_char at str_buf[0], range_end_char
++		   at str_buf[4], and compared char at str_buf[2].  */
++		str_buf[1] = 0;
++		str_buf[2] = c;
++		str_buf[3] = 0;
++		str_buf[5] = 0;
++		for (; workp < p - chars_length ;)
++		  {
++		    wchar_t *range_start_char, *range_end_char;
++
++		    /* match if (range_start_char <= c <= range_end_char).  */
++
++		    /* If range_start(or end) < 0, we assume -range_start(end)
++		       is the offset of the collating symbol which is specified
++		       as the character of the range start(end).  */
++
++		    /* range_start */
++		    if (*workp < 0)
++		      range_start_char = charset_top - (*workp++);
++		    else
++		      {
++			str_buf[0] = *workp++;
++			range_start_char = str_buf;
++		      }
++
++		    /* range_end */
++		    if (*workp < 0)
++		      range_end_char = charset_top - (*workp++);
++		    else
++		      {
++			str_buf[4] = *workp++;
++			range_end_char = str_buf + 4;
++		      }
++
++# ifdef _LIBC
++		    if (__wcscoll (range_start_char, str_buf+2) <= 0
++			&& __wcscoll (str_buf+2, range_end_char) <= 0)
++# else
++		    if (wcscoll (range_start_char, str_buf+2) <= 0
++			&& wcscoll (str_buf+2, range_end_char) <= 0)
++# endif
++		      goto char_set_matched;
++		  }
++	      }
++
++            /* match with char?  */
++	    for (; workp < p ; workp++)
++	      if (c == *workp)
++		goto char_set_matched;
++
++	    negate = !negate;
++
++	  char_set_matched:
++	    if (negate) goto fail;
++#else
++            /* Cast to `unsigned' instead of `unsigned char' in case the
++               bit list is a full 32 bytes long.  */
++	    if (c < (unsigned) (*p * BYTEWIDTH)
++		&& p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
++	      negate = !negate;
++
++	    p += 1 + *p;
++
++	    if (!negate) goto fail;
++#undef WORK_BUFFER_SIZE
++#endif /* WCHAR */
++	    SET_REGS_MATCHED ();
++            d++;
++	    break;
++	  }
++
++
++        /* The beginning of a group is represented by start_memory.
++           The arguments are the register number in the next byte, and the
++           number of groups inner to this one in the next.  The text
++           matched within the group is recorded (in the internal
++           registers data structure) under the register number.  */
++        case start_memory:
++	  DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n",
++			(long int) *p, (long int) p[1]);
++
++          /* Find out if this group can match the empty string.  */
++	  p1 = p;		/* To send to group_match_null_string_p.  */
++
++          if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
++            REG_MATCH_NULL_STRING_P (reg_info[*p])
++              = PREFIX(group_match_null_string_p) (&p1, pend, reg_info);
++
++          /* Save the position in the string where we were the last time
++             we were at this open-group operator in case the group is
++             operated upon by a repetition operator, e.g., with `(a*)*b'
++             against `ab'; then we want to ignore where we are now in
++             the string in case this attempt to match fails.  */
++          old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
++                             ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
++                             : regstart[*p];
++	  DEBUG_PRINT2 ("  old_regstart: %d\n",
++			 POINTER_TO_OFFSET (old_regstart[*p]));
++
++          regstart[*p] = d;
++	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
++
++          IS_ACTIVE (reg_info[*p]) = 1;
++          MATCHED_SOMETHING (reg_info[*p]) = 0;
++
++	  /* Clear this whenever we change the register activity status.  */
++	  set_regs_matched_done = 0;
++
++          /* This is the new highest active register.  */
++          highest_active_reg = *p;
++
++          /* If nothing was active before, this is the new lowest active
++             register.  */
++          if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
++            lowest_active_reg = *p;
++
++          /* Move past the register number and inner group count.  */
++          p += 2;
++	  just_past_start_mem = p;
++
++          break;
++
++
++        /* The stop_memory opcode represents the end of a group.  Its
++           arguments are the same as start_memory's: the register
++           number, and the number of inner groups.  */
++	case stop_memory:
++	  DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n",
++			(long int) *p, (long int) p[1]);
++
++          /* We need to save the string position the last time we were at
++             this close-group operator in case the group is operated
++             upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
++             against `aba'; then we want to ignore where we are now in
++             the string in case this attempt to match fails.  */
++          old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
++                           ? REG_UNSET (regend[*p]) ? d : regend[*p]
++			   : regend[*p];
++	  DEBUG_PRINT2 ("      old_regend: %d\n",
++			 POINTER_TO_OFFSET (old_regend[*p]));
++
++          regend[*p] = d;
++	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
++
++          /* This register isn't active anymore.  */
++          IS_ACTIVE (reg_info[*p]) = 0;
++
++	  /* Clear this whenever we change the register activity status.  */
++	  set_regs_matched_done = 0;
++
++          /* If this was the only register active, nothing is active
++             anymore.  */
++          if (lowest_active_reg == highest_active_reg)
++            {
++              lowest_active_reg = NO_LOWEST_ACTIVE_REG;
++              highest_active_reg = NO_HIGHEST_ACTIVE_REG;
++            }
++          else
++            { /* We must scan for the new highest active register, since
++                 it isn't necessarily one less than now: consider
++                 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
++                 new highest active register is 1.  */
++              UCHAR_T r = *p - 1;
++              while (r > 0 && !IS_ACTIVE (reg_info[r]))
++                r--;
++
++              /* If we end up at register zero, that means that we saved
++                 the registers as the result of an `on_failure_jump', not
++                 a `start_memory', and we jumped to past the innermost
++                 `stop_memory'.  For example, in ((.)*) we save
++                 registers 1 and 2 as a result of the *, but when we pop
++                 back to the second ), we are at the stop_memory 1.
++                 Thus, nothing is active.  */
++	      if (r == 0)
++                {
++                  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
++                  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
++                }
++              else
++                highest_active_reg = r;
++            }
++
++          /* If just failed to match something this time around with a
++             group that's operated on by a repetition operator, try to
++             force exit from the ``loop'', and restore the register
++             information for this group that we had before trying this
++             last match.  */
++          if ((!MATCHED_SOMETHING (reg_info[*p])
++               || just_past_start_mem == p - 1)
++	      && (p + 2) < pend)
++            {
++              boolean is_a_jump_n = false;
++
++              p1 = p + 2;
++              mcnt = 0;
++              switch ((re_opcode_t) *p1++)
++                {
++                  case jump_n:
++		    is_a_jump_n = true;
++                  case pop_failure_jump:
++		  case maybe_pop_jump:
++		  case jump:
++		  case dummy_failure_jump:
++                    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++		    if (is_a_jump_n)
++		      p1 += OFFSET_ADDRESS_SIZE;
++                    break;
++
++                  default:
++                    /* do nothing */ ;
++                }
++	      p1 += mcnt;
++
++              /* If the next operation is a jump backwards in the pattern
++	         to an on_failure_jump right before the start_memory
++                 corresponding to this stop_memory, exit from the loop
++                 by forcing a failure after pushing on the stack the
++                 on_failure_jump's jump in the pattern, and d.  */
++              if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
++                  && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory
++		  && p1[2+OFFSET_ADDRESS_SIZE] == *p)
++		{
++                  /* If this group ever matched anything, then restore
++                     what its registers were before trying this last
++                     failed match, e.g., with `(a*)*b' against `ab' for
++                     regstart[1], and, e.g., with `((a*)*(b*)*)*'
++                     against `aba' for regend[3].
++
++                     Also restore the registers for inner groups for,
++                     e.g., `((a*)(b*))*' against `aba' (register 3 would
++                     otherwise get trashed).  */
++
++                  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
++		    {
++		      unsigned r;
++
++                      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
++
++		      /* Restore this and inner groups' (if any) registers.  */
++                      for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
++			   r++)
++                        {
++                          regstart[r] = old_regstart[r];
++
++                          /* xx why this test?  */
++                          if (old_regend[r] >= regstart[r])
++                            regend[r] = old_regend[r];
++                        }
++                    }
++		  p1++;
++                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++                  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
++
++                  goto fail;
++                }
++            }
++
++          /* Move past the register number and the inner group count.  */
++          p += 2;
++          break;
++
++
++	/* \<digit> has been turned into a `duplicate' command which is
++           followed by the numeric value of <digit> as the register number.  */
++        case duplicate:
++	  {
++	    register const CHAR_T *d2, *dend2;
++	    int regno = *p++;   /* Get which register to match against.  */
++	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
++
++	    /* Can't back reference a group which we've never matched.  */
++            if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
++              goto fail;
++
++            /* Where in input to try to start matching.  */
++            d2 = regstart[regno];
++
++            /* Where to stop matching; if both the place to start and
++               the place to stop matching are in the same string, then
++               set to the place to stop, otherwise, for now have to use
++               the end of the first string.  */
++
++            dend2 = ((FIRST_STRING_P (regstart[regno])
++		      == FIRST_STRING_P (regend[regno]))
++		     ? regend[regno] : end_match_1);
++	    for (;;)
++	      {
++		/* If necessary, advance to next segment in register
++                   contents.  */
++		while (d2 == dend2)
++		  {
++		    if (dend2 == end_match_2) break;
++		    if (dend2 == regend[regno]) break;
++
++                    /* End of string1 => advance to string2. */
++                    d2 = string2;
++                    dend2 = regend[regno];
++		  }
++		/* At end of register contents => success */
++		if (d2 == dend2) break;
++
++		/* If necessary, advance to next segment in data.  */
++		PREFETCH ();
++
++		/* How many characters left in this segment to match.  */
++		mcnt = dend - d;
++
++		/* Want how many consecutive characters we can match in
++                   one shot, so, if necessary, adjust the count.  */
++                if (mcnt > dend2 - d2)
++		  mcnt = dend2 - d2;
++
++		/* Compare that many; failure if mismatch, else move
++                   past them.  */
++		if (translate
++                    ? PREFIX(bcmp_translate) (d, d2, mcnt, translate)
++                    : memcmp (d, d2, mcnt*sizeof(UCHAR_T)))
++		  goto fail;
++		d += mcnt, d2 += mcnt;
++
++		/* Do this because we've match some characters.  */
++		SET_REGS_MATCHED ();
++	      }
++	  }
++	  break;
++
++
++        /* begline matches the empty string at the beginning of the string
++           (unless `not_bol' is set in `bufp'), and, if
++           `newline_anchor' is set, after newlines.  */
++	case begline:
++          DEBUG_PRINT1 ("EXECUTING begline.\n");
++
++          if (AT_STRINGS_BEG (d))
++            {
++              if (!bufp->not_bol) break;
++            }
++          else if (d[-1] == '\n' && bufp->newline_anchor)
++            {
++              break;
++            }
++          /* In all other cases, we fail.  */
++          goto fail;
++
++
++        /* endline is the dual of begline.  */
++	case endline:
++          DEBUG_PRINT1 ("EXECUTING endline.\n");
++
++          if (AT_STRINGS_END (d))
++            {
++              if (!bufp->not_eol) break;
++            }
++
++          /* We have to ``prefetch'' the next character.  */
++          else if ((d == end1 ? *string2 : *d) == '\n'
++                   && bufp->newline_anchor)
++            {
++              break;
++            }
++          goto fail;
++
++
++	/* Match at the very beginning of the data.  */
++        case begbuf:
++          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
++          if (AT_STRINGS_BEG (d))
++            break;
++          goto fail;
++
++
++	/* Match at the very end of the data.  */
++        case endbuf:
++          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
++	  if (AT_STRINGS_END (d))
++	    break;
++          goto fail;
++
++
++        /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
++           pushes NULL as the value for the string on the stack.  Then
++           `pop_failure_point' will keep the current value for the
++           string, instead of restoring it.  To see why, consider
++           matching `foo\nbar' against `.*\n'.  The .* matches the foo;
++           then the . fails against the \n.  But the next thing we want
++           to do is match the \n against the \n; if we restored the
++           string value, we would be back at the foo.
++
++           Because this is used only in specific cases, we don't need to
++           check all the things that `on_failure_jump' does, to make
++           sure the right things get saved on the stack.  Hence we don't
++           share its code.  The only reason to push anything on the
++           stack at all is that otherwise we would have to change
++           `anychar's code to do something besides goto fail in this
++           case; that seems worse than this.  */
++        case on_failure_keep_string_jump:
++          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
++
++          EXTRACT_NUMBER_AND_INCR (mcnt, p);
++#ifdef _LIBC
++          DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
++#else
++          DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
++#endif
++
++          PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
++          break;
++
++
++	/* Uses of on_failure_jump:
++
++           Each alternative starts with an on_failure_jump that points
++           to the beginning of the next alternative.  Each alternative
++           except the last ends with a jump that in effect jumps past
++           the rest of the alternatives.  (They really jump to the
++           ending jump of the following alternative, because tensioning
++           these jumps is a hassle.)
++
++           Repeats start with an on_failure_jump that points past both
++           the repetition text and either the following jump or
++           pop_failure_jump back to this on_failure_jump.  */
++	case on_failure_jump:
++        on_failure:
++          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
++
++          EXTRACT_NUMBER_AND_INCR (mcnt, p);
++#ifdef _LIBC
++          DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
++#else
++          DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
++#endif
++
++          /* If this on_failure_jump comes right before a group (i.e.,
++             the original * applied to a group), save the information
++             for that group and all inner ones, so that if we fail back
++             to this point, the group's information will be correct.
++             For example, in \(a*\)*\1, we need the preceding group,
++             and in \(zz\(a*\)b*\)\2, we need the inner group.  */
++
++          /* We can't use `p' to check ahead because we push
++             a failure point to `p + mcnt' after we do this.  */
++          p1 = p;
++
++          /* We need to skip no_op's before we look for the
++             start_memory in case this on_failure_jump is happening as
++             the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
++             against aba.  */
++          while (p1 < pend && (re_opcode_t) *p1 == no_op)
++            p1++;
++
++          if (p1 < pend && (re_opcode_t) *p1 == start_memory)
++            {
++              /* We have a new highest active register now.  This will
++                 get reset at the start_memory we are about to get to,
++                 but we will have saved all the registers relevant to
++                 this repetition op, as described above.  */
++              highest_active_reg = *(p1 + 1) + *(p1 + 2);
++              if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
++                lowest_active_reg = *(p1 + 1);
++            }
++
++          DEBUG_PRINT1 (":\n");
++          PUSH_FAILURE_POINT (p + mcnt, d, -2);
++          break;
++
++
++        /* A smart repeat ends with `maybe_pop_jump'.
++	   We change it to either `pop_failure_jump' or `jump'.  */
++        case maybe_pop_jump:
++          EXTRACT_NUMBER_AND_INCR (mcnt, p);
++          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
++          {
++	    register UCHAR_T *p2 = p;
++
++            /* Compare the beginning of the repeat with what in the
++               pattern follows its end. If we can establish that there
++               is nothing that they would both match, i.e., that we
++               would have to backtrack because of (as in, e.g., `a*a')
++               then we can change to pop_failure_jump, because we'll
++               never have to backtrack.
++
++               This is not true in the case of alternatives: in
++               `(a|ab)*' we do need to backtrack to the `ab' alternative
++               (e.g., if the string was `ab').  But instead of trying to
++               detect that here, the alternative has put on a dummy
++               failure point which is what we will end up popping.  */
++
++	    /* Skip over open/close-group commands.
++	       If what follows this loop is a ...+ construct,
++	       look at what begins its body, since we will have to
++	       match at least one of that.  */
++	    while (1)
++	      {
++		if (p2 + 2 < pend
++		    && ((re_opcode_t) *p2 == stop_memory
++			|| (re_opcode_t) *p2 == start_memory))
++		  p2 += 3;
++		else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend
++			 && (re_opcode_t) *p2 == dummy_failure_jump)
++		  p2 += 2 + 2 * OFFSET_ADDRESS_SIZE;
++		else
++		  break;
++	      }
++
++	    p1 = p + mcnt;
++	    /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
++	       to the `maybe_finalize_jump' of this case.  Examine what
++	       follows.  */
++
++            /* If we're at the end of the pattern, we can change.  */
++            if (p2 == pend)
++	      {
++		/* Consider what happens when matching ":\(.*\)"
++		   against ":/".  I don't really understand this code
++		   yet.  */
++  	        p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
++		  pop_failure_jump;
++                DEBUG_PRINT1
++                  ("  End of pattern: change to `pop_failure_jump'.\n");
++              }
++
++            else if ((re_opcode_t) *p2 == exactn
++#ifdef MBS_SUPPORT
++		     || (re_opcode_t) *p2 == exactn_bin
++#endif
++		     || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
++	      {
++		register UCHAR_T c
++                  = *p2 == (UCHAR_T) endline ? '\n' : p2[2];
++
++                if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn
++#ifdef MBS_SUPPORT
++		     || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin
++#endif
++		    ) && p1[3+OFFSET_ADDRESS_SIZE] != c)
++                  {
++  		    p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
++		      pop_failure_jump;
++#ifdef WCHAR
++		      DEBUG_PRINT3 ("  %C != %C => pop_failure_jump.\n",
++				    (wint_t) c,
++				    (wint_t) p1[3+OFFSET_ADDRESS_SIZE]);
++#else
++		      DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
++				    (char) c,
++				    (char) p1[3+OFFSET_ADDRESS_SIZE]);
++#endif
++                  }
++
++#ifndef WCHAR
++		else if ((re_opcode_t) p1[3] == charset
++			 || (re_opcode_t) p1[3] == charset_not)
++		  {
++		    int negate = (re_opcode_t) p1[3] == charset_not;
++
++		    if (c < (unsigned) (p1[4] * BYTEWIDTH)
++			&& p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
++		      negate = !negate;
++
++                    /* `negate' is equal to 1 if c would match, which means
++                        that we can't change to pop_failure_jump.  */
++		    if (!negate)
++                      {
++  		        p[-3] = (unsigned char) pop_failure_jump;
++                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
++                      }
++		  }
++#endif /* not WCHAR */
++	      }
++#ifndef WCHAR
++            else if ((re_opcode_t) *p2 == charset)
++	      {
++		/* We win if the first character of the loop is not part
++                   of the charset.  */
++                if ((re_opcode_t) p1[3] == exactn
++ 		    && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
++ 			  && (p2[2 + p1[5] / BYTEWIDTH]
++ 			      & (1 << (p1[5] % BYTEWIDTH)))))
++		  {
++		    p[-3] = (unsigned char) pop_failure_jump;
++		    DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
++                  }
++
++		else if ((re_opcode_t) p1[3] == charset_not)
++		  {
++		    int idx;
++		    /* We win if the charset_not inside the loop
++		       lists every character listed in the charset after.  */
++		    for (idx = 0; idx < (int) p2[1]; idx++)
++		      if (! (p2[2 + idx] == 0
++			     || (idx < (int) p1[4]
++				 && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
++			break;
++
++		    if (idx == p2[1])
++                      {
++  		        p[-3] = (unsigned char) pop_failure_jump;
++                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
++                      }
++		  }
++		else if ((re_opcode_t) p1[3] == charset)
++		  {
++		    int idx;
++		    /* We win if the charset inside the loop
++		       has no overlap with the one after the loop.  */
++		    for (idx = 0;
++			 idx < (int) p2[1] && idx < (int) p1[4];
++			 idx++)
++		      if ((p2[2 + idx] & p1[5 + idx]) != 0)
++			break;
++
++		    if (idx == p2[1] || idx == p1[4])
++                      {
++  		        p[-3] = (unsigned char) pop_failure_jump;
++                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
++                      }
++		  }
++	      }
++#endif /* not WCHAR */
++	  }
++	  p -= OFFSET_ADDRESS_SIZE;	/* Point at relative address again.  */
++	  if ((re_opcode_t) p[-1] != pop_failure_jump)
++	    {
++	      p[-1] = (UCHAR_T) jump;
++              DEBUG_PRINT1 ("  Match => jump.\n");
++	      goto unconditional_jump;
++	    }
++        /* Note fall through.  */
++
++
++	/* The end of a simple repeat has a pop_failure_jump back to
++           its matching on_failure_jump, where the latter will push a
++           failure point.  The pop_failure_jump takes off failure
++           points put on by this pop_failure_jump's matching
++           on_failure_jump; we got through the pattern to here from the
++           matching on_failure_jump, so didn't fail.  */
++        case pop_failure_jump:
++          {
++            /* We need to pass separate storage for the lowest and
++               highest registers, even though we don't care about the
++               actual values.  Otherwise, we will restore only one
++               register from the stack, since lowest will == highest in
++               `pop_failure_point'.  */
++            active_reg_t dummy_low_reg, dummy_high_reg;
++            UCHAR_T *pdummy = NULL;
++            const CHAR_T *sdummy = NULL;
++
++            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
++            POP_FAILURE_POINT (sdummy, pdummy,
++                               dummy_low_reg, dummy_high_reg,
++                               reg_dummy, reg_dummy, reg_info_dummy);
++          }
++	  /* Note fall through.  */
++
++	unconditional_jump:
++#ifdef _LIBC
++	  DEBUG_PRINT2 ("\n%p: ", p);
++#else
++	  DEBUG_PRINT2 ("\n0x%x: ", p);
++#endif
++          /* Note fall through.  */
++
++        /* Unconditionally jump (without popping any failure points).  */
++        case jump:
++	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
++          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
++	  p += mcnt;				/* Do the jump.  */
++#ifdef _LIBC
++          DEBUG_PRINT2 ("(to %p).\n", p);
++#else
++          DEBUG_PRINT2 ("(to 0x%x).\n", p);
++#endif
++	  break;
++
++
++        /* We need this opcode so we can detect where alternatives end
++           in `group_match_null_string_p' et al.  */
++        case jump_past_alt:
++          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
++          goto unconditional_jump;
++
++
++        /* Normally, the on_failure_jump pushes a failure point, which
++           then gets popped at pop_failure_jump.  We will end up at
++           pop_failure_jump, also, and with a pattern of, say, `a+', we
++           are skipping over the on_failure_jump, so we have to push
++           something meaningless for pop_failure_jump to pop.  */
++        case dummy_failure_jump:
++          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
++          /* It doesn't matter what we push for the string here.  What
++             the code at `fail' tests is the value for the pattern.  */
++          PUSH_FAILURE_POINT (NULL, NULL, -2);
++          goto unconditional_jump;
++
++
++        /* At the end of an alternative, we need to push a dummy failure
++           point in case we are followed by a `pop_failure_jump', because
++           we don't want the failure point for the alternative to be
++           popped.  For example, matching `(a|ab)*' against `aab'
++           requires that we match the `ab' alternative.  */
++        case push_dummy_failure:
++          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
++          /* See comments just above at `dummy_failure_jump' about the
++             two zeroes.  */
++          PUSH_FAILURE_POINT (NULL, NULL, -2);
++          break;
++
++        /* Have to succeed matching what follows at least n times.
++           After that, handle like `on_failure_jump'.  */
++        case succeed_n:
++          EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
++          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
++
++          assert (mcnt >= 0);
++          /* Originally, this is how many times we HAVE to succeed.  */
++          if (mcnt > 0)
++            {
++               mcnt--;
++	       p += OFFSET_ADDRESS_SIZE;
++               STORE_NUMBER_AND_INCR (p, mcnt);
++#ifdef _LIBC
++               DEBUG_PRINT3 ("  Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE
++			     , mcnt);
++#else
++               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE
++			     , mcnt);
++#endif
++            }
++	  else if (mcnt == 0)
++            {
++#ifdef _LIBC
++              DEBUG_PRINT2 ("  Setting two bytes from %p to no_op.\n",
++			    p + OFFSET_ADDRESS_SIZE);
++#else
++              DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n",
++			    p + OFFSET_ADDRESS_SIZE);
++#endif /* _LIBC */
++
++#ifdef WCHAR
++	      p[1] = (UCHAR_T) no_op;
++#else
++	      p[2] = (UCHAR_T) no_op;
++              p[3] = (UCHAR_T) no_op;
++#endif /* WCHAR */
++              goto on_failure;
++            }
++          break;
++
++        case jump_n:
++          EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
++          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
++
++          /* Originally, this is how many times we CAN jump.  */
++          if (mcnt)
++            {
++               mcnt--;
++               STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt);
++
++#ifdef _LIBC
++               DEBUG_PRINT3 ("  Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE,
++			     mcnt);
++#else
++               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE,
++			     mcnt);
++#endif /* _LIBC */
++	       goto unconditional_jump;
++            }
++          /* If don't have to jump any more, skip over the rest of command.  */
++	  else
++	    p += 2 * OFFSET_ADDRESS_SIZE;
++          break;
++
++	case set_number_at:
++	  {
++            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
++
++            EXTRACT_NUMBER_AND_INCR (mcnt, p);
++            p1 = p + mcnt;
++            EXTRACT_NUMBER_AND_INCR (mcnt, p);
++#ifdef _LIBC
++            DEBUG_PRINT3 ("  Setting %p to %d.\n", p1, mcnt);
++#else
++            DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
++#endif
++	    STORE_NUMBER (p1, mcnt);
++            break;
++          }
++
++#if 0
++	/* The DEC Alpha C compiler 3.x generates incorrect code for the
++	   test  WORDCHAR_P (d - 1) != WORDCHAR_P (d)  in the expansion of
++	   AT_WORD_BOUNDARY, so this code is disabled.  Expanding the
++	   macro and introducing temporary variables works around the bug.  */
++
++	case wordbound:
++	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
++	  if (AT_WORD_BOUNDARY (d))
++	    break;
++	  goto fail;
++
++	case notwordbound:
++	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
++	  if (AT_WORD_BOUNDARY (d))
++	    goto fail;
++	  break;
++#else
++	case wordbound:
++	{
++	  boolean prevchar, thischar;
++
++	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
++	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
++	    break;
++
++	  prevchar = WORDCHAR_P (d - 1);
++	  thischar = WORDCHAR_P (d);
++	  if (prevchar != thischar)
++	    break;
++	  goto fail;
++	}
++
++      case notwordbound:
++	{
++	  boolean prevchar, thischar;
++
++	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
++	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
++	    goto fail;
++
++	  prevchar = WORDCHAR_P (d - 1);
++	  thischar = WORDCHAR_P (d);
++	  if (prevchar != thischar)
++	    goto fail;
++	  break;
++	}
++#endif
++
++	case wordbeg:
++          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
++	  if (!AT_STRINGS_END (d) && WORDCHAR_P (d)
++	      && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
++	    break;
++          goto fail;
++
++	case wordend:
++          DEBUG_PRINT1 ("EXECUTING wordend.\n");
++	  if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
++              && (AT_STRINGS_END (d) || !WORDCHAR_P (d)))
++	    break;
++          goto fail;
++
++#ifdef emacs
++  	case before_dot:
++          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
++ 	  if (PTR_CHAR_POS ((unsigned char *) d) >= point)
++  	    goto fail;
++  	  break;
++
++  	case at_dot:
++          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
++ 	  if (PTR_CHAR_POS ((unsigned char *) d) != point)
++  	    goto fail;
++  	  break;
++
++  	case after_dot:
++          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
++          if (PTR_CHAR_POS ((unsigned char *) d) <= point)
++  	    goto fail;
++  	  break;
++
++	case syntaxspec:
++          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
++	  mcnt = *p++;
++	  goto matchsyntax;
++
++        case wordchar:
++          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
++	  mcnt = (int) Sword;
++        matchsyntax:
++	  PREFETCH ();
++	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
++	  d++;
++	  if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
++	    goto fail;
++          SET_REGS_MATCHED ();
++	  break;
++
++	case notsyntaxspec:
++          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
++	  mcnt = *p++;
++	  goto matchnotsyntax;
++
++        case notwordchar:
++          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
++	  mcnt = (int) Sword;
++        matchnotsyntax:
++	  PREFETCH ();
++	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
++	  d++;
++	  if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
++	    goto fail;
++	  SET_REGS_MATCHED ();
++          break;
++
++#else /* not emacs */
++	case wordchar:
++          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
++	  PREFETCH ();
++          if (!WORDCHAR_P (d))
++            goto fail;
++	  SET_REGS_MATCHED ();
++          d++;
++	  break;
++
++	case notwordchar:
++          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
++	  PREFETCH ();
++	  if (WORDCHAR_P (d))
++            goto fail;
++          SET_REGS_MATCHED ();
++          d++;
++	  break;
++#endif /* not emacs */
++
++        default:
++          abort ();
++	}
++      continue;  /* Successfully executed one pattern command; keep going.  */
++
++
++    /* We goto here if a matching operation fails. */
++    fail:
++      if (!FAIL_STACK_EMPTY ())
++	{ /* A restart point is known.  Restore to that state.  */
++          DEBUG_PRINT1 ("\nFAIL:\n");
++          POP_FAILURE_POINT (d, p,
++                             lowest_active_reg, highest_active_reg,
++                             regstart, regend, reg_info);
++
++          /* If this failure point is a dummy, try the next one.  */
++          if (!p)
++	    goto fail;
++
++          /* If we failed to the end of the pattern, don't examine *p.  */
++	  assert (p <= pend);
++          if (p < pend)
++            {
++              boolean is_a_jump_n = false;
++
++              /* If failed to a backwards jump that's part of a repetition
++                 loop, need to pop this failure point and use the next one.  */
++              switch ((re_opcode_t) *p)
++                {
++                case jump_n:
++                  is_a_jump_n = true;
++                case maybe_pop_jump:
++                case pop_failure_jump:
++                case jump:
++                  p1 = p + 1;
++                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++                  p1 += mcnt;
++
++                  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
++                      || (!is_a_jump_n
++                          && (re_opcode_t) *p1 == on_failure_jump))
++                    goto fail;
++                  break;
++                default:
++                  /* do nothing */ ;
++                }
++            }
++
++          if (d >= string1 && d <= end1)
++	    dend = end_match_1;
++        }
++      else
++        break;   /* Matching at this starting point really fails.  */
++    } /* for (;;) */
++
++  if (best_regs_set)
++    goto restore_best_regs;
++
++  FREE_VARIABLES ();
++
++  return -1;         			/* Failure to match.  */
++} /* re_match_2 */
++
++/* Subroutine definitions for re_match_2.  */
++
++
++/* We are passed P pointing to a register number after a start_memory.
++
++   Return true if the pattern up to the corresponding stop_memory can
++   match the empty string, and false otherwise.
++
++   If we find the matching stop_memory, sets P to point to one past its number.
++   Otherwise, sets P to an undefined byte less than or equal to END.
++
++   We don't handle duplicates properly (yet).  */
++
++static boolean
++PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
++                                   PREFIX(register_info_type) *reg_info)
++{
++  int mcnt;
++  /* Point to after the args to the start_memory.  */
++  UCHAR_T *p1 = *p + 2;
++
++  while (p1 < end)
++    {
++      /* Skip over opcodes that can match nothing, and return true or
++	 false, as appropriate, when we get to one that can't, or to the
++         matching stop_memory.  */
++
++      switch ((re_opcode_t) *p1)
++        {
++        /* Could be either a loop or a series of alternatives.  */
++        case on_failure_jump:
++          p1++;
++          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++
++          /* If the next operation is not a jump backwards in the
++	     pattern.  */
++
++	  if (mcnt >= 0)
++	    {
++              /* Go through the on_failure_jumps of the alternatives,
++                 seeing if any of the alternatives cannot match nothing.
++                 The last alternative starts with only a jump,
++                 whereas the rest start with on_failure_jump and end
++                 with a jump, e.g., here is the pattern for `a|b|c':
++
++                 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
++                 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
++                 /exactn/1/c
++
++                 So, we have to first go through the first (n-1)
++                 alternatives and then deal with the last one separately.  */
++
++
++              /* Deal with the first (n-1) alternatives, which start
++                 with an on_failure_jump (see above) that jumps to right
++                 past a jump_past_alt.  */
++
++              while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] ==
++		     jump_past_alt)
++                {
++                  /* `mcnt' holds how many bytes long the alternative
++                     is, including the ending `jump_past_alt' and
++                     its number.  */
++
++                  if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt -
++						(1 + OFFSET_ADDRESS_SIZE),
++						reg_info))
++                    return false;
++
++                  /* Move to right after this alternative, including the
++		     jump_past_alt.  */
++                  p1 += mcnt;
++
++                  /* Break if it's the beginning of an n-th alternative
++                     that doesn't begin with an on_failure_jump.  */
++                  if ((re_opcode_t) *p1 != on_failure_jump)
++                    break;
++
++		  /* Still have to check that it's not an n-th
++		     alternative that starts with an on_failure_jump.  */
++		  p1++;
++                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++                  if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] !=
++		      jump_past_alt)
++                    {
++		      /* Get to the beginning of the n-th alternative.  */
++                      p1 -= 1 + OFFSET_ADDRESS_SIZE;
++                      break;
++                    }
++                }
++
++              /* Deal with the last alternative: go back and get number
++                 of the `jump_past_alt' just before it.  `mcnt' contains
++                 the length of the alternative.  */
++              EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE);
++
++              if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info))
++                return false;
++
++              p1 += mcnt;	/* Get past the n-th alternative.  */
++            } /* if mcnt > 0 */
++          break;
++
++
++        case stop_memory:
++	  assert (p1[1] == **p);
++          *p = p1 + 2;
++          return true;
++
++
++        default:
++          if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
++            return false;
++        }
++    } /* while p1 < end */
++
++  return false;
++} /* group_match_null_string_p */
++
++
++/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
++   It expects P to be the first byte of a single alternative and END one
++   byte past the last. The alternative can contain groups.  */
++
++static boolean
++PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end,
++                                 PREFIX(register_info_type) *reg_info)
++{
++  int mcnt;
++  UCHAR_T *p1 = p;
++
++  while (p1 < end)
++    {
++      /* Skip over opcodes that can match nothing, and break when we get
++         to one that can't.  */
++
++      switch ((re_opcode_t) *p1)
++        {
++	/* It's a loop.  */
++        case on_failure_jump:
++          p1++;
++          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++          p1 += mcnt;
++          break;
++
++	default:
++          if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
++            return false;
++        }
++    }  /* while p1 < end */
++
++  return true;
++} /* alt_match_null_string_p */
++
++
++/* Deals with the ops common to group_match_null_string_p and
++   alt_match_null_string_p.
++
++   Sets P to one after the op and its arguments, if any.  */
++
++static boolean
++PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
++                                       PREFIX(register_info_type) *reg_info)
++{
++  int mcnt;
++  boolean ret;
++  int reg_no;
++  UCHAR_T *p1 = *p;
++
++  switch ((re_opcode_t) *p1++)
++    {
++    case no_op:
++    case begline:
++    case endline:
++    case begbuf:
++    case endbuf:
++    case wordbeg:
++    case wordend:
++    case wordbound:
++    case notwordbound:
++#ifdef emacs
++    case before_dot:
++    case at_dot:
++    case after_dot:
++#endif
++      break;
++
++    case start_memory:
++      reg_no = *p1;
++      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
++      ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info);
++
++      /* Have to set this here in case we're checking a group which
++         contains a group and a back reference to it.  */
++
++      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
++        REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
++
++      if (!ret)
++        return false;
++      break;
++
++    /* If this is an optimized succeed_n for zero times, make the jump.  */
++    case jump:
++      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++      if (mcnt >= 0)
++        p1 += mcnt;
++      else
++        return false;
++      break;
++
++    case succeed_n:
++      /* Get to the number of times to succeed.  */
++      p1 += OFFSET_ADDRESS_SIZE;
++      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++
++      if (mcnt == 0)
++        {
++          p1 -= 2 * OFFSET_ADDRESS_SIZE;
++          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
++          p1 += mcnt;
++        }
++      else
++        return false;
++      break;
++
++    case duplicate:
++      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
++        return false;
++      break;
++
++    case set_number_at:
++      p1 += 2 * OFFSET_ADDRESS_SIZE;
++
++    default:
++      /* All other opcodes mean we cannot match the empty string.  */
++      return false;
++  }
++
++  *p = p1;
++  return true;
++} /* common_op_match_null_string_p */
++
++
++/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
++   bytes; nonzero otherwise.  */
++
++static int
++PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, register int len,
++                        RE_TRANSLATE_TYPE translate)
++{
++  register const UCHAR_T *p1 = (const UCHAR_T *) s1;
++  register const UCHAR_T *p2 = (const UCHAR_T *) s2;
++  while (len)
++    {
++#ifdef WCHAR
++      if (((*p1<=0xff)?translate[*p1++]:*p1++)
++	  != ((*p2<=0xff)?translate[*p2++]:*p2++))
++	return 1;
++#else /* BYTE */
++      if (translate[*p1++] != translate[*p2++]) return 1;
++#endif /* WCHAR */
++      len--;
++    }
++  return 0;
++}
++
++
++#else /* not INSIDE_RECURSION */
++
++/* Entry points for GNU code.  */
++
++/* re_compile_pattern is the GNU regular expression compiler: it
++   compiles PATTERN (of length SIZE) and puts the result in BUFP.
++   Returns 0 if the pattern was valid, otherwise an error string.
++
++   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
++   are set in BUFP on entry.
++
++   We call regex_compile to do the actual compilation.  */
++
++const char *
++re_compile_pattern (const char *pattern, size_t length,
++                    struct re_pattern_buffer *bufp)
++{
++  reg_errcode_t ret;
++
++  /* GNU code is written to assume at least RE_NREGS registers will be set
++     (and at least one extra will be -1).  */
++  bufp->regs_allocated = REGS_UNALLOCATED;
++
++  /* And GNU code determines whether or not to get register information
++     by passing null for the REGS argument to re_match, etc., not by
++     setting no_sub.  */
++  bufp->no_sub = 0;
++
++  /* Match anchors at newline.  */
++  bufp->newline_anchor = 1;
++
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp);
++  else
++# endif
++    ret = byte_regex_compile (pattern, length, re_syntax_options, bufp);
++
++  if (!ret)
++    return NULL;
++  return gettext (re_error_msgid[(int) ret]);
++}
++#ifdef _LIBC
++weak_alias (__re_compile_pattern, re_compile_pattern)
++#endif
++
++/* Entry points compatible with 4.2 BSD regex library.  We don't define
++   them unless specifically requested.  */
++
++#if defined _REGEX_RE_COMP || defined _LIBC
++
++/* BSD has one and only one pattern buffer.  */
++static struct re_pattern_buffer re_comp_buf;
++
++char *
++#ifdef _LIBC
++/* Make these definitions weak in libc, so POSIX programs can redefine
++   these names if they don't use our functions, and still use
++   regcomp/regexec below without link errors.  */
++weak_function
++#endif
++re_comp (const char *s)
++{
++  reg_errcode_t ret;
++
++  if (!s)
++    {
++      if (!re_comp_buf.buffer)
++	return (char *) gettext ("No previous regular expression");
++      return 0;
++    }
++
++  if (!re_comp_buf.buffer)
++    {
++      re_comp_buf.buffer = (unsigned char *) malloc (200);
++      if (re_comp_buf.buffer == NULL)
++        return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
++      re_comp_buf.allocated = 200;
++
++      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
++      if (re_comp_buf.fastmap == NULL)
++	return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
++    }
++
++  /* Since `re_exec' always passes NULL for the `regs' argument, we
++     don't need to initialize the pattern buffer fields which affect it.  */
++
++  /* Match anchors at newlines.  */
++  re_comp_buf.newline_anchor = 1;
++
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
++  else
++# endif
++    ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
++
++  if (!ret)
++    return NULL;
++
++  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
++  return (char *) gettext (re_error_msgid[(int) ret]);
++}
++
++
++int
++#ifdef _LIBC
++weak_function
++#endif
++re_exec (const char *s)
++{
++  const int len = strlen (s);
++  return
++    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
++}
++
++#endif /* _REGEX_RE_COMP */
++
++/* POSIX.2 functions.  Don't define these for Emacs.  */
++
++#ifndef emacs
++
++/* regcomp takes a regular expression as a string and compiles it.
++
++   PREG is a regex_t *.  We do not expect any fields to be initialized,
++   since POSIX says we shouldn't.  Thus, we set
++
++     `buffer' to the compiled pattern;
++     `used' to the length of the compiled pattern;
++     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
++       REG_EXTENDED bit in CFLAGS is set; otherwise, to
++       RE_SYNTAX_POSIX_BASIC;
++     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
++     `fastmap' to an allocated space for the fastmap;
++     `fastmap_accurate' to zero;
++     `re_nsub' to the number of subexpressions in PATTERN.
++
++   PATTERN is the address of the pattern string.
++
++   CFLAGS is a series of bits which affect compilation.
++
++     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
++     use POSIX basic syntax.
++
++     If REG_NEWLINE is set, then . and [^...] don't match newline.
++     Also, regexec will try a match beginning after every newline.
++
++     If REG_ICASE is set, then we considers upper- and lowercase
++     versions of letters to be equivalent when matching.
++
++     If REG_NOSUB is set, then when PREG is passed to regexec, that
++     routine will report only success or failure, and nothing about the
++     registers.
++
++   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
++   the return codes and their meanings.)  */
++
++int
++regcomp (regex_t *preg, const char *pattern, int cflags)
++{
++  reg_errcode_t ret;
++  reg_syntax_t syntax
++    = (cflags & REG_EXTENDED) ?
++      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
++
++  /* regex_compile will allocate the space for the compiled pattern.  */
++  preg->buffer = 0;
++  preg->allocated = 0;
++  preg->used = 0;
++
++  /* Try to allocate space for the fastmap.  */
++  preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
++
++  if (cflags & REG_ICASE)
++    {
++      int i;
++
++      preg->translate
++	= (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
++				      * sizeof (*(RE_TRANSLATE_TYPE)0));
++      if (preg->translate == NULL)
++        return (int) REG_ESPACE;
++
++      /* Map uppercase characters to corresponding lowercase ones.  */
++      for (i = 0; i < CHAR_SET_SIZE; i++)
++        preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
++    }
++  else
++    preg->translate = NULL;
++
++  /* If REG_NEWLINE is set, newlines are treated differently.  */
++  if (cflags & REG_NEWLINE)
++    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
++      syntax &= ~RE_DOT_NEWLINE;
++      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
++      /* It also changes the matching behavior.  */
++      preg->newline_anchor = 1;
++    }
++  else
++    preg->newline_anchor = 0;
++
++  preg->no_sub = !!(cflags & REG_NOSUB);
++
++  /* POSIX says a null character in the pattern terminates it, so we
++     can use strlen here in compiling the pattern.  */
++# ifdef MBS_SUPPORT
++  if (MB_CUR_MAX != 1)
++    ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg);
++  else
++# endif
++    ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg);
++
++  /* POSIX doesn't distinguish between an unmatched open-group and an
++     unmatched close-group: both are REG_EPAREN.  */
++  if (ret == REG_ERPAREN) ret = REG_EPAREN;
++
++  if (ret == REG_NOERROR && preg->fastmap)
++    {
++      /* Compute the fastmap now, since regexec cannot modify the pattern
++	 buffer.  */
++      if (re_compile_fastmap (preg) == -2)
++	{
++	  /* Some error occurred while computing the fastmap, just forget
++	     about it.  */
++	  free (preg->fastmap);
++	  preg->fastmap = NULL;
++	}
++    }
++
++  return (int) ret;
++}
++#ifdef _LIBC
++weak_alias (__regcomp, regcomp)
++#endif
++
++
++/* regexec searches for a given pattern, specified by PREG, in the
++   string STRING.
++
++   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
++   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
++   least NMATCH elements, and we set them to the offsets of the
++   corresponding matched substrings.
++
++   EFLAGS specifies `execution flags' which affect matching: if
++   REG_NOTBOL is set, then ^ does not match at the beginning of the
++   string; if REG_NOTEOL is set, then $ does not match at the end.
++
++   We return 0 if we find a match and REG_NOMATCH if not.  */
++
++int
++regexec (const regex_t *preg, const char *string, size_t nmatch,
++         regmatch_t pmatch[], int eflags)
++{
++  int ret;
++  struct re_registers regs;
++  regex_t private_preg;
++  int len = strlen (string);
++  boolean want_reg_info = !preg->no_sub && nmatch > 0;
++
++  private_preg = *preg;
++
++  private_preg.not_bol = !!(eflags & REG_NOTBOL);
++  private_preg.not_eol = !!(eflags & REG_NOTEOL);
++
++  /* The user has told us exactly how many registers to return
++     information about, via `nmatch'.  We have to pass that on to the
++     matching routines.  */
++  private_preg.regs_allocated = REGS_FIXED;
++
++  if (want_reg_info)
++    {
++      regs.num_regs = nmatch;
++      regs.start = TALLOC (nmatch * 2, regoff_t);
++      if (regs.start == NULL)
++        return (int) REG_NOMATCH;
++      regs.end = regs.start + nmatch;
++    }
++
++  /* Perform the searching operation.  */
++  ret = re_search (&private_preg, string, len,
++                   /* start: */ 0, /* range: */ len,
++                   want_reg_info ? &regs : (struct re_registers *) 0);
++
++  /* Copy the register information to the POSIX structure.  */
++  if (want_reg_info)
++    {
++      if (ret >= 0)
++        {
++          unsigned r;
++
++          for (r = 0; r < nmatch; r++)
++            {
++              pmatch[r].rm_so = regs.start[r];
++              pmatch[r].rm_eo = regs.end[r];
++            }
++        }
++
++      /* If we needed the temporary register info, free the space now.  */
++      free (regs.start);
++    }
++
++  /* We want zero return to mean success, unlike `re_search'.  */
++  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
++}
++#ifdef _LIBC
++/* EGLIBC: This is handled in regexec-compat.c.  */
++/*weak_alias (__regexec, regexec)*/
++#include "regexec-compat.c"
++#endif
++
++
++/* Returns a message corresponding to an error code, ERRCODE, returned
++   from either regcomp or regexec.   We don't use PREG here.  */
++
++size_t
++regerror (int errcode, const regex_t *preg __attribute__ ((unused)),
++          char *errbuf, size_t errbuf_size)
++{
++  const char *msg;
++  size_t msg_size;
++
++  if (errcode < 0
++      || errcode >= (int) (sizeof (re_error_msgid)
++			   / sizeof (re_error_msgid[0])))
++    /* Only error codes returned by the rest of the code should be passed
++       to this routine.  If we are given anything else, or if other regex
++       code generates an invalid error code, then the program has a bug.
++       Dump core so we can fix it.  */
++    abort ();
++
++  msg = gettext (re_error_msgid[errcode]);
++
++  msg_size = strlen (msg) + 1; /* Includes the null.  */
++
++  if (errbuf_size != 0)
++    {
++      if (msg_size > errbuf_size)
++        {
++#if defined HAVE_MEMPCPY || defined _LIBC
++	  *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
++#else
++          memcpy (errbuf, msg, errbuf_size - 1);
++          errbuf[errbuf_size - 1] = 0;
++#endif
++        }
++      else
++        memcpy (errb