string.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.string.S 1.9 10/25/01 10:08:51 trini
  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 "../kernel/ppc_asm.tmpl"
  15. #include <linux/config.h>
  16. #include <asm/processor.h>
  17. #include <asm/cache.h>
  18. #include <asm/errno.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. 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. .long 53b,105f
  452. .text
  453. /* the main body of the cacheline loop */
  454. COPY_16_BYTES_WITHEX(0)
  455. #if L1_CACHE_LINE_SIZE >= 32
  456. COPY_16_BYTES_WITHEX(1)
  457. #if L1_CACHE_LINE_SIZE >= 64
  458. COPY_16_BYTES_WITHEX(2)
  459. COPY_16_BYTES_WITHEX(3)
  460. #if L1_CACHE_LINE_SIZE >= 128
  461. COPY_16_BYTES_WITHEX(4)
  462. COPY_16_BYTES_WITHEX(5)
  463. COPY_16_BYTES_WITHEX(6)
  464. COPY_16_BYTES_WITHEX(7)
  465. #endif
  466. #endif
  467. #endif
  468. bdnz 53b
  469. 63: srwi. r0,r5,2
  470. mtctr r0
  471. beq 64f
  472. 30: lwzu r0,4(r4)
  473. 31: stwu r0,4(r6)
  474. bdnz 30b
  475. 64: andi. r0,r5,3
  476. mtctr r0
  477. beq+ 65f
  478. 40: lbz r0,4(r4)
  479. 41: stb r0,4(r6)
  480. addi r4,r4,1
  481. addi r6,r6,1
  482. bdnz 40b
  483. 65: li r3,0
  484. blr
  485. /* read fault, initial single-byte copy */
  486. 100: li r4,0
  487. b 90f
  488. /* write fault, initial single-byte copy */
  489. 101: li r4,1
  490. 90: subf r5,r8,r5
  491. li r3,0
  492. b 99f
  493. /* read fault, initial word copy */
  494. 102: li r4,0
  495. b 91f
  496. /* write fault, initial word copy */
  497. 103: li r4,1
  498. 91: li r3,2
  499. b 99f
  500. /*
  501.  * this stuff handles faults in the cacheline loop and branches to either
  502.  * 104f (if in read part) or 105f (if in write part), after updating r5
  503.  */
  504. COPY_16_BYTES_EXCODE(0)
  505. #if L1_CACHE_LINE_SIZE >= 32
  506. COPY_16_BYTES_EXCODE(1)
  507. #if L1_CACHE_LINE_SIZE >= 64
  508. COPY_16_BYTES_EXCODE(2)
  509. COPY_16_BYTES_EXCODE(3)
  510. #if L1_CACHE_LINE_SIZE >= 128
  511. COPY_16_BYTES_EXCODE(4)
  512. COPY_16_BYTES_EXCODE(5)
  513. COPY_16_BYTES_EXCODE(6)
  514. COPY_16_BYTES_EXCODE(7)
  515. #endif
  516. #endif
  517. #endif
  518. /* read fault in cacheline loop */
  519. 104: li r4,0
  520. b 92f
  521. /* fault on dcbz (effectively a write fault) */
  522. /* or write fault in cacheline loop */
  523. 105: li r4,1
  524. 92: li r3,LG_CACHELINE_BYTES
  525. b 99f
  526. /* read fault in final word loop */
  527. 108: li r4,0
  528. b 93f
  529. /* write fault in final word loop */
  530. 109: li r4,1
  531. 93: andi. r5,r5,3
  532. li r3,2
  533. b 99f
  534. /* read fault in final byte loop */
  535. 110: li r4,0
  536. b 94f
  537. /* write fault in final byte loop */
  538. 111: li r4,1
  539. 94: li r5,0
  540. li r3,0
  541. /*
  542.  * At this stage the number of bytes not copied is
  543.  * r5 + (ctr << r3), and r4 is 0 for read or 1 for write.
  544.  */
  545. 99: mfctr r0
  546. slw r3,r0,r3
  547. add r3,r3,r5
  548. cmpwi 0,r4,0
  549. bne 120f
  550. /* for read fault, clear out the destination: r3 bytes starting at 4(r6) */
  551. srwi. r0,r3,2
  552. li r9,0
  553. mtctr r0
  554. beq 113f
  555. 112: stwu r9,4(r6)
  556. bdnz 112b
  557. 113: andi. r0,r3,3
  558. mtctr r0
  559. beq 120f
  560. 114: stb r9,4(r6)
  561. addi r6,r6,1
  562. bdnz 114b
  563. 120: blr
  564. .section __ex_table,"a"
  565. .align 2
  566. .long 30b,108b
  567. .long 31b,109b
  568. .long 40b,110b
  569. .long 41b,111b
  570. .long 112b,120b
  571. .long 114b,120b
  572. .text
  573. .globl __clear_user
  574. __clear_user:
  575. addi r6,r3,-4
  576. li r3,0
  577. li r5,0
  578. cmplwi 0,r4,4
  579. blt 7f
  580. /* clear a single word */
  581. 11: stwu r5,4(r6)
  582. beqlr
  583. /* clear word sized chunks */
  584. andi. r0,r6,3
  585. add r4,r0,r4
  586. subf r6,r0,r6
  587. srwi r0,r4,2
  588. mtctr r0
  589. bdz 6f
  590. 1: stwu r5,4(r6)
  591. bdnz 1b
  592. 6: andi. r4,r4,3
  593. /* clear byte sized chunks */
  594. 7: cmpwi 0,r4,0
  595. beqlr
  596. mtctr r4
  597. addi r6,r6,3
  598. 8: stbu r5,1(r6)
  599. bdnz 8b
  600. blr
  601. 99: li r3,-EFAULT
  602. blr
  603. .section __ex_table,"a"
  604. .align 2
  605. .long 11b,99b
  606. .long 1b,99b
  607. .long 8b,99b
  608. .text
  609. .globl __strncpy_from_user
  610. __strncpy_from_user:
  611. addi r6,r3,-1
  612. addi r4,r4,-1
  613. cmpwi 0,r5,0
  614. beq 2f
  615. mtctr r5
  616. 1: lbzu r0,1(r4)
  617. cmpwi 0,r0,0
  618. stbu r0,1(r6)
  619. bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
  620. beq 3f
  621. 2: addi r6,r6,1
  622. 3: subf r3,r3,r6
  623. blr
  624. 99: li r3,-EFAULT
  625. blr
  626. .section __ex_table,"a"
  627. .align 2
  628. .long 1b,99b
  629. .text
  630. /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
  631. .globl __strnlen_user
  632. __strnlen_user:
  633. addi r7,r3,-1
  634. subf r6,r7,r5 /* top+1 - str */
  635. cmplw 0,r4,r6
  636. bge 0f
  637. mr r6,r4
  638. 0: mtctr r6 /* ctr = min(len, top - str) */
  639. 1: lbzu r0,1(r7) /* get next byte */
  640. cmpwi 0,r0,0
  641. bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
  642. addi r7,r7,1
  643. subf r3,r3,r7 /* number of bytes we have looked at */
  644. beqlr /* return if we found a 0 byte */
  645. cmpw 0,r3,r4 /* did we look at all len bytes? */
  646. blt 99f /* if not, must have hit top */
  647. addi r3,r4,1 /* return len + 1 to indicate no null found */
  648. blr
  649. 99: li r3,0 /* bad address, return 0 */
  650. blr
  651. .section __ex_table,"a"
  652. .align 2
  653. .long 1b,99b