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