string.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #ifndef _M68K_STRING_H_
  2. #define _M68K_STRING_H_
  3. #include <asm/setup.h>
  4. #include <asm/page.h>
  5. #define __HAVE_ARCH_STRCPY
  6. static inline char * strcpy(char * dest,const char *src)
  7. {
  8. char *xdest = dest;
  9. __asm__ __volatile__
  10. ("1:\tmoveb %1@+,%0@+\n\t"
  11. "jne 1b"
  12. : "=a" (dest), "=a" (src)
  13. : "0" (dest), "1" (src) : "memory");
  14. return xdest;
  15. }
  16. #define __HAVE_ARCH_STRNCPY
  17. static inline char * strncpy(char *dest, const char *src, size_t n)
  18. {
  19. char *xdest = dest;
  20. if (n == 0)
  21. return xdest;
  22. __asm__ __volatile__
  23. ("1:\tmoveb %1@+,%0@+\n\t"
  24. "jeq 2f\n\t"
  25. "subql #1,%2\n\t"
  26. "jne 1b\n\t"
  27. "2:"
  28. : "=a" (dest), "=a" (src), "=d" (n)
  29. : "0" (dest), "1" (src), "2" (n)
  30. : "memory");
  31. return xdest;
  32. }
  33. #define __HAVE_ARCH_STRCAT
  34. static inline char * strcat(char * dest, const char * src)
  35. {
  36. char *tmp = dest;
  37. while (*dest)
  38. dest++;
  39. while ((*dest++ = *src++))
  40. ;
  41. return tmp;
  42. }
  43. #define __HAVE_ARCH_STRNCAT
  44. static inline char * strncat(char *dest, const char *src, size_t count)
  45. {
  46. char *tmp = dest;
  47. if (count) {
  48. while (*dest)
  49. dest++;
  50. while ((*dest++ = *src++)) {
  51. if (--count == 0) {
  52. *dest++='\0';
  53. break;
  54. }
  55. }
  56. }
  57. return tmp;
  58. }
  59. #define __HAVE_ARCH_STRCHR
  60. static inline char * strchr(const char * s, int c)
  61. {
  62. const char ch = c;
  63. for(; *s != ch; ++s)
  64. if (*s == '\0')
  65. return( NULL );
  66. return( (char *) s);
  67. }
  68. #if 0
  69. #define __HAVE_ARCH_STRPBRK
  70. static inline char *strpbrk(const char *cs,const char *ct)
  71. {
  72. const char *sc1,*sc2;
  73. for( sc1 = cs; *sc1 != '\0'; ++sc1)
  74. for( sc2 = ct; *sc2 != '\0'; ++sc2)
  75. if (*sc1 == *sc2)
  76. return((char *) sc1);
  77. return( NULL );
  78. }
  79. #endif
  80. #if 0
  81. #define __HAVE_ARCH_STRSPN
  82. static inline size_t strspn(const char *s, const char *accept)
  83. {
  84. const char *p;
  85. const char *a;
  86. size_t count = 0;
  87. for (p = s; *p != '\0'; ++p)
  88. {
  89. for (a = accept; *a != '\0'; ++a)
  90. if (*p == *a)
  91. break;
  92. if (*a == '\0')
  93. return count;
  94. else
  95. ++count;
  96. }
  97. return count;
  98. }
  99. #endif
  100. /* strstr !! */
  101. #define __HAVE_ARCH_STRLEN
  102. static inline size_t strlen(const char * s)
  103. {
  104. const char *sc;
  105. for (sc = s; *sc != '\0'; ++sc) ;
  106. return(sc - s);
  107. }
  108. /* strnlen !! */
  109. #define __HAVE_ARCH_STRCMP
  110. static inline int strcmp(const char * cs,const char * ct)
  111. {
  112. char __res;
  113. __asm__
  114. ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
  115. "cmpb %1@+,%2\n\t" /* compare a byte */
  116. "jne 2f\n\t" /* not equal, break out */
  117. "tstb %2\n\t" /* at end of cs? */
  118. "jne 1b\n\t" /* no, keep going */
  119. "jra 3f\n\t" /* strings are equal */
  120. "2:\tsubb %1@-,%2\n\t" /* *cs - *ct */
  121. "3:"
  122. : "=a" (cs), "=a" (ct), "=d" (__res)
  123. : "0" (cs), "1" (ct));
  124. return __res;
  125. }
  126. #define __HAVE_ARCH_STRNCMP
  127. static inline int strncmp(const char * cs,const char * ct,size_t count)
  128. {
  129. char __res;
  130. if (!count)
  131. return 0;
  132. __asm__
  133. ("1:\tmovb %0@+,%3\n\t" /* get *cs */
  134. "cmpb %1@+,%3\n\t" /* compare a byte */
  135. "jne 3f\n\t" /* not equal, break out */
  136. "tstb %3\n\t" /* at end of cs? */
  137. "jeq 4f\n\t" /* yes, all done */
  138. "subql #1,%2\n\t" /* no, adjust count */
  139. "jne 1b\n\t" /* more to do, keep going */
  140. "2:\tmoveq #0,%3\n\t" /* strings are equal */
  141. "jra 4f\n\t"
  142. "3:\tsubb %1@-,%3\n\t" /* *cs - *ct */
  143. "4:"
  144. : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
  145. : "0" (cs), "1" (ct), "2" (count));
  146. return __res;
  147. }
  148. #define __HAVE_ARCH_MEMSET
  149. /*
  150. * This is really ugly, but its highly optimizatiable by the
  151. * compiler and is meant as compensation for gcc's missing
  152. * __builtin_memset(). For the 680[23]0 it might be worth considering
  153. * the optimal number of misaligned writes compared to the number of
  154. * tests'n'branches needed to align the destination address. The
  155. * 680[46]0 doesn't really care due to their copy-back caches.
  156. * 10/09/96 - Jes Sorensen
  157. */
  158. static inline void * __memset_g(void * s, int c, size_t count)
  159. {
  160. void *xs = s;
  161. size_t temp;
  162. if (!count)
  163. return xs;
  164. c &= 0xff;
  165. c |= c << 8;
  166. c |= c << 16;
  167. if (count < 36){
  168. long *ls = s;
  169. switch(count){
  170. case 32: case 33: case 34: case 35:
  171. *ls++ = c;
  172. case 28: case 29: case 30: case 31:
  173. *ls++ = c;
  174. case 24: case 25: case 26: case 27:
  175. *ls++ = c;
  176. case 20: case 21: case 22: case 23:
  177. *ls++ = c;
  178. case 16: case 17: case 18: case 19:
  179. *ls++ = c;
  180. case 12: case 13: case 14: case 15:
  181. *ls++ = c;
  182. case 8: case 9: case 10: case 11:
  183. *ls++ = c;
  184. case 4: case 5: case 6: case 7:
  185. *ls++ = c;
  186. break;
  187. default:
  188. break;
  189. }
  190. s = ls;
  191. if (count & 0x02){
  192. short *ss = s;
  193. *ss++ = c;
  194. s = ss;
  195. }
  196. if (count & 0x01){
  197. char *cs = s;
  198. *cs++ = c;
  199. s = cs;
  200. }
  201. return xs;
  202. }
  203. if ((long) s & 1)
  204. {
  205. char *cs = s;
  206. *cs++ = c;
  207. s = cs;
  208. count--;
  209. }
  210. if (count > 2 && (long) s & 2)
  211. {
  212. short *ss = s;
  213. *ss++ = c;
  214. s = ss;
  215. count -= 2;
  216. }
  217. temp = count >> 2;
  218. if (temp)
  219. {
  220. long *ls = s;
  221. temp--;
  222. do
  223. *ls++ = c;
  224. while (temp--);
  225. s = ls;
  226. }
  227. if (count & 2)
  228. {
  229. short *ss = s;
  230. *ss++ = c;
  231. s = ss;
  232. }
  233. if (count & 1)
  234. {
  235. char *cs = s;
  236. *cs = c;
  237. }
  238. return xs;
  239. }
  240. /*
  241. * __memset_page assumes that data is longword aligned. Most, if not
  242. * all, of these page sized memsets are performed on page aligned
  243. * areas, thus we do not need to check if the destination is longword
  244. * aligned. Of course we suffer a serious performance loss if this is
  245. * not the case but I think the risk of this ever happening is
  246. * extremely small. We spend a lot of time clearing pages in
  247. * get_empty_page() so I think it is worth it anyway. Besides, the
  248. * 680[46]0 do not really care about misaligned writes due to their
  249. * copy-back cache.
  250. *
  251. * The optimized case for the 680[46]0 is implemented using the move16
  252. * instruction. My tests showed that this implementation is 35-45%
  253. * faster than the original implementation using movel, the only
  254. * caveat is that the destination address must be 16-byte aligned.
  255. * 01/09/96 - Jes Sorensen
  256. */
  257. static inline void * __memset_page(void * s,int c,size_t count)
  258. {
  259. unsigned long data, tmp;
  260. void *xs = s;
  261. c = c & 255;
  262. data = c | (c << 8);
  263. data |= data << 16;
  264. #ifdef CPU_M68040_OR_M68060_ONLY
  265. if (((unsigned long) s) & 0x0f)
  266. __memset_g(s, c, count);
  267. else{
  268. unsigned long *sp = s;
  269. *sp++ = data;
  270. *sp++ = data;
  271. *sp++ = data;
  272. *sp++ = data;
  273. __asm__ __volatile__("1:\t"
  274. ".chip 68040\n\t"
  275. "move16 %2@+,%0@+\n\t"
  276. ".chip 68k\n\t"
  277. "subqw #8,%2\n\t"
  278. "subqw #8,%2\n\t"
  279. "dbra %1,1b\n\t"
  280. : "=a" (sp), "=d" (tmp)
  281. : "a" (s), "0" (sp), "1" ((count - 16) / 16 - 1)
  282. );
  283. }
  284. #else
  285. __asm__ __volatile__("1:\t"
  286. "movel %2,%0@+\n\t"
  287. "movel %2,%0@+\n\t"
  288. "movel %2,%0@+\n\t"
  289. "movel %2,%0@+\n\t"
  290. "movel %2,%0@+\n\t"
  291. "movel %2,%0@+\n\t"
  292. "movel %2,%0@+\n\t"
  293. "movel %2,%0@+\n\t"
  294. "dbra %1,1b\n\t"
  295. : "=a" (s), "=d" (tmp)
  296. : "d" (data), "0" (s), "1" (count / 32 - 1)
  297. );
  298. #endif
  299. return xs;
  300. }
  301. extern void *memset(void *,int,__kernel_size_t);
  302. #define __memset_const(s,c,count) \
  303. ((count==PAGE_SIZE) ? \
  304. __memset_page((s),(c),(count)) : \
  305. __memset_g((s),(c),(count)))
  306. #define memset(s, c, count) \
  307. (__builtin_constant_p(count) ? \
  308. __memset_const((s),(c),(count)) : \
  309. __memset_g((s),(c),(count)))
  310. #define __HAVE_ARCH_MEMCPY
  311. extern void * memcpy(void *, const void *, size_t );
  312. /*
  313. * __builtin_memcpy() does not handle page-sized memcpys very well,
  314. * thus following the same assumptions as for page-sized memsets, this
  315. * function copies page-sized areas using an unrolled loop, without
  316. * considering alignment.
  317. *
  318. * For the 680[46]0 only kernels we use the move16 instruction instead
  319. * as it writes through the data-cache, invalidating the cache-lines
  320. * touched. In this way we do not use up the entire data-cache (well,
  321. * half of it on the 68060) by copying a page. An unrolled loop of two
  322. * move16 instructions seem to the fastest. The only caveat is that
  323. * both source and destination must be 16-byte aligned, if not we fall
  324. * back to the generic memcpy function. - Jes
  325. */
  326. static inline void * __memcpy_page(void * to, const void * from, size_t count)
  327. {
  328. unsigned long tmp;
  329. void *xto = to;
  330. #ifdef CPU_M68040_OR_M68060_ONLY
  331. if (((unsigned long) to | (unsigned long) from) & 0x0f)
  332. return memcpy(to, from, count);
  333. __asm__ __volatile__("1:\t"
  334. ".chip 68040\n\t"
  335. "move16 %1@+,%0@+\n\t"
  336. "move16 %1@+,%0@+\n\t"
  337. ".chip 68k\n\t"
  338. "dbra %2,1b\n\t"
  339. : "=a" (to), "=a" (from), "=d" (tmp)
  340. : "0" (to), "1" (from) , "2" (count / 32 - 1)
  341. );
  342. #else
  343. __asm__ __volatile__("1:\t"
  344. "movel %1@+,%0@+\n\t"
  345. "movel %1@+,%0@+\n\t"
  346. "movel %1@+,%0@+\n\t"
  347. "movel %1@+,%0@+\n\t"
  348. "movel %1@+,%0@+\n\t"
  349. "movel %1@+,%0@+\n\t"
  350. "movel %1@+,%0@+\n\t"
  351. "movel %1@+,%0@+\n\t"
  352. "dbra %2,1b\n\t"
  353. : "=a" (to), "=a" (from), "=d" (tmp)
  354. : "0" (to), "1" (from) , "2" (count / 32 - 1)
  355. );
  356. #endif
  357. return xto;
  358. }
  359. #define __memcpy_const(to, from, n) \
  360. ((n==PAGE_SIZE) ? \
  361. __memcpy_page((to),(from),(n)) : \
  362. __builtin_memcpy((to),(from),(n)))
  363. #define memcpy(to, from, n) \
  364. (__builtin_constant_p(n) ? \
  365. __memcpy_const((to),(from),(n)) : \
  366. memcpy((to),(from),(n)))
  367. #define __HAVE_ARCH_MEMMOVE
  368. static inline void * memmove(void * dest,const void * src, size_t n)
  369. {
  370. void *xdest = dest;
  371. size_t temp;
  372. if (!n)
  373. return xdest;
  374. if (dest < src)
  375. {
  376. if ((long) dest & 1)
  377. {
  378. char *cdest = dest;
  379. const char *csrc = src;
  380. *cdest++ = *csrc++;
  381. dest = cdest;
  382. src = csrc;
  383. n--;
  384. }
  385. if (n > 2 && (long) dest & 2)
  386. {
  387. short *sdest = dest;
  388. const short *ssrc = src;
  389. *sdest++ = *ssrc++;
  390. dest = sdest;
  391. src = ssrc;
  392. n -= 2;
  393. }
  394. temp = n >> 2;
  395. if (temp)
  396. {
  397. long *ldest = dest;
  398. const long *lsrc = src;
  399. temp--;
  400. do
  401. *ldest++ = *lsrc++;
  402. while (temp--);
  403. dest = ldest;
  404. src = lsrc;
  405. }
  406. if (n & 2)
  407. {
  408. short *sdest = dest;
  409. const short *ssrc = src;
  410. *sdest++ = *ssrc++;
  411. dest = sdest;
  412. src = ssrc;
  413. }
  414. if (n & 1)
  415. {
  416. char *cdest = dest;
  417. const char *csrc = src;
  418. *cdest = *csrc;
  419. }
  420. }
  421. else
  422. {
  423. dest = (char *) dest + n;
  424. src = (const char *) src + n;
  425. if ((long) dest & 1)
  426. {
  427. char *cdest = dest;
  428. const char *csrc = src;
  429. *--cdest = *--csrc;
  430. dest = cdest;
  431. src = csrc;
  432. n--;
  433. }
  434. if (n > 2 && (long) dest & 2)
  435. {
  436. short *sdest = dest;
  437. const short *ssrc = src;
  438. *--sdest = *--ssrc;
  439. dest = sdest;
  440. src = ssrc;
  441. n -= 2;
  442. }
  443. temp = n >> 2;
  444. if (temp)
  445. {
  446. long *ldest = dest;
  447. const long *lsrc = src;
  448. temp--;
  449. do
  450. *--ldest = *--lsrc;
  451. while (temp--);
  452. dest = ldest;
  453. src = lsrc;
  454. }
  455. if (n & 2)
  456. {
  457. short *sdest = dest;
  458. const short *ssrc = src;
  459. *--sdest = *--ssrc;
  460. dest = sdest;
  461. src = ssrc;
  462. }
  463. if (n & 1)
  464. {
  465. char *cdest = dest;
  466. const char *csrc = src;
  467. *--cdest = *--csrc;
  468. }
  469. }
  470. return xdest;
  471. }
  472. #define __HAVE_ARCH_MEMCMP
  473. extern int memcmp(const void * ,const void * ,size_t );
  474. #define memcmp(cs, ct, n) \
  475. (__builtin_constant_p(n) ? \
  476. __builtin_memcmp((cs),(ct),(n)) : \
  477. memcmp((cs),(ct),(n)))
  478. #define __HAVE_ARCH_MEMCHR
  479. static inline void *memchr(const void *cs, int c, size_t count)
  480. {
  481. /* Someone else can optimize this, I don't care - tonym@mac.linux-m68k.org */
  482. unsigned char *ret = (unsigned char *)cs;
  483. for(;count>0;count--,ret++)
  484. if(*ret == c) return ret;
  485. return NULL;
  486. }
  487. #endif /* _M68K_STRING_H_ */