140843Smsmith/******************************************************************* 240843Smsmith** m a t h 6 4 . c 340843Smsmith** Forth Inspired Command Language - 64 bit math support routines 440843Smsmith** Author: John Sadler (john_sadler@alum.mit.edu) 540843Smsmith** Created: 25 January 1998 651786Sdcs** Rev 2.03: Support for 128 bit DP math. This file really ouught to 751786Sdcs** be renamed! 894290Sdcs** $Id: math64.c,v 1.9 2001/12/05 07:21:34 jsadler Exp $ 940843Smsmith*******************************************************************/ 1076116Sdcs/* 1176116Sdcs** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 1276116Sdcs** All rights reserved. 1376116Sdcs** 1476116Sdcs** Get the latest Ficl release at http://ficl.sourceforge.net 1576116Sdcs** 1694290Sdcs** I am interested in hearing from anyone who uses ficl. If you have 1794290Sdcs** a problem, a success story, a defect, an enhancement request, or 1894290Sdcs** if you would like to contribute to the ficl release, please 1994290Sdcs** contact me by email at the address above. 2094290Sdcs** 2176116Sdcs** L I C E N S E and D I S C L A I M E R 2276116Sdcs** 2376116Sdcs** Redistribution and use in source and binary forms, with or without 2476116Sdcs** modification, are permitted provided that the following conditions 2576116Sdcs** are met: 2676116Sdcs** 1. Redistributions of source code must retain the above copyright 2776116Sdcs** notice, this list of conditions and the following disclaimer. 2876116Sdcs** 2. Redistributions in binary form must reproduce the above copyright 2976116Sdcs** notice, this list of conditions and the following disclaimer in the 3076116Sdcs** documentation and/or other materials provided with the distribution. 3176116Sdcs** 3276116Sdcs** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 3376116Sdcs** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3476116Sdcs** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3576116Sdcs** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 3676116Sdcs** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3776116Sdcs** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3876116Sdcs** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3976116Sdcs** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4076116Sdcs** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4176116Sdcs** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4276116Sdcs** SUCH DAMAGE. 4376116Sdcs*/ 4440843Smsmith 4551786Sdcs/* $FreeBSD$ */ 4651786Sdcs 4740843Smsmith#include "ficl.h" 4840843Smsmith#include "math64.h" 4940843Smsmith 5040843Smsmith 5140843Smsmith/************************************************************************** 5240843Smsmith m 6 4 A b s 5351786Sdcs** Returns the absolute value of an DPINT 5440843Smsmith**************************************************************************/ 5551786SdcsDPINT m64Abs(DPINT x) 5640843Smsmith{ 5740843Smsmith if (m64IsNegative(x)) 5840843Smsmith x = m64Negate(x); 5940843Smsmith 6040843Smsmith return x; 6140843Smsmith} 6240843Smsmith 6340843Smsmith 6440843Smsmith/************************************************************************** 6540843Smsmith m 6 4 F l o o r e d D i v I 6640843Smsmith** 6740843Smsmith** FROM THE FORTH ANS... 6840843Smsmith** Floored division is integer division in which the remainder carries 6940843Smsmith** the sign of the divisor or is zero, and the quotient is rounded to 7040843Smsmith** its arithmetic floor. Symmetric division is integer division in which 7140843Smsmith** the remainder carries the sign of the dividend or is zero and the 7240843Smsmith** quotient is the mathematical quotient rounded towards zero or 7340843Smsmith** truncated. Examples of each are shown in tables 3.3 and 3.4. 7440843Smsmith** 7540843Smsmith** Table 3.3 - Floored Division Example 7640843Smsmith** Dividend Divisor Remainder Quotient 7740843Smsmith** -------- ------- --------- -------- 7840843Smsmith** 10 7 3 1 7940843Smsmith** -10 7 4 -2 8040843Smsmith** 10 -7 -4 -2 8140843Smsmith** -10 -7 -3 1 8240843Smsmith** 8340843Smsmith** 8440843Smsmith** Table 3.4 - Symmetric Division Example 8540843Smsmith** Dividend Divisor Remainder Quotient 8640843Smsmith** -------- ------- --------- -------- 8740843Smsmith** 10 7 3 1 8840843Smsmith** -10 7 -3 -1 8940843Smsmith** 10 -7 3 -1 9040843Smsmith** -10 -7 -3 1 9140843Smsmith**************************************************************************/ 9251786SdcsINTQR m64FlooredDivI(DPINT num, FICL_INT den) 9340843Smsmith{ 9440843Smsmith INTQR qr; 9540843Smsmith UNSQR uqr; 9640843Smsmith int signRem = 1; 9740843Smsmith int signQuot = 1; 9840843Smsmith 9940843Smsmith if (m64IsNegative(num)) 10040843Smsmith { 10140843Smsmith num = m64Negate(num); 10240843Smsmith signQuot = -signQuot; 10340843Smsmith } 10440843Smsmith 10540843Smsmith if (den < 0) 10640843Smsmith { 10740843Smsmith den = -den; 10840843Smsmith signRem = -signRem; 10940843Smsmith signQuot = -signQuot; 11040843Smsmith } 11140843Smsmith 11251786Sdcs uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den); 11340843Smsmith qr = m64CastQRUI(uqr); 11440843Smsmith if (signQuot < 0) 11540843Smsmith { 11640843Smsmith qr.quot = -qr.quot; 11740843Smsmith if (qr.rem != 0) 11840843Smsmith { 11940843Smsmith qr.quot--; 12040843Smsmith qr.rem = den - qr.rem; 12140843Smsmith } 12240843Smsmith } 12340843Smsmith 12440843Smsmith if (signRem < 0) 12540843Smsmith qr.rem = -qr.rem; 12640843Smsmith 12740843Smsmith return qr; 12840843Smsmith} 12940843Smsmith 13040843Smsmith 13140843Smsmith/************************************************************************** 13240843Smsmith m 6 4 I s N e g a t i v e 13351786Sdcs** Returns TRUE if the specified DPINT has its sign bit set. 13440843Smsmith**************************************************************************/ 13551786Sdcsint m64IsNegative(DPINT x) 13640843Smsmith{ 13740843Smsmith return (x.hi < 0); 13840843Smsmith} 13940843Smsmith 14040843Smsmith 14140843Smsmith/************************************************************************** 14240843Smsmith m 6 4 M a c 14340843Smsmith** Mixed precision multiply and accumulate primitive for number building. 14451786Sdcs** Multiplies DPUNS u by FICL_UNS mul and adds FICL_UNS add. Mul is typically 14540843Smsmith** the numeric base, and add represents a digit to be appended to the 14640843Smsmith** growing number. 14740843Smsmith** Returns the result of the operation 14840843Smsmith**************************************************************************/ 14951786SdcsDPUNS m64Mac(DPUNS u, FICL_UNS mul, FICL_UNS add) 15040843Smsmith{ 15151786Sdcs DPUNS resultLo = ficlLongMul(u.lo, mul); 15251786Sdcs DPUNS resultHi = ficlLongMul(u.hi, mul); 15340843Smsmith resultLo.hi += resultHi.lo; 15440843Smsmith resultHi.lo = resultLo.lo + add; 15540843Smsmith 15640843Smsmith if (resultHi.lo < resultLo.lo) 15740843Smsmith resultLo.hi++; 15840843Smsmith 15940843Smsmith resultLo.lo = resultHi.lo; 16040843Smsmith 16140843Smsmith return resultLo; 16240843Smsmith} 16340843Smsmith 16440843Smsmith 16540843Smsmith/************************************************************************** 16640843Smsmith m 6 4 M u l I 16751786Sdcs** Multiplies a pair of FICL_INTs and returns an DPINT result. 16840843Smsmith**************************************************************************/ 16951786SdcsDPINT m64MulI(FICL_INT x, FICL_INT y) 17040843Smsmith{ 17151786Sdcs DPUNS prod; 17240843Smsmith int sign = 1; 17340843Smsmith 17440843Smsmith if (x < 0) 17540843Smsmith { 17640843Smsmith sign = -sign; 17740843Smsmith x = -x; 17840843Smsmith } 17940843Smsmith 18040843Smsmith if (y < 0) 18140843Smsmith { 18240843Smsmith sign = -sign; 18340843Smsmith y = -y; 18440843Smsmith } 18540843Smsmith 18640843Smsmith prod = ficlLongMul(x, y); 18740843Smsmith if (sign > 0) 18840843Smsmith return m64CastUI(prod); 18940843Smsmith else 19040843Smsmith return m64Negate(m64CastUI(prod)); 19140843Smsmith} 19240843Smsmith 19340843Smsmith 19440843Smsmith/************************************************************************** 19540843Smsmith m 6 4 N e g a t e 19651786Sdcs** Negates an DPINT by complementing and incrementing. 19740843Smsmith**************************************************************************/ 19851786SdcsDPINT m64Negate(DPINT x) 19940843Smsmith{ 20040843Smsmith x.hi = ~x.hi; 20140843Smsmith x.lo = ~x.lo; 20240843Smsmith x.lo ++; 20340843Smsmith if (x.lo == 0) 20440843Smsmith x.hi++; 20540843Smsmith 20640843Smsmith return x; 20740843Smsmith} 20840843Smsmith 20940843Smsmith 21040843Smsmith/************************************************************************** 21140843Smsmith m 6 4 P u s h 21251786Sdcs** Push an DPINT onto the specified stack in the order required 21340843Smsmith** by ANS Forth (most significant cell on top) 21440843Smsmith** These should probably be macros... 21540843Smsmith**************************************************************************/ 21651786Sdcsvoid i64Push(FICL_STACK *pStack, DPINT i64) 21740843Smsmith{ 21851786Sdcs stackPushINT(pStack, i64.lo); 21951786Sdcs stackPushINT(pStack, i64.hi); 22040843Smsmith return; 22140843Smsmith} 22240843Smsmith 22351786Sdcsvoid u64Push(FICL_STACK *pStack, DPUNS u64) 22440843Smsmith{ 22551786Sdcs stackPushINT(pStack, u64.lo); 22651786Sdcs stackPushINT(pStack, u64.hi); 22740843Smsmith return; 22840843Smsmith} 22940843Smsmith 23040843Smsmith 23140843Smsmith/************************************************************************** 23240843Smsmith m 6 4 P o p 23351786Sdcs** Pops an DPINT off the stack in the order required by ANS Forth 23440843Smsmith** (most significant cell on top) 23540843Smsmith** These should probably be macros... 23640843Smsmith**************************************************************************/ 23751786SdcsDPINT i64Pop(FICL_STACK *pStack) 23840843Smsmith{ 23951786Sdcs DPINT ret; 24051786Sdcs ret.hi = stackPopINT(pStack); 24151786Sdcs ret.lo = stackPopINT(pStack); 24240843Smsmith return ret; 24340843Smsmith} 24440843Smsmith 24551786SdcsDPUNS u64Pop(FICL_STACK *pStack) 24640843Smsmith{ 24751786Sdcs DPUNS ret; 24851786Sdcs ret.hi = stackPopINT(pStack); 24951786Sdcs ret.lo = stackPopINT(pStack); 25040843Smsmith return ret; 25140843Smsmith} 25240843Smsmith 25340843Smsmith 25440843Smsmith/************************************************************************** 25540843Smsmith m 6 4 S y m m e t r i c D i v 25651786Sdcs** Divide an DPINT by a FICL_INT and return a FICL_INT quotient and a 25751786Sdcs** FICL_INT remainder. The absolute values of quotient and remainder are not 25840843Smsmith** affected by the signs of the numerator and denominator (the operation 25940843Smsmith** is symmetric on the number line) 26040843Smsmith**************************************************************************/ 26151786SdcsINTQR m64SymmetricDivI(DPINT num, FICL_INT den) 26240843Smsmith{ 26340843Smsmith INTQR qr; 26440843Smsmith UNSQR uqr; 26540843Smsmith int signRem = 1; 26640843Smsmith int signQuot = 1; 26740843Smsmith 26840843Smsmith if (m64IsNegative(num)) 26940843Smsmith { 27040843Smsmith num = m64Negate(num); 27140843Smsmith signRem = -signRem; 27240843Smsmith signQuot = -signQuot; 27340843Smsmith } 27440843Smsmith 27540843Smsmith if (den < 0) 27640843Smsmith { 27740843Smsmith den = -den; 27840843Smsmith signQuot = -signQuot; 27940843Smsmith } 28040843Smsmith 28151786Sdcs uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den); 28240843Smsmith qr = m64CastQRUI(uqr); 28340843Smsmith if (signRem < 0) 28440843Smsmith qr.rem = -qr.rem; 28540843Smsmith 28640843Smsmith if (signQuot < 0) 28740843Smsmith qr.quot = -qr.quot; 28840843Smsmith 28940843Smsmith return qr; 29040843Smsmith} 29140843Smsmith 29240843Smsmith 29340843Smsmith/************************************************************************** 29440843Smsmith m 6 4 U M o d 29551786Sdcs** Divides a DPUNS by base (an UNS16) and returns an UNS16 remainder. 29651786Sdcs** Writes the quotient back to the original DPUNS as a side effect. 29751786Sdcs** This operation is typically used to convert an DPUNS to a text string 29840843Smsmith** in any base. See words.c:numberSignS, for example. 29940843Smsmith** Mechanics: performs 4 ficlLongDivs, each of which produces 16 bits 30051786Sdcs** of the quotient. C does not provide a way to divide an FICL_UNS by an 30151786Sdcs** UNS16 and get an FICL_UNS quotient (ldiv is closest, but it's signed, 30240843Smsmith** unfortunately), so I've used ficlLongDiv. 30340843Smsmith**************************************************************************/ 30451786Sdcs#if (BITS_PER_CELL == 32) 30551786Sdcs 30651786Sdcs#define UMOD_SHIFT 16 30751786Sdcs#define UMOD_MASK 0x0000ffff 30851786Sdcs 30951786Sdcs#elif (BITS_PER_CELL == 64) 31051786Sdcs 31151786Sdcs#define UMOD_SHIFT 32 31251786Sdcs#define UMOD_MASK 0x00000000ffffffff 31351786Sdcs 31451786Sdcs#endif 31551786Sdcs 31651786SdcsUNS16 m64UMod(DPUNS *pUD, UNS16 base) 31740843Smsmith{ 31851786Sdcs DPUNS ud; 31940843Smsmith UNSQR qr; 32051786Sdcs DPUNS result; 32140843Smsmith 32240843Smsmith result.hi = result.lo = 0; 32340843Smsmith 32440843Smsmith ud.hi = 0; 32551786Sdcs ud.lo = pUD->hi >> UMOD_SHIFT; 32651786Sdcs qr = ficlLongDiv(ud, (FICL_UNS)base); 32751786Sdcs result.hi = qr.quot << UMOD_SHIFT; 32840843Smsmith 32951786Sdcs ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->hi & UMOD_MASK); 33051786Sdcs qr = ficlLongDiv(ud, (FICL_UNS)base); 33151786Sdcs result.hi |= qr.quot & UMOD_MASK; 33240843Smsmith 33351786Sdcs ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo >> UMOD_SHIFT); 33451786Sdcs qr = ficlLongDiv(ud, (FICL_UNS)base); 33551786Sdcs result.lo = qr.quot << UMOD_SHIFT; 33640843Smsmith 33751786Sdcs ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo & UMOD_MASK); 33851786Sdcs qr = ficlLongDiv(ud, (FICL_UNS)base); 33951786Sdcs result.lo |= qr.quot & UMOD_MASK; 34040843Smsmith 34140843Smsmith *pUD = result; 34240843Smsmith 34340843Smsmith return (UNS16)(qr.rem); 34440843Smsmith} 34540843Smsmith 34640843Smsmith 34751786Sdcs/************************************************************************** 34851786Sdcs** Contributed by 34976116Sdcs** Michael A. Gauland gaulandm@mdhost.cse.tek.com 35051786Sdcs**************************************************************************/ 35151786Sdcs#if PORTABLE_LONGMULDIV != 0 35251786Sdcs/************************************************************************** 35351786Sdcs m 6 4 A d d 35451786Sdcs** 35551786Sdcs**************************************************************************/ 35651786SdcsDPUNS m64Add(DPUNS x, DPUNS y) 35751786Sdcs{ 35851786Sdcs DPUNS result; 35951786Sdcs int carry; 36051786Sdcs 36151786Sdcs result.hi = x.hi + y.hi; 36251786Sdcs result.lo = x.lo + y.lo; 36351786Sdcs 36451786Sdcs 36551786Sdcs carry = ((x.lo | y.lo) & CELL_HI_BIT) && !(result.lo & CELL_HI_BIT); 36651786Sdcs carry |= ((x.lo & y.lo) & CELL_HI_BIT); 36751786Sdcs 36851786Sdcs if (carry) 36951786Sdcs { 37051786Sdcs result.hi++; 37151786Sdcs } 37251786Sdcs 37351786Sdcs return result; 37451786Sdcs} 37551786Sdcs 37651786Sdcs 37751786Sdcs/************************************************************************** 37851786Sdcs m 6 4 S u b 37951786Sdcs** 38051786Sdcs**************************************************************************/ 38151786SdcsDPUNS m64Sub(DPUNS x, DPUNS y) 38251786Sdcs{ 38351786Sdcs DPUNS result; 38451786Sdcs 38551786Sdcs result.hi = x.hi - y.hi; 38651786Sdcs result.lo = x.lo - y.lo; 38751786Sdcs 38851786Sdcs if (x.lo < y.lo) 38951786Sdcs { 39051786Sdcs result.hi--; 39151786Sdcs } 39251786Sdcs 39351786Sdcs return result; 39451786Sdcs} 39551786Sdcs 39651786Sdcs 39751786Sdcs/************************************************************************** 39851786Sdcs m 6 4 A S L 39951786Sdcs** 64 bit left shift 40051786Sdcs**************************************************************************/ 40151786SdcsDPUNS m64ASL( DPUNS x ) 40251786Sdcs{ 40351786Sdcs DPUNS result; 40451786Sdcs 40551786Sdcs result.hi = x.hi << 1; 40651786Sdcs if (x.lo & CELL_HI_BIT) 40751786Sdcs { 40851786Sdcs result.hi++; 40951786Sdcs } 41051786Sdcs 41151786Sdcs result.lo = x.lo << 1; 41251786Sdcs 41351786Sdcs return result; 41451786Sdcs} 41551786Sdcs 41651786Sdcs 41751786Sdcs/************************************************************************** 41851786Sdcs m 6 4 A S R 41951786Sdcs** 64 bit right shift (unsigned - no sign extend) 42051786Sdcs**************************************************************************/ 42151786SdcsDPUNS m64ASR( DPUNS x ) 42251786Sdcs{ 42351786Sdcs DPUNS result; 42451786Sdcs 42551786Sdcs result.lo = x.lo >> 1; 42651786Sdcs if (x.hi & 1) 42751786Sdcs { 42851786Sdcs result.lo |= CELL_HI_BIT; 42951786Sdcs } 43051786Sdcs 43151786Sdcs result.hi = x.hi >> 1; 43251786Sdcs return result; 43351786Sdcs} 43451786Sdcs 43551786Sdcs 43651786Sdcs/************************************************************************** 43751786Sdcs m 6 4 O r 43851786Sdcs** 64 bit bitwise OR 43951786Sdcs**************************************************************************/ 44051786SdcsDPUNS m64Or( DPUNS x, DPUNS y ) 44151786Sdcs{ 44251786Sdcs DPUNS result; 44351786Sdcs 44451786Sdcs result.hi = x.hi | y.hi; 44551786Sdcs result.lo = x.lo | y.lo; 44651786Sdcs 44751786Sdcs return result; 44851786Sdcs} 44951786Sdcs 45051786Sdcs 45151786Sdcs/************************************************************************** 45251786Sdcs m 6 4 C o m p a r e 45351786Sdcs** Return -1 if x < y; 0 if x==y, and 1 if x > y. 45451786Sdcs**************************************************************************/ 45551786Sdcsint m64Compare(DPUNS x, DPUNS y) 45651786Sdcs{ 45751786Sdcs int result; 45851786Sdcs 45951786Sdcs if (x.hi > y.hi) 46051786Sdcs { 46151786Sdcs result = +1; 46251786Sdcs } 46351786Sdcs else if (x.hi < y.hi) 46451786Sdcs { 46551786Sdcs result = -1; 46651786Sdcs } 46751786Sdcs else 46851786Sdcs { 46951786Sdcs /* High parts are equal */ 47051786Sdcs if (x.lo > y.lo) 47151786Sdcs { 47251786Sdcs result = +1; 47351786Sdcs } 47451786Sdcs else if (x.lo < y.lo) 47551786Sdcs { 47651786Sdcs result = -1; 47751786Sdcs } 47851786Sdcs else 47951786Sdcs { 48051786Sdcs result = 0; 48151786Sdcs } 48251786Sdcs } 48351786Sdcs 48451786Sdcs return result; 48551786Sdcs} 48651786Sdcs 48751786Sdcs 48851786Sdcs/************************************************************************** 48951786Sdcs f i c l L o n g M u l 49051786Sdcs** Portable versions of ficlLongMul and ficlLongDiv in C 49151786Sdcs** Contributed by: 49276116Sdcs** Michael A. Gauland gaulandm@mdhost.cse.tek.com 49351786Sdcs**************************************************************************/ 49451786SdcsDPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) 49551786Sdcs{ 49651786Sdcs DPUNS result = { 0, 0 }; 49751786Sdcs DPUNS addend; 49851786Sdcs 49951786Sdcs addend.lo = y; 50051786Sdcs addend.hi = 0; /* No sign extension--arguments are unsigned */ 50151786Sdcs 50251786Sdcs while (x != 0) 50351786Sdcs { 50451786Sdcs if ( x & 1) 50551786Sdcs { 50651786Sdcs result = m64Add(result, addend); 50751786Sdcs } 50851786Sdcs x >>= 1; 50951786Sdcs addend = m64ASL(addend); 51051786Sdcs } 51151786Sdcs return result; 51251786Sdcs} 51351786Sdcs 51451786Sdcs 51551786Sdcs/************************************************************************** 51651786Sdcs f i c l L o n g D i v 51751786Sdcs** Portable versions of ficlLongMul and ficlLongDiv in C 51851786Sdcs** Contributed by: 51976116Sdcs** Michael A. Gauland gaulandm@mdhost.cse.tek.com 52051786Sdcs**************************************************************************/ 52151786SdcsUNSQR ficlLongDiv(DPUNS q, FICL_UNS y) 52251786Sdcs{ 52351786Sdcs UNSQR result; 52451786Sdcs DPUNS quotient; 52551786Sdcs DPUNS subtrahend; 52651786Sdcs DPUNS mask; 52751786Sdcs 52851786Sdcs quotient.lo = 0; 52951786Sdcs quotient.hi = 0; 53051786Sdcs 53151786Sdcs subtrahend.lo = y; 53251786Sdcs subtrahend.hi = 0; 53351786Sdcs 53451786Sdcs mask.lo = 1; 53551786Sdcs mask.hi = 0; 53651786Sdcs 53751786Sdcs while ((m64Compare(subtrahend, q) < 0) && 53851786Sdcs (subtrahend.hi & CELL_HI_BIT) == 0) 53951786Sdcs { 54051786Sdcs mask = m64ASL(mask); 54151786Sdcs subtrahend = m64ASL(subtrahend); 54251786Sdcs } 54351786Sdcs 54451786Sdcs while (mask.lo != 0 || mask.hi != 0) 54551786Sdcs { 54651786Sdcs if (m64Compare(subtrahend, q) <= 0) 54751786Sdcs { 54851786Sdcs q = m64Sub( q, subtrahend); 54951786Sdcs quotient = m64Or(quotient, mask); 55051786Sdcs } 55151786Sdcs mask = m64ASR(mask); 55251786Sdcs subtrahend = m64ASR(subtrahend); 55351786Sdcs } 55451786Sdcs 55551786Sdcs result.quot = quotient.lo; 55651786Sdcs result.rem = q.lo; 55751786Sdcs return result; 55851786Sdcs} 55951786Sdcs 56051786Sdcs#endif 56151786Sdcs 562