string.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * String handling functions for PowerPC.
  3.  *
  4.  * Copyright (C) 1996 Paul Mackerras.
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version
  9.  * 2 of the License, or (at your option) any later version.
  10.  */
  11. #include <asm/ppc_asm.tmpl>
  12. #include <asm/processor.h>
  13. #include <asm/errno.h>
  14. #define CACHE_LINE_SIZE 128
  15. #define LG_CACHE_LINE_SIZE 7
  16. #define MAX_COPY_PREFETCH 1
  17. #define COPY_16_BYTES
  18. lwz r7,4(r4);
  19. lwz r8,8(r4);
  20. lwz r9,12(r4);
  21. lwzu r10,16(r4);
  22. stw r7,4(r6);
  23. stw r8,8(r6);
  24. stw r9,12(r6);
  25. stwu r10,16(r6)
  26. #define COPY_16_BYTES_WITHEX(n)
  27. 8 ## n ## 0:
  28. lwz r7,4(r4);
  29. 8 ## n ## 1:
  30. lwz r8,8(r4);
  31. 8 ## n ## 2:
  32. lwz r9,12(r4);
  33. 8 ## n ## 3:
  34. lwzu r10,16(r4);
  35. 8 ## n ## 4:
  36. stw r7,4(r6);
  37. 8 ## n ## 5:
  38. stw r8,8(r6);
  39. 8 ## n ## 6:
  40. stw r9,12(r6);
  41. 8 ## n ## 7:
  42. stwu r10,16(r6)
  43. #define COPY_16_BYTES_EXCODE(n)
  44. 9 ## n ## 0:
  45. addi r5,r5,-(16 * n);
  46. b 104f;
  47. 9 ## n ## 1:
  48. addi r5,r5,-(16 * n);
  49. b 105f;
  50. .section __ex_table,"a";
  51. .align 3;
  52. .llong 8 ## n ## 0b,9 ## n ## 0b;
  53. .llong 8 ## n ## 1b,9 ## n ## 0b;
  54. .llong 8 ## n ## 2b,9 ## n ## 0b;
  55. .llong 8 ## n ## 3b,9 ## n ## 0b;
  56. .llong 8 ## n ## 4b,9 ## n ## 1b;
  57. .llong 8 ## n ## 5b,9 ## n ## 1b;
  58. .llong 8 ## n ## 6b,9 ## n ## 1b;
  59. .llong 8 ## n ## 7b,9 ## n ## 1b;
  60. .text
  61. CACHELINE_BYTES = CACHE_LINE_SIZE
  62. LG_CACHELINE_BYTES = LG_CACHE_LINE_SIZE
  63. CACHELINE_MASK = (CACHE_LINE_SIZE-1)
  64. _GLOBAL(strcpy)
  65. addi r5,r3,-1
  66. addi r4,r4,-1
  67. 1: lbzu r0,1(r4)
  68. cmpwi 0,r0,0
  69. stbu r0,1(r5)
  70. bne 1b
  71. blr
  72. _GLOBAL(strncpy)
  73. cmpwi 0,r5,0
  74. beqlr
  75. mtctr r5
  76. addi r6,r3,-1
  77. addi r4,r4,-1
  78. 1: lbzu r0,1(r4)
  79. cmpwi 0,r0,0
  80. stbu r0,1(r6)
  81. bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
  82. blr
  83. _GLOBAL(strcat)
  84. addi r5,r3,-1
  85. addi r4,r4,-1
  86. 1: lbzu r0,1(r5)
  87. cmpwi 0,r0,0
  88. bne 1b
  89. addi r5,r5,-1
  90. 1: lbzu r0,1(r4)
  91. cmpwi 0,r0,0
  92. stbu r0,1(r5)
  93. bne 1b
  94. blr
  95. _GLOBAL(strcmp)
  96. addi r5,r3,-1
  97. addi r4,r4,-1
  98. 1: lbzu r3,1(r5)
  99. cmpwi 1,r3,0
  100. lbzu r0,1(r4)
  101. subf. r3,r0,r3
  102. beqlr 1
  103. beq 1b
  104. blr
  105. _GLOBAL(strlen)
  106. addi r4,r3,-1
  107. 1: lbzu r0,1(r4)
  108. cmpwi 0,r0,0
  109. bne 1b
  110. subf r3,r3,r4
  111. blr
  112. /*
  113.  * Use dcbz on the complete cache lines in the destination
  114.  * to set them to zero.  This requires that the destination
  115.  * area is cacheable.  -- paulus
  116.  */
  117. _GLOBAL(cacheable_memzero)
  118. mr r5,r4
  119. li r4,0
  120. addi r6,r3,-4
  121. cmplwi 0,r5,4
  122. blt 7f
  123. stwu r4,4(r6)
  124. beqlr
  125. andi. r0,r6,3
  126. add r5,r0,r5
  127. subf r6,r0,r6
  128. clrlwi r7,r6,32-LG_CACHELINE_BYTES
  129. add r8,r7,r5
  130. srwi r9,r8,LG_CACHELINE_BYTES
  131. addic. r9,r9,-1 /* total number of complete cachelines */
  132. ble 2f
  133. xori r0,r7,CACHELINE_MASK & ~3
  134. srwi. r0,r0,2
  135. beq 3f
  136. mtctr r0
  137. 4: stwu r4,4(r6)
  138. bdnz 4b
  139. 3: mtctr r9
  140. li r7,4
  141. 10: dcbz r7,r6
  142. addi r6,r6,CACHELINE_BYTES
  143. bdnz 10b
  144. clrlwi r5,r8,32-LG_CACHELINE_BYTES
  145. addi r5,r5,4
  146. 2: srwi r0,r5,2
  147. mtctr r0
  148. bdz 6f
  149. 1: stwu r4,4(r6)
  150. bdnz 1b
  151. 6: andi. r5,r5,3
  152. 7: cmpwi 0,r5,0
  153. beqlr
  154. mtctr r5
  155. addi r6,r6,3
  156. 8: stbu r4,1(r6)
  157. bdnz 8b
  158. blr
  159. _GLOBAL(memset)
  160. rlwimi r4,r4,8,16,23
  161. rlwimi r4,r4,16,0,15
  162. addi r6,r3,-4
  163. cmplwi 0,r5,4
  164. blt 7f
  165. stwu r4,4(r6)
  166. beqlr
  167. andi. r0,r6,3
  168. add r5,r0,r5
  169. subf r6,r0,r6
  170. srwi r0,r5,2
  171. mtctr r0
  172. bdz 6f
  173. 1: stwu r4,4(r6)
  174. bdnz 1b
  175. 6: andi. r5,r5,3
  176. 7: cmpwi 0,r5,0
  177. beqlr
  178. mtctr r5
  179. addi r6,r6,3
  180. 8: stbu r4,1(r6)
  181. bdnz 8b
  182. blr
  183. _GLOBAL(memmove)
  184. cmplw 0,r3,r4
  185. bgt .backwards_memcpy
  186. /* fall through */
  187. _GLOBAL(memcpy)
  188. srwi. r7,r5,3
  189. addi r6,r3,-4
  190. addi r4,r4,-4
  191. beq 2f /* if less than 8 bytes to do */
  192. andi. r0,r6,3 /* get dest word aligned */
  193. mtctr r7
  194. bne 5f
  195. 1: lwz r7,4(r4)
  196. lwzu r8,8(r4)
  197. stw r7,4(r6)
  198. stwu r8,8(r6)
  199. bdnz 1b
  200. andi. r5,r5,7
  201. 2: cmplwi 0,r5,4
  202. blt 3f
  203. lwzu r0,4(r4)
  204. addi r5,r5,-4
  205. stwu r0,4(r6)
  206. 3: cmpwi 0,r5,0
  207. beqlr
  208. mtctr r5
  209. addi r4,r4,3
  210. addi r6,r6,3
  211. 4: lbzu r0,1(r4)
  212. stbu r0,1(r6)
  213. bdnz 4b
  214. blr
  215. 5: subfic r0,r0,4
  216. mtctr r0
  217. 6: lbz r7,4(r4)
  218. addi r4,r4,1
  219. stb r7,4(r6)
  220. addi r6,r6,1
  221. bdnz 6b
  222. subf r5,r0,r5
  223. rlwinm. r7,r5,32-3,3,31
  224. beq 2b
  225. mtctr r7
  226. b 1b
  227. _GLOBAL(backwards_memcpy)
  228. rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
  229. add r6,r3,r5
  230. add r4,r4,r5
  231. beq 2f
  232. andi. r0,r6,3
  233. mtctr r7
  234. bne 5f
  235. 1: lwz r7,-4(r4)
  236. lwzu r8,-8(r4)
  237. stw r7,-4(r6)
  238. stwu r8,-8(r6)
  239. bdnz 1b
  240. andi. r5,r5,7
  241. 2: cmplwi 0,r5,4
  242. blt 3f
  243. lwzu r0,-4(r4)
  244. subi r5,r5,4
  245. stwu r0,-4(r6)
  246. 3: cmpwi 0,r5,0
  247. beqlr
  248. mtctr r5
  249. 4: lbzu r0,-1(r4)
  250. stbu r0,-1(r6)
  251. bdnz 4b
  252. blr
  253. 5: mtctr r0
  254. 6: lbzu r7,-1(r4)
  255. stbu r7,-1(r6)
  256. bdnz 6b
  257. subf r5,r0,r5
  258. rlwinm. r7,r5,32-3,3,31
  259. beq 2b
  260. mtctr r7
  261. b 1b
  262. _GLOBAL(memcmp)
  263. cmpwi 0,r5,0
  264. ble- 2f
  265. mtctr r5
  266. addi r6,r3,-1
  267. addi r4,r4,-1
  268. 1: lbzu r3,1(r6)
  269. lbzu r0,1(r4)
  270. subf. r3,r0,r3
  271. bdnzt 2,1b
  272. blr
  273. 2: li r3,0
  274. blr
  275. _GLOBAL(memchr)
  276. cmpwi 0,r5,0
  277. ble- 2f
  278. mtctr r5
  279. addi r3,r3,-1
  280. 1: lbzu r0,1(r3)
  281. cmpw 0,r0,r4
  282. bdnzf 2,1b
  283. beqlr
  284. 2: li r3,0
  285. blr
  286. _GLOBAL(__copy_tofrom_user)
  287. addi r4,r4,-4
  288. addi r6,r3,-4
  289. neg r0,r3
  290. andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
  291. beq 58f
  292. cmplw 0,r5,r0 /* is this more than total to do? */
  293. blt 63f /* if not much to do */
  294. andi. r8,r0,3 /* get it word-aligned first */
  295. mtctr r8
  296. beq+ 61f
  297. 70: lbz r9,4(r4) /* do some bytes */
  298. 71: stb r9,4(r6)
  299. addi r4,r4,1
  300. addi r6,r6,1
  301. bdnz 70b
  302. 61: subf r5,r0,r5
  303. srwi. r0,r0,2
  304. mtctr r0
  305. beq 58f
  306. 72: lwzu r9,4(r4) /* do some words */
  307. 73: stwu r9,4(r6)
  308. bdnz 72b
  309. 58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
  310. clrlwi r5,r5,32-LG_CACHELINE_BYTES
  311. li r11,4
  312. beq 63f
  313. /* Here we decide how far ahead to prefetch the source */
  314. #if MAX_COPY_PREFETCH > 1
  315. /* Heuristically, for large transfers we prefetch
  316.    MAX_COPY_PREFETCH cachelines ahead.  For small transfers
  317.    we prefetch 1 cacheline ahead. */
  318. cmpwi r0,MAX_COPY_PREFETCH
  319. li r7,1
  320. li r3,4
  321. ble 111f
  322. li r7,MAX_COPY_PREFETCH
  323. 111: mtctr r7
  324. 112: dcbt r3,r4
  325. addi r3,r3,CACHELINE_BYTES
  326. bdnz 112b
  327. #else /* MAX_COPY_PREFETCH == 1 */
  328. li r3,CACHELINE_BYTES + 4
  329. dcbt r11,r4
  330. #endif /* MAX_COPY_PREFETCH */
  331. mtctr r0
  332. dcbt r3,r4
  333. 53:
  334. 54: dcbz r11,r6
  335. /* had to move these to keep extable in order */
  336. .section __ex_table,"a"
  337. .align 3
  338. .llong 70b,100f
  339. .llong 71b,101f
  340. .llong 72b,102f
  341. .llong 73b,103f
  342. .llong 54b,105f
  343. .text
  344. /* the main body of the cacheline loop */
  345. COPY_16_BYTES_WITHEX(0)
  346. #if CACHE_LINE_SIZE >= 32
  347. COPY_16_BYTES_WITHEX(1)
  348. #if CACHE_LINE_SIZE >= 64
  349. COPY_16_BYTES_WITHEX(2)
  350. COPY_16_BYTES_WITHEX(3)
  351. #if CACHE_LINE_SIZE >= 128
  352. COPY_16_BYTES_WITHEX(4)
  353. COPY_16_BYTES_WITHEX(5)
  354. COPY_16_BYTES_WITHEX(6)
  355. COPY_16_BYTES_WITHEX(7)
  356. #endif
  357. #endif
  358. #endif
  359. bdnz 53b
  360. 63: srwi. r0,r5,2
  361. mtctr r0
  362. beq 64f
  363. 30: lwzu r0,4(r4)
  364. 31: stwu r0,4(r6)
  365. bdnz 30b
  366. 64: andi. r0,r5,3
  367. mtctr r0
  368. beq+ 65f
  369. 40: lbz r0,4(r4)
  370. 41: stb r0,4(r6)
  371. addi r4,r4,1
  372. addi r6,r6,1
  373. bdnz 40b
  374. 65: li r3,0
  375. blr
  376. /* read fault, initial single-byte copy */
  377. 100: li r4,0
  378. b 90f
  379. /* write fault, initial single-byte copy */
  380. 101: li r4,1
  381. 90: subf r5,r8,r5
  382. li r3,0
  383. b 99f
  384. /* read fault, initial word copy */
  385. 102: li r4,0
  386. b 91f
  387. /* write fault, initial word copy */
  388. 103: li r4,1
  389. 91: li r3,2
  390. b 99f
  391. /*
  392.  * this stuff handles faults in the cacheline loop and branches to either
  393.  * 104f (if in read part) or 105f (if in write part), after updating r5
  394.  */
  395. COPY_16_BYTES_EXCODE(0)
  396. #if CACHE_LINE_SIZE >= 32
  397. COPY_16_BYTES_EXCODE(1)
  398. #if CACHE_LINE_SIZE >= 64
  399. COPY_16_BYTES_EXCODE(2)
  400. COPY_16_BYTES_EXCODE(3)
  401. #if CACHE_LINE_SIZE >= 128
  402. COPY_16_BYTES_EXCODE(4)
  403. COPY_16_BYTES_EXCODE(5)
  404. COPY_16_BYTES_EXCODE(6)
  405. COPY_16_BYTES_EXCODE(7)
  406. #endif
  407. #endif
  408. #endif
  409. /* read fault in cacheline loop */
  410. 104: li r4,0
  411. b 92f
  412. /* fault on dcbz (effectively a write fault) */
  413. /* or write fault in cacheline loop */
  414. 105: li r4,1
  415. 92: li r3,LG_CACHELINE_BYTES
  416. b 99f
  417. /* read fault in final word loop */
  418. 108: li r4,0
  419. b 93f
  420. /* write fault in final word loop */
  421. 109: li r4,1
  422. 93: andi. r5,r5,3
  423. li r3,2
  424. b 99f
  425. /* read fault in final byte loop */
  426. 110: li r4,0
  427. b 94f
  428. /* write fault in final byte loop */
  429. 111: li r4,1
  430. 94: li r5,0
  431. li r3,0
  432. /*
  433.  * At this stage the number of bytes not copied is
  434.  * r5 + (ctr << r3), and r4 is 0 for read or 1 for write.
  435.  */
  436. 99: mfctr r0
  437. slw r3,r0,r3
  438. add r3,r3,r5
  439. cmpwi 0,r4,0
  440. bne 120f
  441. /* for read fault, clear out the destination: r3 bytes starting at 4(r6) */
  442. srwi. r0,r3,2
  443. li r9,0
  444. mtctr r0
  445. beq 113f
  446. 112: stwu r9,4(r6)
  447. bdnz 112b
  448. 113: andi. r0,r3,3
  449. mtctr r0
  450. beq 120f
  451. 114: stb r9,4(r6)
  452. addi r6,r6,1
  453. bdnz 114b
  454. 120: blr
  455. .section __ex_table,"a"
  456. .align 3
  457. .llong 30b,108b
  458. .llong 31b,109b
  459. .llong 40b,110b
  460. .llong 41b,111b
  461. .llong 112b,120b
  462. .llong 114b,120b
  463. .text
  464. _GLOBAL(__clear_user)
  465. addi r6,r3,-4
  466. li r3,0
  467. li r5,0
  468. cmplwi 0,r4,4
  469. blt 7f
  470. /* clear a single word */
  471. 11: stwu r5,4(r6)
  472. beqlr
  473. /* clear word sized chunks */
  474. andi. r0,r6,3
  475. add r4,r0,r4
  476. subf r6,r0,r6
  477. srwi r0,r4,2
  478. andi. r4,r4,3
  479. mtctr r0
  480. bdz 7f
  481. 1: stwu r5,4(r6)
  482. bdnz 1b
  483. /* clear byte sized chunks */
  484. 7: cmpwi 0,r4,0
  485. beqlr
  486. mtctr r4
  487. addi r6,r6,3
  488. 8: stbu r5,1(r6)
  489. bdnz 8b
  490. blr
  491. 90: mr r3,r4
  492. blr
  493. 91: mfctr r3
  494. slwi r3,r3,2
  495. add r3,r3,r4
  496. blr
  497. 92: mfctr r3
  498. blr
  499. .section __ex_table,"a"
  500. .align 3
  501. .llong 11b,90b
  502. .llong 1b,91b
  503. .llong 8b,92b
  504. .text
  505. _GLOBAL(__strncpy_from_user)
  506. addi r6,r3,-1
  507. addi r4,r4,-1
  508. cmpwi 0,r5,0
  509. beq 2f
  510. mtctr r5
  511. 1: lbzu r0,1(r4)
  512. cmpwi 0,r0,0
  513. stbu r0,1(r6)
  514. bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
  515. beq 3f
  516. 2: addi r6,r6,1
  517. 3: subf r3,r3,r6
  518. blr
  519. 99: li r3,-EFAULT
  520. blr
  521. .section __ex_table,"a"
  522. .align 3
  523. .llong 1b,99b
  524. .text
  525. /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
  526. _GLOBAL(__strnlen_user)
  527. addi r7,r3,-1
  528. subf r6,r7,r5 /* top+1 - str */
  529. cmplw 0,r4,r6
  530. bge 0f
  531. mr r6,r4
  532. 0: mtctr r6 /* ctr = min(len, top - str) */
  533. 1: lbzu r0,1(r7) /* get next byte */
  534. cmpwi 0,r0,0
  535. bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
  536. addi r7,r7,1
  537. subf r3,r3,r7 /* number of bytes we have looked at */
  538. beqlr /* return if we found a 0 byte */
  539. cmpw 0,r3,r4 /* did we look at all len bytes? */
  540. blt 99f /* if not, must have hit top */
  541. addi r3,r4,1 /* return len + 1 to indicate no null found */
  542. blr
  543. 99: li r3,0 /* bad address, return 0 */
  544. blr
  545. .section __ex_table,"a"
  546. .align 3
  547. .llong 1b,99b