~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/freebl/mpi/hppa20.s

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
; The contents of this file are subject to the Mozilla Public
 
2
; License Version 1.1 (the "License"); you may not use this file
 
3
; except in compliance with the License. You may obtain a copy of
 
4
; the License at http://www.mozilla.org/MPL/
 
5
 
6
; Software distributed under the License is distributed on an "AS
 
7
; IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
8
; implied. See the License for the specific language governing
 
9
; rights and limitations under the License.
 
10
 
11
; The Original Code is MAXPY multiple-precision integer arithmetic.
 
12
 
13
; The Initial Developer of the Original Code is the Hewlett-Packard Company.
 
14
; Portions created by Hewlett-Packard Company are 
 
15
; Copyright (C) 1997 Hewlett-Packard Company.  All Rights Reserved.
 
16
 
17
; Contributor(s):
 
18
;  coded by:   William B. Ackerman
 
19
 
20
; Alternatively, the contents of this file may be used under the
 
21
; terms of the GNU General Public License Version 2 or later (the
 
22
; "GPL"), in which case the provisions of the GPL are applicable 
 
23
; instead of those above.  If you wish to allow use of your 
 
24
; version of this file only under the terms of the GPL and not to
 
25
; allow others to use your version of this file under the MPL,
 
26
; indicate your decision by deleting the provisions above and
 
27
; replace them with the notice and other provisions required by
 
28
; the GPL.  If you do not delete the provisions above, a recipient
 
29
; may use your version of this file under either the MPL or the
 
30
; GPL.
 
31
 
 
32
#ifdef __LP64__
 
33
        .LEVEL   2.0W
 
34
#else
 
35
;       .LEVEL   1.1
 
36
;       .ALLOW   2.0N
 
37
        .LEVEL   2.0N
 
38
#endif
 
39
        .SPACE   $TEXT$,SORT=8
 
40
        .SUBSPA  $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
 
41
 
 
42
; ***************************************************************
 
43
;
 
44
;                 maxpy_[little/big]
 
45
;
 
46
; ***************************************************************
 
47
 
 
48
; There is no default -- you must specify one or the other.
 
49
#define LITTLE_WORDIAN 1
 
50
 
 
51
#ifdef LITTLE_WORDIAN
 
52
#define EIGHT 8
 
53
#define SIXTEEN 16
 
54
#define THIRTY_TWO 32
 
55
#define UN_EIGHT -8
 
56
#define UN_SIXTEEN -16
 
57
#define UN_TWENTY_FOUR -24
 
58
#endif
 
59
 
 
60
#ifdef BIG_WORDIAN
 
61
#define EIGHT -8
 
62
#define SIXTEEN -16
 
63
#define THIRTY_TWO -32
 
64
#define UN_EIGHT 8
 
65
#define UN_SIXTEEN 16
 
66
#define UN_TWENTY_FOUR 24
 
67
#endif
 
68
 
 
69
; This performs a multiple-precision integer version of "daxpy",
 
70
; Using the selected addressing direction.  "Little-wordian" means that
 
71
; the least significant word of a number is stored at the lowest address.
 
72
; "Big-wordian" means that the most significant word is at the lowest
 
73
; address.  Either way, the incoming address of the vector is that
 
74
; of the least significant word.  That means that, for little-wordian
 
75
; addressing, we move the address upward as we propagate carries
 
76
; from the least significant word to the most significant.  For
 
77
; big-wordian we move the address downward.
 
78
 
 
79
; We use the following registers:
 
80
;
 
81
;     r2   return PC, of course
 
82
;     r26 = arg1 =  length
 
83
;     r25 = arg2 =  address of scalar
 
84
;     r24 = arg3 =  multiplicand vector
 
85
;     r23 = arg4 =  result vector
 
86
;
 
87
;     fr9 = scalar loaded once only from r25
 
88
 
 
89
; The cycle counts shown in the bodies below are simply the result of a
 
90
; scheduling by hand.  The actual PCX-U hardware does it differently.
 
91
; The intention is that the overall speed is the same.
 
92
 
 
93
; The pipeline startup and shutdown code is constructed in the usual way,
 
94
; by taking the loop bodies and removing unnecessary instructions.
 
95
; We have left the comments describing cycle numbers in the code.
 
96
; These are intended for reference when comparing with the main loop,
 
97
; and have no particular relationship to actual cycle numbers.
 
98
 
 
99
#ifdef LITTLE_WORDIAN
 
100
maxpy_little
 
101
#else
 
102
maxpy_big
 
103
#endif
 
104
        .PROC
 
105
        .CALLINFO FRAME=120,ENTRY_GR=%r4
 
106
        .ENTER
 
107
 
 
108
; Of course, real men don't use the sissy "enter" and "leave" commands.
 
109
; They write their own stack manipulation stuff.  Unfortunately,
 
110
; that doesn't generate complete unwind info, whereas "enter" and
 
111
; "leave" (if the documentation is to be believed) do so.  Therefore,
 
112
; we use the sissy commands.  We have verified (by real-man methods)
 
113
; that the above command generates what we want:
 
114
;       STW,MA  %r3,128(%sp)
 
115
;       STW     %r4,-124(%sp)
 
116
 
 
117
        ADDIB,< -1,%r26,$L0         ; If N = 0, exit immediately.
 
118
        FLDD    0(%r25),%fr9        ; fr9 = scalar
 
119
 
 
120
; First startup
 
121
 
 
122
        FLDD    0(%r24),%fr24       ; Cycle 1
 
123
        XMPYU   %fr9R,%fr24R,%fr27  ; Cycle 3
 
124
        XMPYU   %fr9R,%fr24L,%fr25  ; Cycle 4
 
125
        XMPYU   %fr9L,%fr24L,%fr26  ; Cycle 5
 
126
        CMPIB,> 3,%r26,$N_IS_SMALL  ; Pick out cases N = 1, 2, or 3
 
127
        XMPYU   %fr9L,%fr24R,%fr24  ; Cycle 6
 
128
        FLDD    EIGHT(%r24),%fr28   ; Cycle 8
 
129
        XMPYU   %fr9L,%fr28R,%fr31  ; Cycle 10
 
130
        FSTD    %fr24,-96(%sp)
 
131
        XMPYU   %fr9R,%fr28L,%fr30  ; Cycle 11
 
132
        FSTD    %fr25,-80(%sp)
 
133
        LDO     SIXTEEN(%r24),%r24  ; Cycle 12
 
134
        FSTD    %fr31,-64(%sp)
 
135
        XMPYU   %fr9R,%fr28R,%fr29  ; Cycle 13
 
136
        FSTD    %fr27,-48(%sp)
 
137
 
 
138
; Second startup
 
139
 
 
140
        XMPYU   %fr9L,%fr28L,%fr28  ; Cycle 1
 
141
        FSTD    %fr30,-56(%sp)
 
142
        FLDD    0(%r24),%fr24
 
143
 
 
144
        FSTD    %fr26,-88(%sp)      ; Cycle 2
 
145
 
 
146
        XMPYU   %fr9R,%fr24R,%fr27  ; Cycle 3
 
147
        FSTD    %fr28,-104(%sp)
 
148
 
 
149
        XMPYU   %fr9R,%fr24L,%fr25  ; Cycle 4
 
150
        LDD     -96(%sp),%r3
 
151
        FSTD    %fr29,-72(%sp)
 
152
 
 
153
        XMPYU   %fr9L,%fr24L,%fr26  ; Cycle 5
 
154
        LDD     -64(%sp),%r19
 
155
        LDD     -80(%sp),%r21
 
156
 
 
157
        XMPYU   %fr9L,%fr24R,%fr24  ; Cycle 6
 
158
        LDD     -56(%sp),%r20
 
159
        ADD     %r21,%r3,%r3
 
160
 
 
161
        ADD,DC  %r20,%r19,%r19      ; Cycle 7
 
162
        LDD     -88(%sp),%r4
 
163
        SHRPD   %r3,%r0,32,%r21
 
164
        LDD     -48(%sp),%r1
 
165
 
 
166
        FLDD    EIGHT(%r24),%fr28   ; Cycle 8
 
167
        LDD     -104(%sp),%r31
 
168
        ADD,DC  %r0,%r0,%r20
 
169
        SHRPD   %r19,%r3,32,%r3
 
170
 
 
171
        LDD     -72(%sp),%r29       ; Cycle 9
 
172
        SHRPD   %r20,%r19,32,%r20
 
173
        ADD     %r21,%r1,%r1
 
174
 
 
175
        XMPYU   %fr9L,%fr28R,%fr31  ; Cycle 10
 
176
        ADD,DC  %r3,%r4,%r4
 
177
        FSTD    %fr24,-96(%sp)
 
178
 
 
179
        XMPYU   %fr9R,%fr28L,%fr30  ; Cycle 11
 
180
        ADD,DC  %r0,%r20,%r20
 
181
        LDD     0(%r23),%r3
 
182
        FSTD    %fr25,-80(%sp)
 
183
 
 
184
        LDO     SIXTEEN(%r24),%r24  ; Cycle 12
 
185
        FSTD    %fr31,-64(%sp)
 
186
 
 
187
        XMPYU   %fr9R,%fr28R,%fr29  ; Cycle 13
 
188
        ADD     %r0,%r0,%r0         ; clear the carry bit
 
189
        ADDIB,<= -4,%r26,$ENDLOOP   ; actually happens in cycle 12
 
190
        FSTD    %fr27,-48(%sp)
 
191
;        MFCTL   %cr16,%r21         ; for timing
 
192
;        STD     %r21,-112(%sp)
 
193
 
 
194
; Here is the loop.
 
195
 
 
196
$LOOP   XMPYU   %fr9L,%fr28L,%fr28  ; Cycle 1
 
197
        ADD,DC  %r29,%r4,%r4
 
198
        FSTD    %fr30,-56(%sp)
 
199
        FLDD    0(%r24),%fr24
 
200
 
 
201
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
202
        ADD,DC  %r0,%r20,%r20
 
203
        FSTD    %fr26,-88(%sp)
 
204
 
 
205
        XMPYU   %fr9R,%fr24R,%fr27  ; Cycle 3
 
206
        ADD     %r3,%r1,%r1
 
207
        FSTD    %fr28,-104(%sp)
 
208
        LDD     UN_EIGHT(%r23),%r21
 
209
 
 
210
        XMPYU   %fr9R,%fr24L,%fr25  ; Cycle 4
 
211
        ADD,DC  %r21,%r4,%r28
 
212
        FSTD    %fr29,-72(%sp)    
 
213
        LDD     -96(%sp),%r3
 
214
 
 
215
        XMPYU   %fr9L,%fr24L,%fr26  ; Cycle 5
 
216
        ADD,DC  %r20,%r31,%r22
 
217
        LDD     -64(%sp),%r19
 
218
        LDD     -80(%sp),%r21
 
219
 
 
220
        XMPYU   %fr9L,%fr24R,%fr24  ; Cycle 6
 
221
        ADD     %r21,%r3,%r3
 
222
        LDD     -56(%sp),%r20
 
223
        STD     %r1,UN_SIXTEEN(%r23)
 
224
 
 
225
        ADD,DC  %r20,%r19,%r19      ; Cycle 7
 
226
        SHRPD   %r3,%r0,32,%r21
 
227
        LDD     -88(%sp),%r4
 
228
        LDD     -48(%sp),%r1
 
229
 
 
230
        ADD,DC  %r0,%r0,%r20        ; Cycle 8
 
231
        SHRPD   %r19,%r3,32,%r3
 
232
        FLDD    EIGHT(%r24),%fr28
 
233
        LDD     -104(%sp),%r31
 
234
 
 
235
        SHRPD   %r20,%r19,32,%r20   ; Cycle 9
 
236
        ADD     %r21,%r1,%r1
 
237
        STD     %r28,UN_EIGHT(%r23)
 
238
        LDD     -72(%sp),%r29
 
239
 
 
240
        XMPYU   %fr9L,%fr28R,%fr31  ; Cycle 10
 
241
        ADD,DC  %r3,%r4,%r4
 
242
        FSTD    %fr24,-96(%sp)
 
243
 
 
244
        XMPYU   %fr9R,%fr28L,%fr30  ; Cycle 11
 
245
        ADD,DC  %r0,%r20,%r20
 
246
        FSTD    %fr25,-80(%sp)
 
247
        LDD     0(%r23),%r3
 
248
 
 
249
        LDO     SIXTEEN(%r24),%r24  ; Cycle 12
 
250
        FSTD    %fr31,-64(%sp)
 
251
 
 
252
        XMPYU   %fr9R,%fr28R,%fr29  ; Cycle 13
 
253
        ADD     %r22,%r1,%r1
 
254
        ADDIB,> -2,%r26,$LOOP       ; actually happens in cycle 12
 
255
        FSTD    %fr27,-48(%sp)
 
256
 
 
257
$ENDLOOP
 
258
 
 
259
; Shutdown code, first stage.
 
260
 
 
261
;        MFCTL   %cr16,%r21         ; for timing
 
262
;        STD     %r21,UN_SIXTEEN(%r23)
 
263
;        LDD     -112(%sp),%r21
 
264
;        STD     %r21,UN_EIGHT(%r23)
 
265
 
 
266
        XMPYU   %fr9L,%fr28L,%fr28  ; Cycle 1
 
267
        ADD,DC  %r29,%r4,%r4
 
268
        CMPIB,= 0,%r26,$ONEMORE
 
269
        FSTD    %fr30,-56(%sp)
 
270
 
 
271
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
272
        ADD,DC  %r0,%r20,%r20
 
273
        FSTD    %fr26,-88(%sp)
 
274
 
 
275
        ADD     %r3,%r1,%r1         ; Cycle 3
 
276
        FSTD    %fr28,-104(%sp)
 
277
        LDD     UN_EIGHT(%r23),%r21
 
278
 
 
279
        ADD,DC  %r21,%r4,%r28       ; Cycle 4
 
280
        FSTD    %fr29,-72(%sp)    
 
281
        STD     %r28,UN_EIGHT(%r23) ; moved up from cycle 9
 
282
        LDD     -96(%sp),%r3
 
283
 
 
284
        ADD,DC  %r20,%r31,%r22      ; Cycle 5
 
285
        STD     %r1,UN_SIXTEEN(%r23)
 
286
$JOIN4
 
287
        LDD     -64(%sp),%r19
 
288
        LDD     -80(%sp),%r21
 
289
 
 
290
        ADD     %r21,%r3,%r3        ; Cycle 6
 
291
        LDD     -56(%sp),%r20
 
292
 
 
293
        ADD,DC  %r20,%r19,%r19      ; Cycle 7
 
294
        SHRPD   %r3,%r0,32,%r21
 
295
        LDD     -88(%sp),%r4
 
296
        LDD     -48(%sp),%r1
 
297
 
 
298
        ADD,DC  %r0,%r0,%r20        ; Cycle 8
 
299
        SHRPD   %r19,%r3,32,%r3
 
300
        LDD     -104(%sp),%r31
 
301
 
 
302
        SHRPD   %r20,%r19,32,%r20   ; Cycle 9
 
303
        ADD     %r21,%r1,%r1
 
304
        LDD     -72(%sp),%r29
 
305
 
 
306
        ADD,DC  %r3,%r4,%r4         ; Cycle 10
 
307
 
 
308
        ADD,DC  %r0,%r20,%r20       ; Cycle 11
 
309
        LDD     0(%r23),%r3
 
310
 
 
311
        ADD     %r22,%r1,%r1        ; Cycle 13
 
312
 
 
313
; Shutdown code, second stage.
 
314
 
 
315
        ADD,DC  %r29,%r4,%r4        ; Cycle 1
 
316
 
 
317
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
318
        ADD,DC  %r0,%r20,%r20
 
319
 
 
320
        LDD     UN_EIGHT(%r23),%r21 ; Cycle 3
 
321
        ADD     %r3,%r1,%r1
 
322
 
 
323
        ADD,DC  %r21,%r4,%r28       ; Cycle 4
 
324
 
 
325
        ADD,DC  %r20,%r31,%r22      ; Cycle 5
 
326
 
 
327
        STD     %r1,UN_SIXTEEN(%r23); Cycle 6
 
328
 
 
329
        STD     %r28,UN_EIGHT(%r23) ; Cycle 9
 
330
 
 
331
        LDD     0(%r23),%r3         ; Cycle 11
 
332
 
 
333
; Shutdown code, third stage.
 
334
 
 
335
        LDO     SIXTEEN(%r23),%r23
 
336
        ADD     %r3,%r22,%r1
 
337
$JOIN1  ADD,DC  %r0,%r0,%r21
 
338
        CMPIB,*= 0,%r21,$L0         ; if no overflow, exit
 
339
        STD     %r1,UN_SIXTEEN(%r23)
 
340
 
 
341
; Final carry propagation
 
342
 
 
343
$FINAL1 LDO     EIGHT(%r23),%r23
 
344
        LDD     UN_SIXTEEN(%r23),%r21
 
345
        ADDI    1,%r21,%r21
 
346
        CMPIB,*= 0,%r21,$FINAL1     ; Keep looping if there is a carry.
 
347
        STD     %r21,UN_SIXTEEN(%r23)
 
348
        B       $L0
 
349
        NOP
 
350
 
 
351
; Here is the code that handles the difficult cases N=1, N=2, and N=3.
 
352
; We do the usual trick -- branch out of the startup code at appropriate
 
353
; points, and branch into the shutdown code.
 
354
 
 
355
$N_IS_SMALL
 
356
        CMPIB,= 0,%r26,$N_IS_ONE
 
357
        FSTD    %fr24,-96(%sp)      ; Cycle 10
 
358
        FLDD    EIGHT(%r24),%fr28   ; Cycle 8
 
359
        XMPYU   %fr9L,%fr28R,%fr31  ; Cycle 10
 
360
        XMPYU   %fr9R,%fr28L,%fr30  ; Cycle 11
 
361
        FSTD    %fr25,-80(%sp)
 
362
        FSTD    %fr31,-64(%sp)      ; Cycle 12
 
363
        XMPYU   %fr9R,%fr28R,%fr29  ; Cycle 13
 
364
        FSTD    %fr27,-48(%sp)
 
365
        XMPYU   %fr9L,%fr28L,%fr28  ; Cycle 1
 
366
        CMPIB,= 2,%r26,$N_IS_THREE
 
367
        FSTD    %fr30,-56(%sp)
 
368
 
 
369
; N = 2
 
370
        FSTD    %fr26,-88(%sp)      ; Cycle 2
 
371
        FSTD    %fr28,-104(%sp)     ; Cycle 3
 
372
        LDD     -96(%sp),%r3        ; Cycle 4
 
373
        FSTD    %fr29,-72(%sp)
 
374
        B       $JOIN4
 
375
        ADD     %r0,%r0,%r22
 
376
 
 
377
$N_IS_THREE
 
378
        FLDD    SIXTEEN(%r24),%fr24
 
379
        FSTD    %fr26,-88(%sp)      ; Cycle 2
 
380
        XMPYU   %fr9R,%fr24R,%fr27  ; Cycle 3
 
381
        FSTD    %fr28,-104(%sp)
 
382
        XMPYU   %fr9R,%fr24L,%fr25  ; Cycle 4
 
383
        LDD     -96(%sp),%r3
 
384
        FSTD    %fr29,-72(%sp)
 
385
        XMPYU   %fr9L,%fr24L,%fr26  ; Cycle 5
 
386
        LDD     -64(%sp),%r19
 
387
        LDD     -80(%sp),%r21
 
388
        B       $JOIN3
 
389
        ADD     %r0,%r0,%r22
 
390
 
 
391
$N_IS_ONE
 
392
        FSTD    %fr25,-80(%sp)
 
393
        FSTD    %fr27,-48(%sp)
 
394
        FSTD    %fr26,-88(%sp)      ; Cycle 2
 
395
        B       $JOIN5
 
396
        ADD     %r0,%r0,%r22
 
397
 
 
398
; We came out of the unrolled loop with wrong parity.  Do one more
 
399
; single cycle.  This is quite tricky, because of the way the
 
400
; carry chains and SHRPD chains have been chopped up.
 
401
 
 
402
$ONEMORE
 
403
 
 
404
        FLDD    0(%r24),%fr24
 
405
 
 
406
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
407
        ADD,DC  %r0,%r20,%r20
 
408
        FSTD    %fr26,-88(%sp)
 
409
 
 
410
        XMPYU   %fr9R,%fr24R,%fr27  ; Cycle 3
 
411
        FSTD    %fr28,-104(%sp)
 
412
        LDD     UN_EIGHT(%r23),%r21
 
413
        ADD     %r3,%r1,%r1
 
414
 
 
415
        XMPYU   %fr9R,%fr24L,%fr25  ; Cycle 4
 
416
        ADD,DC  %r21,%r4,%r28
 
417
        STD     %r28,UN_EIGHT(%r23) ; moved from cycle 9
 
418
        LDD     -96(%sp),%r3
 
419
        FSTD    %fr29,-72(%sp)    
 
420
 
 
421
        XMPYU   %fr9L,%fr24L,%fr26  ; Cycle 5
 
422
        ADD,DC  %r20,%r31,%r22
 
423
        LDD     -64(%sp),%r19
 
424
        LDD     -80(%sp),%r21
 
425
 
 
426
        STD     %r1,UN_SIXTEEN(%r23); Cycle 6
 
427
$JOIN3
 
428
        XMPYU   %fr9L,%fr24R,%fr24
 
429
        LDD     -56(%sp),%r20
 
430
        ADD     %r21,%r3,%r3
 
431
 
 
432
        ADD,DC  %r20,%r19,%r19      ; Cycle 7
 
433
        LDD     -88(%sp),%r4
 
434
        SHRPD   %r3,%r0,32,%r21
 
435
        LDD     -48(%sp),%r1
 
436
 
 
437
        LDD     -104(%sp),%r31      ; Cycle 8
 
438
        ADD,DC  %r0,%r0,%r20
 
439
        SHRPD   %r19,%r3,32,%r3
 
440
 
 
441
        LDD     -72(%sp),%r29       ; Cycle 9
 
442
        SHRPD   %r20,%r19,32,%r20
 
443
        ADD     %r21,%r1,%r1
 
444
 
 
445
        ADD,DC  %r3,%r4,%r4         ; Cycle 10
 
446
        FSTD    %fr24,-96(%sp)
 
447
 
 
448
        ADD,DC  %r0,%r20,%r20       ; Cycle 11
 
449
        LDD     0(%r23),%r3
 
450
        FSTD    %fr25,-80(%sp)
 
451
 
 
452
        ADD     %r22,%r1,%r1        ; Cycle 13
 
453
        FSTD    %fr27,-48(%sp)
 
454
 
 
455
; Shutdown code, stage 1-1/2.
 
456
 
 
457
        ADD,DC  %r29,%r4,%r4        ; Cycle 1
 
458
 
 
459
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
460
        ADD,DC  %r0,%r20,%r20     
 
461
        FSTD    %fr26,-88(%sp)
 
462
 
 
463
        LDD     UN_EIGHT(%r23),%r21 ; Cycle 3
 
464
        ADD     %r3,%r1,%r1
 
465
 
 
466
        ADD,DC  %r21,%r4,%r28       ; Cycle 4
 
467
        STD     %r28,UN_EIGHT(%r23) ; moved from cycle 9
 
468
 
 
469
        ADD,DC  %r20,%r31,%r22      ; Cycle 5
 
470
        STD     %r1,UN_SIXTEEN(%r23)
 
471
$JOIN5
 
472
        LDD     -96(%sp),%r3        ; moved from cycle 4
 
473
        LDD     -80(%sp),%r21
 
474
        ADD     %r21,%r3,%r3        ; Cycle 6
 
475
        ADD,DC  %r0,%r0,%r19        ; Cycle 7
 
476
        LDD     -88(%sp),%r4
 
477
        SHRPD   %r3,%r0,32,%r21
 
478
        LDD     -48(%sp),%r1
 
479
        SHRPD   %r19,%r3,32,%r3     ; Cycle 8
 
480
        ADD     %r21,%r1,%r1        ; Cycle 9
 
481
        ADD,DC  %r3,%r4,%r4         ; Cycle 10
 
482
        LDD     0(%r23),%r3         ; Cycle 11
 
483
        ADD     %r22,%r1,%r1        ; Cycle 13
 
484
 
 
485
; Shutdown code, stage 2-1/2.
 
486
 
 
487
        ADD,DC  %r0,%r4,%r4         ; Cycle 1
 
488
        LDO     SIXTEEN(%r23),%r23  ; Cycle 2
 
489
        LDD     UN_EIGHT(%r23),%r21 ; Cycle 3
 
490
        ADD     %r3,%r1,%r1
 
491
        STD     %r1,UN_SIXTEEN(%r23)
 
492
        ADD,DC  %r21,%r4,%r1
 
493
        B       $JOIN1
 
494
        LDO     EIGHT(%r23),%r23
 
495
 
 
496
; exit
 
497
 
 
498
$L0
 
499
        .LEAVE
 
500
 
 
501
; We have verified that the above command generates what we want:
 
502
;       LDW     -124(%sp),%r4
 
503
;       BVE     (%r2)
 
504
;       LDW,MB  -128(%sp),%r3
 
505
 
 
506
        .PROCEND
 
507
 
 
508
; ***************************************************************
 
509
;
 
510
;                 add_diag_[little/big]
 
511
;
 
512
; ***************************************************************
 
513
 
 
514
; The arguments are as follows:
 
515
;     r2   return PC, of course
 
516
;     r26 = arg1 =  length
 
517
;     r25 = arg2 =  vector to square
 
518
;     r24 = arg3 =  result vector
 
519
 
 
520
#ifdef LITTLE_WORDIAN
 
521
add_diag_little
 
522
#else
 
523
add_diag_big
 
524
#endif
 
525
        .PROC
 
526
        .CALLINFO FRAME=120,ENTRY_GR=%r4
 
527
        .ENTER
 
528
 
 
529
        ADDIB,< -1,%r26,$Z0         ; If N=0, exit immediately.
 
530
        NOP
 
531
 
 
532
; Startup code
 
533
 
 
534
        FLDD    0(%r25),%fr7        ; Cycle 2 (alternate body)
 
535
        XMPYU   %fr7R,%fr7R,%fr29   ; Cycle 4
 
536
        XMPYU   %fr7L,%fr7R,%fr27   ; Cycle 5
 
537
        XMPYU   %fr7L,%fr7L,%fr30
 
538
        LDO     SIXTEEN(%r25),%r25  ; Cycle 6
 
539
        FSTD    %fr29,-88(%sp)
 
540
        FSTD    %fr27,-72(%sp)      ; Cycle 7
 
541
        CMPIB,= 0,%r26,$DIAG_N_IS_ONE ; Cycle 1 (main body)
 
542
        FSTD    %fr30,-96(%sp)
 
543
        FLDD    UN_EIGHT(%r25),%fr7 ; Cycle 2
 
544
        LDD     -88(%sp),%r22       ; Cycle 3
 
545
        LDD     -72(%sp),%r31       ; Cycle 4
 
546
        XMPYU   %fr7R,%fr7R,%fr28
 
547
        XMPYU   %fr7L,%fr7R,%fr24   ; Cycle 5
 
548
        XMPYU   %fr7L,%fr7L,%fr31
 
549
        LDD     -96(%sp),%r20       ; Cycle 6
 
550
        FSTD    %fr28,-80(%sp)
 
551
        ADD     %r0,%r0,%r0         ; clear the carry bit
 
552
        ADDIB,<= -2,%r26,$ENDDIAGLOOP ; Cycle 7
 
553
        FSTD    %fr24,-64(%sp)
 
554
 
 
555
; Here is the loop.  It is unrolled twice, modelled after the "alternate body" and then the "main body".
 
556
 
 
557
$DIAGLOOP
 
558
        SHRPD   %r31,%r0,31,%r3     ; Cycle 1 (alternate body)
 
559
        LDO     SIXTEEN(%r25),%r25
 
560
        LDD     0(%r24),%r1
 
561
        FSTD    %fr31,-104(%sp)
 
562
        SHRPD   %r0,%r31,31,%r4     ; Cycle 2
 
563
        ADD,DC  %r22,%r3,%r3
 
564
        FLDD    UN_SIXTEEN(%r25),%fr7   
 
565
        ADD,DC  %r0,%r20,%r20       ; Cycle 3
 
566
        ADD     %r1,%r3,%r3
 
567
        XMPYU   %fr7R,%fr7R,%fr29   ; Cycle 4
 
568
        LDD     -80(%sp),%r21
 
569
        STD     %r3,0(%r24)
 
570
        XMPYU   %fr7L,%fr7R,%fr27   ; Cycle 5
 
571
        XMPYU   %fr7L,%fr7L,%fr30
 
572
        LDD     -64(%sp),%r29       
 
573
        LDD     EIGHT(%r24),%r1  
 
574
        ADD,DC  %r4,%r20,%r20       ; Cycle 6
 
575
        LDD     -104(%sp),%r19
 
576
        FSTD    %fr29,-88(%sp)
 
577
        ADD     %r20,%r1,%r1        ; Cycle 7
 
578
        FSTD    %fr27,-72(%sp)
 
579
        SHRPD   %r29,%r0,31,%r4     ; Cycle 1 (main body)
 
580
        LDO     THIRTY_TWO(%r24),%r24
 
581
        LDD     UN_SIXTEEN(%r24),%r28
 
582
        FSTD    %fr30,-96(%sp)
 
583
        SHRPD   %r0,%r29,31,%r3     ; Cycle 2
 
584
        ADD,DC  %r21,%r4,%r4
 
585
        FLDD    UN_EIGHT(%r25),%fr7
 
586
        STD     %r1,UN_TWENTY_FOUR(%r24)
 
587
        ADD,DC  %r0,%r19,%r19       ; Cycle 3
 
588
        ADD     %r28,%r4,%r4
 
589
        XMPYU   %fr7R,%fr7R,%fr28   ; Cycle 4
 
590
        LDD     -88(%sp),%r22
 
591
        STD     %r4,UN_SIXTEEN(%r24)
 
592
        XMPYU   %fr7L,%fr7R,%fr24   ; Cycle 5
 
593
        XMPYU   %fr7L,%fr7L,%fr31
 
594
        LDD     -72(%sp),%r31
 
595
        LDD     UN_EIGHT(%r24),%r28
 
596
        ADD,DC  %r3,%r19,%r19       ; Cycle 6
 
597
        LDD     -96(%sp),%r20
 
598
        FSTD    %fr28,-80(%sp)
 
599
        ADD     %r19,%r28,%r28      ; Cycle 7
 
600
        FSTD    %fr24,-64(%sp)
 
601
        ADDIB,> -2,%r26,$DIAGLOOP   ; Cycle 8
 
602
        STD     %r28,UN_EIGHT(%r24)
 
603
 
 
604
$ENDDIAGLOOP
 
605
 
 
606
        ADD,DC  %r0,%r22,%r22    
 
607
        CMPIB,= 0,%r26,$ONEMOREDIAG
 
608
        SHRPD   %r31,%r0,31,%r3
 
609
 
 
610
; Shutdown code, first stage.
 
611
 
 
612
        FSTD    %fr31,-104(%sp)     ; Cycle 1 (alternate body)
 
613
        LDD     0(%r24),%r28
 
614
        SHRPD   %r0,%r31,31,%r4     ; Cycle 2
 
615
        ADD     %r3,%r22,%r3
 
616
        ADD,DC  %r0,%r20,%r20       ; Cycle 3
 
617
        LDD     -80(%sp),%r21
 
618
        ADD     %r3,%r28,%r3
 
619
        LDD     -64(%sp),%r29       ; Cycle 4
 
620
        STD     %r3,0(%r24)
 
621
        LDD     EIGHT(%r24),%r1     ; Cycle 5
 
622
        LDO     SIXTEEN(%r25),%r25  ; Cycle 6
 
623
        LDD     -104(%sp),%r19
 
624
        ADD,DC  %r4,%r20,%r20
 
625
        ADD     %r20,%r1,%r1        ; Cycle 7
 
626
        ADD,DC  %r0,%r21,%r21       ; Cycle 8
 
627
        STD     %r1,EIGHT(%r24)
 
628
 
 
629
; Shutdown code, second stage.
 
630
 
 
631
        SHRPD   %r29,%r0,31,%r4     ; Cycle 1 (main body)
 
632
        LDO     THIRTY_TWO(%r24),%r24
 
633
        LDD     UN_SIXTEEN(%r24),%r1
 
634
        SHRPD   %r0,%r29,31,%r3      ; Cycle 2
 
635
        ADD     %r4,%r21,%r4
 
636
        ADD,DC  %r0,%r19,%r19       ; Cycle 3
 
637
        ADD     %r4,%r1,%r4
 
638
        STD     %r4,UN_SIXTEEN(%r24); Cycle 4
 
639
        LDD     UN_EIGHT(%r24),%r28 ; Cycle 5
 
640
        ADD,DC  %r3,%r19,%r19       ; Cycle 6       
 
641
        ADD     %r19,%r28,%r28      ; Cycle 7
 
642
        ADD,DC  %r0,%r0,%r22        ; Cycle 8
 
643
        CMPIB,*= 0,%r22,$Z0         ; if no overflow, exit
 
644
        STD     %r28,UN_EIGHT(%r24)
 
645
 
 
646
; Final carry propagation
 
647
 
 
648
$FDIAG2
 
649
        LDO     EIGHT(%r24),%r24
 
650
        LDD     UN_EIGHT(%r24),%r26
 
651
        ADDI    1,%r26,%r26
 
652
        CMPIB,*= 0,%r26,$FDIAG2     ; Keep looping if there is a carry.
 
653
        STD     %r26,UN_EIGHT(%r24)
 
654
 
 
655
        B   $Z0
 
656
        NOP
 
657
 
 
658
; Here is the code that handles the difficult case N=1.
 
659
; We do the usual trick -- branch out of the startup code at appropriate
 
660
; points, and branch into the shutdown code.
 
661
 
 
662
$DIAG_N_IS_ONE
 
663
 
 
664
        LDD     -88(%sp),%r22
 
665
        LDD     -72(%sp),%r31
 
666
        B       $JOINDIAG
 
667
        LDD     -96(%sp),%r20
 
668
 
 
669
; We came out of the unrolled loop with wrong parity.  Do one more
 
670
; single cycle.  This is the "alternate body".  It will, of course,
 
671
; give us opposite registers from the other case, so we need
 
672
; completely different shutdown code.
 
673
 
 
674
$ONEMOREDIAG
 
675
        FSTD    %fr31,-104(%sp)     ; Cycle 1 (alternate body)
 
676
        LDD     0(%r24),%r28
 
677
        FLDD    0(%r25),%fr7        ; Cycle 2
 
678
        SHRPD   %r0,%r31,31,%r4
 
679
        ADD     %r3,%r22,%r3
 
680
        ADD,DC  %r0,%r20,%r20       ; Cycle 3
 
681
        LDD     -80(%sp),%r21
 
682
        ADD     %r3,%r28,%r3
 
683
        LDD     -64(%sp),%r29       ; Cycle 4
 
684
        STD     %r3,0(%r24)
 
685
        XMPYU   %fr7R,%fr7R,%fr29
 
686
        LDD     EIGHT(%r24),%r1     ; Cycle 5
 
687
        XMPYU   %fr7L,%fr7R,%fr27
 
688
        XMPYU   %fr7L,%fr7L,%fr30
 
689
        LDD     -104(%sp),%r19      ; Cycle 6
 
690
        FSTD    %fr29,-88(%sp)
 
691
        ADD,DC  %r4,%r20,%r20
 
692
        FSTD    %fr27,-72(%sp)      ; Cycle 7
 
693
        ADD     %r20,%r1,%r1
 
694
        ADD,DC  %r0,%r21,%r21       ; Cycle 8
 
695
        STD     %r1,EIGHT(%r24)
 
696
 
 
697
; Shutdown code, first stage.
 
698
 
 
699
        SHRPD   %r29,%r0,31,%r4     ; Cycle 1 (main body)
 
700
        LDO     THIRTY_TWO(%r24),%r24
 
701
        FSTD    %fr30,-96(%sp)
 
702
        LDD     UN_SIXTEEN(%r24),%r1
 
703
        SHRPD   %r0,%r29,31,%r3     ; Cycle 2
 
704
        ADD     %r4,%r21,%r4
 
705
        ADD,DC  %r0,%r19,%r19       ; Cycle 3
 
706
        LDD     -88(%sp),%r22
 
707
        ADD     %r4,%r1,%r4
 
708
        LDD     -72(%sp),%r31       ; Cycle 4
 
709
        STD     %r4,UN_SIXTEEN(%r24)
 
710
        LDD     UN_EIGHT(%r24),%r28 ; Cycle 5
 
711
        LDD     -96(%sp),%r20       ; Cycle 6
 
712
        ADD,DC  %r3,%r19,%r19
 
713
        ADD     %r19,%r28,%r28      ; Cycle 7
 
714
        ADD,DC  %r0,%r22,%r22       ; Cycle 8
 
715
        STD     %r28,UN_EIGHT(%r24)
 
716
 
 
717
; Shutdown code, second stage.
 
718
 
 
719
$JOINDIAG
 
720
        SHRPD   %r31,%r0,31,%r3     ; Cycle 1 (alternate body)
 
721
        LDD     0(%r24),%r28        
 
722
        SHRPD   %r0,%r31,31,%r4     ; Cycle 2
 
723
        ADD     %r3,%r22,%r3
 
724
        ADD,DC  %r0,%r20,%r20       ; Cycle 3
 
725
        ADD     %r3,%r28,%r3
 
726
        STD     %r3,0(%r24)         ; Cycle 4
 
727
        LDD     EIGHT(%r24),%r1     ; Cycle 5
 
728
        ADD,DC  %r4,%r20,%r20
 
729
        ADD     %r20,%r1,%r1        ; Cycle 7
 
730
        ADD,DC  %r0,%r0,%r21        ; Cycle 8
 
731
        CMPIB,*= 0,%r21,$Z0         ; if no overflow, exit
 
732
        STD     %r1,EIGHT(%r24)
 
733
 
 
734
; Final carry propagation
 
735
 
 
736
$FDIAG1
 
737
        LDO     EIGHT(%r24),%r24
 
738
        LDD     EIGHT(%r24),%r26
 
739
        ADDI    1,%r26,%r26
 
740
        CMPIB,*= 0,%r26,$FDIAG1    ; Keep looping if there is a carry.
 
741
        STD     %r26,EIGHT(%r24)
 
742
 
 
743
$Z0
 
744
        .LEAVE
 
745
        .PROCEND
 
746
;       .ALLOW
 
747
 
 
748
        .SPACE         $TEXT$
 
749
        .SUBSPA        $CODE$
 
750
#ifdef LITTLE_WORDIAN
 
751
        .EXPORT        maxpy_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
 
752
        .EXPORT        add_diag_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
 
753
#else
 
754
        .EXPORT        maxpy_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
 
755
        .EXPORT        add_diag_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
 
756
#endif
 
757
        .END
 
758
 
 
759
 
 
760
; How to use "maxpy_PA20_little" and "maxpy_PA20_big"
 
761
 
762
; The routine "maxpy_PA20_little" or "maxpy_PA20_big"
 
763
; performs a 64-bit x any-size multiply, and adds the
 
764
; result to an area of memory.  That is, it performs
 
765
; something like
 
766
 
767
;      A B C D
 
768
;    *       Z
 
769
;   __________
 
770
;    P Q R S T
 
771
 
772
; and then adds the "PQRST" vector into an area of memory,
 
773
; handling all carries.
 
774
 
775
; Digression on nomenclature and endian-ness:
 
776
 
777
; Each of the capital letters in the above represents a 64-bit
 
778
; quantity.  That is, you could think of the discussion as
 
779
; being in terms of radix-16-quintillion arithmetic.  The data
 
780
; type being manipulated is "unsigned long long int".  This
 
781
; requires the 64-bit extension of the HP-UX C compiler,
 
782
; available at release 10.  You need these compiler flags to
 
783
; enable these extensions:
 
784
 
785
;       -Aa +e +DA2.0 +DS2.0
 
786
 
787
; (The first specifies ANSI C, the second enables the
 
788
; extensions, which are beyond ANSI C, and the third and
 
789
; fourth tell the compiler to use whatever features of the
 
790
; PA2.0 architecture it wishes, in order to made the code more
 
791
; efficient.  Since the presence of the assembly code will
 
792
; make the program unable to run on anything less than PA2.0,
 
793
; you might as well gain the performance enhancements in the C
 
794
; code as well.)
 
795
 
796
; Questions of "endian-ness" often come up, usually in the
 
797
; context of byte ordering in a word.  These routines have a
 
798
; similar issue, that could be called "wordian-ness".
 
799
; Independent of byte ordering (PA is always big-endian), one
 
800
; can make two choices when representing extremely large
 
801
; numbers as arrays of 64-bit doublewords in memory.
 
802
 
803
; "Little-wordian" layout means that the least significant
 
804
; word of a number is stored at the lowest address.
 
805
 
806
;   MSW     LSW
 
807
;    |       |
 
808
;    V       V
 
809
 
810
;    A B C D E
 
811
 
812
;    ^     ^ ^
 
813
;    |     | |____ address 0
 
814
;    |     |
 
815
;    |     |_______address 8
 
816
;    |
 
817
;    address 32
 
818
 
819
; "Big-wordian" means that the most significant word is at the
 
820
; lowest address.
 
821
 
822
;   MSW     LSW
 
823
;    |       |
 
824
;    V       V
 
825
 
826
;    A B C D E
 
827
 
828
;    ^     ^ ^
 
829
;    |     | |____ address 32
 
830
;    |     |
 
831
;    |     |_______address 24
 
832
;    |
 
833
;    address 0
 
834
 
835
; When you compile the file, you must specify one or the other, with
 
836
; a switch "-DLITTLE_WORDIAN" or "-DBIG_WORDIAN".
 
837
 
838
;     Incidentally, you assemble this file as part of your
 
839
;     project with the same C compiler as the rest of the program.
 
840
;     My "makefile" for a superprecision arithmetic package has
 
841
;     the following stuff:
 
842
 
843
;     # definitions:
 
844
;     CC = cc -Aa +e -z +DA2.0 +DS2.0 +w1
 
845
;     CFLAGS = +O3
 
846
;     LDFLAGS = -L /usr/lib -Wl,-aarchive
 
847
 
848
;     # general build rule for ".s" files:
 
849
;     .s.o:
 
850
;             $(CC) $(CFLAGS) -c $< -DBIG_WORDIAN
 
851
 
852
;     # Now any bind step that calls for pa20.o will assemble pa20.s
 
853
 
854
; End of digression, back to arithmetic:
 
855
 
856
; The way we multiply two huge numbers is, of course, to multiply
 
857
; the "ABCD" vector by each of the "WXYZ" doublewords, adding
 
858
; the result vectors with increasing offsets, the way we learned
 
859
; in school, back before we all used calculators:
 
860
 
861
;            A B C D
 
862
;          * W X Y Z
 
863
;         __________
 
864
;          P Q R S T
 
865
;        E F G H I
 
866
;      M N O P Q
 
867
;  + R S T U V
 
868
;    _______________
 
869
;    F I N A L S U M
 
870
 
871
; So we call maxpy_PA20_big (in my case; my package is
 
872
; big-wordian) repeatedly, giving the W, X, Y, and Z arguments
 
873
; in turn as the "scalar", and giving the "ABCD" vector each
 
874
; time.  We direct it to add its result into an area of memory
 
875
; that we have cleared at the start.  We skew the exact
 
876
; location into that area with each call.
 
877
 
878
; The prototype for the function is
 
879
 
880
; extern void maxpy_PA20_big(
 
881
;    int length,        /* Number of doublewords in the multiplicand vector. */
 
882
;    const long long int *scalaraddr,    /* Address to fetch the scalar. */
 
883
;    const long long int *multiplicand,  /* The multiplicand vector. */
 
884
;    long long int *result);             /* Where to accumulate the result. */
 
885
 
886
; (You should place a copy of this prototype in an include file
 
887
; or in your C file.)
 
888
 
889
; Now, IN ALL CASES, the given address for the multiplicand or
 
890
; the result is that of the LEAST SIGNIFICANT DOUBLEWORD.
 
891
; That word is, of course, the word at which the routine
 
892
; starts processing.  "maxpy_PA20_little" then increases the
 
893
; addresses as it computes.  "maxpy_PA20_big" decreases them.
 
894
 
895
; In our example above, "length" would be 4 in each case.
 
896
; "multiplicand" would be the "ABCD" vector.  Specifically,
 
897
; the address of the element "D".  "scalaraddr" would be the
 
898
; address of "W", "X", "Y", or "Z" on the four calls that we
 
899
; would make.  (The order doesn't matter, of course.)
 
900
; "result" would be the appropriate address in the result
 
901
; area.  When multiplying by "Z", that would be the least
 
902
; significant word.  When multiplying by "Y", it would be the
 
903
; next higher word (8 bytes higher if little-wordian; 8 bytes
 
904
; lower if big-wordian), and so on.  The size of the result
 
905
; area must be the the sum of the sizes of the multiplicand
 
906
; and multiplier vectors, and must be initialized to zero
 
907
; before we start.
 
908
 
909
; Whenever the routine adds its partial product into the result
 
910
; vector, it follows carry chains as far as they need to go.
 
911
 
912
; Here is the super-precision multiply routine that I use for
 
913
; my package.  The package is big-wordian.  I have taken out
 
914
; handling of exponents (it's a floating point package):
 
915
 
916
; static void mul_PA20(
 
917
;   int size,
 
918
;   const long long int *arg1,
 
919
;   const long long int *arg2,
 
920
;   long long int *result)
 
921
; {
 
922
;    int i;
 
923
 
924
;    for (i=0 ; i<2*size ; i++) result[i] = 0ULL;
 
925
 
926
;    for (i=0 ; i<size ; i++) {
 
927
;       maxpy_PA20_big(size, &arg2[i], &arg1[size-1], &result[size+i]);
 
928
;    }
 
929
; }