1 #include "libnwcc.h"
2 #include <limits.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 /* Macros for bitwise access.. NOTE: These are little-endian */
8 #define GET_BIT(ar, idx) \
9 !!((ar)[(idx) / CHAR_BIT] & (1 << (idx) % CHAR_BIT))
10
11 #define SET_BIT(ar, idx) \
12 ((ar)[(idx) / CHAR_BIT] |= (1 << (idx) % CHAR_BIT))
13
14 #define CLR_BIT(ar, idx) \
15 ((ar)[(idx) / CHAR_BIT] &= ~(1 << (idx) % CHAR_BIT))
16
17 static void
do_reverse(unsigned char * data,int data_size)18 do_reverse(unsigned char *data, int data_size) {
19 /* Convert from little to big endian */
20 unsigned char *start = data;
21 unsigned char *end = data +
22 (data_size / 8 - 1);
23 do {
24 unsigned char tmp = *start;
25 *start = *end;
26 *end = tmp;
27 } while (++start < --end);
28 }
29
30 /*
31 * This function must be called on big endian hosts to
32 * convert data to little endian format before processing,
33 * and afterwards to convert the result back to big endian.
34 * This is just a quick temporary kludge to get this code
35 * ``up and running'' on PowerPC. Performance is TERRIBLE
36 */
37 static void
correct_endianness(unsigned char * data,int data_size)38 correct_endianness(unsigned char *data, int data_size) {
39 /* XXX cross-compilation */
40 int x = 123;
41
42 if (((unsigned char *)&x)[sizeof(int) - 1] == 123) {
43 do_reverse(data, data_size);
44 }
45 }
46
47
48 #if 0
49 static void
50 dump_llong(unsigned char *p, int data_size) {
51 unsigned char *uc;
52
53 for (uc = p + /*7*/ (data_size / 8) - 1; uc >= p; --uc) {
54 int i;
55
56 for (i = 7; i >= 0; --i) {
57 putchar('0' + GET_BIT(uc, i));
58 }
59 }
60 putchar('\n');
61 }
62 #endif
63
64
65 static int
skip_zeros(unsigned char * num,int data_size)66 skip_zeros(unsigned char *num, int data_size) {
67 int i;
68 int j = CHAR_BIT - 1;
69 unsigned char mask;
70
71 for (i = /*7*/data_size / 8 - 1; i >= 0; --i) {
72 if (num[i] != 0) {
73 break;
74 }
75 }
76 if (i == -1) {
77 return -1;
78 }
79 for (mask = 1 << (CHAR_BIT - 1); (num[i] & mask) == 0; mask >>= 1)
80 --j;
81 return (i * CHAR_BIT) + j;
82
83 }
84
85 void
__nwcc_sub(unsigned char * dest,unsigned char * src,int maxbit,int wrong_endianness,int data_size)86 __nwcc_sub(/*unsigned char *res,*/ unsigned char *dest, unsigned char *src,
87 int maxbit, int wrong_endianness, int data_size) {
88
89 int i;
90 int carry = 0;
91 unsigned char res[8];
92
93 if (wrong_endianness) {
94 correct_endianness(dest, data_size);
95 correct_endianness(src, data_size);
96 }
97
98 memset(res, 0, 8);
99 for (i = 0; i < maxbit || (carry && i < /*64*/data_size); ++i) {
100 int dbitval = GET_BIT(dest, i);
101 int sbitval = GET_BIT(src, i);
102 int resbit;
103
104 if (carry) {
105 if (sbitval) {
106 sbitval = 0;
107 } else {
108 sbitval = 1;
109 carry = 0;
110 }
111 }
112
113 resbit = dbitval - sbitval;
114 if (resbit < 0) {
115 carry = 1;
116 }
117 if (resbit) {
118 SET_BIT(res, i);
119 }
120 }
121 memcpy(dest, res, 8);
122 if (wrong_endianness) {
123 correct_endianness(dest, data_size);
124 }
125 }
126
127 void
__nwcc_add(unsigned char * dest,unsigned char * src,int data_size,int wrong_endianness)128 __nwcc_add(unsigned char *dest, unsigned char *src,
129 int data_size, int wrong_endianness) {
130
131 int carry = 0;
132 int i;
133 unsigned char res[8];
134
135 if (wrong_endianness) {
136 correct_endianness(dest, data_size);
137 correct_endianness(src, data_size);
138 }
139
140 memset(res, 0, 8);
141
142 for (i = 0; i < /*64*/data_size; ++i) {
143 int dbitval = GET_BIT(dest, i);
144 int sbitval = GET_BIT(src, i);
145 int resbit;
146
147 if (dbitval && sbitval) {
148 if (carry) {
149 resbit = 1;
150 } else {
151 resbit = 0;
152 }
153 carry = 1;
154 } else if (carry) {
155 if (dbitval || sbitval) {
156 resbit = 0;
157 } else {
158 resbit = 1;
159 carry = 0;
160 }
161 } else {
162 resbit = dbitval + sbitval;
163 carry = 0;
164 }
165
166 if (resbit) {
167 SET_BIT(res, i);
168 }
169 }
170 memcpy(dest, res, 8);
171 if (wrong_endianness) {
172 correct_endianness(dest, data_size);
173 }
174 }
175
176 void
__nwcc_shift_right(unsigned char * dest,unsigned src,int data_size,int wrong_endianness)177 __nwcc_shift_right(unsigned char *dest, unsigned src,
178 int data_size, int wrong_endianness) {
179 int kill_bytes = src / 8;
180 int nbytes = data_size / 8;
181 int shift_bits;
182 unsigned char *p;
183 unsigned char *destp;
184
185 if (wrong_endianness) {
186 correct_endianness(dest, data_size);
187 }
188 if (kill_bytes) {
189 destp = dest;
190 for (p = dest+kill_bytes; p < dest+nbytes; ++p) {
191 *destp++ = *p;
192 }
193 while (destp < dest+nbytes) {
194 *destp++ = 0;
195 }
196 }
197 if ((shift_bits = src - (kill_bytes * 8)) > 0) {
198 int saved_bits = 0;
199
200 for (p = dest+nbytes-1; p >= dest; --p) {
201 int new_saved_bits = *p << (8-shift_bits);
202
203 *p = (*p >> shift_bits) | saved_bits;
204 saved_bits = new_saved_bits;
205 }
206 }
207 if (wrong_endianness) {
208 correct_endianness(dest, data_size);
209 }
210 }
211
212 void
__nwcc_shift_left(unsigned char * dest,unsigned src,int data_size,int wrong_endianness)213 __nwcc_shift_left(unsigned char *dest, unsigned src,
214 int data_size, int wrong_endianness) {
215
216 int kill_bytes = src / 8;
217 int nbytes = data_size / 8;
218 int shift_bits;
219 unsigned char *p;
220 unsigned char *destp;
221
222 if (wrong_endianness) {
223 correct_endianness(dest, data_size);
224 }
225 if (kill_bytes) {
226 destp = dest+nbytes-1;
227 for (p = dest+nbytes-1-kill_bytes; p >= dest; --p) {
228 *destp-- = *p;
229 }
230 while (destp >= dest) {
231 *destp-- = 0;
232 }
233 }
234
235 if ((shift_bits = src - (kill_bytes * 8)) > 0) {
236 int saved_bits = 0;
237
238 for (p = dest; p < dest+nbytes; ++p) {
239 int new_saved_bits = *p >> (8-shift_bits);
240
241 *p = (*p << shift_bits) | saved_bits;
242 saved_bits = new_saved_bits;
243 }
244 }
245 if (wrong_endianness) {
246 correct_endianness(dest, data_size);
247 }
248 }
249
250
251
252 static int
no_fit(unsigned char * dest,unsigned char * src,int chunkstart,int destbit,int srcbit)253 no_fit(
254 unsigned char *dest, unsigned char *src,
255 int chunkstart, int destbit, int srcbit) {
256
257 int ndestbits;
258
259
260 #if 0
261 printf("no_fit() dest %d, src %d\n", destbit, srcbit);
262 {
263 unsigned char *tmp;
264 for (tmp = dest; tmp < dest+8; ++tmp) {
265 printf("%02x ", *tmp);
266 }
267 putchar(10);
268 }
269
270
271 {
272 unsigned char *tmp;
273 for (tmp = src; tmp < src+8; ++tmp) {
274 printf("%02x ", *tmp);
275 }
276 putchar(10);
277 }
278 #endif
279
280
281
282 while (GET_BIT(dest, destbit) == 0) {
283 --destbit;
284 }
285 ndestbits = destbit - chunkstart;
286
287 if (ndestbits < srcbit) {
288 /* Less dest bits selected */
289 return 1;
290 } else if (ndestbits > srcbit) {
291 /* Definitely a fit */
292 return 0;
293 } else {
294 /* Compare all bits */
295 int i;
296 int j;
297
298 for (i = destbit, j = srcbit; i >= chunkstart; --i, --j) {
299 int dbitval = GET_BIT(dest, i);
300 int sbitval = GET_BIT(src, j);
301
302 if (dbitval < sbitval) {
303 return 1;
304 } else if (dbitval > sbitval) {
305 return 0;
306 }
307 }
308 }
309 return 0;
310 }
311
312 static void
get_value_range(unsigned char * res,unsigned char * src,int start,int end)313 get_value_range(unsigned char *res, unsigned char *src, int start, int end) {
314 int i;
315 int j;
316
317 memset(res, 0, 8);
318 for (i = start, j = 0; i <= end; ++i, ++j) {
319 int val = GET_BIT(src, i);
320
321 if (val) {
322 SET_BIT(res, j);
323 } else {
324 CLR_BIT(res, j);
325 }
326 }
327 }
328
329
330 static void
prepend_bit(unsigned char * dest,int newbit)331 prepend_bit(unsigned char *dest, int newbit) {
332 int i;
333
334 for (i = 7; i >= 0; --i) {
335 dest[i] <<= 1;
336 if (i > 0) {
337 int prev;
338
339 prev = GET_BIT(dest, (i - 1) * 8 + 7);
340 if (prev) {
341 SET_BIT(dest, i * 8);
342 } else {
343 CLR_BIT(dest, i * 8);
344 }
345 } else {
346 if (newbit) {
347 SET_BIT(dest, 0);
348 } else {
349 CLR_BIT(dest, 0);
350 }
351 }
352 }
353 }
354
355 /*
356 * Division of two unsigned 64bit values. Though this is hardcoded for 64bit
357 * right now, it is in principle completely independent of the size of its
358 * input and should be able to deal with arbitrarily sized integers.
359 * The result is stored in dest. If want_remainder is nonzero, the result is
360 * the remainder (useful for modulo.)
361 *
362 * This was hard to write and is probably less efficient than it could be.
363 */
364 void
__nwcc_ulldiv(unsigned char * dest,unsigned char * src,int want_remainder,int data_size)365 __nwcc_ulldiv(
366 unsigned char *dest,
367 unsigned char *src,
368 int want_remainder,
369 int data_size) {
370
371 int destbit;
372 int srcbit;
373 int curbit;
374 int initial;
375 int nbits;
376 int resbits = 0;
377 unsigned char destbuf[8];
378 unsigned char result[8];
379
380 correct_endianness(src, data_size);
381 correct_endianness(dest, data_size);
382
383 memset(result, 0, sizeof result);
384 if ((destbit = skip_zeros(dest, data_size)) == -1) {
385 /* 0 / something is 0 */
386 memcpy(dest, result, sizeof result);
387 return;
388 } else if ((srcbit = skip_zeros(src, data_size)) == -1) {
389 puts("DIVISION BY ZERO ERROR");
390 abort();
391 }
392
393 #if 0
394 if (destbit < 32 && srcbit < 32) {
395 /* Wow, no trickery required */
396 return;
397 }
398 #endif
399
400 /*
401 * Do the school method:
402 * 123 / 11 = 11
403 * 11
404 * --
405 * 13
406 * 11
407 * ...
408 */
409 curbit = destbit;
410 memset(destbuf, 0, sizeof destbuf);
411
412 nbits = 0, ++curbit;
413
414 for (initial = 1;; initial = 0) {
415
416 for (;;) {
417 /* Get one more bit */
418 if (--curbit == -1) {
419 /* Doesn't fit */
420 break;
421 } else {
422 int newbit = GET_BIT(dest, curbit);
423
424 prepend_bit(destbuf, newbit);
425 /*
426 * 02/20/09: There was an overflow for
427 * very large values in no_fit(). But
428 * we can't break if nbits >= data_size
429 * because that misses the final
430 * iteration
431 */
432 if (nbits < data_size - 1) {
433 ++nbits;
434 } else {
435 ;
436 }
437
438 if (!initial) {
439 if (no_fit(destbuf, src, 0,
440 nbits, srcbit)) {
441 #if 0
442 CLR_BIT(result, 63-resbits);
443 #endif
444 CLR_BIT(result, data_size-1-resbits);
445 ++resbits;
446 } else {
447 /*
448 * Divisor now fits into
449 * dividend
450 */
451 break;
452 }
453 } else if (!no_fit(destbuf, src, 0,
454 nbits, srcbit)) {
455 /*
456 * Divisor fits into initial sub-
457 * dividend
458 */
459 break;
460 }
461 }
462 }
463
464 if (curbit > -1) {
465 /*unsigned char tmp[8];*/
466
467 __nwcc_sub(/*tmp,*/ destbuf, src, destbit, 0, data_size);
468
469 /* Add a 1 to the result */
470 #if 0
471 SET_BIT(result, 63 - resbits);
472 #endif
473 SET_BIT(result, data_size - 1 - resbits);
474 ++resbits;
475 /*memcpy(destbuf, tmp, 8);*/
476 if ((nbits = skip_zeros(destbuf, data_size)) == -1) {
477 nbits = 0;
478 }
479 } else {
480 if (want_remainder) {
481 memcpy(dest, destbuf, 8);
482 correct_endianness(dest, data_size);
483 return;
484 }
485 break;
486 }
487 }
488
489 /*
490 * Now the result is stored at the end of the result buffer, so we have
491 * to move it to the start as necessary
492 */
493 #if 0
494 get_value_range(dest, result, 64 - resbits, 63);
495 #endif
496 get_value_range(dest, result, data_size - resbits, data_size - 1);
497 correct_endianness(dest, data_size);
498 }
499
500 void
__nwcc_negate(unsigned char * dest,int data_size)501 __nwcc_negate(unsigned char *dest, int data_size) {
502 int i;
503 unsigned char src[8] = { 1 };
504
505 for (i = 0; i < /*64*/data_size; ++i) {
506 int bit = GET_BIT(dest, i);
507
508 if (bit) {
509 CLR_BIT(dest, i);
510 } else {
511 SET_BIT(dest, i);
512 }
513 }
514 __nwcc_add(dest, src, data_size, 0);
515 }
516
517 void
__nwcc_lldiv(unsigned char * dest,unsigned char * src,int want_remainder,int data_size)518 __nwcc_lldiv(
519 unsigned char *dest,
520 unsigned char *src,
521 int want_remainder,
522 int data_size) {
523
524 int neg_dest = 0;
525 int neg_src = 0;
526
527 correct_endianness(src, data_size);
528 correct_endianness(dest, data_size);
529 if (GET_BIT(dest, data_size - 1)) {
530 /* Sign bit set! */
531 neg_dest = 1;
532 __nwcc_negate(dest, data_size);
533 }
534 if (GET_BIT(src, data_size - 1)) {
535 /* Sign bit set! */
536 neg_src = 1;
537 __nwcc_negate(src, data_size);
538 }
539 correct_endianness(dest, data_size);
540 correct_endianness(src, data_size);
541
542 __nwcc_ulldiv(dest, src, want_remainder, data_size);
543 if (neg_dest || neg_src) {
544 if (neg_dest != neg_src) {
545 /*
546 * One side isn't negative - make result negative
547 * (if both were negative, the result is positive)
548 *
549 * 06/22/08: This was missing: A negative value
550 * modulo a positive one does yield a negative
551 * result, but a positive value modulo negative
552 * does not!
553 */
554 if (!want_remainder || !neg_src) {
555 correct_endianness(dest, data_size);
556 __nwcc_negate(dest, data_size);
557 correct_endianness(dest, data_size);
558 }
559 } else {
560 /*
561 * 06/22/08: Negative % negative yields a negative
562 * result!
563 */
564 if (want_remainder) {
565 correct_endianness(dest, data_size);
566 __nwcc_negate(dest, data_size);
567 correct_endianness(dest, data_size);
568 }
569 }
570 }
571 }
572
573
574 void
__nwcc_ullmul(unsigned char * dest,unsigned char * src,int data_size)575 __nwcc_ullmul(unsigned char *dest, unsigned char *src, int data_size) {
576 int destbit;
577 int srcbit;
578 int i;
579 int j;
580 unsigned char result[8];
581 unsigned char tmp[8];
582
583 correct_endianness(dest, data_size);
584 correct_endianness(src, data_size);
585
586 memset(result, 0, sizeof result);
587 if ((destbit = skip_zeros(dest, data_size)) == -1
588 || (srcbit = skip_zeros(src, data_size)) == -1) {
589 /* 0 * something = 0 */
590 memcpy(dest, result, sizeof result);
591 return;
592 }
593
594 #if 0
595 printf("hmm %llu, %llu\n", *(unsigned long long *)dest,
596 *(unsigned long long *)src);
597 printf(" ");
598 dump_llong((void *)dest, 64);
599 printf("*");
600 dump_llong((void *)src, 64);
601 #endif
602 /*
603 * School method -
604 * 1101 * 101
605 * 1101
606 * 0000
607 * 1101
608 * -------
609 * 1000001
610 */
611 for (i = 0; i <= srcbit; ++i) {
612 memset(tmp, 0, 8);
613 if (GET_BIT(src, i) == 0) {
614 continue;
615 }
616 for (j = 0; j <= destbit; ++j) {
617 int idx = i + j;
618
619 if (idx > data_size - 1) {
620 /*
621 * 06/22/08: This was missing: Don't step over
622 * the bounds of the number!
623 */
624 break;
625 }
626 if (GET_BIT(dest, j)) {
627 SET_BIT(tmp, idx);
628 } else {
629 CLR_BIT(tmp, idx);
630 }
631 }
632 #if 0
633 printf(" line for src bit %d: ", i);
634 dump_llong((void *)tmp, 64);
635 printf(" ");
636 dump_llong((void *)tmp, 64);
637 printf(" +");
638 dump_llong((void *)result, 64);
639 #endif
640 __nwcc_add(result, tmp, data_size, 0);
641 #if 0
642 printf(" =");
643 dump_llong((void *)result, 64);
644 puts("===");
645 #endif
646 }
647 memcpy(dest, result, 8);
648 correct_endianness(dest, data_size);
649 #if 0
650 puts("===");
651 printf(" ");
652 dump_llong((void *)dest, 64);
653 #endif
654 }
655
656 void
__nwcc_llmul(unsigned char * dest,unsigned char * src,int data_size)657 __nwcc_llmul(unsigned char *dest, unsigned char *src, int data_size) {
658 int neg_dest = 0;
659 int neg_src = 0;
660
661 correct_endianness(dest, data_size);
662 correct_endianness(src, data_size);
663 if (GET_BIT(dest, data_size - 1)) {
664 /* Sign bit set! */
665 neg_dest = 1;
666 __nwcc_negate(dest, data_size);
667 }
668 if (GET_BIT(src, data_size - 1)) {
669 /* Sign bit set! */
670 neg_src = 1;
671 __nwcc_negate(src, data_size);
672 }
673 correct_endianness(dest, data_size);
674 correct_endianness(src, data_size);
675 __nwcc_ullmul(dest, src, data_size);
676 if (neg_dest || neg_src) {
677 if (neg_dest != neg_src) {
678 /*
679 * One side isn't negative - make result negative
680 * (if both were negative, the result is positive)
681 */
682 correct_endianness(dest, data_size);
683 __nwcc_negate(dest, data_size);
684 correct_endianness(dest, data_size);
685 }
686 }
687 }
688
689
690 #if 0
691 void
692 dump_item(void *p, int size) {
693 int i;
694 unsigned char *ucp = p;
695
696 for (i = 0; i < size; ++i) {
697 printf("%02x ", *ucp++);
698 }
699 putchar('\n');
700
701 ucp = p;
702 for (i = 0; i < size; ++i) {
703 int j;
704 for (j = 0; j < 8; ++j) {
705 putchar('0' + !!(*ucp & (1 << (7 - j))));
706 }
707 ++ucp;
708 }
709 putchar('\n');
710 }
711 #endif
712
713
714 void
__nwcc_conv_to_ldouble(unsigned char * dest,unsigned char * src)715 __nwcc_conv_to_ldouble(unsigned char *dest, unsigned char *src) {
716 if (1) {
717 unsigned int exp;
718 unsigned int quiet_nan;
719 unsigned int mantissa0;
720 unsigned int mantissa1;
721
722 #if 0
723 printf("src double = %f\n", *(double *)src);
724 dump_item(src,8);
725 #endif
726
727 memset(dest, 0, 16);
728
729 /* Set sign bit */
730 if (src[0] & 0x80) {
731 dest[0] = 0x80;
732 } else {
733 dest[0] = 0;
734 }
735
736 /* Get exponent */
737 exp = ((src[0] & 0x7f) << 4) | ((src[1] & 0xf0) >> 4);
738
739 quiet_nan = !!(src[1] & 0x10);
740
741 (void) quiet_nan;
742
743 /* Get mantissa - upper 3 bits of last byte plus 2 full bytes */
744 mantissa0 = /*(src[1] & 0xf) << 16) |*/ (src[2] << 8) | src[3];
745 memcpy(&mantissa1, src+4, sizeof mantissa1);
746
747 #if 0
748 printf("input double ........ sign = %x exp = %x quiet = %x mant = %x %x\n",
749 sign, exp, quiet_nan, mantissa0, mantissa1);
750 #endif
751
752 /* Convert to long double */
753 exp <<= 4; /* extend 11 bits to 15 bits */
754 exp |= src[1] & 0xf; /* 4 highest mantissa bits of double become part of the exponent */
755
756 dest[0] |= (exp >> 8) & 0x7f; /* Get upper 7 bits */
757 dest[1] = exp & 0xff; /* Get lower 8 bits */
758
759 /* dest[2] = 0;*/ /* empty */
760 /* dest[3] = 0;*/ /* empty */
761
762 mantissa0 <<= 16; /* extend from 20 to 32 bits */
763 memcpy(dest+/*4*/2, &mantissa0, sizeof mantissa0);
764 memcpy(dest+/*8*/4, &mantissa1, sizeof mantissa1);
765 memset(dest+10/*2*/, 0, /*4*/6);
766 #if 0
767 printf("dest ldouble = %f\n", *(long double *)dest);
768 dump_item(dest, 16);
769 #endif
770 }
771 }
772
773 void
__nwcc_conv_from_ldouble(unsigned char * dest,unsigned char * src)774 __nwcc_conv_from_ldouble(unsigned char *dest, unsigned char *src) {
775 if (1) {
776 #if 0
777 unsigned int exp;
778 unsigned int quiet_nan;
779 unsigned int mantissa0;
780 unsigned int mantissa1;
781 unsigned int sign;
782 #endif
783
784
785 memcpy(dest, src, 8);
786 return;
787
788
789
790
791 #if 0
792
793 memset(dest, 0, 8);
794
795 /* Set sign bit */
796 sign = !!(src[0] & 0x80);
797
798 /* Get exponent */
799 exp = ((src[0] & 0x7f) << 8) | src[1];
800
801 /* Get mantissa - upper 3 bits of last byte plus 2 full bytes */
802 memcpy(&mantissa0, src+4, sizeof mantissa0);
803 memcpy(&mantissa1, src+8, sizeof mantissa1);
804
805 #if 0
806 printf("sign = %x exp = %x quiet = %x mant = %x %x\n",
807 sign, exp, quiet_nan, mantissa0, mantissa1);
808 #endif
809
810 /* Now convert to double */
811 if (sign) {
812 dest[0] = 0x80;
813 } else {
814 dest[0] = 0;
815 }
816
817
818 /* Lower 4 exponent bits become upper 4 mantissa bits */
819 dest[1] = exp & 0xf;
820
821
822 exp >>= 4;
823 exp &= 0x7ff; /* 11 bits */
824 dest[0] |= (exp >> 4); /* get upper 7 bits */
825 dest[1] |= (exp & 0xf) << 4; /* get lower 4 bits */
826 mantissa0 &= 0xfffff; /* 20 bits */
827 dest[1] |= mantissa0 >> 16; /* get upper 4 bits */
828 dest[2] = (mantissa0 >> 8) & 0xff; /* set whole byte */
829 dest[3] = (mantissa0 >> 0) & 0xff; /* set whole byte */
830 memcpy(dest+4, &mantissa1, sizeof mantissa1); /* mantissa 1 has same size */
831 #if 0
832 printf("res double = %f\n", *(double *)dest);
833 dump_item(dest, 8);
834 #endif
835 #endif
836 }
837 }
838
839
840 void
__nwcc_stack_corrupt(void)841 __nwcc_stack_corrupt(void) {
842 printf("ERROR: Stack corruption detected, cannot continue program\n");
843 printf(" execution. Calling abort()\n");
844 abort();
845 }
846
847 void
llong_to_hex(char * out,unsigned char * in,int is_bigend)848 llong_to_hex(char *out, unsigned char *in, int is_bigend) {
849 char *p;
850 char buf[5];
851 int i;
852 int j;
853
854 *out++ = '0';
855 *out++ = 'x';
856
857 /* 4 binary digits = 1 hex digit. Life's so easy. */
858 p = (out + 64 / 4);
859 *p-- = 0;
860
861 if (is_bigend) {
862 static unsigned char tmp[8];
863 unsigned char *sp;
864 unsigned char *ep;
865
866 memcpy(tmp, in, 8);
867 sp = tmp;
868 ep = tmp+7;
869 do {
870 unsigned char c = *sp;
871 *sp = *ep;
872 *ep = c;
873 } while (++sp < --ep);
874 in = tmp;
875 }
876
877 j = 3;
878 for (i = 0; i < 64; ++i) {
879 buf[j] = '0' + GET_BIT(in, i);
880 if (j == 0) {
881 buf[4] = 0;
882 *p-- = "0123456789abcdef"[strtol(buf, NULL, 2)];
883 j = 3;
884 } else {
885 --j;
886 }
887 }
888 }
889
890 #ifdef TEST_LIBNWCC
891
892 int
main()893 main() {
894 long long l1 = 246;
895 long long l2 = 5;
896 long long testdest[128];
897 long long testsrc[128];
898 long long gcc_res;
899 int i;
900 int i1;
901 int i2;
902 int testdest_int[128];
903 int testsrc_int[128];
904
905 #if 0
906 memset(&testdest[0], 0, 8);
907 ((char *)&testdest[0])[7] = 1;
908 dump_llong((void *)&testdest[0], 64);
909 __nwcc_shift_left((void *)&testdest[0], 9, 64, 1);
910 dump_llong((void *)&testdest[0], 64);
911 return 0;
912 #endif
913 srand(time(NULL));
914 for (i = 0; i < 128; ++i) {
915 /* XXX This stuff is crude ... */
916 testdest[i] = rand();
917 while (testdest[i] < UINT_MAX) {
918 testdest[i] += rand();
919 }
920 testsrc[i] = rand();
921 if (testsrc[i] == 0) ++testsrc[i];
922 while (testdest[i] < testsrc[i]) {
923 testdest[i] += rand();
924 }
925 l1 = testdest[i];
926 l2 = testsrc[i];
927 gcc_res = l1 / l2;
928 __nwcc_ulldiv((void *)&testdest[i], (void *)&testsrc[i], 0, 64);
929 #if 0
930 gcc_res = l1 * l2;
931 __nwcc_llmul((void *)&testdest[i], (void *)&testsrc[i], 64);
932 #endif
933 #if 0
934 gcc_res = l1 + l2;
935 __nwcc_add((void *)&testdest[i],
936 (void *)&testsrc[i], 64, 1);
937 #endif
938 gcc_res >>= 9;
939
940 __nwcc_shift_right((void *)&testdest[i], 9 , 64, 1);
941
942 if (testdest[i] != gcc_res) {
943
944 puts("BAD RESULT");
945 } else {
946 printf("worked! %lld %lld (%lld,%lld)\n",
947 testdest[i], gcc_res, l1, l2);
948 }
949 }
950 return 0;
951
952 for (i = 0; i < 128; ++i) {
953 /* XXX This stuff is crude ... */
954 int gcc_res_int;
955
956 testdest_int[i] = rand();
957 testsrc_int[i] = rand();
958 while (testdest_int[i] < testsrc_int[i]) {
959 testdest_int[i] += rand();
960 }
961 i1 = testdest_int[i];
962 i2 = testsrc_int[i];
963 gcc_res_int = i1 / i2;
964 __nwcc_ulldiv((void *)&testdest_int[i], (void *)&testsrc_int[i], 0, 32);
965 if (testdest_int[i] != gcc_res_int) {
966 puts("BAD RESULT");
967 } else {
968 printf("worked! %d %d (%d,%d)\n",
969 testdest_int[i], gcc_res_int, i1, i2);
970 }
971 }
972
973 return 0;
974 }
975
976 #endif
977
978
979