1 |
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 |
/* ***** BEGIN LICENSE BLOCK ***** |
3 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 |
* |
5 |
* The contents of this file are subject to the Mozilla Public License Version |
6 |
* 1.1 (the "License"); you may not use this file except in compliance with |
7 |
* the License. You may obtain a copy of the License at |
8 |
* http://www.mozilla.org/MPL/ |
9 |
* |
10 |
* Software distributed under the License is distributed on an "AS IS" basis, |
11 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
12 |
* for the specific language governing rights and limitations under the |
13 |
* License. |
14 |
* |
15 |
* The Original Code is Mozilla Communicator client code, released |
16 |
* March 31, 1998. |
17 |
* |
18 |
* The Initial Developer of the Original Code is |
19 |
* Netscape Communications Corporation. |
20 |
* Portions created by the Initial Developer are Copyright (C) 1998 |
21 |
* the Initial Developer. All Rights Reserved. |
22 |
* |
23 |
* Contributor(s): |
24 |
* |
25 |
* Alternatively, the contents of this file may be used under the terms of |
26 |
* either of the GNU General Public License Version 2 or later (the "GPL"), |
27 |
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
28 |
* in which case the provisions of the GPL or the LGPL are applicable instead |
29 |
* of those above. If you wish to allow use of your version of this file only |
30 |
* under the terms of either the GPL or the LGPL, and not to allow others to |
31 |
* use your version of this file under the terms of the MPL, indicate your |
32 |
* decision by deleting the provisions above and replace them with the notice |
33 |
* and other provisions required by the GPL or the LGPL. If you do not delete |
34 |
* the provisions above, a recipient may use your version of this file under |
35 |
* the terms of any one of the MPL, the GPL or the LGPL. |
36 |
* |
37 |
* ***** END LICENSE BLOCK ***** */ |
38 |
|
39 |
/* |
40 |
** File: jslong.h |
41 |
** Description: Portable access to 64 bit numerics |
42 |
** |
43 |
** Long-long (64-bit signed integer type) support. Some C compilers |
44 |
** don't support 64 bit integers yet, so we use these macros to |
45 |
** support both machines that do and don't. |
46 |
**/ |
47 |
#ifndef jslong_h___ |
48 |
#define jslong_h___ |
49 |
|
50 |
#include "jstypes.h" |
51 |
|
52 |
JS_BEGIN_EXTERN_C |
53 |
|
54 |
#ifdef JS_HAVE_LONG_LONG |
55 |
|
56 |
#if JS_BYTES_PER_LONG == 8 |
57 |
#define JSLL_INIT(hi, lo) ((hi ## L << 32) + lo ## L) |
58 |
#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__) |
59 |
#define JSLL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64) |
60 |
#else |
61 |
#define JSLL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL) |
62 |
#endif |
63 |
|
64 |
/*********************************************************************** |
65 |
** MACROS: JSLL_* |
66 |
** DESCRIPTION: |
67 |
** The following macros define portable access to the 64 bit |
68 |
** math facilities. |
69 |
** |
70 |
***********************************************************************/ |
71 |
|
72 |
/*********************************************************************** |
73 |
** MACROS: JSLL_<relational operators> |
74 |
** |
75 |
** JSLL_IS_ZERO Test for zero |
76 |
** JSLL_EQ Test for equality |
77 |
** JSLL_NE Test for inequality |
78 |
** JSLL_GE_ZERO Test for zero or positive |
79 |
** JSLL_CMP Compare two values |
80 |
***********************************************************************/ |
81 |
#define JSLL_IS_ZERO(a) ((a) == 0) |
82 |
#define JSLL_EQ(a, b) ((a) == (b)) |
83 |
#define JSLL_NE(a, b) ((a) != (b)) |
84 |
#define JSLL_GE_ZERO(a) ((a) >= 0) |
85 |
#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b)) |
86 |
#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b)) |
87 |
|
88 |
/*********************************************************************** |
89 |
** MACROS: JSLL_<logical operators> |
90 |
** |
91 |
** JSLL_AND Logical and |
92 |
** JSLL_OR Logical or |
93 |
** JSLL_XOR Logical exclusion |
94 |
** JSLL_OR2 A disgusting deviation |
95 |
** JSLL_NOT Negation (one's compliment) |
96 |
***********************************************************************/ |
97 |
#define JSLL_AND(r, a, b) ((r) = (a) & (b)) |
98 |
#define JSLL_OR(r, a, b) ((r) = (a) | (b)) |
99 |
#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b)) |
100 |
#define JSLL_OR2(r, a) ((r) = (r) | (a)) |
101 |
#define JSLL_NOT(r, a) ((r) = ~(a)) |
102 |
|
103 |
/*********************************************************************** |
104 |
** MACROS: JSLL_<mathematical operators> |
105 |
** |
106 |
** JSLL_NEG Negation (two's compliment) |
107 |
** JSLL_ADD Summation (two's compliment) |
108 |
** JSLL_SUB Difference (two's compliment) |
109 |
***********************************************************************/ |
110 |
#define JSLL_NEG(r, a) ((r) = -(a)) |
111 |
#define JSLL_ADD(r, a, b) ((r) = (a) + (b)) |
112 |
#define JSLL_SUB(r, a, b) ((r) = (a) - (b)) |
113 |
|
114 |
/*********************************************************************** |
115 |
** MACROS: JSLL_<mathematical operators> |
116 |
** |
117 |
** JSLL_MUL Product (two's compliment) |
118 |
** JSLL_DIV Quotient (two's compliment) |
119 |
** JSLL_MOD Modulus (two's compliment) |
120 |
***********************************************************************/ |
121 |
#define JSLL_MUL(r, a, b) ((r) = (a) * (b)) |
122 |
#define JSLL_DIV(r, a, b) ((r) = (a) / (b)) |
123 |
#define JSLL_MOD(r, a, b) ((r) = (a) % (b)) |
124 |
|
125 |
/*********************************************************************** |
126 |
** MACROS: JSLL_<shifting operators> |
127 |
** |
128 |
** JSLL_SHL Shift left [0..64] bits |
129 |
** JSLL_SHR Shift right [0..64] bits with sign extension |
130 |
** JSLL_USHR Unsigned shift right [0..64] bits |
131 |
** JSLL_ISHL Signed shift left [0..64] bits |
132 |
***********************************************************************/ |
133 |
#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b)) |
134 |
#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b)) |
135 |
#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b)) |
136 |
#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b)) |
137 |
|
138 |
/*********************************************************************** |
139 |
** MACROS: JSLL_<conversion operators> |
140 |
** |
141 |
** JSLL_L2I Convert to signed 32 bit |
142 |
** JSLL_L2UI Convert to unsigned 32 bit |
143 |
** JSLL_L2F Convert to floating point |
144 |
** JSLL_L2D Convert to floating point |
145 |
** JSLL_I2L Convert signed to 64 bit |
146 |
** JSLL_UI2L Convert unsigned to 64 bit |
147 |
** JSLL_F2L Convert float to 64 bit |
148 |
** JSLL_D2L Convert float to 64 bit |
149 |
***********************************************************************/ |
150 |
#define JSLL_L2I(i, l) ((i) = (JSInt32)(l)) |
151 |
#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l)) |
152 |
#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l)) |
153 |
#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l)) |
154 |
|
155 |
#define JSLL_I2L(l, i) ((l) = (JSInt64)(i)) |
156 |
#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui)) |
157 |
#define JSLL_F2L(l, f) ((l) = (JSInt64)(f)) |
158 |
#define JSLL_D2L(l, d) ((l) = (JSInt64)(d)) |
159 |
|
160 |
/*********************************************************************** |
161 |
** MACROS: JSLL_UDIVMOD |
162 |
** DESCRIPTION: |
163 |
** Produce both a quotient and a remainder given an unsigned |
164 |
** INPUTS: JSUint64 a: The dividend of the operation |
165 |
** JSUint64 b: The quotient of the operation |
166 |
** OUTPUTS: JSUint64 *qp: pointer to quotient |
167 |
** JSUint64 *rp: pointer to remainder |
168 |
***********************************************************************/ |
169 |
#define JSLL_UDIVMOD(qp, rp, a, b) \ |
170 |
(*(qp) = ((JSUint64)(a) / (b)), \ |
171 |
*(rp) = ((JSUint64)(a) % (b))) |
172 |
|
173 |
#else /* !JS_HAVE_LONG_LONG */ |
174 |
|
175 |
#ifdef IS_LITTLE_ENDIAN |
176 |
#define JSLL_INIT(hi, lo) {JS_INT32(lo), JS_INT32(hi)} |
177 |
#else |
178 |
#define JSLL_INIT(hi, lo) {JS_INT32(hi), JS_INT32(lo)} |
179 |
#endif |
180 |
|
181 |
#define JSLL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) |
182 |
#define JSLL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) |
183 |
#define JSLL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) |
184 |
#define JSLL_GE_ZERO(a) (((a).hi >> 31) == 0) |
185 |
|
186 |
#ifdef DEBUG |
187 |
#define JSLL_CMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_CMP(a, op, b)) |
188 |
#define JSLL_UCMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_UCMP(a, op, b)) |
189 |
#else |
190 |
#define JSLL_CMP(a, op, b) JSLL_REAL_CMP(a, op, b) |
191 |
#define JSLL_UCMP(a, op, b) JSLL_REAL_UCMP(a, op, b) |
192 |
#endif |
193 |
|
194 |
#define JSLL_REAL_CMP(a,op,b) (((JSInt32)(a).hi op (JSInt32)(b).hi) || \ |
195 |
(((a).hi == (b).hi) && ((a).lo op (b).lo))) |
196 |
#define JSLL_REAL_UCMP(a,op,b) (((a).hi op (b).hi) || \ |
197 |
(((a).hi == (b).hi) && ((a).lo op (b).lo))) |
198 |
|
199 |
#define JSLL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ |
200 |
(r).hi = (a).hi & (b).hi) |
201 |
#define JSLL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ |
202 |
(r).hi = (a).hi | (b).hi) |
203 |
#define JSLL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ |
204 |
(r).hi = (a).hi ^ (b).hi) |
205 |
#define JSLL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ |
206 |
(r).hi = (r).hi | (a).hi) |
207 |
#define JSLL_NOT(r, a) ((r).lo = ~(a).lo, \ |
208 |
(r).hi = ~(a).hi) |
209 |
|
210 |
#define JSLL_NEG(r, a) ((r).lo = -(JSInt32)(a).lo, \ |
211 |
(r).hi = -(JSInt32)(a).hi - ((r).lo != 0)) |
212 |
#define JSLL_ADD(r, a, b) { \ |
213 |
JSInt64 _a, _b; \ |
214 |
_a = a; _b = b; \ |
215 |
(r).lo = _a.lo + _b.lo; \ |
216 |
(r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ |
217 |
} |
218 |
|
219 |
#define JSLL_SUB(r, a, b) { \ |
220 |
JSInt64 _a, _b; \ |
221 |
_a = a; _b = b; \ |
222 |
(r).lo = _a.lo - _b.lo; \ |
223 |
(r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ |
224 |
} |
225 |
|
226 |
#define JSLL_MUL(r, a, b) { \ |
227 |
JSInt64 _a, _b; \ |
228 |
_a = a; _b = b; \ |
229 |
JSLL_MUL32(r, _a.lo, _b.lo); \ |
230 |
(r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ |
231 |
} |
232 |
|
233 |
#define jslo16(a) ((a) & JS_BITMASK(16)) |
234 |
#define jshi16(a) ((a) >> 16) |
235 |
|
236 |
#define JSLL_MUL32(r, a, b) { \ |
237 |
JSUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ |
238 |
_a1 = jshi16(a), _a0 = jslo16(a); \ |
239 |
_b1 = jshi16(b), _b0 = jslo16(b); \ |
240 |
_y0 = _a0 * _b0; \ |
241 |
_y1 = _a0 * _b1; \ |
242 |
_y2 = _a1 * _b0; \ |
243 |
_y3 = _a1 * _b1; \ |
244 |
_y1 += jshi16(_y0); /* can't carry */ \ |
245 |
_y1 += _y2; /* might carry */ \ |
246 |
if (_y1 < _y2) \ |
247 |
_y3 += (JSUint32)(JS_BIT(16)); /* propagate */ \ |
248 |
(r).lo = (jslo16(_y1) << 16) + jslo16(_y0); \ |
249 |
(r).hi = _y3 + jshi16(_y1); \ |
250 |
} |
251 |
|
252 |
#define JSLL_UDIVMOD(qp, rp, a, b) jsll_udivmod(qp, rp, a, b) |
253 |
|
254 |
extern JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b); |
255 |
|
256 |
#define JSLL_DIV(r, a, b) { \ |
257 |
JSInt64 _a, _b; \ |
258 |
JSUint32 _negative = (JSInt32)(a).hi < 0; \ |
259 |
if (_negative) { \ |
260 |
JSLL_NEG(_a, a); \ |
261 |
} else { \ |
262 |
_a = a; \ |
263 |
} \ |
264 |
if ((JSInt32)(b).hi < 0) { \ |
265 |
_negative ^= 1; \ |
266 |
JSLL_NEG(_b, b); \ |
267 |
} else { \ |
268 |
_b = b; \ |
269 |
} \ |
270 |
JSLL_UDIVMOD(&(r), 0, _a, _b); \ |
271 |
if (_negative) \ |
272 |
JSLL_NEG(r, r); \ |
273 |
} |
274 |
|
275 |
#define JSLL_MOD(r, a, b) { \ |
276 |
JSInt64 _a, _b; \ |
277 |
JSUint32 _negative = (JSInt32)(a).hi < 0; \ |
278 |
if (_negative) { \ |
279 |
JSLL_NEG(_a, a); \ |
280 |
} else { \ |
281 |
_a = a; \ |
282 |
} \ |
283 |
if ((JSInt32)(b).hi < 0) { \ |
284 |
JSLL_NEG(_b, b); \ |
285 |
} else { \ |
286 |
_b = b; \ |
287 |
} \ |
288 |
JSLL_UDIVMOD(0, &(r), _a, _b); \ |
289 |
if (_negative) \ |
290 |
JSLL_NEG(r, r); \ |
291 |
} |
292 |
|
293 |
#define JSLL_SHL(r, a, b) { \ |
294 |
if (b) { \ |
295 |
JSInt64 _a; \ |
296 |
_a = a; \ |
297 |
if ((b) < 32) { \ |
298 |
(r).lo = _a.lo << ((b) & 31); \ |
299 |
(r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \ |
300 |
} else { \ |
301 |
(r).lo = 0; \ |
302 |
(r).hi = _a.lo << ((b) & 31); \ |
303 |
} \ |
304 |
} else { \ |
305 |
(r) = (a); \ |
306 |
} \ |
307 |
} |
308 |
|
309 |
/* a is an JSInt32, b is JSInt32, r is JSInt64 */ |
310 |
#define JSLL_ISHL(r, a, b) { \ |
311 |
if (b) { \ |
312 |
JSInt64 _a; \ |
313 |
_a.lo = (a); \ |
314 |
_a.hi = 0; \ |
315 |
if ((b) < 32) { \ |
316 |
(r).lo = (a) << ((b) & 31); \ |
317 |
(r).hi = ((a) >> (32 - (b))); \ |
318 |
} else { \ |
319 |
(r).lo = 0; \ |
320 |
(r).hi = (a) << ((b) & 31); \ |
321 |
} \ |
322 |
} else { \ |
323 |
(r).lo = (a); \ |
324 |
(r).hi = 0; \ |
325 |
} \ |
326 |
} |
327 |
|
328 |
#define JSLL_SHR(r, a, b) { \ |
329 |
if (b) { \ |
330 |
JSInt64 _a; \ |
331 |
_a = a; \ |
332 |
if ((b) < 32) { \ |
333 |
(r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ |
334 |
(r).hi = (JSInt32)_a.hi >> ((b) & 31); \ |
335 |
} else { \ |
336 |
(r).lo = (JSInt32)_a.hi >> ((b) & 31); \ |
337 |
(r).hi = (JSInt32)_a.hi >> 31; \ |
338 |
} \ |
339 |
} else { \ |
340 |
(r) = (a); \ |
341 |
} \ |
342 |
} |
343 |
|
344 |
#define JSLL_USHR(r, a, b) { \ |
345 |
if (b) { \ |
346 |
JSInt64 _a; \ |
347 |
_a = a; \ |
348 |
if ((b) < 32) { \ |
349 |
(r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ |
350 |
(r).hi = _a.hi >> ((b) & 31); \ |
351 |
} else { \ |
352 |
(r).lo = _a.hi >> ((b) & 31); \ |
353 |
(r).hi = 0; \ |
354 |
} \ |
355 |
} else { \ |
356 |
(r) = (a); \ |
357 |
} \ |
358 |
} |
359 |
|
360 |
#define JSLL_L2I(i, l) ((i) = (l).lo) |
361 |
#define JSLL_L2UI(ui, l) ((ui) = (l).lo) |
362 |
#define JSLL_L2F(f, l) { double _d; JSLL_L2D(_d, l); (f) = (JSFloat64)_d; } |
363 |
|
364 |
#define JSLL_L2D(d, l) { \ |
365 |
int _negative; \ |
366 |
JSInt64 _absval; \ |
367 |
\ |
368 |
_negative = (l).hi >> 31; \ |
369 |
if (_negative) { \ |
370 |
JSLL_NEG(_absval, l); \ |
371 |
} else { \ |
372 |
_absval = l; \ |
373 |
} \ |
374 |
(d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ |
375 |
if (_negative) \ |
376 |
(d) = -(d); \ |
377 |
} |
378 |
|
379 |
#define JSLL_I2L(l, i) { JSInt32 _i = (i) >> 31; (l).lo = (i); (l).hi = _i; } |
380 |
#define JSLL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0) |
381 |
#define JSLL_F2L(l, f) { double _d = (double)f; JSLL_D2L(l, _d); } |
382 |
|
383 |
#define JSLL_D2L(l, d) { \ |
384 |
int _negative; \ |
385 |
double _absval, _d_hi; \ |
386 |
JSInt64 _lo_d; \ |
387 |
\ |
388 |
_negative = ((d) < 0); \ |
389 |
_absval = _negative ? -(d) : (d); \ |
390 |
\ |
391 |
(l).hi = _absval / 4.294967296e9; \ |
392 |
(l).lo = 0; \ |
393 |
JSLL_L2D(_d_hi, l); \ |
394 |
_absval -= _d_hi; \ |
395 |
_lo_d.hi = 0; \ |
396 |
if (_absval < 0) { \ |
397 |
_lo_d.lo = -_absval; \ |
398 |
JSLL_SUB(l, l, _lo_d); \ |
399 |
} else { \ |
400 |
_lo_d.lo = _absval; \ |
401 |
JSLL_ADD(l, l, _lo_d); \ |
402 |
} \ |
403 |
\ |
404 |
if (_negative) \ |
405 |
JSLL_NEG(l, l); \ |
406 |
} |
407 |
|
408 |
#endif /* !JS_HAVE_LONG_LONG */ |
409 |
|
410 |
JS_END_EXTERN_C |
411 |
|
412 |
#endif /* jslong_h___ */ |