|
|
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.