string_32.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Most of the string-functions are rather heavily hand-optimized,
  4. * see especially strsep,strstr,str[c]spn. They should work, but are not
  5. * very easy to understand. Everything is done entirely within the register
  6. * set, making the functions fast and clean. String instructions have been
  7. * used through-out, making for "slightly" unclear code :-)
  8. *
  9. * AK: On P4 and K7 using non string instruction implementations might be faster
  10. * for large memory blocks. But most of them are unlikely to be used on large
  11. * strings.
  12. */
  13. #include <linux/string.h>
  14. #include <linux/export.h>
  15. #ifdef __HAVE_ARCH_STRCPY
  16. char *strcpy(char *dest, const char *src)
  17. {
  18. int d0, d1, d2;
  19. asm volatile("1:\tlodsb\n\t"
  20. "stosb\n\t"
  21. "testb %%al,%%al\n\t"
  22. "jne 1b"
  23. : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  24. : "0" (src), "1" (dest) : "memory");
  25. return dest;
  26. }
  27. EXPORT_SYMBOL(strcpy);
  28. #endif
  29. #ifdef __HAVE_ARCH_STRNCPY
  30. char *strncpy(char *dest, const char *src, size_t count)
  31. {
  32. int d0, d1, d2, d3;
  33. asm volatile("1:\tdecl %2\n\t"
  34. "js 2f\n\t"
  35. "lodsb\n\t"
  36. "stosb\n\t"
  37. "testb %%al,%%al\n\t"
  38. "jne 1b\n\t"
  39. "rep\n\t"
  40. "stosb\n"
  41. "2:"
  42. : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
  43. : "0" (src), "1" (dest), "2" (count) : "memory");
  44. return dest;
  45. }
  46. EXPORT_SYMBOL(strncpy);
  47. #endif
  48. #ifdef __HAVE_ARCH_STRCAT
  49. char *strcat(char *dest, const char *src)
  50. {
  51. int d0, d1, d2, d3;
  52. asm volatile("repne\n\t"
  53. "scasb\n\t"
  54. "decl %1\n"
  55. "1:\tlodsb\n\t"
  56. "stosb\n\t"
  57. "testb %%al,%%al\n\t"
  58. "jne 1b"
  59. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  60. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory");
  61. return dest;
  62. }
  63. EXPORT_SYMBOL(strcat);
  64. #endif
  65. #ifdef __HAVE_ARCH_STRNCAT
  66. char *strncat(char *dest, const char *src, size_t count)
  67. {
  68. int d0, d1, d2, d3;
  69. asm volatile("repne\n\t"
  70. "scasb\n\t"
  71. "decl %1\n\t"
  72. "movl %8,%3\n"
  73. "1:\tdecl %3\n\t"
  74. "js 2f\n\t"
  75. "lodsb\n\t"
  76. "stosb\n\t"
  77. "testb %%al,%%al\n\t"
  78. "jne 1b\n"
  79. "2:\txorl %2,%2\n\t"
  80. "stosb"
  81. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  82. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
  83. : "memory");
  84. return dest;
  85. }
  86. EXPORT_SYMBOL(strncat);
  87. #endif
  88. #ifdef __HAVE_ARCH_STRCMP
  89. int strcmp(const char *cs, const char *ct)
  90. {
  91. int d0, d1;
  92. int res;
  93. asm volatile("1:\tlodsb\n\t"
  94. "scasb\n\t"
  95. "jne 2f\n\t"
  96. "testb %%al,%%al\n\t"
  97. "jne 1b\n\t"
  98. "xorl %%eax,%%eax\n\t"
  99. "jmp 3f\n"
  100. "2:\tsbbl %%eax,%%eax\n\t"
  101. "orb $1,%%al\n"
  102. "3:"
  103. : "=a" (res), "=&S" (d0), "=&D" (d1)
  104. : "1" (cs), "2" (ct)
  105. : "memory");
  106. return res;
  107. }
  108. EXPORT_SYMBOL(strcmp);
  109. #endif
  110. #ifdef __HAVE_ARCH_STRNCMP
  111. int strncmp(const char *cs, const char *ct, size_t count)
  112. {
  113. int res;
  114. int d0, d1, d2;
  115. asm volatile("1:\tdecl %3\n\t"
  116. "js 2f\n\t"
  117. "lodsb\n\t"
  118. "scasb\n\t"
  119. "jne 3f\n\t"
  120. "testb %%al,%%al\n\t"
  121. "jne 1b\n"
  122. "2:\txorl %%eax,%%eax\n\t"
  123. "jmp 4f\n"
  124. "3:\tsbbl %%eax,%%eax\n\t"
  125. "orb $1,%%al\n"
  126. "4:"
  127. : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
  128. : "1" (cs), "2" (ct), "3" (count)
  129. : "memory");
  130. return res;
  131. }
  132. EXPORT_SYMBOL(strncmp);
  133. #endif
  134. #ifdef __HAVE_ARCH_STRCHR
  135. char *strchr(const char *s, int c)
  136. {
  137. int d0;
  138. char *res;
  139. asm volatile("movb %%al,%%ah\n"
  140. "1:\tlodsb\n\t"
  141. "cmpb %%ah,%%al\n\t"
  142. "je 2f\n\t"
  143. "testb %%al,%%al\n\t"
  144. "jne 1b\n\t"
  145. "movl $1,%1\n"
  146. "2:\tmovl %1,%0\n\t"
  147. "decl %0"
  148. : "=a" (res), "=&S" (d0)
  149. : "1" (s), "0" (c)
  150. : "memory");
  151. return res;
  152. }
  153. EXPORT_SYMBOL(strchr);
  154. #endif
  155. #ifdef __HAVE_ARCH_STRLEN
  156. size_t strlen(const char *s)
  157. {
  158. int d0;
  159. size_t res;
  160. asm volatile("repne\n\t"
  161. "scasb"
  162. : "=c" (res), "=&D" (d0)
  163. : "1" (s), "a" (0), "0" (0xffffffffu)
  164. : "memory");
  165. return ~res - 1;
  166. }
  167. EXPORT_SYMBOL(strlen);
  168. #endif
  169. #ifdef __HAVE_ARCH_MEMCHR
  170. void *memchr(const void *cs, int c, size_t count)
  171. {
  172. int d0;
  173. void *res;
  174. if (!count)
  175. return NULL;
  176. asm volatile("repne\n\t"
  177. "scasb\n\t"
  178. "je 1f\n\t"
  179. "movl $1,%0\n"
  180. "1:\tdecl %0"
  181. : "=D" (res), "=&c" (d0)
  182. : "a" (c), "0" (cs), "1" (count)
  183. : "memory");
  184. return res;
  185. }
  186. EXPORT_SYMBOL(memchr);
  187. #endif
  188. #ifdef __HAVE_ARCH_MEMSCAN
  189. void *memscan(void *addr, int c, size_t size)
  190. {
  191. if (!size)
  192. return addr;
  193. asm volatile("repnz; scasb\n\t"
  194. "jnz 1f\n\t"
  195. "dec %%edi\n"
  196. "1:"
  197. : "=D" (addr), "=c" (size)
  198. : "0" (addr), "1" (size), "a" (c)
  199. : "memory");
  200. return addr;
  201. }
  202. EXPORT_SYMBOL(memscan);
  203. #endif
  204. #ifdef __HAVE_ARCH_STRNLEN
  205. size_t strnlen(const char *s, size_t count)
  206. {
  207. int d0;
  208. int res;
  209. asm volatile("movl %2,%0\n\t"
  210. "jmp 2f\n"
  211. "1:\tcmpb $0,(%0)\n\t"
  212. "je 3f\n\t"
  213. "incl %0\n"
  214. "2:\tdecl %1\n\t"
  215. "cmpl $-1,%1\n\t"
  216. "jne 1b\n"
  217. "3:\tsubl %2,%0"
  218. : "=a" (res), "=&d" (d0)
  219. : "c" (s), "1" (count)
  220. : "memory");
  221. return res;
  222. }
  223. EXPORT_SYMBOL(strnlen);
  224. #endif