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