2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * Optimised string operations
26 FILE_LICENCE ( GPL2_OR_LATER );
33 * @v dest Destination address
34 * @v src Source address
36 * @ret dest Destination address
38 void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src,
41 const void *esi = src;
44 /* We often do large dword-aligned and dword-length block
45 * moves. Using movsl rather than movsb speeds these up by
48 __asm__ __volatile__ ( "rep movsl"
49 : "=&D" ( edi ), "=&S" ( esi ),
51 : "0" ( edi ), "1" ( esi ), "2" ( len >> 2 )
53 __asm__ __volatile__ ( "rep movsb"
54 : "=&D" ( edi ), "=&S" ( esi ),
56 : "0" ( edi ), "1" ( esi ), "2" ( len & 3 )
62 * Copy memory area backwards
64 * @v dest Destination address
65 * @v src Source address
67 * @ret dest Destination address
69 void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest,
72 void *edi = ( dest + len - 1 );
73 const void *esi = ( src + len - 1 );
76 /* Assume memmove() is not performance-critical, and perform a
77 * bytewise copy for simplicity.
79 __asm__ __volatile__ ( "std\n\t"
82 : "=&D" ( edi ), "=&S" ( esi ),
84 : "0" ( edi ), "1" ( esi ),
92 * Copy (possibly overlapping) memory area
94 * @v dest Destination address
95 * @v src Source address
97 * @ret dest Destination address
99 void * __memmove ( void *dest, const void *src, size_t len ) {
102 return __memcpy ( dest, src, len );
104 return __memcpy_reverse ( dest, src, len );
111 * @v dest Destination address
112 * @v src Source address
114 * @ret dest Destination address
116 void * memswap ( void *dest, void *src, size_t len ) {
120 __asm__ __volatile__ ( "\n1:\n\t"
123 "movb (%0,%2), %b3\n\t"
124 "xchgb (%1,%2), %b3\n\t"
125 "movb %b3, (%0,%2)\n\t"
128 : "=r" ( src ), "=r" ( dest ),
129 "=&c" ( discard_c ), "=&q" ( discard )
130 : "0" ( src ), "1" ( dest ), "2" ( len )
137 * Calculate length of string
140 * @ret len Length (excluding NUL)
142 size_t strlen ( const char *string ) {
143 const char *discard_D;
146 __asm__ __volatile__ ( "repne scasb\n\t"
148 : "=&D" ( discard_D ), "=&c" ( len_plus_one )
149 : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) );
151 return ( len_plus_one - 1 );
155 * Compare strings (up to a specified length)
157 * @v str1 First string
158 * @v str2 Second string
159 * @v len Maximum length
160 * @ret diff Difference
162 int strncmp ( const char *str1, const char *str2, size_t len ) {
163 const void *discard_S;
164 const void *discard_D;
168 __asm__ __volatile__ ( "\n1:\n\t"
180 /* Not equal; CF indicates difference */
185 : "=&S" ( discard_S ), "=&D" ( discard_D ),
186 "=&c" ( discard_c ), "=&a" ( diff )
187 : "0" ( str1 ), "1" ( str2 ), "2" ( len ) );