Annotation of mstools/samples/largeint/mips/largeint.s, revision 1.1

1.1     ! root        1: //      TITLE("Large Integer Arithmetic")
        !             2: //++
        !             3: //
        !             4: // Module Name:
        !             5: //
        !             6: //    largeint.s
        !             7: //
        !             8: // Abstract:
        !             9: //
        !            10: //    This module implements routines for performing extended integer
        !            11: //    arithmtic.
        !            12: //
        !            13: // Environment:
        !            14: //
        !            15: //    Any mode.
        !            16: //
        !            17: // Revision History:
        !            18: //
        !            19: //--
        !            20: 
        !            21: #include "ksmips.h"
        !            22: 
        !            23:         SBTTL("Large Integer Add")
        !            24: //++
        !            25: //
        !            26: // LARGE_INTEGER
        !            27: // LargeIntegerAdd (
        !            28: //    IN LARGE_INTEGER Addend1,
        !            29: //    IN LARGE_INTEGER Addend2
        !            30: //    )
        !            31: //
        !            32: // Routine Description:
        !            33: //
        !            34: //    This function adds a signed large integer to a signed large integer and
        !            35: //    returns the signed large integer result.
        !            36: //
        !            37: // Arguments:
        !            38: //
        !            39: //    Addend1 (a2, a3) - Supplies the first addend value.
        !            40: //
        !            41: //    Addend2 (4 * 4(sp), 4 * 5(sp)) - Supplies the second addend value.
        !            42: //
        !            43: // Return Value:
        !            44: //
        !            45: //    The large integer result is stored at the address supplied by a0.
        !            46: //
        !            47: //--
        !            48: 
        !            49:         LEAF_ENTRY(LargeIntegerAdd)
        !            50: 
        !            51:         lw      t0,4 * 4(sp)            // get low part of addend2 value
        !            52:         lw      t1,4 * 5(sp)            // get high part of addend2 value
        !            53:         addu    t0,t0,a2                // add low parts of large integer
        !            54:         addu    t1,t1,a3                // add high parts of large integer
        !            55:         sltu    t2,t0,a2                // generate carry from low part
        !            56:         addu    t1,t1,t2                // add carry to high part
        !            57:         sw      t0,0(a0)                // store low part of result
        !            58:         sw      t1,4(a0)                // store high part of result
        !            59:         move    v0,a0                   // set function return register
        !            60:         j       ra                      // return
        !            61: 
        !            62:         .end    LargeIntegerAdd
        !            63: 
        !            64:         SBTTL("Convert Long to Large Integer")
        !            65: //++
        !            66: //
        !            67: // LARGE_INTEGER
        !            68: // ConvertLongToLargeInteger (
        !            69: //     IN LONG SignedInteger
        !            70: //     )
        !            71: //
        !            72: // Routine Description:
        !            73: //
        !            74: //     This function converts the a signed integer to a signed large integer
        !            75: //     and returns the result.
        !            76: //
        !            77: // Arguments:
        !            78: //
        !            79: //     SignedInteger (a1) - Supplies the value to convert.
        !            80: //
        !            81: // Return Value:
        !            82: //
        !            83: //     The large integer result is stored at the address supplied by a0.
        !            84: //
        !            85: //--
        !            86: 
        !            87:         LEAF_ENTRY(ConvertLongToLargeInteger)
        !            88: 
        !            89:         sra     a2,a1,31                // compute high part of result
        !            90:         sw      a1,0(a0)                // store low part of result
        !            91:         sw      a2,4(a0)                // store high part of result
        !            92:         move    v0,a0                   // set function return register
        !            93:         j       ra                      // return
        !            94: 
        !            95:         .end    ConvertLongToLargeInteger
        !            96: 
        !            97:         SBTTL("Convert Ulong to Large Integer")
        !            98: //++
        !            99: //
        !           100: // LARGE_INTEGER
        !           101: // ConvertUlongToLargeInteger (
        !           102: //     IN LONG UnsignedInteger
        !           103: //     )
        !           104: //
        !           105: // Routine Description:
        !           106: //
        !           107: //     This function converts the an unsigned integer to a signed large
        !           108: //     integer and returns the result.
        !           109: //
        !           110: // Arguments:
        !           111: //
        !           112: //     UnsignedInteger (a1) - Supplies the value to convert.
        !           113: //
        !           114: // Return Value:
        !           115: //
        !           116: //     The large integer result is stored at the address supplied by a0.
        !           117: //
        !           118: //--
        !           119: 
        !           120:         LEAF_ENTRY(ConvertUlongToLargeInteger)
        !           121: 
        !           122:         sw      a1,0(a0)                // store low part of result
        !           123:         sw      zero,4(a0)              // store high part of result
        !           124:         move    v0,a0                   // set function return register
        !           125:         j       ra                      // return
        !           126: 
        !           127:         .end    ConvertUlongToLargeInteger
        !           128: 
        !           129:         SBTTL("Enlarged Signed Integer Multiply")
        !           130: //++
        !           131: //
        !           132: // LARGE_INTEGER
        !           133: // EnlargedIntegerMultiply (
        !           134: //    IN LONG Multiplicand,
        !           135: //    IN LONG Multiplier
        !           136: //    )
        !           137: //
        !           138: // Routine Description:
        !           139: //
        !           140: //    This function multiplies a signed integer by an signed integer and
        !           141: //    returns a signed large integer result.
        !           142: //
        !           143: // Arguments:
        !           144: //
        !           145: //    Multiplicand (a1) - Supplies the multiplicand value.
        !           146: //
        !           147: //    Multiplier (a2) - Supplies the multiplier value.
        !           148: //
        !           149: // Return Value:
        !           150: //
        !           151: //    The large integer result is stored at the address supplied by a0.
        !           152: //
        !           153: //--
        !           154: 
        !           155:         LEAF_ENTRY(EnlargedIntegerMultiply)
        !           156: 
        !           157:         mult    a1,a2                  // multiply longword value
        !           158:         mflo    t0                     // get low 32-bits of result
        !           159:         mfhi    t1                     // get high 32-bits of result
        !           160:         sw      t0,0(a0)               // set low part of result
        !           161:         sw      t1,4(a0)               // set high part of result
        !           162:         move    v0,a0                  // set function return register
        !           163:         j       ra                     // return
        !           164: 
        !           165:         .end    EnlargedIntegerMultiply)
        !           166: 
        !           167:         SBTTL("Enlarged Unsigned Integer Multiply")
        !           168: //++
        !           169: //
        !           170: // LARGE_INTEGER
        !           171: // EnlargedUnsignedMultiply (
        !           172: //    IN ULONG Multiplicand,
        !           173: //    IN ULONG Multiplier
        !           174: //    )
        !           175: //
        !           176: // Routine Description:
        !           177: //
        !           178: //    This function multiplies an unsigned integer by an unsigned integer
        !           179: //    and returns a signed large integer result.
        !           180: //
        !           181: // Arguments:
        !           182: //
        !           183: //    Multiplicand (a1) - Supplies the multiplicand value.
        !           184: //
        !           185: //    Multiplier (a2) - Supplies the multiplier value.
        !           186: //
        !           187: // Return Value:
        !           188: //
        !           189: //    The large integer result is stored at the address supplied by a0.
        !           190: //
        !           191: //--
        !           192: 
        !           193:         LEAF_ENTRY(EnlargedUnsignedMultiply)
        !           194: 
        !           195:         multu   a1,a2                  // multiply longword value
        !           196:         mflo    t0                     // get low 32-bits of result
        !           197:         mfhi    t1                     // get high 32-bits of result
        !           198:         sw      t0,0(a0)               // set low part of result
        !           199:         sw      t1,4(a0)               // set high part of result
        !           200:         move    v0,a0                  // set function return register
        !           201:         j       ra                     // return
        !           202: 
        !           203:         .end    EnlargedUnsignedMultiply)
        !           204: 
        !           205:         SBTTL("Enlarged Unsigned Divide")
        !           206: //++
        !           207: //
        !           208: // ULONG
        !           209: // EnlargedUnsignedDivide (
        !           210: //    IN ULARGE_INTEGER Dividend,
        !           211: //    IN ULONG Divisor,
        !           212: //    IN PULONG Remainder.
        !           213: //    )
        !           214: //
        !           215: // Routine Description:
        !           216: //
        !           217: //    This function divides an unsigned large integer by an unsigned long
        !           218: //    and returns the resultant quotient and optionally the remainder.
        !           219: //
        !           220: //    N.B. It is assumed that no overflow will occur.
        !           221: //
        !           222: // Arguments:
        !           223: //
        !           224: //    Dividend (a0, a1) - Supplies the dividend value.
        !           225: //
        !           226: //    Divisor (a2) - Supplies the divisor value.
        !           227: //
        !           228: //    Remainder (a3) - Supplies an optional pointer to a variable that
        !           229: //        receives the remainder.
        !           230: //
        !           231: // Return Value:
        !           232: //
        !           233: //    The unsigned long integer quotient is returned as the function value.
        !           234: //
        !           235: //--
        !           236: 
        !           237:         LEAF_ENTRY(EnlargedUnsignedDivide)
        !           238: 
        !           239:         .set    noreorder
        !           240:         .set    noat
        !           241:         beq     zero,a2,20f             // if eq, attempted division by zero
        !           242:         sltu    v1,a1,a2                // check if overflow will occur
        !           243:         beq     zero,v1,30f             // if eq, overflow will occur
        !           244:         li      t1,31                   // set loop count
        !           245: 10:     sra     t2,a1,31                // replicate partial remainder high bit
        !           246:         sll     a1,a1,1                 // shift next dividend bit
        !           247:         srl     t0,a0,31                // into the partial remainder
        !           248:         or      a1,a1,t0                //
        !           249:         sltu    t0,a1,a2                // check if partial remainder less
        !           250:         subu    t0,t0,1                 // convert to 0 or -1
        !           251:         or      t0,t0,t2                // merge with partial remainder high bit
        !           252:         and     t3,t0,a2                // select divisor or zero
        !           253:         sll     a0,a0,1                 // left shift quotient
        !           254:         subu    a0,a0,t0                // merge quotient bit
        !           255:         subu    a1,a1,t3                // subtract out divisor
        !           256:         bne     zero,t1,10b             // if ne, more iterations to go
        !           257:         subu    t1,t1,1                 // decrement iteration count
        !           258:         beq     zero,a3,40f             // if eq, remainder not requested
        !           259:         move    v0,a0                   // set quotient value
        !           260:         j       ra                      // return
        !           261:         sw      a1,0(a3)                // store longword remainder
        !           262:         .set    at
        !           263:         .set    reorder
        !           264: 
        !           265: 20:     break   DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
        !           266:         j       ra                      //
        !           267: 
        !           268: 30:     break   DIVIDE_OVERFLOW_BREAKPOINT // division value overflows result
        !           269: 40:     j       ra                      //
        !           270: 
        !           271:         .end    EnlargedUnsignedDivide
        !           272: 
        !           273:         SBTTL("Extended Large Integer Divide")
        !           274: //++
        !           275: //
        !           276: // LARGE_INTEGER
        !           277: // ExtendedLargeIntegerDivide (
        !           278: //    IN LARGE_INTEGER Dividend,
        !           279: //    IN ULONG Divisor,
        !           280: //    IN PULONG Remainder.
        !           281: //    )
        !           282: //
        !           283: // Routine Description:
        !           284: //
        !           285: //    This function divides an unsigned large integer by an unsigned long
        !           286: //    and returns the resultant quotient and optionally the remainder.
        !           287: //
        !           288: // Arguments:
        !           289: //
        !           290: //    Dividend (a2, a3) - Supplies the dividend value.
        !           291: //
        !           292: //    Divisor (4 * 4(sp)) - Supplies the divisor value.
        !           293: //
        !           294: //    Remainder (4 * 5(sp)- Supplies an optional pointer to a variable
        !           295: //      that receives the remainder.
        !           296: //
        !           297: // Return Value:
        !           298: //
        !           299: //    The large integer result is stored at the address supplied by a0.
        !           300: //
        !           301: //--
        !           302: 
        !           303:         LEAF_ENTRY(ExtendedLargeIntegerDivide)
        !           304: 
        !           305:         .set    noreorder
        !           306:         .set    noat
        !           307:         move    v0,a0                   // set function return register
        !           308:         lw      a1,4 * 4(sp)            // get divisor value
        !           309:         lw      t0,4 * 5(sp)            // get address to store remainder
        !           310:         beq     zero,a1,30f             // if eq, attempted division by zero
        !           311:         li      t1,63                   // set loop count
        !           312:         move    t2,zero                 // clear partial remainder
        !           313: 10:     sra     t3,t2,31                // replicate partial remainder high bit
        !           314:         sll     t2,t2,1                 // shift next dividend bit
        !           315:         srl     t4,a3,31                // into the partial remainder
        !           316:         or      t2,t2,t4                //
        !           317:         sll     a3,a3,1                 // double left shift dividend
        !           318:         srl     t4,a2,31                //
        !           319:         or      a3,a3,t4                //
        !           320:         sltu    t4,t2,a1                // check if partial remainder less
        !           321:         subu    t4,t4,1                 // convert to 0 or -1
        !           322:         or      t4,t4,t3                // merge with partial remainder high bit
        !           323:         and     t5,t4,a1                // select divisor or 0
        !           324:         sll     a2,a2,1                 //
        !           325:         subu    a2,a2,t4                // merge quotient bit
        !           326:         subu    t2,t2,t5                // subtract out divisor
        !           327:         bne     zero,t1,10b             // if ne, more iterations to go
        !           328:         subu    t1,t1,1                 // decrement iteration count
        !           329:         beq     zero,t0,20f             // if eq, remainder not requested
        !           330:         sw      a2,0(a0)                // store low part of quotient
        !           331:         sw      t2,0(t0)                // store longword remainder
        !           332: 20:     j       ra                      // return
        !           333:         sw      a3,4(a0)                // store high part of quotient
        !           334:         .set    at
        !           335:         .set    reorder
        !           336: 
        !           337: 30:     break   DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
        !           338:         j       ra                      //
        !           339: 
        !           340:         .end    ExtendedLargeIntegerDivide
        !           341: 
        !           342:         SBTTL("Extended Magic Divide")
        !           343: //++
        !           344: //
        !           345: // LARGE_INTEGER
        !           346: // ExtendedMagicDivide (
        !           347: //    IN LARGE_INTEGER Dividend,
        !           348: //    IN LARGE_INTEGER MagicDivisor,
        !           349: //    IN CCHAR ShiftCount
        !           350: //    )
        !           351: //
        !           352: // Routine Description:
        !           353: //
        !           354: //    This function divides a signed large integer by an unsigned large integer
        !           355: //    and returns the signed large integer result. The division is performed
        !           356: //    using reciprocal multiplication of a signed large integer value by an
        !           357: //    unsigned large integer fraction which represents the most significant
        !           358: //    64-bits of the reciprocal divisor rounded up in its least significant bit
        !           359: //    and normalized with respect to bit 63. A shift count is also provided
        !           360: //    which is used to truncate the fractional bits from the result value.
        !           361: //
        !           362: // Arguments:
        !           363: //
        !           364: //    Dividend (a2, a3) - Supplies the dividend value.
        !           365: //
        !           366: //    MagicDivisor (4 * 4(sp), 4 * 5(sp)) - Supplies the magic divisor value
        !           367: //       which is a 64-bit multiplicative reciprocal.
        !           368: //
        !           369: //    Shiftcount (4 * 6(sp)) - Supplies the right shift adjustment value.
        !           370: //
        !           371: // Return Value:
        !           372: //
        !           373: //    The large integer result is stored at the address supplied by a0.
        !           374: //
        !           375: //--
        !           376: 
        !           377:         LEAF_ENTRY(ExtendedMagicDivide)
        !           378: 
        !           379:         move    t0,a2                   // assume dividend is positive
        !           380:         move    t1,a3                   //
        !           381:         bgez    a3,10f                  // if gez, positive dividend
        !           382:         subu    t0,zero,t0              // negate low part of dividend
        !           383:         subu    t1,zero,t1              // negate high part of dividend
        !           384:         sltu    t2,zero,t0              // set borrow from high part
        !           385:         subu    t1,t1,t2                // subtract out out borrow
        !           386: 10:     lw      a1,4 * 4(sp)            // get low part of magic dividor
        !           387:         lw      t2,4 * 5(sp)            // get high part of magic divisor
        !           388:         lbu     v0,4 * 6(sp)            // get shift count
        !           389: 
        !           390: //
        !           391: // Compute low 32-bits of dividend times low 32-bits of divisor.
        !           392: //
        !           393: 
        !           394:         multu   t0,a1                   //
        !           395:         mfhi    t3                      // save high 32-bits of product
        !           396: 
        !           397: //
        !           398: // Compute low 32-bits of dividend time high 32-bits of divisor.
        !           399: //
        !           400: 
        !           401:         multu   t0,t2                   //
        !           402:         mflo    t4                      // save low 32-bits of product
        !           403:         mfhi    t5                      // save high 32-bits of product
        !           404: 
        !           405: //
        !           406: // Compute high 32-bits of dividend times low 32-bits of divisor.
        !           407: //
        !           408: 
        !           409:         multu   t1,a1                   //
        !           410:         mflo    t6                      // save loow 32-bits of product
        !           411:         mfhi    t7                      // save high 32-bits of product
        !           412: 
        !           413: //
        !           414: // Compute high 32-bits of dividend times high 32-bits of divisor.
        !           415: //
        !           416: 
        !           417:         multu   t1,t2                   //
        !           418:         mflo    t8                      // save low 32-bits of product
        !           419:         mfhi    t9                      // save high 32-bits of product
        !           420: 
        !           421: //
        !           422: // Add partial results to form high 64-bits of result.
        !           423: //
        !           424: 
        !           425:         addu    t0,t3,t4                //
        !           426:         sltu    t1,t0,t4                // generate carry
        !           427:         addu    t0,t0,t6                //
        !           428:         sltu    t2,t0,t6                // generate carry
        !           429:         addu    t2,t1,t2                // combine carries
        !           430:         addu    t1,t2,t5                //
        !           431:         sltu    t2,t1,t5                // generate carry
        !           432:         addu    t1,t1,t7                //
        !           433:         sltu    t3,t1,t7                // generate carry
        !           434:         addu    t2,t2,t3                // combine carries
        !           435:         addu    t1,t1,t8                //
        !           436:         sltu    t3,t1,t8                // generate carry
        !           437:         addu    t2,t2,t3                // combine carries
        !           438:         addu    t2,t2,t9                //
        !           439: 
        !           440: //
        !           441: // Right shift the result by the specified shift count and negate result
        !           442: // if necessary.
        !           443: //
        !           444: 
        !           445:         li      v1,32                   // compute left shift count
        !           446:         subu    v1,v1,v0                //
        !           447:         bgtz    v1,20f                  // if gtz, shift less that 32-bits
        !           448: 
        !           449: //
        !           450: // Shift count is greater than or equal 32 bits - high half of result is zero,
        !           451: // low half is the high half shifted right by remaining count.
        !           452: //
        !           453: 
        !           454:         move    t1,zero                 // set high half of result
        !           455:         srl     t0,t2,v0                // set low half of result
        !           456:         b       30f                     //
        !           457: 
        !           458: //
        !           459: // Shift count is less than 32-bits - high half of result is the high half
        !           460: // of product shifted right by count, low half of result is the shifted out
        !           461: // bits of the high half combined with the rigth shifted low half of the
        !           462: // product.
        !           463: //
        !           464: 
        !           465: 20:     srl     t0,t1,v0                // shift low half right count bits
        !           466:         srl     t1,t2,v0                // shift high half right count bits
        !           467:         beq     zero,v0,30f             // if eq, no more shifts necessary
        !           468:         sll     t2,t2,v1                // isolate shifted out bits of high half
        !           469:         or      t0,t0,t2                // combine bits for low half of result
        !           470: 
        !           471: //
        !           472: // Negate result if neccessary.
        !           473: //
        !           474: 
        !           475: 30:     bgez    a3,40f                  // if gez, positive result
        !           476:         subu    t0,zero,t0              // negate low half of result
        !           477:         subu    t1,zero,t1              // negate high half of result
        !           478:         beq     zero,t0,40f             // if eq, negation complete
        !           479:         subu    t1,t1,1                 // convert high part to ones complement
        !           480: 40:     sw      t0,0(a0)                // store low half of result
        !           481:         sw      t1,4(a0)                // store high half of result
        !           482:         move    v0,a0                   // set function return register
        !           483:         j       ra                      // return
        !           484: 
        !           485:         .end    ExtendedMagicDivide
        !           486: 
        !           487:         SBTTL("Large Integer Divide")
        !           488: //++
        !           489: //
        !           490: // LARGE_INTEGER
        !           491: // LargeIntegerDivide (
        !           492: //    IN LARGE_INTEGER Dividend,
        !           493: //    IN LARGE_INTEGER Divisor,
        !           494: //    IN PLARGE_INTEGER Remainder.
        !           495: //    )
        !           496: //
        !           497: // Routine Description:
        !           498: //
        !           499: //    This function divides an unsigned large integer by an unsigned
        !           500: //    large and returns the resultant quotient and optionally the remainder.
        !           501: //
        !           502: // Arguments:
        !           503: //
        !           504: //    Dividend (a2, a3) - Supplies the dividend value.
        !           505: //
        !           506: //    Divisor (4 * 4(sp), 4 * 5(sp)) - Supplies the divisor value.
        !           507: //
        !           508: //    Remainder (4 * 6(sp)- Supplies an optional pointer to a variable
        !           509: //      that receives the remainder.
        !           510: //
        !           511: // Return Value:
        !           512: //
        !           513: //    The large integer result is stored at the address supplied by a0.
        !           514: //
        !           515: //--
        !           516: 
        !           517:         LEAF_ENTRY(LargeIntegerDivide)
        !           518: 
        !           519:         .set    noreorder
        !           520:         .set    noat
        !           521:         move    v0,a0                   // set function return register
        !           522:         lw      a1,4 * 4(sp)            // get low part of divisor
        !           523:         lw      t0,4 * 5(sp)            // get high part of divisor
        !           524:         lw      t1,4 * 6(sp)            // get address to store remainder
        !           525:         or      v1,t0,a1                // combine low and high parts
        !           526:         beq     zero,v1,60f             // if eq, attempted division by zero
        !           527:         li      t2,63                   // set loop count
        !           528:         move    t3,zero                 // clear partial remainder
        !           529:         move    t4,zero                 //
        !           530: 10:     sll     t4,t4,1                 // shift next dividend bit
        !           531:         srl     t5,t3,31                // into the partial remainder
        !           532:         or      t4,t4,t5                //
        !           533:         sll     t3,t3,1                 //
        !           534:         srl     t5,a3,31                //
        !           535:         or      t3,t3,t5                //
        !           536:         sll     a3,a3,1                 // double left shift dividend
        !           537:         srl     t5,a2,31                //
        !           538:         or      a3,a3,t5                //
        !           539:         sltu    t5,t4,t0                // check if partial remainder less
        !           540:         beq     zero,t5,20f             // if eq, partial remainder not less
        !           541:         sll     a2,a2,1                 //
        !           542:         bne     zero,t2,10b             // if ne, more iterations to go
        !           543:         subu    t2,t2,1                 // decrement iteration count
        !           544:         beq     zero,t1,50f             // if eq, remainder not requested
        !           545:         sw      a2,0(a0)                // store low part of quotient
        !           546:         sw      t3,0(t1)                // store large integer remainder
        !           547:         sw      t4,4(t1)                //
        !           548:         j       ra                      // return
        !           549:         sw      a3,4(a0)                // store high part of quotient
        !           550: 
        !           551: 20:     bne     t0,t4,30f               // if ne, partial remainder greater
        !           552:         sltu    t5,t3,a1                // check is partial remainder less
        !           553:         bne     zero,t5,40f             // if ne, partial remainder less
        !           554:         nop                             //
        !           555: 30:     or      a2,a2,1                 // merge quotient bit
        !           556:         subu    t4,t4,t0                // subtract out divisor high part
        !           557:         sltu    t5,t3,a1                // set borrow from high part
        !           558:         subu    t4,t4,t5                // subtract borrow from high part
        !           559:         subu    t3,t3,a1                // subtract out divisor low
        !           560: 40:     bne     zero,t2,10b             // if ne, more iterations to go
        !           561:         subu    t2,t2,1                 // decrement iteration count
        !           562:         beq     zero,t1,50f             // if eq, remainder not requested
        !           563:         sw      a2,0(a0)                // store low part of quotient
        !           564:         sw      t3,0(t1)                // store large integer remainder
        !           565:         sw      t4,4(t1)                //
        !           566: 50:     j       ra                      // return
        !           567:         sw      a3,4(a0)                // store high part of quotient
        !           568:         .set    at
        !           569:         .set    reorder
        !           570: 
        !           571: 60:     break   DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
        !           572:         j       ra                      //
        !           573: 
        !           574:         .end    LargeIntegerDivide
        !           575: 
        !           576:         SBTTL("Extended Integer Multiply")
        !           577: //++
        !           578: //
        !           579: // LARGE_INTEGER
        !           580: // ExtendedIntegerMultiply (
        !           581: //    IN LARGE_INTEGER Multiplicand,
        !           582: //    IN ULONG Multiplier
        !           583: //    )
        !           584: //
        !           585: // Routine Description:
        !           586: //
        !           587: //    This function multiplies a signed large integer by a signed integer and
        !           588: //    returns the signed large integer result.
        !           589: //
        !           590: // Arguments:
        !           591: //
        !           592: //    Multiplicand (a2, a3) - Supplies the multiplicand value.
        !           593: //
        !           594: //    Multiplier (4 * 4(sp)) - Supplies the multiplier value.
        !           595: //
        !           596: // Return Value:
        !           597: //
        !           598: //    The large integer result is stored at the address supplied by a0.
        !           599: //
        !           600: //--
        !           601: 
        !           602:         LEAF_ENTRY(ExtendedIntegerMultiply)
        !           603: 
        !           604:         lw      a1,4 * 4(sp)            // get multiplier value
        !           605:         xor     t9,a1,a3                // compute sign of result
        !           606:         move    t0,a1                   // assume multiplier positive
        !           607:         bgez    a1,10f                  // if gez, positive multiplier
        !           608:         subu    t0,zero,t0              // negate multiplier
        !           609: 10:     move    t1,a2                   // assume multiplicand positive
        !           610:         move    t2,a3                   //
        !           611:         bgez    a3,20f                  // if gez, positive multiplicand
        !           612:         subu    t1,zero,t1              // negate multiplicand
        !           613:         subu    t2,zero,t2              //
        !           614:         sltu    t3,zero,t1              // compute borrow from high part
        !           615:         subu    t2,t2,t3                // subtract out borrow
        !           616: 
        !           617: //
        !           618: // Compute low 32-bits of multiplier times the low 32-bit of multiplicand.
        !           619: //
        !           620: 
        !           621: 20:     multu   t0,t1                   //
        !           622:         mflo    t4                      // save low 32-bits of product
        !           623:         mfhi    t5                      // save high 32-bits of product
        !           624: 
        !           625: //
        !           626: // Compute low 32-bits of multiplier times the high 32-bits of multiplicand.
        !           627: //
        !           628: 
        !           629:         multu   t0,t2                   //
        !           630:         mflo    t6                      // save low 32-bits of product
        !           631:         mfhi    t7                      // save high 32-bits of product
        !           632: 
        !           633: //
        !           634: // Add partial results to form high 64-bits of result.
        !           635: //
        !           636: 
        !           637:         addu    t5,t5,t6                //
        !           638:         sltu    t3,t5,t6                // generate carry
        !           639:         addu    t6,t3,t7                //
        !           640: 
        !           641: //
        !           642: // Negate result if neccessary.
        !           643: //
        !           644: 
        !           645:         bgez    t9,40f                  // if gez, positive result
        !           646:         subu    t4,zero,t4              // negate low half of result
        !           647:         subu    t5,zero,t5              // negate high half of result
        !           648:         subu    t6,zero,t6              // negate extended part of result
        !           649:         beq     zero,t4,30f             // if eq, negation complete
        !           650:         subu    t5,t5,1                 // convert high part to ones complement
        !           651:         subu    t6,t6,1                 // convert extended part to ones complement
        !           652:         b       40f                     //
        !           653: 
        !           654: 30:     beq     zero,t5,40f             // if eq, negation complete
        !           655:         subu    t6,t6,1                 // convert extended part to ones complement
        !           656: 
        !           657: //
        !           658: // Check for result overflow.
        !           659: //
        !           660: 
        !           661: 40:     sra     t0,t5,31                // compute sign of high part
        !           662:         beq     t0,t6,50f               // if eq, no overflow
        !           663:         lui     t0,0x8000               // get largest negative number
        !           664:         add     t0,t0,t0                // cause overflow exception
        !           665: 50:     sw      t4,0(a0)                // store low half of result
        !           666:         sw      t5,4(a0)                // store high half of result
        !           667:         move    v0,a0                   // set function return register
        !           668:         j       ra                      // return
        !           669: 
        !           670:         .end    ExtendedIntegerMultiply
        !           671: 
        !           672:         SBTTL("Large Integer Negate")
        !           673: //++
        !           674: //
        !           675: // LARGE_INTEGER
        !           676: // LargeIntegerNegate (
        !           677: //    IN LARGE_INTEGER Subtrahend
        !           678: //    )
        !           679: //
        !           680: // Routine Description:
        !           681: //
        !           682: //    This function negates a signed large integer and returns the signed
        !           683: //    large integer result.
        !           684: //
        !           685: // Arguments:
        !           686: //
        !           687: //    Subtrahend (a2, a3) - Supplies the subtrahend value.
        !           688: //
        !           689: // Return Value:
        !           690: //
        !           691: //    The large integer result is stored at the address supplied by a0.
        !           692: //
        !           693: //--
        !           694: 
        !           695:         LEAF_ENTRY(LargeIntegerNegate)
        !           696: 
        !           697:         subu    a2,zero,a2              // negate low part of subtrahend
        !           698:         subu    a3,zero,a3              // negate high part of subtrahend
        !           699:         sltu    t0,zero,a2              // compute borrow from high part
        !           700:         subu    a3,a3,t0                // subtract borrow from high part
        !           701:         sw      a2,0(a0)                // store low part of result
        !           702:         sw      a3,4(a0)                // store high part of result
        !           703:         move    v0,a0                   // set function return register
        !           704:         j       ra                      // return
        !           705: 
        !           706:         .end    LargeIntegerNegate
        !           707: 
        !           708:         SBTTL("Large Integer Subtract")
        !           709: //++
        !           710: //
        !           711: // LARGE_INTEGER
        !           712: // LargeIntegerSubtract (
        !           713: //    IN LARGE_INTEGER Minuend,
        !           714: //    IN LARGE_INTEGER Subtrahend
        !           715: //    )
        !           716: //
        !           717: // Routine Description:
        !           718: //
        !           719: //    This function subtracts a signed large integer from a signed large
        !           720: //    integer and returns the signed large integer result.
        !           721: //
        !           722: // Arguments:
        !           723: //
        !           724: //    Minuend (a2, a3) - Supplies the minuend value.
        !           725: //
        !           726: //    Subtrahend (4 * 4(sp), 4 * 5(sp)) - Supplies the subtrahend value.
        !           727: //
        !           728: // Return Value:
        !           729: //
        !           730: //    The large integer result is stored at the address supplied by a0.
        !           731: //
        !           732: //--
        !           733: 
        !           734:         LEAF_ENTRY(LargeIntegerSubtract)
        !           735: 
        !           736:         lw      a1,4 * 4(sp)            // get low part of subtrahend
        !           737:         lw      t2,4 * 5(sp)            // get high part of subtrahend
        !           738:         subu    t0,a2,a1                // subtract low parts
        !           739:         subu    t1,a3,t2                // subtract high parts
        !           740:         sltu    t3,a2,a1                // generate borrow from high part
        !           741:         subu    t1,t1,t3                // subtract borrow
        !           742:         sw      t0,0(a0)                // store low part of result
        !           743:         sw      t1,4(a0)                // store high part of result
        !           744:         move    v0,a0                   // set function return register
        !           745:         j       ra                      // return
        !           746: 
        !           747:         .end    LargeIntegerSubtract
        !           748: 
        !           749:         SBTTL("Large Integer Shift Left")
        !           750: //++
        !           751: //
        !           752: // LARGE_INTEGER
        !           753: // LargeIntegerShiftLeft (
        !           754: //    IN LARGE_INTEGER LargeInteger,
        !           755: //    IN CCHAR ShiftCount
        !           756: //    )
        !           757: //
        !           758: // Routine Description:
        !           759: //
        !           760: //    This function shifts a signed large integer left by an unsigned
        !           761: //    integer modulo 64 and returns the shifted signed large integer
        !           762: //    result.
        !           763: //
        !           764: //    N.B. No test is made for significant bits shifted out of the result.
        !           765: //
        !           766: // Arguments:
        !           767: //
        !           768: //    LargeInteger (a2, a3) - Supplies the large integer to be shifted.
        !           769: //
        !           770: //    ShiftCount (4 * 4(sp)) - Supplies the left shift count.
        !           771: //
        !           772: // Return Value:
        !           773: //
        !           774: //    The large integer result is stored at the address supplied by a0.
        !           775: //
        !           776: //--
        !           777: 
        !           778:         LEAF_ENTRY(LargeIntegerShiftLeft)
        !           779: 
        !           780:         lw      a1,4 * 4(sp)            // get shift count
        !           781:         move    v0,a0                   // set function return register
        !           782:         and     a1,a1,0x3f              // truncate shift count mod 64
        !           783: 
        !           784: //
        !           785: // Left shift the operand by the specified shift count.
        !           786: //
        !           787: 
        !           788:         li      v1,32                   // compute right shift count
        !           789:         subu    v1,v1,a1                //
        !           790:         bgtz    v1,10f                  // if gtz, shift less that 32-bits
        !           791: 
        !           792: //
        !           793: // Shift count is greater than or equal 32 bits - low half of result is zero,
        !           794: // high half is the low half shifted left by remaining count.
        !           795: //
        !           796: 
        !           797:         sll     a3,a2,a1                // set high half of result
        !           798:         sw      zero,0(a0)              // store low part of reuslt
        !           799:         sw      a3,4(a0)                // store high part of result
        !           800:         j       ra                      // return
        !           801: 
        !           802: //
        !           803: // Shift count is less than 32-bits - high half of result is the high half
        !           804: // of operand shifted left by count combined with the low half of the operand
        !           805: // shifted right, low half of result is the low half shifted left.
        !           806: //
        !           807: 
        !           808: 10:     sll     a3,a3,a1                // shift high half left count bits
        !           809:         beq     zero,a1,20f             // if eq, no more shifts necessary
        !           810:         srl     t0,a2,v1                // isolate shifted out bits of low half
        !           811:         sll     a2,a2,a1                // shift low half left count bits
        !           812:         or      a3,a3,t0                // combine bits for high half of result
        !           813: 20:     sw      a2,0(a0)                // store low part of reuslt
        !           814:         sw      a3,4(a0)                // store high part of result
        !           815:         j       ra                      // return
        !           816: 
        !           817:         .end    LargeIntegerShiftLeft
        !           818: 
        !           819:         SBTTL("Large Integer Logical Shift Right")
        !           820: //++
        !           821: //
        !           822: // LARGE_INTEGER
        !           823: // LargeIntegerShiftRight (
        !           824: //    IN LARGE_INTEGER LargeInteger,
        !           825: //    IN CCHAR ShiftCount
        !           826: //    )
        !           827: //
        !           828: // Routine Description:
        !           829: //
        !           830: //    This function shifts an unsigned large integer right by an unsigned
        !           831: //    integer modulo 64 and returns the shifted unsigned large integer
        !           832: //    result.
        !           833: //
        !           834: // Arguments:
        !           835: //
        !           836: //    LargeInteger (a2, a3) - Supplies the large integer to be shifted.
        !           837: //
        !           838: //    ShiftCount (4 * 4(sp)) - Supplies the right shift count.
        !           839: //
        !           840: // Return Value:
        !           841: //
        !           842: //    The large integer result is stored at the address supplied by a0.
        !           843: //
        !           844: //--
        !           845: 
        !           846:         LEAF_ENTRY(LargeIntegerShiftRight)
        !           847: 
        !           848:         lw      a1,4 * 4(sp)            // get shift count
        !           849:         move    v0,a0                   // set function return register
        !           850:         and     a1,a1,0x3f              // truncate shift count mod 64
        !           851: 
        !           852: //
        !           853: // Right shift the operand by the specified shift count.
        !           854: //
        !           855: 
        !           856:         li      v1,32                   // compute left shift count
        !           857:         subu    v1,v1,a1                //
        !           858:         bgtz    v1,10f                  // if gtz, shift less that 32-bits
        !           859: 
        !           860: //
        !           861: // Shift count is greater than or equal 32 bits - high half of result is
        !           862: // zero, low half is the high half shifted right by remaining count.
        !           863: //
        !           864: 
        !           865:         srl     a2,a3,a1                // set low half of result
        !           866:         sw      a2,0(a0)                // store low part of reuslt
        !           867:         sw      zero,4(a0)              // store high part of result
        !           868:         j       ra                      // return
        !           869: 
        !           870: //
        !           871: // Shift count is less than 32-bits - high half of result is the high half
        !           872: // of operand shifted right by count, low half of result is the shifted out
        !           873: // bits of the high half combined with the right shifted low half of the
        !           874: // operand.
        !           875: //
        !           876: 
        !           877: 10:     srl     a2,a2,a1                // shift low half right count bits
        !           878:         beq     zero,a1,20f             // if eq, no more shifts necessary
        !           879:         sll     t0,a3,v1                // isolate shifted out bits of high half
        !           880:         srl     a3,a3,a1                // shift high half right count bits
        !           881:         or      a2,a2,t0                // combine bits for low half of result
        !           882: 20:     sw      a2,0(a0)                // store low part of reuslt
        !           883:         sw      a3,4(a0)                // store high part of result
        !           884:         j       ra                      // return
        !           885: 
        !           886:         .end    LargeIntegerShiftRight
        !           887: 
        !           888:         SBTTL("Large Integer Arithmetic Shift Right")
        !           889: //++
        !           890: //
        !           891: // LARGE_INTEGER
        !           892: // LargeIntegerArithmeticShift (
        !           893: //    IN LARGE_INTEGER LargeInteger,
        !           894: //    IN CCHAR ShiftCount
        !           895: //    )
        !           896: //
        !           897: // Routine Description:
        !           898: //
        !           899: //    This function shifts a signed large integer right by an unsigned
        !           900: //    integer modulo 64 and returns the shifted signed large integer
        !           901: //    result.
        !           902: //
        !           903: // Arguments:
        !           904: //
        !           905: //    LargeInteger (a1, a2) - Supplies the large integer to be shifted.
        !           906: //
        !           907: //    ShiftCount (a3) - Supplies the right shift count.
        !           908: //
        !           909: // Return Value:
        !           910: //
        !           911: //    The large integer result is stored at the address supplied by a0.
        !           912: //
        !           913: //--
        !           914: 
        !           915:         LEAF_ENTRY(LargeIntegerArithmeticShift)
        !           916: 
        !           917:         lw      a1,4 * 4(sp)            // get shift count
        !           918:         move    v0,a0                   // set function return register
        !           919:         and     a1,a1,0x3f              // truncate shift count mod 64
        !           920: 
        !           921: //
        !           922: // Right shift the operand by the specified shift count.
        !           923: //
        !           924: 
        !           925:         li      v1,32                   // compute left shift count
        !           926:         subu    v1,v1,a1                //
        !           927:         bgtz    v1,10f                  // if gtz, shift less that 32-bits
        !           928: 
        !           929: //
        !           930: // Shift count is greater than or equal 32 bits - high half of result is
        !           931: // zero, low half is the high half shifted right by remaining count.
        !           932: //
        !           933: 
        !           934:         sra     a2,a3,a1                // set low half of result
        !           935:         sra     a3,a3,31                // set high half of result
        !           936:         sw      a2,0(a0)                // store low part of reuslt
        !           937:         sw      a3,4(a0)                // store high part of result
        !           938:         j       ra                      // return
        !           939: 
        !           940: //
        !           941: // Shift count is less than 32-bits - high half of result is the high half
        !           942: // of operand shifted right by count, low half of result is the shifted out
        !           943: // bits of the high half combined with the right shifted low half of the
        !           944: // operand.
        !           945: //
        !           946: 
        !           947: 10:     srl     a2,a2,a1                // shift low half right count bits
        !           948:         beq     zero,a1,20f             // if eq, no more shifts necessary
        !           949:         sll     t0,a3,v1                // isolate shifted out bits of high half
        !           950:         sra     a3,a3,a1                // shift high half right count bits
        !           951:         or      a2,a2,t0                // combine bits for low half of result
        !           952: 20:     sw      a2,0(a0)                // store low part of reuslt
        !           953:         sw      a3,4(a0)                // store high part of result
        !           954:         j       ra                      // return
        !           955: 
        !           956:         .end    LargeIntegerArithmeticShift

unix.superglobalmegacorp.com

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