linux/arch/alpha/lib/strlen_user.S
<<
>>
Prefs
   1/*
   2 * arch/alpha/lib/strlen_user.S
   3 *
   4 * Return the length of the string including the NUL terminator
   5 * (strlen+1) or zero if an error occurred.
   6 *
   7 * In places where it is critical to limit the processing time,
   8 * and the data is not trusted, strnlen_user() should be used.
   9 * It will return a value greater than its second argument if
  10 * that limit would be exceeded. This implementation is allowed
  11 * to access memory beyond the limit, but will not cross a page
  12 * boundary when doing so.
  13 */
  14
  15#include <asm/regdef.h>
  16
  17
  18/* Allow an exception for an insn; exit if we get one.  */
  19#define EX(x,y...)                      \
  20        99: x,##y;                      \
  21        .section __ex_table,"a";        \
  22        .long 99b - .;                  \
  23        lda v0, $exception-99b(zero);   \
  24        .previous
  25
  26
  27        .set noreorder
  28        .set noat
  29        .text
  30
  31        .globl __strlen_user
  32        .ent __strlen_user
  33        .frame sp, 0, ra
  34
  35        .align 3
  36__strlen_user:
  37        ldah    a1, 32767(zero) # do not use plain strlen_user() for strings
  38                                # that might be almost 2 GB long; you should
  39                                # be using strnlen_user() instead
  40
  41        .globl __strnlen_user
  42
  43        .align 3
  44__strnlen_user:
  45        .prologue 0
  46
  47        EX( ldq_u t0, 0(a0) )   # load first quadword (a0 may be misaligned)
  48        lda     t1, -1(zero)
  49        insqh   t1, a0, t1
  50        andnot  a0, 7, v0
  51        or      t1, t0, t0
  52        subq    a0, 1, a0       # get our +1 for the return 
  53        cmpbge  zero, t0, t1    # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
  54        subq    a1, 7, t2
  55        subq    a0, v0, t0
  56        bne     t1, $found
  57
  58        addq    t2, t0, t2
  59        addq    a1, 1, a1
  60
  61        .align 3
  62$loop:  ble     t2, $limit
  63        EX( ldq t0, 8(v0) )
  64        subq    t2, 8, t2
  65        addq    v0, 8, v0       # addr += 8
  66        cmpbge  zero, t0, t1
  67        beq     t1, $loop
  68
  69$found: negq    t1, t2          # clear all but least set bit
  70        and     t1, t2, t1
  71
  72        and     t1, 0xf0, t2    # binary search for that set bit
  73        and     t1, 0xcc, t3
  74        and     t1, 0xaa, t4
  75        cmovne  t2, 4, t2
  76        cmovne  t3, 2, t3
  77        cmovne  t4, 1, t4
  78        addq    t2, t3, t2
  79        addq    v0, t4, v0
  80        addq    v0, t2, v0
  81        nop                     # dual issue next two on ev4 and ev5
  82        subq    v0, a0, v0
  83$exception:
  84        ret
  85
  86        .align 3                # currently redundant
  87$limit:
  88        subq    a1, t2, v0
  89        ret
  90
  91        .end __strlen_user
  92
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.