root/arch/microblaze/lib/uaccess_old.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /*
   2  * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
   3  * Copyright (C) 2009 PetaLogix
   4  * Copyright (C) 2007 LynuxWorks, Inc.
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file "COPYING" in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 #include <linux/errno.h>
  12 #include <linux/linkage.h>
  13 #include <asm/page.h>
  14 
  15 /*
  16  * int __strncpy_user(char *to, char *from, int len);
  17  *
  18  * Returns:
  19  *  -EFAULT  for an exception
  20  *  len      if we hit the buffer limit
  21  *  bytes copied
  22  */
  23 
  24         .text
  25 .globl __strncpy_user;
  26 .type  __strncpy_user, @function
  27 .align 4;
  28 __strncpy_user:
  29 
  30         /*
  31          * r5 - to
  32          * r6 - from
  33          * r7 - len
  34          * r3 - temp count
  35          * r4 - temp val
  36          */
  37         beqid   r7,3f
  38         addik   r3,r7,0         /* temp_count = len */
  39 1:
  40         lbu     r4,r6,r0
  41         beqid   r4,2f
  42         sb      r4,r5,r0
  43 
  44         addik   r5,r5,1
  45         addik   r6,r6,1         /* delay slot */
  46 
  47         addik   r3,r3,-1
  48         bnei    r3,1b           /* break on len */
  49 2:
  50         rsubk   r3,r3,r7        /* temp_count = len - temp_count */
  51 3:
  52         rtsd    r15,8
  53         nop
  54         .size   __strncpy_user, . - __strncpy_user
  55 
  56         .section        .fixup, "ax"
  57         .align  2
  58 4:
  59         brid    3b
  60         addik   r3,r0, -EFAULT
  61 
  62         .section        __ex_table, "a"
  63         .word   1b,4b
  64 
  65 /*
  66  * int __strnlen_user(char __user *str, int maxlen);
  67  *
  68  * Returns:
  69  *  0 on error
  70  *  maxlen + 1  if no NUL byte found within maxlen bytes
  71  *  size of the string (including NUL byte)
  72  */
  73 
  74         .text
  75 .globl __strnlen_user;
  76 .type  __strnlen_user, @function
  77 .align 4;
  78 __strnlen_user:
  79         beqid   r6,3f
  80         addik   r3,r6,0
  81 1:
  82         lbu     r4,r5,r0
  83         beqid   r4,2f           /* break on NUL */
  84         addik   r3,r3,-1        /* delay slot */
  85 
  86         bneid   r3,1b
  87         addik   r5,r5,1         /* delay slot */
  88 
  89         addik   r3,r3,-1        /* for break on len */
  90 2:
  91         rsubk   r3,r3,r6
  92 3:
  93         rtsd    r15,8
  94         nop
  95         .size   __strnlen_user, . - __strnlen_user
  96 
  97         .section        .fixup,"ax"
  98 4:
  99         brid    3b
 100         addk    r3,r0,r0
 101 
 102         .section        __ex_table,"a"
 103         .word   1b,4b
 104 
 105 /* Loop unrolling for __copy_tofrom_user */
 106 #define COPY(offset)    \
 107 1:      lwi     r4 , r6, 0x0000 + offset;       \
 108 2:      lwi     r19, r6, 0x0004 + offset;       \
 109 3:      lwi     r20, r6, 0x0008 + offset;       \
 110 4:      lwi     r21, r6, 0x000C + offset;       \
 111 5:      lwi     r22, r6, 0x0010 + offset;       \
 112 6:      lwi     r23, r6, 0x0014 + offset;       \
 113 7:      lwi     r24, r6, 0x0018 + offset;       \
 114 8:      lwi     r25, r6, 0x001C + offset;       \
 115 9:      swi     r4 , r5, 0x0000 + offset;       \
 116 10:     swi     r19, r5, 0x0004 + offset;       \
 117 11:     swi     r20, r5, 0x0008 + offset;       \
 118 12:     swi     r21, r5, 0x000C + offset;       \
 119 13:     swi     r22, r5, 0x0010 + offset;       \
 120 14:     swi     r23, r5, 0x0014 + offset;       \
 121 15:     swi     r24, r5, 0x0018 + offset;       \
 122 16:     swi     r25, r5, 0x001C + offset;       \
 123         .section __ex_table,"a";                \
 124         .word   1b, 33f;                        \
 125         .word   2b, 33f;                        \
 126         .word   3b, 33f;                        \
 127         .word   4b, 33f;                        \
 128         .word   5b, 33f;                        \
 129         .word   6b, 33f;                        \
 130         .word   7b, 33f;                        \
 131         .word   8b, 33f;                        \
 132         .word   9b, 33f;                        \
 133         .word   10b, 33f;                       \
 134         .word   11b, 33f;                       \
 135         .word   12b, 33f;                       \
 136         .word   13b, 33f;                       \
 137         .word   14b, 33f;                       \
 138         .word   15b, 33f;                       \
 139         .word   16b, 33f;                       \
 140         .text
 141 
 142 #define COPY_80(offset) \
 143         COPY(0x00 + offset);\
 144         COPY(0x20 + offset);\
 145         COPY(0x40 + offset);\
 146         COPY(0x60 + offset);
 147 
 148 /*
 149  * int __copy_tofrom_user(char *to, char *from, int len)
 150  * Return:
 151  *   0 on success
 152  *   number of not copied bytes on error
 153  */
 154         .text
 155 .globl __copy_tofrom_user;
 156 .type  __copy_tofrom_user, @function
 157 .align 4;
 158 __copy_tofrom_user:
 159         /*
 160          * r5 - to
 161          * r6 - from
 162          * r7, r3 - count
 163          * r4 - tempval
 164          */
 165         beqid   r7, 0f /* zero size is not likely */
 166         or      r3, r5, r6 /* find if is any to/from unaligned */
 167         or      r3, r3, r7 /* find if count is unaligned */
 168         andi    r3, r3, 0x3 /* mask last 3 bits */
 169         bneid   r3, bu1 /* if r3 is not zero then byte copying */
 170         or      r3, r0, r0
 171 
 172         rsubi   r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
 173         beqid   r3, page;
 174         or      r3, r0, r0
 175 
 176 w1:     lw      r4, r6, r3 /* at least one 4 byte copy */
 177 w2:     sw      r4, r5, r3
 178         addik   r7, r7, -4
 179         bneid   r7, w1
 180         addik   r3, r3, 4
 181         addik   r3, r7, 0
 182         rtsd    r15, 8
 183         nop
 184 
 185         .section        __ex_table,"a"
 186         .word   w1, 0f;
 187         .word   w2, 0f;
 188         .text
 189 
 190 .align 4 /* Alignment is important to keep icache happy */
 191 page:   /* Create room on stack and save registers for storign values */
 192         addik   r1, r1, -40
 193         swi     r5, r1, 0
 194         swi     r6, r1, 4
 195         swi     r7, r1, 8
 196         swi     r19, r1, 12
 197         swi     r20, r1, 16
 198         swi     r21, r1, 20
 199         swi     r22, r1, 24
 200         swi     r23, r1, 28
 201         swi     r24, r1, 32
 202         swi     r25, r1, 36
 203 loop:   /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
 204         /* Loop unrolling to get performance boost */
 205         COPY_80(0x000);
 206         COPY_80(0x080);
 207         COPY_80(0x100);
 208         COPY_80(0x180);
 209         /* copy loop */
 210         addik   r6, r6, 0x200
 211         addik   r7, r7, -0x200
 212         bneid   r7, loop
 213         addik   r5, r5, 0x200
 214 
 215         /* Restore register content */
 216         lwi     r5, r1, 0
 217         lwi     r6, r1, 4
 218         lwi     r7, r1, 8
 219         lwi     r19, r1, 12
 220         lwi     r20, r1, 16
 221         lwi     r21, r1, 20
 222         lwi     r22, r1, 24
 223         lwi     r23, r1, 28
 224         lwi     r24, r1, 32
 225         lwi     r25, r1, 36
 226         addik   r1, r1, 40
 227         /* return back */
 228         addik   r3, r0, 0
 229         rtsd    r15, 8
 230         nop
 231 
 232 /* Fault case - return temp count */
 233 33:
 234         addik   r3, r7, 0
 235         /* Restore register content */
 236         lwi     r5, r1, 0
 237         lwi     r6, r1, 4
 238         lwi     r7, r1, 8
 239         lwi     r19, r1, 12
 240         lwi     r20, r1, 16
 241         lwi     r21, r1, 20
 242         lwi     r22, r1, 24
 243         lwi     r23, r1, 28
 244         lwi     r24, r1, 32
 245         lwi     r25, r1, 36
 246         addik   r1, r1, 40
 247         /* return back */
 248         rtsd    r15, 8
 249         nop
 250 
 251 .align 4 /* Alignment is important to keep icache happy */
 252 bu1:    lbu     r4,r6,r3
 253 bu2:    sb      r4,r5,r3
 254         addik   r7,r7,-1
 255         bneid   r7,bu1
 256         addik   r3,r3,1         /* delay slot */
 257 0:
 258         addik   r3,r7,0
 259         rtsd    r15,8
 260         nop
 261         .size   __copy_tofrom_user, . - __copy_tofrom_user
 262 
 263         .section        __ex_table,"a"
 264         .word   bu1, 0b;
 265         .word   bu2, 0b;
 266         .text

/* [<][>][^][v][top][bottom][index][help] */