uaccess.S 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /*
  2. * linux/arch/arm/lib/uaccess.S
  3. *
  4. * Copyright (C) 1995, 1996,1997,1998 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Routines to block copy data to/from user memory
  11. * These are highly optimised both for the 4k page size
  12. * and for various alignments.
  13. */
  14. #include <linux/linkage.h>
  15. #include <asm/assembler.h>
  16. #include <asm/errno.h>
  17. .text
  18. #define PAGE_SHIFT 12
  19. /* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
  20. * Purpose : copy a block to user memory from kernel memory
  21. * Params : to - user memory
  22. * : from - kernel memory
  23. * : n - number of bytes to copy
  24. * Returns : Number of bytes NOT copied.
  25. */
  26. .c2u_dest_not_aligned:
  27. rsb ip, ip, #4
  28. cmp ip, #2
  29. ldrb r3, [r1], #1
  30. USER( strbt r3, [r0], #1) @ May fault
  31. ldrgeb r3, [r1], #1
  32. USER( strgebt r3, [r0], #1) @ May fault
  33. ldrgtb r3, [r1], #1
  34. USER( strgtbt r3, [r0], #1) @ May fault
  35. sub r2, r2, ip
  36. b .c2u_dest_aligned
  37. ENTRY(__arch_copy_to_user)
  38. stmfd sp!, {r2, r4 - r7, lr}
  39. cmp r2, #4
  40. blt .c2u_not_enough
  41. PLD( pld [r1, #0] )
  42. PLD( pld [r0, #0] )
  43. ands ip, r0, #3
  44. bne .c2u_dest_not_aligned
  45. .c2u_dest_aligned:
  46. ands ip, r1, #3
  47. bne .c2u_src_not_aligned
  48. /*
  49. * Seeing as there has to be at least 8 bytes to copy, we can
  50. * copy one word, and force a user-mode page fault...
  51. */
  52. .c2u_0fupi: subs r2, r2, #4
  53. addmi ip, r2, #4
  54. bmi .c2u_0nowords
  55. ldr r3, [r1], #4
  56. USER( strt r3, [r0], #4) @ May fault
  57. mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  58. rsb ip, ip, #0
  59. movs ip, ip, lsr #32 - PAGE_SHIFT
  60. beq .c2u_0fupi
  61. /*
  62. * ip = max no. of bytes to copy before needing another "strt" insn
  63. */
  64. cmp r2, ip
  65. movlt ip, r2
  66. sub r2, r2, ip
  67. subs ip, ip, #32
  68. blt .c2u_0rem8lp
  69. PLD( pld [r1, #28] )
  70. PLD( pld [r0, #28] )
  71. PLD( subs ip, ip, #64 )
  72. PLD( blt .c2u_0cpynopld )
  73. PLD( pld [r1, #60] )
  74. PLD( pld [r0, #60] )
  75. .c2u_0cpy8lp:
  76. PLD( pld [r1, #92] )
  77. PLD( pld [r0, #92] )
  78. .c2u_0cpynopld: ldmia r1!, {r3 - r6}
  79. stmia r0!, {r3 - r6} @ Shouldnt fault
  80. ldmia r1!, {r3 - r6}
  81. subs ip, ip, #32
  82. stmia r0!, {r3 - r6} @ Shouldnt fault
  83. bpl .c2u_0cpy8lp
  84. PLD( cmn ip, #64 )
  85. PLD( bge .c2u_0cpynopld )
  86. PLD( add ip, ip, #64 )
  87. .c2u_0rem8lp: cmn ip, #16
  88. ldmgeia r1!, {r3 - r6}
  89. stmgeia r0!, {r3 - r6} @ Shouldnt fault
  90. tst ip, #8
  91. ldmneia r1!, {r3 - r4}
  92. stmneia r0!, {r3 - r4} @ Shouldnt fault
  93. tst ip, #4
  94. ldrne r3, [r1], #4
  95. strnet r3, [r0], #4 @ Shouldnt fault
  96. ands ip, ip, #3
  97. beq .c2u_0fupi
  98. .c2u_0nowords: teq ip, #0
  99. beq .c2u_finished
  100. .c2u_nowords: cmp ip, #2
  101. ldrb r3, [r1], #1
  102. USER( strbt r3, [r0], #1) @ May fault
  103. ldrgeb r3, [r1], #1
  104. USER( strgebt r3, [r0], #1) @ May fault
  105. ldrgtb r3, [r1], #1
  106. USER( strgtbt r3, [r0], #1) @ May fault
  107. b .c2u_finished
  108. .c2u_not_enough:
  109. movs ip, r2
  110. bne .c2u_nowords
  111. .c2u_finished: mov r0, #0
  112. LOADREGS(fd,sp!,{r2, r4 - r7, pc})
  113. .c2u_src_not_aligned:
  114. bic r1, r1, #3
  115. ldr r7, [r1], #4
  116. cmp ip, #2
  117. bgt .c2u_3fupi
  118. beq .c2u_2fupi
  119. .c2u_1fupi: subs r2, r2, #4
  120. addmi ip, r2, #4
  121. bmi .c2u_1nowords
  122. mov r3, r7, pull #8
  123. ldr r7, [r1], #4
  124. orr r3, r3, r7, push #24
  125. USER( strt r3, [r0], #4) @ May fault
  126. mov ip, r0, lsl #32 - PAGE_SHIFT
  127. rsb ip, ip, #0
  128. movs ip, ip, lsr #32 - PAGE_SHIFT
  129. beq .c2u_1fupi
  130. cmp r2, ip
  131. movlt ip, r2
  132. sub r2, r2, ip
  133. subs ip, ip, #16
  134. blt .c2u_1rem8lp
  135. PLD( pld [r1, #12] )
  136. PLD( pld [r0, #12] )
  137. PLD( subs ip, ip, #32 )
  138. PLD( blt .c2u_1cpynopld )
  139. PLD( pld [r1, #28] )
  140. PLD( pld [r0, #28] )
  141. .c2u_1cpy8lp:
  142. PLD( pld [r1, #44] )
  143. PLD( pld [r0, #44] )
  144. .c2u_1cpynopld: mov r3, r7, pull #8
  145. ldmia r1!, {r4 - r7}
  146. subs ip, ip, #16
  147. orr r3, r3, r4, push #24
  148. mov r4, r4, pull #8
  149. orr r4, r4, r5, push #24
  150. mov r5, r5, pull #8
  151. orr r5, r5, r6, push #24
  152. mov r6, r6, pull #8
  153. orr r6, r6, r7, push #24
  154. stmia r0!, {r3 - r6} @ Shouldnt fault
  155. bpl .c2u_1cpy8lp
  156. PLD( cmn ip, #32 )
  157. PLD( bge .c2u_1cpynopld )
  158. PLD( add ip, ip, #32 )
  159. .c2u_1rem8lp: tst ip, #8
  160. movne r3, r7, pull #8
  161. ldmneia r1!, {r4, r7}
  162. orrne r3, r3, r4, push #24
  163. movne r4, r4, pull #8
  164. orrne r4, r4, r7, push #24
  165. stmneia r0!, {r3 - r4} @ Shouldnt fault
  166. tst ip, #4
  167. movne r3, r7, pull #8
  168. ldrne r7, [r1], #4
  169. orrne r3, r3, r7, push #24
  170. strnet r3, [r0], #4 @ Shouldnt fault
  171. ands ip, ip, #3
  172. beq .c2u_1fupi
  173. .c2u_1nowords: mov r3, r7, get_byte_1
  174. teq ip, #0
  175. beq .c2u_finished
  176. cmp ip, #2
  177. USER( strbt r3, [r0], #1) @ May fault
  178. movge r3, r7, get_byte_2
  179. USER( strgebt r3, [r0], #1) @ May fault
  180. movgt r3, r7, get_byte_3
  181. USER( strgtbt r3, [r0], #1) @ May fault
  182. b .c2u_finished
  183. .c2u_2fupi: subs r2, r2, #4
  184. addmi ip, r2, #4
  185. bmi .c2u_2nowords
  186. mov r3, r7, pull #16
  187. ldr r7, [r1], #4
  188. orr r3, r3, r7, push #16
  189. USER( strt r3, [r0], #4) @ May fault
  190. mov ip, r0, lsl #32 - PAGE_SHIFT
  191. rsb ip, ip, #0
  192. movs ip, ip, lsr #32 - PAGE_SHIFT
  193. beq .c2u_2fupi
  194. cmp r2, ip
  195. movlt ip, r2
  196. sub r2, r2, ip
  197. subs ip, ip, #16
  198. blt .c2u_2rem8lp
  199. PLD( pld [r1, #12] )
  200. PLD( pld [r0, #12] )
  201. PLD( subs ip, ip, #32 )
  202. PLD( blt .c2u_2cpynopld )
  203. PLD( pld [r1, #28] )
  204. PLD( pld [r0, #28] )
  205. .c2u_2cpy8lp:
  206. PLD( pld [r1, #44] )
  207. PLD( pld [r0, #44] )
  208. .c2u_2cpynopld: mov r3, r7, pull #16
  209. ldmia r1!, {r4 - r7}
  210. subs ip, ip, #16
  211. orr r3, r3, r4, push #16
  212. mov r4, r4, pull #16
  213. orr r4, r4, r5, push #16
  214. mov r5, r5, pull #16
  215. orr r5, r5, r6, push #16
  216. mov r6, r6, pull #16
  217. orr r6, r6, r7, push #16
  218. stmia r0!, {r3 - r6} @ Shouldnt fault
  219. bpl .c2u_2cpy8lp
  220. PLD( cmn ip, #32 )
  221. PLD( bge .c2u_2cpynopld )
  222. PLD( add ip, ip, #32 )
  223. .c2u_2rem8lp: tst ip, #8
  224. movne r3, r7, pull #16
  225. ldmneia r1!, {r4, r7}
  226. orrne r3, r3, r4, push #16
  227. movne r4, r4, pull #16
  228. orrne r4, r4, r7, push #16
  229. stmneia r0!, {r3 - r4} @ Shouldnt fault
  230. tst ip, #4
  231. movne r3, r7, pull #16
  232. ldrne r7, [r1], #4
  233. orrne r3, r3, r7, push #16
  234. strnet r3, [r0], #4 @ Shouldnt fault
  235. ands ip, ip, #3
  236. beq .c2u_2fupi
  237. .c2u_2nowords: mov r3, r7, get_byte_2
  238. teq ip, #0
  239. beq .c2u_finished
  240. cmp ip, #2
  241. USER( strbt r3, [r0], #1) @ May fault
  242. movge r3, r7, get_byte_3
  243. USER( strgebt r3, [r0], #1) @ May fault
  244. ldrgtb r3, [r1], #0
  245. USER( strgtbt r3, [r0], #1) @ May fault
  246. b .c2u_finished
  247. .c2u_3fupi: subs r2, r2, #4
  248. addmi ip, r2, #4
  249. bmi .c2u_3nowords
  250. mov r3, r7, pull #24
  251. ldr r7, [r1], #4
  252. orr r3, r3, r7, push #8
  253. USER( strt r3, [r0], #4) @ May fault
  254. mov ip, r0, lsl #32 - PAGE_SHIFT
  255. rsb ip, ip, #0
  256. movs ip, ip, lsr #32 - PAGE_SHIFT
  257. beq .c2u_3fupi
  258. cmp r2, ip
  259. movlt ip, r2
  260. sub r2, r2, ip
  261. subs ip, ip, #16
  262. blt .c2u_3rem8lp
  263. PLD( pld [r1, #12] )
  264. PLD( pld [r0, #12] )
  265. PLD( subs ip, ip, #32 )
  266. PLD( blt .c2u_3cpynopld )
  267. PLD( pld [r1, #28] )
  268. PLD( pld [r0, #28] )
  269. .c2u_3cpy8lp:
  270. PLD( pld [r1, #44] )
  271. PLD( pld [r0, #44] )
  272. .c2u_3cpynopld: mov r3, r7, pull #24
  273. ldmia r1!, {r4 - r7}
  274. subs ip, ip, #16
  275. orr r3, r3, r4, push #8
  276. mov r4, r4, pull #24
  277. orr r4, r4, r5, push #8
  278. mov r5, r5, pull #24
  279. orr r5, r5, r6, push #8
  280. mov r6, r6, pull #24
  281. orr r6, r6, r7, push #8
  282. stmia r0!, {r3 - r6} @ Shouldnt fault
  283. bpl .c2u_3cpy8lp
  284. PLD( cmn ip, #32 )
  285. PLD( bge .c2u_3cpynopld )
  286. PLD( add ip, ip, #32 )
  287. .c2u_3rem8lp: tst ip, #8
  288. movne r3, r7, pull #24
  289. ldmneia r1!, {r4, r7}
  290. orrne r3, r3, r4, push #8
  291. movne r4, r4, pull #24
  292. orrne r4, r4, r7, push #8
  293. stmneia r0!, {r3 - r4} @ Shouldnt fault
  294. tst ip, #4
  295. movne r3, r7, pull #24
  296. ldrne r7, [r1], #4
  297. orrne r3, r3, r7, push #8
  298. strnet r3, [r0], #4 @ Shouldnt fault
  299. ands ip, ip, #3
  300. beq .c2u_3fupi
  301. .c2u_3nowords: mov r3, r7, get_byte_3
  302. teq ip, #0
  303. beq .c2u_finished
  304. cmp ip, #2
  305. USER( strbt r3, [r0], #1) @ May fault
  306. ldrgeb r3, [r1], #1
  307. USER( strgebt r3, [r0], #1) @ May fault
  308. ldrgtb r3, [r1], #0
  309. USER( strgtbt r3, [r0], #1) @ May fault
  310. b .c2u_finished
  311. .section .fixup,"ax"
  312. .align 0
  313. 9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
  314. .previous
  315. /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
  316. * Purpose : copy a block from user memory to kernel memory
  317. * Params : to - kernel memory
  318. * : from - user memory
  319. * : n - number of bytes to copy
  320. * Returns : Number of bytes NOT copied.
  321. */
  322. .cfu_dest_not_aligned:
  323. rsb ip, ip, #4
  324. cmp ip, #2
  325. USER( ldrbt r3, [r1], #1) @ May fault
  326. strb r3, [r0], #1
  327. USER( ldrgebt r3, [r1], #1) @ May fault
  328. strgeb r3, [r0], #1
  329. USER( ldrgtbt r3, [r1], #1) @ May fault
  330. strgtb r3, [r0], #1
  331. sub r2, r2, ip
  332. b .cfu_dest_aligned
  333. ENTRY(__arch_copy_from_user)
  334. stmfd sp!, {r0, r2, r4 - r7, lr}
  335. cmp r2, #4
  336. blt .cfu_not_enough
  337. PLD( pld [r1, #0] )
  338. PLD( pld [r0, #0] )
  339. ands ip, r0, #3
  340. bne .cfu_dest_not_aligned
  341. .cfu_dest_aligned:
  342. ands ip, r1, #3
  343. bne .cfu_src_not_aligned
  344. /*
  345. * Seeing as there has to be at least 8 bytes to copy, we can
  346. * copy one word, and force a user-mode page fault...
  347. */
  348. .cfu_0fupi: subs r2, r2, #4
  349. addmi ip, r2, #4
  350. bmi .cfu_0nowords
  351. USER( ldrt r3, [r1], #4)
  352. str r3, [r0], #4
  353. mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  354. rsb ip, ip, #0
  355. movs ip, ip, lsr #32 - PAGE_SHIFT
  356. beq .cfu_0fupi
  357. /*
  358. * ip = max no. of bytes to copy before needing another "strt" insn
  359. */
  360. cmp r2, ip
  361. movlt ip, r2
  362. sub r2, r2, ip
  363. subs ip, ip, #32
  364. blt .cfu_0rem8lp
  365. PLD( pld [r1, #28] )
  366. PLD( pld [r0, #28] )
  367. PLD( subs ip, ip, #64 )
  368. PLD( blt .cfu_0cpynopld )
  369. PLD( pld [r1, #60] )
  370. PLD( pld [r0, #60] )
  371. .cfu_0cpy8lp:
  372. PLD( pld [r1, #92] )
  373. PLD( pld [r0, #92] )
  374. .cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault
  375. stmia r0!, {r3 - r6}
  376. ldmia r1!, {r3 - r6} @ Shouldnt fault
  377. subs ip, ip, #32
  378. stmia r0!, {r3 - r6}
  379. bpl .cfu_0cpy8lp
  380. PLD( cmn ip, #64 )
  381. PLD( bge .cfu_0cpynopld )
  382. PLD( add ip, ip, #64 )
  383. .cfu_0rem8lp: cmn ip, #16
  384. ldmgeia r1!, {r3 - r6} @ Shouldnt fault
  385. stmgeia r0!, {r3 - r6}
  386. tst ip, #8
  387. ldmneia r1!, {r3 - r4} @ Shouldnt fault
  388. stmneia r0!, {r3 - r4}
  389. tst ip, #4
  390. ldrnet r3, [r1], #4 @ Shouldnt fault
  391. strne r3, [r0], #4
  392. ands ip, ip, #3
  393. beq .cfu_0fupi
  394. .cfu_0nowords: teq ip, #0
  395. beq .cfu_finished
  396. .cfu_nowords: cmp ip, #2
  397. USER( ldrbt r3, [r1], #1) @ May fault
  398. strb r3, [r0], #1
  399. USER( ldrgebt r3, [r1], #1) @ May fault
  400. strgeb r3, [r0], #1
  401. USER( ldrgtbt r3, [r1], #1) @ May fault
  402. strgtb r3, [r0], #1
  403. b .cfu_finished
  404. .cfu_not_enough:
  405. movs ip, r2
  406. bne .cfu_nowords
  407. .cfu_finished: mov r0, #0
  408. add sp, sp, #8
  409. LOADREGS(fd,sp!,{r4 - r7, pc})
  410. .cfu_src_not_aligned:
  411. bic r1, r1, #3
  412. USER( ldrt r7, [r1], #4) @ May fault
  413. cmp ip, #2
  414. bgt .cfu_3fupi
  415. beq .cfu_2fupi
  416. .cfu_1fupi: subs r2, r2, #4
  417. addmi ip, r2, #4
  418. bmi .cfu_1nowords
  419. mov r3, r7, pull #8
  420. USER( ldrt r7, [r1], #4) @ May fault
  421. orr r3, r3, r7, push #24
  422. str r3, [r0], #4
  423. mov ip, r1, lsl #32 - PAGE_SHIFT
  424. rsb ip, ip, #0
  425. movs ip, ip, lsr #32 - PAGE_SHIFT
  426. beq .cfu_1fupi
  427. cmp r2, ip
  428. movlt ip, r2
  429. sub r2, r2, ip
  430. subs ip, ip, #16
  431. blt .cfu_1rem8lp
  432. PLD( pld [r1, #12] )
  433. PLD( pld [r0, #12] )
  434. PLD( subs ip, ip, #32 )
  435. PLD( blt .cfu_1cpynopld )
  436. PLD( pld [r1, #28] )
  437. PLD( pld [r0, #28] )
  438. .cfu_1cpy8lp:
  439. PLD( pld [r1, #44] )
  440. PLD( pld [r0, #44] )
  441. .cfu_1cpynopld: mov r3, r7, pull #8
  442. ldmia r1!, {r4 - r7} @ Shouldnt fault
  443. subs ip, ip, #16
  444. orr r3, r3, r4, push #24
  445. mov r4, r4, pull #8
  446. orr r4, r4, r5, push #24
  447. mov r5, r5, pull #8
  448. orr r5, r5, r6, push #24
  449. mov r6, r6, pull #8
  450. orr r6, r6, r7, push #24
  451. stmia r0!, {r3 - r6}
  452. bpl .cfu_1cpy8lp
  453. PLD( cmn ip, #32 )
  454. PLD( bge .cfu_1cpynopld )
  455. PLD( add ip, ip, #32 )
  456. .cfu_1rem8lp: tst ip, #8
  457. movne r3, r7, pull #8
  458. ldmneia r1!, {r4, r7} @ Shouldnt fault
  459. orrne r3, r3, r4, push #24
  460. movne r4, r4, pull #8
  461. orrne r4, r4, r7, push #24
  462. stmneia r0!, {r3 - r4}
  463. tst ip, #4
  464. movne r3, r7, pull #8
  465. USER( ldrnet r7, [r1], #4) @ May fault
  466. orrne r3, r3, r7, push #24
  467. strne r3, [r0], #4
  468. ands ip, ip, #3
  469. beq .cfu_1fupi
  470. .cfu_1nowords: mov r3, r7, get_byte_1
  471. teq ip, #0
  472. beq .cfu_finished
  473. cmp ip, #2
  474. strb r3, [r0], #1
  475. movge r3, r7, get_byte_2
  476. strgeb r3, [r0], #1
  477. movgt r3, r7, get_byte_3
  478. strgtb r3, [r0], #1
  479. b .cfu_finished
  480. .cfu_2fupi: subs r2, r2, #4
  481. addmi ip, r2, #4
  482. bmi .cfu_2nowords
  483. mov r3, r7, pull #16
  484. USER( ldrt r7, [r1], #4) @ May fault
  485. orr r3, r3, r7, push #16
  486. str r3, [r0], #4
  487. mov ip, r1, lsl #32 - PAGE_SHIFT
  488. rsb ip, ip, #0
  489. movs ip, ip, lsr #32 - PAGE_SHIFT
  490. beq .cfu_2fupi
  491. cmp r2, ip
  492. movlt ip, r2
  493. sub r2, r2, ip
  494. subs ip, ip, #16
  495. blt .cfu_2rem8lp
  496. PLD( pld [r1, #12] )
  497. PLD( pld [r0, #12] )
  498. PLD( subs ip, ip, #32 )
  499. PLD( blt .cfu_2cpynopld )
  500. PLD( pld [r1, #28] )
  501. PLD( pld [r0, #28] )
  502. .cfu_2cpy8lp:
  503. PLD( pld [r1, #44] )
  504. PLD( pld [r0, #44] )
  505. .cfu_2cpynopld: mov r3, r7, pull #16
  506. ldmia r1!, {r4 - r7} @ Shouldnt fault
  507. subs ip, ip, #16
  508. orr r3, r3, r4, push #16
  509. mov r4, r4, pull #16
  510. orr r4, r4, r5, push #16
  511. mov r5, r5, pull #16
  512. orr r5, r5, r6, push #16
  513. mov r6, r6, pull #16
  514. orr r6, r6, r7, push #16
  515. stmia r0!, {r3 - r6}
  516. bpl .cfu_2cpy8lp
  517. PLD( cmn ip, #32 )
  518. PLD( bge .cfu_2cpynopld )
  519. PLD( add ip, ip, #32 )
  520. .cfu_2rem8lp: tst ip, #8
  521. movne r3, r7, pull #16
  522. ldmneia r1!, {r4, r7} @ Shouldnt fault
  523. orrne r3, r3, r4, push #16
  524. movne r4, r4, pull #16
  525. orrne r4, r4, r7, push #16
  526. stmneia r0!, {r3 - r4}
  527. tst ip, #4
  528. movne r3, r7, pull #16
  529. USER( ldrnet r7, [r1], #4) @ May fault
  530. orrne r3, r3, r7, push #16
  531. strne r3, [r0], #4
  532. ands ip, ip, #3
  533. beq .cfu_2fupi
  534. .cfu_2nowords: mov r3, r7, get_byte_2
  535. teq ip, #0
  536. beq .cfu_finished
  537. cmp ip, #2
  538. strb r3, [r0], #1
  539. movge r3, r7, get_byte_3
  540. strgeb r3, [r0], #1
  541. USER( ldrgtbt r3, [r1], #0) @ May fault
  542. strgtb r3, [r0], #1
  543. b .cfu_finished
  544. .cfu_3fupi: subs r2, r2, #4
  545. addmi ip, r2, #4
  546. bmi .cfu_3nowords
  547. mov r3, r7, pull #24
  548. USER( ldrt r7, [r1], #4) @ May fault
  549. orr r3, r3, r7, push #8
  550. str r3, [r0], #4
  551. mov ip, r1, lsl #32 - PAGE_SHIFT
  552. rsb ip, ip, #0
  553. movs ip, ip, lsr #32 - PAGE_SHIFT
  554. beq .cfu_3fupi
  555. cmp r2, ip
  556. movlt ip, r2
  557. sub r2, r2, ip
  558. subs ip, ip, #16
  559. blt .cfu_3rem8lp
  560. PLD( pld [r1, #12] )
  561. PLD( pld [r0, #12] )
  562. PLD( subs ip, ip, #32 )
  563. PLD( blt .cfu_3cpynopld )
  564. PLD( pld [r1, #28] )
  565. PLD( pld [r0, #28] )
  566. .cfu_3cpy8lp:
  567. PLD( pld [r1, #44] )
  568. PLD( pld [r0, #44] )
  569. .cfu_3cpynopld: mov r3, r7, pull #24
  570. ldmia r1!, {r4 - r7} @ Shouldnt fault
  571. orr r3, r3, r4, push #8
  572. mov r4, r4, pull #24
  573. orr r4, r4, r5, push #8
  574. mov r5, r5, pull #24
  575. orr r5, r5, r6, push #8
  576. mov r6, r6, pull #24
  577. orr r6, r6, r7, push #8
  578. stmia r0!, {r3 - r6}
  579. subs ip, ip, #16
  580. bpl .cfu_3cpy8lp
  581. PLD( cmn ip, #32 )
  582. PLD( bge .cfu_3cpynopld )
  583. PLD( add ip, ip, #32 )
  584. .cfu_3rem8lp: tst ip, #8
  585. movne r3, r7, pull #24
  586. ldmneia r1!, {r4, r7} @ Shouldnt fault
  587. orrne r3, r3, r4, push #8
  588. movne r4, r4, pull #24
  589. orrne r4, r4, r7, push #8
  590. stmneia r0!, {r3 - r4}
  591. tst ip, #4
  592. movne r3, r7, pull #24
  593. USER( ldrnet r7, [r1], #4) @ May fault
  594. orrne r3, r3, r7, push #8
  595. strne r3, [r0], #4
  596. ands ip, ip, #3
  597. beq .cfu_3fupi
  598. .cfu_3nowords: mov r3, r7, get_byte_3
  599. teq ip, #0
  600. beq .cfu_finished
  601. cmp ip, #2
  602. strb r3, [r0], #1
  603. USER( ldrgebt r3, [r1], #1) @ May fault
  604. strgeb r3, [r0], #1
  605. USER( ldrgtbt r3, [r1], #1) @ May fault
  606. strgtb r3, [r0], #1
  607. b .cfu_finished
  608. .section .fixup,"ax"
  609. .align 0
  610. /*
  611. * We took an exception. r0 contains a pointer to
  612. * the byte not copied.
  613. */
  614. 9001: ldr r2, [sp], #4 @ void *to
  615. sub r2, r0, r2 @ bytes copied
  616. ldr r1, [sp], #4 @ unsigned long count
  617. subs r4, r1, r2 @ bytes left to copy
  618. movne r1, r4
  619. blne __memzero
  620. mov r0, r4
  621. LOADREGS(fd,sp!, {r4 - r7, pc})
  622. .previous
  623. /* Prototype: int __arch_clear_user(void *addr, size_t sz)
  624. * Purpose : clear some user memory
  625. * Params : addr - user memory address to clear
  626. * : sz - number of bytes to clear
  627. * Returns : number of bytes NOT cleared
  628. */
  629. ENTRY(__arch_clear_user)
  630. stmfd sp!, {r1, lr}
  631. mov r2, #0
  632. cmp r1, #4
  633. blt 2f
  634. ands ip, r0, #3
  635. beq 1f
  636. cmp ip, #2
  637. USER( strbt r2, [r0], #1)
  638. USER( strlebt r2, [r0], #1)
  639. USER( strltbt r2, [r0], #1)
  640. rsb ip, ip, #4
  641. sub r1, r1, ip @ 7 6 5 4 3 2 1
  642. 1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
  643. USER( strplt r2, [r0], #4)
  644. USER( strplt r2, [r0], #4)
  645. bpl 1b
  646. adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
  647. USER( strplt r2, [r0], #4)
  648. 2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
  649. USER( strnebt r2, [r0], #1)
  650. USER( strnebt r2, [r0], #1)
  651. tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
  652. USER( strnebt r2, [r0], #1)
  653. mov r0, #0
  654. LOADREGS(fd,sp!, {r1, pc})
  655. .section .fixup,"ax"
  656. .align 0
  657. 9001: LOADREGS(fd,sp!, {r0, pc})
  658. .previous