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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*------------------------------------------------------------------------------
  2.  * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
  3.  *
  4.  * Assembly Language User Access Routines
  5.  *  Copyright (C) 2000 Hewlett-Packard (John Marvin)
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2, or (at your option)
  10.  *    any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21. /*
  22.  * These routines still have plenty of room for optimization
  23.  * (word & doubleword load/store, dual issue, store hints, etc.).
  24.  */
  25. /*
  26.  * The following routines assume that space register 3 (sr3) contains
  27.  * the space id associated with the current users address space.
  28.  */
  29. .level 1.1
  30. .text
  31. #include <asm/assembly.h>
  32. #include <asm/errno.h>
  33. /*
  34.  * get_sr gets the appropriate space value into
  35.  * sr1 for kernel/user space access, depending
  36.  * on the flag stored in the task structure.
  37.  */
  38. /* FIXME! depi below has hardcoded idea of kernel stack size */
  39. .macro  get_sr
  40. copy        %r30,%r1        ;! Get task structure
  41. depi        0,31,14,%r1     ;! into r1
  42. ldw         TASK_SEGMENT(%r1),%r22
  43. mfsp        %sr3,%r1
  44. or,<>       %r22,%r0,%r0
  45. copy        %r0,%r1
  46. mtsp        %r1,%sr1
  47. .endm
  48. /*
  49.  * unsigned long
  50.  * lcopy_to_user(void *to, const void *from, unsigned long n)
  51.  *
  52.  * Returns 0 for success.
  53.  * otherwise, returns number of bytes not transferred.
  54.  */
  55. .export lcopy_to_user,code
  56. lcopy_to_user:
  57. .proc
  58. .callinfo NO_CALLS
  59. .entry
  60. comib,=,n   0,%r24,$lctu_done
  61. get_sr
  62. $lctu_loop:
  63. ldbs,ma     1(%r25),%r1
  64. addib,<>    -1,%r24,$lctu_loop
  65. 1:      stbs,ma     %r1,1(%sr1,%r26)
  66. $lctu_done:
  67. bv          %r0(%r2)
  68. copy        %r24,%r28
  69. .exit
  70. 2:      b $lctu_done
  71. ldo         1(%r24),%r24
  72. .section __ex_table,"a"
  73. .word       1b,(2b-1b)
  74. .previous
  75. .procend
  76. /*
  77.  * unsigned long
  78.  * lcopy_from_user(void *to, const void *from, unsigned long n)
  79.  *
  80.  * Returns 0 for success.
  81.  * otherwise, returns number of bytes not transferred.
  82.  *
  83.  * NOTE: This routine will also zero any bytes in the
  84.  *       destination that were not copied due to a fault.
  85.  *
  86.  */
  87. .export lcopy_from_user,code
  88. lcopy_from_user:
  89. .proc
  90. .callinfo NO_CALLS
  91. .entry
  92. comib,=,n   0,%r24,$lcfu_done
  93. get_sr
  94. $lcfu_loop:
  95. 1:      ldbs,ma     1(%sr1,%r25),%r1
  96. addib,<>    -1,%r24,$lcfu_loop
  97. stbs,ma     %r1,1(%r26)
  98. $lcfu_done:
  99. bv          %r0(%r2)
  100. copy        %r24,%r28
  101. .exit
  102. 2:      copy        %r24,%r23
  103. $lcfu_zero_loop:
  104. addib,<>    -1,%r23,$lcfu_zero_loop
  105. stbs,ma     %r0,1(%r26)
  106. b           $lcfu_done
  107. nop
  108. .section __ex_table,"a"
  109. .word       1b,(2b-1b)
  110. .previous
  111. .procend
  112. /*
  113.  * long lstrncpy_from_user(char *dst, const char *src, long n)
  114.  *
  115.  * Returns -EFAULT if exception before terminator,
  116.  *         N if the entire buffer filled,
  117.  *         otherwise strlen + 1 (i.e. includes zero byte)
  118.  */
  119. .export lstrncpy_from_user,code
  120. lstrncpy_from_user:
  121. .proc
  122. .callinfo NO_CALLS
  123. .entry
  124. comib,=     0,%r24,$lsfu_done
  125. copy        %r26,%r23
  126. get_sr
  127. 1:      ldbs,ma     1(%sr1,%r25),%r1
  128. $lsfu_loop:
  129. stbs,ma     %r1,1(%r26)
  130. comib,=,n   0,%r1,$lsfu_done
  131. addib,<>,n  -1,%r24,$lsfu_loop
  132. 2:      ldbs,ma     1(%sr1,%r25),%r1
  133. $lsfu_done:
  134. sub         %r26,%r23,%r28
  135. $lsfu_exit:
  136. bv          %r0(%r2)
  137. nop
  138. .exit
  139. 3:      b           $lsfu_exit
  140. ldi         -EFAULT,%r28
  141. .section __ex_table,"a"
  142. .word       1b,(3b-1b)
  143. .word       2b,(2b-1b)
  144. .previous
  145. .procend
  146. /*
  147.  * unsigned long lclear_user(void *to, unsigned long n)
  148.  *
  149.  * Returns 0 for success.
  150.  * otherwise, returns number of bytes not transferred.
  151.  */
  152. .export lclear_user,code
  153. lclear_user:
  154. .proc
  155. .callinfo NO_CALLS
  156. .entry
  157. comib,=,n   0,%r25,$lclu_done
  158. get_sr
  159. $lclu_loop:
  160. addib,<>    -1,%r25,$lclu_loop
  161. 1:      stbs,ma     %r0,1(%sr1,%r26)
  162. $lclu_done:
  163. bv          %r0(%r2)
  164. copy        %r25,%r28
  165. .exit
  166. 2:      b $lclu_done
  167. ldo        1(%r25),%r25
  168. .section __ex_table,"a"
  169. .word       1b,(2b-1b)
  170. .previous
  171. .procend
  172. /*
  173.  * long lstrnlen_user(char *s, long n)
  174.  *
  175.  * Returns 0 if exception before zero byte or reaching N,
  176.  *         N+1 if N would be exceeded,
  177.  *         else strlen + 1 (i.e. includes zero byte).
  178.  */
  179. .export lstrnlen_user,code
  180. lstrnlen_user:
  181. .proc
  182. .callinfo NO_CALLS
  183. .entry
  184. comib,=     0,%r25,$lslen_nzero
  185. copy     %r26,%r24
  186. get_sr
  187. 1:      ldbs,ma     1(%sr1,%r26),%r1
  188. $lslen_loop:
  189. comib,=,n   0,%r1,$lslen_done
  190. addib,<>    -1,%r25,$lslen_loop
  191. 2:      ldbs,ma     1(%sr1,%r26),%r1
  192. $lslen_done:
  193. bv          %r0(%r2)
  194. sub     %r26,%r24,%r28
  195. .exit
  196. $lslen_nzero:
  197. b           $lslen_done
  198. ldo         1(%r26),%r26 /* special case for N == 0 */
  199. 3:      b           $lslen_done
  200. copy        %r24,%r26    /* reset r26 so 0 is returned on fault */
  201. .section __ex_table,"a"
  202. .word       1b,(3b-1b)
  203. .word       2b,(2b-1b)
  204. .previous
  205. .procend
  206. .end