From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28273 invoked by alias); 27 Feb 2013 03:17:34 -0000 Received: (qmail 28206 invoked by uid 22791); 27 Feb 2013 03:17:32 -0000 X-SWARE-Spam-Status: No, hits=-5.1 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,KHOP_RCVD_TRUST,KHOP_SPAMHAUS_DROP,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_CP,TW_DR,TW_MV,TW_OV,TW_XF X-Spam-Check-By: sourceware.org Received: from mail-da0-f42.google.com (HELO mail-da0-f42.google.com) (209.85.210.42) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Feb 2013 03:17:10 +0000 Received: by mail-da0-f42.google.com with SMTP id n15so59222dad.29 for ; Tue, 26 Feb 2013 19:17:08 -0800 (PST) X-Received: by 10.68.180.1 with SMTP id dk1mr889018pbc.209.1361935028827; Tue, 26 Feb 2013 19:17:08 -0800 (PST) Received: from pebble.twiddle.net (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id pp1sm265271pac.7.2013.02.26.19.17.07 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 26 Feb 2013 19:17:07 -0800 (PST) From: Richard Henderson To: libc-ports@sourceware.org Cc: Joseph Myers Subject: [PATCH 21/26] arm: Implement armv6t2 optimized strcpy Date: Wed, 27 Feb 2013 03:17:00 -0000 Message-Id: <1361934986-17018-22-git-send-email-rth@twiddle.net> In-Reply-To: <1361934986-17018-1-git-send-email-rth@twiddle.net> References: <1361934986-17018-1-git-send-email-rth@twiddle.net> X-IsSubscribed: yes Mailing-List: contact libc-ports-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: libc-ports-owner@sourceware.org X-SW-Source: 2013-02/txt/msg00097.txt.bz2 Four times faster than the byte-by-byte default version. --- * sysdeps/arm/armv6t2/strcpy.S: New file. * sysdeps/arm/armv6t2/stpcpy.S: New file. --- ports/sysdeps/arm/armv6t2/stpcpy.S | 1 + ports/sysdeps/arm/armv6t2/strcpy.S | 213 +++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 ports/sysdeps/arm/armv6t2/stpcpy.S create mode 100644 ports/sysdeps/arm/armv6t2/strcpy.S diff --git a/ports/sysdeps/arm/armv6t2/stpcpy.S b/ports/sysdeps/arm/armv6t2/stpcpy.S new file mode 100644 index 0000000..21a4f38 --- /dev/null +++ b/ports/sysdeps/arm/armv6t2/stpcpy.S @@ -0,0 +1 @@ +/* Defined in strcpy.S. */ diff --git a/ports/sysdeps/arm/armv6t2/strcpy.S b/ports/sysdeps/arm/armv6t2/strcpy.S new file mode 100644 index 0000000..a0e3bcc --- /dev/null +++ b/ports/sysdeps/arm/armv6t2/strcpy.S @@ -0,0 +1,213 @@ +/* Copyright (C) 2013 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 + . */ + +#include + +/* Endian independent macros for shifting bytes within registers. */ +#ifdef __ARMEB__ +#define lsh_gt lsr +#define lsh_ls lsl +#else +#define lsh_gt lsl +#define lsh_ls lsr +#endif + +#ifndef USE_AS_STPCPY +# define STRCPY strcpy +#endif + + .syntax unified + .text + +ENTRY(__stpcpy) + @ Signal stpcpy with NULL in IP. + s(mov) ip, #0 + b 0f +END(__stpcpy) + +weak_alias (__stpcpy, stpcpy) +libc_hidden_def (__stpcpy) +libc_hidden_builtin_def (stpcpy) + +ENTRY(strcpy) + @ Signal strcpy with DEST in IP. + mov ip, r0 +0: + @ To cater to long strings, we want 8 byte alignment in the source. + @ To cater to small strings, we don't want to start that right away. + @ Loop up to 16 times, less whatever it takes to reach alignment. + and r3, r1, #7 + rsb r3, r3, #16 + + @ Loop until we find ... +1: ldrb r2, [r1], #1 + subs r3, r3, #1 @ ... the alignment point + strb r2, [r0], #1 + it ne + cmpne r2, #0 @ ... or EOS + bne 1b + + @ Disambiguate the exit possibilites above + cmp r2, #0 @ Found EOS + beq .Lreturn + + @ Load the next two words asap + ldrd r2, r3, [r1], #8 + + @ For longer strings, we actaully need a stack frame. + push { r4, r5, r6, r7 } + cfi_adjust_cfa_offset (16) + cfi_rel_offset (r4, 0) + cfi_rel_offset (r5, 4) + cfi_rel_offset (r6, 8) + cfi_rel_offset (r7, 12) + + @ Adding (unsigned saturating) 0xfe means result of 0xfe for any byte + @ that was originally zero and 0xff otherwise. Therefore we consider + @ the lsb of each byte the "found" bit, with 0 for a match. + movw r7, #0xfefe + tst r0, #3 @ Test alignment of DEST + movt r7, #0xfefe + bne .Lunaligned + + @ So now source (r1) is aligned to 8, and dest (r0) is aligned to 4. + @ Loop, reading 8 bytes at a time, searching for EOS. + .balign 16 +2: uqadd8 r4, r2, r7 @ Find EOS + uqadd8 r5, r3, r7 + pld [r1, #256] + mvns r4, r4 @ EOS in first word? + + pld [r0, #256] + bne 3f + str r2, [r0], #4 + mvns r5, r5 @ EOS in second word? + + bne 4f + str r3, [r0], #4 + ldrd r2, r3, [r1], #8 + b 2b + +3: s(sub) r1, r1, #4 @ backup to first word +4: s(sub) r1, r1, #4 @ backup to second word + + @ ... then finish up any tail a byte at a time. + @ Note that we generally back up and re-read source bytes, + @ but we'll not re-write dest bytes. +.Lbyte_loop: + ldrb r2, [r1], #1 + cmp r2, #0 + strb r2, [r0], #1 + bne .Lbyte_loop + + pop { r4, r5, r6, r7 } + cfi_remember_state + cfi_adjust_cfa_offset (-16) + cfi_restore (r4) + cfi_restore (r5) + cfi_restore (r6) + cfi_restore (r7) + +.Lreturn: + cmp ip, #0 @ Was this strcpy or strcpy? + ite eq + subeq r0, r0, #1 @ stpcpy: undo post-inc from store + movne r0, ip @ strcpy: return original dest + bx lr + +.Lunaligned: + cfi_restore_state + @ Here, source is aligned to 8, but the destination is not word + @ aligned. Therefore we have to shift the data in order to be + @ able to perform aligned word stores. + + @ Find out which misalignment we're dealing with. + tst r0, #1 + beq .Lunaligned2 + tst r0, #2 + bne .Lunaligned3 + @ Fallthru to .Lunaligned1. + +.macro unaligned_copy unalign + @ Prologue to unaligned loop. Seed shifted non-zero bytes. + uqadd8 r4, r2, r7 @ Find EOS + uqadd8 r5, r3, r7 + mvns r4, r4 @ EOS in first word? + it ne + subne r1, r1, #8 + bne .Lbyte_loop +#ifdef __ARMEB__ + rev r2, r2 @ Byte stores below need LE data +#endif + @ Store a few bytes from the first word. + @ At the same time we align r0 and shift out bytes from r2. +.rept 4-\unalign + strb r2, [r0], #1 + s(lsr) r2, r2, #8 +.endr +#ifdef __ARMEB__ + rev r2, r2 @ Undo previous rev +#endif + @ Rotated unaligned copy loop. The tail of the prologue is + @ shared with the loop itself. + .balign 8 +1: mvns r5, r5 @ EOS in second word? + bne 4f + @ Combine first and second words + orr r2, r2, r3, lsh_gt #(\unalign*8) + @ Save leftover bytes from the two words + lsh_ls r6, r3, #((4-\unalign)*8) + str r2, [r0], #4 + @ The "real" start of the unaligned copy loop. + ldrd r2, r3, [r1], #8 @ Load 8 more bytes + uqadd8 r4, r2, r7 @ Find EOS + pld [r1, #256] + uqadd8 r5, r3, r7 + pld [r0, #256] + mvns r4, r4 @ EOS in first word? + bne 3f + @ Combine the leftover and the first word + orr r6, r6, r2, lsh_gt #(\unalign*8) + @ Discard used bytes from the first word. + lsh_ls r2, r2, #((4-\unalign)*8) + str r6, [r0], #4 + b 1b + @ Found EOS in one of the words; adjust backward +3: s(sub) r1, r1, #4 + mov r2, r6 +4: s(sub) r1, r1, #4 + @ And store the remaining bytes from the leftover +#ifdef __ARMEB__ + rev r2, r2 +#endif +.rept \unalign + strb r2, [r0], #1 + s(lsr) r2, r2, #8 +.endr + b .Lbyte_loop +.endm + +.Lunaligned1: + unaligned_copy 1 +.Lunaligned2: + unaligned_copy 2 +.Lunaligned3: + unaligned_copy 3 + +END(STRCPY) + +libc_hidden_builtin_def (strcpy) -- 1.8.1.2