Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997, 1998
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/*		INT64liba.c
62
**		-----------
63
**
64
**  This file contains functions which perform 64-bit
65
**  arithmetic on 32-bit machines.
66
**
67
**  The functions all use abstract types which refer
68
**  to some characteristic of that type, so that INT32
69
**  is a 32-bit signed integer, and UINT64 is a 32-bit
70
**  unsigned integer.  These types are defined in the
71
**  file 'INT64_types.h'.
72
*/
73
 
74
 
75
#include <stdio.h>
76
#include "ossg.h"
77
 
7 7u83 78
#if defined(__TenDRA__)
2 7u83 79
#include "abstract.h"
80
#else
81
#include "concrete.h"
82
#endif  /* defined(__TenDRA__) */
83
 
84
 
85
#undef STATIC
86
#ifndef DEBUG
87
#define STATIC static
88
#else
89
#define STATIC
90
#endif  /* ndef DEBUG */
91
 
7 7u83 92
#define UINT32_const(X)((UINT32)(X))
2 7u83 93
 
94
 
95
/* Error Treatments handling */
96
 
97
int __TDFerror;
98
 
99
#define OVERFLOW_ERROR	(__TDFerror = -1)
100
#if USE_SEPARATE_DIV_ZERO_ERROR
101
#define DIV_ZERO_ERROR	(__TDFerror = 0)
102
#else
103
#define DIV_ZERO_ERROR OVERFLOW_ERROR
104
#endif
105
#define CLEAR_ERRORS	(__TDFerror = 1)
106
 
107
 
108
 
109
/* Declarations of functions used internally */
110
 
7 7u83 111
static TDF_INT64	TDFUplus(TDF_INT64, TDF_INT64);
112
static TDF_INT64	TDFUminus(TDF_INT64, TDF_INT64);
113
static TDF_INT64	TDFUmult(TDF_INT64, TDF_INT64);
114
static TDF_INT64	TDFUdiv_rem(TDF_INT64, TDF_INT64, UINT32);
115
static TDF_INT64	TDFUshr(TDF_INT64, UINT32);
2 7u83 116
 
117
 
118
 
119
/* Declarations of DEBUG functions */
120
 
121
#if DEBUG
7 7u83 122
INT64	make_INT64(INT32, UINT32);
123
UINT64	make_UINT64(UINT32, UINT32);
124
void 	INT64_print(char *,  INT64, char *);
125
void	UINT64_print(char *, UINT64, char *);
2 7u83 126
#endif
127
 
128
 
129
/*  Forward declarations  */
130
 
7 7u83 131
INT64	__TDFUs_plus(INT64, INT64);
132
INT64	__TDFUs_minus(INT64, INT64);
133
INT64	__TDFUs_mult(INT64, INT64);
134
INT64	__TDFUs_div1(INT64, INT64);
135
INT64	__TDFUs_div2(INT64, INT64);
136
INT64	__TDFUs_rem1(INT64, INT64);
137
INT64	__TDFUs_rem2(INT64, INT64);
138
INT64	__TDFUneg(INT64);
139
INT64	__TDFUabs(INT64);
140
INT64	__TDFUsswiden(INT32);
141
INT64	__TDFUuswiden(UINT32);
142
INT32	__TDFUssshorten(INT64);
143
INT32	__TDFUusshorten(UINT64);
144
INT64	__TDFUu642s64(UINT64);
145
INT64	__TDFUs_max(INT64, INT64);
146
INT64	__TDFUs_min(INT64, INT64);
147
int	__TDFUs_test(INT64, INT64);
2 7u83 148
 
7 7u83 149
UINT64	__TDFUu_plus(UINT64, UINT64);
150
UINT64	__TDFUu_minus(UINT64, UINT64);
151
UINT64	__TDFUu_mult(UINT64, UINT64);
152
UINT64	__TDFUu_div2(UINT64, UINT64);
153
UINT64	__TDFUu_rem2(UINT64, UINT64);
154
UINT64	__TDFUu_shl(UINT64, UINT32);
155
UINT64	__TDFUu_shr(UINT64, UINT32);
156
UINT64	__TDFUuuwiden(UINT32);
157
UINT64	__TDFUsuwiden(INT32);
158
UINT32	__TDFUsushorten(INT64);
159
UINT32	__TDFUuushorten(UINT64);
160
UINT64	__TDFUs642u64(INT64);
161
UINT64	__TDFUu_max(UINT64, UINT64);
162
UINT64	__TDFUu_min(UINT64, UINT64);
163
int	__TDFUu_test(UINT64, UINT64);
164
UINT64	__TDFUand(UINT64, UINT64);
165
UINT64	__TDFUor(UINT64, UINT64);
166
UINT64	__TDFUxor(UINT64, UINT64);
167
UINT64	__TDFUnot(UINT64);
2 7u83 168
 
169
 
170
 
171
#define TDFUis_positive(X)	((hi_32(X) >= 0))
172
#define TDFUis_negative(X)	((hi_32(X) < 0))
173
#define TDFUis_zero(X)		((hi_32(X) == 0) && (lo_32(X) == 0))
7 7u83 174
#define TDFUis_nonzero(X)	((hi_32(X)!= 0) || (lo_32(X)!= 0))
2 7u83 175
 
176
 
177
/*
178
** 	TDFUshl:
179
**
180
**  Simply masks out the necessary bits as appropriate
181
**  for shifts of less than 32 and those greater than 32.
182
**
183
**  No error checking - should have already been done.
184
**
185
**  Defined here as a macro, which is implemented as a
186
**  TDF token.  This token is then used in the PL_TDF
187
**  file which implements the remaining functions in the
188
**  64-bit arithmetic library.
189
**
190
**  The token must contain IF, but TDFC only allows this
191
**  to be done with "procedure tokens".  If non-TenDRA
192
**  compilation is to be possible, this macro cannot be
193
**  used directly since constants will produce illegal
194
**  shift values, so a function has to be defined.  A
195
**  function cannot have the desired side-effect of updating
196
**  the first parameter (without making it into a pointer),
197
**  so another macro is used (which calls the function
198
**  defined using the macro which produces the definition
199
**  of the TDF token !!!  Got it ???
200
*/
201
 
202
 
7 7u83 203
#define _TDFUshl(shifted_a,a,n)\
2 7u83 204
{ \
205
    if (n > 32)		/* assuming n <= 64 */ \
206
    { \
7 7u83 207
	hi_u32(shifted_a) = lo_u32(a) << (n -32); \
208
	lo_u32(shifted_a) = (UINT32)0x00000000; \
2 7u83 209
    } \
210
    else	/*  (0 < n <= 32)  */ \
211
    { \
7 7u83 212
	hi_u32(shifted_a) = (lo_u32(a) >> (32-n)) | (hi_u32(a) << n); \
213
	lo_u32(shifted_a) =  lo_u32(a) << n; \
2 7u83 214
    } \
215
}
216
 
217
#ifdef __TenDRA__
218
 
219
/* Want to use this value in the .pl file */
220
 
221
#pragma token EXP rvalue : int : BIGEND_INT64 #
222
#ifndef BIGENDIAN_INT64
223
#define BIGEND_INT64 0
224
#else
225
#define BIGEND_INT64 BIGENDIAN_INT64
226
#endif
227
 
228
 
229
 
230
/* Use a "procedure token" to implement TDFUshl */
231
 
7 7u83 232
#pragma token PROC(EXP lvalue : TDF_INT64 : , \
2 7u83 233
		    EXP rvalue : TDF_INT64 : , \
7 7u83 234
		    EXP rvalue : UINT32 :)\
2 7u83 235
		STATEMENT TDFUshl #
7 7u83 236
#define TDFUshl(shifted_a,a,n)_TDFUshl((shifted_a), (a), (n))
2 7u83 237
#else
238
 
239
/* Use a macro (which calls a function) to implement TDFUshl */
240
 
7 7u83 241
TDF_INT64 __TDFUshl(TDF_INT64, UINT32);
242
TDF_INT64 __TDFUshl(TDF_INT64 a, UINT32 n)
2 7u83 243
{
244
    TDF_INT64 tmp;
245
 
246
    _TDFUshl(tmp, a, n);
7 7u83 247
    return tmp;
2 7u83 248
}
249
#define TDFUshl(shifted_a,a,n) { shifted_a = __TDFUshl(a,n); }
250
#endif  /* __TenDRA__ */
251
 
252
 
253
 
254
 
255
/*  Function definitions  */
256
 
257
 
258
 
259
/*
260
**	TDFUplus:
261
**
262
**  Generic function to add two 64-bit integers,
263
**  interpretting each as an unsigned value.
264
*/
265
 
7 7u83 266
static TDF_INT64
267
TDFUplus(TDF_INT64 a, TDF_INT64 b)
2 7u83 268
{
269
    TDF_INT64	sum;
270
 
7 7u83 271
    lo_u32(sum) = lo_u32(a) + lo_u32(b);
2 7u83 272
    if (lo_u32(sum) < lo_u32(a)) {
7 7u83 273
	hi_u32(sum) = hi_u32(a) + hi_u32(b) + 1;
274
    } else {
275
	hi_u32(sum) = hi_u32(a) + hi_u32(b);
2 7u83 276
    }
277
    return sum;
278
}
279
 
280
 
281
 
282
/*
283
**	__TDFUs_plus:
284
**
285
**  Interpret signed numbers as unsigned, add them
286
**  as unsigned numbers, then reinterpret as signed.
287
**  Error handling if two positives produce a negative
288
**  or two negative produce a positive, else alright.
289
*/
290
 
7 7u83 291
INT64
292
__TDFUs_plus(INT64 param_a, INT64 param_b)
2 7u83 293
{
294
    TDF_INT64	sum, a, b;
295
 
296
    PARAM(a) = param_a;
297
    PARAM(b) = param_b;
298
    CLEAR_ERRORS;
299
    sum = TDFUplus (a, b);	/* add as unsigned numbers */
300
 
301
    if (TDFUis_positive(a)	&&	/* a >= 0 */
302
	TDFUis_positive(b)	&&	/* b >= 0 */
7 7u83 303
	TDFUis_negative(sum)) {		/* a+b < 0 */
2 7u83 304
	OVERFLOW_ERROR;
305
    }
306
    if (TDFUis_negative(a)	&&	/* a < 0 */
307
	TDFUis_negative(b)	&&	/* b < 0 */
7 7u83 308
	TDFUis_positive(sum)) {		/* a+b >= 0 */
2 7u83 309
	OVERFLOW_ERROR;
310
    }
311
 
7 7u83 312
    return PARAM(sum);
2 7u83 313
}
314
 
315
 
316
 
317
/*
318
**	__TDFUu_plus:
319
**
320
**  Adds arguments, and tests to see if sum is less
321
**  than the first argument for error detection.
322
*/
323
 
7 7u83 324
UINT64
325
__TDFUu_plus(UINT64 param_a, UINT64 param_b)
2 7u83 326
{
327
    TDF_INT64	sum, a, b;
328
 
329
    UPARAM(a) = param_a;
330
    UPARAM(b) = param_b;
331
    CLEAR_ERRORS;
7 7u83 332
    sum = TDFUplus(a, b);
2 7u83 333
 
334
    if ((hi_u32(sum) <= hi_u32(a))	&&
7 7u83 335
	(lo_u32(sum) < lo_u32(a))) {	/* sum < a */
2 7u83 336
	OVERFLOW_ERROR;
337
    }
338
 
7 7u83 339
    return UPARAM(sum);
2 7u83 340
}
341
 
342
 
343
 
344
/*
345
**	TDFUminus:
346
**
347
**  Generic function to subtracting two 64-bit
348
**  integers, interpretting each as an unsigned value.
349
*/
350
 
7 7u83 351
static TDF_INT64
352
TDFUminus(TDF_INT64 a, TDF_INT64 b)
2 7u83 353
{
354
    TDF_INT64	sum;
355
 
7 7u83 356
    lo_u32(sum) = lo_u32(a) - lo_u32(b);
2 7u83 357
    if (lo_u32(sum) > lo_u32(a)) {
7 7u83 358
	hi_u32(sum) = hi_u32(a) - hi_u32(b) - 1;
359
    } else {
360
	hi_u32(sum) = hi_u32(a) - hi_u32(b);
2 7u83 361
    }
362
    return sum;
363
}
364
 
365
 
366
 
367
/*
368
**	__TDFUs_minus:
369
**
370
**  Interpret signed numbers as unsigned, add them
371
**  as unsigned numbers, then reinterpret as signed.
372
**  Error handling if two positives produce a negative
373
**  or two negative produce a positive, else alright.
374
*/
375
 
7 7u83 376
INT64
377
__TDFUs_minus(INT64 param_a, INT64 param_b)
2 7u83 378
{
379
    TDF_INT64	diff, a, b;
380
 
381
    PARAM(a) = param_a;
382
    PARAM(b) = param_b;
383
    CLEAR_ERRORS;
384
    diff = TDFUminus (a, b);	/* subtract as unsigned numbers */
385
 
386
    if (TDFUis_positive(a)	&&	/* a >= 0 */
387
	TDFUis_negative(b)	&&	/* b < 0 */
7 7u83 388
	TDFUis_negative(diff)) {	/* a-b < 0 */
2 7u83 389
	OVERFLOW_ERROR;
390
    }
391
    if (TDFUis_negative(a)	&&	/* a < 0 */
392
	TDFUis_positive(b)	&&	/* b >= 0 */
7 7u83 393
	TDFUis_positive(diff)) {	/* a-b >= 0 */
2 7u83 394
	OVERFLOW_ERROR;
395
    }
396
 
7 7u83 397
    return PARAM(diff);
2 7u83 398
}
399
 
400
 
401
 
402
/*
403
**	__TDFUu_minus:
404
**
405
**  Adds arguments, and tests to see if sum is less
406
**  than the first argument for error detection.
407
*/
408
 
7 7u83 409
UINT64
410
__TDFUu_minus(UINT64 param_a, UINT64 param_b)
2 7u83 411
{
412
    TDF_INT64	diff, a, b;
413
 
414
    UPARAM(a) = param_a;
415
    UPARAM(b) = param_b;
416
    CLEAR_ERRORS;
7 7u83 417
    diff = TDFUminus(a, b);
2 7u83 418
 
419
    if ((hi_u32(diff) >= hi_u32(a))	&&
7 7u83 420
	(lo_u32(diff) > lo_u32(a))) {	/* diff > a */
2 7u83 421
	OVERFLOW_ERROR;
422
    }
423
 
7 7u83 424
    return UPARAM(diff);
2 7u83 425
}
426
 
427
 
428
 
429
 
430
 
431
 
432
 
433
 
434
 
435
/*
436
**		a3	a2	a1	a0
437
**
438
**	X	b3	b2	b1	b0
439
**		--------------------------
440
**			     ----a0 X b0----	(STAGE1)
441
**
442
**		     ----a1 X b0----		(STAGE2)
443
**		     ----a0 X b1----
444
**
445
**	     ----a2 X b0----			(STAGE3)
446
**	     ----a1 X b1----
447
**	     ----a0 X b2----
448
**
449
**   ----a3 X b0----				(STAGE4)
450
**   ----a2 X b1----
451
**   ----a1 X b2----
452
**   ----a0 X b3----
453
**
454
**
455
**  These are the only terms necessary to produce the answer.
456
**  The other terms must all be used at error checking to
457
**  ensure that overflow does not occur.
458
**
459
**  By adding the contributions in this order, it is possible
460
**  to control the size of the sum as each stage, i.e. only
461
**  certain terms need to be considered, reducing the number
462
**  of steps in the addition.
463
**
464
**  If the parameter 'error_check' is non-zero, error-checking
465
**  is done: its value is reset to zero if non occur.
466
*/
467
 
468
 
469
#define hi_u16(X)	((X) >> 16)
7 7u83 470
#define lo_u16(X)	((X) & ((UINT32)0xffff))
2 7u83 471
 
7 7u83 472
static TDF_INT64
473
TDFUmult(TDF_INT64 a, TDF_INT64 b)
2 7u83 474
{
475
    TDF_INT64	prod;
476
    UINT32	a0, a1, a2, a3;
477
    UINT32	b0, b1, b2, b3;
478
    UINT32	work1, work2;
479
 
7 7u83 480
    a0 = lo_u16(lo_u32(a));
481
    a1 = hi_u16(lo_u32(a));
482
    a2 = lo_u16(hi_u32(a));
483
    a3 = hi_u16(hi_u32(a));
2 7u83 484
 
7 7u83 485
    b0 = lo_u16(lo_u32(b));
486
    b1 = hi_u16(lo_u32(b));
487
    b2 = lo_u16(hi_u32(b));
488
    b3 = hi_u16(hi_u32(b));
2 7u83 489
 
490
    if ((a1 == 0) && (a2 == 0) && (a3 == 0) &&
7 7u83 491
	(b1 == 0) && (b2 == 0) && (b3 == 0)) {
2 7u83 492
	hi_u32(prod) = 0;	/* result fits into 32 bits */
493
	lo_u32(prod) = a0 * b0;
7 7u83 494
	return prod;
2 7u83 495
    }
496
 
497
/* Start STAGE1 */
498
 
499
    lo_u32(prod) = a0 * b0;
500
 
501
 
502
/* Start STAGE2 */
503
 
504
    work1 = a1 * b0;
505
    work2 = work1 + (a0 * b1);
506
    if (work2 < work1) {
7 7u83 507
	hi_u32(prod) = ((UINT32) 0x10000);	/* set carry in result */
508
    } else {
2 7u83 509
	hi_u32(prod) = 0;		/* must initialise somewhere */
510
    }
511
 
512
    work1 = lo_u16(work2);	/* lo-16 bits of sum */
513
    work2 = hi_u16(work2);	/* hi-16 bits of sum */
514
 
515
    lo_u32(prod) += (work1 << 16);
516
    if ((work1 << 16) > lo_u32(prod)) {	/* wrap */
517
	hi_u32(prod) += (1 + work2);
7 7u83 518
    } else {
2 7u83 519
	hi_u32(prod) += work2;
520
    }
521
 
522
 
523
/* Start STAGE3 */
524
 
525
    work1 = a2 * b0;
526
    work2 = work1 + (a1 * b1);
527
 
528
    if (work1 > work2) {
529
	OVERFLOW_ERROR;
530
    }
531
 
532
    work1 = work2 + (a0 * b2);
533
 
534
    if (work2 > work1) {
535
	OVERFLOW_ERROR;
536
    }
537
 
538
    hi_u32(prod) += work1;
539
 
540
    if (work1 > hi_u32(prod)) {
541
	OVERFLOW_ERROR;
542
    }
543
 
544
 
545
/* Start STAGE4 */
546
 
547
    work1 = a3 * b0;
548
    work2 = a2 * b1;
549
 
7 7u83 550
    if ((work1 > ((UINT32)0xffff)) ||
551
	(work2 > ((UINT32)0xffff))) {
2 7u83 552
	OVERFLOW_ERROR;
553
    }
554
 
555
    work1 = work1 + work2;
556
    work2 = a1 * b2;
557
 
7 7u83 558
    if (work2 > ((UINT32)0xffff)) {
2 7u83 559
	OVERFLOW_ERROR;
560
    }
561
 
562
    work1 = work1 + work2;
563
    work2 = a0 * b3;
564
    work1 = work1 + work2;
565
 
7 7u83 566
    if ((work1 > ((UINT32)0xffff)) ||
567
	(work2 > ((UINT32)0xffff))) {
2 7u83 568
	OVERFLOW_ERROR;
569
    }
570
 
571
    work2 = work1 << 16;	/* We've made sure this will work */
572
    hi_u32(prod) += work2;
573
 
574
    if ((work2 > hi_u32(prod))	||	/* This mustn't overflow */
575
	(a3 * b1 != 0)		||
576
	(a2 * b2 != 0)		||	/* Remaining contributions */
577
	(a1 * b3 != 0)		||	/*    must all be zero     */
578
	(a3 * b2 != 0)		||
579
	(a2 * b3 != 0)		||
7 7u83 580
	(a3 * b3 != 0)) {
2 7u83 581
	OVERFLOW_ERROR;
582
    }
583
 
584
    return prod;
585
}
586
 
587
 
588
 
589
 
590
 
591
/*
592
**	__TDFUs_mult:
593
**
594
**  Implements long multiplication in binary,
595
**  checking for errors as it goes along.
596
*/
597
 
598
 
7 7u83 599
INT64
600
__TDFUs_mult(INT64 param_a, INT64 param_b)
2 7u83 601
{
602
    TDF_INT64	prod, a, b;
603
    int		sign;
604
 
605
    PARAM(a) = param_a;
606
    PARAM(b) = param_b;
607
    CLEAR_ERRORS;
608
 
609
    sign = ((hi_32(a) ^ hi_32(b)) < 0);	/* sign of result */
610
 
611
    PARAM(a) = __TDFUabs(param_a);
612
    PARAM(b) = __TDFUabs(param_b);
7 7u83 613
    prod = TDFUmult (a, b);		/* Any overflow will be flagged */
2 7u83 614
 
7 7u83 615
    if (hi_32(prod) < 0) {		/* definitely okay if this is false */
616
	if ((sign == 0) ||		/* positive int too big for INT_64 */
2 7u83 617
	    (hi_u32(prod) > ((UINT32) 0x80000000)) ||   /* signed int too big for INT_64 */
7 7u83 618
	    (lo_u32(prod) > ((UINT32)0x00000000))) {
2 7u83 619
	    OVERFLOW_ERROR;
620
	}
621
    }
622
 
623
    if ((sign == 0)				 ||	/* result is unsigned */
624
	((hi_u32(prod) == ((UINT32) 0x80000000)) &&	/* - this number has the same     */
7 7u83 625
	 (lo_u32(prod) != ((UINT32) 0x00000000)))) {	/* representation as its negation */
626
	return PARAM(prod);
2 7u83 627
    }
7 7u83 628
    return __TDFUneg(PARAM(prod));
2 7u83 629
}
630
 
631
 
632
 
633
 
634
/*
635
**	__TDFUu_mult:
636
**
637
**  Implements long multiplication in binary,
638
**  checking for errors as it goes along.
639
*/
640
 
641
#if 0
642
 
7 7u83 643
UINT64
644
__TDFUu_mult(UINT64 param_a, UINT64 param_b)
2 7u83 645
{
646
    TDF_INT64	prod, a, b;
647
 
7 7u83 648
    if (__TDFUu_test(param_b, UPARAM(const_u0)) == 0) return UPARAM(const_u0);
2 7u83 649
 
650
    UPARAM(a) = param_a;
651
    UPARAM(b) = param_b;
652
    prod = const_u0;
653
 
7 7u83 654
    while (__TDFUu_test(UPARAM(b), UPARAM(const_u1))!= 0)
2 7u83 655
    {
7 7u83 656
	if ((lo_u32(b) & 1)!= 0) {
2 7u83 657
	    prod = __TDFUu_plus (UPARAM(prod), UPARAM(a));	/* Any overflow will be flagged */
658
	}
7 7u83 659
	PARAM(a) = __TDFUu_shl(UPARAM(a), (UINT32)1);
660
	PARAM(b) = __TDFUu_shr(UPARAM(b), (UINT32)1);
661
    }
2 7u83 662
 
7 7u83 663
    return UPARAM(__TDFUu_plus(prod, a));
2 7u83 664
}
665
 
666
#else
667
 
7 7u83 668
UINT64
669
__TDFUu_mult(UINT64 param_a, UINT64 param_b)
2 7u83 670
{
671
    TDF_INT64	prod, a, b;
672
 
673
    UPARAM(a) = param_a;
674
    UPARAM(b) = param_b;
675
    CLEAR_ERRORS;
676
    prod = TDFUmult (a, b);	/* Any overflow will be flagged */
7 7u83 677
    return UPARAM(prod);
2 7u83 678
}
679
 
680
#endif
681
 
682
 
683
 
684
/*
685
**	Implementation of div0, div1, rem0 and rem1.
686
**	===========================================
687
**
688
**  Clearly there are no problems for unsigned numbers.
689
**  I have written a generic function to divide two
690
**  unsigned 64-bit integers which produces both the
691
**  result of the divide and the remainder.
692
**
693
**  For signed numbers, a and b, it is possible to work
694
**  out the values of m and n s.t.:
695
**
696
**	|a| = n * |b| + m,	(0 <= m < |b|)
697
**
698
**  From this information, I believe the correct values
699
**  for the various functions can be deduced from the
700
**  following table:
701
**
702
**
703
**	a	b	class	 |	div		rem
704
**    ======================================================
705
**	+	+	  1	 |	 n		 m
706
**	+	+	  2	 |	 n		 m
707
**	+	-	  1	 | -n or -(n+1)	    0 or (b+m)
708
**	+	-	  2	 |	-n		 m
709
**	-	+	  1	 | -n or -(n+1)	    0 or (b-m)
710
**	-	+	  2	 |	-n		-m
711
**	-	-	  1	 |	 n		-m
712
**	-	-	  2	 |	 n		-m
713
*/
714
 
715
 
716
 
717
 
718
/*
719
**	TDFUdiv_rem:
720
**
721
**  Generic function to divide two 64-bit integers,
722
**  interpretting each as an unsigned value.  Implements
723
**  the basic 'shift, compare and subtract' algorithm.
724
**
725
**  Since the one function produces both the result and
726
**  the remainder, it is passed a parameter which tells
727
**  it which result is expected.  The S_DIV_0_1 flags is
728
**  used for a signed-div0 call for which the arguments
729
**  represent integers of different signs; in this case,
730
**  it is the result depends on the remainder (and so
731
**  is adjusted according while this information is still
732
**  freely available.
733
**
734
*/
735
 
7 7u83 736
#define S_DIV1		((UINT32)0)
737
#define S_DIV2		((UINT32)2)
738
#define U_DIV2		((UINT32)3)
739
#define S_REM1		((UINT32)4)
740
#define S_REM2		((UINT32)6)
741
#define U_REM2		((UINT32)7)
742
#define S_DIV1_0_1	((UINT32)8)
2 7u83 743
 
744
#define is_signed(X)	(((X) & 1) == 0)
745
#define is_class1(X)	(((X) & 2) == 0)
746
#define is_div(X)	(((X) & 4) == 0)
747
 
7 7u83 748
static TDF_INT64
749
TDFUdiv_rem(TDF_INT64 a, TDF_INT64 b, UINT32 flags)
2 7u83 750
{
751
    TDF_INT64	new_int, a_upper;
752
    UINT32	i;
753
 
754
    new_int = const_u0;
755
    a_upper = const_u0;
756
 
757
    if (hi_u32(a) == 0) {
758
	if (hi_u32(b) == 0) {	/* both a and b fit into 32 bits */
759
	    lo_u32(new_int) = lo_u32(a) / lo_u32(b);
7 7u83 760
	    lo_u32(a_upper) = lo_u32(a)% lo_u32(b);
761
	} else {			/* b > a */
2 7u83 762
	    lo_u32(new_int) = 0;
763
	    a_upper = a;
764
	}
7 7u83 765
    } else {
766
	for (i = 64; i > 0; i--) {
767
	    TDFUshl(new_int, new_int,(UINT32)1);
2 7u83 768
 
7 7u83 769
	    TDFUshl(a_upper, a_upper,(UINT32)1);
770
	    if ((hi_u32(a) >> 31)!= 0) {
2 7u83 771
		hi_u32(a) &= ((UINT32) 0x7fffffff);	/* mask out for shift */
772
		lo_u32(a_upper) |= 1;	/* do carry */
773
	    }
7 7u83 774
	    TDFUshl(a, a,(UINT32)1);
775
 
2 7u83 776
	    if (__TDFUu_test(UPARAM(a_upper), UPARAM(b)) >= 0) {
7 7u83 777
		UPARAM(a_upper) = __TDFUu_minus(UPARAM(a_upper), UPARAM(b));
2 7u83 778
		lo_u32(new_int) |= 1;
779
	    }
7 7u83 780
	}
781
 
2 7u83 782
    }
783
 
7 7u83 784
    if (is_div(flags)) {	/* result of 'div' */
2 7u83 785
	if ((flags == S_DIV1_0_1)	&&
7 7u83 786
	   ((lo_32(a_upper)!= 0)	||
787
	    (hi_32(a_upper)!= 0))) {
2 7u83 788
	    PARAM(new_int) = __TDFUs_plus(PARAM(new_int), PARAM(const_1));
789
	}
7 7u83 790
	return new_int;
2 7u83 791
    }
792
 
7 7u83 793
    return a_upper;		/* result of 'rem' */
2 7u83 794
}
795
 
796
 
797
 
798
/*
799
**	__TDFUs_div1:
800
**
801
**  Division-by-zero is the only possible error.
802
*/
803
 
7 7u83 804
INT64
805
__TDFUs_div1(INT64 param_a, INT64 param_b)
2 7u83 806
{
807
    TDF_INT64	quot, a, b;
808
    int		is_neg;
809
 
810
    PARAM(b) = param_b;
7 7u83 811
    if (TDFUis_zero(b)) {
2 7u83 812
	DIV_ZERO_ERROR;		/* Stop now - return anything */
813
	return param_b;
814
    }
815
    PARAM(a) = param_a;
816
 
817
    is_neg = ((hi_32(a) ^ hi_32(b)) < 0);		/* is result negative ? */
818
    PARAM(a) = __TDFUabs(param_a);
819
    PARAM(b) = __TDFUabs(param_b);
820
 
821
    if (is_neg) {
7 7u83 822
	quot = TDFUdiv_rem(a, b, S_DIV1_0_1);
2 7u83 823
	CLEAR_ERRORS;					/* May have been set by __TDFUabs */
7 7u83 824
	hi_32(quot) = hi_32(quot)^((INT32)
2 7u83 825
		((UINT32) 0xffffffff));		/* Avoid errors, don't call __TDFUneg */
7 7u83 826
	lo_32(quot) = lo_32(quot)^ UINT32_const(0xffffffff);
827
	return PARAM(TDFUplus(quot, const_1));
2 7u83 828
    }
829
 
7 7u83 830
    quot = TDFUdiv_rem(a, b, S_DIV1);
2 7u83 831
    CLEAR_ERRORS;	/* May have been set by __TDFUabs */
832
 
7 7u83 833
    if (TDFUis_negative(quot)) {	/* Only happens for INT_MAX+1 */
2 7u83 834
	OVERFLOW_ERROR;
835
    }
7 7u83 836
    return PARAM(quot);
2 7u83 837
}
838
 
839
 
840
 
841
/*
842
**	__TDFUs_div2:
843
**
844
**  Division-by-zero is the only possible error.
845
*/
846
 
7 7u83 847
INT64
848
__TDFUs_div2(INT64 param_a, INT64 param_b)
2 7u83 849
{
850
    TDF_INT64	quot, a, b;
851
    int		is_neg;
852
 
853
    PARAM(b) = param_b;
7 7u83 854
    if (TDFUis_zero(b)) {
2 7u83 855
	DIV_ZERO_ERROR;		/* Stop now - return anything */
856
	return param_b;
857
    }
858
    PARAM(a) = param_a;
859
 
860
    is_neg = ((hi_32(a) ^ hi_32(b)) < 0);	/* is result negative ? */
861
    PARAM(a) = __TDFUabs(param_a);
862
    PARAM(b) = __TDFUabs(param_b);
863
 
7 7u83 864
    quot = TDFUdiv_rem(a, b, S_DIV2);
2 7u83 865
    CLEAR_ERRORS;	/* May have been set by __TDFUabs */
866
 
867
    if (is_neg) {
7 7u83 868
	hi_32(quot) = hi_32(quot)^
2 7u83 869
	   ( (INT32) ((UINT32) 0xffffffff)); /* Avoid errors, don't call __TDFUneg */
7 7u83 870
	lo_32(quot) = lo_32(quot)^((UINT32)0xffffffff);
871
	return PARAM(TDFUplus(quot, const_1));
2 7u83 872
    }
873
 
7 7u83 874
    if (TDFUis_negative(quot)) {	/* Only happens for INT_MAX+1 */
2 7u83 875
	OVERFLOW_ERROR;
876
    }
7 7u83 877
    return PARAM(quot);
2 7u83 878
}
879
 
880
 
881
 
882
/*
883
**	__TDFUu_div2:
884
**
885
**  Division-by-zero is the only possible error.
886
*/
887
 
7 7u83 888
UINT64
889
__TDFUu_div2(UINT64 param_a, UINT64 param_b)
2 7u83 890
{
891
    TDF_INT64	a, b;
892
 
893
    CLEAR_ERRORS;
894
 
895
    UPARAM(b) = param_b;
7 7u83 896
    if (TDFUis_zero(b)) {
2 7u83 897
	DIV_ZERO_ERROR;		/* Stop now - return anything */
898
	return param_b;
899
    }
900
    UPARAM(a) = param_a;
901
 
7 7u83 902
    return UPARAM(TDFUdiv_rem(a, b, U_DIV2));
2 7u83 903
}
904
 
905
 
906
/*
907
**	__TDFUs_rem1:
908
**
909
**  Modulo-zero is the only possible error.
910
*/
911
 
7 7u83 912
INT64
913
__TDFUs_rem1(INT64 param_a, INT64 param_b)
2 7u83 914
{
915
    TDF_INT64	rem, a, b, abs_a, abs_b;
916
    int		is_neg;
917
 
918
    PARAM(b) = param_b;
7 7u83 919
    if (TDFUis_zero(b)) {
2 7u83 920
	DIV_ZERO_ERROR;		/* Stop now - return anything */
921
	return param_b;
922
    }
923
    PARAM(a) = param_a;
924
    PARAM(abs_a) = __TDFUabs(param_a);
925
    PARAM(abs_b) = __TDFUabs(param_b);
926
 
927
    is_neg = TDFUis_negative(b);	/* is result negative ? */
7 7u83 928
    rem = TDFUdiv_rem(abs_a, abs_b, S_REM1);
2 7u83 929
    CLEAR_ERRORS;		/* May have been set by __TDFUabs */
930
 
931
    if (TDFUis_positive(a)	&&
932
	TDFUis_negative(b)	&&
7 7u83 933
	TDFUis_nonzero(rem)) {
934
	return __TDFUs_plus(param_b, PARAM(rem));
2 7u83 935
    }
936
 
937
    if (TDFUis_negative(a)	&&
938
	TDFUis_positive(b)	&&
7 7u83 939
	TDFUis_nonzero(rem)) {
940
	return __TDFUs_minus(param_b, PARAM(rem));
2 7u83 941
    }
942
 
7 7u83 943
    if (is_neg) {
944
	    return __TDFUneg(PARAM(rem));
945
    }
946
    return PARAM(rem);
2 7u83 947
}
948
 
949
 
950
 
951
/*
952
**	__TDFUs_rem2:
953
**
954
**  Modulo-zero is the only possible error.
955
*/
956
 
7 7u83 957
INT64
958
__TDFUs_rem2(INT64 param_a, INT64 param_b)
2 7u83 959
{
960
    TDF_INT64	rem, a, b;
961
    int		is_neg;
962
 
963
    PARAM(b) = param_b;
7 7u83 964
    if (TDFUis_zero(b)) {
2 7u83 965
	DIV_ZERO_ERROR;		/* Stop now - return anything */
966
	return param_b;
967
    }
968
    PARAM(a) = param_a;
969
 
970
    is_neg = TDFUis_negative(a);	/* is result negative ? */
971
    PARAM(a) = __TDFUabs(param_a);
972
    PARAM(b) = __TDFUabs(param_b);
973
 
7 7u83 974
    rem = TDFUdiv_rem(a, b, S_REM2);
2 7u83 975
    CLEAR_ERRORS;		/* May have been set by __TDFUabs */
976
 
7 7u83 977
    if (is_neg) {
978
	    return __TDFUneg(PARAM(rem));
979
    }
980
    return PARAM(rem);
2 7u83 981
}
982
 
983
 
984
 
985
/*
986
**	__TDFUu_rem2:
987
**
988
**  Modulo-zero is the only possible error.
989
*/
990
 
7 7u83 991
UINT64
992
__TDFUu_rem2(UINT64 param_a, UINT64 param_b)
2 7u83 993
{
994
    TDF_INT64	a, b;
995
 
996
    UPARAM(b) = param_b;
7 7u83 997
    if (TDFUis_zero(b)) {
2 7u83 998
	DIV_ZERO_ERROR;		/* Stop now - return anything */
999
	return param_b;
1000
    }
1001
    UPARAM(a) = param_a;
1002
 
1003
    CLEAR_ERRORS;
7 7u83 1004
    return UPARAM(TDFUdiv_rem(a, b, U_REM2));
2 7u83 1005
}
1006
 
1007
 
1008
 
1009
/*
1010
** 	__TDFUneg:
1011
**
1012
**  Flip all bits and add 1, as for 2's complement.
1013
**  Overflow error if original value was INT64_MIN.
1014
*/
1015
 
7 7u83 1016
INT64
1017
__TDFUneg(INT64 param_a)
2 7u83 1018
{
1019
    TDF_INT64	a;
1020
 
1021
    PARAM(a) = param_a;
7 7u83 1022
    hi_32(a) = hi_32(a)^((INT32)((UINT32)0xffffffff));
1023
    lo_32(a) = lo_32(a)^((UINT32)0xffffffff);
1024
    return __TDFUs_plus(PARAM(a), PARAM(const_1));	/* Should handle any errors */
2 7u83 1025
}
1026
 
1027
 
1028
 
1029
 
1030
/*
1031
** 	__TDFUs_shl:
1032
**
1033
**  Best implemented in PL_TDF.
1034
*/
1035
 
1036
 
1037
 
1038
/*
1039
** 	__TDFUu_shl:
1040
**
1041
**  Does error checking.  If all is okay, returns the value.
7 7u83 1042
**
2 7u83 1043
*/
1044
 
7 7u83 1045
UINT64
1046
__TDFUu_shl(UINT64 param_a, UINT32 n)
2 7u83 1047
{
1048
    TDF_INT64	a;
1049
 
1050
    CLEAR_ERRORS;
1051
    if (n > 63) {
1052
	OVERFLOW_ERROR;
7 7u83 1053
	return UPARAM(const_u0);
2 7u83 1054
    }
1055
 
1056
    if (n == 0)	return param_a;
1057
 
1058
    /* check that the result won't overflow */
1059
 
1060
    UPARAM(a) = param_a;
1061
    if (n > 32) {
7 7u83 1062
	if (((lo_u32(a) >> (64-n))!= 0)	|| (hi_u32(a)!= 0)) {
2 7u83 1063
	    OVERFLOW_ERROR;
1064
	}
7 7u83 1065
    } else if ((hi_u32(a) >> (32-n))!= 0) {
2 7u83 1066
	OVERFLOW_ERROR;
1067
    }
1068
 
7 7u83 1069
    TDFUshl(a, a, n);
1070
    return UPARAM(a);
2 7u83 1071
}
1072
 
1073
 
1074
 
1075
/*
1076
** 	__TDFUu_shr:
1077
**
1078
**  2 cases: n > 32  - copy high 32-bits across and shift.
1079
**  	     n <= 32 - mask out two contributions and OR together.
1080
*/
1081
 
7 7u83 1082
static TDF_INT64
1083
TDFUshr(TDF_INT64 a, UINT32 n)
2 7u83 1084
{
1085
    TDF_INT64	shifted_a;
1086
 
1087
    CLEAR_ERRORS;
7 7u83 1088
    if (n >= 32) {	/* 32 <= n < 64 */
1089
	lo_u32(shifted_a) = hi_u32(a) >> (n -32);
1090
	hi_u32(shifted_a) = (UINT32)0x00000000;
1091
    } else {	/*  (0 < n <= 32)  */
1092
	lo_u32(shifted_a) = (hi_u32(a) << (32-n)) | (lo_u32(a) >> n);
1093
	hi_u32(shifted_a) =  hi_u32(a) >> n;
2 7u83 1094
    }
1095
 
7 7u83 1096
    return shifted_a;
2 7u83 1097
}
1098
 
1099
 
1100
 
1101
/*
1102
** 	__TDFUs_shr:
1103
**
1104
**  Best implemented in PL_TDF
1105
*/
1106
 
1107
 
1108
 
1109
/*
1110
** 	__TDFUu_shr:
1111
**
1112
**  Error occurs if n > 64 since the result is undefined.
1113
*/
1114
 
7 7u83 1115
UINT64
1116
__TDFUu_shr(UINT64 param_a, UINT32 n)
2 7u83 1117
{
1118
    TDF_INT64	a;
1119
 
1120
    CLEAR_ERRORS;
1121
    if (n > 63) {	/* This is undefined */
1122
	OVERFLOW_ERROR;
7 7u83 1123
	return UPARAM(const_u0);
2 7u83 1124
    }
1125
 
1126
    if (n == 0) return param_a;
1127
    UPARAM(a) = param_a;
7 7u83 1128
    return UPARAM(TDFUshr(a, n));
2 7u83 1129
}
1130
 
1131
 
1132
 
1133
/*
1134
** 	__TDFUabs:
1135
**
1136
**  Checks for a negative quantity, for which it
1137
**  calls '__TDFUneg'.  Overflow for, as for __TDFUneg,
1138
**  occurs when the value is INT32_MIN.
7 7u83 1139
**
2 7u83 1140
*/
1141
 
7 7u83 1142
INT64
1143
__TDFUabs(INT64 param_a)
2 7u83 1144
{
1145
    TDF_INT64	a;
1146
 
1147
    PARAM(a) = param_a;
1148
    if (TDFUis_negative(a)) {
7 7u83 1149
	return __TDFUneg (param_a);	/* This handles any errors */
2 7u83 1150
    }
1151
 
1152
    CLEAR_ERRORS;
7 7u83 1153
    return param_a;
2 7u83 1154
}
1155
 
1156
 
1157
/*
1158
** 	__TDFUsswiden:
1159
**
1160
**  Extends the sign bit, and returns the new int.
1161
**
1162
*/
1163
 
7 7u83 1164
INT64
1165
__TDFUsswiden(INT32 a)
2 7u83 1166
{
1167
    TDF_INT64	ext_int;
1168
 
1169
    CLEAR_ERRORS;
1170
    hi_32(ext_int) = (INT32) ((a < 0) ? -1 : 0);	/* sign-extend a */
7 7u83 1171
    lo_32(ext_int) = (UINT32)a;
1172
    return PARAM(ext_int);
2 7u83 1173
}
1174
 
1175
 
1176
/*
1177
** 	__TDFUsuwiden:
1178
**
1179
**  Error if a is negative.
1180
**  Otherwise extends the sign bit (just to be safe)
1181
*/
1182
 
7 7u83 1183
UINT64 __TDFUsuwiden(INT32 a)
2 7u83 1184
{
1185
    TDF_INT64	ext_int;
1186
 
1187
    CLEAR_ERRORS;
7 7u83 1188
    if (a < 0) {
2 7u83 1189
	OVERFLOW_ERROR;
1190
    }
1191
 
7 7u83 1192
    hi_u32(ext_int) = (UINT32)((a < 0)? 0xffffffff : 0);
2 7u83 1193
					/* sign-extend a */
7 7u83 1194
    lo_u32(ext_int) = (UINT32)a;
1195
    return UPARAM(ext_int);
2 7u83 1196
}
1197
 
1198
 
1199
/*
1200
** 	__TDFUuuwiden:
1201
**
1202
**  Puts zero in bits 32-63 and returns
1203
*/
1204
 
7 7u83 1205
UINT64
1206
__TDFUuuwiden(UINT32 a)
2 7u83 1207
{
1208
    TDF_INT64	ext_int;
1209
 
1210
    CLEAR_ERRORS;
1211
    hi_u32(ext_int) = 0;
1212
    lo_u32(ext_int) = a;
7 7u83 1213
    return UPARAM(ext_int);
2 7u83 1214
}
1215
 
1216
 
1217
/*
1218
** 	__TDFUuswiden:
1219
**
1220
**  Same as __TDFUuuswiden.
1221
**
1222
*/
1223
 
7 7u83 1224
INT64
1225
__TDFUuswiden(UINT32 a)
2 7u83 1226
{
1227
    TDF_INT64	ext_int;
1228
 
1229
    CLEAR_ERRORS;
1230
    hi_32(ext_int) = 0;
1231
    lo_32(ext_int) = a;
7 7u83 1232
    return PARAM(ext_int);
2 7u83 1233
}
1234
 
1235
 
1236
/*
1237
** 	__TDFUssshorten:
1238
**
1239
**  Check that bits 31-63 are all set/unset,
1240
**  otherwise signal overflow.  Mask sign
1241
**  bit into bit-31.
1242
*/
1243
 
7 7u83 1244
INT32
1245
__TDFUssshorten(INT64 param_a)
2 7u83 1246
{
1247
    TDF_INT64	a;
1248
 
1249
    PARAM(a) = param_a;
1250
    CLEAR_ERRORS;
7 7u83 1251
    switch ((int)hi_32(a)) {
2 7u83 1252
      case 0:
7 7u83 1253
	  if ((lo_32(a) & ((UINT32)0x80000000))!= 0) {
2 7u83 1254
	      OVERFLOW_ERROR;
1255
	  }
1256
	  break;
1257
      case -1:
7 7u83 1258
	  if ((lo_32(a) & ((UINT32)0x80000000)) == 0) {
2 7u83 1259
	      OVERFLOW_ERROR;
1260
	  }
1261
	  break;
1262
      default:
1263
	  OVERFLOW_ERROR;
1264
    }
1265
 
7 7u83 1266
    return ((((INT32)lo_32(a)) & ((INT32)0x7fffffff)) |
1267
	    (hi_32(a) & ((INT32)((UINT32)0x80000000))));
2 7u83 1268
 
1269
}
1270
 
1271
 
1272
/*
1273
** 	__TDFUsushorten:
1274
**
1275
**  Check that bits 32-63 are all zero
1276
**  otherwise signal overflow.  Answer
1277
**  is in bits 0-31.
1278
*/
1279
 
7 7u83 1280
UINT32
1281
__TDFUsushorten(INT64 param_a)
2 7u83 1282
{
1283
    TDF_INT64	a;
1284
 
1285
    PARAM(a) = param_a;
1286
    CLEAR_ERRORS;
7 7u83 1287
    if (hi_32(a) != 0) {
2 7u83 1288
	OVERFLOW_ERROR;
1289
    }
1290
 
7 7u83 1291
    return lo_32(a);
2 7u83 1292
}
1293
 
1294
 
1295
/*
1296
** 	__TDFUuushorten:
1297
**
1298
**  Error if bits 32-63 are not all zero.
1299
**  Return bits 0-31.
1300
*/
1301
 
7 7u83 1302
UINT32
1303
__TDFUuushorten(UINT64 param_a)
2 7u83 1304
{
1305
    TDF_INT64	a;
1306
 
1307
    UPARAM(a) = param_a;
1308
    CLEAR_ERRORS;
7 7u83 1309
    if (hi_u32(a) != 0) {
2 7u83 1310
	OVERFLOW_ERROR;
1311
    }
1312
 
7 7u83 1313
    return lo_u32(a);
2 7u83 1314
}
1315
 
1316
 
1317
/*
1318
** 	__TDFUusshorten:
1319
**
1320
**  Error if bits 31-63 are not all zero.
1321
**  Return bits 0-31.
1322
*/
1323
 
7 7u83 1324
INT32
1325
__TDFUusshorten(UINT64 param_a)
2 7u83 1326
{
1327
    TDF_INT64	a;
1328
 
1329
    UPARAM(a) = param_a;
1330
    CLEAR_ERRORS;
7 7u83 1331
    if ((hi_u32(a)!= 0)	||
1332
	(((INT32) lo_u32(a)) < 0)) {	/* Must be an error - started off unsigned */
2 7u83 1333
	OVERFLOW_ERROR;
1334
    }
1335
 
7 7u83 1336
    return (INT32)lo_u32(a);
2 7u83 1337
}
1338
 
1339
 
1340
/*
1341
** 	__TDFUu642s64:
1342
**
1343
**  Error only if MSB of "a" is set.
1344
**  Return bits 0-31.
1345
*/
1346
 
7 7u83 1347
INT64
1348
__TDFUu642s64(UINT64 param_a)
2 7u83 1349
{
1350
    TDF_INT64	a;
1351
 
1352
    UPARAM(a) = param_a;
1353
    CLEAR_ERRORS;
7 7u83 1354
    if (TDFUis_negative(a)) {	/* Cast and check */
2 7u83 1355
	OVERFLOW_ERROR;
1356
    }
1357
 
7 7u83 1358
    return PARAM(a);
2 7u83 1359
}
1360
 
1361
 
1362
/*
1363
** 	__TDFUs642u64:
1364
**
1365
**  Error only if "a" < 0.
1366
**  Return bits 0-31.
1367
*/
1368
 
7 7u83 1369
UINT64
1370
__TDFUs642u64(INT64 param_a)
2 7u83 1371
{
1372
    TDF_INT64	a;
1373
 
1374
    PARAM(a) = param_a;
1375
    CLEAR_ERRORS;
7 7u83 1376
    if (TDFUis_negative(a)) {	/* Check and cast */
2 7u83 1377
	OVERFLOW_ERROR;
1378
    }
1379
 
7 7u83 1380
    return UPARAM(a);
2 7u83 1381
}
1382
 
1383
 
1384
 
1385
 
1386
/*
1387
** 	__TDFUs_max:
1388
**
1389
**  Uses: (a>b) ? a : b		No errors.
1390
**
1391
*/
1392
 
7 7u83 1393
INT64
1394
__TDFUs_max(INT64 param_a, INT64 param_b)
2 7u83 1395
{
1396
    CLEAR_ERRORS;
1397
    if (__TDFUs_test(param_a, param_b) > 0) {
1398
	 return param_a;			/* a = max(a,b) */
1399
    }
7 7u83 1400
    return param_b;				/* b = max(a,b) */
2 7u83 1401
}
1402
 
1403
 
1404
/*
1405
** 	__TDFUu_max:
1406
**
1407
**  Uses: (a>b) ? a : b		No errors.
1408
**
1409
*/
1410
 
7 7u83 1411
UINT64
1412
__TDFUu_max(UINT64 param_a, UINT64 param_b)
2 7u83 1413
{
1414
    if (__TDFUu_test(param_a, param_b) > 0) {
1415
	 return param_a;			/* a = max(a,b) */
1416
    }
7 7u83 1417
    return param_b;				/* b = max(a,b) */
2 7u83 1418
}
1419
 
1420
 
1421
/*
1422
** 	__TDFUs_min:
1423
**
1424
**  Uses: (a<b) ? a : b		No errors.
1425
**
1426
*/
1427
 
7 7u83 1428
INT64
1429
__TDFUs_min(INT64 param_a, INT64 param_b)
2 7u83 1430
{
1431
    if (__TDFUs_test(param_a, param_b) < 0) {
1432
	return param_a;				/* a = min(a,b) */
1433
    }
1434
    return param_b;				/* b = min(a,b) */
1435
}
1436
 
1437
 
1438
/*
1439
** 	__TDFUu_min:
1440
**
1441
**  Uses: (a<b) ? a : b		No errors.
1442
**
1443
*/
1444
 
7 7u83 1445
UINT64
1446
__TDFUu_min(UINT64 param_a, UINT64 param_b)
2 7u83 1447
{
1448
    if (__TDFUu_test(param_a, param_b) < 0) {
1449
	return param_a;				/* a = min(a,b) */
1450
    }
1451
    return param_b;				/* b = min(a,b) */
1452
}
1453
 
1454
 
1455
 
1456
 
1457
/*
1458
**	TDFs_test:
1459
**
1460
**  Returns -1  if a < b;	This gives:  a op b <=> TDFs_test(a,b) op 0
1461
**           0  if a = b;
1462
**	     1  if a > b.
1463
**
1464
*/
1465
 
7 7u83 1466
int
1467
__TDFUs_test(INT64 param_a, INT64 param_b)
2 7u83 1468
{
1469
    TDF_INT64	a, b;
1470
 
1471
    PARAM(a) = param_a;
1472
    PARAM(b) = param_b;
1473
    CLEAR_ERRORS;
1474
    if (hi_32(a) < hi_32(b)) return -1;
1475
    if (hi_32(a) > hi_32(b)) return 1;
1476
    if (lo_32(a) < lo_32(b)) return -1;
1477
    if (lo_32(a) > lo_32(b)) return 1;
1478
    return 0;
1479
}
1480
 
1481
 
1482
/*
1483
**	__TDFUu_test:  as for __TDFUs_test, but for unsigned types.
1484
*/
1485
 
7 7u83 1486
int
1487
__TDFUu_test(UINT64 param_a, UINT64 param_b)
2 7u83 1488
{
1489
    TDF_INT64	a, b;
1490
 
1491
    UPARAM(a) = param_a;
1492
    UPARAM(b) = param_b;
1493
    CLEAR_ERRORS;
1494
 
1495
    if (hi_u32(a) < hi_u32(b)) return -1;
1496
    if (hi_u32(a) > hi_u32(b)) return 1;
1497
    if (lo_u32(a) < lo_u32(b)) return -1;
1498
    if (lo_u32(a) > lo_u32(b)) return 1;
1499
    return 0;
1500
}
1501
 
1502
 
1503
 
1504
 
1505
/*
1506
**	__TDFUand
1507
**
1508
**  ANDs the hi- and low-words together, and returns.
1509
*/
1510
 
7 7u83 1511
UINT64
1512
__TDFUand(UINT64 param_a, UINT64 param_b)
2 7u83 1513
{
1514
    TDF_INT64	a, b;
1515
 
1516
    UPARAM(a) = param_a;
1517
    UPARAM(b) = param_b;
1518
    CLEAR_ERRORS;
1519
 
1520
    hi_u32(a) = (hi_u32(a) & hi_u32(b));
1521
    lo_u32(a) = (lo_u32(a) & lo_u32(b));
7 7u83 1522
    return UPARAM(a);
2 7u83 1523
}
1524
 
1525
 
1526
/*
1527
**	__TDFUor
1528
**
1529
**  ORs the hi- and low-words together, and returns.
1530
*/
1531
 
7 7u83 1532
UINT64
1533
__TDFUor(UINT64 param_a, UINT64 param_b)
2 7u83 1534
{
1535
    TDF_INT64	a, b;
1536
 
1537
    UPARAM(a) = param_a;
1538
    UPARAM(b) = param_b;
1539
    CLEAR_ERRORS;
1540
 
1541
    hi_u32(a) = (hi_u32(a) | hi_u32(b));
1542
    lo_u32(a) = (lo_u32(a) | lo_u32(b));
7 7u83 1543
    return UPARAM(a);
2 7u83 1544
}
1545
 
1546
 
1547
 
1548
/*
1549
**	__TDFUxor
1550
**
1551
**  ORs the hi- and low-words together, and returns.
1552
*/
1553
 
7 7u83 1554
UINT64
1555
__TDFUxor(UINT64 param_a, UINT64 param_b)
2 7u83 1556
{
1557
    TDF_INT64	a, b;
1558
 
1559
    UPARAM(a) = param_a;
1560
    UPARAM(b) = param_b;
1561
    CLEAR_ERRORS;
1562
 
7 7u83 1563
    hi_u32(a) = (hi_u32(a)^ hi_u32(b));
1564
    lo_u32(a) = (lo_u32(a)^ lo_u32(b));
1565
    return UPARAM(a);
2 7u83 1566
}
1567
 
1568
 
1569
 
1570
/*
1571
**	__TDFUnot
1572
**
1573
**  XORs the hi- and low-words each with 0xffffffff
1574
*/
1575
 
7 7u83 1576
UINT64
1577
__TDFUnot(UINT64 param_a)
2 7u83 1578
{
1579
    TDF_INT64	a;
1580
 
1581
    UPARAM(a) = param_a;
1582
    CLEAR_ERRORS;
7 7u83 1583
    hi_u32(a) = hi_u32(a)^((UINT32)0xffffffff);
1584
    lo_u32(a) = lo_u32(a)^((UINT32)0xffffffff);
1585
    return UPARAM(a);
2 7u83 1586
}
1587
 
1588
 
1589
 
1590
 
1591
/* Functions only used for debug purposes - normally hidden */
1592
 
1593
#if DEBUG
7 7u83 1594
INT64
1595
make_INT64(INT32 new_hi, UINT32 new_lo)
2 7u83 1596
{
1597
    TDF_INT64	new_int;
1598
 
7 7u83 1599
    hi_32(new_int) = new_hi;
1600
    lo_32(new_int) = new_lo;
1601
    return PARAM(new_int);
2 7u83 1602
}
1603
 
1604
 
7 7u83 1605
UINT64
1606
make_UINT64(UINT32 new_hi, UINT32 new_lo)
2 7u83 1607
{
1608
    TDF_INT64	new_int;
1609
 
7 7u83 1610
    hi_u32(new_int) = new_hi;
1611
    lo_u32(new_int) = new_lo;
1612
    return UPARAM(new_int);
2 7u83 1613
}
1614
 
7 7u83 1615
void
1616
INT64_print(char * t1, INT64 a, char *t2)
2 7u83 1617
{
7 7u83 1618
    IGNORE printf("%s(%d,%u)%s", t1, (int)a.hi32, (unsigned)a.lo32, t2);
2 7u83 1619
    return;
1620
}
1621
 
7 7u83 1622
void
1623
UINT64_print(char * t1, UINT64 a, char * t2)
2 7u83 1624
{
7 7u83 1625
    IGNORE printf("%s(%u,%u)%s", t1, (unsigned)a.hi32, (unsigned)a.lo32, t2);
2 7u83 1626
    return;
1627
}
1628
#endif  /* DEBUG */