[BACK]Return to submul_1.asm CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / x86 / pentium4 / sse2

Annotation of OpenXM_contrib/gmp/mpn/x86/pentium4/sse2/submul_1.asm, Revision 1.1.1.1

1.1       ohara       1: dnl  Intel Pentium-4 mpn_submul_1 -- Multiply a limb vector with a limb and
                      2: dnl  subtract the result from a second limb vector.
                      3:
                      4: dnl  Copyright 2001, 2002 Free Software Foundation, Inc.
                      5: dnl
                      6: dnl  This file is part of the GNU MP Library.
                      7: dnl
                      8: dnl  The GNU MP Library is free software; you can redistribute it and/or
                      9: dnl  modify it under the terms of the GNU Lesser General Public License as
                     10: dnl  published by the Free Software Foundation; either version 2.1 of the
                     11: dnl  License, or (at your option) any later version.
                     12: dnl
                     13: dnl  The GNU MP Library is distributed in the hope that it will be useful,
                     14: dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     16: dnl  Lesser General Public License for more details.
                     17: dnl
                     18: dnl  You should have received a copy of the GNU Lesser General Public
                     19: dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
                     20: dnl  not, write to the Free Software Foundation, Inc., 59 Temple Place -
                     21: dnl  Suite 330, Boston, MA 02111-1307, USA.
                     22:
                     23: include(`../config.m4')
                     24:
                     25:
                     26: C P4: 7 cycles/limb, unstable timing, at least on early Pentium4 silicon
                     27: C     (stepping 10).
                     28:
                     29:
                     30: C mp_limb_t mpn_submul_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
                     31: C                         mp_limb_t mult);
                     32: C mp_limb_t mpn_submul_1c (mp_ptr dst, mp_srcptr src, mp_size_t size,
                     33: C                          mp_limb_t mult, mp_limb_t carry);
                     34: C
                     35: C This code is not particularly good at 7 c/l.  The dependent chain is only
                     36: C 4 c/l and there's only 4 MMX unit instructions, so it's not clear why that
                     37: C speed isn't achieved.
                     38: C
                     39: C The arrangements made here to get a two instruction dependent chain are
                     40: C slightly subtle.  In the loop the carry (or borrow rather) is a negative
                     41: C so that a paddq can be used to give a low limb ready to store, and a high
                     42: C limb ready to become the new carry after a psrlq.
                     43: C
                     44: C If the carry was a simple twos complement negative then the psrlq shift
                     45: C would need to bring in 0 bits or 1 bits according to whether the high was
                     46: C zero or non-zero, since a non-zero value would represent a negative
                     47: C needing sign extension.  That wouldn't be particularly easy to arrange and
                     48: C certainly would add an instruction to the dependent chain, so instead an
                     49: C offset is applied so that the high limb will be 0xFFFFFFFF+c.  With c in
                     50: C the range -0xFFFFFFFF to 0, the value 0xFFFFFFFF+c is in the range 0 to
                     51: C 0xFFFFFFFF and is therefore always positive and can always have 0 bits
                     52: C shifted in, which is what psrlq does.
                     53: C
                     54: C The extra 0xFFFFFFFF must be subtracted before c is used, but that can be
                     55: C done off the dependent chain.  The total adjustment then is to add
                     56: C 0xFFFFFFFF00000000 to offset the new carry, and subtract
                     57: C 0x00000000FFFFFFFF to remove the offset from the current carry, for a net
                     58: C add of 0xFFFFFFFE00000001.  In the code this is applied to the destination
                     59: C limb when fetched.
                     60: C
                     61: C It's also possible to view the 0xFFFFFFFF adjustment as a ones-complement
                     62: C negative, which is how it's undone for the return value, but that doesn't
                     63: C seem as clear.
                     64:
                     65: defframe(PARAM_CARRY,     20)
                     66: defframe(PARAM_MULTIPLIER,16)
                     67: defframe(PARAM_SIZE,      12)
                     68: defframe(PARAM_SRC,       8)
                     69: defframe(PARAM_DST,       4)
                     70:
                     71:        TEXT
                     72:        ALIGN(16)
                     73:
                     74: PROLOGUE(mpn_submul_1c)
                     75: deflit(`FRAME',0)
                     76:        movd    PARAM_CARRY, %mm1
                     77:        jmp     L(start_1c)
                     78: EPILOGUE()
                     79:
                     80: PROLOGUE(mpn_submul_1)
                     81: deflit(`FRAME',0)
                     82:        pxor    %mm1, %mm1              C initial borrow
                     83:
                     84: L(start_1c):
                     85:        movl    PARAM_SRC, %eax
                     86:        pcmpeqd %mm0, %mm0
                     87:
                     88:        movd    PARAM_MULTIPLIER, %mm7
                     89:        pcmpeqd %mm6, %mm6
                     90:
                     91:        movl    PARAM_DST, %edx
                     92:        psrlq   $32, %mm0               C 0x00000000FFFFFFFF
                     93:
                     94:        movl    PARAM_SIZE, %ecx
                     95:        psllq   $32, %mm6               C 0xFFFFFFFF00000000
                     96:
                     97:        psubq   %mm0, %mm6              C 0xFFFFFFFE00000001
                     98:
                     99:        psubq   %mm1, %mm0              C 0xFFFFFFFF - borrow
                    100:
                    101:
                    102:        C eax   src, incrementing
                    103:        C ebx
                    104:        C ecx   loop counter, decrementing
                    105:        C edx   dst, incrementing
                    106:        C
                    107:        C mm0   0xFFFFFFFF - borrow
                    108:        C mm6   0xFFFFFFFE00000001
                    109:        C mm7   multiplier
                    110:
                    111: L(loop):
                    112:        movd    (%eax), %mm1            C src
                    113:        leal    4(%eax), %eax
                    114:        movd    (%edx), %mm2            C dst
                    115:        paddq   %mm6, %mm2              C add 0xFFFFFFFE00000001
                    116:        pmuludq %mm7, %mm1
                    117:        psubq   %mm1, %mm2              C prod
                    118:        paddq   %mm2, %mm0              C borrow
                    119:        subl    $1, %ecx
                    120:        movd    %mm0, (%edx)            C result
                    121:        psrlq   $32, %mm0
                    122:        leal    4(%edx), %edx
                    123:        jnz     L(loop)
                    124:
                    125:        movd    %mm0, %eax
                    126:        notl    %eax
                    127:        emms
                    128:        ret
                    129:
                    130: EPILOGUE()

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>