mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer.
 | |
| 
 | |
| Copyright (C) 1996-2017 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of the GNU MP Library.
 | |
| 
 | |
| The GNU MP Library is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU Lesser General Public License as published by
 | |
| the Free Software Foundation; either version 2.1 of the License, or (at your
 | |
| option) any later version.
 | |
| 
 | |
| The GNU MP Library is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | |
| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 | |
| License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU Lesser General Public License
 | |
| along with the GNU MP Library.  If not, see <http://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| /*
 | |
|   INPUT PARAMETERS
 | |
|   res_ptr	(sp + 4)
 | |
|   s_ptr		(sp + 8)
 | |
|   s_size	(sp + 16)
 | |
|   cnt		(sp + 12)
 | |
| */
 | |
| 
 | |
| #include "sysdep.h"
 | |
| #include "asm-syntax.h"
 | |
| 
 | |
| #define res_ptr a1
 | |
| #define s_ptr a0
 | |
| #define s_size d6
 | |
| #define cnt d4
 | |
| 
 | |
| 	TEXT
 | |
| ENTRY(__mpn_lshift)
 | |
| 
 | |
| /* Save used registers on the stack.  */
 | |
| 	moveml	R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
 | |
| 	cfi_adjust_cfa_offset (6*4)
 | |
| 	cfi_rel_offset (R(d2), 0)
 | |
| 	cfi_rel_offset (R(d3), 4)
 | |
| 	cfi_rel_offset (R(d4), 8)
 | |
| 	cfi_rel_offset (R(d5), 12)
 | |
| 	cfi_rel_offset (R(d6), 16)
 | |
| 	cfi_rel_offset (R(a2), 20)
 | |
| 
 | |
| /* Copy the arguments to registers.  */
 | |
| 	movel	MEM_DISP(sp,28),R(res_ptr)
 | |
| 	movel	MEM_DISP(sp,32),R(s_ptr)
 | |
| 	movel	MEM_DISP(sp,36),R(s_size)
 | |
| 	movel	MEM_DISP(sp,40),R(cnt)
 | |
| 
 | |
| 	moveql	#1,R(d5)
 | |
| 	cmpl	R(d5),R(cnt)
 | |
| 	bne	L(Lnormal)
 | |
| 	cmpl	R(s_ptr),R(res_ptr)
 | |
| 	bls	L(Lspecial)		/* jump if s_ptr >= res_ptr */
 | |
| #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
 | |
| 	lea	MEM_INDX1(s_ptr,s_size,l,4),R(a2)
 | |
| #else /* not mc68020 */
 | |
| 	movel	R(s_size),R(d0)
 | |
| 	asll	#2,R(d0)
 | |
| 	lea	MEM_INDX(s_ptr,d0,l),R(a2)
 | |
| #endif
 | |
| 	cmpl	R(res_ptr),R(a2)
 | |
| 	bls	L(Lspecial)		/* jump if res_ptr >= s_ptr + s_size */
 | |
| 
 | |
| L(Lnormal:)
 | |
| 	moveql	#32,R(d5)
 | |
| 	subl	R(cnt),R(d5)
 | |
| 
 | |
| #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
 | |
| 	lea	MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
 | |
| 	lea	MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
 | |
| #else /* not mc68000 */
 | |
| 	movel	R(s_size),R(d0)
 | |
| 	asll	#2,R(d0)
 | |
| 	addl	R(s_size),R(s_ptr)
 | |
| 	addl	R(s_size),R(res_ptr)
 | |
| #endif
 | |
| 	movel	MEM_PREDEC(s_ptr),R(d2)
 | |
| 	movel	R(d2),R(d0)
 | |
| 	lsrl	R(d5),R(d0)		/* compute carry limb */
 | |
| 
 | |
| 	lsll	R(cnt),R(d2)
 | |
| 	movel	R(d2),R(d1)
 | |
| 	subql	#1,R(s_size)
 | |
| 	beq	L(Lend)
 | |
| 	lsrl	#1,R(s_size)
 | |
| 	bcs	L(L1)
 | |
| 	subql	#1,R(s_size)
 | |
| 
 | |
| L(Loop:)
 | |
| 	movel	MEM_PREDEC(s_ptr),R(d2)
 | |
| 	movel	R(d2),R(d3)
 | |
| 	lsrl	R(d5),R(d3)
 | |
| 	orl	R(d3),R(d1)
 | |
| 	movel	R(d1),MEM_PREDEC(res_ptr)
 | |
| 	lsll	R(cnt),R(d2)
 | |
| L(L1:)
 | |
| 	movel	MEM_PREDEC(s_ptr),R(d1)
 | |
| 	movel	R(d1),R(d3)
 | |
| 	lsrl	R(d5),R(d3)
 | |
| 	orl	R(d3),R(d2)
 | |
| 	movel	R(d2),MEM_PREDEC(res_ptr)
 | |
| 	lsll	R(cnt),R(d1)
 | |
| 
 | |
| 	dbf	R(s_size),L(Loop)
 | |
| 	subl	#0x10000,R(s_size)
 | |
| 	bcc	L(Loop)
 | |
| 
 | |
| L(Lend:)
 | |
| 	movel	R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */
 | |
| 
 | |
| /* Restore used registers from stack frame.  */
 | |
| 	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
 | |
| 	cfi_remember_state
 | |
| 	cfi_adjust_cfa_offset (-6*4)
 | |
| 	cfi_restore (R(d2))
 | |
| 	cfi_restore (R(d3))
 | |
| 	cfi_restore (R(d4))
 | |
| 	cfi_restore (R(d5))
 | |
| 	cfi_restore (R(d6))
 | |
| 	cfi_restore (R(a2))
 | |
| 	rts
 | |
| 
 | |
| /* We loop from least significant end of the arrays, which is only
 | |
|    permissible if the source and destination don't overlap, since the
 | |
|    function is documented to work for overlapping source and destination.  */
 | |
| 
 | |
| 	cfi_restore_state
 | |
| L(Lspecial:)
 | |
| 	clrl	R(d0)			/* initialize carry */
 | |
| 	eorw	#1,R(s_size)
 | |
| 	lsrl	#1,R(s_size)
 | |
| 	bcc	L(LL1)
 | |
| 	subql	#1,R(s_size)
 | |
| 
 | |
| L(LLoop:)
 | |
| 	movel	MEM_POSTINC(s_ptr),R(d2)
 | |
| 	addxl	R(d2),R(d2)
 | |
| 	movel	R(d2),MEM_POSTINC(res_ptr)
 | |
| L(LL1:)
 | |
| 	movel	MEM_POSTINC(s_ptr),R(d2)
 | |
| 	addxl	R(d2),R(d2)
 | |
| 	movel	R(d2),MEM_POSTINC(res_ptr)
 | |
| 
 | |
| 	dbf	R(s_size),L(LLoop)
 | |
| 	addxl	R(d0),R(d0)		/* save cy in lsb */
 | |
| 	subl	#0x10000,R(s_size)
 | |
| 	bcs	L(LLend)
 | |
| 	lsrl	#1,R(d0)		/* restore cy */
 | |
| 	bra	L(LLoop)
 | |
| 
 | |
| L(LLend:)
 | |
| /* Restore used registers from stack frame.  */
 | |
| 	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
 | |
| 	cfi_adjust_cfa_offset (-6*4)
 | |
| 	cfi_restore (R(d2))
 | |
| 	cfi_restore (R(d3))
 | |
| 	cfi_restore (R(d4))
 | |
| 	cfi_restore (R(d5))
 | |
| 	cfi_restore (R(d6))
 | |
| 	cfi_restore (R(a2))
 | |
| 	rts
 | |
| END(__mpn_lshift)
 |