.Title QUADMATH - A package of routines to manipulate quadwords ;++ ; ; Written by Kevin Carosso, @ Hughes S&CG PWB/ENG. ; ; This is a simple package of four routines to do quadword mathematics. ; ; Note: ; All arguments are addresses of quadwords. ; ;-- ;------------------------------------------------------------------------------ ; ; ADDQ - Integer addition. ; ; Call: ; ret = ADDQ (Sum, Operand1, Operand2) ; i.e.: ; Sum = Operand1 + Operand2 ; ;- .Entry ADDQ, ^M movq @12(ap), r0 ; Get the two addends. movq @8(ap), r2 addl r0, r2 ; Add low order longwords adwc r1, r3 ; then high order. movq r2, @4(ap) ; Store result movl #SS$_NORMAL, r0 ; and return success. ret ;------------------------------------------------------------------------------ ; ; SUBQ - Integer subtraction. ; ; Call: ; ret = SUBQ (Difference, Operand1, Operand2) ; i.e.: ; Difference = Operand1 - Operand2 ; ;- .Entry SUBQ, ^M movq @12(ap), r0 ; Get the two operands. movq @8(ap), r2 subl2 r0, r2 ; Subtract low order longwords sbwc r1, r3 ; then high order. movq r2, @4(ap) ; Store result movl #SS$_NORMAL, r0 ; and return success. ret ;------------------------------------------------------------------------------ ; ; MULQ - Integer multiplication. ; ; Call: ; ret = MULQ (Product, Operand1, Operand2) ; i.e.: ; Product = Operand1 * Operand2 ; ;- .Entry MULQ, ^M movq @8(ap), r0 ; Get the operands movq @12(ap), r2 emul r0, r2, #0, r4 ; Multiply low order half mull3 r1, r2, r6 ; hi-order = A[high] * B[low] mull3 r0, r3, r7 ; + A[low] * B[high] addl2 r7, r6 tstl r0 ; If A[low] < 0 then compensate for bgeq 10$ addl2 r2, r6 ; unsigned bias of 2^32. 10$: tstl r2 ; Same for B bgeq 20$ addl2 r0, r6 20$: addl2 r6, r5 ; Combine with high of A[low] * B[high] movq r4, @4(ap) ; Store result movl #SS$_NORMAL, r0 ret ;------------------------------------------------------------------------------ ; ; DIVQ - Integer division. ; ; Call: ; ret = DIVQ (Quotient, Remainder, Dividend, Divisor) ; i.e.: ; (Quotient, Remainder) = Dividend/Divisor ; ;- .Entry DIVQ, ^M movq @16(ap), r0 ; Get divisor. movq @12(ap), r2 ; Get dividend. movq r2, r4 ; Quotient := Dividend clrq r6 ; Remainder := 0 clrl r8 ; Use this for a "carry" flag. movl #65, r10 ; Loop counter. 10$: ashq #1, r6, r6 ; Shift remainder left by 1 bisl2 r8, r6 ; and shift in from dividend "carry". clrl r8 ; Clear the "carry" flag. cmpl r1, r7 ; See if divisor > current remainder bneq 20$ cmpl r0, r6 20$: bgtru 30$ ; and if so skip on ("carry" is clear). subl2 r0, r6 ; Subtract divisor from remainder. sbwc r1, r7 incl r8 ; Set "carry". 30$: clrl r9 ; Now check whether or not we will tstl r5 ; need a "carry" after the shift. bgeq 40$ incl r9 ; Set it if so. 40$: ashq #1, r4, r4 ; Shift quotient left by one bisl2 r8, r4 ; and shift in a new bit. movl r9, r8 ; Set "carry" for this operation. decl r10 ; Decrement counter bneq 10$ ; and loop back. movq r4, @4(ap) ; Save the quotient movq r6, @8(ap) ; and the remainder. movl #SS$_NORMAL, r0 ; Return success... ret .End