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

