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

« back to all changes in this revision

Viewing changes to msvc/gmp/mpn/x86i/p6/sqr_basecase.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
 
 
2
;  Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
 
3
 
4
;  This file is part of the GNU MP Library.
 
5
 
6
;  The GNU MP Library is free software; you can redistribute it and/or
 
7
;  modify it under the terms of the GNU Lesser General Public License as
 
8
;  published by the Free Software Foundation; either version 2.1 of the
 
9
;  License, or (at your option) any later version.
 
10
 
11
;  The GNU MP Library is distributed in the hope that it will be useful,
 
12
;  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
;  Lesser General Public License for more details.
 
15
 
16
;  You should have received a copy of the GNU Lesser General Public
 
17
;  License along with the GNU MP Library; see the file COPYING.LIB.  If
 
18
;  not, write to the Free Software Foundation, Inc., 59 Temple Place -
 
19
;  Suite 330, Boston, MA 02111-1307, USA.
 
20
;
 
21
; Translation of AT&T syntax code by Brian Gladman 
 
22
 
 
23
%include "..\\x86i.inc" 
 
24
 
 
25
        global  ___gmpn_sqr_basecase
 
26
 
 
27
%ifdef  DLL
 
28
        export  ___gmpn_sqr_basecase
 
29
%endif
 
30
 
 
31
%define UNROLL_COUNT    64      ; seems to be maximum required (I hope!)
 
32
 
 
33
%define PARAM_SIZE      esp+frame+12 
 
34
%define PARAM_SRC   esp+frame+8 
 
35
%define PARAM_DST   esp+frame+4 
 
36
%define frame           0 
 
37
 
 
38
        section .text
 
39
        
 
40
        align   32
 
41
                
 
42
___gmpn_sqr_basecase:
 
43
    mov     edx,[PARAM_SIZE]
 
44
    mov     eax,[PARAM_SRC]
 
45
    cmp     edx,2
 
46
    mov     ecx,[PARAM_DST]
 
47
    je      Ltwo_limbs
 
48
    mov     eax,[eax]
 
49
    ja      Lthree_or_more
 
50
 
 
51
;  one limb only 
 
52
;  eax        src limb 
 
53
;  ebx 
 
54
;  ecx        dst 
 
55
;  edx 
 
56
 
 
57
    mul     eax
 
58
    mov     [ecx],eax
 
59
    mov     [4+ecx],edx
 
60
    ret
 
61
 
 
62
;  eax        src 
 
63
;  ebx 
 
64
;  ecx        dst 
 
65
;  edx 
 
66
 
 
67
%define SAVE_ESI    esp+frame-4 
 
68
%define SAVE_EBX    esp+frame-8 
 
69
%define SAVE_EDI    esp+frame-12 
 
70
%define SAVE_EBP    esp+frame-16 
 
71
%define frame           16
 
72
 
 
73
Ltwo_limbs: 
 
74
    sub     esp,frame
 
75
    mov     [SAVE_ESI],esi
 
76
    mov     esi,eax
 
77
    mov     eax,[eax]
 
78
    mul     eax                         ;  src[0]^2 
 
79
    mov     [ecx],eax           ;  dst[0] 
 
80
    mov     eax,[4+esi]
 
81
    mov     [SAVE_EBX],ebx
 
82
    mov     ebx,edx                     ;  dst[1] 
 
83
    mul     eax                         ;  src[1]^2 
 
84
    mov     [SAVE_EDI],edi
 
85
    mov     edi,eax                     ;  dst[2] 
 
86
    mov     eax,[esi]
 
87
    mov     [SAVE_EBP],ebp
 
88
    mov     ebp,edx                     ;  dst[3] 
 
89
    mul     dword [4+esi]       ;  src[0]*src[1] 
 
90
    add     ebx,eax
 
91
    mov     esi,[SAVE_ESI]
 
92
    adc     edi,edx
 
93
    adc     ebp,0
 
94
    add     eax,ebx
 
95
    mov     ebx,[SAVE_EBX]
 
96
    adc     edx,edi
 
97
    mov     edi,[SAVE_EDI]
 
98
    adc     ebp,0
 
99
    mov     [4+ecx],eax
 
100
    mov     [12+ecx],ebp
 
101
    mov     ebp,[SAVE_EBP]
 
102
    mov     [8+ecx],edx
 
103
    add     esp,frame
 
104
    ret
 
105
 
 
106
;  eax        src low limb 
 
107
;  ebx 
 
108
;  ecx        dst 
 
109
;  edx        size 
 
110
 
 
111
Lthree_or_more: 
 
112
        sub             esp,frame
 
113
        mov             [SAVE_ESI],esi
 
114
    cmp     edx,4
 
115
    mov     esi,[PARAM_SRC]
 
116
    jae     Lfour_or_more
 
117
 
 
118
;  three limbs 
 
119
;  eax        src low limb 
 
120
;  ebx 
 
121
;  ecx        dst 
 
122
;  edx 
 
123
;  esi        src 
 
124
;  edi 
 
125
;  ebp 
 
126
 
 
127
        mov             [SAVE_EBP],ebp
 
128
        mov             [SAVE_EDI],edi
 
129
    mul     eax                         ;  src[0] ^ 2 
 
130
    mov     [ecx],eax
 
131
    mov     [4+ecx],edx
 
132
    mov     eax,[4+esi]
 
133
    xor     ebp,ebp
 
134
    mul     eax                         ;  src[1] ^ 2 
 
135
    mov     [8+ecx],eax
 
136
    mov     [12+ecx],edx
 
137
    mov     eax,[8+esi]
 
138
        mov             [SAVE_EBX],ebx
 
139
    mul     eax                         ;  src[2] ^ 2 
 
140
    mov     [16+ecx],eax
 
141
    mov     [20+ecx],edx
 
142
    mov     eax,[esi]
 
143
    mul     dword [4+esi]       ;  src[0] * src[1] 
 
144
    mov     ebx,eax
 
145
    mov     edi,edx
 
146
    mov     eax,[esi]
 
147
    mul     dword [8+esi]       ;  src[0] * src[2] 
 
148
    add     edi,eax
 
149
    mov     ebp,edx
 
150
    adc     ebp,0
 
151
    mov     eax,[4+esi]
 
152
    mul     dword [8+esi]       ;  src[1] * src[2] 
 
153
    xor     esi,esi
 
154
    add     ebp,eax
 
155
 
 
156
;  eax 
 
157
;  ebx        dst[1] 
 
158
;  ecx        dst 
 
159
;  edx        dst[4] 
 
160
;  esi        zero,will be dst[5] 
 
161
;  edi        dst[2] 
 
162
;  ebp        dst[3] 
 
163
 
 
164
    adc     edx,0
 
165
    add     ebx,ebx
 
166
    adc     edi,edi
 
167
    adc     ebp,ebp
 
168
    adc     edx,edx
 
169
    mov     eax,[4+ecx]
 
170
    adc     esi,0
 
171
    add     eax,ebx
 
172
    mov     [4+ecx],eax
 
173
    mov     eax,[8+ecx]
 
174
    adc     eax,edi
 
175
    mov     ebx,[12+ecx]
 
176
    adc     ebx,ebp
 
177
    mov     edi,[16+ecx]
 
178
    mov     [8+ecx],eax
 
179
    mov     ebp,[SAVE_EBP]
 
180
    mov     [12+ecx],ebx
 
181
    mov     ebx,[SAVE_EBX]
 
182
    adc     edi,edx
 
183
    mov     eax,[20+ecx]
 
184
    mov     [16+ecx],edi
 
185
    mov     edi,[SAVE_EDI]
 
186
    adc     eax,esi                     ;  no carry out of this 
 
187
    mov     esi,[SAVE_ESI]
 
188
    mov     [20+ecx],eax
 
189
    add     esp,frame
 
190
    ret
 
191
 
 
192
;  eax        src low limb 
 
193
;  ebx 
 
194
;  ecx 
 
195
;  edx        size 
 
196
;  esi        src 
 
197
;  edi 
 
198
;  ebp 
 
199
;  First multiply src[0]*src[1..size-1] and store at dst[1..size]. 
 
200
 
 
201
%define VAR_COUNTER     esp+frame-20 
 
202
%define VAR_JMP         esp+frame-24 
 
203
%define STACK_SPACE 24 
 
204
 
 
205
Lfour_or_more: 
 
206
        sub     esp,STACK_SPACE-frame
 
207
%define       frame   STACK_SPACE 
 
208
    mov     ecx,1
 
209
    mov     [SAVE_EDI],edi
 
210
    mov     edi,[PARAM_DST]
 
211
    mov     [SAVE_EBX],ebx
 
212
    sub     ecx,edx                             ;  -(size-1) 
 
213
    mov     [SAVE_EBP],ebp
 
214
    mov     ebx,0                               ;  initial carry 
 
215
    lea     esi,[esi+edx*4]             ;  &src[size] 
 
216
    mov     ebp,eax                             ;  multiplier 
 
217
    lea     edi,[-4+edi+edx*4]  ;  &dst[size-1] 
 
218
 
 
219
;  This loop runs at just over 6 c/l. 
 
220
;  eax        scratch 
 
221
;  ebx        carry 
 
222
;  ecx        counter,limbs,negative,-(size-1) to -1 
 
223
;  edx        scratch 
 
224
;  esi        &src[size] 
 
225
;  edi        &dst[size-1] 
 
226
;  ebp        multiplier 
 
227
 
 
228
Lmul_1: 
 
229
    mov     eax,ebp
 
230
    mul     dword [esi+ecx*4]
 
231
    add     eax,ebx
 
232
    mov     ebx,0
 
233
    adc     ebx,edx
 
234
    mov     [4+edi+ecx*4],eax
 
235
    inc     ecx
 
236
    jnz     Lmul_1
 
237
    mov     [4+edi],ebx
 
238
 
 
239
;  Addmul src[n]*src[n+1..size-1] at dst[2*n-1...],for each n=1..size-2. 
 
240
;  
 
241
;  The last two addmuls,which are the bottom right corner of the product 
 
242
;  triangle,are left to the end.  These are src[size-3]*src[size-2,size-1] 
 
243
;  and src[size-2]*src[size-1].  If size is 4 then it's only these corner 
 
244
;  cases that need to be done. 
 
245
;  
 
246
;  The unrolled code is the same as mpn_addmul_1(),see that routine for some 
 
247
;  comments. 
 
248
;  
 
249
;  VAR_COUNTER is the outer loop,running from -(size-4) to -1,inclusive. 
 
250
;  
 
251
;  VAR_JMP is the computed jump into the unrolled code,stepped by one code 
 
252
;  chunk each outer loop. 
 
253
;
 
254
;   This is also hard-coded in the address calculation below. 
 
255
;
 
256
;   With &src[size] and &dst[size-1] pointers,the displacements in the 
 
257
;   unrolled code fit in a byte for UNROLL_COUNT values up to 32,but above 
 
258
;   that an offset must be added to them. 
 
259
;
 
260
;  eax 
 
261
;  ebx        carry 
 
262
;  ecx 
 
263
;  edx 
 
264
;  esi        &src[size] 
 
265
;  edi        &dst[size-1] 
 
266
;  ebp 
 
267
 
 
268
%define CODE_BYTES_PER_LIMB     15 
 
269
%if     UNROLL_COUNT > 32
 
270
%define OFFSET  4*(UNROLL_COUNT-32)
 
271
%else
 
272
%define OFFSET  0
 
273
%endif
 
274
    mov     ecx,[PARAM_SIZE]
 
275
    sub     ecx,4
 
276
    jz      Lcorner
 
277
    mov     edx,ecx
 
278
    neg     ecx
 
279
    shl     ecx,4
 
280
%if     OFFSET != 0
 
281
        sub             esi,OFFSET
 
282
%endif
 
283
 
 
284
%ifdef  PIC
 
285
    call    Lhere
 
286
Lhere:
 
287
    add     ecx,[esp]
 
288
    add     ecx,Lunroll_inner_end-Lhere-(2*CODE_BYTES_PER_LIMB)
 
289
    add     ecx,edx
 
290
    add         esp,4
 
291
%else
 
292
        lea     ecx,[Lunroll_inner_end-2*CODE_BYTES_PER_LIMB+ecx+edx]
 
293
%endif
 
294
        neg     edx
 
295
%if OFFSET != 0
 
296
        sub             edi,OFFSET
 
297
%endif
 
298
 
 
299
;  The calculated jump mustn't be before the start of the available 
 
300
;  code.  This is the limit that UNROLL_COUNT puts on the src operand 
 
301
;  size,but checked here using the jump address directly. 
 
302
 
 
303
; ASSERT(ae,movl_text_address( Lunroll_inner_start,%eax) cmpl %eax,%ecx) 
 
304
 
 
305
%ifdef  ASSERT
 
306
        mov             eax,Lunroll_inner_start
 
307
        cmp             ecx,eax
 
308
        jae             Lunroll_outer_top
 
309
        jmp             exit
 
310
%endif
 
311
 
 
312
;  eax 
 
313
;  ebx        high limb to store 
 
314
;  ecx        VAR_JMP 
 
315
;  edx        VAR_COUNTER,limbs,negative 
 
316
;  esi        &src[size],constant 
 
317
;  edi        dst ptr,second highest limb of last addmul 
 
318
;  ebp 
 
319
 
 
320
%if     UNROLL_COUNT % 2 == 1
 
321
%define cmovX   cmovz
 
322
%else
 
323
%define cmovX   cmovnz
 
324
%endif
 
325
 
 
326
        align   16
 
327
Lunroll_outer_top: 
 
328
    mov     ebp,[-12+OFFSET+esi+edx*4]   ;  multiplier 
 
329
    mov     [VAR_COUNTER],edx
 
330
    mov     eax,[-8+OFFSET+esi+edx*4]   ;  first limb of multiplicand 
 
331
    mul     ebp
 
332
    test    cl,1
 
333
    mov     ebx,edx    ;  high carry 
 
334
    lea     edi,[4+edi]
 
335
    mov     edx,ecx    ;  jump 
 
336
    mov     ecx,eax    ;  low carry 
 
337
    lea     edx,[CODE_BYTES_PER_LIMB+edx]
 
338
        cmovX   ecx,ebx
 
339
        cmovX   ebx,eax
 
340
    mov     [VAR_JMP],edx
 
341
    jmp     edx
 
342
 
 
343
;  Must be on an even address here so the low bit of the jump address 
 
344
;  will indicate which way around ecx/ebx should start. 
 
345
 
 
346
;  eax        scratch 
 
347
;  ebx        carry high 
 
348
;  ecx        carry low 
 
349
;  edx        scratch 
 
350
;  esi        src pointer 
 
351
;  edi        dst pointer 
 
352
;  ebp        multiplier 
 
353
;  
 
354
;  15 code bytes each limb 
 
355
;  ecx/ebx reversed on each chunk 
 
356
 
 
357
        align   2
 
358
 
 
359
Lunroll_inner_start: 
 
360
 
 
361
%assign i       UNROLL_COUNT
 
362
%rep    UNROLL_COUNT
 
363
        %assign disp_src        OFFSET-4*i
 
364
        %assign disp_dst        disp_src 
 
365
;       m4_assert(disp_src>=-128 && disp_src<128)
 
366
;       m4_assert(disp_dst>=-128 && disp_dst<128)
 
367
 
 
368
        mov             eax,[byte disp_src+esi]
 
369
    mul     ebp
 
370
%if     i % 2 == 0
 
371
        add             [byte disp_dst+edi],ebx
 
372
        adc     ecx,eax
 
373
    mov     ebx,edx
 
374
    adc     ebx,0
 
375
%else
 
376
        add             [byte disp_dst+edi],ecx
 
377
        adc     ebx,eax
 
378
    mov     ecx,edx
 
379
    adc     ecx,0
 
380
%endif
 
381
%assign i       i-1
 
382
%endrep
 
383
 
 
384
Lunroll_inner_end: 
 
385
    add     [OFFSET+edi],ebx
 
386
    mov     edx,[VAR_COUNTER]
 
387
    adc     ecx,0
 
388
    mov     [OFFSET+4+edi],ecx
 
389
    mov     ecx,[VAR_JMP]
 
390
    inc     edx
 
391
    jnz     Lunroll_outer_top
 
392
 
 
393
%if     OFFSET != 0
 
394
    add     esi,OFFSET
 
395
    add     edi,OFFSET
 
396
%endif
 
397
 
 
398
;  eax 
 
399
;  ebx 
 
400
;  ecx 
 
401
;  edx 
 
402
;  esi        &src[size] 
 
403
;  edi        &dst[2*size-5] 
 
404
;  ebp 
 
405
 
 
406
        align   16
 
407
Lcorner: 
 
408
    mov     eax,[-12+esi]
 
409
    mul     dword [-8+esi]
 
410
    add     [edi],eax
 
411
    mov     eax,[-12+esi]
 
412
    mov     ebx,0
 
413
    adc     ebx,edx
 
414
    mul     dword [-4+esi]
 
415
    add     ebx,eax
 
416
    mov     eax,[-8+esi]
 
417
    adc     edx,0
 
418
    add     [4+edi],ebx
 
419
    mov     ebx,0
 
420
    adc     ebx,edx
 
421
    mul     dword [-4+esi]
 
422
    mov     ecx,[PARAM_SIZE]
 
423
    add     eax,ebx
 
424
    adc     edx,0
 
425
    mov     [8+edi],eax
 
426
    mov     [12+edi],edx
 
427
    mov     edi,[PARAM_DST]
 
428
 
 
429
;  Left shift of dst[1..2*size-2],the bit shifted out becomes dst[2*size-1]. 
 
430
 
 
431
    sub     ecx,1                               ;  size-1 
 
432
    xor     eax,eax                             ;  ready for final adcl,and clear carry 
 
433
    mov     edx,ecx
 
434
    mov     esi,[PARAM_SRC]
 
435
 
 
436
;  eax 
 
437
;  ebx 
 
438
;  ecx        counter,size-1 to 1 
 
439
;  edx        size-1 (for later use) 
 
440
;  esi        src (for later use) 
 
441
;  edi        dst,incrementing 
 
442
;  ebp 
 
443
 
 
444
Llshift: 
 
445
    rcl     dword [4+edi],1
 
446
    rcl     dword [8+edi],1
 
447
    lea     edi,[8+edi]
 
448
    dec     ecx
 
449
    jnz     Llshift
 
450
    adc     eax,eax
 
451
    mov     [4+edi],eax                 ;  dst most significant limb 
 
452
    mov     eax,[esi]                   ;  src[0] 
 
453
    lea     esi,[4+esi+edx*4]   ;  &src[size] 
 
454
    sub     ecx,edx                             ;  -(size-1) 
 
455
 
 
456
;  Now add in the squares on the diagonal,src[0]^2,src[1]^2,...,
 
457
;  src[size-1]^2.  dst[0] hasn't yet been set at all yet,and just gets the 
 
458
;  low limb of src[0]^2. 
 
459
 
 
460
    mul     eax
 
461
    mov     [edi+ecx*8],eax     ;  dst[0] 
 
462
 
 
463
;  eax        scratch 
 
464
;  ebx        scratch 
 
465
;  ecx        counter,negative 
 
466
;  edx        carry 
 
467
;  esi        &src[size] 
 
468
;  edi        dst[2*size-2] 
 
469
;  ebp 
 
470
 
 
471
Ldiag: 
 
472
    mov     eax,[esi+ecx*4]
 
473
    mov     ebx,edx
 
474
    mul     eax
 
475
    add     [4+edi+ecx*8],ebx
 
476
    adc     [8+edi+ecx*8],eax
 
477
    adc     edx,0
 
478
    inc     ecx
 
479
    jnz     Ldiag
 
480
    mov     esi,[SAVE_ESI]
 
481
    mov     ebx,[SAVE_EBX]
 
482
    add     [4+edi],edx                 ;  dst most significant limb 
 
483
    mov     edi,[SAVE_EDI]
 
484
    mov     ebp,[SAVE_EBP]
 
485
    add     esp,frame
 
486
    ret
 
487
 
 
488
        end