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