~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/gmp/mpn/x86/pentium4/sse2/submul_1.asm

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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()