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

« back to all changes in this revision

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