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

« back to all changes in this revision

Viewing changes to src/gmp/mpn/x86/k6/divrem_1.asm

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2007-04-09 11:51:51 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070409115151-ql8cr0kalzx1jmla
Tags: 0.9i-20070324-2
Upload to unstable. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
dnl  AMD K6 mpn_divrem_1 -- mpn by limb division.
 
2
 
 
3
dnl  Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
4
dnl
 
5
dnl  This file is part of the GNU MP Library.
 
6
dnl
 
7
dnl  The GNU MP Library is free software; you can redistribute it and/or
 
8
dnl  modify it under the terms of the GNU Lesser General Public License as
 
9
dnl  published by the Free Software Foundation; either version 2.1 of the
 
10
dnl  License, or (at your option) any later version.
 
11
dnl
 
12
dnl  The GNU MP Library is distributed in the hope that it will be useful,
 
13
dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
dnl  Lesser General Public License for more details.
 
16
dnl
 
17
dnl  You should have received a copy of the GNU Lesser General Public
 
18
dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
 
19
dnl  not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 
20
dnl  Fifth Floor, Boston, MA 02110-1301, USA.
 
21
 
 
22
include(`../config.m4')
 
23
 
 
24
 
 
25
C K6: 20 cycles/limb
 
26
 
 
27
 
 
28
C mp_limb_t mpn_divrem_1 (mp_ptr dst, mp_size_t xsize,
 
29
C                         mp_srcptr src, mp_size_t size, mp_limb_t divisor);
 
30
C mp_limb_t mpn_divrem_1c (mp_ptr dst, mp_size_t xsize,
 
31
C                          mp_srcptr src, mp_size_t size, mp_limb_t divisor,
 
32
C                          mp_limb_t carry);
 
33
C
 
34
C The code here is basically the same as mpn/x86/divrem_1.asm, but uses loop
 
35
C instead of decl+jnz, since it comes out 2 cycles/limb faster.
 
36
C
 
37
C A test is done to see if the high limb is less the the divisor, and if so
 
38
C one less div is done.  A div is 20 cycles, so assuming high<divisor about
 
39
C half the time, then this test saves half that amount.  The branch
 
40
C misprediction penalty is less than that.
 
41
C
 
42
C Back-to-back div instructions run at 20 cycles, the same as the loop here,
 
43
C so it seems there's nothing to gain by rearranging the loop.  Pairing the
 
44
C mov and loop instructions was found to gain nothing.
 
45
C
 
46
C Enhancements:
 
47
C
 
48
C The low-latency K6 multiply might be thought to suit a mul-by-inverse, but
 
49
C that algorithm has been found to suffer from the relatively poor carry
 
50
C handling on K6 and too many auxiliary instructions.  The fractional part
 
51
C however could be done at about 13 c/l, if it mattered enough.
 
52
 
 
53
defframe(PARAM_CARRY,  24)
 
54
defframe(PARAM_DIVISOR,20)
 
55
defframe(PARAM_SIZE,   16)
 
56
defframe(PARAM_SRC,    12)
 
57
defframe(PARAM_XSIZE,  8)
 
58
defframe(PARAM_DST,    4)
 
59
 
 
60
        TEXT
 
61
 
 
62
        ALIGN(32)
 
63
PROLOGUE(mpn_divrem_1c)
 
64
deflit(`FRAME',0)
 
65
 
 
66
        movl    PARAM_SIZE, %ecx
 
67
        pushl   %edi            FRAME_pushl()
 
68
 
 
69
        movl    PARAM_SRC, %edi
 
70
        pushl   %esi            FRAME_pushl()
 
71
 
 
72
        movl    PARAM_DIVISOR, %esi
 
73
        pushl   %ebx            FRAME_pushl()
 
74
 
 
75
        movl    PARAM_DST, %ebx
 
76
        pushl   %ebp            FRAME_pushl()
 
77
 
 
78
        movl    PARAM_XSIZE, %ebp
 
79
        orl     %ecx, %ecx              C size
 
80
 
 
81
        movl    PARAM_CARRY, %edx
 
82
        jz      L(fraction)             C if size==0
 
83
 
 
84
        leal    -4(%ebx,%ebp,4), %ebx   C dst one limb below integer part
 
85
        jmp     L(integer_top)
 
86
 
 
87
EPILOGUE()
 
88
 
 
89
 
 
90
        ALIGN(16)
 
91
PROLOGUE(mpn_divrem_1)
 
92
deflit(`FRAME',0)
 
93
 
 
94
        movl    PARAM_SIZE, %ecx
 
95
        pushl   %edi            FRAME_pushl()
 
96
 
 
97
        movl    PARAM_SRC, %edi
 
98
        pushl   %esi            FRAME_pushl()
 
99
 
 
100
        movl    PARAM_DIVISOR, %esi
 
101
        orl     %ecx,%ecx               C size
 
102
 
 
103
        jz      L(size_zero)
 
104
        pushl   %ebx            FRAME_pushl()
 
105
 
 
106
        movl    -4(%edi,%ecx,4), %eax   C src high limb
 
107
        xorl    %edx, %edx
 
108
 
 
109
        movl    PARAM_DST, %ebx
 
110
        pushl   %ebp            FRAME_pushl()
 
111
 
 
112
        movl    PARAM_XSIZE, %ebp
 
113
        cmpl    %esi, %eax
 
114
 
 
115
        leal    -4(%ebx,%ebp,4), %ebx   C dst one limb below integer part
 
116
        jae     L(integer_entry)
 
117
 
 
118
 
 
119
        C high<divisor, so high of dst is zero, and avoid one div
 
120
 
 
121
        movl    %edx, (%ebx,%ecx,4)
 
122
        decl    %ecx
 
123
 
 
124
        movl    %eax, %edx
 
125
        jz      L(fraction)
 
126
 
 
127
 
 
128
L(integer_top):
 
129
        C eax   scratch (quotient)
 
130
        C ebx   dst+4*xsize-4
 
131
        C ecx   counter
 
132
        C edx   scratch (remainder)
 
133
        C esi   divisor
 
134
        C edi   src
 
135
        C ebp   xsize
 
136
 
 
137
        movl    -4(%edi,%ecx,4), %eax
 
138
L(integer_entry):
 
139
 
 
140
        divl    %esi
 
141
 
 
142
        movl    %eax, (%ebx,%ecx,4)
 
143
        loop    L(integer_top)
 
144
 
 
145
 
 
146
L(fraction):
 
147
        orl     %ebp, %ecx
 
148
        jz      L(done)
 
149
 
 
150
        movl    PARAM_DST, %ebx
 
151
 
 
152
 
 
153
L(fraction_top):
 
154
        C eax   scratch (quotient)
 
155
        C ebx   dst
 
156
        C ecx   counter
 
157
        C edx   scratch (remainder)
 
158
        C esi   divisor
 
159
        C edi
 
160
        C ebp
 
161
 
 
162
        xorl    %eax, %eax
 
163
 
 
164
        divl    %esi
 
165
 
 
166
        movl    %eax, -4(%ebx,%ecx,4)
 
167
        loop    L(fraction_top)
 
168
 
 
169
 
 
170
L(done):
 
171
        popl    %ebp
 
172
        movl    %edx, %eax
 
173
        popl    %ebx
 
174
        popl    %esi
 
175
        popl    %edi
 
176
        ret
 
177
 
 
178
 
 
179
L(size_zero):
 
180
deflit(`FRAME',8)
 
181
        movl    PARAM_XSIZE, %ecx
 
182
        xorl    %eax, %eax
 
183
 
 
184
        movl    PARAM_DST, %edi
 
185
 
 
186
        cld     C better safe than sorry, see mpn/x86/README
 
187
 
 
188
        rep
 
189
        stosl
 
190
 
 
191
        popl    %esi
 
192
        popl    %edi
 
193
        ret
 
194
EPILOGUE()