OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [alpha/] [lib/] [strlen_user.S] - Rev 1765

Compare with Previous | Blame | View Log

/*
 * arch/alpha/lib/strlen_user.S
 *
 * Return the length of the string including the NUL terminator
 * (strlen+1) or zero if an error occurred.
 *
 * In places where it is critical to limit the processing time,
 * and the data is not trusted, strnlen_user() should be used.
 * It will return a value greater than its second argument if
 * that limit would be exceeded. This implementation is allowed
 * to access memory beyond the limit, but will not cross a page
 * boundary when doing so.
 */

#include <asm/regdef.h>


/* Allow an exception for an insn; exit if we get one.  */
#define EX(x,y...)                      \
        99: x,##y;                      \
        .section __ex_table,"a";        \
        .gprel32 99b;                   \
        lda v0, $exception-99b(zero);   \
        .previous


        .set noreorder
        .set noat
        .text

        .globl __strlen_user
        .ent __strlen_user
        .frame sp, 0, ra

        .align 3
__strlen_user:
        ldah    a1, 32767(zero) # do not use plain strlen_user() for strings
                                # that might be almost 2 GB long; you should
                                # be using strnlen_user() instead

        .globl __strnlen_user

        .align 3
__strnlen_user:
        ldgp    $29,0($27)      # we do exceptions -- we need the gp.
        .prologue 1

        EX( ldq_u t0, 0(a0) )   # load first quadword (a0 may be misaligned)
        lda     t1, -1(zero)
        insqh   t1, a0, t1
        andnot  a0, 7, v0
        or      t1, t0, t0
        subq    a0, 1, a0       # get our +1 for the return 
        cmpbge  zero, t0, t1    # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
        subq    a1, 7, t2
        subq    a0, v0, t0
        bne     t1, $found

        addq    t2, t0, t2
        addq    a1, 1, a1

        .align 3
$loop:  ble     t2, $limit
        EX( ldq t0, 8(v0) )
        subq    t2, 8, t2
        addq    v0, 8, v0       # addr += 8
        cmpbge  zero, t0, t1
        beq     t1, $loop

$found: negq    t1, t2          # clear all but least set bit
        and     t1, t2, t1

        and     t1, 0xf0, t2    # binary search for that set bit
        and     t1, 0xcc, t3
        and     t1, 0xaa, t4
        cmovne  t2, 4, t2
        cmovne  t3, 2, t3
        cmovne  t4, 1, t4
        addq    t2, t3, t2
        addq    v0, t4, v0
        addq    v0, t2, v0
        nop                     # dual issue next two on ev4 and ev5
        subq    v0, a0, v0
$exception:
        ret

        .align 3                # currently redundant
$limit:
        subq    a1, t2, v0
        ret

        .end __strlen_user

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.