lusercopy.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * User Space Access Routines
  3. *
  4. * Copyright (C) 2000-2002 Hewlett-Packard (John Marvin)
  5. * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org>
  6. * Copyright (C) 2001 Matthieu Delahaye <delahaym at esiee.fr>
  7. * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
  8. *
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2, or (at your option)
  13. * any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * These routines still have plenty of room for optimization
  26. * (word & doubleword load/store, dual issue, store hints, etc.).
  27. */
  28. /*
  29. * The following routines assume that space register 3 (sr3) contains
  30. * the space id associated with the current users address space.
  31. */
  32. .text
  33. #include <asm/assembly.h>
  34. #include <asm/errno.h>
  35. /*
  36. * get_sr gets the appropriate space value into
  37. * sr1 for kernel/user space access, depending
  38. * on the flag stored in the task structure.
  39. */
  40. .macro get_sr
  41. mfctl %cr30,%r1
  42. ldw TI_SEGMENT(%r1),%r22
  43. mfsp %sr3,%r1
  44. or,<> %r22,%r0,%r0
  45. copy %r0,%r1
  46. mtsp %r1,%sr1
  47. .endm
  48. .macro fixup_branch lbl
  49. ldil L%\lbl, %r1
  50. ldo R%\lbl(%r1), %r1
  51. bv %r0(%r1)
  52. .endm
  53. /*
  54. * long lstrncpy_from_user(char *dst, const char *src, long n)
  55. *
  56. * Returns -EFAULT if exception before terminator,
  57. * N if the entire buffer filled,
  58. * otherwise strlen (i.e. excludes zero byte)
  59. */
  60. .export lstrncpy_from_user,code
  61. lstrncpy_from_user:
  62. .proc
  63. .callinfo NO_CALLS
  64. .entry
  65. comib,= 0,%r24,$lsfu_done
  66. copy %r24,%r23
  67. get_sr
  68. 1: ldbs,ma 1(%sr1,%r25),%r1
  69. $lsfu_loop:
  70. stbs,ma %r1,1(%r26)
  71. comib,=,n 0,%r1,$lsfu_done
  72. addib,<>,n -1,%r24,$lsfu_loop
  73. 2: ldbs,ma 1(%sr1,%r25),%r1
  74. $lsfu_done:
  75. sub %r23,%r24,%r28
  76. $lsfu_exit:
  77. bv %r0(%r2)
  78. nop
  79. .exit
  80. .section .fixup,"ax"
  81. 3: fixup_branch $lsfu_exit
  82. ldi -EFAULT,%r28
  83. .previous
  84. .section __ex_table,"aw"
  85. #ifdef __LP64__
  86. .dword 1b,3b
  87. .dword 2b,3b
  88. #else
  89. .word 1b,3b
  90. .word 2b,3b
  91. #endif
  92. .previous
  93. .procend
  94. /*
  95. * unsigned long lclear_user(void *to, unsigned long n)
  96. *
  97. * Returns 0 for success.
  98. * otherwise, returns number of bytes not transferred.
  99. */
  100. .export lclear_user,code
  101. lclear_user:
  102. .proc
  103. .callinfo NO_CALLS
  104. .entry
  105. comib,=,n 0,%r25,$lclu_done
  106. get_sr
  107. $lclu_loop:
  108. addib,<> -1,%r25,$lclu_loop
  109. 1: stbs,ma %r0,1(%sr1,%r26)
  110. $lclu_done:
  111. bv %r0(%r2)
  112. copy %r25,%r28
  113. .exit
  114. .section .fixup,"ax"
  115. 2: fixup_branch $lclu_done
  116. ldo 1(%r25),%r25
  117. .previous
  118. .section __ex_table,"aw"
  119. #ifdef __LP64__
  120. .dword 1b,2b
  121. #else
  122. .word 1b,2b
  123. #endif
  124. .previous
  125. .procend
  126. /*
  127. * long lstrnlen_user(char *s, long n)
  128. *
  129. * Returns 0 if exception before zero byte or reaching N,
  130. * N+1 if N would be exceeded,
  131. * else strlen + 1 (i.e. includes zero byte).
  132. */
  133. .export lstrnlen_user,code
  134. lstrnlen_user:
  135. .proc
  136. .callinfo NO_CALLS
  137. .entry
  138. comib,= 0,%r25,$lslen_nzero
  139. copy %r26,%r24
  140. get_sr
  141. 1: ldbs,ma 1(%sr1,%r26),%r1
  142. $lslen_loop:
  143. comib,=,n 0,%r1,$lslen_done
  144. addib,<> -1,%r25,$lslen_loop
  145. 2: ldbs,ma 1(%sr1,%r26),%r1
  146. $lslen_done:
  147. bv %r0(%r2)
  148. sub %r26,%r24,%r28
  149. .exit
  150. $lslen_nzero:
  151. b $lslen_done
  152. ldo 1(%r26),%r26 /* special case for N == 0 */
  153. .section .fixup,"ax"
  154. 3: fixup_branch $lslen_done
  155. copy %r24,%r26 /* reset r26 so 0 is returned on fault */
  156. .previous
  157. .section __ex_table,"aw"
  158. #ifdef __LP64__
  159. .dword 1b,3b
  160. .dword 2b,3b
  161. #else
  162. .word 1b,3b
  163. .word 2b,3b
  164. #endif
  165. .previous
  166. .procend
  167. .end