string.c 6.7 KB

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