string_32.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #define __NO_FORTIFY
  14. #include <linux/string.h>
  15. #include <linux/export.h>
  16. #ifdef __HAVE_ARCH_STRCPY
  17. char *strcpy(char *dest, const char *src)
  18. {
  19. int d0, d1, d2;
  20. asm volatile("1:\tlodsb\n\t"
  21. "stosb\n\t"
  22. "testb %%al,%%al\n\t"
  23. "jne 1b"
  24. : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  25. : "0" (src), "1" (dest) : "memory");
  26. return dest;
  27. }
  28. EXPORT_SYMBOL(strcpy);
  29. #endif
  30. #ifdef __HAVE_ARCH_STRNCPY
  31. char *strncpy(char *dest, const char *src, size_t count)
  32. {
  33. int d0, d1, d2, d3;
  34. asm volatile("1:\tdecl %2\n\t"
  35. "js 2f\n\t"
  36. "lodsb\n\t"
  37. "stosb\n\t"
  38. "testb %%al,%%al\n\t"
  39. "jne 1b\n\t"
  40. "rep\n\t"
  41. "stosb\n"
  42. "2:"
  43. : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
  44. : "0" (src), "1" (dest), "2" (count) : "memory");
  45. return dest;
  46. }
  47. EXPORT_SYMBOL(strncpy);
  48. #endif
  49. #ifdef __HAVE_ARCH_STRCAT
  50. char *strcat(char *dest, const char *src)
  51. {
  52. int d0, d1, d2, d3;
  53. asm volatile("repne\n\t"
  54. "scasb\n\t"
  55. "decl %1\n"
  56. "1:\tlodsb\n\t"
  57. "stosb\n\t"
  58. "testb %%al,%%al\n\t"
  59. "jne 1b"
  60. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  61. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory");
  62. return dest;
  63. }
  64. EXPORT_SYMBOL(strcat);
  65. #endif
  66. #ifdef __HAVE_ARCH_STRNCAT
  67. char *strncat(char *dest, const char *src, size_t count)
  68. {
  69. int d0, d1, d2, d3;
  70. asm volatile("repne\n\t"
  71. "scasb\n\t"
  72. "decl %1\n\t"
  73. "movl %8,%3\n"
  74. "1:\tdecl %3\n\t"
  75. "js 2f\n\t"
  76. "lodsb\n\t"
  77. "stosb\n\t"
  78. "testb %%al,%%al\n\t"
  79. "jne 1b\n"
  80. "2:\txorl %2,%2\n\t"
  81. "stosb"
  82. : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  83. : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
  84. : "memory");
  85. return dest;
  86. }
  87. EXPORT_SYMBOL(strncat);
  88. #endif
  89. #ifdef __HAVE_ARCH_STRCMP
  90. int strcmp(const char *cs, const char *ct)
  91. {
  92. int d0, d1;
  93. int res;
  94. asm volatile("1:\tlodsb\n\t"
  95. "scasb\n\t"
  96. "jne 2f\n\t"
  97. "testb %%al,%%al\n\t"
  98. "jne 1b\n\t"
  99. "xorl %%eax,%%eax\n\t"
  100. "jmp 3f\n"
  101. "2:\tsbbl %%eax,%%eax\n\t"
  102. "orb $1,%%al\n"
  103. "3:"
  104. : "=a" (res), "=&S" (d0), "=&D" (d1)
  105. : "1" (cs), "2" (ct)
  106. : "memory");
  107. return res;
  108. }
  109. EXPORT_SYMBOL(strcmp);
  110. #endif
  111. #ifdef __HAVE_ARCH_STRNCMP
  112. int strncmp(const char *cs, const char *ct, size_t count)
  113. {
  114. int res;
  115. int d0, d1, d2;
  116. asm volatile("1:\tdecl %3\n\t"
  117. "js 2f\n\t"
  118. "lodsb\n\t"
  119. "scasb\n\t"
  120. "jne 3f\n\t"
  121. "testb %%al,%%al\n\t"
  122. "jne 1b\n"
  123. "2:\txorl %%eax,%%eax\n\t"
  124. "jmp 4f\n"
  125. "3:\tsbbl %%eax,%%eax\n\t"
  126. "orb $1,%%al\n"
  127. "4:"
  128. : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
  129. : "1" (cs), "2" (ct), "3" (count)
  130. : "memory");
  131. return res;
  132. }
  133. EXPORT_SYMBOL(strncmp);
  134. #endif
  135. #ifdef __HAVE_ARCH_STRCHR
  136. char *strchr(const char *s, int c)
  137. {
  138. int d0;
  139. char *res;
  140. asm volatile("movb %%al,%%ah\n"
  141. "1:\tlodsb\n\t"
  142. "cmpb %%ah,%%al\n\t"
  143. "je 2f\n\t"
  144. "testb %%al,%%al\n\t"
  145. "jne 1b\n\t"
  146. "movl $1,%1\n"
  147. "2:\tmovl %1,%0\n\t"
  148. "decl %0"
  149. : "=a" (res), "=&S" (d0)
  150. : "1" (s), "0" (c)
  151. : "memory");
  152. return res;
  153. }
  154. EXPORT_SYMBOL(strchr);
  155. #endif
  156. #ifdef __HAVE_ARCH_STRLEN
  157. size_t strlen(const char *s)
  158. {
  159. int d0;
  160. size_t res;
  161. asm volatile("repne\n\t"
  162. "scasb"
  163. : "=c" (res), "=&D" (d0)
  164. : "1" (s), "a" (0), "0" (0xffffffffu)
  165. : "memory");
  166. return ~res - 1;
  167. }
  168. EXPORT_SYMBOL(strlen);
  169. #endif
  170. #ifdef __HAVE_ARCH_MEMCHR
  171. void *memchr(const void *cs, int c, size_t count)
  172. {
  173. int d0;
  174. void *res;
  175. if (!count)
  176. return NULL;
  177. asm volatile("repne\n\t"
  178. "scasb\n\t"
  179. "je 1f\n\t"
  180. "movl $1,%0\n"
  181. "1:\tdecl %0"
  182. : "=D" (res), "=&c" (d0)
  183. : "a" (c), "0" (cs), "1" (count)
  184. : "memory");
  185. return res;
  186. }
  187. EXPORT_SYMBOL(memchr);
  188. #endif
  189. #ifdef __HAVE_ARCH_MEMSCAN
  190. void *memscan(void *addr, int c, size_t size)
  191. {
  192. if (!size)
  193. return addr;
  194. asm volatile("repnz; scasb\n\t"
  195. "jnz 1f\n\t"
  196. "dec %%edi\n"
  197. "1:"
  198. : "=D" (addr), "=c" (size)
  199. : "0" (addr), "1" (size), "a" (c)
  200. : "memory");
  201. return addr;
  202. }
  203. EXPORT_SYMBOL(memscan);
  204. #endif
  205. #ifdef __HAVE_ARCH_STRNLEN
  206. size_t strnlen(const char *s, size_t count)
  207. {
  208. int d0;
  209. int res;
  210. asm volatile("movl %2,%0\n\t"
  211. "jmp 2f\n"
  212. "1:\tcmpb $0,(%0)\n\t"
  213. "je 3f\n\t"
  214. "incl %0\n"
  215. "2:\tdecl %1\n\t"
  216. "cmpl $-1,%1\n\t"
  217. "jne 1b\n"
  218. "3:\tsubl %2,%0"
  219. : "=a" (res), "=&d" (d0)
  220. : "c" (s), "1" (count)
  221. : "memory");
  222. return res;
  223. }
  224. EXPORT_SYMBOL(strnlen);
  225. #endif