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