Blame sysdeps/powerpc/powerpc64/power8/strncpy.S

Packit 6c4009
/* Optimized strncpy/stpncpy implementation for PowerPC64/POWER8.
Packit 6c4009
   Copyright (C) 2015-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
Packit 6c4009
#ifdef USE_AS_STPNCPY
Packit 6c4009
# ifndef STPNCPY
Packit 6c4009
#   define FUNC_NAME __stpncpy
Packit 6c4009
# else
Packit 6c4009
#   define FUNC_NAME STPNCPY
Packit 6c4009
# endif
Packit 6c4009
#else
Packit 6c4009
# ifndef STRNCPY
Packit 6c4009
#  define FUNC_NAME strncpy
Packit 6c4009
# else
Packit 6c4009
#  define FUNC_NAME STRNCPY
Packit 6c4009
# endif
Packit 6c4009
#endif  /* !USE_AS_STPNCPY  */
Packit 6c4009
Packit 6c4009
#ifndef MEMSET
Packit 6c4009
/* For builds without IFUNC support, local calls should be made to internal
Packit 6c4009
   GLIBC symbol (created by libc_hidden_builtin_def).  */
Packit 6c4009
# ifdef SHARED
Packit 6c4009
#  define MEMSET_is_local
Packit 6c4009
#  define MEMSET   __GI_memset
Packit 6c4009
# else
Packit 6c4009
#  define MEMSET   memset
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define FRAMESIZE (FRAME_MIN_SIZE+48)
Packit 6c4009
Packit 6c4009
/* Implements the function
Packit 6c4009
Packit 6c4009
   char * [r3] strncpy (char *dest [r3], const char *src [r4], size_t n [r5])
Packit 6c4009
Packit 6c4009
   or
Packit 6c4009
Packit 6c4009
   char * [r3] stpncpy (char *dest [r3], const char *src [r4], size_t n [r5])
Packit 6c4009
Packit 6c4009
   if USE_AS_STPCPY is defined.
Packit 6c4009
Packit 6c4009
   The implementation uses unaligned doubleword access to avoid specialized
Packit 6c4009
   code paths depending of data alignment.  Although recent powerpc64 uses
Packit 6c4009
   64K as default, the page cross handling assumes minimum page size of
Packit 6c4009
   4k.  */
Packit 6c4009
Packit 6c4009
	.machine  power7
Packit 6c4009
#ifdef MEMSET_is_local
Packit 6c4009
ENTRY_TOCLESS (FUNC_NAME, 4)
Packit 6c4009
#else
Packit 6c4009
ENTRY (FUNC_NAME, 4)
Packit 6c4009
#endif
Packit 6c4009
	CALL_MCOUNT 3
Packit 6c4009
Packit 6c4009
        /* Check if the [src]+15 will cross a 4K page by checking if the bit
Packit 6c4009
           indicating the page size changes.  Basically:
Packit 6c4009
Packit 6c4009
           uint64_t srcin = (uint64_t)src;
Packit 6c4009
           uint64_t ob = srcin & 4096UL;
Packit 6c4009
           uint64_t nb = (srcin+15UL) & 4096UL;
Packit 6c4009
           if (ob ^ nb)
Packit 6c4009
             goto pagecross;  */
Packit 6c4009
Packit 6c4009
	addi	r10,r4,16
Packit 6c4009
	rlwinm	r9,r4,0,19,19
Packit 6c4009
Packit 6c4009
	/* Save some non-volatile registers on the stack.  */
Packit 6c4009
	std	r26,-48(r1)
Packit 6c4009
	std	r27,-40(r1)
Packit 6c4009
Packit 6c4009
	rlwinm	r8,r10,0,19,19
Packit 6c4009
Packit 6c4009
	std	r28,-32(r1)
Packit 6c4009
	std	r29,-24(r1)
Packit 6c4009
Packit 6c4009
	cmpld	cr7,r9,r8
Packit 6c4009
Packit 6c4009
	std	r30,-16(r1)
Packit 6c4009
	std	r31,-8(r1)
Packit 6c4009
Packit 6c4009
	/* Update CFI.  */
Packit 6c4009
	cfi_offset(r26, -48)
Packit 6c4009
	cfi_offset(r27, -40)
Packit 6c4009
	cfi_offset(r28, -32)
Packit 6c4009
	cfi_offset(r29, -24)
Packit 6c4009
	cfi_offset(r30, -16)
Packit 6c4009
	cfi_offset(r31, -8)
Packit 6c4009
Packit 6c4009
	beq	cr7,L(unaligned_lt_16)
Packit 6c4009
	rldicl	r9,r4,0,61
Packit 6c4009
	subfic	r8,r9,8
Packit 6c4009
	cmpld	cr7,r5,r8
Packit 6c4009
	bgt 	cr7,L(pagecross)
Packit 6c4009
Packit 6c4009
	/* At this points there is 1 to 15 bytes to check and write.  Since it could
Packit 6c4009
	   be either from first unaligned 16 bytes access or from bulk copy, the code
Packit 6c4009
	   uses an unrolled byte read/write instead of trying to analyze the cmpb
Packit 6c4009
	   results.  */
Packit 6c4009
L(short_path):
Packit 6c4009
	mr	r9,r3
Packit 6c4009
L(short_path_1):
Packit 6c4009
	/* Return if there are no more bytes to be written.  */
Packit 6c4009
	cmpdi	cr7,r5,0
Packit 6c4009
	beq	cr7,L(short_path_loop_end_1)
Packit 6c4009
L(short_path_2):
Packit 6c4009
	/* Copy one char from src (r4) and write it to dest (r9).  If it is the
Packit 6c4009
	   end-of-string, start the null padding.  Continue, otherwise.  */
Packit 6c4009
	lbz	r10,0(r4)
Packit 6c4009
	cmpdi	cr7,r10,0
Packit 6c4009
	stb	r10,0(r9)
Packit 6c4009
	beq	cr7,L(zero_pad_start_1)
Packit 6c4009
	/* If there are no more bytes to be written, return.  */
Packit 6c4009
	cmpdi	cr0,r5,1
Packit 6c4009
	addi	r8,r9,1
Packit 6c4009
	addi	r6,r5,-1
Packit 6c4009
	beq	cr0,L(short_path_loop_end_0)
Packit 6c4009
	/* Copy another char from src (r4) to dest (r9).  Check again if it is
Packit 6c4009
	   the end-of-string.  If so, start the null padding.  */
Packit 6c4009
	lbz	r10,1(r4)
Packit 6c4009
	cmpdi	cr7,r10,0
Packit 6c4009
	stb	r10,1(r9)
Packit 6c4009
	beq	cr7,L(zero_pad_start_prepare_1)
Packit 6c4009
	/* Eagerly decrement r5 by 3, which is the number of bytes already
Packit 6c4009
	   written, plus one write that will be performed later on.  */
Packit 6c4009
	addi	r10,r5,-3
Packit 6c4009
	b	L(short_path_loop_1)
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
L(short_path_loop):
Packit 6c4009
	/* At this point, the induction variable, r5, as well as the pointers
Packit 6c4009
	   to dest and src (r9 and r4, respectivelly) have been updated.
Packit 6c4009
Packit 6c4009
	   Note: The registers r7 and r10 are induction variables derived from
Packit 6c4009
	   r5.  They are used to determine if the total number of writes has
Packit 6c4009
	   been reached at every other write.
Packit 6c4009
Packit 6c4009
	   Copy one char from src (r4) and write it to dest (r9).  If it is the
Packit 6c4009
	   end-of-string, start the null padding.  Continue, otherwise.  */
Packit 6c4009
	lbz	r8,0(r4)
Packit 6c4009
	addi	r7,r10,-2
Packit 6c4009
	cmpdi	cr5,r8,0
Packit 6c4009
	stb	r8,0(r9)
Packit 6c4009
	beq	cr5,L(zero_pad_start_1)
Packit 6c4009
	beq	cr7,L(short_path_loop_end_0)
Packit 6c4009
	/* Copy another char from src (r4) to dest (r9).  Check again if it is
Packit 6c4009
	   the end-of-string.  If so, start the null padding.  */
Packit 6c4009
	lbz	r8,1(r4)
Packit 6c4009
	cmpdi	cr7,r8,0
Packit 6c4009
	stb	r8,1(r9)
Packit 6c4009
	beq	cr7,L(zero_pad_start)
Packit 6c4009
	mr	r10,r7
Packit 6c4009
L(short_path_loop_1):
Packit 6c4009
	/* This block is reached after two chars have been already written to
Packit 6c4009
	   dest.  Nevertheless, r5 (the induction variable), r9 (the pointer to
Packit 6c4009
	   dest), and r4 (the pointer to src) have not yet been updated.
Packit 6c4009
Packit 6c4009
	   At this point:
Packit 6c4009
	     r5 holds the count of bytes yet to be written plus 2.
Packit 6c4009
	     r9 points to the last two chars that were already written to dest.
Packit 6c4009
	     r4 points to the last two chars that were already copied from src.
Packit 6c4009
Packit 6c4009
	   The algorithm continues by decrementing r5, the induction variable,
Packit 6c4009
	   so that it reflects the last two writes.  The pointers to dest (r9)
Packit 6c4009
	   and to src (r4) are increment by two, for the same reason.
Packit 6c4009
Packit 6c4009
	   Note: Register r10 is another induction variable, derived from r5,
Packit 6c4009
	   which determines if the total number of writes has been reached.  */
Packit 6c4009
	addic.	r5,r5,-2
Packit 6c4009
	addi	r9,r9,2
Packit 6c4009
	cmpdi	cr7,r10,0 /* Eagerly check if the next write is the last.  */
Packit 6c4009
	addi	r4,r4,2
Packit 6c4009
	addi	r6,r9,1
Packit 6c4009
	bne	cr0,L(short_path_loop) /* Check if the total number of writes
Packit 6c4009
					  has been reached at every other
Packit 6c4009
					  write.  */
Packit 6c4009
#ifdef USE_AS_STPNCPY
Packit 6c4009
	mr	r3,r9
Packit 6c4009
	b	L(short_path_loop_end)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
L(short_path_loop_end_0):
Packit 6c4009
#ifdef USE_AS_STPNCPY
Packit 6c4009
	addi	r3,r9,1
Packit 6c4009
	b	L(short_path_loop_end)
Packit 6c4009
#endif
Packit 6c4009
L(short_path_loop_end_1):
Packit 6c4009
#ifdef USE_AS_STPNCPY
Packit 6c4009
	mr	r3,r9
Packit 6c4009
#endif
Packit 6c4009
L(short_path_loop_end):
Packit 6c4009
	/* Restore non-volatile registers.  */
Packit 6c4009
	ld	r26,-48(r1)
Packit 6c4009
	ld	r27,-40(r1)
Packit 6c4009
	ld	r28,-32(r1)
Packit 6c4009
	ld	r29,-24(r1)
Packit 6c4009
	ld	r30,-16(r1)
Packit 6c4009
	ld	r31,-8(r1)
Packit 6c4009
	blr
Packit 6c4009
Packit 6c4009
	/* This code pads the remainder of dest with NULL bytes.  The algorithm
Packit 6c4009
	   calculates the remaining size and calls memset.  */
Packit 6c4009
	.align	4
Packit 6c4009
L(zero_pad_start):
Packit 6c4009
	mr	r5,r10
Packit 6c4009
	mr	r9,r6
Packit 6c4009
L(zero_pad_start_1):
Packit 6c4009
	/* At this point:
Packit 6c4009
	     - r5 holds the number of bytes that still have to be written to
Packit 6c4009
	       dest.
Packit 6c4009
	     - r9 points to the position, in dest, where the first null byte
Packit 6c4009
	       will be written.
Packit 6c4009
	   The above statements are true both when control reaches this label
Packit 6c4009
	   from a branch or when falling through the previous lines.  */
Packit 6c4009
#ifndef USE_AS_STPNCPY
Packit 6c4009
	mr	r30,r3       /* Save the return value of strncpy.  */
Packit 6c4009
#endif
Packit 6c4009
	/* Prepare the call to memset.  */
Packit 6c4009
	mr	r3,r9        /* Pointer to the area to be zero-filled.  */
Packit 6c4009
	li	r4,0         /* Byte to be written (zero).  */
Packit 6c4009
Packit 6c4009
	/* We delayed the creation of the stack frame, as well as the saving of
Packit 6c4009
	   the link register, because only at this point, we are sure that
Packit 6c4009
	   doing so is actually needed.  */
Packit 6c4009
Packit 6c4009
	/* Save the link register.  */
Packit 6c4009
	mflr	r0
Packit 6c4009
	std	r0,16(r1)
Packit 6c4009
Packit 6c4009
	/* Create the stack frame.  */
Packit 6c4009
	stdu	r1,-FRAMESIZE(r1)
Packit 6c4009
	cfi_adjust_cfa_offset(FRAMESIZE)
Packit 6c4009
	cfi_offset(lr, 16)
Packit 6c4009
Packit 6c4009
	bl	MEMSET
Packit 6c4009
#ifndef MEMSET_is_local
Packit 6c4009
	nop
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	ld	r0,FRAMESIZE+16(r1)
Packit 6c4009
Packit 6c4009
#ifndef USE_AS_STPNCPY
Packit 6c4009
	mr	r3,r30       /* Restore the return value of strncpy, i.e.:
Packit 6c4009
				dest.  For stpncpy, the return value is the
Packit 6c4009
				same as return value of memset.  */
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	/* Restore non-volatile registers and return.  */
Packit 6c4009
	ld	r26,FRAMESIZE-48(r1)
Packit 6c4009
	ld	r27,FRAMESIZE-40(r1)
Packit 6c4009
	ld	r28,FRAMESIZE-32(r1)
Packit 6c4009
	ld	r29,FRAMESIZE-24(r1)
Packit 6c4009
	ld	r30,FRAMESIZE-16(r1)
Packit 6c4009
	ld	r31,FRAMESIZE-8(r1)
Packit 6c4009
	/* Restore the stack frame.  */
Packit 6c4009
	addi	r1,r1,FRAMESIZE
Packit 6c4009
	cfi_adjust_cfa_offset(-FRAMESIZE)
Packit 6c4009
	/* Restore the link register.  */
Packit 6c4009
	mtlr	r0
Packit 6c4009
	cfi_restore(lr)
Packit 6c4009
	blr
Packit 6c4009
Packit 6c4009
	/* The common case where [src]+16 will not cross a 4K page boundary.
Packit 6c4009
	   In this case the code fast check the first 16 bytes by using doubleword
Packit 6c4009
	   read/compares and update destiny if neither total size or null byte
Packit 6c4009
	   is found in destiny. */
Packit 6c4009
	.align	4
Packit 6c4009
L(unaligned_lt_16):
Packit 6c4009
	cmpldi	cr7,r5,7
Packit 6c4009
	ble	cr7,L(short_path)
Packit 6c4009
	ld	r7,0(r4)
Packit 6c4009
	li	r8,0
Packit 6c4009
	cmpb	r8,r7,r8
Packit 6c4009
	cmpdi	cr7,r8,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2)
Packit 6c4009
	addi	r6,r5,-8
Packit 6c4009
	std	r7,0(r3)
Packit 6c4009
	addi	r9,r3,8
Packit 6c4009
	cmpldi	cr7,r6,7
Packit 6c4009
	addi	r7,r4,8
Packit 6c4009
	ble	cr7,L(short_path_prepare_1_1)
Packit 6c4009
	ld	r4,8(r4)
Packit 6c4009
	cmpb	r8,r4,r8
Packit 6c4009
	cmpdi	cr7,r8,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2_1)
Packit 6c4009
	std	r4,8(r3)
Packit 6c4009
	addi	r29,r3,16
Packit 6c4009
	addi	r5,r5,-16
Packit 6c4009
	/* Neither the null byte was found or total length was reached,
Packit 6c4009
	   align to 16 bytes and issue a bulk copy/compare.  */
Packit 6c4009
	b	L(align_to_16b)
Packit 6c4009
Packit 6c4009
	/* In the case of 4k page boundary cross, the algorithm first align
Packit 6c4009
	   the address to a doubleword, calculate a mask based on alignment
Packit 6c4009
	   to ignore the bytes and continue using doubleword.  */
Packit 6c4009
	.align	4
Packit 6c4009
L(pagecross):
Packit 6c4009
	rldicr	r11,r4,0,59	/* Align the address to 8 bytes boundary.  */
Packit 6c4009
	li	r6,-1		/* MASK = 0xffffffffffffffffUL.  */
Packit 6c4009
	sldi	r9,r9,3		/* Calculate padding.  */
Packit 6c4009
	ld	r7,0(r11)	/* Load doubleword from memory.  */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	sld	r9,r6,r9	/* MASK = MASK << padding.  */
Packit 6c4009
#else
Packit 6c4009
	srd	r9,r6,r9	/* MASK = MASK >> padding.  */
Packit 6c4009
#endif
Packit 6c4009
	orc	r9,r7,r9	/* Mask bits that are not part of the
Packit 6c4009
				   string.  */
Packit 6c4009
	li	r7,0
Packit 6c4009
	cmpb	r9,r9,r7	/* Check for null bytes in DWORD1.  */
Packit 6c4009
	cmpdi	cr7,r9,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2)
Packit 6c4009
	subf	r8,r8,r5	/* Adjust total length.  */
Packit 6c4009
	cmpldi	cr7,r8,8	/* Check if length was reached.  */
Packit 6c4009
	ble	cr7,L(short_path_prepare_2)
Packit 6c4009
Packit 6c4009
	/* For next checks we have aligned address, so we check for more
Packit 6c4009
	   three doublewords to make sure we can read 16 unaligned bytes
Packit 6c4009
	   to start the bulk copy with 16 aligned addresses.  */
Packit 6c4009
	ld	r7,8(r11)
Packit 6c4009
	cmpb	r9,r7,r9
Packit 6c4009
	cmpdi	cr7,r9,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2)
Packit 6c4009
	addi	r7,r8,-8
Packit 6c4009
	cmpldi	cr7,r7,8
Packit 6c4009
	ble	cr7,L(short_path_prepare_2)
Packit 6c4009
	ld	r7,16(r11)
Packit 6c4009
	cmpb	r9,r7,r9
Packit 6c4009
	cmpdi	cr7,r9,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2)
Packit 6c4009
	addi	r8,r8,-16
Packit 6c4009
	cmpldi	cr7,r8,8
Packit 6c4009
	ble	cr7,L(short_path_prepare_2)
Packit 6c4009
	ld	r8,24(r11)
Packit 6c4009
	cmpb	r9,r8,r9
Packit 6c4009
	cmpdi	cr7,r9,0
Packit 6c4009
	bne	cr7,L(short_path_prepare_2)
Packit 6c4009
Packit 6c4009
	/* No null byte found in the 32 bytes readed and length not reached,
Packit 6c4009
	   read source again using unaligned loads and store them.  */
Packit 6c4009
	ld	r9,0(r4)
Packit 6c4009
	addi	r29,r3,16
Packit 6c4009
	addi	r5,r5,-16
Packit 6c4009
	std	r9,0(r3)
Packit 6c4009
	ld	r9,8(r4)
Packit 6c4009
	std	r9,8(r3)
Packit 6c4009
Packit 6c4009
	/* Align source to 16 bytes and adjust destiny and size.  */
Packit 6c4009
L(align_to_16b):
Packit 6c4009
	rldicl	r9,r10,0,60
Packit 6c4009
	rldicr	r28,r10,0,59
Packit 6c4009
	add	r12,r5,r9
Packit 6c4009
	subf	r29,r9,r29
Packit 6c4009
Packit 6c4009
	/* The bulk read/compare/copy loads two doublewords, compare and merge
Packit 6c4009
	   in a single register for speed.  This is an attempt to speed up the
Packit 6c4009
	   null-checking process for bigger strings.  */
Packit 6c4009
Packit 6c4009
	cmpldi	cr7,r12,15
Packit 6c4009
	ble	cr7,L(short_path_prepare_1_2)
Packit 6c4009
Packit 6c4009
	/* Main loop for large sizes, unrolled 2 times to get better use of
Packit 6c4009
	   pipeline.  */
Packit 6c4009
	ld	r8,0(28)
Packit 6c4009
	ld	r10,8(28)
Packit 6c4009
	li	r9,0
Packit 6c4009
	cmpb	r7,r8,r9
Packit 6c4009
	cmpb	r9,r10,r9
Packit 6c4009
	or.	r6,r9,r7
Packit 6c4009
	bne	cr0,L(short_path_prepare_2_3)
Packit 6c4009
	addi	r5,r12,-16
Packit 6c4009
	addi	r4,r28,16
Packit 6c4009
	std	r8,0(r29)
Packit 6c4009
	std	r10,8(r29)
Packit 6c4009
	cmpldi	cr7,r5,15
Packit 6c4009
	addi	r9,r29,16
Packit 6c4009
	ble	cr7,L(short_path_1)
Packit 6c4009
	mr	r11,r28
Packit 6c4009
	mr	r6,r29
Packit 6c4009
	li	r30,0
Packit 6c4009
	subfic	r26,r4,48
Packit 6c4009
	subfic	r27,r9,48
Packit 6c4009
Packit 6c4009
	b	L(loop_16b)
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
L(loop_start):
Packit 6c4009
	ld	r31,0(r11)
Packit 6c4009
	ld	r10,8(r11)
Packit 6c4009
	cmpb	r0,r31,r7
Packit 6c4009
	cmpb	r8,r10,r7
Packit 6c4009
	or.	r7,r0,r8
Packit 6c4009
	addi	r5,r5,-32
Packit 6c4009
	cmpldi	cr7,r5,15
Packit 6c4009
	add	r4,r4,r26
Packit 6c4009
	add	r9,r9,r27
Packit 6c4009
	bne	cr0,L(short_path_prepare_2_2)
Packit 6c4009
	add	r4,r28,r4
Packit 6c4009
	std	r31,0(r6)
Packit 6c4009
	add	r9,r29,r9
Packit 6c4009
	std	r10,8(r6)
Packit 6c4009
	ble	cr7,L(short_path_1)
Packit 6c4009
Packit 6c4009
L(loop_16b):
Packit 6c4009
	ld	r10,16(r11)
Packit 6c4009
	ld	r0,24(r11)
Packit 6c4009
	cmpb	r8,r10,r30
Packit 6c4009
	cmpb	r7,r0,r30
Packit 6c4009
	or.	r7,r8,r7
Packit 6c4009
	addi	r12,r12,-32
Packit 6c4009
	cmpldi	cr7,r12,15
Packit 6c4009
	addi	r11,r11,32
Packit 6c4009
	bne	cr0,L(short_path_2)
Packit 6c4009
	std	r10,16(r6)
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	std	r0,-8(r6)
Packit 6c4009
	bgt	cr7,L(loop_start)
Packit 6c4009
Packit 6c4009
	mr	r5,r12
Packit 6c4009
	mr	r4,r11
Packit 6c4009
	mr	r9,r6
Packit 6c4009
	b	L(short_path_1)
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
L(short_path_prepare_1_1):
Packit 6c4009
	mr	r5,r6
Packit 6c4009
	mr	r4,r7
Packit 6c4009
	b	L(short_path_1)
Packit 6c4009
L(short_path_prepare_1_2):
Packit 6c4009
	mr	r5,r12
Packit 6c4009
	mr	r4,r28
Packit 6c4009
	mr	r9,r29
Packit 6c4009
	b	L(short_path_1)
Packit 6c4009
L(short_path_prepare_2):
Packit 6c4009
	mr	r9,r3
Packit 6c4009
	b	L(short_path_2)
Packit 6c4009
L(short_path_prepare_2_1):
Packit 6c4009
	mr	r5,r6
Packit 6c4009
	mr	r4,r7
Packit 6c4009
	b	L(short_path_2)
Packit 6c4009
L(short_path_prepare_2_2):
Packit 6c4009
	mr	r5,r12
Packit 6c4009
	mr	r4,r11
Packit 6c4009
	mr	r9,r6
Packit 6c4009
	b	L(short_path_2)
Packit 6c4009
L(short_path_prepare_2_3):
Packit 6c4009
	mr	r5,r12
Packit 6c4009
	mr	r4,r28
Packit 6c4009
	mr	r9,r29
Packit 6c4009
	b	L(short_path_2)
Packit 6c4009
L(zero_pad_start_prepare_1):
Packit 6c4009
	mr	r5,r6
Packit 6c4009
	mr	r9,r8
Packit 6c4009
	b	L(zero_pad_start_1)
Packit 6c4009
END (FUNC_NAME)
Packit 6c4009
Packit 6c4009
#ifndef USE_AS_STPNCPY
Packit 6c4009
libc_hidden_builtin_def (strncpy)
Packit 6c4009
#endif