dnl Intel Pentium mpn_mul_2 -- mpn by 2-limb multiplication.
dnl Copyright 2001, 2002 Free Software Foundation, Inc.
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 modify
dnl it under the terms of either:
dnl
dnl * the GNU Lesser General Public License as published by the Free
dnl Software Foundation; either version 3 of the License, or (at your
dnl option) any later version.
dnl
dnl or
dnl
dnl * the GNU General Public License as published by the Free Software
dnl Foundation; either version 2 of the License, or (at your option) any
dnl later version.
dnl
dnl or both in parallel, as here.
dnl
dnl The GNU MP Library is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
dnl for more details.
dnl
dnl You should have received copies of the GNU General Public License and the
dnl GNU Lesser General Public License along with the GNU MP Library. If not,
dnl see https://www.gnu.org/licenses/.
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()