/*1* arch/alpha/lib/strlen_user.S2*3* Return the length of the string including the NUL terminator4* (strlen+1) or zero if an error occurred.5*6* In places where it is critical to limit the processing time,7* and the data is not trusted, strnlen_user() should be used.8* It will return a value greater than its second argument if9* that limit would be exceeded. This implementation is allowed10* to access memory beyond the limit, but will not cross a page11* boundary when doing so.12*/1314#include <asm/regdef.h>151617/* Allow an exception for an insn; exit if we get one. */18#define EX(x,y...) \1999: x,##y; \20.section __ex_table,"a"; \21.long 99b - .; \22lda v0, $exception-99b(zero); \23.previous242526.set noreorder27.set noat28.text2930.globl __strlen_user31.ent __strlen_user32.frame sp, 0, ra3334.align 335__strlen_user:36ldah a1, 32767(zero) # do not use plain strlen_user() for strings37# that might be almost 2 GB long; you should38# be using strnlen_user() instead3940.globl __strnlen_user4142.align 343__strnlen_user:44.prologue 04546EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned)47lda t1, -1(zero)48insqh t1, a0, t149andnot a0, 7, v050or t1, t0, t051subq a0, 1, a0 # get our +1 for the return52cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 053subq a1, 7, t254subq a0, v0, t055bne t1, $found5657addq t2, t0, t258addq a1, 1, a15960.align 361$loop: ble t2, $limit62EX( ldq t0, 8(v0) )63subq t2, 8, t264addq v0, 8, v0 # addr += 865cmpbge zero, t0, t166beq t1, $loop6768$found: negq t1, t2 # clear all but least set bit69and t1, t2, t17071and t1, 0xf0, t2 # binary search for that set bit72and t1, 0xcc, t373and t1, 0xaa, t474cmovne t2, 4, t275cmovne t3, 2, t376cmovne t4, 1, t477addq t2, t3, t278addq v0, t4, v079addq v0, t2, v080nop # dual issue next two on ev4 and ev581subq v0, a0, v082$exception:83ret8485.align 3 # currently redundant86$limit:87subq a1, t2, v088ret8990.end __strlen_user919293