home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-cris / arch-v10 / uaccess.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  18.0 KB  |  661 lines

  1. /* 
  2.  * Authors:    Bjorn Wesen (bjornw@axis.com)
  3.  *           Hans-Peter Nilsson (hp@axis.com)
  4.  *
  5.  */
  6. #ifndef _CRIS_ARCH_UACCESS_H
  7. #define _CRIS_ARCH_UACCESS_H
  8.  
  9. /*
  10.  * We don't tell gcc that we are accessing memory, but this is OK
  11.  * because we do not write to any memory gcc knows about, so there
  12.  * are no aliasing issues.
  13.  *
  14.  * Note that PC at a fault is the address *after* the faulting
  15.  * instruction.
  16.  */
  17. #define __put_user_asm(x, addr, err, op)            \
  18.     __asm__ __volatile__(                    \
  19.         "    "op" %1,[%2]\n"                \
  20.         "2:\n"                        \
  21.         "    .section .fixup,\"ax\"\n"        \
  22.         "3:    move.d %3,%0\n"                \
  23.         "    jump 2b\n"                \
  24.         "    .previous\n"                \
  25.         "    .section __ex_table,\"a\"\n"        \
  26.         "    .dword 2b,3b\n"                \
  27.         "    .previous\n"                \
  28.         : "=r" (err)                    \
  29.         : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  30.  
  31. #define __put_user_asm_64(x, addr, err)                \
  32.     __asm__ __volatile__(                    \
  33.         "    move.d %M1,[%2]\n"            \
  34.         "2:    move.d %H1,[%2+4]\n"            \
  35.         "4:\n"                        \
  36.         "    .section .fixup,\"ax\"\n"        \
  37.         "3:    move.d %3,%0\n"                \
  38.         "    jump 4b\n"                \
  39.         "    .previous\n"                \
  40.         "    .section __ex_table,\"a\"\n"        \
  41.         "    .dword 2b,3b\n"                \
  42.         "    .dword 4b,3b\n"                \
  43.         "    .previous\n"                \
  44.         : "=r" (err)                    \
  45.         : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  46.  
  47. /* See comment before __put_user_asm.  */
  48.  
  49. #define __get_user_asm(x, addr, err, op)        \
  50.     __asm__ __volatile__(                \
  51.         "    "op" [%2],%1\n"            \
  52.         "2:\n"                    \
  53.         "    .section .fixup,\"ax\"\n"    \
  54.         "3:    move.d %3,%0\n"            \
  55.         "    moveq 0,%1\n"            \
  56.         "    jump 2b\n"            \
  57.         "    .previous\n"            \
  58.         "    .section __ex_table,\"a\"\n"    \
  59.         "    .dword 2b,3b\n"            \
  60.         "    .previous\n"            \
  61.         : "=r" (err), "=r" (x)            \
  62.         : "r" (addr), "g" (-EFAULT), "0" (err))
  63.  
  64. #define __get_user_asm_64(x, addr, err)            \
  65.     __asm__ __volatile__(                \
  66.         "    move.d [%2],%M1\n"        \
  67.         "2:    move.d [%2+4],%H1\n"        \
  68.         "4:\n"                    \
  69.         "    .section .fixup,\"ax\"\n"    \
  70.         "3:    move.d %3,%0\n"            \
  71.         "    moveq 0,%1\n"            \
  72.         "    jump 4b\n"            \
  73.         "    .previous\n"            \
  74.         "    .section __ex_table,\"a\"\n"    \
  75.         "    .dword 2b,3b\n"            \
  76.         "    .dword 4b,3b\n"            \
  77.         "    .previous\n"            \
  78.         : "=r" (err), "=r" (x)            \
  79.         : "r" (addr), "g" (-EFAULT), "0" (err))
  80.  
  81. /*
  82.  * Copy a null terminated string from userspace.
  83.  *
  84.  * Must return:
  85.  * -EFAULT        for an exception
  86.  * count        if we hit the buffer limit
  87.  * bytes copied        if we hit a null byte
  88.  * (without the null byte)
  89.  */
  90. static inline long
  91. __do_strncpy_from_user(char *dst, const char *src, long count)
  92. {
  93.     long res;
  94.  
  95.     if (count == 0)
  96.         return 0;
  97.  
  98.     /*
  99.      * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
  100.      *  So do we.
  101.      *
  102.      *  This code is deduced from:
  103.      *
  104.      *    char tmp2;
  105.      *    long tmp1, tmp3    
  106.      *    tmp1 = count;
  107.      *    while ((*dst++ = (tmp2 = *src++)) != 0
  108.      *           && --tmp1)
  109.      *      ;
  110.      *
  111.      *    res = count - tmp1;
  112.      *
  113.      *  with tweaks.
  114.      */
  115.  
  116.     __asm__ __volatile__ (
  117.         "    move.d %3,%0\n"
  118.         "    move.b [%2+],$r9\n"
  119.         "1:    beq 2f\n"
  120.         "    move.b $r9,[%1+]\n"
  121.  
  122.         "    subq 1,%0\n"
  123.         "    bne 1b\n"
  124.         "    move.b [%2+],$r9\n"
  125.  
  126.         "2:    sub.d %3,%0\n"
  127.         "    neg.d %0,%0\n"
  128.         "3:\n"
  129.         "    .section .fixup,\"ax\"\n"
  130.         "4:    move.d %7,%0\n"
  131.         "    jump 3b\n"
  132.  
  133.         /* There's one address for a fault at the first move, and
  134.            two possible PC values for a fault at the second move,
  135.            being a delay-slot filler.  However, the branch-target
  136.            for the second move is the same as the first address.
  137.            Just so you don't get confused...  */
  138.         "    .previous\n"
  139.         "    .section __ex_table,\"a\"\n"
  140.         "    .dword 1b,4b\n"
  141.         "    .dword 2b,4b\n"
  142.         "    .previous"
  143.         : "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
  144.         : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
  145.         : "r9");
  146.  
  147.     return res;
  148. }
  149.  
  150. /* A few copy asms to build up the more complex ones from.
  151.  
  152.    Note again, a post-increment is performed regardless of whether a bus
  153.    fault occurred in that instruction, and PC for a faulted insn is the
  154.    address *after* the insn.  */
  155.  
  156. #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  157.     __asm__ __volatile__ (                \
  158.             COPY                \
  159.         "1:\n"                    \
  160.         "    .section .fixup,\"ax\"\n"    \
  161.             FIXUP                \
  162.         "    jump 1b\n"            \
  163.         "    .previous\n"            \
  164.         "    .section __ex_table,\"a\"\n"    \
  165.             TENTRY                \
  166.         "    .previous\n"            \
  167.         : "=r" (to), "=r" (from), "=r" (ret)    \
  168.         : "0" (to), "1" (from), "2" (ret)    \
  169.         : "r9", "memory")
  170.  
  171. #define __asm_copy_from_user_1(to, from, ret) \
  172.     __asm_copy_user_cont(to, from, ret,    \
  173.         "    move.b [%1+],$r9\n"    \
  174.         "2:    move.b $r9,[%0+]\n",    \
  175.         "3:    addq 1,%2\n"        \
  176.         "    clear.b [%0+]\n",    \
  177.         "    .dword 2b,3b\n")
  178.  
  179. #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  180.     __asm_copy_user_cont(to, from, ret,        \
  181.         "    move.w [%1+],$r9\n"        \
  182.         "2:    move.w $r9,[%0+]\n" COPY,    \
  183.         "3:    addq 2,%2\n"            \
  184.         "    clear.w [%0+]\n" FIXUP,        \
  185.         "    .dword 2b,3b\n" TENTRY)
  186.  
  187. #define __asm_copy_from_user_2(to, from, ret) \
  188.     __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
  189.  
  190. #define __asm_copy_from_user_3(to, from, ret)        \
  191.     __asm_copy_from_user_2x_cont(to, from, ret,    \
  192.         "    move.b [%1+],$r9\n"        \
  193.         "4:    move.b $r9,[%0+]\n",        \
  194.         "5:    addq 1,%2\n"            \
  195.         "    clear.b [%0+]\n",        \
  196.         "    .dword 4b,5b\n")
  197.  
  198. #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  199.     __asm_copy_user_cont(to, from, ret,        \
  200.         "    move.d [%1+],$r9\n"        \
  201.         "2:    move.d $r9,[%0+]\n" COPY,    \
  202.         "3:    addq 4,%2\n"            \
  203.         "    clear.d [%0+]\n" FIXUP,        \
  204.         "    .dword 2b,3b\n" TENTRY)
  205.  
  206. #define __asm_copy_from_user_4(to, from, ret) \
  207.     __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
  208.  
  209. #define __asm_copy_from_user_5(to, from, ret) \
  210.     __asm_copy_from_user_4x_cont(to, from, ret,    \
  211.         "    move.b [%1+],$r9\n"        \
  212.         "4:    move.b $r9,[%0+]\n",        \
  213.         "5:    addq 1,%2\n"            \
  214.         "    clear.b [%0+]\n",        \
  215.         "    .dword 4b,5b\n")
  216.  
  217. #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  218.     __asm_copy_from_user_4x_cont(to, from, ret,    \
  219.         "    move.w [%1+],$r9\n"        \
  220.         "4:    move.w $r9,[%0+]\n" COPY,    \
  221.         "5:    addq 2,%2\n"            \
  222.         "    clear.w [%0+]\n" FIXUP,        \
  223.         "    .dword 4b,5b\n" TENTRY)
  224.  
  225. #define __asm_copy_from_user_6(to, from, ret) \
  226.     __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
  227.  
  228. #define __asm_copy_from_user_7(to, from, ret) \
  229.     __asm_copy_from_user_6x_cont(to, from, ret,    \
  230.         "    move.b [%1+],$r9\n"        \
  231.         "6:    move.b $r9,[%0+]\n",        \
  232.         "7:    addq 1,%2\n"            \
  233.         "    clear.b [%0+]\n",        \
  234.         "    .dword 6b,7b\n")
  235.  
  236. #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  237.     __asm_copy_from_user_4x_cont(to, from, ret,    \
  238.         "    move.d [%1+],$r9\n"        \
  239.         "4:    move.d $r9,[%0+]\n" COPY,    \
  240.         "5:    addq 4,%2\n"            \
  241.         "    clear.d [%0+]\n" FIXUP,        \
  242.         "    .dword 4b,5b\n" TENTRY)
  243.  
  244. #define __asm_copy_from_user_8(to, from, ret) \
  245.     __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
  246.  
  247. #define __asm_copy_from_user_9(to, from, ret) \
  248.     __asm_copy_from_user_8x_cont(to, from, ret,    \
  249.         "    move.b [%1+],$r9\n"        \
  250.         "6:    move.b $r9,[%0+]\n",        \
  251.         "7:    addq 1,%2\n"            \
  252.         "    clear.b [%0+]\n",        \
  253.         "    .dword 6b,7b\n")
  254.  
  255. #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  256.     __asm_copy_from_user_8x_cont(to, from, ret,    \
  257.         "    move.w [%1+],$r9\n"        \
  258.         "6:    move.w $r9,[%0+]\n" COPY,    \
  259.         "7:    addq 2,%2\n"            \
  260.         "    clear.w [%0+]\n" FIXUP,        \
  261.         "    .dword 6b,7b\n" TENTRY)
  262.  
  263. #define __asm_copy_from_user_10(to, from, ret) \
  264.     __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
  265.  
  266. #define __asm_copy_from_user_11(to, from, ret)        \
  267.     __asm_copy_from_user_10x_cont(to, from, ret,    \
  268.         "    move.b [%1+],$r9\n"        \
  269.         "8:    move.b $r9,[%0+]\n",        \
  270.         "9:    addq 1,%2\n"            \
  271.         "    clear.b [%0+]\n",        \
  272.         "    .dword 8b,9b\n")
  273.  
  274. #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  275.     __asm_copy_from_user_8x_cont(to, from, ret,    \
  276.         "    move.d [%1+],$r9\n"        \
  277.         "6:    move.d $r9,[%0+]\n" COPY,    \
  278.         "7:    addq 4,%2\n"            \
  279.         "    clear.d [%0+]\n" FIXUP,        \
  280.         "    .dword 6b,7b\n" TENTRY)
  281.  
  282. #define __asm_copy_from_user_12(to, from, ret) \
  283.     __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
  284.  
  285. #define __asm_copy_from_user_13(to, from, ret) \
  286.     __asm_copy_from_user_12x_cont(to, from, ret,    \
  287.         "    move.b [%1+],$r9\n"        \
  288.         "8:    move.b $r9,[%0+]\n",        \
  289.         "9:    addq 1,%2\n"            \
  290.         "    clear.b [%0+]\n",        \
  291.         "    .dword 8b,9b\n")
  292.  
  293. #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  294.     __asm_copy_from_user_12x_cont(to, from, ret,    \
  295.         "    move.w [%1+],$r9\n"        \
  296.         "8:    move.w $r9,[%0+]\n" COPY,    \
  297.         "9:    addq 2,%2\n"            \
  298.         "    clear.w [%0+]\n" FIXUP,        \
  299.         "    .dword 8b,9b\n" TENTRY)
  300.  
  301. #define __asm_copy_from_user_14(to, from, ret) \
  302.     __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
  303.  
  304. #define __asm_copy_from_user_15(to, from, ret) \
  305.     __asm_copy_from_user_14x_cont(to, from, ret,    \
  306.         "    move.b [%1+],$r9\n"        \
  307.         "10:    move.b $r9,[%0+]\n",        \
  308.         "11:    addq 1,%2\n"            \
  309.         "    clear.b [%0+]\n",        \
  310.         "    .dword 10b,11b\n")
  311.  
  312. #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  313.     __asm_copy_from_user_12x_cont(to, from, ret,    \
  314.         "    move.d [%1+],$r9\n"        \
  315.         "8:    move.d $r9,[%0+]\n" COPY,    \
  316.         "9:    addq 4,%2\n"            \
  317.         "    clear.d [%0+]\n" FIXUP,        \
  318.         "    .dword 8b,9b\n" TENTRY)
  319.  
  320. #define __asm_copy_from_user_16(to, from, ret) \
  321.     __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
  322.  
  323. #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  324.     __asm_copy_from_user_16x_cont(to, from, ret,    \
  325.         "    move.d [%1+],$r9\n"        \
  326.         "10:    move.d $r9,[%0+]\n" COPY,    \
  327.         "11:    addq 4,%2\n"            \
  328.         "    clear.d [%0+]\n" FIXUP,        \
  329.         "    .dword 10b,11b\n" TENTRY)
  330.  
  331. #define __asm_copy_from_user_20(to, from, ret) \
  332.     __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
  333.  
  334. #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  335.     __asm_copy_from_user_20x_cont(to, from, ret,    \
  336.         "    move.d [%1+],$r9\n"        \
  337.         "12:    move.d $r9,[%0+]\n" COPY,    \
  338.         "13:    addq 4,%2\n"            \
  339.         "    clear.d [%0+]\n" FIXUP,        \
  340.         "    .dword 12b,13b\n" TENTRY)
  341.  
  342. #define __asm_copy_from_user_24(to, from, ret) \
  343.     __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
  344.  
  345. /* And now, the to-user ones.  */
  346.  
  347. #define __asm_copy_to_user_1(to, from, ret)    \
  348.     __asm_copy_user_cont(to, from, ret,    \
  349.         "    move.b [%1+],$r9\n"    \
  350.         "    move.b $r9,[%0+]\n2:\n",    \
  351.         "3:    addq 1,%2\n",        \
  352.         "    .dword 2b,3b\n")
  353.  
  354. #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  355.     __asm_copy_user_cont(to, from, ret,        \
  356.         "    move.w [%1+],$r9\n"        \
  357.         "    move.w $r9,[%0+]\n2:\n" COPY,    \
  358.         "3:    addq 2,%2\n" FIXUP,        \
  359.         "    .dword 2b,3b\n" TENTRY)
  360.  
  361. #define __asm_copy_to_user_2(to, from, ret) \
  362.     __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
  363.  
  364. #define __asm_copy_to_user_3(to, from, ret) \
  365.     __asm_copy_to_user_2x_cont(to, from, ret,    \
  366.         "    move.b [%1+],$r9\n"        \
  367.         "    move.b $r9,[%0+]\n4:\n",        \
  368.         "5:    addq 1,%2\n",            \
  369.         "    .dword 4b,5b\n")
  370.  
  371. #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  372.     __asm_copy_user_cont(to, from, ret,        \
  373.         "    move.d [%1+],$r9\n"        \
  374.         "    move.d $r9,[%0+]\n2:\n" COPY,    \
  375.         "3:    addq 4,%2\n" FIXUP,        \
  376.         "    .dword 2b,3b\n" TENTRY)
  377.  
  378. #define __asm_copy_to_user_4(to, from, ret) \
  379.     __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
  380.  
  381. #define __asm_copy_to_user_5(to, from, ret) \
  382.     __asm_copy_to_user_4x_cont(to, from, ret,    \
  383.         "    move.b [%1+],$r9\n"        \
  384.         "    move.b $r9,[%0+]\n4:\n",        \
  385.         "5:    addq 1,%2\n",            \
  386.         "    .dword 4b,5b\n")
  387.  
  388. #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  389.     __asm_copy_to_user_4x_cont(to, from, ret,    \
  390.         "    move.w [%1+],$r9\n"        \
  391.         "    move.w $r9,[%0+]\n4:\n" COPY,    \
  392.         "5:    addq 2,%2\n" FIXUP,        \
  393.         "    .dword 4b,5b\n" TENTRY)
  394.  
  395. #define __asm_copy_to_user_6(to, from, ret) \
  396.     __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
  397.  
  398. #define __asm_copy_to_user_7(to, from, ret) \
  399.     __asm_copy_to_user_6x_cont(to, from, ret,    \
  400.         "    move.b [%1+],$r9\n"        \
  401.         "    move.b $r9,[%0+]\n6:\n",        \
  402.         "7:    addq 1,%2\n",            \
  403.         "    .dword 6b,7b\n")
  404.  
  405. #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  406.     __asm_copy_to_user_4x_cont(to, from, ret,    \
  407.         "    move.d [%1+],$r9\n"        \
  408.         "    move.d $r9,[%0+]\n4:\n" COPY,    \
  409.         "5:    addq 4,%2\n"  FIXUP,        \
  410.         "    .dword 4b,5b\n" TENTRY)
  411.  
  412. #define __asm_copy_to_user_8(to, from, ret) \
  413.     __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
  414.  
  415. #define __asm_copy_to_user_9(to, from, ret) \
  416.     __asm_copy_to_user_8x_cont(to, from, ret,    \
  417.         "    move.b [%1+],$r9\n"        \
  418.         "    move.b $r9,[%0+]\n6:\n",        \
  419.         "7:    addq 1,%2\n",            \
  420.         "    .dword 6b,7b\n")
  421.  
  422. #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  423.     __asm_copy_to_user_8x_cont(to, from, ret,    \
  424.         "    move.w [%1+],$r9\n"        \
  425.         "    move.w $r9,[%0+]\n6:\n" COPY,    \
  426.         "7:    addq 2,%2\n" FIXUP,        \
  427.         "    .dword 6b,7b\n" TENTRY)
  428.  
  429. #define __asm_copy_to_user_10(to, from, ret) \
  430.     __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
  431.  
  432. #define __asm_copy_to_user_11(to, from, ret) \
  433.     __asm_copy_to_user_10x_cont(to, from, ret,    \
  434.         "    move.b [%1+],$r9\n"        \
  435.         "    move.b $r9,[%0+]\n8:\n",        \
  436.         "9:    addq 1,%2\n",            \
  437.         "    .dword 8b,9b\n")
  438.  
  439. #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  440.     __asm_copy_to_user_8x_cont(to, from, ret,    \
  441.         "    move.d [%1+],$r9\n"        \
  442.         "    move.d $r9,[%0+]\n6:\n" COPY,    \
  443.         "7:    addq 4,%2\n" FIXUP,        \
  444.         "    .dword 6b,7b\n" TENTRY)
  445.  
  446. #define __asm_copy_to_user_12(to, from, ret) \
  447.     __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
  448.  
  449. #define __asm_copy_to_user_13(to, from, ret) \
  450.     __asm_copy_to_user_12x_cont(to, from, ret,    \
  451.         "    move.b [%1+],$r9\n"        \
  452.         "    move.b $r9,[%0+]\n8:\n",        \
  453.         "9:    addq 1,%2\n",            \
  454.         "    .dword 8b,9b\n")
  455.  
  456. #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  457.     __asm_copy_to_user_12x_cont(to, from, ret,    \
  458.         "    move.w [%1+],$r9\n"        \
  459.         "    move.w $r9,[%0+]\n8:\n" COPY,    \
  460.         "9:    addq 2,%2\n" FIXUP,        \
  461.         "    .dword 8b,9b\n" TENTRY)
  462.  
  463. #define __asm_copy_to_user_14(to, from, ret)    \
  464.     __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
  465.  
  466. #define __asm_copy_to_user_15(to, from, ret) \
  467.     __asm_copy_to_user_14x_cont(to, from, ret,    \
  468.         "    move.b [%1+],$r9\n"        \
  469.         "    move.b $r9,[%0+]\n10:\n",        \
  470.         "11:    addq 1,%2\n",            \
  471.         "    .dword 10b,11b\n")
  472.  
  473. #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  474.     __asm_copy_to_user_12x_cont(to, from, ret,    \
  475.         "    move.d [%1+],$r9\n"        \
  476.         "    move.d $r9,[%0+]\n8:\n" COPY,    \
  477.         "9:    addq 4,%2\n" FIXUP,        \
  478.         "    .dword 8b,9b\n" TENTRY)
  479.  
  480. #define __asm_copy_to_user_16(to, from, ret) \
  481.     __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
  482.  
  483. #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  484.     __asm_copy_to_user_16x_cont(to, from, ret,    \
  485.         "    move.d [%1+],$r9\n"        \
  486.         "    move.d $r9,[%0+]\n10:\n" COPY,    \
  487.         "11:    addq 4,%2\n" FIXUP,        \
  488.         "    .dword 10b,11b\n" TENTRY)
  489.  
  490. #define __asm_copy_to_user_20(to, from, ret) \
  491.     __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
  492.  
  493. #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)    \
  494.     __asm_copy_to_user_20x_cont(to, from, ret,    \
  495.         "    move.d [%1+],$r9\n"        \
  496.         "    move.d $r9,[%0+]\n12:\n" COPY,    \
  497.         "13:    addq 4,%2\n" FIXUP,        \
  498.         "    .dword 12b,13b\n" TENTRY)
  499.  
  500. #define __asm_copy_to_user_24(to, from, ret)    \
  501.     __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
  502.  
  503. /* Define a few clearing asms with exception handlers.  */
  504.  
  505. /* This frame-asm is like the __asm_copy_user_cont one, but has one less
  506.    input.  */
  507.  
  508. #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
  509.     __asm__ __volatile__ (                \
  510.             CLEAR                \
  511.         "1:\n"                    \
  512.         "    .section .fixup,\"ax\"\n"    \
  513.             FIXUP                \
  514.         "    jump 1b\n"            \
  515.         "    .previous\n"            \
  516.         "    .section __ex_table,\"a\"\n"    \
  517.             TENTRY                \
  518.         "    .previous"            \
  519.         : "=r" (to), "=r" (ret)            \
  520.         : "0" (to), "1" (ret)            \
  521.         : "memory")
  522.  
  523. #define __asm_clear_1(to, ret) \
  524.     __asm_clear(to, ret,            \
  525.         "    clear.b [%0+]\n2:\n",    \
  526.         "3:    addq 1,%1\n",        \
  527.         "    .dword 2b,3b\n")
  528.  
  529. #define __asm_clear_2(to, ret) \
  530.     __asm_clear(to, ret,            \
  531.         "    clear.w [%0+]\n2:\n",    \
  532.         "3:    addq 2,%1\n",        \
  533.         "    .dword 2b,3b\n")
  534.  
  535. #define __asm_clear_3(to, ret) \
  536.      __asm_clear(to, ret,            \
  537.          "    clear.w [%0+]\n"    \
  538.          "2:    clear.b [%0+]\n3:\n",    \
  539.          "4:    addq 2,%1\n"        \
  540.          "5:    addq 1,%1\n",        \
  541.          "    .dword 2b,4b\n"        \
  542.          "    .dword 3b,5b\n")
  543.  
  544. #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  545.     __asm_clear(to, ret,                \
  546.         "    clear.d [%0+]\n2:\n" CLEAR,    \
  547.         "3:    addq 4,%1\n" FIXUP,        \
  548.         "    .dword 2b,3b\n" TENTRY)
  549.  
  550. #define __asm_clear_4(to, ret) \
  551.     __asm_clear_4x_cont(to, ret, "", "", "")
  552.  
  553. #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  554.     __asm_clear_4x_cont(to, ret,            \
  555.         "    clear.d [%0+]\n4:\n" CLEAR,    \
  556.         "5:    addq 4,%1\n" FIXUP,        \
  557.         "    .dword 4b,5b\n" TENTRY)
  558.  
  559. #define __asm_clear_8(to, ret) \
  560.     __asm_clear_8x_cont(to, ret, "", "", "")
  561.  
  562. #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  563.     __asm_clear_8x_cont(to, ret,            \
  564.         "    clear.d [%0+]\n6:\n" CLEAR,    \
  565.         "7:    addq 4,%1\n" FIXUP,        \
  566.         "    .dword 6b,7b\n" TENTRY)
  567.  
  568. #define __asm_clear_12(to, ret) \
  569.     __asm_clear_12x_cont(to, ret, "", "", "")
  570.  
  571. #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  572.     __asm_clear_12x_cont(to, ret,            \
  573.         "    clear.d [%0+]\n8:\n" CLEAR,    \
  574.         "9:    addq 4,%1\n" FIXUP,        \
  575.         "    .dword 8b,9b\n" TENTRY)
  576.  
  577. #define __asm_clear_16(to, ret) \
  578.     __asm_clear_16x_cont(to, ret, "", "", "")
  579.  
  580. #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  581.     __asm_clear_16x_cont(to, ret,            \
  582.         "    clear.d [%0+]\n10:\n" CLEAR,    \
  583.         "11:    addq 4,%1\n" FIXUP,        \
  584.         "    .dword 10b,11b\n" TENTRY)
  585.  
  586. #define __asm_clear_20(to, ret) \
  587.     __asm_clear_20x_cont(to, ret, "", "", "")
  588.  
  589. #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  590.     __asm_clear_20x_cont(to, ret,            \
  591.         "    clear.d [%0+]\n12:\n" CLEAR,    \
  592.         "13:    addq 4,%1\n" FIXUP,        \
  593.         "    .dword 12b,13b\n" TENTRY)
  594.  
  595. #define __asm_clear_24(to, ret) \
  596.     __asm_clear_24x_cont(to, ret, "", "", "")
  597.  
  598. /*
  599.  * Return the size of a string (including the ending 0)
  600.  *
  601.  * Return length of string in userspace including terminating 0
  602.  * or 0 for error.  Return a value greater than N if too long.
  603.  */
  604.  
  605. static inline long
  606. strnlen_user(const char *s, long n)
  607. {
  608.     long res, tmp1;
  609.  
  610.     if (!access_ok(VERIFY_READ, s, 0))
  611.         return 0;
  612.  
  613.     /*
  614.      * This code is deduced from:
  615.      *
  616.      *    tmp1 = n;
  617.      *    while (tmp1-- > 0 && *s++)
  618.      *      ;
  619.      *
  620.      *    res = n - tmp1;
  621.      *
  622.      *  (with tweaks).
  623.      */
  624.  
  625.     __asm__ __volatile__ (
  626.         "    move.d %1,$r9\n"
  627.         "0:\n"
  628.         "    ble 1f\n"
  629.         "    subq 1,$r9\n"
  630.  
  631.         "    test.b [%0+]\n"
  632.         "    bne 0b\n"
  633.         "    test.d $r9\n"
  634.         "1:\n"
  635.         "    move.d %1,%0\n"
  636.         "    sub.d $r9,%0\n"
  637.         "2:\n"
  638.         "    .section .fixup,\"ax\"\n"
  639.  
  640.         "3:    clear.d %0\n"
  641.         "    jump 2b\n"
  642.  
  643.         /* There's one address for a fault at the first move, and
  644.            two possible PC values for a fault at the second move,
  645.            being a delay-slot filler.  However, the branch-target
  646.            for the second move is the same as the first address.
  647.            Just so you don't get confused...  */
  648.         "    .previous\n"
  649.         "    .section __ex_table,\"a\"\n"
  650.         "    .dword 0b,3b\n"
  651.         "    .dword 1b,3b\n"
  652.         "    .previous\n"
  653.         : "=r" (res), "=r" (tmp1)
  654.         : "0" (s), "1" (n)
  655.         : "r9");
  656.  
  657.     return res;
  658. }
  659.  
  660. #endif
  661.