Blame sysdeps/m68k/m680x0/rshift.S

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