| /* |
| * strncpy_from_user.S: Sparc64 strncpy from userspace. |
| * |
| * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) |
| */ |
| |
| #include <asm/asi.h> |
| #include <asm/errno.h> |
| |
| .data |
| .align 8 |
| 0: .xword 0x0101010101010101 |
| |
| .text |
| .align 32 |
| |
| /* Must return: |
| * |
| * -EFAULT for an exception |
| * count if we hit the buffer limit |
| * bytes copied if we hit a null byte |
| * (without the null byte) |
| * |
| * This implementation assumes: |
| * %o1 is 8 aligned => !(%o2 & 7) |
| * %o0 is 8 aligned (if not, it will be slooooow, but will work) |
| * |
| * This is optimized for the common case: |
| * in my stats, 90% of src are 8 aligned (even on sparc32) |
| * and average length is 18 or so. |
| */ |
| |
| .globl __strncpy_from_user |
| .type __strncpy_from_user,#function |
| __strncpy_from_user: |
| /* %o0=dest, %o1=src, %o2=count */ |
| andcc %o1, 7, %g0 ! IEU1 Group |
| bne,pn %icc, 30f ! CTI |
| add %o0, %o2, %g3 ! IEU0 |
| 60: ldxa [%o1] %asi, %g1 ! Load Group |
| brlez,pn %o2, 10f ! CTI |
| mov %o0, %o3 ! IEU0 |
| 50: sethi %hi(0b), %o4 ! IEU0 Group |
| ldx [%o4 + %lo(0b)], %o4 ! Load |
| sllx %o4, 7, %o5 ! IEU1 Group |
| 1: sub %g1, %o4, %g2 ! IEU0 Group |
| stx %g1, [%o0] ! Store |
| add %o0, 8, %o0 ! IEU1 |
| andcc %g2, %o5, %g0 ! IEU1 Group |
| bne,pn %xcc, 5f ! CTI |
| add %o1, 8, %o1 ! IEU0 |
| cmp %o0, %g3 ! IEU1 Group |
| bl,a,pt %xcc, 1b ! CTI |
| 61: ldxa [%o1] %asi, %g1 ! Load |
| 10: retl ! CTI Group |
| mov %o2, %o0 ! IEU0 |
| 5: srlx %g2, 32, %g7 ! IEU0 Group |
| sethi %hi(0xff00), %o4 ! IEU1 |
| andcc %g7, %o5, %g0 ! IEU1 Group |
| be,pn %icc, 2f ! CTI |
| or %o4, %lo(0xff00), %o4 ! IEU0 |
| srlx %g1, 48, %g7 ! IEU0 Group |
| andcc %g7, %o4, %g0 ! IEU1 Group |
| be,pn %icc, 50f ! CTI |
| andcc %g7, 0xff, %g0 ! IEU1 Group |
| be,pn %icc, 51f ! CTI |
| srlx %g1, 32, %g7 ! IEU0 |
| andcc %g7, %o4, %g0 ! IEU1 Group |
| be,pn %icc, 52f ! CTI |
| andcc %g7, 0xff, %g0 ! IEU1 Group |
| be,pn %icc, 53f ! CTI |
| 2: andcc %g2, %o5, %g0 ! IEU1 Group |
| be,pn %icc, 2f ! CTI |
| srl %g1, 16, %g7 ! IEU0 |
| andcc %g7, %o4, %g0 ! IEU1 Group |
| be,pn %icc, 54f ! CTI |
| andcc %g7, 0xff, %g0 ! IEU1 Group |
| be,pn %icc, 55f ! CTI |
| andcc %g1, %o4, %g0 ! IEU1 Group |
| be,pn %icc, 56f ! CTI |
| andcc %g1, 0xff, %g0 ! IEU1 Group |
| be,a,pn %icc, 57f ! CTI |
| sub %o0, %o3, %o0 ! IEU0 |
| 2: cmp %o0, %g3 ! IEU1 Group |
| bl,a,pt %xcc, 50b ! CTI |
| 62: ldxa [%o1] %asi, %g1 ! Load |
| retl ! CTI Group |
| mov %o2, %o0 ! IEU0 |
| 50: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 8, %o0 |
| 51: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 7, %o0 |
| 52: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 6, %o0 |
| 53: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 5, %o0 |
| 54: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 4, %o0 |
| 55: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 3, %o0 |
| 56: sub %o0, %o3, %o0 |
| retl |
| sub %o0, 2, %o0 |
| 57: retl |
| sub %o0, 1, %o0 |
| 30: brlez,pn %o2, 3f |
| sub %g0, %o2, %o3 |
| add %o0, %o2, %o0 |
| 63: lduba [%o1] %asi, %o4 |
| 1: add %o1, 1, %o1 |
| brz,pn %o4, 2f |
| stb %o4, [%o0 + %o3] |
| addcc %o3, 1, %o3 |
| bne,pt %xcc, 1b |
| 64: lduba [%o1] %asi, %o4 |
| 3: retl |
| mov %o2, %o0 |
| 2: retl |
| add %o2, %o3, %o0 |
| .size __strncpy_from_user, .-__strncpy_from_user |
| |
| .section __ex_table,"a" |
| .align 4 |
| .word 60b, __retl_efault |
| .word 61b, __retl_efault |
| .word 62b, __retl_efault |
| .word 63b, __retl_efault |
| .word 64b, __retl_efault |
| .previous |