linux-old/arch/alpha/lib/ev67-strlen_user.S
<<
>>
Prefs
   1/*
   2 * arch/alpha/lib/ev67-strlen_user.S
   3 * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
   4 *
   5 * Return the length of the string including the NULL terminator
   6 * (strlen+1) or zero if an error occurred.
   7 *
   8 * In places where it is critical to limit the processing time,
   9 * and the data is not trusted, strnlen_user() should be used.
  10 * It will return a value greater than its second argument if
  11 * that limit would be exceeded. This implementation is allowed
  12 * to access memory beyond the limit, but will not cross a page
  13 * boundary when doing so.
  14 *
  15 * Much of the information about 21264 scheduling/coding comes from:
  16 *      Compiler Writer's Guide for the Alpha 21264
  17 *      abbreviated as 'CWG' in other comments here
  18 *      ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
  19 * Scheduling notation:
  20 *      E       - either cluster
  21 *      U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
  22 *      L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
  23 * Try not to change the actual algorithm if possible for consistency.
  24 */
  25
  26#include <asm/regdef.h>
  27
  28
  29/* Allow an exception for an insn; exit if we get one.  */
  30#define EX(x,y...)                      \
  31        99: x,##y;                      \
  32        .section __ex_table,"a";        \
  33        .gprel32 99b;                   \
  34        lda v0, $exception-99b(zero);   \
  35        .previous
  36
  37
  38        .set noreorder
  39        .set noat
  40        .text
  41
  42        .globl __strlen_user
  43        .ent __strlen_user
  44        .frame sp, 0, ra
  45
  46        .align 4
  47__strlen_user:
  48        ldah    a1, 32767(zero) # do not use plain strlen_user() for strings
  49                                # that might be almost 2 GB long; you should
  50                                # be using strnlen_user() instead
  51        nop
  52        nop
  53        nop
  54
  55        .globl __strnlen_user
  56
  57        .align 4
  58__strnlen_user:
  59        ldgp    $29,0($27)      # E E : we do exceptions -- we need the gp.
  60                                /* Decomposes into lda/ldah */
  61        .prologue 1
  62        EX( ldq_u t0, 0(a0) )   # L : load first quadword (a0 may be misaligned)
  63        lda     t1, -1(zero)    # E :
  64
  65        insqh   t1, a0, t1      # U :
  66        andnot  a0, 7, v0       # E :
  67        or      t1, t0, t0      # E :
  68        subq    a0, 1, a0       # E : get our +1 for the return 
  69
  70        cmpbge  zero, t0, t1    # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
  71        subq    a1, 7, t2       # E :
  72        subq    a0, v0, t0      # E :
  73        bne     t1, $found      # U :
  74
  75        addq    t2, t0, t2      # E :
  76        addq    a1, 1, a1       # E :
  77        nop                     # E :
  78        nop                     # E :
  79
  80        .align 4
  81$loop:  ble     t2, $limit      # U :
  82        EX( ldq t0, 8(v0) )     # L :
  83        nop                     # E :
  84        nop                     # E :
  85
  86        cmpbge  zero, t0, t1    # E :
  87        subq    t2, 8, t2       # E :
  88        addq    v0, 8, v0       # E : addr += 8
  89        beq     t1, $loop       # U :
  90
  91$found: cttz    t1, t2          # U0 :
  92        addq    v0, t2, v0      # E :
  93        subq    v0, a0, v0      # E :
  94        ret                     # L0 :
  95
  96$exception:
  97        nop
  98        nop
  99        nop
 100        ret
 101
 102        .align 4                # currently redundant
 103$limit:
 104        nop
 105        nop
 106        subq    a1, t2, v0
 107        ret
 108
 109        .end __strlen_user
 110
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.