1*ca987d46SWarner Losh /*******************************************************************
2*ca987d46SWarner Losh ** m a t h 6 4 . c
3*ca987d46SWarner Losh ** Forth Inspired Command Language - 64 bit math support routines
4*ca987d46SWarner Losh ** Author: John Sadler (john_sadler@alum.mit.edu)
5*ca987d46SWarner Losh ** Created: 25 January 1998
6*ca987d46SWarner Losh ** Rev 2.03: Support for 128 bit DP math. This file really ouught to
7*ca987d46SWarner Losh ** be renamed!
8*ca987d46SWarner Losh ** $Id: math64.c,v 1.9 2001/12/05 07:21:34 jsadler Exp $
9*ca987d46SWarner Losh *******************************************************************/
10*ca987d46SWarner Losh /*
11*ca987d46SWarner Losh ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
12*ca987d46SWarner Losh ** All rights reserved.
13*ca987d46SWarner Losh **
14*ca987d46SWarner Losh ** Get the latest Ficl release at http://ficl.sourceforge.net
15*ca987d46SWarner Losh **
16*ca987d46SWarner Losh ** I am interested in hearing from anyone who uses ficl. If you have
17*ca987d46SWarner Losh ** a problem, a success story, a defect, an enhancement request, or
18*ca987d46SWarner Losh ** if you would like to contribute to the ficl release, please
19*ca987d46SWarner Losh ** contact me by email at the address above.
20*ca987d46SWarner Losh **
21*ca987d46SWarner Losh ** L I C E N S E and D I S C L A I M E R
22*ca987d46SWarner Losh **
23*ca987d46SWarner Losh ** Redistribution and use in source and binary forms, with or without
24*ca987d46SWarner Losh ** modification, are permitted provided that the following conditions
25*ca987d46SWarner Losh ** are met:
26*ca987d46SWarner Losh ** 1. Redistributions of source code must retain the above copyright
27*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer.
28*ca987d46SWarner Losh ** 2. Redistributions in binary form must reproduce the above copyright
29*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer in the
30*ca987d46SWarner Losh ** documentation and/or other materials provided with the distribution.
31*ca987d46SWarner Losh **
32*ca987d46SWarner Losh ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33*ca987d46SWarner Losh ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34*ca987d46SWarner Losh ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35*ca987d46SWarner Losh ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36*ca987d46SWarner Losh ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*ca987d46SWarner Losh ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*ca987d46SWarner Losh ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*ca987d46SWarner Losh ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40*ca987d46SWarner Losh ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41*ca987d46SWarner Losh ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42*ca987d46SWarner Losh ** SUCH DAMAGE.
43*ca987d46SWarner Losh */
44*ca987d46SWarner Losh
45*ca987d46SWarner Losh
46*ca987d46SWarner Losh #include "ficl.h"
47*ca987d46SWarner Losh #include "math64.h"
48*ca987d46SWarner Losh
49*ca987d46SWarner Losh
50*ca987d46SWarner Losh /**************************************************************************
51*ca987d46SWarner Losh m 6 4 A b s
52*ca987d46SWarner Losh ** Returns the absolute value of an DPINT
53*ca987d46SWarner Losh **************************************************************************/
m64Abs(DPINT x)54*ca987d46SWarner Losh DPINT m64Abs(DPINT x)
55*ca987d46SWarner Losh {
56*ca987d46SWarner Losh if (m64IsNegative(x))
57*ca987d46SWarner Losh x = m64Negate(x);
58*ca987d46SWarner Losh
59*ca987d46SWarner Losh return x;
60*ca987d46SWarner Losh }
61*ca987d46SWarner Losh
62*ca987d46SWarner Losh
63*ca987d46SWarner Losh /**************************************************************************
64*ca987d46SWarner Losh m 6 4 F l o o r e d D i v I
65*ca987d46SWarner Losh **
66*ca987d46SWarner Losh ** FROM THE FORTH ANS...
67*ca987d46SWarner Losh ** Floored division is integer division in which the remainder carries
68*ca987d46SWarner Losh ** the sign of the divisor or is zero, and the quotient is rounded to
69*ca987d46SWarner Losh ** its arithmetic floor. Symmetric division is integer division in which
70*ca987d46SWarner Losh ** the remainder carries the sign of the dividend or is zero and the
71*ca987d46SWarner Losh ** quotient is the mathematical quotient rounded towards zero or
72*ca987d46SWarner Losh ** truncated. Examples of each are shown in tables 3.3 and 3.4.
73*ca987d46SWarner Losh **
74*ca987d46SWarner Losh ** Table 3.3 - Floored Division Example
75*ca987d46SWarner Losh ** Dividend Divisor Remainder Quotient
76*ca987d46SWarner Losh ** -------- ------- --------- --------
77*ca987d46SWarner Losh ** 10 7 3 1
78*ca987d46SWarner Losh ** -10 7 4 -2
79*ca987d46SWarner Losh ** 10 -7 -4 -2
80*ca987d46SWarner Losh ** -10 -7 -3 1
81*ca987d46SWarner Losh **
82*ca987d46SWarner Losh **
83*ca987d46SWarner Losh ** Table 3.4 - Symmetric Division Example
84*ca987d46SWarner Losh ** Dividend Divisor Remainder Quotient
85*ca987d46SWarner Losh ** -------- ------- --------- --------
86*ca987d46SWarner Losh ** 10 7 3 1
87*ca987d46SWarner Losh ** -10 7 -3 -1
88*ca987d46SWarner Losh ** 10 -7 3 -1
89*ca987d46SWarner Losh ** -10 -7 -3 1
90*ca987d46SWarner Losh **************************************************************************/
m64FlooredDivI(DPINT num,FICL_INT den)91*ca987d46SWarner Losh INTQR m64FlooredDivI(DPINT num, FICL_INT den)
92*ca987d46SWarner Losh {
93*ca987d46SWarner Losh INTQR qr;
94*ca987d46SWarner Losh UNSQR uqr;
95*ca987d46SWarner Losh int signRem = 1;
96*ca987d46SWarner Losh int signQuot = 1;
97*ca987d46SWarner Losh
98*ca987d46SWarner Losh if (m64IsNegative(num))
99*ca987d46SWarner Losh {
100*ca987d46SWarner Losh num = m64Negate(num);
101*ca987d46SWarner Losh signQuot = -signQuot;
102*ca987d46SWarner Losh }
103*ca987d46SWarner Losh
104*ca987d46SWarner Losh if (den < 0)
105*ca987d46SWarner Losh {
106*ca987d46SWarner Losh den = -den;
107*ca987d46SWarner Losh signRem = -signRem;
108*ca987d46SWarner Losh signQuot = -signQuot;
109*ca987d46SWarner Losh }
110*ca987d46SWarner Losh
111*ca987d46SWarner Losh uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den);
112*ca987d46SWarner Losh qr = m64CastQRUI(uqr);
113*ca987d46SWarner Losh if (signQuot < 0)
114*ca987d46SWarner Losh {
115*ca987d46SWarner Losh qr.quot = -qr.quot;
116*ca987d46SWarner Losh if (qr.rem != 0)
117*ca987d46SWarner Losh {
118*ca987d46SWarner Losh qr.quot--;
119*ca987d46SWarner Losh qr.rem = den - qr.rem;
120*ca987d46SWarner Losh }
121*ca987d46SWarner Losh }
122*ca987d46SWarner Losh
123*ca987d46SWarner Losh if (signRem < 0)
124*ca987d46SWarner Losh qr.rem = -qr.rem;
125*ca987d46SWarner Losh
126*ca987d46SWarner Losh return qr;
127*ca987d46SWarner Losh }
128*ca987d46SWarner Losh
129*ca987d46SWarner Losh
130*ca987d46SWarner Losh /**************************************************************************
131*ca987d46SWarner Losh m 6 4 I s N e g a t i v e
132*ca987d46SWarner Losh ** Returns TRUE if the specified DPINT has its sign bit set.
133*ca987d46SWarner Losh **************************************************************************/
m64IsNegative(DPINT x)134*ca987d46SWarner Losh int m64IsNegative(DPINT x)
135*ca987d46SWarner Losh {
136*ca987d46SWarner Losh return (x.hi < 0);
137*ca987d46SWarner Losh }
138*ca987d46SWarner Losh
139*ca987d46SWarner Losh
140*ca987d46SWarner Losh /**************************************************************************
141*ca987d46SWarner Losh m 6 4 M a c
142*ca987d46SWarner Losh ** Mixed precision multiply and accumulate primitive for number building.
143*ca987d46SWarner Losh ** Multiplies DPUNS u by FICL_UNS mul and adds FICL_UNS add. Mul is typically
144*ca987d46SWarner Losh ** the numeric base, and add represents a digit to be appended to the
145*ca987d46SWarner Losh ** growing number.
146*ca987d46SWarner Losh ** Returns the result of the operation
147*ca987d46SWarner Losh **************************************************************************/
m64Mac(DPUNS u,FICL_UNS mul,FICL_UNS add)148*ca987d46SWarner Losh DPUNS m64Mac(DPUNS u, FICL_UNS mul, FICL_UNS add)
149*ca987d46SWarner Losh {
150*ca987d46SWarner Losh DPUNS resultLo = ficlLongMul(u.lo, mul);
151*ca987d46SWarner Losh DPUNS resultHi = ficlLongMul(u.hi, mul);
152*ca987d46SWarner Losh resultLo.hi += resultHi.lo;
153*ca987d46SWarner Losh resultHi.lo = resultLo.lo + add;
154*ca987d46SWarner Losh
155*ca987d46SWarner Losh if (resultHi.lo < resultLo.lo)
156*ca987d46SWarner Losh resultLo.hi++;
157*ca987d46SWarner Losh
158*ca987d46SWarner Losh resultLo.lo = resultHi.lo;
159*ca987d46SWarner Losh
160*ca987d46SWarner Losh return resultLo;
161*ca987d46SWarner Losh }
162*ca987d46SWarner Losh
163*ca987d46SWarner Losh
164*ca987d46SWarner Losh /**************************************************************************
165*ca987d46SWarner Losh m 6 4 M u l I
166*ca987d46SWarner Losh ** Multiplies a pair of FICL_INTs and returns an DPINT result.
167*ca987d46SWarner Losh **************************************************************************/
m64MulI(FICL_INT x,FICL_INT y)168*ca987d46SWarner Losh DPINT m64MulI(FICL_INT x, FICL_INT y)
169*ca987d46SWarner Losh {
170*ca987d46SWarner Losh DPUNS prod;
171*ca987d46SWarner Losh int sign = 1;
172*ca987d46SWarner Losh
173*ca987d46SWarner Losh if (x < 0)
174*ca987d46SWarner Losh {
175*ca987d46SWarner Losh sign = -sign;
176*ca987d46SWarner Losh x = -x;
177*ca987d46SWarner Losh }
178*ca987d46SWarner Losh
179*ca987d46SWarner Losh if (y < 0)
180*ca987d46SWarner Losh {
181*ca987d46SWarner Losh sign = -sign;
182*ca987d46SWarner Losh y = -y;
183*ca987d46SWarner Losh }
184*ca987d46SWarner Losh
185*ca987d46SWarner Losh prod = ficlLongMul(x, y);
186*ca987d46SWarner Losh if (sign > 0)
187*ca987d46SWarner Losh return m64CastUI(prod);
188*ca987d46SWarner Losh else
189*ca987d46SWarner Losh return m64Negate(m64CastUI(prod));
190*ca987d46SWarner Losh }
191*ca987d46SWarner Losh
192*ca987d46SWarner Losh
193*ca987d46SWarner Losh /**************************************************************************
194*ca987d46SWarner Losh m 6 4 N e g a t e
195*ca987d46SWarner Losh ** Negates an DPINT by complementing and incrementing.
196*ca987d46SWarner Losh **************************************************************************/
m64Negate(DPINT x)197*ca987d46SWarner Losh DPINT m64Negate(DPINT x)
198*ca987d46SWarner Losh {
199*ca987d46SWarner Losh x.hi = ~x.hi;
200*ca987d46SWarner Losh x.lo = ~x.lo;
201*ca987d46SWarner Losh x.lo ++;
202*ca987d46SWarner Losh if (x.lo == 0)
203*ca987d46SWarner Losh x.hi++;
204*ca987d46SWarner Losh
205*ca987d46SWarner Losh return x;
206*ca987d46SWarner Losh }
207*ca987d46SWarner Losh
208*ca987d46SWarner Losh
209*ca987d46SWarner Losh /**************************************************************************
210*ca987d46SWarner Losh m 6 4 P u s h
211*ca987d46SWarner Losh ** Push an DPINT onto the specified stack in the order required
212*ca987d46SWarner Losh ** by ANS Forth (most significant cell on top)
213*ca987d46SWarner Losh ** These should probably be macros...
214*ca987d46SWarner Losh **************************************************************************/
i64Push(FICL_STACK * pStack,DPINT i64)215*ca987d46SWarner Losh void i64Push(FICL_STACK *pStack, DPINT i64)
216*ca987d46SWarner Losh {
217*ca987d46SWarner Losh stackPushINT(pStack, i64.lo);
218*ca987d46SWarner Losh stackPushINT(pStack, i64.hi);
219*ca987d46SWarner Losh return;
220*ca987d46SWarner Losh }
221*ca987d46SWarner Losh
u64Push(FICL_STACK * pStack,DPUNS u64)222*ca987d46SWarner Losh void u64Push(FICL_STACK *pStack, DPUNS u64)
223*ca987d46SWarner Losh {
224*ca987d46SWarner Losh stackPushINT(pStack, u64.lo);
225*ca987d46SWarner Losh stackPushINT(pStack, u64.hi);
226*ca987d46SWarner Losh return;
227*ca987d46SWarner Losh }
228*ca987d46SWarner Losh
229*ca987d46SWarner Losh
230*ca987d46SWarner Losh /**************************************************************************
231*ca987d46SWarner Losh m 6 4 P o p
232*ca987d46SWarner Losh ** Pops an DPINT off the stack in the order required by ANS Forth
233*ca987d46SWarner Losh ** (most significant cell on top)
234*ca987d46SWarner Losh ** These should probably be macros...
235*ca987d46SWarner Losh **************************************************************************/
i64Pop(FICL_STACK * pStack)236*ca987d46SWarner Losh DPINT i64Pop(FICL_STACK *pStack)
237*ca987d46SWarner Losh {
238*ca987d46SWarner Losh DPINT ret;
239*ca987d46SWarner Losh ret.hi = stackPopINT(pStack);
240*ca987d46SWarner Losh ret.lo = stackPopINT(pStack);
241*ca987d46SWarner Losh return ret;
242*ca987d46SWarner Losh }
243*ca987d46SWarner Losh
u64Pop(FICL_STACK * pStack)244*ca987d46SWarner Losh DPUNS u64Pop(FICL_STACK *pStack)
245*ca987d46SWarner Losh {
246*ca987d46SWarner Losh DPUNS ret;
247*ca987d46SWarner Losh ret.hi = stackPopINT(pStack);
248*ca987d46SWarner Losh ret.lo = stackPopINT(pStack);
249*ca987d46SWarner Losh return ret;
250*ca987d46SWarner Losh }
251*ca987d46SWarner Losh
252*ca987d46SWarner Losh
253*ca987d46SWarner Losh /**************************************************************************
254*ca987d46SWarner Losh m 6 4 S y m m e t r i c D i v
255*ca987d46SWarner Losh ** Divide an DPINT by a FICL_INT and return a FICL_INT quotient and a
256*ca987d46SWarner Losh ** FICL_INT remainder. The absolute values of quotient and remainder are not
257*ca987d46SWarner Losh ** affected by the signs of the numerator and denominator (the operation
258*ca987d46SWarner Losh ** is symmetric on the number line)
259*ca987d46SWarner Losh **************************************************************************/
m64SymmetricDivI(DPINT num,FICL_INT den)260*ca987d46SWarner Losh INTQR m64SymmetricDivI(DPINT num, FICL_INT den)
261*ca987d46SWarner Losh {
262*ca987d46SWarner Losh INTQR qr;
263*ca987d46SWarner Losh UNSQR uqr;
264*ca987d46SWarner Losh int signRem = 1;
265*ca987d46SWarner Losh int signQuot = 1;
266*ca987d46SWarner Losh
267*ca987d46SWarner Losh if (m64IsNegative(num))
268*ca987d46SWarner Losh {
269*ca987d46SWarner Losh num = m64Negate(num);
270*ca987d46SWarner Losh signRem = -signRem;
271*ca987d46SWarner Losh signQuot = -signQuot;
272*ca987d46SWarner Losh }
273*ca987d46SWarner Losh
274*ca987d46SWarner Losh if (den < 0)
275*ca987d46SWarner Losh {
276*ca987d46SWarner Losh den = -den;
277*ca987d46SWarner Losh signQuot = -signQuot;
278*ca987d46SWarner Losh }
279*ca987d46SWarner Losh
280*ca987d46SWarner Losh uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den);
281*ca987d46SWarner Losh qr = m64CastQRUI(uqr);
282*ca987d46SWarner Losh if (signRem < 0)
283*ca987d46SWarner Losh qr.rem = -qr.rem;
284*ca987d46SWarner Losh
285*ca987d46SWarner Losh if (signQuot < 0)
286*ca987d46SWarner Losh qr.quot = -qr.quot;
287*ca987d46SWarner Losh
288*ca987d46SWarner Losh return qr;
289*ca987d46SWarner Losh }
290*ca987d46SWarner Losh
291*ca987d46SWarner Losh
292*ca987d46SWarner Losh /**************************************************************************
293*ca987d46SWarner Losh m 6 4 U M o d
294*ca987d46SWarner Losh ** Divides a DPUNS by base (an UNS16) and returns an UNS16 remainder.
295*ca987d46SWarner Losh ** Writes the quotient back to the original DPUNS as a side effect.
296*ca987d46SWarner Losh ** This operation is typically used to convert an DPUNS to a text string
297*ca987d46SWarner Losh ** in any base. See words.c:numberSignS, for example.
298*ca987d46SWarner Losh ** Mechanics: performs 4 ficlLongDivs, each of which produces 16 bits
299*ca987d46SWarner Losh ** of the quotient. C does not provide a way to divide an FICL_UNS by an
300*ca987d46SWarner Losh ** UNS16 and get an FICL_UNS quotient (ldiv is closest, but it's signed,
301*ca987d46SWarner Losh ** unfortunately), so I've used ficlLongDiv.
302*ca987d46SWarner Losh **************************************************************************/
303*ca987d46SWarner Losh #if (BITS_PER_CELL == 32)
304*ca987d46SWarner Losh
305*ca987d46SWarner Losh #define UMOD_SHIFT 16
306*ca987d46SWarner Losh #define UMOD_MASK 0x0000ffff
307*ca987d46SWarner Losh
308*ca987d46SWarner Losh #elif (BITS_PER_CELL == 64)
309*ca987d46SWarner Losh
310*ca987d46SWarner Losh #define UMOD_SHIFT 32
311*ca987d46SWarner Losh #define UMOD_MASK 0x00000000ffffffff
312*ca987d46SWarner Losh
313*ca987d46SWarner Losh #endif
314*ca987d46SWarner Losh
m64UMod(DPUNS * pUD,UNS16 base)315*ca987d46SWarner Losh UNS16 m64UMod(DPUNS *pUD, UNS16 base)
316*ca987d46SWarner Losh {
317*ca987d46SWarner Losh DPUNS ud;
318*ca987d46SWarner Losh UNSQR qr;
319*ca987d46SWarner Losh DPUNS result;
320*ca987d46SWarner Losh
321*ca987d46SWarner Losh result.hi = result.lo = 0;
322*ca987d46SWarner Losh
323*ca987d46SWarner Losh ud.hi = 0;
324*ca987d46SWarner Losh ud.lo = pUD->hi >> UMOD_SHIFT;
325*ca987d46SWarner Losh qr = ficlLongDiv(ud, (FICL_UNS)base);
326*ca987d46SWarner Losh result.hi = qr.quot << UMOD_SHIFT;
327*ca987d46SWarner Losh
328*ca987d46SWarner Losh ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->hi & UMOD_MASK);
329*ca987d46SWarner Losh qr = ficlLongDiv(ud, (FICL_UNS)base);
330*ca987d46SWarner Losh result.hi |= qr.quot & UMOD_MASK;
331*ca987d46SWarner Losh
332*ca987d46SWarner Losh ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo >> UMOD_SHIFT);
333*ca987d46SWarner Losh qr = ficlLongDiv(ud, (FICL_UNS)base);
334*ca987d46SWarner Losh result.lo = qr.quot << UMOD_SHIFT;
335*ca987d46SWarner Losh
336*ca987d46SWarner Losh ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo & UMOD_MASK);
337*ca987d46SWarner Losh qr = ficlLongDiv(ud, (FICL_UNS)base);
338*ca987d46SWarner Losh result.lo |= qr.quot & UMOD_MASK;
339*ca987d46SWarner Losh
340*ca987d46SWarner Losh *pUD = result;
341*ca987d46SWarner Losh
342*ca987d46SWarner Losh return (UNS16)(qr.rem);
343*ca987d46SWarner Losh }
344*ca987d46SWarner Losh
345*ca987d46SWarner Losh
346*ca987d46SWarner Losh /**************************************************************************
347*ca987d46SWarner Losh ** Contributed by
348*ca987d46SWarner Losh ** Michael A. Gauland gaulandm@mdhost.cse.tek.com
349*ca987d46SWarner Losh **************************************************************************/
350*ca987d46SWarner Losh #if PORTABLE_LONGMULDIV != 0
351*ca987d46SWarner Losh /**************************************************************************
352*ca987d46SWarner Losh m 6 4 A d d
353*ca987d46SWarner Losh **
354*ca987d46SWarner Losh **************************************************************************/
m64Add(DPUNS x,DPUNS y)355*ca987d46SWarner Losh DPUNS m64Add(DPUNS x, DPUNS y)
356*ca987d46SWarner Losh {
357*ca987d46SWarner Losh DPUNS result;
358*ca987d46SWarner Losh int carry;
359*ca987d46SWarner Losh
360*ca987d46SWarner Losh result.hi = x.hi + y.hi;
361*ca987d46SWarner Losh result.lo = x.lo + y.lo;
362*ca987d46SWarner Losh
363*ca987d46SWarner Losh
364*ca987d46SWarner Losh carry = ((x.lo | y.lo) & CELL_HI_BIT) && !(result.lo & CELL_HI_BIT);
365*ca987d46SWarner Losh carry |= ((x.lo & y.lo) & CELL_HI_BIT);
366*ca987d46SWarner Losh
367*ca987d46SWarner Losh if (carry)
368*ca987d46SWarner Losh {
369*ca987d46SWarner Losh result.hi++;
370*ca987d46SWarner Losh }
371*ca987d46SWarner Losh
372*ca987d46SWarner Losh return result;
373*ca987d46SWarner Losh }
374*ca987d46SWarner Losh
375*ca987d46SWarner Losh
376*ca987d46SWarner Losh /**************************************************************************
377*ca987d46SWarner Losh m 6 4 S u b
378*ca987d46SWarner Losh **
379*ca987d46SWarner Losh **************************************************************************/
m64Sub(DPUNS x,DPUNS y)380*ca987d46SWarner Losh DPUNS m64Sub(DPUNS x, DPUNS y)
381*ca987d46SWarner Losh {
382*ca987d46SWarner Losh DPUNS result;
383*ca987d46SWarner Losh
384*ca987d46SWarner Losh result.hi = x.hi - y.hi;
385*ca987d46SWarner Losh result.lo = x.lo - y.lo;
386*ca987d46SWarner Losh
387*ca987d46SWarner Losh if (x.lo < y.lo)
388*ca987d46SWarner Losh {
389*ca987d46SWarner Losh result.hi--;
390*ca987d46SWarner Losh }
391*ca987d46SWarner Losh
392*ca987d46SWarner Losh return result;
393*ca987d46SWarner Losh }
394*ca987d46SWarner Losh
395*ca987d46SWarner Losh
396*ca987d46SWarner Losh /**************************************************************************
397*ca987d46SWarner Losh m 6 4 A S L
398*ca987d46SWarner Losh ** 64 bit left shift
399*ca987d46SWarner Losh **************************************************************************/
m64ASL(DPUNS x)400*ca987d46SWarner Losh DPUNS m64ASL( DPUNS x )
401*ca987d46SWarner Losh {
402*ca987d46SWarner Losh DPUNS result;
403*ca987d46SWarner Losh
404*ca987d46SWarner Losh result.hi = x.hi << 1;
405*ca987d46SWarner Losh if (x.lo & CELL_HI_BIT)
406*ca987d46SWarner Losh {
407*ca987d46SWarner Losh result.hi++;
408*ca987d46SWarner Losh }
409*ca987d46SWarner Losh
410*ca987d46SWarner Losh result.lo = x.lo << 1;
411*ca987d46SWarner Losh
412*ca987d46SWarner Losh return result;
413*ca987d46SWarner Losh }
414*ca987d46SWarner Losh
415*ca987d46SWarner Losh
416*ca987d46SWarner Losh /**************************************************************************
417*ca987d46SWarner Losh m 6 4 A S R
418*ca987d46SWarner Losh ** 64 bit right shift (unsigned - no sign extend)
419*ca987d46SWarner Losh **************************************************************************/
m64ASR(DPUNS x)420*ca987d46SWarner Losh DPUNS m64ASR( DPUNS x )
421*ca987d46SWarner Losh {
422*ca987d46SWarner Losh DPUNS result;
423*ca987d46SWarner Losh
424*ca987d46SWarner Losh result.lo = x.lo >> 1;
425*ca987d46SWarner Losh if (x.hi & 1)
426*ca987d46SWarner Losh {
427*ca987d46SWarner Losh result.lo |= CELL_HI_BIT;
428*ca987d46SWarner Losh }
429*ca987d46SWarner Losh
430*ca987d46SWarner Losh result.hi = x.hi >> 1;
431*ca987d46SWarner Losh return result;
432*ca987d46SWarner Losh }
433*ca987d46SWarner Losh
434*ca987d46SWarner Losh
435*ca987d46SWarner Losh /**************************************************************************
436*ca987d46SWarner Losh m 6 4 O r
437*ca987d46SWarner Losh ** 64 bit bitwise OR
438*ca987d46SWarner Losh **************************************************************************/
m64Or(DPUNS x,DPUNS y)439*ca987d46SWarner Losh DPUNS m64Or( DPUNS x, DPUNS y )
440*ca987d46SWarner Losh {
441*ca987d46SWarner Losh DPUNS result;
442*ca987d46SWarner Losh
443*ca987d46SWarner Losh result.hi = x.hi | y.hi;
444*ca987d46SWarner Losh result.lo = x.lo | y.lo;
445*ca987d46SWarner Losh
446*ca987d46SWarner Losh return result;
447*ca987d46SWarner Losh }
448*ca987d46SWarner Losh
449*ca987d46SWarner Losh
450*ca987d46SWarner Losh /**************************************************************************
451*ca987d46SWarner Losh m 6 4 C o m p a r e
452*ca987d46SWarner Losh ** Return -1 if x < y; 0 if x==y, and 1 if x > y.
453*ca987d46SWarner Losh **************************************************************************/
m64Compare(DPUNS x,DPUNS y)454*ca987d46SWarner Losh int m64Compare(DPUNS x, DPUNS y)
455*ca987d46SWarner Losh {
456*ca987d46SWarner Losh int result;
457*ca987d46SWarner Losh
458*ca987d46SWarner Losh if (x.hi > y.hi)
459*ca987d46SWarner Losh {
460*ca987d46SWarner Losh result = +1;
461*ca987d46SWarner Losh }
462*ca987d46SWarner Losh else if (x.hi < y.hi)
463*ca987d46SWarner Losh {
464*ca987d46SWarner Losh result = -1;
465*ca987d46SWarner Losh }
466*ca987d46SWarner Losh else
467*ca987d46SWarner Losh {
468*ca987d46SWarner Losh /* High parts are equal */
469*ca987d46SWarner Losh if (x.lo > y.lo)
470*ca987d46SWarner Losh {
471*ca987d46SWarner Losh result = +1;
472*ca987d46SWarner Losh }
473*ca987d46SWarner Losh else if (x.lo < y.lo)
474*ca987d46SWarner Losh {
475*ca987d46SWarner Losh result = -1;
476*ca987d46SWarner Losh }
477*ca987d46SWarner Losh else
478*ca987d46SWarner Losh {
479*ca987d46SWarner Losh result = 0;
480*ca987d46SWarner Losh }
481*ca987d46SWarner Losh }
482*ca987d46SWarner Losh
483*ca987d46SWarner Losh return result;
484*ca987d46SWarner Losh }
485*ca987d46SWarner Losh
486*ca987d46SWarner Losh
487*ca987d46SWarner Losh /**************************************************************************
488*ca987d46SWarner Losh f i c l L o n g M u l
489*ca987d46SWarner Losh ** Portable versions of ficlLongMul and ficlLongDiv in C
490*ca987d46SWarner Losh ** Contributed by:
491*ca987d46SWarner Losh ** Michael A. Gauland gaulandm@mdhost.cse.tek.com
492*ca987d46SWarner Losh **************************************************************************/
ficlLongMul(FICL_UNS x,FICL_UNS y)493*ca987d46SWarner Losh DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
494*ca987d46SWarner Losh {
495*ca987d46SWarner Losh DPUNS result = { 0, 0 };
496*ca987d46SWarner Losh DPUNS addend;
497*ca987d46SWarner Losh
498*ca987d46SWarner Losh addend.lo = y;
499*ca987d46SWarner Losh addend.hi = 0; /* No sign extension--arguments are unsigned */
500*ca987d46SWarner Losh
501*ca987d46SWarner Losh while (x != 0)
502*ca987d46SWarner Losh {
503*ca987d46SWarner Losh if ( x & 1)
504*ca987d46SWarner Losh {
505*ca987d46SWarner Losh result = m64Add(result, addend);
506*ca987d46SWarner Losh }
507*ca987d46SWarner Losh x >>= 1;
508*ca987d46SWarner Losh addend = m64ASL(addend);
509*ca987d46SWarner Losh }
510*ca987d46SWarner Losh return result;
511*ca987d46SWarner Losh }
512*ca987d46SWarner Losh
513*ca987d46SWarner Losh
514*ca987d46SWarner Losh /**************************************************************************
515*ca987d46SWarner Losh f i c l L o n g D i v
516*ca987d46SWarner Losh ** Portable versions of ficlLongMul and ficlLongDiv in C
517*ca987d46SWarner Losh ** Contributed by:
518*ca987d46SWarner Losh ** Michael A. Gauland gaulandm@mdhost.cse.tek.com
519*ca987d46SWarner Losh **************************************************************************/
ficlLongDiv(DPUNS q,FICL_UNS y)520*ca987d46SWarner Losh UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
521*ca987d46SWarner Losh {
522*ca987d46SWarner Losh UNSQR result;
523*ca987d46SWarner Losh DPUNS quotient;
524*ca987d46SWarner Losh DPUNS subtrahend;
525*ca987d46SWarner Losh DPUNS mask;
526*ca987d46SWarner Losh
527*ca987d46SWarner Losh quotient.lo = 0;
528*ca987d46SWarner Losh quotient.hi = 0;
529*ca987d46SWarner Losh
530*ca987d46SWarner Losh subtrahend.lo = y;
531*ca987d46SWarner Losh subtrahend.hi = 0;
532*ca987d46SWarner Losh
533*ca987d46SWarner Losh mask.lo = 1;
534*ca987d46SWarner Losh mask.hi = 0;
535*ca987d46SWarner Losh
536*ca987d46SWarner Losh while ((m64Compare(subtrahend, q) < 0) &&
537*ca987d46SWarner Losh (subtrahend.hi & CELL_HI_BIT) == 0)
538*ca987d46SWarner Losh {
539*ca987d46SWarner Losh mask = m64ASL(mask);
540*ca987d46SWarner Losh subtrahend = m64ASL(subtrahend);
541*ca987d46SWarner Losh }
542*ca987d46SWarner Losh
543*ca987d46SWarner Losh while (mask.lo != 0 || mask.hi != 0)
544*ca987d46SWarner Losh {
545*ca987d46SWarner Losh if (m64Compare(subtrahend, q) <= 0)
546*ca987d46SWarner Losh {
547*ca987d46SWarner Losh q = m64Sub( q, subtrahend);
548*ca987d46SWarner Losh quotient = m64Or(quotient, mask);
549*ca987d46SWarner Losh }
550*ca987d46SWarner Losh mask = m64ASR(mask);
551*ca987d46SWarner Losh subtrahend = m64ASR(subtrahend);
552*ca987d46SWarner Losh }
553*ca987d46SWarner Losh
554*ca987d46SWarner Losh result.quot = quotient.lo;
555*ca987d46SWarner Losh result.rem = q.lo;
556*ca987d46SWarner Losh return result;
557*ca987d46SWarner Losh }
558*ca987d46SWarner Losh
559*ca987d46SWarner Losh #endif
560*ca987d46SWarner Losh
561