[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     ! 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>