 1da177e4c3
			
		
	
	
	1da177e4c3
	
	
	
		
			
			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!
		
			
				
	
	
		
			107 lines
		
	
	
	
		
			2.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			2.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * arch/alpha/lib/ev67-strlen_user.S
 | |
|  * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
 | |
|  *
 | |
|  * Return the length of the string including the NULL 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.
 | |
|  *
 | |
|  * Much of the information about 21264 scheduling/coding comes from:
 | |
|  *      Compiler Writer's Guide for the Alpha 21264
 | |
|  *      abbreviated as 'CWG' in other comments here
 | |
|  *      ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
 | |
|  * Scheduling notation:
 | |
|  *      E       - either cluster
 | |
|  *      U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
 | |
|  *      L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
 | |
|  * Try not to change the actual algorithm if possible for consistency.
 | |
|  */
 | |
| 
 | |
| #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 4
 | |
| __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
 | |
| 	nop
 | |
| 	nop
 | |
| 	nop
 | |
| 
 | |
| 	.globl __strnlen_user
 | |
| 
 | |
| 	.align 4
 | |
| __strnlen_user:
 | |
| 	.prologue 0
 | |
| 	EX( ldq_u t0, 0(a0) )	# L : load first quadword (a0 may be misaligned)
 | |
| 	lda     t1, -1(zero)	# E :
 | |
| 
 | |
| 	insqh   t1, a0, t1	# U :
 | |
| 	andnot  a0, 7, v0	# E :
 | |
| 	or      t1, t0, t0	# E :
 | |
| 	subq	a0, 1, a0	# E : get our +1 for the return 
 | |
| 
 | |
| 	cmpbge  zero, t0, t1	# E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
 | |
| 	subq	a1, 7, t2	# E :
 | |
| 	subq	a0, v0, t0	# E :
 | |
| 	bne     t1, $found	# U :
 | |
| 
 | |
| 	addq	t2, t0, t2	# E :
 | |
| 	addq	a1, 1, a1	# E :
 | |
| 	nop			# E :
 | |
| 	nop			# E :
 | |
| 
 | |
| 	.align 4
 | |
| $loop:	ble	t2, $limit	# U :
 | |
| 	EX( ldq t0, 8(v0) )	# L :
 | |
| 	nop			# E :
 | |
| 	nop			# E :
 | |
| 
 | |
| 	cmpbge  zero, t0, t1	# E :
 | |
| 	subq	t2, 8, t2	# E :
 | |
| 	addq    v0, 8, v0	# E : addr += 8
 | |
| 	beq     t1, $loop	# U :
 | |
| 
 | |
| $found: cttz	t1, t2		# U0 :
 | |
| 	addq	v0, t2, v0	# E :
 | |
| 	subq    v0, a0, v0	# E :
 | |
| 	ret			# L0 :
 | |
| 
 | |
| $exception:
 | |
| 	nop
 | |
| 	nop
 | |
| 	nop
 | |
| 	ret
 | |
| 
 | |
| 	.align 4		# currently redundant
 | |
| $limit:
 | |
| 	nop
 | |
| 	nop
 | |
| 	subq	a1, t2, v0
 | |
| 	ret
 | |
| 
 | |
| 	.end __strlen_user
 |