mpir/mpn/x86/pentium/mul_2.asm

142 lines
3.1 KiB
NASM
Raw Normal View History

dnl Intel Pentium mpn_mul_2 -- mpn by 2-limb multiplication.
dnl Copyright 2001, 2002 Free Software Foundation, Inc.
dnl
dnl This file is part of the GNU MP Library.
dnl
dnl The GNU MP Library is free software; you can redistribute it and/or
dnl modify it under the terms of the GNU Lesser General Public License as
dnl published by the Free Software Foundation; either version 2.1 of the
dnl License, or (at your option) any later version.
dnl
dnl The GNU MP Library is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl Lesser General Public License for more details.
dnl
dnl You should have received a copy of the GNU Lesser General Public
dnl License along with the GNU MP Library; see the file COPYING.LIB. If
dnl not, write to the Free Software Foundation, Inc., 51 Franklin Street,
dnl Fifth Floor, Boston, MA 02110-1301, USA. */
include(`../config.m4')
C P5: 24.0 cycles/limb
C mp_limb_t mpn_mul_2 (mp_ptr dst, mp_srcptr src, mp_size_t size,
C mp_srcptr mult);
C
C At 24 c/l this is only 2 cycles faster than a separate mul_1 and addmul_1,
C but has the advantage of making just one pass over the operands.
C
C There's not enough registers to use PARAM_MULT directly, so the multiplier
C limbs are transferred to local variables on the stack.
defframe(PARAM_MULT, 16)
defframe(PARAM_SIZE, 12)
defframe(PARAM_SRC, 8)
defframe(PARAM_DST, 4)
dnl re-use parameter space
define(VAR_MULT_LOW, `PARAM_SRC')
define(VAR_MULT_HIGH,`PARAM_DST')
TEXT
ALIGN(8)
PROLOGUE(mpn_mul_2)
deflit(`FRAME',0)
pushl %esi FRAME_pushl()
pushl %edi FRAME_pushl()
movl PARAM_SRC, %esi
movl PARAM_DST, %edi
movl PARAM_MULT, %eax
movl PARAM_SIZE, %ecx
movl 4(%eax), %edx C mult high
movl (%eax), %eax C mult low
movl %eax, VAR_MULT_LOW
movl %edx, VAR_MULT_HIGH
pushl %ebx FRAME_pushl()
pushl %ebp FRAME_pushl()
mull (%esi) C src[0] * mult[0]
movl %eax, %ebp C in case src==dst
movl (%esi), %eax C src[0]
movl %ebp, (%edi) C dst[0]
movl %edx, %ebx C initial low carry
xorl %ebp, %ebp C initial high carry
leal (%edi,%ecx,4), %edi C dst end
mull VAR_MULT_HIGH C src[0] * mult[1]
subl $2, %ecx C size-2
js L(done)
leal 8(%esi,%ecx,4), %esi C &src[size]
xorl $-1, %ecx C -(size-1)
L(top):
C eax low prod
C ebx low carry
C ecx counter, negative
C edx high prod
C esi src end
C edi dst end
C ebp high carry (0 or -1)
andl $1, %ebp C 1 or 0
addl %eax, %ebx
adcl %edx, %ebp
ASSERT(nc)
movl (%esi,%ecx,4), %eax
mull VAR_MULT_LOW
addl %eax, %ebx C low carry
movl (%esi,%ecx,4), %eax
adcl %ebp, %edx C high carry
movl %ebx, (%edi,%ecx,4)
sbbl %ebp, %ebp C new high carry, -1 or 0
movl %edx, %ebx C new low carry
mull VAR_MULT_HIGH
incl %ecx
jnz L(top)
L(done):
andl $1, %ebp C 1 or 0
addl %ebx, %eax
adcl %ebp, %edx
ASSERT(nc)
movl %eax, (%edi) C store carry low
movl %edx, %eax C return carry high
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
EPILOGUE()