|
|
1.1 root 1: // TITLE("Large Integer Arithmetic")
2: //++
3: //
4: // Copyright (c) 1990 Microsoft Corporation
5: // Copyright (c) 1993 Digital Equipment Corporation
6: //
7: // Module Name:
8: //
9: // largeint.s
10: //
11: // Abstract:
12: //
13: // This module implements routines for performing extended integer
14: // arithmetic.
15: //
16: // Author:
17: //
18: // David N. Cutler (davec) 18-Apr-1990
19: //
20: // Environment:
21: //
22: // Any mode.
23: //
24: // Revision History:
25: //
26: // Thomas Van Baak (tvb) 9-May-1992
27: //
28: // Adapted for Alpha AXP.
29: //
30: //--
31:
32: #include "ksalpha.h"
33:
34: //
35: // Alpha AXP Implementation Notes:
36: //
37: // The LargeInteger functions defined below implement a set of portable
38: // 64-bit integer arithmetic operations for x86, Mips, and Alpha systems
39: // using the LARGE_INTEGER data type. Code using LARGE_INTEGER variables
40: // and calling these functions will be portable across all NT platforms.
41: // This is the recommended approach to 64-bit arithmetic on NT.
42: //
43: // However, if performance is more important than portability, then for
44: // Alpha systems, the native 64-bit integer data types may be used instead
45: // of the LARGE_INTEGER type and the LargeInteger functions. The Alpha C
46: // compilers support a __int64 data type (renamed LONGLONG in the system
47: // header files). All C integer arithmetic operators may be used with
48: // these quadword types. This eliminates the need for, and the overhead
49: // of, any of the portable LargeInteger functions.
50: //
51: // In general, a LARGE_INTEGER cannot simply be converted to a LONGLONG
52: // because of explicit references in application code to the 32-bit LowPart
53: // and HighPart members of the LARGE_INTEGER structure.
54: //
55: // The performance difference between using the portable LARGE_INTEGER
56: // types with LargeInteger functions and the Alpha LONGLONG types and
57: // operations is often not significant enough to warrant modifying otherwise
58: // portable code. In addition, future compiler optimization and inlining may
59: // actually result in identical performance between portable LARGE_INTEGER
60: // code and Alpha specific LONGLONG code. Therefore it is recommended to
61: // keep NT source code portable.
62: //
63: // The Alpha source for the large integer functions below differs from the
64: // Mips version since for Alpha a 64-bit argument or return value is passed
65: // through a 64-bit integer register. In addition, most operations are
66: // implemented with a single instruction. The division routines below,
67: // however, like Mips, use a simple shift/subtract algorithm which is
68: // considerably slower than the algorithm used by Alpha runtime division
69: // routines.
70: //
71:
72: SBTTL("Convert Long to Large Integer")
73: //++
74: //
75: // LARGE_INTEGER
76: // ConvertLongToLargeInteger (
77: // IN LONG SignedInteger
78: // )
79: //
80: // Routine Description:
81: //
82: // This function converts a signed integer to a signed large integer
83: // and returns the result.
84: //
85: // Arguments:
86: //
87: // SignedInteger (a0) - Supplies the value to convert.
88: //
89: // Return Value:
90: //
91: // The large integer result is returned as the function value in v0.
92: //
93: //--
94:
95: LEAF_ENTRY(ConvertLongToLargeInteger)
96:
97: addl a0, 0, v0 // ensure canonical (signed long) form
98: ret zero, (ra) // return
99:
100: .end ConvertLongToLargeInteger
101:
102: SBTTL("Convert Ulong to Large Integer")
103: //++
104: //
105: // LARGE_INTEGER
106: // ConvertUlongToLargeInteger (
107: // IN ULONG UnsignedInteger
108: // )
109: //
110: // Routine Description:
111: //
112: // This function converts an unsigned integer to a signed large
113: // integer and returns the result.
114: //
115: // Arguments:
116: //
117: // UnsignedInteger (a0) - Supplies the value to convert.
118: //
119: // Return Value:
120: //
121: // The large integer result is returned as the function value in v0.
122: //
123: //--
124:
125: LEAF_ENTRY(ConvertUlongToLargeInteger)
126:
127: zap a0, 0xf0, v0 // convert canonical ULONG to quadword
128: ret zero, (ra) // return
129:
130: .end ConvertUlongToLargeInteger
131:
132: SBTTL("Enlarged Signed Integer Multiply")
133: //++
134: //
135: // LARGE_INTEGER
136: // EnlargedIntegerMultiply (
137: // IN LONG Multiplicand,
138: // IN LONG Multiplier
139: // )
140: //
141: // Routine Description:
142: //
143: // This function multiplies a signed integer by a signed integer and
144: // returns a signed large integer result.
145: //
146: // N.B. An overflow is not possible.
147: //
148: // Arguments:
149: //
150: // Multiplicand (a0) - Supplies the multiplicand value.
151: //
152: // Multiplier (a1) - Supplies the multiplier value.
153: //
154: // Return Value:
155: //
156: // The large integer result is returned as the function value in v0.
157: //
158: //--
159:
160: LEAF_ENTRY(EnlargedIntegerMultiply)
161:
162: addl a0, 0, a0 // ensure canonical (signed long) form
163: addl a1, 0, a1 // ensure canonical (signed long) form
164: mulq a0, a1, v0 // multiply signed both quadwords
165: ret zero, (ra) // return
166:
167: .end EnlargedIntegerMultiply
168:
169: SBTTL("Enlarged Unsigned Divide")
170: //++
171: //
172: // ULONG
173: // EnlargedUnsignedDivide (
174: // IN ULARGE_INTEGER Dividend,
175: // IN ULONG Divisor,
176: // IN OUT PULONG Remainder OPTIONAL
177: // )
178: //
179: // Routine Description:
180: //
181: // This function divides an unsigned large integer by an unsigned long
182: // and returns the resultant quotient and optionally the remainder.
183: //
184: // N.B. An overflow or divide by zero exception is possible.
185: //
186: // Arguments:
187: //
188: // Dividend (a0) - Supplies the unsigned 64-bit dividend value.
189: //
190: // Divisor (a1) - Supplies the unsigned 32-bit divisor value.
191: //
192: // Remainder (a2) - Supplies an optional pointer to a variable that
193: // receives the unsigned 32-bit remainder.
194: //
195: // Return Value:
196: //
197: // The unsigned long integer quotient is returned as the function value.
198: //
199: //--
200:
201: LEAF_ENTRY(EnlargedUnsignedDivide)
202:
203: //
204: // Check for division by zero.
205: //
206:
207: zap a1, 0xf0, a1 // convert ULONG divisor to quadword
208: beq a1, 30f // trap if divisor is zero
209:
210: //
211: // Check for overflow. If the divisor is less than the upper half of the
212: // dividend the quotient would be wider than 32 bits.
213: //
214:
215: srl a0, 32, t0 // get upper longword of dividend
216: cmpule a1, t0, t1 // is divisor <= upper dividend?
217: bne t1, 40f // if ne[true], then overflow trap
218:
219: //
220: // Perform the shift/subtract loop 8 times and 4 bits per loop.
221: //
222: // t0 - Temp used for 0/1 results of compares.
223: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
224: // t2 - Loop counter.
225: //
226:
227: ldiq t2, 32/4 // set iteration count
228:
229: srl a0, 32, t1 // get top 32 bits of carry-out
230: sll a0, 32, a0 // preshift first 32 bits left
231:
232: 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
233: addq a0, a0, a0 // shift low-dividend left
234: addq t1, t1, t1 // shift high-dividend left
235: bis t1, t0, t1 // merge in carry-out of low-dividend
236:
237: cmpule a1, t1, t0 // if dividend >= divisor,
238: addq a0, t0, a0 // then set quotient bit
239: subq t1, a1, t0 // subtract divisor from dividend,
240: cmovlbs a0, t0, t1 // if dividend >= divisor
241:
242: cmplt a0, 0, t0 // predict low-dividend shift carry-out
243: addq a0, a0, a0 // shift low-dividend left
244: addq t1, t1, t1 // shift high-dividend left
245: bis t1, t0, t1 // merge in carry-out of low-dividend
246:
247: cmpule a1, t1, t0 // if dividend >= divisor,
248: addq a0, t0, a0 // then set quotient bit
249: subq t1, a1, t0 // subtract divisor from dividend,
250: cmovlbs a0, t0, t1 // if dividend >= divisor
251:
252: cmplt a0, 0, t0 // predict low-dividend shift carry-out
253: addq a0, a0, a0 // shift low-dividend left
254: addq t1, t1, t1 // shift high-dividend left
255: bis t1, t0, t1 // merge in carry-out of low-dividend
256:
257: cmpule a1, t1, t0 // if dividend >= divisor,
258: addq a0, t0, a0 // then set quotient bit
259: subq t1, a1, t0 // subtract divisor from dividend,
260: cmovlbs a0, t0, t1 // if dividend >= divisor
261:
262: cmplt a0, 0, t0 // predict low-dividend shift carry-out
263: addq a0, a0, a0 // shift low-dividend left
264: addq t1, t1, t1 // shift high-dividend left
265: bis t1, t0, t1 // merge in carry-out of low-dividend
266:
267: cmpule a1, t1, t0 // if dividend >= divisor,
268: addq a0, t0, a0 // then set quotient bit
269: subq t1, a1, t0 // subtract divisor from dividend,
270: cmovlbs a0, t0, t1 // if dividend >= divisor
271:
272: subq t2, 1, t2 // any more iterations?
273: bne t2, 10b //
274:
275: //
276: // Finished with remainder value in t1 and quotient value in a0.
277: //
278:
279: addl a0, 0, v0 // set longword quotient return value
280: beq a2, 20f // skip optional remainder store
281: stl t1, 0(a2) // store longword remainder
282:
283: 20: ret zero, (ra) // return
284:
285: //
286: // Generate an exception for divide by zero and return a zero quotient if the
287: // caller continues execution.
288: //
289:
290: 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
291:
292: GENERATE_TRAP
293:
294: ldil v0, 0 // return zero quotient
295: ret zero, (ra) // return
296:
297: //
298: // Generate an exception for overflow.
299: //
300:
301: 40: ldiq a0, 0x8000000000000000 //
302: subqv zero, a0, v0 // negate in order to overflow
303: trapb // wait for trap to occur
304: ret zero, (ra) // return
305:
306: .end EnlargedUnsignedDivide
307:
308: SBTTL("Enlarged Unsigned Integer Multiply")
309: //++
310: //
311: // LARGE_INTEGER
312: // EnlargedUnsignedMultiply (
313: // IN ULONG Multiplicand,
314: // IN ULONG Multiplier
315: // )
316: //
317: // Routine Description:
318: //
319: // This function multiplies an unsigned integer by an unsigned integer
320: // and returns a signed large integer result.
321: //
322: // Arguments:
323: //
324: // Multiplicand (a0) - Supplies the multiplicand value.
325: //
326: // Multiplier (a1) - Supplies the multiplier value.
327: //
328: // Return Value:
329: //
330: // The large integer result is returned as the function value in v0.
331: //
332: //--
333:
334: LEAF_ENTRY(EnlargedUnsignedMultiply)
335:
336: zap a0, 0xf0, a0 // convert canonical ULONG to quadword
337: zap a1, 0xf0, a1 // convert canonical ULONG to quadword
338: mulq a0, a1, v0 // multiply signed both quadwords
339: ret zero, (ra) // return
340:
341: .end EnlargedUnsignedMultiply
342:
343: SBTTL("Extended Integer Multiply")
344: //++
345: //
346: // LARGE_INTEGER
347: // ExtendedIntegerMultiply (
348: // IN LARGE_INTEGER Multiplicand,
349: // IN LONG Multiplier
350: // )
351: //
352: // Routine Description:
353: //
354: // This function multiplies a signed large integer by a signed integer and
355: // returns the signed large integer result.
356: //
357: // N.B. An overflow is possible, but no exception is generated.
358: //
359: // Arguments:
360: //
361: // Multiplicand (a0) - Supplies the multiplicand value.
362: //
363: // Multiplier (a1) - Supplies the multiplier value.
364: //
365: // Return Value:
366: //
367: // The large integer result is returned as the function value in v0.
368: //
369: //--
370:
371: LEAF_ENTRY(ExtendedIntegerMultiply)
372:
373: addl a1, 0, a1 // ensure canonical (signed long) form
374: mulq a0, a1, v0 // multiply signed both quadwords
375: ret zero, (ra) // return
376:
377: .end ExtendedIntegerMultiply
378:
379: SBTTL("Extended Large Integer Divide")
380: //++
381: //
382: // LARGE_INTEGER
383: // ExtendedLargeIntegerDivide (
384: // IN LARGE_INTEGER Dividend,
385: // IN ULONG Divisor,
386: // IN OUT PULONG Remainder OPTIONAL
387: // )
388: //
389: // Routine Description:
390: //
391: // This function divides an unsigned large integer by an unsigned long
392: // and returns the quadword quotient and optionally the long remainder.
393: //
394: // N.B. A divide by zero exception is possible.
395: //
396: // Arguments:
397: //
398: // Dividend (a0) - Supplies the dividend value.
399: //
400: // Divisor (a1) - Supplies the divisor value.
401: //
402: // Remainder (a2) - Supplies an optional pointer to a variable that
403: // receives the remainder.
404: //
405: // Return Value:
406: //
407: // The large integer result is returned as the function value in v0.
408: //
409: //--
410:
411: LEAF_ENTRY(ExtendedLargeIntegerDivide)
412:
413: //
414: // Check for division by zero.
415: //
416:
417: zap a1, 0xf0, a1 // convert canonical ULONG to quadword
418: beq a1, 30f // trap if divisor is zero
419:
420: //
421: // Perform the shift/subtract loop 16 times and 4 bits per loop.
422: //
423: // t0 - Temp used for 0/1 results of compares.
424: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
425: // t2 - Loop counter.
426: //
427:
428: ldiq t2, 64/4 // set iteration count
429:
430: ldiq t1, 0 // zero-extend dividend to 128 bits
431:
432: 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
433: addq a0, a0, a0 // shift low-dividend left
434: addq t1, t1, t1 // shift high-dividend left
435: bis t1, t0, t1 // merge in carry-out of low-dividend
436:
437: cmpule a1, t1, t0 // if dividend >= divisor,
438: addq a0, t0, a0 // then set quotient bit
439: subq t1, a1, t0 // subtract divisor from dividend,
440: cmovlbs a0, t0, t1 // if dividend >= divisor
441:
442: cmplt a0, 0, t0 // predict low-dividend shift carry-out
443: addq a0, a0, a0 // shift low-dividend left
444: addq t1, t1, t1 // shift high-dividend left
445: bis t1, t0, t1 // merge in carry-out of low-dividend
446:
447: cmpule a1, t1, t0 // if dividend >= divisor,
448: addq a0, t0, a0 // then set quotient bit
449: subq t1, a1, t0 // subtract divisor from dividend,
450: cmovlbs a0, t0, t1 // if dividend >= divisor
451:
452: cmplt a0, 0, t0 // predict low-dividend shift carry-out
453: addq a0, a0, a0 // shift low-dividend left
454: addq t1, t1, t1 // shift high-dividend left
455: bis t1, t0, t1 // merge in carry-out of low-dividend
456:
457: cmpule a1, t1, t0 // if dividend >= divisor,
458: addq a0, t0, a0 // then set quotient bit
459: subq t1, a1, t0 // subtract divisor from dividend,
460: cmovlbs a0, t0, t1 // if dividend >= divisor
461:
462: cmplt a0, 0, t0 // predict low-dividend shift carry-out
463: addq a0, a0, a0 // shift low-dividend left
464: addq t1, t1, t1 // shift high-dividend left
465: bis t1, t0, t1 // merge in carry-out of low-dividend
466:
467: cmpule a1, t1, t0 // if dividend >= divisor,
468: addq a0, t0, a0 // then set quotient bit
469: subq t1, a1, t0 // subtract divisor from dividend,
470: cmovlbs a0, t0, t1 // if dividend >= divisor
471:
472: subq t2, 1, t2 // any more iterations?
473: bne t2, 10b //
474:
475: //
476: // Finished with remainder value in t1 and quotient value in a0.
477: //
478:
479: mov a0, v0 // set quadword quotient return value
480: beq a2, 20f // skip optional remainder store
481: stl t1, 0(a2) // store longword remainder
482:
483: 20: ret zero, (ra) // return
484:
485: //
486: // Generate an exception for divide by zero.
487: //
488:
489: 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
490:
491: GENERATE_TRAP
492:
493: br zero, 30b // in case they continue
494:
495: .end ExtendedLargeIntegerDivide
496:
497: SBTTL("Extended Magic Divide")
498: //++
499: //
500: // LARGE_INTEGER
501: // ExtendedMagicDivide (
502: // IN LARGE_INTEGER Dividend,
503: // IN LARGE_INTEGER MagicDivisor,
504: // IN CCHAR ShiftCount
505: // )
506: //
507: // Routine Description:
508: //
509: // This function divides a signed large integer by an unsigned large integer
510: // and returns the signed large integer result. The division is performed
511: // using reciprocal multiplication of a signed large integer value by an
512: // unsigned large integer fraction which represents the most significant
513: // 64-bits of the reciprocal divisor rounded up in its least significant bit
514: // and normalized with respect to bit 63. A shift count is also provided
515: // which is used to truncate the fractional bits from the result value.
516: //
517: // Arguments:
518: //
519: // Dividend (a0) - Supplies the dividend value.
520: //
521: // MagicDivisor (a1) - Supplies the magic divisor value which
522: // is a 64-bit multiplicative reciprocal.
523: //
524: // Shiftcount (a2) - Supplies the right shift adjustment value.
525: //
526: // Return Value:
527: //
528: // The large integer result is returned as the function value in v0.
529: //
530: //--
531:
532: LEAF_ENTRY(ExtendedMagicDivide)
533:
534: //
535: // Make the dividend positive for the reciprocal multiplication to work.
536: //
537:
538: negq a0, t0 // negate dividend
539: cmovgt a0, a0, t0 // get absolute value in t0
540:
541: //
542: // Multiply both quadword arguments together and take only the upper 64 bits of
543: // the resulting 128 bit product. This can be done using the umulh instruction.
544: //
545: // Division of a dividend by a constant divisor through reciprocal
546: // multiplication works because a/b is equivalent to (a*x)/(b*x) for any
547: // value of x. Now if b is a constant, some "magic" integer x can be chosen,
548: // based on the value of b, so that (b*x) is very close to a large power of
549: // two (e.g., 2^64). Then a/b = (a*x)/(b*x) = (a*x)/(2^64) = (a*x)>>64. This
550: // effectively turns the problem of division by a constant into multiplication
551: // by a constant which is a much faster operation.
552: //
553:
554: umulh t0, a1, t1 // multiply high both quadword arguments
555: sra t1, a2, t1 // shift result right by requested amount
556:
557: //
558: // Make the result negative if the dividend was negative.
559: //
560:
561: negq t1, t0 // negate result
562: cmovgt a0, t1, t0 // restore sign of dividend
563:
564: mov t0, v0 // set quadword result return value
565: ret zero, (ra) // return
566:
567: .end ExtendedMagicDivide
568:
569: SBTTL("Large Integer Add")
570: //++
571: //
572: // LARGE_INTEGER
573: // LargeIntegerAdd (
574: // IN LARGE_INTEGER Addend1,
575: // IN LARGE_INTEGER Addend2
576: // )
577: //
578: // Routine Description:
579: //
580: // This function adds a signed large integer to a signed large integer and
581: // returns the signed large integer result.
582: //
583: // N.B. An overflow is possible, but no exception is generated.
584: //
585: // Arguments:
586: //
587: // Addend1 (a0) - Supplies the first addend value.
588: //
589: // Addend2 (a1) - Supplies the second addend value.
590: //
591: // Return Value:
592: //
593: // The large integer result is returned as the function value in v0.
594: //
595: //--
596:
597: LEAF_ENTRY(LargeIntegerAdd)
598:
599: addq a0, a1, v0 // add both quadword arguments
600: ret zero, (ra) // return
601:
602: .end LargeIntegerAdd
603:
604: SBTTL("Large Integer Arithmetic Shift Right")
605: //++
606: //
607: // LARGE_INTEGER
608: // LargeIntegerArithmeticShift (
609: // IN LARGE_INTEGER LargeInteger,
610: // IN CCHAR ShiftCount
611: // )
612: //
613: // Routine Description:
614: //
615: // This function shifts a signed large integer right by an unsigned integer
616: // modulo 64 and returns the shifted signed large integer result.
617: //
618: // Arguments:
619: //
620: // LargeInteger (a0) - Supplies the large integer to be shifted.
621: //
622: // ShiftCount (a1) - Supplies the right shift count.
623: //
624: // Return Value:
625: //
626: // The large integer result is returned as the function value in v0.
627: //
628: //--
629:
630: LEAF_ENTRY(LargeIntegerArithmeticShift)
631:
632: sra a0, a1, v0 // shift the quadword right/arithmetic
633: ret zero, (ra) // return
634:
635: .end LargeIntegerArithmeticShift
636:
637: SBTTL("Large Integer Divide")
638: //++
639: //
640: // LARGE_INTEGER
641: // LargeIntegerDivide (
642: // IN LARGE_INTEGER Dividend,
643: // IN LARGE_INTEGER Divisor,
644: // IN OUT PLARGE_INTEGER Remainder OPTIONAL
645: // )
646: //
647: // Routine Description:
648: //
649: // This function divides an unsigned large integer by an unsigned large
650: // integer and returns the quadword quotient and optionally the quadword
651: // remainder.
652: //
653: // N.B. A divide by zero exception is possible.
654: //
655: // Arguments:
656: //
657: // Dividend (a0) - Supplies the dividend value.
658: //
659: // Divisor (a1) - Supplies the divisor value.
660: //
661: // Remainder (a2) - Supplies an optional pointer to a variable that
662: // receives the remainder.
663: //
664: // Return Value:
665: //
666: // The large integer result is returned as the function value in v0.
667: //
668: //--
669:
670: LEAF_ENTRY(LargeIntegerDivide)
671:
672: //
673: // Check for division by zero.
674: //
675:
676: beq a1, 30f // trap if divisor is zero
677:
678: //
679: // Perform the shift/subtract loop 16 times and 4 bits per loop.
680: //
681: // t0 - Temp used for 0/1 results of compares.
682: // t1 - High 64-bits of 128-bit (t1, a0) dividend.
683: // t2 - Loop counter.
684: //
685:
686: ldiq t2, 64/4 // set iteration count
687:
688: ldiq t1, 0 // zero-extend dividend to 128 bits
689:
690: 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
691: addq a0, a0, a0 // shift low-dividend left
692: addq t1, t1, t1 // shift high-dividend left
693: bis t1, t0, t1 // merge in carry-out of low-dividend
694:
695: cmpule a1, t1, t0 // if dividend >= divisor,
696: addq a0, t0, a0 // then set quotient bit
697: subq t1, a1, t0 // subtract divisor from dividend,
698: cmovlbs a0, t0, t1 // if dividend >= divisor
699:
700: cmplt a0, 0, t0 // predict low-dividend shift carry-out
701: addq a0, a0, a0 // shift low-dividend left
702: addq t1, t1, t1 // shift high-dividend left
703: bis t1, t0, t1 // merge in carry-out of low-dividend
704:
705: cmpule a1, t1, t0 // if dividend >= divisor,
706: addq a0, t0, a0 // then set quotient bit
707: subq t1, a1, t0 // subtract divisor from dividend,
708: cmovlbs a0, t0, t1 // if dividend >= divisor
709:
710: cmplt a0, 0, t0 // predict low-dividend shift carry-out
711: addq a0, a0, a0 // shift low-dividend left
712: addq t1, t1, t1 // shift high-dividend left
713: bis t1, t0, t1 // merge in carry-out of low-dividend
714:
715: cmpule a1, t1, t0 // if dividend >= divisor,
716: addq a0, t0, a0 // then set quotient bit
717: subq t1, a1, t0 // subtract divisor from dividend,
718: cmovlbs a0, t0, t1 // if dividend >= divisor
719:
720: cmplt a0, 0, t0 // predict low-dividend shift carry-out
721: addq a0, a0, a0 // shift low-dividend left
722: addq t1, t1, t1 // shift high-dividend left
723: bis t1, t0, t1 // merge in carry-out of low-dividend
724:
725: cmpule a1, t1, t0 // if dividend >= divisor,
726: addq a0, t0, a0 // then set quotient bit
727: subq t1, a1, t0 // subtract divisor from dividend,
728: cmovlbs a0, t0, t1 // if dividend >= divisor
729:
730: subq t2, 1, t2 // any more iterations?
731: bne t2, 10b //
732:
733: //
734: // Finished with remainder value in t1 and quotient value in a0.
735: //
736:
737: mov a0, v0 // set quadword quotient return value
738: beq a2, 20f // skip optional remainder store
739: stq t1, 0(a2) // store quadword remainder
740:
741: 20: ret zero, (ra) // return
742:
743: //
744: // Generate an exception for divide by zero.
745: //
746:
747: 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
748:
749: GENERATE_TRAP
750:
751: br zero, 30b // in case they continue
752:
753: .end LargeIntegerDivide
754:
755: SBTTL("Large Integer Negate")
756: //++
757: //
758: // LARGE_INTEGER
759: // LargeIntegerNegate (
760: // IN LARGE_INTEGER Subtrahend
761: // )
762: //
763: // Routine Description:
764: //
765: // This function negates a signed large integer and returns the signed
766: // large integer result.
767: //
768: // N.B. An overflow is possible, but no exception is generated.
769: //
770: // Arguments:
771: //
772: // Subtrahend (a0) - Supplies the subtrahend value.
773: //
774: // Return Value:
775: //
776: // The large integer result is returned as the function value in v0.
777: //
778: //--
779:
780: LEAF_ENTRY(LargeIntegerNegate)
781:
782: subq zero, a0, v0 // negate the quadword argument
783: ret zero, (ra) // return
784:
785: .end LargeIntegerNegate
786:
787: SBTTL("Large Integer Shift Left")
788: //++
789: //
790: // LARGE_INTEGER
791: // LargeIntegerShiftLeft (
792: // IN LARGE_INTEGER LargeInteger,
793: // IN CCHAR ShiftCount
794: // )
795: //
796: // Routine Description:
797: //
798: // This function shifts a signed large integer left by an unsigned integer
799: // modulo 64 and returns the shifted signed large integer result.
800: //
801: // Arguments:
802: //
803: // LargeInteger (a0) - Supplies the large integer to be shifted.
804: //
805: // ShiftCount (a1) - Supplies the left shift count.
806: //
807: // Return Value:
808: //
809: // The large integer result is returned as the function value in v0.
810: //
811: //--
812:
813: LEAF_ENTRY(LargeIntegerShiftLeft)
814:
815: sll a0, a1, v0 // shift the quadword argument left
816: ret zero, (ra) // return
817:
818: .end LargeIntegerShiftLeft
819:
820: SBTTL("Large Integer Logical Shift Right")
821: //++
822: //
823: // LARGE_INTEGER
824: // LargeIntegerShiftRight (
825: // IN LARGE_INTEGER LargeInteger,
826: // IN CCHAR ShiftCount
827: // )
828: //
829: // Routine Description:
830: //
831: // This function shifts an unsigned large integer right by an unsigned
832: // integer modulo 64 and returns the shifted unsigned large integer result.
833: //
834: // Arguments:
835: //
836: // LargeInteger (a0) - Supplies the large integer to be shifted.
837: //
838: // ShiftCount (a1) - Supplies the right shift count.
839: //
840: // Return Value:
841: //
842: // The large integer result is returned as the function value in v0.
843: //
844: //--
845:
846: LEAF_ENTRY(LargeIntegerShiftRight)
847:
848: srl a0, a1, v0 // shift the quadword right/logical
849: ret zero, (ra) // return
850:
851: .end LargeIntegerShiftRight
852:
853: SBTTL("Large Integer Subtract")
854: //++
855: //
856: // LARGE_INTEGER
857: // LargeIntegerSubtract (
858: // IN LARGE_INTEGER Minuend,
859: // IN LARGE_INTEGER Subtrahend
860: // )
861: //
862: // Routine Description:
863: //
864: // This function subtracts a signed large integer from a signed large
865: // integer and returns the signed large integer result.
866: //
867: // N.B. An overflow is possible, but no exception is generated.
868: //
869: // Arguments:
870: //
871: // Minuend (a0) - Supplies the minuend value.
872: //
873: // Subtrahend (a1) - Supplies the subtrahend value.
874: //
875: // Return Value:
876: //
877: // The large integer result is returned as the function value in v0.
878: //
879: //--
880:
881: LEAF_ENTRY(LargeIntegerSubtract)
882:
883: subq a0, a1, v0 // subtract the quadword arguments
884: ret zero, (ra) // return
885:
886: .end LargeIntegerSubtract
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.