string.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * This string-include defines all string functions as inline
  3. * functions. Use gcc. It also assumes ds=es=data space, this should be
  4. * normal. Most of the string-functions are rather heavily hand-optimized,
  5. * see especially strtok,strstr,str[c]spn. They should work, but are not
  6. * very easy to understand. Everything is done entirely within the register
  7. * set, making the functions fast and clean. String instructions have been
  8. * used through-out, making for "slightly" unclear code :-)
  9. *
  10. * NO Copyright (C) 1991, 1992 Linus Torvalds,
  11. * consider these trivial functions to be PD.
  12. *
  13. * Modified for uClibc by Erik Andersen <andersen@codepoet.org>
  14. * These make no attempt to use nifty things like mmx/3dnow/etc.
  15. * These are not inline, and will therefore not be as fast as
  16. * modifying the headers to use inlines (and cannot therefore
  17. * do tricky things when dealing with const memory). But they
  18. * should (I hope!) be faster than their generic equivalents....
  19. *
  20. * More importantly, these should provide a good example for
  21. * others to follow when adding arch specific optimizations.
  22. * -Erik
  23. */
  24. #define _STDIO_UTILITY
  25. #define _GNU_SOURCE
  26. #include <string.h>
  27. #include <locale.h> /* for __LOCALE_C_ONLY */
  28. #ifdef L_strcpy
  29. char * strcpy(char * dest, const char * src)
  30. {
  31. int d0, d1, d2;
  32. __asm__ __volatile__(
  33. "1:\tlodsb\n\t"
  34. "stosb\n\t"
  35. "testb %%al,%%al\n\t"
  36. "jne 1b"
  37. : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  38. :"0" (src),"1" (dest) : "memory");
  39. return dest;
  40. }
  41. #endif
  42. #ifdef L_strncpy
  43. char * strncpy(char * dest, const char * src, size_t count)
  44. {
  45. int d0, d1, d2, d3;
  46. __asm__ __volatile__(
  47. "incl %2\n"
  48. "1:\n"
  49. "decl %2\n"
  50. "jz 2f\n"
  51. "lodsb\n\t"
  52. "stosb\n\t"
  53. "testb %%al,%%al\n\t"
  54. "jne 1b\n\t"
  55. "decl %2\n"
  56. "rep\n\t"
  57. "stosb\n"
  58. "2:"
  59. : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
  60. :"0" (src),"1" (dest),"2" (count) : "memory");
  61. return dest;
  62. }
  63. #endif
  64. #ifdef L_strcat
  65. char *strcat(char * dest, const char * src)
  66. {
  67. int d0, d1, d2, d3;
  68. __asm__ __volatile__(
  69. "repne\n\t"
  70. "scasb\n\t"
  71. "decl %1\n"
  72. "1:\tlodsb\n\t"
  73. "stosb\n\t"
  74. "testb %%al,%%al\n\t"
  75. "jne 1b"
  76. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  77. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
  78. return dest;
  79. }
  80. #endif
  81. #ifdef L_strncat
  82. char *strncat(char * dest,
  83. const char * src, size_t count)
  84. {
  85. int d0, d1, d2, d3;
  86. __asm__ __volatile__(
  87. "repne\n\t"
  88. "scasb\n\t"
  89. "decl %1\n\t"
  90. "movl %8,%3\n"
  91. "incl %3\n"
  92. "1:\tdecl %3\n\t"
  93. "jz 2f\n"
  94. "lodsb\n\t"
  95. "stosb\n\t"
  96. "testb %%al,%%al\n\t"
  97. "jne 1b\n"
  98. "jmp 3f\n"
  99. "2:\txorl %2,%2\n\t"
  100. "stosb\n"
  101. "3:"
  102. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  103. : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
  104. : "memory");
  105. return dest;
  106. }
  107. #endif
  108. #ifdef L_strcmp
  109. int strcmp(const char *cs, const char *ct)
  110. {
  111. int d0, d1;
  112. register int __res;
  113. __asm__ __volatile__(
  114. "1:\tlodsb\n\t"
  115. "scasb\n\t"
  116. "jne 2f\n\t"
  117. "testb %%al,%%al\n\t"
  118. "jne 1b\n\t"
  119. "xorl %%eax,%%eax\n\t"
  120. "jmp 3f\n"
  121. "2:\tsbbl %%eax,%%eax\n\t"
  122. "orb $1,%%al\n"
  123. "3:"
  124. :"=a" (__res), "=&S" (d0), "=&D" (d1)
  125. :"1" (cs),"2" (ct));
  126. return __res;
  127. }
  128. #ifdef __LOCALE_C_ONLY
  129. weak_alias(strcmp,strcoll);
  130. #endif /* __LOCALE_C_ONLY */
  131. #endif
  132. #ifdef L_strncmp
  133. int strncmp(const char *cs, const char *ct, size_t count)
  134. {
  135. register int __res;
  136. int d0, d1, d2;
  137. __asm__ __volatile__(
  138. "incl %3\n"
  139. "1:\tdecl %3\n\t"
  140. "jz 2f\n"
  141. "lodsb\n\t"
  142. "scasb\n\t"
  143. "jne 3f\n\t"
  144. "testb %%al,%%al\n\t"
  145. "jne 1b\n"
  146. "2:\txorl %%eax,%%eax\n\t"
  147. "jmp 4f\n"
  148. "3:\tsbbl %%eax,%%eax\n\t"
  149. "orb $1,%%al\n"
  150. "4:"
  151. :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
  152. :"1" (cs),"2" (ct),"3" (count));
  153. return __res;
  154. }
  155. #endif
  156. #ifdef L_strchr
  157. char * strchr(const char *s, int c)
  158. {
  159. int d0;
  160. register char * __res;
  161. __asm__ __volatile__(
  162. "movb %%al,%%ah\n"
  163. "1:\tlodsb\n\t"
  164. "cmpb %%ah,%%al\n\t"
  165. "je 2f\n\t"
  166. "testb %%al,%%al\n\t"
  167. "jne 1b\n\t"
  168. "movl $1,%1\n"
  169. "2:\tmovl %1,%0\n\t"
  170. "decl %0"
  171. :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
  172. return __res;
  173. }
  174. weak_alias(strchr,index);
  175. #endif
  176. #ifdef L_strrchr
  177. char *strrchr(const char *s, int c)
  178. {
  179. int d0, d1;
  180. register char * __res;
  181. __asm__ __volatile__(
  182. "movb %%al,%%ah\n"
  183. "1:\tlodsb\n\t"
  184. "cmpb %%ah,%%al\n\t"
  185. "jne 2f\n\t"
  186. "leal -1(%%esi),%0\n"
  187. "2:\ttestb %%al,%%al\n\t"
  188. "jne 1b"
  189. :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
  190. return __res;
  191. }
  192. weak_alias(strrchr,rindex);
  193. #endif
  194. #ifdef L_strlen
  195. size_t strlen(const char *s)
  196. {
  197. int d0;
  198. register int __res;
  199. __asm__ __volatile__(
  200. "repne\n\t"
  201. "scasb\n\t"
  202. "notl %0\n\t"
  203. "decl %0"
  204. :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
  205. return __res;
  206. }
  207. #endif
  208. #ifdef L_strnlen
  209. size_t strnlen(const char *s, size_t count)
  210. {
  211. int d0;
  212. register int __res;
  213. __asm__ __volatile__(
  214. "movl %2,%0\n\t"
  215. "incl %1\n"
  216. "jmp 2f\n"
  217. "1:\tcmpb $0,(%0)\n\t"
  218. "je 3f\n\t"
  219. "incl %0\n"
  220. "2:\tdecl %1\n\t"
  221. "jne 1b\n"
  222. "3:\tsubl %2,%0"
  223. :"=a" (__res), "=&d" (d0)
  224. :"c" (s),"1" (count));
  225. return __res;
  226. }
  227. #endif
  228. #ifdef L_memcpy
  229. void *memcpy(void * to, const void * from, size_t n)
  230. {
  231. int d0, d1, d2;
  232. __asm__ __volatile__(
  233. "rep ; movsl\n\t"
  234. "testb $2,%b4\n\t"
  235. "je 1f\n\t"
  236. "movsw\n"
  237. "1:\ttestb $1,%b4\n\t"
  238. "je 2f\n\t"
  239. "movsb\n"
  240. "2:"
  241. : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  242. :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
  243. : "memory");
  244. return (to);
  245. }
  246. #endif
  247. #ifdef L_memmove
  248. void *memmove(void *dest, const void *src, size_t n)
  249. {
  250. int d0, d1, d2;
  251. if (dest<src)
  252. __asm__ __volatile__(
  253. "rep\n\t"
  254. "movsb"
  255. : "=&c" (d0), "=&S" (d1), "=&D" (d2)
  256. :"0" (n),"1" (src),"2" (dest)
  257. : "memory");
  258. else
  259. __asm__ __volatile__(
  260. "std\n\t"
  261. "rep\n\t"
  262. "movsb\n\t"
  263. "cld"
  264. : "=&c" (d0), "=&S" (d1), "=&D" (d2)
  265. :"0" (n),
  266. "1" (n-1+(const char *)src),
  267. "2" (n-1+(char *)dest)
  268. :"memory");
  269. return dest;
  270. }
  271. #endif
  272. #ifdef L_memchr
  273. void *memchr(const void *cs, int c, size_t count)
  274. {
  275. int d0;
  276. register void * __res;
  277. if (!count)
  278. return NULL;
  279. __asm__ __volatile__(
  280. "repne\n\t"
  281. "scasb\n\t"
  282. "je 1f\n\t"
  283. "movl $1,%0\n"
  284. "1:\tdecl %0"
  285. :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
  286. return __res;
  287. }
  288. #endif
  289. #ifdef L_memset
  290. void *memset(void *s, int c, size_t count)
  291. {
  292. int d0, d1;
  293. __asm__ __volatile__(
  294. "rep\n\t"
  295. "stosb"
  296. : "=&c" (d0), "=&D" (d1)
  297. :"a" (c),"1" (s),"0" (count)
  298. :"memory");
  299. return s;
  300. }
  301. #endif