Annotation of mstools/samples/largeint/alpha/largeint.s, revision 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.