|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.