Blame mpn/m68k/lshift.asm

Packit 5c3484
dnl  mc68020 mpn_lshift -- mpn left shift.
Packit 5c3484
Packit 5c3484
dnl  Copyright 1996, 1999-2003 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
dnl  This file is part of the GNU MP Library.
Packit 5c3484
dnl
Packit 5c3484
dnl  The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
dnl  it under the terms of either:
Packit 5c3484
dnl
Packit 5c3484
dnl    * the GNU Lesser General Public License as published by the Free
Packit 5c3484
dnl      Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
dnl      option) any later version.
Packit 5c3484
dnl
Packit 5c3484
dnl  or
Packit 5c3484
dnl
Packit 5c3484
dnl    * the GNU General Public License as published by the Free Software
Packit 5c3484
dnl      Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
dnl      later version.
Packit 5c3484
dnl
Packit 5c3484
dnl  or both in parallel, as here.
Packit 5c3484
dnl
Packit 5c3484
dnl  The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
dnl  for more details.
Packit 5c3484
dnl
Packit 5c3484
dnl  You should have received copies of the GNU General Public License and the
Packit 5c3484
dnl  GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
dnl  see https://www.gnu.org/licenses/.
Packit 5c3484
Packit 5c3484
include(`../config.m4')
Packit 5c3484
Packit 5c3484
Packit 5c3484
C           cycles/limb
Packit 5c3484
C        shift==1  shift>1
Packit 5c3484
C 68040:    5         12
Packit 5c3484
Packit 5c3484
Packit 5c3484
C mp_limb_t mpn_lshift (mp_ptr res_ptr, mp_srcptr s_ptr, mp_size_t s_size,
Packit 5c3484
C                       unsigned cnt);
Packit 5c3484
C
Packit 5c3484
C The "cnt" parameter is either 16 bits or 32 bits depending on
Packit 5c3484
C SIZEOF_UNSIGNED (see ABI notes in mpn/m68k/README).  The value is of
Packit 5c3484
C course only 1 to 31.  When loaded as 16 bits there's garbage in the upper
Packit 5c3484
C half, hence the use of cmpw.  The shift instructions take the their count
Packit 5c3484
C modulo 64, so the upper part doesn't matter to them either.
Packit 5c3484
C
Packit 5c3484
Packit 5c3484
C INPUT PARAMETERS
Packit 5c3484
C res_ptr	(sp + 4)
Packit 5c3484
C s_ptr		(sp + 8)
Packit 5c3484
C s_size	(sp + 12)
Packit 5c3484
C cnt		(sp + 16)
Packit 5c3484
Packit 5c3484
define(res_ptr, `a1')
Packit 5c3484
define(s_ptr,   `a0')
Packit 5c3484
define(s_size,  `d6')
Packit 5c3484
define(cnt,     `d4')
Packit 5c3484
Packit 5c3484
ifdef(`SIZEOF_UNSIGNED',,
Packit 5c3484
`m4_error(`SIZEOF_UNSIGNED not defined, should be in config.m4
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
PROLOGUE(mpn_lshift)
Packit 5c3484
C Save used registers on the stack.
Packit 5c3484
	moveml	d2-d6/a2, M(-,sp)
Packit 5c3484
Packit 5c3484
C Copy the arguments to registers.
Packit 5c3484
	movel	M(sp,28), res_ptr
Packit 5c3484
	movel	M(sp,32), s_ptr
Packit 5c3484
	movel	M(sp,36), s_size
Packit 5c3484
ifelse(SIZEOF_UNSIGNED,2,
Packit 5c3484
`	movew	M(sp,40), cnt',
Packit 5c3484
`	movel	M(sp,40), cnt')
Packit 5c3484
Packit 5c3484
	moveql	#1, d5
Packit 5c3484
	cmpw	d5, cnt
Packit 5c3484
	bne	L(Lnormal)
Packit 5c3484
	cmpl	s_ptr, res_ptr
Packit 5c3484
	bls	L(Lspecial)		C jump if s_ptr >= res_ptr
Packit 5c3484
Packit 5c3484
ifelse(scale_available_p,1,`
Packit 5c3484
	lea	M(s_ptr,s_size,l,4), a2
Packit 5c3484
',`
Packit 5c3484
	movel	s_size, d0
Packit 5c3484
	asll	#2, d0
Packit 5c3484
	lea	M(s_ptr,d0,l), a2
Packit 5c3484
')
Packit 5c3484
	cmpl	res_ptr, a2
Packit 5c3484
	bls	L(Lspecial)		C jump if res_ptr >= s_ptr + s_size
Packit 5c3484
Packit 5c3484
L(Lnormal):
Packit 5c3484
	moveql	#32, d5
Packit 5c3484
	subl	cnt, d5
Packit 5c3484
Packit 5c3484
ifelse(scale_available_p,1,`
Packit 5c3484
	lea	M(s_ptr,s_size,l,4), s_ptr
Packit 5c3484
	lea	M(res_ptr,s_size,l,4), res_ptr
Packit 5c3484
',`
Packit 5c3484
	movel	s_size, d0
Packit 5c3484
	asll	#2, d0
Packit 5c3484
	addl	d0, s_ptr
Packit 5c3484
	addl	d0, res_ptr
Packit 5c3484
')
Packit 5c3484
	movel	M(-,s_ptr), d2
Packit 5c3484
	movel	d2, d0
Packit 5c3484
	lsrl	d5, d0		C compute carry limb
Packit 5c3484
Packit 5c3484
	lsll	cnt, d2
Packit 5c3484
	movel	d2, d1
Packit 5c3484
	subql	#1, s_size
Packit 5c3484
	beq	L(Lend)
Packit 5c3484
	lsrl	#1, s_size
Packit 5c3484
	bcs	L(L1)
Packit 5c3484
	subql	#1, s_size
Packit 5c3484
Packit 5c3484
L(Loop):
Packit 5c3484
	movel	M(-,s_ptr), d2
Packit 5c3484
	movel	d2, d3
Packit 5c3484
	lsrl	d5, d3
Packit 5c3484
	orl	d3, d1
Packit 5c3484
	movel	d1, M(-,res_ptr)
Packit 5c3484
	lsll	cnt, d2
Packit 5c3484
L(L1):
Packit 5c3484
	movel	M(-,s_ptr), d1
Packit 5c3484
	movel	d1, d3
Packit 5c3484
	lsrl	d5, d3
Packit 5c3484
	orl	d3, d2
Packit 5c3484
	movel	d2, M(-,res_ptr)
Packit 5c3484
	lsll	cnt, d1
Packit 5c3484
Packit 5c3484
	dbf	s_size, L(Loop)
Packit 5c3484
	subl	#0x10000, s_size
Packit 5c3484
	bcc	L(Loop)
Packit 5c3484
Packit 5c3484
L(Lend):
Packit 5c3484
	movel	d1, M(-,res_ptr)	C store least significant limb
Packit 5c3484
Packit 5c3484
C Restore used registers from stack frame.
Packit 5c3484
	moveml	M(sp,+), d2-d6/a2
Packit 5c3484
	rts
Packit 5c3484
Packit 5c3484
C We loop from least significant end of the arrays, which is only
Packit 5c3484
C permissable if the source and destination don't overlap, since the
Packit 5c3484
C function is documented to work for overlapping source and destination.
Packit 5c3484
Packit 5c3484
L(Lspecial):
Packit 5c3484
	clrl	d0			C initialize carry
Packit 5c3484
	eorw	#1, s_size
Packit 5c3484
	lsrl	#1, s_size
Packit 5c3484
	bcc	L(LL1)
Packit 5c3484
	subql	#1, s_size
Packit 5c3484
Packit 5c3484
L(LLoop):
Packit 5c3484
	movel	M(s_ptr,+), d2
Packit 5c3484
	addxl	d2, d2
Packit 5c3484
	movel	d2, M(res_ptr,+)
Packit 5c3484
L(LL1):
Packit 5c3484
	movel	M(s_ptr,+), d2
Packit 5c3484
	addxl	d2, d2
Packit 5c3484
	movel	d2, M(res_ptr,+)
Packit 5c3484
Packit 5c3484
	dbf	s_size, L(LLoop)
Packit 5c3484
	addxl	d0, d0		C save cy in lsb
Packit 5c3484
	subl	#0x10000, s_size
Packit 5c3484
	bcs	L(LLend)
Packit 5c3484
	lsrl	#1, d0		C restore cy
Packit 5c3484
	bra	L(LLoop)
Packit 5c3484
Packit 5c3484
L(LLend):
Packit 5c3484
C Restore used registers from stack frame.
Packit 5c3484
	moveml	M(sp,+), d2-d6/a2
Packit 5c3484
	rts
Packit 5c3484
Packit 5c3484
EPILOGUE(mpn_lshift)