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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: U3copy_from_user.S,v 1.3.2.1 2002/01/15 07:17:47 davem Exp $
  2.  * U3memcpy.S: UltraSparc-III optimized copy from userspace.
  3.  *
  4.  * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
  5.  */
  6. #ifdef __KERNEL__
  7. #include <asm/visasm.h>
  8. #include <asm/asi.h>
  9. #include <asm/dcu.h>
  10. #include <asm/spitfire.h>
  11. #undef SMALL_COPY_USES_FPU
  12. #define EXNV(x,y,a,b)
  13. 98: x,y;
  14. .section .fixup;
  15. .align 4;
  16. 99: VISExitHalf;
  17. ba U3cfu_fixup;
  18.  a, b, %o1;
  19. .section __ex_table;
  20. .align 4;
  21. .word 98b, 99b;
  22. .text;
  23. .align 4;
  24. #define EX(x,y,a,b)
  25. 98: x,y;
  26. .section .fixup;
  27. .align 4;
  28. 99: VISExitHalf;
  29. ba U3cfu_fixup;
  30.  a, b, %o1;
  31. .section __ex_table;
  32. .align 4;
  33. .word 98b, 99b;
  34. .text;
  35. .align 4;
  36. #define EX2(x,y)
  37. 98: x,y;
  38. .section .fixup;
  39. .align 4;
  40. 99: VISExitHalf;
  41. and %o2, (0x40 - 1), %o1;
  42. add %o1, %o4, %o1;
  43. ba U3cfu_fixup;
  44.  add %o1, 0x1c0, %o1;
  45. .section __ex_table;
  46. .align 4;
  47. .word 98b, 99b;
  48. .text;
  49. .align 4;
  50. #define EX3(x,y)
  51. 98: x,y;
  52. .section .fixup;
  53. .align 4;
  54. 99: VISExitHalf;
  55. and %o2, (0x40 - 1), %o1;
  56. sll %g3, 6, %g3;
  57. add %o1, 0x80, %o1;
  58. ba U3cfu_fixup;
  59.  add %o1, %g3, %o1;
  60. .section __ex_table;
  61. .align 4;
  62. .word 98b, 99b;
  63. .text;
  64. .align 4;
  65. #define EX4(x,y)
  66. 98: x,y;
  67. .section .fixup;
  68. .align 4;
  69. 99: VISExitHalf;
  70. and %o2, (0x40 - 1), %o1;
  71. add %o1, 0x40, %o1;
  72. ba U3cfu_fixup;
  73.  add %o1, %g3, %o1;
  74. .section __ex_table;
  75. .align 4;
  76. .word 98b, 99b;
  77. .text;
  78. .align 4;
  79. #else
  80. #define ASI_BLK_P 0xf0
  81. #define FPRS_FEF  0x04
  82. #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
  83. #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
  84. #define SMALL_COPY_USES_FPU
  85. #define EXNV(x,y,a,b) x,y;
  86. #define EX(x,y,a,b) x,y;
  87. #define EX2(x,y) x,y;
  88. #define EX3(x,y) x,y;
  89. #define EX4(x,y) x,y;
  90. #endif
  91. /* Special/non-trivial issues of this code:
  92.  *
  93.  * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
  94.  * 2) Only low 32 FPU registers are used so that only the
  95.  *    lower half of the FPU register set is dirtied by this
  96.  *    code.  This is especially important in the kernel.
  97.  * 3) This code never prefetches cachelines past the end
  98.  *    of the source buffer.
  99.  */
  100. .text
  101. .align 32
  102. /* The cheetah's flexible spine, oversized liver, enlarged heart,
  103.  * slender muscular body, and claws make it the swiftest hunter
  104.  * in Africa and the fastest animal on land.  Can reach speeds
  105.  * of up to 2.4GB per second.
  106.  */
  107. .globl U3copy_from_user
  108. U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */
  109. #ifndef __KERNEL__
  110. /* Save away original 'dst' for memcpy return value. */
  111. mov %o0, %g3 ! A0 Group
  112. #endif
  113. /* Anything to copy at all? */
  114. cmp %o2, 0 ! A1
  115. ble,pn %icc, U3copy_from_user_short_ret! BR
  116. /* Extremely small copy? */
  117.  cmp %o2, 31 ! A0 Group
  118. ble,pn %icc, U3copy_from_user_short ! BR
  119. /* Large enough to use unrolled prefetch loops? */
  120.  cmp %o2, 0x100 ! A1
  121. bge,a,pt %icc, U3copy_from_user_enter ! BR Group
  122.  andcc %o0, 0x3f, %g2 ! A0
  123. ba,pt %xcc, U3copy_from_user_toosmall ! BR Group
  124.  andcc %o0, 0x7, %g2 ! A0
  125. .align 32
  126. U3copy_from_user_short:
  127. /* Copy %o2 bytes from src to dst, one byte at a time. */
  128. EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS Group
  129. add %o1, 0x1, %o1 ! A0
  130. add %o0, 0x1, %o0 ! A1
  131. subcc %o2, 1, %o2 ! A0 Group
  132. bg,pt %icc, U3copy_from_user_short ! BR
  133.  stb %o3, [%o0 + -1] ! MS Group (1-cycle stall)
  134. U3copy_from_user_short_ret:
  135. #ifdef __KERNEL__
  136. retl ! BR Group (0-4 cycle stall)
  137.  clr %o0 ! A0
  138. #else
  139. retl ! BR Group (0-4 cycle stall)
  140.  mov %g3, %o0 ! A0
  141. #endif
  142. /* Here len >= (6 * 64) and condition codes reflect execution
  143.  * of "andcc %o0, 0x7, %g2", done by caller.
  144.  */
  145. .align 64
  146. U3copy_from_user_enter:
  147. /* Is 'dst' already aligned on an 64-byte boundary? */
  148. be,pt %xcc, 2f ! BR
  149. /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
  150.  * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
  151.  * subtract this from 'len'.
  152.  */
  153.  sub %g2, 0x40, %g2 ! A0 Group
  154. sub %g0, %g2, %g2 ! A0 Group
  155. sub %o2, %g2, %o2 ! A0 Group
  156. /* Copy %g2 bytes from src to dst, one byte at a time. */
  157. 1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group)
  158. add %o1, 0x1, %o1 ! A1
  159. add %o0, 0x1, %o0 ! A0 Group
  160. subcc %g2, 0x1, %g2 ! A1
  161. bg,pt %icc, 1b ! BR Group
  162.  stb %o3, [%o0 + -1] ! MS Group
  163. 2: VISEntryHalf ! MS+MS
  164. and %o1, 0x7, %g1 ! A1
  165. ba,pt %xcc, U3copy_from_user_begin ! BR
  166.  alignaddr %o1, %g0, %o1 ! MS       (Break-after)
  167. .align 64
  168. U3copy_from_user_begin:
  169. #ifdef __KERNEL__
  170. .globl U3copy_from_user_nop_1_6
  171. U3copy_from_user_nop_1_6:
  172. ldxa [%g0] ASI_DCU_CONTROL_REG, %g3
  173. sethi %uhi(DCU_PE), %o3
  174. sllx %o3, 32, %o3
  175. or %g3, %o3, %o3
  176. stxa %o3, [%g0] ASI_DCU_CONTROL_REG ! Enable P-cache
  177. membar #Sync
  178. #endif
  179. prefetcha [%o1 + 0x000] %asi, #one_read ! MS Group1
  180. prefetcha [%o1 + 0x040] %asi, #one_read ! MS Group2
  181. andn %o2, (0x40 - 1), %o4 ! A0
  182. prefetcha [%o1 + 0x080] %asi, #one_read ! MS Group3
  183. cmp %o4, 0x140 ! A0
  184. prefetcha [%o1 + 0x0c0] %asi, #one_read ! MS Group4
  185. EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) ! MS Group5 (%f0 results at G8)
  186. bge,a,pt %icc, 1f ! BR
  187. prefetcha [%o1 + 0x100] %asi, #one_read ! MS Group6
  188. 1: EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) ! AX        (%f2 results at G9)
  189. cmp %o4, 0x180 ! A1
  190. bge,a,pt %icc, 1f ! BR
  191.  prefetcha [%o1 + 0x140] %asi, #one_read ! MS Group7
  192. 1: EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) ! AX        (%f4 results at G10)
  193. cmp %o4, 0x1c0 ! A1
  194. bge,a,pt %icc, 1f ! BR
  195.  prefetcha [%o1 + 0x180] %asi, #one_read ! MS Group8
  196. 1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12)
  197. EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) ! AX        (%f6 results at G12)
  198. faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13)
  199. EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) ! MS         (%f8 results at G13)
  200. faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15)
  201. EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS (%f10 results at G15)
  202. faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16)
  203. EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS (%f12 results at G16)
  204. faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18)
  205. EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS (%f14 results at G18)
  206. faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19)
  207. EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) ! MS (%f0 results at G19)
  208. /* We only use the first loop if len > (7 * 64). */
  209. subcc %o4, 0x1c0, %o4 ! A0 Group17
  210. bg,pt %icc, U3copy_from_user_loop1 ! BR
  211.  add %o1, 0x40, %o1 ! A1
  212. add %o4, 0x140, %o4 ! A0 Group18
  213. ba,pt %xcc, U3copy_from_user_loop2 ! BR
  214.  srl %o4, 6, %o3 ! A0 Group19
  215. nop
  216. nop
  217. nop
  218. nop
  219. nop
  220. nop
  221. nop
  222. /* This loop performs the copy and queues new prefetches.
  223.  * We drop into the second loop when len <= (5 * 64).  Note
  224.  * that this (5 * 64) factor has been subtracted from len
  225.  * already.
  226.  */
  227. U3copy_from_user_loop1:
  228. EX2(ldda [%o1 + 0x008] %asi, %f2) ! MS Group2 (%f2 results at G5)
  229. faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5)
  230. EX2(ldda [%o1 + 0x010] %asi, %f4) ! MS Group3 (%f4 results at G6)
  231. faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7)
  232. stda %f16, [%o0] ASI_BLK_P ! MS
  233. EX2(ldda [%o1 + 0x018] %asi, %f6) ! AX (%f6 results at G7)
  234. faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall)
  235. EX2(ldda [%o1 + 0x020] %asi, %f8) ! MS         (%f8 results at G15)
  236. faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16)
  237. EX2(ldda [%o1 + 0x028] %asi, %f10) ! MS (%f10 results at G16)
  238. faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17)
  239. EX2(ldda [%o1 + 0x030] %asi, %f12) ! MS (%f12 results at G17)
  240. faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18)
  241. EX2(ldda [%o1 + 0x038] %asi, %f14) ! MS (%f14 results at G18)
  242. faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19)
  243. EX2(ldda [%o1 + 0x040] %asi, %f0) ! AX (%f0 results at G19)
  244. prefetcha [%o1 + 0x180] %asi, #one_read ! MS
  245. faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20)
  246. subcc %o4, 0x40, %o4 ! A0
  247. add %o1, 0x40, %o1 ! A1
  248. bg,pt %xcc, U3copy_from_user_loop1 ! BR
  249.  add %o0, 0x40, %o0 ! A0 Group18
  250. U3copy_from_user_loop2_enter:
  251. mov 5, %o3 ! A1
  252. /* This loop performs on the copy, no new prefetches are
  253.  * queued.  We do things this way so that we do not perform
  254.  * any spurious prefetches past the end of the src buffer.
  255.  */
  256. U3copy_from_user_loop2:
  257. EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS
  258. faligndata %f12, %f14, %f28 ! FGA Group2
  259. EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS
  260. faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall)
  261. stda %f16, [%o0] ASI_BLK_P ! MS
  262. EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX
  263. faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall)
  264. EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS
  265. faligndata %f2, %f4, %f18 ! FGA Group13
  266. EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS
  267. faligndata %f4, %f6, %f20 ! FGA Group14
  268. EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS
  269. faligndata %f6, %f8, %f22 ! FGA Group15
  270. EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS
  271. faligndata %f8, %f10, %f24 ! FGA Group16
  272. EX3(ldda [%o1 + 0x040] %asi, %f0) ! AX
  273. faligndata %f10, %f12, %f26 ! FGA Group17
  274. subcc %o3, 0x01, %o3 ! A0
  275. add %o1, 0x40, %o1 ! A1
  276. bg,pt %xcc, U3copy_from_user_loop2 ! BR
  277.  add %o0, 0x40, %o0 ! A0 Group18
  278. /* Finally we copy the last full 64-byte block. */
  279. U3copy_from_user_loopfini:
  280. EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS
  281. faligndata %f12, %f14, %f28 ! FGA
  282. EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS Group19
  283. faligndata %f14, %f0, %f30 ! FGA
  284. stda %f16, [%o0] ASI_BLK_P ! MS Group20
  285. EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX
  286. faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall)
  287. EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS
  288. faligndata %f2, %f4, %f18 ! FGA Group12
  289. EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS
  290. faligndata %f4, %f6, %f20 ! FGA Group13
  291. EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS
  292. faligndata %f6, %f8, %f22 ! FGA Group14
  293. EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS
  294. faligndata %f8, %f10, %f24 ! FGA Group15
  295. cmp %g1, 0 ! A0
  296. be,pt %icc, 1f ! BR
  297.  add %o0, 0x40, %o0 ! A1
  298. EX4(ldda [%o1 + 0x040] %asi, %f0) ! MS
  299. 1: faligndata %f10, %f12, %f26 ! FGA Group16
  300. faligndata %f12, %f14, %f28 ! FGA Group17
  301. faligndata %f14, %f0, %f30 ! FGA Group18
  302. stda %f16, [%o0] ASI_BLK_P ! MS
  303. add %o0, 0x40, %o0 ! A0
  304. add %o1, 0x40, %o1 ! A1
  305. #ifdef __KERNEL__
  306. .globl U3copy_from_user_nop_2_3
  307. U3copy_from_user_nop_2_3:
  308. mov PRIMARY_CONTEXT, %o3
  309. stxa %g0, [%o3] ASI_DMMU ! Flush P-cache
  310. stxa %g3, [%g0] ASI_DCU_CONTROL_REG ! Disable P-cache
  311. #endif
  312. membar #Sync ! MS Group26 (7-cycle stall)
  313. /* Now we copy the (len modulo 64) bytes at the end.
  314.  * Note how we borrow the %f0 loaded above.
  315.  *
  316.  * Also notice how this code is careful not to perform a
  317.  * load past the end of the src buffer just like similar
  318.  * code found in U3copy_from_user_toosmall processing.
  319.  */
  320. U3copy_from_user_loopend:
  321. and %o2, 0x3f, %o2 ! A0 Group
  322. andcc %o2, 0x38, %g2 ! A0 Group
  323. be,pn %icc, U3copy_from_user_endcruft ! BR
  324.  subcc %g2, 0x8, %g2 ! A1
  325. be,pn %icc, U3copy_from_user_endcruft ! BR Group
  326.  cmp %g1, 0 ! A0
  327. be,a,pt %icc, 1f ! BR Group
  328.  EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) ! MS
  329. 1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) ! MS Group
  330. add %o1, 0x8, %o1 ! A0
  331. sub %o2, 0x8, %o2 ! A1
  332. subcc %g2, 0x8, %g2 ! A0 Group
  333. faligndata %f0, %f2, %f8 ! FGA Group
  334. std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX)
  335. be,pn %icc, U3copy_from_user_endcruft ! BR
  336.  add %o0, 0x8, %o0 ! A0
  337. EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) ! MS Group
  338. add %o1, 0x8, %o1 ! A0
  339. sub %o2, 0x8, %o2 ! A1
  340. subcc %g2, 0x8, %g2 ! A0 Group
  341. faligndata %f2, %f0, %f8 ! FGA
  342. std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX)
  343. bne,pn %icc, 1b ! BR
  344.  add %o0, 0x8, %o0 ! A0 Group
  345. /* If anything is left, we copy it one byte at a time.
  346.  * Note that %g1 is (src & 0x3) saved above before the
  347.  * alignaddr was performed.
  348.  */
  349. U3copy_from_user_endcruft:
  350. cmp %o2, 0
  351. add %o1, %g1, %o1
  352. VISExitHalf
  353. be,pn %icc, U3copy_from_user_short_ret
  354.  nop
  355. ba,a,pt %xcc, U3copy_from_user_short
  356. /* If we get here, then 32 <= len < (6 * 64) */
  357. U3copy_from_user_toosmall:
  358. #ifdef SMALL_COPY_USES_FPU
  359. /* Is 'dst' already aligned on an 8-byte boundary? */
  360. be,pt %xcc, 2f ! BR Group
  361. /* Compute abs((dst & 7) - 8) into %g2.  This is the number
  362.  * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
  363.  * subtract this from 'len'.
  364.  */
  365.  sub %g2, 0x8, %g2 ! A0
  366. sub %g0, %g2, %g2 ! A0 Group (reg-dep)
  367. sub %o2, %g2, %o2 ! A0 Group (reg-dep)
  368. /* Copy %g2 bytes from src to dst, one byte at a time. */
  369. 1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) (%o3 in 3 cycles)
  370. add %o1, 0x1, %o1 ! A1
  371. add %o0, 0x1, %o0 ! A0 Group
  372. subcc %g2, 0x1, %g2 ! A1
  373. bg,pt %icc, 1b ! BR Group
  374.  stb %o3, [%o0 + -1] ! MS Group
  375. 2: VISEntryHalf ! MS+MS
  376. /* Compute (len - (len % 8)) into %g2.  This is guarenteed
  377.  * to be nonzero.
  378.  */
  379. andn %o2, 0x7, %g2 ! A0 Group
  380. /* You may read this and believe that it allows reading
  381.  * one 8-byte longword past the end of src.  It actually
  382.  * does not, as %g2 is subtracted as loads are done from
  383.  * src, so we always stop before running off the end.
  384.  * Also, we are guarenteed to have at least 0x10 bytes
  385.  * to move here.
  386.  */
  387. sub %g2, 0x8, %g2 ! A0 Group (reg-dep)
  388. alignaddr %o1, %g0, %g1 ! MS       (Break-after)
  389. EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group (1-cycle stall)
  390. add %g1, 0x8, %g1 ! A0
  391. 1: EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0) ! MS Group
  392. add %g1, 0x8, %g1 ! A0
  393. sub %o2, 0x8, %o2 ! A1
  394. subcc %g2, 0x8, %g2 ! A0 Group
  395. faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall)
  396. std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall)
  397. add %o1, 0x8, %o1 ! A0
  398. be,pn %icc, 2f ! BR
  399.  add %o0, 0x8, %o0 ! A1
  400. EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group
  401. add %g1, 0x8, %g1 ! A0
  402. sub %o2, 0x8, %o2 ! A1
  403. subcc %g2, 0x8, %g2 ! A0 Group
  404. faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall)
  405. std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall)
  406. add %o1, 0x8, %o1 ! A0
  407. bne,pn %icc, 1b ! BR
  408.  add %o0, 0x8, %o0 ! A1
  409. /* Nothing left to copy? */
  410. 2: cmp %o2, 0 ! A0 Group
  411. VISExitHalf ! A0+MS
  412. be,pn %icc, U3copy_from_user_short_ret! BR Group
  413.  nop ! A0
  414. ba,a,pt %xcc, U3copy_from_user_short ! BR Group
  415. #else /* !(SMALL_COPY_USES_FPU) */
  416. xor %o1, %o0, %g2
  417. andcc %g2, 0x7, %g0
  418. bne,pn %icc, U3copy_from_user_short
  419.  andcc %o1, 0x7, %g2
  420. be,pt %xcc, 2f
  421.  sub %g2, 0x8, %g2
  422. sub %g0, %g2, %g2
  423. sub %o2, %g2, %o2
  424. 1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
  425. add %o1, 0x1, %o1
  426. add %o0, 0x1, %o0
  427. subcc %g2, 0x1, %g2
  428. bg,pt %icc, 1b
  429.  stb %o3, [%o0 + -1]
  430. 2: andn %o2, 0x7, %g2
  431. sub %o2, %g2, %o2
  432. 3: EXNV(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2)
  433. add %o1, 0x8, %o1
  434. add %o0, 0x8, %o0
  435. subcc %g2, 0x8, %g2
  436. bg,pt %icc, 3b
  437.  stx %o3, [%o0 + -8]
  438. cmp %o2, 0
  439. bne,pn %icc, U3copy_from_user_short
  440.  nop
  441. ba,a,pt %xcc, U3copy_from_user_short_ret
  442. #endif /* !(SMALL_COPY_USES_FPU) */
  443. #ifdef __KERNEL__
  444. .globl U3cfu_fixup
  445. U3cfu_fixup:
  446. /* Since this is copy_from_user(), zero out the rest of the
  447.  * kernel buffer.
  448.  */
  449. cmp %o1, 0
  450. ble,pn %icc, 2f
  451.  mov %o1, %g2
  452. 1: subcc %g2, 1, %g2
  453. stb %g0, [%o0]
  454. bne,pt %icc, 1b
  455.  add %o0, 1, %o0
  456. 2: retl
  457.  mov %o1, %o0
  458. #endif