Annotation of mstools/samples/largeint/alpha/largeint.s, revision 1.1.1.1

1.1       root        1: //      TITLE("Large Integer Arithmetic")
                      2: //++
                      3: //
                      4: // Copyright (c) 1990  Microsoft Corporation
                      5: // Copyright (c) 1993  Digital Equipment Corporation
                      6: //
                      7: // Module Name:
                      8: //
                      9: //    largeint.s
                     10: //
                     11: // Abstract:
                     12: //
                     13: //    This module implements routines for performing extended integer
                     14: //    arithmetic.
                     15: //
                     16: // Author:
                     17: //
                     18: //    David N. Cutler (davec) 18-Apr-1990
                     19: //
                     20: // Environment:
                     21: //
                     22: //    Any mode.
                     23: //
                     24: // Revision History:
                     25: //
                     26: //    Thomas Van Baak (tvb) 9-May-1992
                     27: //
                     28: //        Adapted for Alpha AXP.
                     29: //
                     30: //--
                     31: 
                     32: #include "ksalpha.h"
                     33: 
                     34: //
                     35: // Alpha AXP Implementation Notes:
                     36: //
                     37: //    The LargeInteger functions defined below implement a set of portable
                     38: //    64-bit integer arithmetic operations for x86, Mips, and Alpha systems
                     39: //    using the LARGE_INTEGER data type. Code using LARGE_INTEGER variables
                     40: //    and calling these functions will be portable across all NT platforms.
                     41: //    This is the recommended approach to 64-bit arithmetic on NT.
                     42: //
                     43: //    However, if performance is more important than portability, then for
                     44: //    Alpha systems, the native 64-bit integer data types may be used instead
                     45: //    of the LARGE_INTEGER type and the LargeInteger functions. The Alpha C
                     46: //    compilers support a __int64 data type (renamed LONGLONG in the system
                     47: //    header files). All C integer arithmetic operators may be used with
                     48: //    these quadword types. This eliminates the need for, and the overhead
                     49: //    of, any of the portable LargeInteger functions.
                     50: //
                     51: //    In general, a LARGE_INTEGER cannot simply be converted to a LONGLONG
                     52: //    because of explicit references in application code to the 32-bit LowPart
                     53: //    and HighPart members of the LARGE_INTEGER structure.
                     54: //
                     55: //    The performance difference between using the portable LARGE_INTEGER
                     56: //    types with LargeInteger functions and the Alpha LONGLONG types and
                     57: //    operations is often not significant enough to warrant modifying otherwise
                     58: //    portable code. In addition, future compiler optimization and inlining may
                     59: //    actually result in identical performance between portable LARGE_INTEGER
                     60: //    code and Alpha specific LONGLONG code. Therefore it is recommended to
                     61: //    keep NT source code portable.
                     62: //
                     63: //    The Alpha source for the large integer functions below differs from the
                     64: //    Mips version since for Alpha a 64-bit argument or return value is passed
                     65: //    through a 64-bit integer register. In addition, most operations are
                     66: //    implemented with a single instruction. The division routines below,
                     67: //    however, like Mips, use a simple shift/subtract algorithm which is
                     68: //    considerably slower than the algorithm used by Alpha runtime division
                     69: //    routines.
                     70: //
                     71: 
                     72:         SBTTL("Convert Long to Large Integer")
                     73: //++
                     74: //
                     75: // LARGE_INTEGER
                     76: // ConvertLongToLargeInteger (
                     77: //    IN LONG SignedInteger
                     78: //    )
                     79: //
                     80: // Routine Description:
                     81: //
                     82: //    This function converts a signed integer to a signed large integer
                     83: //    and returns the result.
                     84: //
                     85: // Arguments:
                     86: //
                     87: //    SignedInteger (a0) - Supplies the value to convert.
                     88: //
                     89: // Return Value:
                     90: //
                     91: //    The large integer result is returned as the function value in v0.
                     92: //
                     93: //--
                     94: 
                     95:         LEAF_ENTRY(ConvertLongToLargeInteger)
                     96: 
                     97:         addl    a0, 0, v0               // ensure canonical (signed long) form
                     98:         ret     zero, (ra)              // return
                     99: 
                    100:         .end    ConvertLongToLargeInteger
                    101: 
                    102:         SBTTL("Convert Ulong to Large Integer")
                    103: //++
                    104: //
                    105: // LARGE_INTEGER
                    106: // ConvertUlongToLargeInteger (
                    107: //    IN ULONG UnsignedInteger
                    108: //    )
                    109: //
                    110: // Routine Description:
                    111: //
                    112: //    This function converts an unsigned integer to a signed large
                    113: //    integer and returns the result.
                    114: //
                    115: // Arguments:
                    116: //
                    117: //    UnsignedInteger (a0) - Supplies the value to convert.
                    118: //
                    119: // Return Value:
                    120: //
                    121: //    The large integer result is returned as the function value in v0.
                    122: //
                    123: //--
                    124: 
                    125:         LEAF_ENTRY(ConvertUlongToLargeInteger)
                    126: 
                    127:         zap     a0, 0xf0, v0            // convert canonical ULONG to quadword
                    128:         ret     zero, (ra)              // return
                    129: 
                    130:         .end    ConvertUlongToLargeInteger
                    131: 
                    132:         SBTTL("Enlarged Signed Integer Multiply")
                    133: //++
                    134: //
                    135: // LARGE_INTEGER
                    136: // EnlargedIntegerMultiply (
                    137: //    IN LONG Multiplicand,
                    138: //    IN LONG Multiplier
                    139: //    )
                    140: //
                    141: // Routine Description:
                    142: //
                    143: //    This function multiplies a signed integer by a signed integer and
                    144: //    returns a signed large integer result.
                    145: //
                    146: //    N.B. An overflow is not possible.
                    147: //
                    148: // Arguments:
                    149: //
                    150: //    Multiplicand (a0) - Supplies the multiplicand value.
                    151: //
                    152: //    Multiplier (a1) - Supplies the multiplier value.
                    153: //
                    154: // Return Value:
                    155: //
                    156: //    The large integer result is returned as the function value in v0.
                    157: //
                    158: //--
                    159: 
                    160:         LEAF_ENTRY(EnlargedIntegerMultiply)
                    161: 
                    162:         addl    a0, 0, a0               // ensure canonical (signed long) form
                    163:         addl    a1, 0, a1               // ensure canonical (signed long) form
                    164:         mulq    a0, a1, v0              // multiply signed both quadwords
                    165:         ret     zero, (ra)              // return
                    166: 
                    167:         .end    EnlargedIntegerMultiply
                    168: 
                    169:         SBTTL("Enlarged Unsigned Divide")
                    170: //++
                    171: //
                    172: // ULONG
                    173: // EnlargedUnsignedDivide (
                    174: //    IN ULARGE_INTEGER Dividend,
                    175: //    IN ULONG Divisor,
                    176: //    IN OUT PULONG Remainder OPTIONAL
                    177: //    )
                    178: //
                    179: // Routine Description:
                    180: //
                    181: //    This function divides an unsigned large integer by an unsigned long
                    182: //    and returns the resultant quotient and optionally the remainder.
                    183: //
                    184: //    N.B. An overflow or divide by zero exception is possible.
                    185: //
                    186: // Arguments:
                    187: //
                    188: //    Dividend (a0) - Supplies the unsigned 64-bit dividend value.
                    189: //
                    190: //    Divisor (a1) - Supplies the unsigned 32-bit divisor value.
                    191: //
                    192: //    Remainder (a2) - Supplies an optional pointer to a variable that
                    193: //      receives the unsigned 32-bit remainder.
                    194: //
                    195: // Return Value:
                    196: //
                    197: //    The unsigned long integer quotient is returned as the function value.
                    198: //
                    199: //--
                    200: 
                    201:         LEAF_ENTRY(EnlargedUnsignedDivide)
                    202: 
                    203: //
                    204: // Check for division by zero.
                    205: //
                    206: 
                    207:         zap     a1, 0xf0, a1            // convert ULONG divisor to quadword
                    208:         beq     a1, 30f                 // trap if divisor is zero
                    209: 
                    210: //
                    211: // Check for overflow. If the divisor is less than the upper half of the
                    212: // dividend the quotient would be wider than 32 bits.
                    213: //
                    214: 
                    215:         srl     a0, 32, t0              // get upper longword of dividend
                    216:         cmpule  a1, t0, t1              // is divisor <= upper dividend?
                    217:         bne     t1, 40f                 // if ne[true], then overflow trap
                    218: 
                    219: //
                    220: // Perform the shift/subtract loop 8 times and 4 bits per loop.
                    221: //
                    222: // t0 - Temp used for 0/1 results of compares.
                    223: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
                    224: // t2 - Loop counter.
                    225: //
                    226: 
                    227:         ldiq    t2, 32/4                // set iteration count
                    228: 
                    229:         srl     a0, 32, t1              // get top 32 bits of carry-out
                    230:         sll     a0, 32, a0              // preshift first 32 bits left
                    231: 
                    232: 10:     cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    233:         addq    a0, a0, a0              // shift low-dividend left
                    234:         addq    t1, t1, t1              // shift high-dividend left
                    235:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    236: 
                    237:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    238:         addq    a0, t0, a0              //   then set quotient bit
                    239:         subq    t1, a1, t0              // subtract divisor from dividend,
                    240:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    241: 
                    242:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    243:         addq    a0, a0, a0              // shift low-dividend left
                    244:         addq    t1, t1, t1              // shift high-dividend left
                    245:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    246: 
                    247:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    248:         addq    a0, t0, a0              //   then set quotient bit
                    249:         subq    t1, a1, t0              // subtract divisor from dividend,
                    250:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    251: 
                    252:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    253:         addq    a0, a0, a0              // shift low-dividend left
                    254:         addq    t1, t1, t1              // shift high-dividend left
                    255:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    256: 
                    257:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    258:         addq    a0, t0, a0              //   then set quotient bit
                    259:         subq    t1, a1, t0              // subtract divisor from dividend,
                    260:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    261: 
                    262:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    263:         addq    a0, a0, a0              // shift low-dividend left
                    264:         addq    t1, t1, t1              // shift high-dividend left
                    265:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    266: 
                    267:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    268:         addq    a0, t0, a0              //   then set quotient bit
                    269:         subq    t1, a1, t0              // subtract divisor from dividend,
                    270:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    271: 
                    272:         subq    t2, 1, t2               // any more iterations?
                    273:         bne     t2, 10b                 //
                    274: 
                    275: //
                    276: // Finished with remainder value in t1 and quotient value in a0.
                    277: //
                    278: 
                    279:         addl    a0, 0, v0               // set longword quotient return value
                    280:         beq     a2, 20f                 // skip optional remainder store
                    281:         stl     t1, 0(a2)               // store longword remainder
                    282: 
                    283: 20:     ret     zero, (ra)              // return
                    284: 
                    285: //
                    286: // Generate an exception for divide by zero and return a zero quotient if the
                    287: // caller continues execution.
                    288: //
                    289: 
                    290: 30:     ldil    a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
                    291: 
                    292:         GENERATE_TRAP
                    293: 
                    294:         ldil    v0, 0                   // return zero quotient
                    295:         ret     zero, (ra)              // return
                    296: 
                    297: //
                    298: // Generate an exception for overflow.
                    299: //
                    300: 
                    301: 40:     ldiq    a0, 0x8000000000000000  //
                    302:         subqv   zero, a0, v0            // negate in order to overflow
                    303:         trapb                           // wait for trap to occur
                    304:         ret     zero, (ra)              // return
                    305: 
                    306:         .end    EnlargedUnsignedDivide
                    307: 
                    308:         SBTTL("Enlarged Unsigned Integer Multiply")
                    309: //++
                    310: //
                    311: // LARGE_INTEGER
                    312: // EnlargedUnsignedMultiply (
                    313: //    IN ULONG Multiplicand,
                    314: //    IN ULONG Multiplier
                    315: //    )
                    316: //
                    317: // Routine Description:
                    318: //
                    319: //    This function multiplies an unsigned integer by an unsigned integer
                    320: //    and returns a signed large integer result.
                    321: //
                    322: // Arguments:
                    323: //
                    324: //    Multiplicand (a0) - Supplies the multiplicand value.
                    325: //
                    326: //    Multiplier (a1) - Supplies the multiplier value.
                    327: //
                    328: // Return Value:
                    329: //
                    330: //    The large integer result is returned as the function value in v0.
                    331: //
                    332: //--
                    333: 
                    334:         LEAF_ENTRY(EnlargedUnsignedMultiply)
                    335: 
                    336:         zap     a0, 0xf0, a0            // convert canonical ULONG to quadword
                    337:         zap     a1, 0xf0, a1            // convert canonical ULONG to quadword
                    338:         mulq    a0, a1, v0              // multiply signed both quadwords
                    339:         ret     zero, (ra)              // return
                    340: 
                    341:         .end    EnlargedUnsignedMultiply
                    342: 
                    343:         SBTTL("Extended Integer Multiply")
                    344: //++
                    345: //
                    346: // LARGE_INTEGER
                    347: // ExtendedIntegerMultiply (
                    348: //    IN LARGE_INTEGER Multiplicand,
                    349: //    IN LONG Multiplier
                    350: //    )
                    351: //
                    352: // Routine Description:
                    353: //
                    354: //    This function multiplies a signed large integer by a signed integer and
                    355: //    returns the signed large integer result.
                    356: //
                    357: //    N.B. An overflow is possible, but no exception is generated.
                    358: //
                    359: // Arguments:
                    360: //
                    361: //    Multiplicand (a0) - Supplies the multiplicand value.
                    362: //
                    363: //    Multiplier (a1) - Supplies the multiplier value.
                    364: //
                    365: // Return Value:
                    366: //
                    367: //    The large integer result is returned as the function value in v0.
                    368: //
                    369: //--
                    370: 
                    371:         LEAF_ENTRY(ExtendedIntegerMultiply)
                    372: 
                    373:         addl    a1, 0, a1               // ensure canonical (signed long) form
                    374:         mulq    a0, a1, v0              // multiply signed both quadwords
                    375:         ret     zero, (ra)              // return
                    376: 
                    377:         .end    ExtendedIntegerMultiply
                    378: 
                    379:         SBTTL("Extended Large Integer Divide")
                    380: //++
                    381: //
                    382: // LARGE_INTEGER
                    383: // ExtendedLargeIntegerDivide (
                    384: //    IN LARGE_INTEGER Dividend,
                    385: //    IN ULONG Divisor,
                    386: //    IN OUT PULONG Remainder OPTIONAL
                    387: //    )
                    388: //
                    389: // Routine Description:
                    390: //
                    391: //    This function divides an unsigned large integer by an unsigned long
                    392: //    and returns the quadword quotient and optionally the long remainder.
                    393: //
                    394: //    N.B. A divide by zero exception is possible.
                    395: //
                    396: // Arguments:
                    397: //
                    398: //    Dividend (a0) - Supplies the dividend value.
                    399: //
                    400: //    Divisor (a1) - Supplies the divisor value.
                    401: //
                    402: //    Remainder (a2) - Supplies an optional pointer to a variable that
                    403: //      receives the remainder.
                    404: //
                    405: // Return Value:
                    406: //
                    407: //    The large integer result is returned as the function value in v0.
                    408: //
                    409: //--
                    410: 
                    411:         LEAF_ENTRY(ExtendedLargeIntegerDivide)
                    412: 
                    413: //
                    414: // Check for division by zero.
                    415: //
                    416: 
                    417:         zap     a1, 0xf0, a1            // convert canonical ULONG to quadword
                    418:         beq     a1, 30f                 // trap if divisor is zero
                    419: 
                    420: //
                    421: // Perform the shift/subtract loop 16 times and 4 bits per loop.
                    422: //
                    423: // t0 - Temp used for 0/1 results of compares.
                    424: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
                    425: // t2 - Loop counter.
                    426: //
                    427: 
                    428:         ldiq    t2, 64/4                // set iteration count
                    429: 
                    430:         ldiq    t1, 0                   // zero-extend dividend to 128 bits
                    431: 
                    432: 10:     cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    433:         addq    a0, a0, a0              // shift low-dividend left
                    434:         addq    t1, t1, t1              // shift high-dividend left
                    435:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    436: 
                    437:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    438:         addq    a0, t0, a0              //   then set quotient bit
                    439:         subq    t1, a1, t0              // subtract divisor from dividend,
                    440:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    441: 
                    442:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    443:         addq    a0, a0, a0              // shift low-dividend left
                    444:         addq    t1, t1, t1              // shift high-dividend left
                    445:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    446: 
                    447:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    448:         addq    a0, t0, a0              //   then set quotient bit
                    449:         subq    t1, a1, t0              // subtract divisor from dividend,
                    450:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    451: 
                    452:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    453:         addq    a0, a0, a0              // shift low-dividend left
                    454:         addq    t1, t1, t1              // shift high-dividend left
                    455:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    456: 
                    457:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    458:         addq    a0, t0, a0              //   then set quotient bit
                    459:         subq    t1, a1, t0              // subtract divisor from dividend,
                    460:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    461: 
                    462:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    463:         addq    a0, a0, a0              // shift low-dividend left
                    464:         addq    t1, t1, t1              // shift high-dividend left
                    465:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    466: 
                    467:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    468:         addq    a0, t0, a0              //   then set quotient bit
                    469:         subq    t1, a1, t0              // subtract divisor from dividend,
                    470:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    471: 
                    472:         subq    t2, 1, t2               // any more iterations?
                    473:         bne     t2, 10b                 //
                    474: 
                    475: //
                    476: // Finished with remainder value in t1 and quotient value in a0.
                    477: //
                    478: 
                    479:         mov     a0, v0                  // set quadword quotient return value
                    480:         beq     a2, 20f                 // skip optional remainder store
                    481:         stl     t1, 0(a2)               // store longword remainder
                    482: 
                    483: 20:     ret     zero, (ra)              // return
                    484: 
                    485: //
                    486: // Generate an exception for divide by zero.
                    487: //
                    488: 
                    489: 30:     ldil    a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
                    490: 
                    491:         GENERATE_TRAP
                    492: 
                    493:         br      zero, 30b               // in case they continue
                    494: 
                    495:         .end    ExtendedLargeIntegerDivide
                    496: 
                    497:         SBTTL("Extended Magic Divide")
                    498: //++
                    499: //
                    500: // LARGE_INTEGER
                    501: // ExtendedMagicDivide (
                    502: //    IN LARGE_INTEGER Dividend,
                    503: //    IN LARGE_INTEGER MagicDivisor,
                    504: //    IN CCHAR ShiftCount
                    505: //    )
                    506: //
                    507: // Routine Description:
                    508: //
                    509: //    This function divides a signed large integer by an unsigned large integer
                    510: //    and returns the signed large integer result. The division is performed
                    511: //    using reciprocal multiplication of a signed large integer value by an
                    512: //    unsigned large integer fraction which represents the most significant
                    513: //    64-bits of the reciprocal divisor rounded up in its least significant bit
                    514: //    and normalized with respect to bit 63. A shift count is also provided
                    515: //    which is used to truncate the fractional bits from the result value.
                    516: //
                    517: // Arguments:
                    518: //
                    519: //    Dividend (a0) - Supplies the dividend value.
                    520: //
                    521: //    MagicDivisor (a1) - Supplies the magic divisor value which
                    522: //      is a 64-bit multiplicative reciprocal.
                    523: //
                    524: //    Shiftcount (a2) - Supplies the right shift adjustment value.
                    525: //
                    526: // Return Value:
                    527: //
                    528: //    The large integer result is returned as the function value in v0.
                    529: //
                    530: //--
                    531: 
                    532:         LEAF_ENTRY(ExtendedMagicDivide)
                    533: 
                    534: //
                    535: // Make the dividend positive for the reciprocal multiplication to work.
                    536: //
                    537: 
                    538:         negq    a0, t0                  // negate dividend
                    539:         cmovgt  a0, a0, t0              // get absolute value in t0
                    540: 
                    541: //
                    542: // Multiply both quadword arguments together and take only the upper 64 bits of
                    543: // the resulting 128 bit product. This can be done using the umulh instruction.
                    544: //
                    545: // Division of a dividend by a constant divisor through reciprocal
                    546: // multiplication works because a/b is equivalent to (a*x)/(b*x) for any
                    547: // value of x. Now if b is a constant, some "magic" integer x can be chosen,
                    548: // based on the value of b, so that (b*x) is very close to a large power of
                    549: // two (e.g., 2^64). Then a/b = (a*x)/(b*x) = (a*x)/(2^64) = (a*x)>>64. This
                    550: // effectively turns the problem of division by a constant into multiplication
                    551: // by a constant which is a much faster operation.
                    552: //
                    553: 
                    554:         umulh   t0, a1, t1              // multiply high both quadword arguments
                    555:         sra     t1, a2, t1              // shift result right by requested amount
                    556: 
                    557: //
                    558: // Make the result negative if the dividend was negative.
                    559: //
                    560: 
                    561:         negq    t1, t0                  // negate result
                    562:         cmovgt  a0, t1, t0              // restore sign of dividend
                    563: 
                    564:         mov     t0, v0                  // set quadword result return value
                    565:         ret     zero, (ra)              // return
                    566: 
                    567:         .end    ExtendedMagicDivide
                    568: 
                    569:         SBTTL("Large Integer Add")
                    570: //++
                    571: //
                    572: // LARGE_INTEGER
                    573: // LargeIntegerAdd (
                    574: //    IN LARGE_INTEGER Addend1,
                    575: //    IN LARGE_INTEGER Addend2
                    576: //    )
                    577: //
                    578: // Routine Description:
                    579: //
                    580: //    This function adds a signed large integer to a signed large integer and
                    581: //    returns the signed large integer result.
                    582: //
                    583: //    N.B. An overflow is possible, but no exception is generated.
                    584: //
                    585: // Arguments:
                    586: //
                    587: //    Addend1 (a0) - Supplies the first addend value.
                    588: //
                    589: //    Addend2 (a1) - Supplies the second addend value.
                    590: //
                    591: // Return Value:
                    592: //
                    593: //    The large integer result is returned as the function value in v0.
                    594: //
                    595: //--
                    596: 
                    597:         LEAF_ENTRY(LargeIntegerAdd)
                    598: 
                    599:         addq    a0, a1, v0              // add both quadword arguments
                    600:         ret     zero, (ra)              // return
                    601: 
                    602:         .end    LargeIntegerAdd
                    603: 
                    604:         SBTTL("Large Integer Arithmetic Shift Right")
                    605: //++
                    606: //
                    607: // LARGE_INTEGER
                    608: // LargeIntegerArithmeticShift (
                    609: //    IN LARGE_INTEGER LargeInteger,
                    610: //    IN CCHAR ShiftCount
                    611: //    )
                    612: //
                    613: // Routine Description:
                    614: //
                    615: //    This function shifts a signed large integer right by an unsigned integer
                    616: //    modulo 64 and returns the shifted signed large integer result.
                    617: //
                    618: // Arguments:
                    619: //
                    620: //    LargeInteger (a0) - Supplies the large integer to be shifted.
                    621: //
                    622: //    ShiftCount (a1) - Supplies the right shift count.
                    623: //
                    624: // Return Value:
                    625: //
                    626: //    The large integer result is returned as the function value in v0.
                    627: //
                    628: //--
                    629: 
                    630:         LEAF_ENTRY(LargeIntegerArithmeticShift)
                    631: 
                    632:         sra     a0, a1, v0              // shift the quadword right/arithmetic
                    633:         ret     zero, (ra)              // return
                    634: 
                    635:         .end    LargeIntegerArithmeticShift
                    636: 
                    637:         SBTTL("Large Integer Divide")
                    638: //++
                    639: //
                    640: // LARGE_INTEGER
                    641: // LargeIntegerDivide (
                    642: //    IN LARGE_INTEGER Dividend,
                    643: //    IN LARGE_INTEGER Divisor,
                    644: //    IN OUT PLARGE_INTEGER Remainder OPTIONAL
                    645: //    )
                    646: //
                    647: // Routine Description:
                    648: //
                    649: //    This function divides an unsigned large integer by an unsigned large
                    650: //    integer and returns the quadword quotient and optionally the quadword
                    651: //    remainder.
                    652: //
                    653: //    N.B. A divide by zero exception is possible.
                    654: //
                    655: // Arguments:
                    656: //
                    657: //    Dividend (a0) - Supplies the dividend value.
                    658: //
                    659: //    Divisor (a1) - Supplies the divisor value.
                    660: //
                    661: //    Remainder (a2) - Supplies an optional pointer to a variable that
                    662: //      receives the remainder.
                    663: //
                    664: // Return Value:
                    665: //
                    666: //    The large integer result is returned as the function value in v0.
                    667: //
                    668: //--
                    669: 
                    670:         LEAF_ENTRY(LargeIntegerDivide)
                    671: 
                    672: //
                    673: // Check for division by zero.
                    674: //
                    675: 
                    676:         beq     a1, 30f                 // trap if divisor is zero
                    677: 
                    678: //
                    679: // Perform the shift/subtract loop 16 times and 4 bits per loop.
                    680: //
                    681: // t0 - Temp used for 0/1 results of compares.
                    682: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
                    683: // t2 - Loop counter.
                    684: //
                    685: 
                    686:         ldiq    t2, 64/4                // set iteration count
                    687: 
                    688:         ldiq    t1, 0                   // zero-extend dividend to 128 bits
                    689: 
                    690: 10:     cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    691:         addq    a0, a0, a0              // shift low-dividend left
                    692:         addq    t1, t1, t1              // shift high-dividend left
                    693:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    694: 
                    695:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    696:         addq    a0, t0, a0              //   then set quotient bit
                    697:         subq    t1, a1, t0              // subtract divisor from dividend,
                    698:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    699: 
                    700:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    701:         addq    a0, a0, a0              // shift low-dividend left
                    702:         addq    t1, t1, t1              // shift high-dividend left
                    703:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    704: 
                    705:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    706:         addq    a0, t0, a0              //   then set quotient bit
                    707:         subq    t1, a1, t0              // subtract divisor from dividend,
                    708:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    709: 
                    710:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    711:         addq    a0, a0, a0              // shift low-dividend left
                    712:         addq    t1, t1, t1              // shift high-dividend left
                    713:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    714: 
                    715:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    716:         addq    a0, t0, a0              //   then set quotient bit
                    717:         subq    t1, a1, t0              // subtract divisor from dividend,
                    718:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    719: 
                    720:         cmplt   a0, 0, t0               // predict low-dividend shift carry-out
                    721:         addq    a0, a0, a0              // shift low-dividend left
                    722:         addq    t1, t1, t1              // shift high-dividend left
                    723:         bis     t1, t0, t1              // merge in carry-out of low-dividend
                    724: 
                    725:         cmpule  a1, t1, t0              // if dividend >= divisor,
                    726:         addq    a0, t0, a0              //   then set quotient bit
                    727:         subq    t1, a1, t0              // subtract divisor from dividend,
                    728:         cmovlbs a0, t0, t1              //   if dividend >= divisor
                    729: 
                    730:         subq    t2, 1, t2               // any more iterations?
                    731:         bne     t2, 10b                 //
                    732: 
                    733: //
                    734: // Finished with remainder value in t1 and quotient value in a0.
                    735: //
                    736: 
                    737:         mov     a0, v0                  // set quadword quotient return value
                    738:         beq     a2, 20f                 // skip optional remainder store
                    739:         stq     t1, 0(a2)               // store quadword remainder
                    740: 
                    741: 20:     ret     zero, (ra)              // return
                    742: 
                    743: //
                    744: // Generate an exception for divide by zero.
                    745: //
                    746: 
                    747: 30:     ldil    a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
                    748: 
                    749:         GENERATE_TRAP
                    750: 
                    751:         br      zero, 30b               // in case they continue
                    752: 
                    753:         .end    LargeIntegerDivide
                    754: 
                    755:         SBTTL("Large Integer Negate")
                    756: //++
                    757: //
                    758: // LARGE_INTEGER
                    759: // LargeIntegerNegate (
                    760: //    IN LARGE_INTEGER Subtrahend
                    761: //    )
                    762: //
                    763: // Routine Description:
                    764: //
                    765: //    This function negates a signed large integer and returns the signed
                    766: //    large integer result.
                    767: //
                    768: //    N.B. An overflow is possible, but no exception is generated.
                    769: //
                    770: // Arguments:
                    771: //
                    772: //    Subtrahend (a0) - Supplies the subtrahend value.
                    773: //
                    774: // Return Value:
                    775: //
                    776: //    The large integer result is returned as the function value in v0.
                    777: //
                    778: //--
                    779: 
                    780:         LEAF_ENTRY(LargeIntegerNegate)
                    781: 
                    782:         subq    zero, a0, v0            // negate the quadword argument
                    783:         ret     zero, (ra)              // return
                    784: 
                    785:         .end    LargeIntegerNegate
                    786: 
                    787:         SBTTL("Large Integer Shift Left")
                    788: //++
                    789: //
                    790: // LARGE_INTEGER
                    791: // LargeIntegerShiftLeft (
                    792: //    IN LARGE_INTEGER LargeInteger,
                    793: //    IN CCHAR ShiftCount
                    794: //    )
                    795: //
                    796: // Routine Description:
                    797: //
                    798: //    This function shifts a signed large integer left by an unsigned integer
                    799: //    modulo 64 and returns the shifted signed large integer result.
                    800: //
                    801: // Arguments:
                    802: //
                    803: //    LargeInteger (a0) - Supplies the large integer to be shifted.
                    804: //
                    805: //    ShiftCount (a1) - Supplies the left shift count.
                    806: //
                    807: // Return Value:
                    808: //
                    809: //    The large integer result is returned as the function value in v0.
                    810: //
                    811: //--
                    812: 
                    813:         LEAF_ENTRY(LargeIntegerShiftLeft)
                    814: 
                    815:         sll     a0, a1, v0              // shift the quadword argument left
                    816:         ret     zero, (ra)              // return
                    817: 
                    818:         .end    LargeIntegerShiftLeft
                    819: 
                    820:         SBTTL("Large Integer Logical Shift Right")
                    821: //++
                    822: //
                    823: // LARGE_INTEGER
                    824: // LargeIntegerShiftRight (
                    825: //    IN LARGE_INTEGER LargeInteger,
                    826: //    IN CCHAR ShiftCount
                    827: //    )
                    828: //
                    829: // Routine Description:
                    830: //
                    831: //    This function shifts an unsigned large integer right by an unsigned
                    832: //    integer modulo 64 and returns the shifted unsigned large integer result.
                    833: //
                    834: // Arguments:
                    835: //
                    836: //    LargeInteger (a0) - Supplies the large integer to be shifted.
                    837: //
                    838: //    ShiftCount (a1) - Supplies the right shift count.
                    839: //
                    840: // Return Value:
                    841: //
                    842: //    The large integer result is returned as the function value in v0.
                    843: //
                    844: //--
                    845: 
                    846:         LEAF_ENTRY(LargeIntegerShiftRight)
                    847: 
                    848:         srl     a0, a1, v0              // shift the quadword right/logical
                    849:         ret     zero, (ra)              // return
                    850: 
                    851:         .end    LargeIntegerShiftRight
                    852: 
                    853:         SBTTL("Large Integer Subtract")
                    854: //++
                    855: //
                    856: // LARGE_INTEGER
                    857: // LargeIntegerSubtract (
                    858: //    IN LARGE_INTEGER Minuend,
                    859: //    IN LARGE_INTEGER Subtrahend
                    860: //    )
                    861: //
                    862: // Routine Description:
                    863: //
                    864: //    This function subtracts a signed large integer from a signed large
                    865: //    integer and returns the signed large integer result.
                    866: //
                    867: //    N.B. An overflow is possible, but no exception is generated.
                    868: //
                    869: // Arguments:
                    870: //
                    871: //    Minuend (a0) - Supplies the minuend value.
                    872: //
                    873: //    Subtrahend (a1) - Supplies the subtrahend value.
                    874: //
                    875: // Return Value:
                    876: //
                    877: //    The large integer result is returned as the function value in v0.
                    878: //
                    879: //--
                    880: 
                    881:         LEAF_ENTRY(LargeIntegerSubtract)
                    882: 
                    883:         subq    a0, a1, v0              // subtract the quadword arguments
                    884:         ret     zero, (ra)              // return
                    885: 
                    886:         .end    LargeIntegerSubtract

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.