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

« back to all changes in this revision

Viewing changes to src/gmp/mpn/x86/p6/aorsmul_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 P6 mpn_addmul_1/mpn_submul_1 -- add or subtract mpn multiple.
 
2
 
 
3
dnl  Copyright 1999, 2000, 2001, 2002 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., 59 Temple Place -
 
20
dnl  Suite 330, Boston, MA 02111-1307, USA.
 
21
 
 
22
include(`../config.m4')
 
23
 
 
24
 
 
25
C P6: 6.35 cycles/limb (at 16 limbs/loop).
 
26
 
 
27
 
 
28
dnl  P6 UNROLL_COUNT cycles/limb
 
29
dnl          8           6.7
 
30
dnl         16           6.35
 
31
dnl         32           6.3
 
32
dnl         64           6.3
 
33
dnl  Maximum possible with the current code is 64.
 
34
 
 
35
deflit(UNROLL_COUNT, 16)
 
36
 
 
37
 
 
38
ifdef(`OPERATION_addmul_1', `
 
39
        define(M4_inst,        addl)
 
40
        define(M4_function_1,  mpn_addmul_1)
 
41
        define(M4_function_1c, mpn_addmul_1c)
 
42
        define(M4_description, add it to)
 
43
        define(M4_desc_retval, carry)
 
44
',`ifdef(`OPERATION_submul_1', `
 
45
        define(M4_inst,        subl)
 
46
        define(M4_function_1,  mpn_submul_1)
 
47
        define(M4_function_1c, mpn_submul_1c)
 
48
        define(M4_description, subtract it from)
 
49
        define(M4_desc_retval, borrow)
 
50
',`m4_error(`Need OPERATION_addmul_1 or OPERATION_submul_1
 
51
')')')
 
52
 
 
53
MULFUNC_PROLOGUE(mpn_addmul_1 mpn_addmul_1c mpn_submul_1 mpn_submul_1c)
 
54
 
 
55
 
 
56
C mp_limb_t M4_function_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
 
57
C                            mp_limb_t mult);
 
58
C mp_limb_t M4_function_1c (mp_ptr dst, mp_srcptr src, mp_size_t size,
 
59
C                             mp_limb_t mult, mp_limb_t carry);
 
60
C
 
61
C Calculate src,size multiplied by mult and M4_description dst,size.
 
62
C Return the M4_desc_retval limb from the top of the result.
 
63
C
 
64
C This code is pretty much the same as the K6 code.  The unrolled loop is
 
65
C the same, but there's just a few scheduling tweaks in the setups and the
 
66
C simple loop.
 
67
C
 
68
C A number of variations have been tried for the unrolled loop, with one or
 
69
C two carries, and with loads scheduled earlier, but nothing faster than 6
 
70
C cycles/limb has been found.
 
71
 
 
72
ifdef(`PIC',`
 
73
deflit(UNROLL_THRESHOLD, 5)
 
74
',`
 
75
deflit(UNROLL_THRESHOLD, 5)
 
76
')
 
77
 
 
78
defframe(PARAM_CARRY,     20)
 
79
defframe(PARAM_MULTIPLIER,16)
 
80
defframe(PARAM_SIZE,      12)
 
81
defframe(PARAM_SRC,       8)
 
82
defframe(PARAM_DST,       4)
 
83
 
 
84
        TEXT
 
85
        ALIGN(32)
 
86
 
 
87
PROLOGUE(M4_function_1c)
 
88
        pushl   %ebx
 
89
deflit(`FRAME',4)
 
90
        movl    PARAM_CARRY, %ebx
 
91
        jmp     L(start_nc)
 
92
EPILOGUE()
 
93
 
 
94
PROLOGUE(M4_function_1)
 
95
        push    %ebx
 
96
deflit(`FRAME',4)
 
97
        xorl    %ebx, %ebx      C initial carry
 
98
 
 
99
L(start_nc):
 
100
        movl    PARAM_SIZE, %ecx
 
101
        pushl   %esi
 
102
deflit(`FRAME',8)
 
103
 
 
104
        movl    PARAM_SRC, %esi
 
105
        pushl   %edi
 
106
deflit(`FRAME',12)
 
107
 
 
108
        movl    PARAM_DST, %edi
 
109
        pushl   %ebp
 
110
deflit(`FRAME',16)
 
111
        cmpl    $UNROLL_THRESHOLD, %ecx
 
112
 
 
113
        movl    PARAM_MULTIPLIER, %ebp
 
114
        jae     L(unroll)
 
115
 
 
116
        
 
117
        C simple loop
 
118
        C this is offset 0x22, so close enough to aligned
 
119
L(simple):
 
120
        C eax   scratch
 
121
        C ebx   carry
 
122
        C ecx   counter
 
123
        C edx   scratch
 
124
        C esi   src
 
125
        C edi   dst
 
126
        C ebp   multiplier
 
127
 
 
128
        movl    (%esi), %eax
 
129
        addl    $4, %edi
 
130
 
 
131
        mull    %ebp
 
132
 
 
133
        addl    %ebx, %eax
 
134
        adcl    $0, %edx
 
135
 
 
136
        M4_inst %eax, -4(%edi)
 
137
        movl    %edx, %ebx
 
138
 
 
139
        adcl    $0, %ebx
 
140
        decl    %ecx
 
141
 
 
142
        leal    4(%esi), %esi
 
143
        jnz     L(simple)
 
144
 
 
145
 
 
146
        popl    %ebp
 
147
        popl    %edi
 
148
 
 
149
        popl    %esi
 
150
        movl    %ebx, %eax
 
151
 
 
152
        popl    %ebx
 
153
        ret
 
154
 
 
155
 
 
156
 
 
157
C------------------------------------------------------------------------------
 
158
C VAR_JUMP holds the computed jump temporarily because there's not enough
 
159
C registers when doing the mul for the initial two carry limbs.
 
160
C
 
161
C The add/adc for the initial carry in %ebx is necessary only for the
 
162
C mpn_add/submul_1c entry points.  Duplicating the startup code to
 
163
C eliminiate this for the plain mpn_add/submul_1 doesn't seem like a good
 
164
C idea.
 
165
 
 
166
dnl  overlapping with parameters already fetched
 
167
define(VAR_COUNTER,`PARAM_SIZE')
 
168
define(VAR_JUMP,   `PARAM_DST')
 
169
 
 
170
        C this is offset 0x43, so close enough to aligned
 
171
L(unroll):
 
172
        C eax
 
173
        C ebx   initial carry
 
174
        C ecx   size
 
175
        C edx
 
176
        C esi   src
 
177
        C edi   dst
 
178
        C ebp
 
179
 
 
180
        movl    %ecx, %edx
 
181
        decl    %ecx
 
182
 
 
183
        subl    $2, %edx
 
184
        negl    %ecx
 
185
 
 
186
        shrl    $UNROLL_LOG2, %edx
 
187
        andl    $UNROLL_MASK, %ecx
 
188
 
 
189
        movl    %edx, VAR_COUNTER
 
190
        movl    %ecx, %edx
 
191
 
 
192
        C 15 code bytes per limb
 
193
ifdef(`PIC',`
 
194
        call    L(pic_calc)
 
195
L(here):
 
196
',`
 
197
        shll    $4, %edx
 
198
        negl    %ecx
 
199
 
 
200
        leal    L(entry) (%edx,%ecx,1), %edx
 
201
')
 
202
        movl    (%esi), %eax            C src low limb
 
203
 
 
204
        movl    %edx, VAR_JUMP
 
205
        leal    ifelse(UNROLL_BYTES,256,128+) 4(%esi,%ecx,4), %esi
 
206
 
 
207
        mull    %ebp
 
208
 
 
209
        addl    %ebx, %eax      C initial carry (from _1c)
 
210
        adcl    $0, %edx
 
211
 
 
212
        movl    %edx, %ebx      C high carry
 
213
        leal    ifelse(UNROLL_BYTES,256,128) (%edi,%ecx,4), %edi
 
214
 
 
215
        movl    VAR_JUMP, %edx
 
216
        testl   $1, %ecx
 
217
        movl    %eax, %ecx      C low carry
 
218
 
 
219
        cmovnz( %ebx, %ecx)     C high,low carry other way around
 
220
        cmovnz( %eax, %ebx)
 
221
 
 
222
        jmp     *%edx
 
223
 
 
224
 
 
225
ifdef(`PIC',`
 
226
L(pic_calc):
 
227
        shll    $4, %edx
 
228
        negl    %ecx
 
229
 
 
230
        C See mpn/x86/README about old gas bugs
 
231
        leal    (%edx,%ecx,1), %edx
 
232
        addl    $L(entry)-L(here), %edx
 
233
 
 
234
        addl    (%esp), %edx
 
235
 
 
236
        ret
 
237
')
 
238
 
 
239
 
 
240
C -----------------------------------------------------------
 
241
        ALIGN(32)
 
242
L(top):
 
243
deflit(`FRAME',16)
 
244
        C eax   scratch
 
245
        C ebx   carry hi
 
246
        C ecx   carry lo
 
247
        C edx   scratch
 
248
        C esi   src
 
249
        C edi   dst
 
250
        C ebp   multiplier
 
251
        C
 
252
        C VAR_COUNTER   loop counter
 
253
        C
 
254
        C 15 code bytes per limb
 
255
 
 
256
        addl    $UNROLL_BYTES, %edi
 
257
 
 
258
L(entry):
 
259
deflit(CHUNK_COUNT,2)
 
260
forloop(`i', 0, UNROLL_COUNT/CHUNK_COUNT-1, `
 
261
        deflit(`disp0', eval(i*4*CHUNK_COUNT ifelse(UNROLL_BYTES,256,-128)))
 
262
        deflit(`disp1', eval(disp0 + 4))
 
263
 
 
264
Zdisp(  movl,   disp0,(%esi), %eax)
 
265
        mull    %ebp
 
266
Zdisp(  M4_inst,%ecx, disp0,(%edi))
 
267
        adcl    %eax, %ebx
 
268
        movl    %edx, %ecx
 
269
        adcl    $0, %ecx
 
270
 
 
271
        movl    disp1(%esi), %eax
 
272
        mull    %ebp
 
273
        M4_inst %ebx, disp1(%edi)
 
274
        adcl    %eax, %ecx
 
275
        movl    %edx, %ebx
 
276
        adcl    $0, %ebx
 
277
')
 
278
 
 
279
        decl    VAR_COUNTER
 
280
        leal    UNROLL_BYTES(%esi), %esi
 
281
 
 
282
        jns     L(top)
 
283
 
 
284
 
 
285
deflit(`disp0', eval(UNROLL_BYTES ifelse(UNROLL_BYTES,256,-128)))
 
286
 
 
287
        M4_inst %ecx, disp0(%edi)
 
288
        movl    %ebx, %eax
 
289
 
 
290
        popl    %ebp
 
291
        popl    %edi
 
292
 
 
293
        popl    %esi
 
294
        popl    %ebx
 
295
        adcl    $0, %eax
 
296
 
 
297
        ret
 
298
 
 
299
EPILOGUE()