Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
		
			
				
	
	
		
			91 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/*
 | 
						|
 * 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
 |