diff options
author | Kevin | 2014-11-15 09:58:27 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 09:58:27 +0800 |
commit | 392e8802486cb573b916e746010e141a75f507e6 (patch) | |
tree | 50029aca02c81f087b90336e670b44e510782330 /ANDROID_3.4.5/arch/alpha/lib/strlen_user.S | |
download | FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.tar.gz FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.tar.bz2 FOSSEE-netbook-kernel-source-392e8802486cb573b916e746010e141a75f507e6.zip |
init android origin source code
Diffstat (limited to 'ANDROID_3.4.5/arch/alpha/lib/strlen_user.S')
-rw-r--r-- | ANDROID_3.4.5/arch/alpha/lib/strlen_user.S | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/arch/alpha/lib/strlen_user.S b/ANDROID_3.4.5/arch/alpha/lib/strlen_user.S new file mode 100644 index 00000000..508a18e9 --- /dev/null +++ b/ANDROID_3.4.5/arch/alpha/lib/strlen_user.S @@ -0,0 +1,91 @@ +/* + * 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"; \ + .long 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: + .prologue 0 + + 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 |