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