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 .long 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 .prologue 0 60 EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned) 61 lda t1, -1(zero) # E : 62 63 insqh t1, a0, t1 # U : 64 andnot a0, 7, v0 # E : 65 or t1, t0, t0 # E : 66 subq a0, 1, a0 # E : get our +1 for the return 67 68 cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0 69 subq a1, 7, t2 # E : 70 subq a0, v0, t0 # E : 71 bne t1, $found # U : 72 73 addq t2, t0, t2 # E : 74 addq a1, 1, a1 # E : 75 nop # E : 76 nop # E : 77 78 .align 4 79$loop: ble t2, $limit # U : 80 EX( ldq t0, 8(v0) ) # L : 81 nop # E : 82 nop # E : 83 84 cmpbge zero, t0, t1 # E : 85 subq t2, 8, t2 # E : 86 addq v0, 8, v0 # E : addr += 8 87 beq t1, $loop # U : 88 89$found: cttz t1, t2 # U0 : 90 addq v0, t2, v0 # E : 91 subq v0, a0, v0 # E : 92 ret # L0 : 93 94$exception: 95 nop 96 nop 97 nop 98 ret 99 100 .align 4 # currently redundant 101$limit: 102 nop 103 nop 104 subq a1, t2, v0 105 ret 106 107 .end __strlen_user 108