DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Untracked file

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is multacc512 multiple-precision integer arithmetic.
 * 
 * The Initial Developer of the Original Code is Hewlett-Packard Company.
 * Portions created by Hewlett-Packard Company are 
 * Copyright (C) March 1999, Hewlett-Packard Company. All Rights Reserved.
 * 
 * Contributor(s):
 *  coded by:   Bill Worley, Hewlett-Packard labs
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL"), in which case the provisions of the GPL are applicable 
 * instead of those above.  If you wish to allow use of your 
 * version of this file only under the terms of the GPL and not to
 * allow others to use your version of this file under the MPL,
 * indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by
 * the GPL.  If you do not delete the provisions above, a recipient
 * may use your version of this file under either the MPL or the
 * GPL.
 *
 *  This PA-RISC 2.0 function computes the product of two unsigned integers,
 *  and adds the result to a previously computed integer.  The multiplicand
 *  is a 512-bit (64-byte, eight doubleword) unsigned integer, stored in
 *  memory in little-double-wordian order.  The multiplier is an unsigned
 *  64-bit integer.  The previously computed integer to which the product is
 *  added is located in the result ("res") area, and is assumed to be a
 *  576-bit (72-byte, nine doubleword) unsigned integer, stored in memory
 *  in little-double-wordian order.  This value normally will be the result
 *  of a previously computed nine doubleword result.  It is not necessary
 *  to pad the multiplicand with an additional 64-bit zero doubleword.
 *
 *  Multiplicand, multiplier, and addend ideally should be aligned at
 *  16-byte boundaries for best performance.  The code will function
 *  correctly for alignment at eight-byte boundaries which are not 16-byte
 *  boundaries, but the execution may be slightly slower due to even/odd
 *  bank conflicts on PA-RISC 8000 processors.
 *
 *  This function is designed to accept the same calling sequence as Bill
 *  Ackerman's "maxpy_little" function.  The carry from the ninth doubleword
 *  of the result is written to the tenth word of the result, as is done by
 *  Bill Ackerman's function.  The final carry also is returned as an
 *  integer, which may be ignored.  The function prototype may be either
 *  of the following:
 *
 *      void multacc512( int l, chunk* m, const chunk* a, chunk* res );
 *          or
 *      int multacc512( int l, chunk* m, const chunk* a, chunk* res );
 *
 *  where:  "l" originally denoted vector lengths.  This parameter is
 *      ignored.  This function always assumes a multiplicand length of
 *      512 bits (eight doublewords), and addend and result lengths of
 *      576 bits (nine doublewords).
 *
 *      "m" is a pointer to the doubleword multiplier, ideally aligned
 *      on a 16-byte boundary.
 *
 *      "a" is a pointer to the eight-doubleword multiplicand, stored
 *      in little-double-wordian order, and ideally aligned on a 16-byte
 *      boundary.
 *
 *      "res" is a pointer to the nine doubleword addend, and to the
 *      nine-doubleword product computed by this function.  The result
 *      also is stored in little-double-wordian order, and ideally is
 *      aligned on a 16-byte boundary. It is expected that the alignment
 *      of the "res" area may alternate between even/odd doubleword
 *      boundaries for successive calls for 512-bit x 512-bit
 *      multiplications.
 *
 *  The code for this function has been scheduled to use the parallelism
 *  of the PA-RISC 8000 series microprocessors as well as the author was
 *  able.  Comments and/or suggestions for improvement are welcomed.
 *
 *  The code is "64-bit safe".  This means it may be called in either
 *  the 32ILP context or the 64LP context.  All 64-bits of registers are
 *  saved and restored.
 *
 *  This code is self-contained.  It requires no other header files in order
 *  to compile and to be linkable on a PA-RISC 2.0 machine.  Symbolic
 *  definitions for registers and stack offsets are included within this
 *  one source file.
 *
 *  This is a leaf routine.  As such, minimal use is made of the stack area.
 *  Of the 192 bytes allocated, 64 bytes are used for saving/restoring eight
 *  general registers, and 128 bytes are used to move intermediate products
 *  from the floating-point registers to the general registers.  Stack
 *  protocols assure proper alignment of these areas.
 *
 */


/*  ====================================================================*/
/*      symbolic definitions for PA-RISC registers      */
/*      in the MIPS style, avoids lots of case shifts       */
/*      assigments (except t4) preserve register number parity  */
/*  ====================================================================*/

#define zero    %r0         /* permanent zero */
#define t5      %r1         /* temp register, altered by addil */

#define rp      %r2         /* return pointer */

#define s1      %r3         /* callee saves register*/
#define s0      %r4         /* callee saves register*/
#define s3      %r5         /* callee saves register*/
#define s2      %r6         /* callee saves register*/
#define s5      %r7         /* callee saves register*/
#define s4      %r8         /* callee saves register*/
#define s7      %r9         /* callee saves register*/
#define s6      %r10        /* callee saves register*/

#define t1      %r19        /* caller saves register*/
#define t0      %r20        /* caller saves register*/
#define t3      %r21        /* caller saves register*/
#define t2      %r22        /* caller saves register*/

#define a3      %r23        /* fourth argument register, high word */
#define a2      %r24        /* third argument register, low word*/
#define a1      %r25        /* second argument register, high word*/
#define a0      %r26        /* first argument register, low word*/

#define v0      %r28        /* high order return value*/
#define v1      %r29        /* low order return value*/

#define sp      %r30        /* stack pointer*/
#define t4      %r31        /* temporary register   */

#define fa0     %fr4        /* first argument register*/
#define fa1     %fr5        /* second argument register*/
#define fa2     %fr6        /* third argument register*/
#define fa3     %fr7        /* fourth argument register*/

#define fa0r    %fr4R       /* first argument register*/
#define fa1r    %fr5R       /* second argument register*/
#define fa2r    %fr6R       /* third argument register*/
#define fa3r    %fr7R       /* fourth argument register*/

#define ft0     %fr8        /* caller saves register*/
#define ft1     %fr9        /* caller saves register*/
#define ft2     %fr10       /* caller saves register*/
#define ft3     %fr11       /* caller saves register*/

#define ft0r    %fr8R       /* caller saves register*/
#define ft1r    %fr9R       /* caller saves register*/
#define ft2r    %fr10R      /* caller saves register*/
#define ft3r    %fr11R      /* caller saves register*/

#define ft4     %fr22       /* caller saves register*/
#define ft5     %fr23       /* caller saves register*/
#define ft6     %fr24       /* caller saves register*/
#define ft7     %fr25       /* caller saves register*/
#define ft8     %fr26       /* caller saves register*/
#define ft9     %fr27       /* caller saves register*/
#define ft10    %fr28       /* caller saves register*/
#define ft11    %fr29       /* caller saves register*/
#define ft12    %fr30       /* caller saves register*/
#define ft13    %fr31       /* caller saves register*/

#define ft4r    %fr22R      /* caller saves register*/
#define ft5r    %fr23R      /* caller saves register*/
#define ft6r    %fr24R      /* caller saves register*/
#define ft7r    %fr25R      /* caller saves register*/
#define ft8r    %fr26R      /* caller saves register*/
#define ft9r    %fr27R      /* caller saves register*/
#define ft10r   %fr28R      /* caller saves register*/
#define ft11r   %fr29R      /* caller saves register*/
#define ft12r   %fr30R      /* caller saves register*/
#define ft13r   %fr31R      /* caller saves register*/



/*  ================================================================== */
/*      functional definitions for PA-RISC registers           */
/*  ================================================================== */

/*              general registers           */

#define T1      a0          /* temp, (length parameter ignored)             */

#define pM      a1          /* -> 64-bit multiplier                         */
#define T2      a1          /* temp, (after fetching multiplier)            */

#define pA      a2          /* -> multiplicand vector (8 64-bit words)      */
#define T3      a2          /* temp, (after fetching multiplicand)          */

#define pR      a3          /* -> addend vector (8 64-bit doublewords,
                                  result vector (9 64-bit words)            */

#define S0      s0          /* callee saves summand registers               */
#define S1      s1
#define S2      s2
#define S3      s3
#define S4      s4
#define S5      s5
#define S6      s6
#define S7      s7

#define S8      v0          /* caller saves summand registers               */
#define S9      v1
#define S10     t0
#define S11     t1
#define S12     t2
#define S13     t3
#define S14     t4
#define S15     t5



/*              floating-point registers                                    */

#define M       fa0         /* multiplier double word                       */
#define MR      fa0r        /* low order half of multiplier double word     */
#define ML      fa0         /* high order half of multiplier double word    */

#define A0      fa2         /* multiplicand double word 0                   */
#define A0R     fa2r        /* low order half of multiplicand double word   */
#define A0L     fa2         /* high order half of multiplicand double word  */

#define A1      fa3         /* multiplicand double word 1                   */
#define A1R     fa3r        /* low order half of multiplicand double word   */
#define A1L     fa3         /* high order half of multiplicand double word  */

#define A2      ft0         /* multiplicand double word 2                   */
#define A2R     ft0r        /* low order half of multiplicand double word   */
#define A2L     ft0         /* high order half of multiplicand double word  */

#define A3      ft1         /* multiplicand double word 3                   */
#define A3R     ft1r        /* low order half of multiplicand double word   */
#define A3L     ft1         /* high order half of multiplicand double word  */

#define A4      ft2         /* multiplicand double word 4                   */
#define A4R     ft2r        /* low order half of multiplicand double word   */
#define A4L     ft2         /* high order half of multiplicand double word  */

#define A5      ft3         /* multiplicand double word 5                   */
#define A5R     ft3r        /* low order half of multiplicand double word   */
#define A5L     ft3         /* high order half of multiplicand double word  */

#define A6      ft4         /* multiplicand double word 6                   */
#define A6R     ft4r        /* low order half of multiplicand double word   */
#define A6L     ft4         /* high order half of multiplicand double word  */

#define A7      ft5         /* multiplicand double word 7                   */
#define A7R     ft5r        /* low order half of multiplicand double word   */
#define A7L     ft5         /* high order half of multiplicand double word  */

#define P0      ft6         /* product word 0                               */
#define P1      ft7         /* product word 0                               */
#define P2      ft8         /* product word 0                               */
#define P3      ft9         /* product word 0                               */
#define P4      ft10        /* product word 0                               */
#define P5      ft11        /* product word 0                               */
#define P6      ft12        /* product word 0                               */
#define P7      ft13        /* product word 0                               */




/*  ======================================================================  */
/*      symbolic definitions for HP-UX stack offsets                        */
/*      symbolic definitions for memory NOPs                                */
/*  ======================================================================  */

#define ST_SZ       192         /* stack area total size                    */

#define SV0         -192(sp)    /* general register save area               */
#define SV1         -184(sp)
#define SV2         -176(sp)
#define SV3         -168(sp)
#define SV4         -160(sp)
#define SV5         -152(sp)
#define SV6         -144(sp)
#define SV7         -136(sp)

#define XF0         -128(sp)    /* data transfer area                       */
#define XF1         -120(sp)    /* for floating-pt to integer regs          */
#define XF2         -112(sp)
#define XF3         -104(sp)
#define XF4         -96(sp)
#define XF5         -88(sp)
#define XF6         -80(sp)
#define XF7         -72(sp)
#define XF8         -64(sp)
#define XF9         -56(sp)
#define XF10        -48(sp)
#define XF11        -40(sp)
#define XF12        -32(sp)
#define XF13        -24(sp)
#define XF14        -16(sp)
#define XF15        -8(sp)

#define mnop    proberi (sp),3,zero     /* memory NOP                       */




/*  ======================================================================  */
/*      assembler formalities                                               */
/*  ======================================================================  */

#ifdef __LP64__
                .level  2.0W
#else
                .level  2.0
#endif
                .space    $TEXT$
                .subspa   $CODE$
                .align    16

/*  ======================================================================  */
/*      here to compute 64-bit x 512-bit product + 512-bit addend           */
/*  ======================================================================  */

multacc512
        .PROC
        .CALLINFO
        .ENTER
    fldd    0(pM),M                 ; multiplier double word
    ldo     ST_SZ(sp),sp            ; push stack

    fldd    0(pA),A0                ; multiplicand double word 0
    std     S1,SV1                  ; save s1

    fldd    16(pA),A2               ; multiplicand double word 2
    std     S3,SV3                  ; save s3

    fldd    32(pA),A4               ; multiplicand double word 4
    std     S5,SV5                  ; save s5

    fldd    48(pA),A6               ; multiplicand double word 6
    std     S7,SV7                  ; save s7


    std     S0,SV0                  ; save s0
    fldd    8(pA),A1                ; multiplicand double word 1
    xmpyu   MR,A0L,P0               ; A0 cross 32-bit word products
    xmpyu   ML,A0R,P2

    std     S2,SV2                  ; save s2
    fldd    24(pA),A3               ; multiplicand double word 3
    xmpyu   MR,A2L,P4               ; A2 cross 32-bit word products
    xmpyu   ML,A2R,P6

    std     S4,SV4                  ; save s4
    fldd    40(pA),A5               ; multiplicand double word 5

    std     S6,SV6                  ; save s6
    fldd    56(pA),A7               ; multiplicand double word 7


    fstd    P0,XF0                  ; MR * A0L
    xmpyu   MR,A0R,P0               ; A0 right 32-bit word product
    xmpyu   MR,A1L,P1               ; A1 cross 32-bit word product

    fstd    P2,XF2                  ; ML * A0R
    xmpyu   ML,A0L,P2               ; A0 left 32-bit word product
    xmpyu   ML,A1R,P3               ; A1 cross 32-bit word product

    fstd    P4,XF4                  ; MR * A2L
    xmpyu   MR,A2R,P4               ; A2 right 32-bit word product
    xmpyu   MR,A3L,P5               ; A3 cross 32-bit word product

    fstd    P6,XF6                  ; ML * A2R
    xmpyu   ML,A2L,P6               ; A2 parallel 32-bit word product
    xmpyu   ML,A3R,P7               ; A3 cross 32-bit word product


    ldd     XF0,S0                  ; MR * A0L
    fstd    P1,XF1                  ; MR * A1L

    ldd     XF2,S2                  ; ML * A0R
    fstd    P3,XF3                  ; ML * A1R

    ldd     XF4,S4                  ; MR * A2L
    fstd    P5,XF5                  ; MR * A3L
    xmpyu   MR,A1R,P1               ; A1 parallel 32-bit word products
    xmpyu   ML,A1L,P3

    ldd     XF6,S6                  ; ML * A2R
    fstd    P7,XF7                  ; ML * A3R
    xmpyu   MR,A3R,P5               ; A3 parallel 32-bit word products
    xmpyu   ML,A3L,P7


    fstd    P0,XF0                  ; MR * A0R
    ldd     XF1,S1                  ; MR * A1L
    nop
    add     S0,S2,T1                ; A0 cross product sum

    fstd    P2,XF2                  ; ML * A0L
    ldd     XF3,S3                  ; ML * A1R
    add,dc  zero,zero,S0            ; A0 cross product sum carry
    depd,z  T1,31,32,S2             ; A0 cross product sum << 32

    fstd    P4,XF4                  ; MR * A2R
    ldd     XF5,S5                  ; MR * A3L
    shrpd   S0,T1,32,S0             ; A0 carry | cross product sum >> 32
    add     S4,S6,T3                ; A2 cross product sum

    fstd    P6,XF6                  ; ML * A2L
    ldd     XF7,S7                  ; ML * A3R
    add,dc  zero,zero,S4            ; A2 cross product sum carry
    depd,z  T3,31,32,S6             ; A2 cross product sum << 32


    ldd     XF0,S8                  ; MR * A0R
    fstd    P1,XF1                  ; MR * A1R
    xmpyu   MR,A4L,P0               ; A4 cross 32-bit word product
    xmpyu   MR,A5L,P1               ; A5 cross 32-bit word product

    ldd     XF2,S10                 ; ML * A0L
    fstd    P3,XF3                  ; ML * A1L
    xmpyu   ML,A4R,P2               ; A4 cross 32-bit word product
    xmpyu   ML,A5R,P3               ; A5 cross 32-bit word product

    ldd     XF4,S12                 ; MR * A2R
    fstd    P5,XF5                  ; MR * A3L
    xmpyu   MR,A6L,P4               ; A6 cross 32-bit word product
    xmpyu   MR,A7L,P5               ; A7 cross 32-bit word product

    ldd     XF6,S14                 ; ML * A2L
    fstd    P7,XF7                  ; ML * A3L
    xmpyu   ML,A6R,P6               ; A6 cross 32-bit word product
    xmpyu   ML,A7R,P7               ; A7 cross 32-bit word product


    fstd    P0,XF0                  ; MR * A4L
    ldd     XF1,S9                  ; MR * A1R
    shrpd   S4,T3,32,S4             ; A2 carry | cross product sum >> 32
    add     S1,S3,T1                ; A1 cross product sum

    fstd    P2,XF2                  ; ML * A4R
    ldd     XF3,S11                 ; ML * A1L
    add,dc  zero,zero,S1            ; A1 cross product sum carry
    depd,z  T1,31,32,S3             ; A1 cross product sum << 32

    fstd    P4,XF4                  ; MR * A6L
    ldd     XF5,S13                 ; MR * A3R
    shrpd   S1,T1,32,S1             ; A1 carry | cross product sum >> 32
    add     S5,S7,T3                ; A3 cross product sum

    fstd    P6,XF6                  ; ML * A6R
    ldd     XF7,S15                 ; ML * A3L
    add,dc  zero,zero,S5            ; A3 cross product sum carry
    depd,z  T3,31,32,S7             ; A3 cross product sum << 32


    shrpd   S5,T3,32,S5             ; A3 carry | cross product sum >> 32
    add     S2,S8,S8                ; M * A0 right doubleword, P0 doubleword

    add,dc  S0,S10,S10              ; M * A0 left doubleword
    add     S3,S9,S9                ; M * A1 right doubleword

    add,dc  S1,S11,S11              ; M * A1 left doubleword
    add     S6,S12,S12              ; M * A2 right doubleword


    ldd     24(pR),S3               ; Addend word 3
    fstd    P1,XF1                  ; MR * A5L
    add,dc  S4,S14,S14              ; M * A2 left doubleword
    xmpyu   MR,A5R,P1               ; A5 right 32-bit word product

    ldd     8(pR),S1                ; Addend word 1
    fstd    P3,XF3                  ; ML * A5R
    add     S7,S13,S13              ; M * A3 right doubleword
    xmpyu   ML,A5L,P3               ; A5 left 32-bit word product

    ldd     0(pR),S7                ; Addend word 0
    fstd    P5,XF5                  ; MR * A7L
    add,dc  S5,S15,S15              ; M * A3 left doubleword
    xmpyu   MR,A7R,P5               ; A7 right 32-bit word product

    ldd     16(pR),S5               ; Addend word 2
    fstd    P7,XF7                  ; ML * A7R
    add     S10,S9,S9               ; P1 doubleword
    xmpyu   ML,A7L,P7               ; A7 left 32-bit word products


    ldd     XF0,S0                  ; MR * A4L
    fstd    P1,XF9                  ; MR * A5R
    add,dc  S11,S12,S12             ; P2 doubleword
    xmpyu   MR,A4R,P0               ; A4 right 32-bit word product

    ldd     XF2,S2                  ; ML * A4R
    fstd    P3,XF11                 ; ML * A5L
    add,dc  S14,S13,S13             ; P3 doubleword
    xmpyu   ML,A4L,P2               ; A4 left 32-bit word product

    ldd     XF6,S6                  ; ML * A6R
    fstd    P5,XF13                 ; MR * A7R
    add,dc  zero,S15,T2             ; P4 partial doubleword
    xmpyu   MR,A6R,P4               ; A6 right 32-bit word product

    ldd     XF4,S4                  ; MR * A6L
    fstd    P7,XF15                 ; ML * A7L
    add     S7,S8,S8                ; R0 + P0, new R0 doubleword
    xmpyu   ML,A6L,P6               ; A6 left 32-bit word product


    fstd    P0,XF0                  ; MR * A4R
    ldd     XF7,S7                  ; ML * A7R
    add,dc  S1,S9,S9                ; c + R1 + P1, new R1 doubleword

    fstd    P2,XF2                  ; ML * A4L
    ldd     XF1,S1                  ; MR * A5L
    add,dc  S5,S12,S12              ; c + R2 + P2, new R2 doubleword

    fstd    P4,XF4                  ; MR * A6R
    ldd     XF5,S5                  ; MR * A7L
    add,dc  S3,S13,S13              ; c + R3 + P3, new R3 doubleword

    fstd    P6,XF6                  ; ML * A6L
    ldd     XF3,S3                  ; ML * A5R
    add,dc  zero,T2,T2              ; c + partial P4
    add     S0,S2,T1                ; A4 cross product sum


    std     S8,0(pR)                ; save R0
    add,dc  zero,zero,S0            ; A4 cross product sum carry
    depd,z  T1,31,32,S2             ; A4 cross product sum << 32

    std     S9,8(pR)                ; save R1
    shrpd   S0,T1,32,S0             ; A4 carry | cross product sum >> 32
    add     S4,S6,T3                ; A6 cross product sum

    std     S12,16(pR)              ; save R2
    add,dc  zero,zero,S4            ; A6 cross product sum carry
    depd,z  T3,31,32,S6             ; A6 cross product sum << 32


    std     S13,24(pR)              ; save R3
    shrpd   S4,T3,32,S4             ; A6 carry | cross product sum >> 32
    add     S1,S3,T1                ; A5 cross product sum

    ldd     XF0,S8                  ; MR * A4R
    add,dc  zero,zero,S1            ; A5 cross product sum carry
    depd,z  T1,31,32,S3             ; A5 cross product sum << 32

    ldd     XF2,S10                 ; ML * A4L
    ldd     XF9,S9                  ; MR * A5R
    shrpd   S1,T1,32,S1             ; A5 carry | cross product sum >> 32
    add     S5,S7,T3                ; A7 cross product sum

    ldd     XF4,S12                 ; MR * A6R
    ldd     XF11,S11                ; ML * A5L
    add,dc  zero,zero,S5            ; A7 cross product sum carry
    depd,z  T3,31,32,S7             ; A7 cross product sum << 32

    ldd     XF6,S14                 ; ML * A6L
    ldd     XF13,S13                ; MR * A7R
    shrpd   S5,T3,32,S5             ; A7 carry | cross product sum >> 32
    add     S2,S8,S8                ; M * A4 right doubleword


    ldd     XF15,S15                ; ML * A7L
    add,dc  S0,S10,S10              ; M * A4 left doubleword
    add     S3,S9,S9                ; M * A5 right doubleword

    add,dc  S1,S11,S11              ; M * A5 left doubleword
    add     S6,S12,S12              ; M * A6 right doubleword

    ldd     32(pR),S0               ; Addend word 4
    ldd     40(pR),S1               ; Addend word 5
    add,dc  S4,S14,S14              ; M * A6 left doubleword
    add     S7,S13,S13              ; M * A7 right doubleword

    ldd     48(pR),S2               ; Addend word 6
    ldd     56(pR),S3               ; Addend word 7
    add,dc  S5,S15,S15              ; M * A7 left doubleword
    add     S8,T2,S8                ; P4 doubleword

    ldd     64(pR),S4               ; Addend word 8
    ldd     SV5,s5                  ; restore s5
    add,dc  S10,S9,S9               ; P5 doubleword
    add,dc  S11,S12,S12             ; P6 doubleword


    ldd     SV6,s6                  ; restore s6
    ldd     SV7,s7                  ; restore s7
    add,dc  S14,S13,S13             ; P7 doubleword
    add,dc  zero,S15,S15            ; P8 doubleword

    add     S0,S8,S8                ; new R4 doubleword

    ldd     SV0,s0                  ; restore s0
    std     S8,32(pR)               ; save R4
    add,dc  S1,S9,S9                ; new R5 doubleword

    ldd     SV1,s1                  ; restore s1
    std     S9,40(pR)               ; save R5
    add,dc  S2,S12,S12              ; new R6 doubleword

    ldd     SV2,s2                  ; restore s2
    std     S12,48(pR)              ; save R6
    add,dc  S3,S13,S13              ; new R7 doubleword

    ldd     SV3,s3                  ; restore s3
    std     S13,56(pR)              ; save R7
    add,dc  S4,S15,S15              ; new R8 doubleword

    ldd     SV4,s4                  ; restore s4
    std     S15,64(pR)              ; save result[8]
    add,dc  zero,zero,v0            ; return carry from R8

    CMPIB,*= 0,v0,$L0               ; if no overflow, exit
    LDO     8(pR),pR

$FINAL1                             ; Final carry propagation
    LDD     64(pR),v0
    LDO     8(pR),pR
    ADDI    1,v0,v0
    CMPIB,*= 0,v0,$FINAL1           ; Keep looping if there is a carry.
    STD     v0,56(pR)
$L0
    bv      zero(rp)                ; -> caller
    ldo     -ST_SZ(sp),sp           ; pop stack

/*  ======================================================================  */
/*      end of module                                                       */
/*  ======================================================================  */

                .LEAVE

                .PROCEND
                .SPACE         $TEXT$
                .SUBSPA        $CODE$
                .EXPORT        multacc512,ENTRY

        .end