Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  *
0005  * vineetg: June 2010
0006  *    -__clear_user( ) called multiple times during elf load was byte loop
0007  *    converted to do as much word clear as possible.
0008  *
0009  * vineetg: Dec 2009
0010  *    -Hand crafted constant propagation for "constant" copy sizes
0011  *    -stock kernel shrunk by 33K at -O3
0012  *
0013  * vineetg: Sept 2009
0014  *    -Added option to (UN)inline copy_(to|from)_user to reduce code sz
0015  *    -kernel shrunk by 200K even at -O3 (gcc 4.2.1)
0016  *    -Enabled when doing -Os
0017  *
0018  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
0019  */
0020 
0021 #ifndef _ASM_ARC_UACCESS_H
0022 #define _ASM_ARC_UACCESS_H
0023 
0024 #include <linux/string.h>   /* for generic string functions */
0025 
0026 /*********** Single byte/hword/word copies ******************/
0027 
0028 #define __get_user_fn(sz, u, k)                 \
0029 ({                              \
0030     long __ret = 0; /* success by default */    \
0031     switch (sz) {                       \
0032     case 1: __arc_get_user_one(*(k), u, "ldb", __ret); break;   \
0033     case 2: __arc_get_user_one(*(k), u, "ldw", __ret); break;   \
0034     case 4: __arc_get_user_one(*(k), u, "ld", __ret);  break;   \
0035     case 8: __arc_get_user_one_64(*(k), u, __ret);     break;   \
0036     }                           \
0037     __ret;                          \
0038 })
0039 
0040 /*
0041  * Returns 0 on success, -EFAULT if not.
0042  * @ret already contains 0 - given that errors will be less likely
0043  * (hence +r asm constraint below).
0044  * In case of error, fixup code will make it -EFAULT
0045  */
0046 #define __arc_get_user_one(dst, src, op, ret)   \
0047     __asm__ __volatile__(                   \
0048     "1: "op"    %1,[%2]\n"      \
0049     "2: ;nop\n"             \
0050     "   .section .fixup, \"ax\"\n"  \
0051     "   .align 4\n"         \
0052     "3: # return -EFAULT\n"     \
0053     "   mov %0, %3\n"           \
0054     "   # zero out dst ptr\n"       \
0055     "   mov %1,  0\n"           \
0056     "   j   2b\n"           \
0057     "   .previous\n"            \
0058     "   .section __ex_table, \"a\"\n"   \
0059     "   .align 4\n"         \
0060     "   .word 1b,3b\n"          \
0061     "   .previous\n"            \
0062                         \
0063     : "+r" (ret), "=r" (dst)        \
0064     : "r" (src), "ir" (-EFAULT))
0065 
0066 #define __arc_get_user_one_64(dst, src, ret)    \
0067     __asm__ __volatile__(                   \
0068     "1: ld   %1,[%2]\n"         \
0069     "4: ld  %R1,[%2, 4]\n"      \
0070     "2: ;nop\n"             \
0071     "   .section .fixup, \"ax\"\n"  \
0072     "   .align 4\n"         \
0073     "3: # return -EFAULT\n"     \
0074     "   mov %0, %3\n"           \
0075     "   # zero out dst ptr\n"       \
0076     "   mov %1,  0\n"           \
0077     "   mov %R1, 0\n"           \
0078     "   j   2b\n"           \
0079     "   .previous\n"            \
0080     "   .section __ex_table, \"a\"\n"   \
0081     "   .align 4\n"         \
0082     "   .word 1b,3b\n"          \
0083     "   .word 4b,3b\n"          \
0084     "   .previous\n"            \
0085                         \
0086     : "+r" (ret), "=r" (dst)        \
0087     : "r" (src), "ir" (-EFAULT))
0088 
0089 #define __put_user_fn(sz, u, k)                 \
0090 ({                              \
0091     long __ret = 0; /* success by default */    \
0092     switch (sz) {                       \
0093     case 1: __arc_put_user_one(*(k), u, "stb", __ret); break;   \
0094     case 2: __arc_put_user_one(*(k), u, "stw", __ret); break;   \
0095     case 4: __arc_put_user_one(*(k), u, "st", __ret);  break;   \
0096     case 8: __arc_put_user_one_64(*(k), u, __ret);     break;   \
0097     }                           \
0098     __ret;                          \
0099 })
0100 
0101 #define __arc_put_user_one(src, dst, op, ret)   \
0102     __asm__ __volatile__(                   \
0103     "1: "op"    %1,[%2]\n"      \
0104     "2: ;nop\n"             \
0105     "   .section .fixup, \"ax\"\n"  \
0106     "   .align 4\n"         \
0107     "3: mov %0, %3\n"           \
0108     "   j   2b\n"           \
0109     "   .previous\n"            \
0110     "   .section __ex_table, \"a\"\n"   \
0111     "   .align 4\n"         \
0112     "   .word 1b,3b\n"          \
0113     "   .previous\n"            \
0114                         \
0115     : "+r" (ret)                \
0116     : "r" (src), "r" (dst), "ir" (-EFAULT))
0117 
0118 #define __arc_put_user_one_64(src, dst, ret)    \
0119     __asm__ __volatile__(                   \
0120     "1: st   %1,[%2]\n"         \
0121     "4: st  %R1,[%2, 4]\n"      \
0122     "2: ;nop\n"             \
0123     "   .section .fixup, \"ax\"\n"  \
0124     "   .align 4\n"         \
0125     "3: mov %0, %3\n"           \
0126     "   j   2b\n"           \
0127     "   .previous\n"            \
0128     "   .section __ex_table, \"a\"\n"   \
0129     "   .align 4\n"         \
0130     "   .word 1b,3b\n"          \
0131     "   .word 4b,3b\n"          \
0132     "   .previous\n"            \
0133                         \
0134     : "+r" (ret)                \
0135     : "r" (src), "r" (dst), "ir" (-EFAULT))
0136 
0137 
0138 static inline unsigned long
0139 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
0140 {
0141     long res = 0;
0142     char val;
0143     unsigned long tmp1, tmp2, tmp3, tmp4;
0144     unsigned long orig_n = n;
0145 
0146     if (n == 0)
0147         return 0;
0148 
0149     /* unaligned */
0150     if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) {
0151 
0152         unsigned char tmp;
0153 
0154         __asm__ __volatile__ (
0155         "   mov.f   lp_count, %0        \n"
0156         "   lpnz 2f             \n"
0157         "1: ldb.ab  %1, [%3, 1]     \n"
0158         "   stb.ab  %1, [%2, 1]     \n"
0159         "   sub     %0,%0,1         \n"
0160         "2: ;nop                \n"
0161         "   .section .fixup, \"ax\"     \n"
0162         "   .align 4            \n"
0163         "3: j   2b              \n"
0164         "   .previous           \n"
0165         "   .section __ex_table, \"a\"  \n"
0166         "   .align 4            \n"
0167         "   .word   1b, 3b          \n"
0168         "   .previous           \n"
0169 
0170         : "+r" (n),
0171         /*
0172          * Note as an '&' earlyclobber operand to make sure the
0173          * temporary register inside the loop is not the same as
0174          *  FROM or TO.
0175         */
0176           "=&r" (tmp), "+r" (to), "+r" (from)
0177         :
0178         : "lp_count", "memory");
0179 
0180         return n;
0181     }
0182 
0183     /*
0184      * Hand-crafted constant propagation to reduce code sz of the
0185      * laddered copy 16x,8,4,2,1
0186      */
0187     if (__builtin_constant_p(orig_n)) {
0188         res = orig_n;
0189 
0190         if (orig_n / 16) {
0191             orig_n = orig_n % 16;
0192 
0193             __asm__ __volatile__(
0194             "   lsr   lp_count, %7,4        \n"
0195             "   lp    3f            \n"
0196             "1: ld.ab   %3, [%2, 4]     \n"
0197             "11:    ld.ab   %4, [%2, 4]     \n"
0198             "12:    ld.ab   %5, [%2, 4]     \n"
0199             "13:    ld.ab   %6, [%2, 4]     \n"
0200             "   st.ab   %3, [%1, 4]     \n"
0201             "   st.ab   %4, [%1, 4]     \n"
0202             "   st.ab   %5, [%1, 4]     \n"
0203             "   st.ab   %6, [%1, 4]     \n"
0204             "   sub     %0,%0,16        \n"
0205             "3: ;nop                \n"
0206             "   .section .fixup, \"ax\"     \n"
0207             "   .align 4            \n"
0208             "4: j   3b              \n"
0209             "   .previous           \n"
0210             "   .section __ex_table, \"a\"  \n"
0211             "   .align 4            \n"
0212             "   .word   1b, 4b          \n"
0213             "   .word   11b,4b          \n"
0214             "   .word   12b,4b          \n"
0215             "   .word   13b,4b          \n"
0216             "   .previous           \n"
0217             : "+r" (res), "+r"(to), "+r"(from),
0218               "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
0219             : "ir"(n)
0220             : "lp_count", "memory");
0221         }
0222         if (orig_n / 8) {
0223             orig_n = orig_n % 8;
0224 
0225             __asm__ __volatile__(
0226             "14:    ld.ab   %3, [%2,4]      \n"
0227             "15:    ld.ab   %4, [%2,4]      \n"
0228             "   st.ab   %3, [%1,4]      \n"
0229             "   st.ab   %4, [%1,4]      \n"
0230             "   sub     %0,%0,8         \n"
0231             "31:    ;nop                \n"
0232             "   .section .fixup, \"ax\"     \n"
0233             "   .align 4            \n"
0234             "4: j   31b             \n"
0235             "   .previous           \n"
0236             "   .section __ex_table, \"a\"  \n"
0237             "   .align 4            \n"
0238             "   .word   14b,4b          \n"
0239             "   .word   15b,4b          \n"
0240             "   .previous           \n"
0241             : "+r" (res), "+r"(to), "+r"(from),
0242               "=r"(tmp1), "=r"(tmp2)
0243             :
0244             : "memory");
0245         }
0246         if (orig_n / 4) {
0247             orig_n = orig_n % 4;
0248 
0249             __asm__ __volatile__(
0250             "16:    ld.ab   %3, [%2,4]      \n"
0251             "   st.ab   %3, [%1,4]      \n"
0252             "   sub     %0,%0,4         \n"
0253             "32:    ;nop                \n"
0254             "   .section .fixup, \"ax\"     \n"
0255             "   .align 4            \n"
0256             "4: j   32b             \n"
0257             "   .previous           \n"
0258             "   .section __ex_table, \"a\"  \n"
0259             "   .align 4            \n"
0260             "   .word   16b,4b          \n"
0261             "   .previous           \n"
0262             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0263             :
0264             : "memory");
0265         }
0266         if (orig_n / 2) {
0267             orig_n = orig_n % 2;
0268 
0269             __asm__ __volatile__(
0270             "17:    ldw.ab   %3, [%2,2]     \n"
0271             "   stw.ab   %3, [%1,2]     \n"
0272             "   sub      %0,%0,2        \n"
0273             "33:    ;nop                \n"
0274             "   .section .fixup, \"ax\"     \n"
0275             "   .align 4            \n"
0276             "4: j   33b             \n"
0277             "   .previous           \n"
0278             "   .section __ex_table, \"a\"  \n"
0279             "   .align 4            \n"
0280             "   .word   17b,4b          \n"
0281             "   .previous           \n"
0282             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0283             :
0284             : "memory");
0285         }
0286         if (orig_n & 1) {
0287             __asm__ __volatile__(
0288             "18:    ldb.ab   %3, [%2,2]     \n"
0289             "   stb.ab   %3, [%1,2]     \n"
0290             "   sub      %0,%0,1        \n"
0291             "34:    ; nop               \n"
0292             "   .section .fixup, \"ax\"     \n"
0293             "   .align 4            \n"
0294             "4: j   34b             \n"
0295             "   .previous           \n"
0296             "   .section __ex_table, \"a\"  \n"
0297             "   .align 4            \n"
0298             "   .word   18b,4b          \n"
0299             "   .previous           \n"
0300             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0301             :
0302             : "memory");
0303         }
0304     } else {  /* n is NOT constant, so laddered copy of 16x,8,4,2,1  */
0305 
0306         __asm__ __volatile__(
0307         "   mov %0,%3           \n"
0308         "   lsr.f   lp_count, %3,4      \n"  /* 16x bytes */
0309         "   lpnz    3f          \n"
0310         "1: ld.ab   %5, [%2, 4]     \n"
0311         "11:    ld.ab   %6, [%2, 4]     \n"
0312         "12:    ld.ab   %7, [%2, 4]     \n"
0313         "13:    ld.ab   %8, [%2, 4]     \n"
0314         "   st.ab   %5, [%1, 4]     \n"
0315         "   st.ab   %6, [%1, 4]     \n"
0316         "   st.ab   %7, [%1, 4]     \n"
0317         "   st.ab   %8, [%1, 4]     \n"
0318         "   sub     %0,%0,16        \n"
0319         "3: and.f   %3,%3,0xf       \n"  /* stragglers */
0320         "   bz      34f         \n"
0321         "   bbit0   %3,3,31f        \n"  /* 8 bytes left */
0322         "14:    ld.ab   %5, [%2,4]      \n"
0323         "15:    ld.ab   %6, [%2,4]      \n"
0324         "   st.ab   %5, [%1,4]      \n"
0325         "   st.ab   %6, [%1,4]      \n"
0326         "   sub.f   %0,%0,8         \n"
0327         "31:    bbit0   %3,2,32f        \n"  /* 4 bytes left */
0328         "16:    ld.ab   %5, [%2,4]      \n"
0329         "   st.ab   %5, [%1,4]      \n"
0330         "   sub.f   %0,%0,4         \n"
0331         "32:    bbit0   %3,1,33f        \n"  /* 2 bytes left */
0332         "17:    ldw.ab  %5, [%2,2]      \n"
0333         "   stw.ab  %5, [%1,2]      \n"
0334         "   sub.f   %0,%0,2         \n"
0335         "33:    bbit0   %3,0,34f        \n"
0336         "18:    ldb.ab  %5, [%2,1]      \n"  /* 1 byte left */
0337         "   stb.ab  %5, [%1,1]      \n"
0338         "   sub.f   %0,%0,1         \n"
0339         "34:    ;nop                \n"
0340         "   .section .fixup, \"ax\"     \n"
0341         "   .align 4            \n"
0342         "4: j   34b             \n"
0343         "   .previous           \n"
0344         "   .section __ex_table, \"a\"  \n"
0345         "   .align 4            \n"
0346         "   .word   1b, 4b          \n"
0347         "   .word   11b,4b          \n"
0348         "   .word   12b,4b          \n"
0349         "   .word   13b,4b          \n"
0350         "   .word   14b,4b          \n"
0351         "   .word   15b,4b          \n"
0352         "   .word   16b,4b          \n"
0353         "   .word   17b,4b          \n"
0354         "   .word   18b,4b          \n"
0355         "   .previous           \n"
0356         : "=r" (res), "+r"(to), "+r"(from), "+r"(n), "=r"(val),
0357           "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
0358         :
0359         : "lp_count", "memory");
0360     }
0361 
0362     return res;
0363 }
0364 
0365 static inline unsigned long
0366 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
0367 {
0368     long res = 0;
0369     char val;
0370     unsigned long tmp1, tmp2, tmp3, tmp4;
0371     unsigned long orig_n = n;
0372 
0373     if (n == 0)
0374         return 0;
0375 
0376     /* unaligned */
0377     if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) {
0378 
0379         unsigned char tmp;
0380 
0381         __asm__ __volatile__(
0382         "   mov.f   lp_count, %0        \n"
0383         "   lpnz 3f             \n"
0384         "   ldb.ab  %1, [%3, 1]     \n"
0385         "1: stb.ab  %1, [%2, 1]     \n"
0386         "   sub     %0, %0, 1       \n"
0387         "3: ;nop                \n"
0388         "   .section .fixup, \"ax\"     \n"
0389         "   .align 4            \n"
0390         "4: j   3b              \n"
0391         "   .previous           \n"
0392         "   .section __ex_table, \"a\"  \n"
0393         "   .align 4            \n"
0394         "   .word   1b, 4b          \n"
0395         "   .previous           \n"
0396 
0397         : "+r" (n),
0398         /* Note as an '&' earlyclobber operand to make sure the
0399          * temporary register inside the loop is not the same as
0400          * FROM or TO.
0401          */
0402           "=&r" (tmp), "+r" (to), "+r" (from)
0403         :
0404         : "lp_count", "memory");
0405 
0406         return n;
0407     }
0408 
0409     if (__builtin_constant_p(orig_n)) {
0410         res = orig_n;
0411 
0412         if (orig_n / 16) {
0413             orig_n = orig_n % 16;
0414 
0415             __asm__ __volatile__(
0416             "   lsr lp_count, %7,4      \n"
0417             "   lp  3f              \n"
0418             "   ld.ab %3, [%2, 4]       \n"
0419             "   ld.ab %4, [%2, 4]       \n"
0420             "   ld.ab %5, [%2, 4]       \n"
0421             "   ld.ab %6, [%2, 4]       \n"
0422             "1: st.ab %3, [%1, 4]       \n"
0423             "11:    st.ab %4, [%1, 4]       \n"
0424             "12:    st.ab %5, [%1, 4]       \n"
0425             "13:    st.ab %6, [%1, 4]       \n"
0426             "   sub   %0, %0, 16        \n"
0427             "3:;nop                 \n"
0428             "   .section .fixup, \"ax\"     \n"
0429             "   .align 4            \n"
0430             "4: j   3b              \n"
0431             "   .previous           \n"
0432             "   .section __ex_table, \"a\"  \n"
0433             "   .align 4            \n"
0434             "   .word   1b, 4b          \n"
0435             "   .word   11b,4b          \n"
0436             "   .word   12b,4b          \n"
0437             "   .word   13b,4b          \n"
0438             "   .previous           \n"
0439             : "+r" (res), "+r"(to), "+r"(from),
0440               "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
0441             : "ir"(n)
0442             : "lp_count", "memory");
0443         }
0444         if (orig_n / 8) {
0445             orig_n = orig_n % 8;
0446 
0447             __asm__ __volatile__(
0448             "   ld.ab   %3, [%2,4]      \n"
0449             "   ld.ab   %4, [%2,4]      \n"
0450             "14:    st.ab   %3, [%1,4]      \n"
0451             "15:    st.ab   %4, [%1,4]      \n"
0452             "   sub     %0, %0, 8       \n"
0453             "31:;nop                \n"
0454             "   .section .fixup, \"ax\"     \n"
0455             "   .align 4            \n"
0456             "4: j   31b             \n"
0457             "   .previous           \n"
0458             "   .section __ex_table, \"a\"  \n"
0459             "   .align 4            \n"
0460             "   .word   14b,4b          \n"
0461             "   .word   15b,4b          \n"
0462             "   .previous           \n"
0463             : "+r" (res), "+r"(to), "+r"(from),
0464               "=r"(tmp1), "=r"(tmp2)
0465             :
0466             : "memory");
0467         }
0468         if (orig_n / 4) {
0469             orig_n = orig_n % 4;
0470 
0471             __asm__ __volatile__(
0472             "   ld.ab   %3, [%2,4]      \n"
0473             "16:    st.ab   %3, [%1,4]      \n"
0474             "   sub     %0, %0, 4       \n"
0475             "32:;nop                \n"
0476             "   .section .fixup, \"ax\"     \n"
0477             "   .align 4            \n"
0478             "4: j   32b             \n"
0479             "   .previous           \n"
0480             "   .section __ex_table, \"a\"  \n"
0481             "   .align 4            \n"
0482             "   .word   16b,4b          \n"
0483             "   .previous           \n"
0484             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0485             :
0486             : "memory");
0487         }
0488         if (orig_n / 2) {
0489             orig_n = orig_n % 2;
0490 
0491             __asm__ __volatile__(
0492             "   ldw.ab    %3, [%2,2]        \n"
0493             "17:    stw.ab    %3, [%1,2]        \n"
0494             "   sub       %0, %0, 2     \n"
0495             "33:;nop                \n"
0496             "   .section .fixup, \"ax\"     \n"
0497             "   .align 4            \n"
0498             "4: j   33b             \n"
0499             "   .previous           \n"
0500             "   .section __ex_table, \"a\"  \n"
0501             "   .align 4            \n"
0502             "   .word   17b,4b          \n"
0503             "   .previous           \n"
0504             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0505             :
0506             : "memory");
0507         }
0508         if (orig_n & 1) {
0509             __asm__ __volatile__(
0510             "   ldb.ab  %3, [%2,1]      \n"
0511             "18:    stb.ab  %3, [%1,1]      \n"
0512             "   sub     %0, %0, 1       \n"
0513             "34:    ;nop                \n"
0514             "   .section .fixup, \"ax\"     \n"
0515             "   .align 4            \n"
0516             "4: j   34b             \n"
0517             "   .previous           \n"
0518             "   .section __ex_table, \"a\"  \n"
0519             "   .align 4            \n"
0520             "   .word   18b,4b          \n"
0521             "   .previous           \n"
0522             : "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
0523             :
0524             : "memory");
0525         }
0526     } else {  /* n is NOT constant, so laddered copy of 16x,8,4,2,1  */
0527 
0528         __asm__ __volatile__(
0529         "   mov   %0,%3         \n"
0530         "   lsr.f lp_count, %3,4        \n"  /* 16x bytes */
0531         "   lpnz  3f            \n"
0532         "   ld.ab %5, [%2, 4]       \n"
0533         "   ld.ab %6, [%2, 4]       \n"
0534         "   ld.ab %7, [%2, 4]       \n"
0535         "   ld.ab %8, [%2, 4]       \n"
0536         "1: st.ab %5, [%1, 4]       \n"
0537         "11:    st.ab %6, [%1, 4]       \n"
0538         "12:    st.ab %7, [%1, 4]       \n"
0539         "13:    st.ab %8, [%1, 4]       \n"
0540         "   sub   %0, %0, 16        \n"
0541         "3: and.f %3,%3,0xf         \n" /* stragglers */
0542         "   bz 34f              \n"
0543         "   bbit0   %3,3,31f        \n" /* 8 bytes left */
0544         "   ld.ab   %5, [%2,4]      \n"
0545         "   ld.ab   %6, [%2,4]      \n"
0546         "14:    st.ab   %5, [%1,4]      \n"
0547         "15:    st.ab   %6, [%1,4]      \n"
0548         "   sub.f   %0, %0, 8       \n"
0549         "31:    bbit0   %3,2,32f        \n"  /* 4 bytes left */
0550         "   ld.ab   %5, [%2,4]      \n"
0551         "16:    st.ab   %5, [%1,4]      \n"
0552         "   sub.f   %0, %0, 4       \n"
0553         "32:    bbit0 %3,1,33f          \n"  /* 2 bytes left */
0554         "   ldw.ab    %5, [%2,2]        \n"
0555         "17:    stw.ab    %5, [%1,2]        \n"
0556         "   sub.f %0, %0, 2         \n"
0557         "33:    bbit0 %3,0,34f          \n"
0558         "   ldb.ab    %5, [%2,1]        \n"  /* 1 byte left */
0559         "18:    stb.ab  %5, [%1,1]      \n"
0560         "   sub.f %0, %0, 1         \n"
0561         "34:    ;nop                \n"
0562         "   .section .fixup, \"ax\"     \n"
0563         "   .align 4            \n"
0564         "4: j   34b             \n"
0565         "   .previous           \n"
0566         "   .section __ex_table, \"a\"  \n"
0567         "   .align 4            \n"
0568         "   .word   1b, 4b          \n"
0569         "   .word   11b,4b          \n"
0570         "   .word   12b,4b          \n"
0571         "   .word   13b,4b          \n"
0572         "   .word   14b,4b          \n"
0573         "   .word   15b,4b          \n"
0574         "   .word   16b,4b          \n"
0575         "   .word   17b,4b          \n"
0576         "   .word   18b,4b          \n"
0577         "   .previous           \n"
0578         : "=r" (res), "+r"(to), "+r"(from), "+r"(n), "=r"(val),
0579           "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
0580         :
0581         : "lp_count", "memory");
0582     }
0583 
0584     return res;
0585 }
0586 
0587 static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
0588 {
0589     long res = n;
0590     unsigned char *d_char = to;
0591 
0592     __asm__ __volatile__(
0593     "   bbit0   %0, 0, 1f       \n"
0594     "75:    stb.ab  %2, [%0,1]      \n"
0595     "   sub %1, %1, 1           \n"
0596     "1: bbit0   %0, 1, 2f       \n"
0597     "76:    stw.ab  %2, [%0,2]      \n"
0598     "   sub %1, %1, 2           \n"
0599     "2: asr.f   lp_count, %1, 2     \n"
0600     "   lpnz    3f          \n"
0601     "77:    st.ab   %2, [%0,4]      \n"
0602     "   sub %1, %1, 4           \n"
0603     "3: bbit0   %1, 1, 4f       \n"
0604     "78:    stw.ab  %2, [%0,2]      \n"
0605     "   sub %1, %1, 2           \n"
0606     "4: bbit0   %1, 0, 5f       \n"
0607     "79:    stb.ab  %2, [%0,1]      \n"
0608     "   sub %1, %1, 1           \n"
0609     "5:                 \n"
0610     "   .section .fixup, \"ax\"     \n"
0611     "   .align 4            \n"
0612     "3: j   5b              \n"
0613     "   .previous           \n"
0614     "   .section __ex_table, \"a\"  \n"
0615     "   .align 4            \n"
0616     "   .word   75b, 3b         \n"
0617     "   .word   76b, 3b         \n"
0618     "   .word   77b, 3b         \n"
0619     "   .word   78b, 3b         \n"
0620     "   .word   79b, 3b         \n"
0621     "   .previous           \n"
0622     : "+r"(d_char), "+r"(res)
0623     : "i"(0)
0624     : "lp_count", "memory");
0625 
0626     return res;
0627 }
0628 
0629 #ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
0630 
0631 #define INLINE_COPY_TO_USER
0632 #define INLINE_COPY_FROM_USER
0633 
0634 #define __clear_user(d, n)      __arc_clear_user(d, n)
0635 #else
0636 extern unsigned long arc_clear_user_noinline(void __user *to,
0637         unsigned long n);
0638 #define __clear_user(d, n)      arc_clear_user_noinline(d, n)
0639 #endif
0640 
0641 #include <asm-generic/uaccess.h>
0642 
0643 #endif