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

Linux/Unix编程

开发平台:

Unix_Linux

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