string.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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 _GNU_SOURCE
  25. #include <string.h>
  26. #include <locale.h> /* for __LOCALE_C_ONLY */
  27. #ifdef L_strcpy
  28. char * strcpy(char * dest, const char * src)
  29. {
  30. int d0, d1, d2;
  31. __asm__ __volatile__(
  32. "1:\tlodsb\n\t"
  33. "stosb\n\t"
  34. "testb %%al,%%al\n\t"
  35. "jne 1b"
  36. : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  37. :"0" (src),"1" (dest) : "memory");
  38. return dest;
  39. }
  40. #endif
  41. #ifdef L_strncpy
  42. char * strncpy(char * dest, const char * src, size_t count)
  43. {
  44. int d0, d1, d2, d3;
  45. __asm__ __volatile__(
  46. "incl %2\n"
  47. "1:\n"
  48. "decl %2\n"
  49. "jz 2f\n"
  50. "lodsb\n\t"
  51. "stosb\n\t"
  52. "testb %%al,%%al\n\t"
  53. "jne 1b\n\t"
  54. "decl %2\n"
  55. "rep\n\t"
  56. "stosb\n"
  57. "2:"
  58. : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
  59. :"0" (src),"1" (dest),"2" (count) : "memory");
  60. return dest;
  61. }
  62. #endif
  63. #ifdef L_strcat
  64. char *strcat(char * dest, const char * src)
  65. {
  66. int d0, d1, d2, d3;
  67. __asm__ __volatile__(
  68. "repne\n\t"
  69. "scasb\n\t"
  70. "decl %1\n"
  71. "1:\tlodsb\n\t"
  72. "stosb\n\t"
  73. "testb %%al,%%al\n\t"
  74. "jne 1b"
  75. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  76. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
  77. return dest;
  78. }
  79. #endif
  80. #ifdef L_strncat
  81. char *strncat(char * dest,
  82. const char * src, size_t count)
  83. {
  84. int d0, d1, d2, d3;
  85. __asm__ __volatile__(
  86. "repne\n\t"
  87. "scasb\n\t"
  88. "decl %1\n\t"
  89. "movl %8,%3\n"
  90. "incl %3\n"
  91. "1:\tdecl %3\n\t"
  92. "jz 2f\n"
  93. "lodsb\n\t"
  94. "stosb\n\t"
  95. "testb %%al,%%al\n\t"
  96. "jne 1b\n"
  97. "jmp 3f\n"
  98. "2:\txorl %2,%2\n\t"
  99. "stosb\n"
  100. "3:"
  101. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  102. : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
  103. : "memory");
  104. return dest;
  105. }
  106. #endif
  107. #ifdef L_strcmp
  108. int strcmp(const char *cs, const char *ct)
  109. {
  110. int d0, d1;
  111. register int __res;
  112. __asm__ __volatile__(
  113. "1:\tlodsb\n\t"
  114. "scasb\n\t"
  115. "jne 2f\n\t"
  116. "testb %%al,%%al\n\t"
  117. "jne 1b\n\t"
  118. "xorl %%eax,%%eax\n\t"
  119. "jmp 3f\n"
  120. "2:\tsbbl %%eax,%%eax\n\t"
  121. "orb $1,%%al\n"
  122. "3:"
  123. :"=a" (__res), "=&S" (d0), "=&D" (d1)
  124. :"1" (cs),"2" (ct));
  125. return __res;
  126. }
  127. #ifdef __LOCALE_C_ONLY
  128. weak_alias(strcmp,strcoll);
  129. #endif /* __LOCALE_C_ONLY */
  130. #endif
  131. #ifdef L_strncmp
  132. int strncmp(const char *cs, const char *ct, size_t count)
  133. {
  134. register int __res;
  135. int d0, d1, d2;
  136. __asm__ __volatile__(
  137. "incl %3\n"
  138. "1:\tdecl %3\n\t"
  139. "jz 2f\n"
  140. "lodsb\n\t"
  141. "scasb\n\t"
  142. "jne 3f\n\t"
  143. "testb %%al,%%al\n\t"
  144. "jne 1b\n"
  145. "2:\txorl %%eax,%%eax\n\t"
  146. "jmp 4f\n"
  147. "3:\tsbbl %%eax,%%eax\n\t"
  148. "orb $1,%%al\n"
  149. "4:"
  150. :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
  151. :"1" (cs),"2" (ct),"3" (count));
  152. return __res;
  153. }
  154. #endif
  155. #ifdef L_strchr
  156. char * strchr(const char *s, int c)
  157. {
  158. int d0;
  159. register char * __res;
  160. __asm__ __volatile__(
  161. "movb %%al,%%ah\n"
  162. "1:\tlodsb\n\t"
  163. "cmpb %%ah,%%al\n\t"
  164. "je 2f\n\t"
  165. "testb %%al,%%al\n\t"
  166. "jne 1b\n\t"
  167. "movl $1,%1\n"
  168. "2:\tmovl %1,%0\n\t"
  169. "decl %0"
  170. :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
  171. return __res;
  172. }
  173. weak_alias(strchr,index);
  174. #endif
  175. #ifdef L_strrchr
  176. char *strrchr(const char *s, int c)
  177. {
  178. int d0, d1;
  179. register char * __res;
  180. __asm__ __volatile__(
  181. "movb %%al,%%ah\n"
  182. "1:\tlodsb\n\t"
  183. "cmpb %%ah,%%al\n\t"
  184. "jne 2f\n\t"
  185. "leal -1(%%esi),%0\n"
  186. "2:\ttestb %%al,%%al\n\t"
  187. "jne 1b"
  188. :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
  189. return __res;
  190. }
  191. weak_alias(strrchr,rindex);
  192. #endif
  193. #ifdef L_strlen
  194. size_t strlen(const char *s)
  195. {
  196. int d0;
  197. register int __res;
  198. __asm__ __volatile__(
  199. "repne\n\t"
  200. "scasb\n\t"
  201. "notl %0\n\t"
  202. "decl %0"
  203. :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
  204. return __res;
  205. }
  206. #endif
  207. #ifdef L_strnlen
  208. size_t strnlen(const char *s, size_t count)
  209. {
  210. int d0;
  211. register int __res;
  212. __asm__ __volatile__(
  213. "movl %2,%0\n\t"
  214. "incl %1\n"
  215. "jmp 2f\n"
  216. "1:\tcmpb $0,(%0)\n\t"
  217. "je 3f\n\t"
  218. "incl %0\n"
  219. "2:\tdecl %1\n\t"
  220. "jne 1b\n"
  221. "3:\tsubl %2,%0"
  222. :"=a" (__res), "=&d" (d0)
  223. :"c" (s),"1" (count));
  224. return __res;
  225. }
  226. #endif
  227. #ifdef L_memcpy
  228. void *memcpy(void * to, const void * from, size_t n)
  229. {
  230. int d0, d1, d2;
  231. __asm__ __volatile__(
  232. "rep ; movsl\n\t"
  233. "testb $2,%b4\n\t"
  234. "je 1f\n\t"
  235. "movsw\n"
  236. "1:\ttestb $1,%b4\n\t"
  237. "je 2f\n\t"
  238. "movsb\n"
  239. "2:"
  240. : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  241. :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
  242. : "memory");
  243. return (to);
  244. }
  245. #endif
  246. #ifdef L_memmove
  247. void *memmove(void *dest, const void *src, size_t n)
  248. {
  249. int d0, d1, d2;
  250. if (dest<src)
  251. __asm__ __volatile__(
  252. "rep\n\t"
  253. "movsb"
  254. : "=&c" (d0), "=&S" (d1), "=&D" (d2)
  255. :"0" (n),"1" (src),"2" (dest)
  256. : "memory");
  257. else
  258. __asm__ __volatile__(
  259. "std\n\t"
  260. "rep\n\t"
  261. "movsb\n\t"
  262. "cld"
  263. : "=&c" (d0), "=&S" (d1), "=&D" (d2)
  264. :"0" (n),
  265. "1" (n-1+(const char *)src),
  266. "2" (n-1+(char *)dest)
  267. :"memory");
  268. return dest;
  269. }
  270. #endif
  271. #ifdef L_memchr
  272. void *memchr(const void *cs, int c, size_t count)
  273. {
  274. int d0;
  275. register void * __res;
  276. if (!count)
  277. return NULL;
  278. __asm__ __volatile__(
  279. "repne\n\t"
  280. "scasb\n\t"
  281. "je 1f\n\t"
  282. "movl $1,%0\n"
  283. "1:\tdecl %0"
  284. :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
  285. return __res;
  286. }
  287. #endif
  288. #ifdef L_memset
  289. void *memset(void *s, int c, size_t count)
  290. {
  291. int d0, d1;
  292. __asm__ __volatile__(
  293. "rep\n\t"
  294. "stosb"
  295. : "=&c" (d0), "=&D" (d1)
  296. :"a" (c),"1" (s),"0" (count)
  297. :"memory");
  298. return s;
  299. }
  300. #endif