xref: /inferno-os/libkern/vlrt-spim.c (revision cd17ce433410c01516d7ba8f052a6c5b67b0e2d5)
1 typedef	unsigned long	ulong;
2 typedef	unsigned int	uint;
3 typedef	unsigned short	ushort;
4 typedef	unsigned char	uchar;
5 typedef	signed char	schar;
6 
7 #define	SIGN(n)	(1UL<<(n-1))
8 
9 typedef	struct	Vlong	Vlong;
10 struct	Vlong
11 {
12 	union
13 	{
14 		struct
15 		{
16 			ulong	lo;
17 			ulong	hi;
18 		};
19 	};
20 };
21 
22 void	abort(void);
23 
24 void
25 _addv(Vlong *r, Vlong a, Vlong b)
26 {
27 	ulong lo, hi;
28 
29 	lo = a.lo + b.lo;
30 	hi = a.hi + b.hi;
31 	if(lo < a.lo)
32 		hi++;
33 	r->lo = lo;
34 	r->hi = hi;
35 }
36 
37 void
38 _subv(Vlong *r, Vlong a, Vlong b)
39 {
40 	ulong lo, hi;
41 
42 	lo = a.lo - b.lo;
43 	hi = a.hi - b.hi;
44 	if(lo > a.lo)
45 		hi--;
46 	r->lo = lo;
47 	r->hi = hi;
48 }
49 
50 
51 void
52 _d2v(Vlong *y, double d)
53 {
54 	union { double d; struct Vlong; } x;
55 	ulong xhi, xlo, ylo, yhi;
56 	int sh;
57 
58 	x.d = d;
59 
60 	xhi = (x.hi & 0xfffff) | 0x100000;
61 	xlo = x.lo;
62 	sh = 1075 - ((x.hi >> 20) & 0x7ff);
63 
64 	ylo = 0;
65 	yhi = 0;
66 	if(sh >= 0) {
67 		/* v = (hi||lo) >> sh */
68 		if(sh < 32) {
69 			if(sh == 0) {
70 				ylo = xlo;
71 				yhi = xhi;
72 			} else {
73 				ylo = (xlo >> sh) | (xhi << (32-sh));
74 				yhi = xhi >> sh;
75 			}
76 		} else {
77 			if(sh == 32) {
78 				ylo = xhi;
79 			} else
80 			if(sh < 64) {
81 				ylo = xhi >> (sh-32);
82 			}
83 		}
84 	} else {
85 		/* v = (hi||lo) << -sh */
86 		sh = -sh;
87 		if(sh <= 10) {
88 			ylo = xlo << sh;
89 			yhi = (xhi << sh) | (xlo >> (32-sh));
90 		} else {
91 			/* overflow */
92 			yhi = d;	/* causes something awful */
93 		}
94 	}
95 	if(x.hi & SIGN(32)) {
96 		if(ylo != 0) {
97 			ylo = -ylo;
98 			yhi = ~yhi;
99 		} else
100 			yhi = -yhi;
101 	}
102 
103 	y->hi = yhi;
104 	y->lo = ylo;
105 }
106 
107 void
108 _f2v(Vlong *y, float f)
109 {
110 	_d2v(y, f);
111 }
112 
113 double
114 _v2d(Vlong x)
115 {
116 	if(x.hi & SIGN(32)) {
117 		if(x.lo) {
118 			x.lo = -x.lo;
119 			x.hi = ~x.hi;
120 		} else
121 			x.hi = -x.hi;
122 		return -((long)x.hi*4294967296. + x.lo);
123 	}
124 	return (long)x.hi*4294967296. + x.lo;
125 }
126 
127 float
128 _v2f(Vlong x)
129 {
130 	return _v2d(x);
131 }
132 
133 static void
134 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
135 {
136 	ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
137 	int i;
138 
139 	numhi = num.hi;
140 	numlo = num.lo;
141 	denhi = den.hi;
142 	denlo = den.lo;
143 
144 	/*
145 	 * get a divide by zero
146 	 */
147 	if(denlo==0 && denhi==0) {
148 		numlo = numlo / denlo;
149 	}
150 
151 	/*
152 	 * set up the divisor and find the number of iterations needed
153 	 */
154 	if(numhi >= SIGN(32)) {
155 		quohi = SIGN(32);
156 		quolo = 0;
157 	} else {
158 		quohi = numhi;
159 		quolo = numlo;
160 	}
161 	i = 0;
162 	while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
163 		denhi = (denhi<<1) | (denlo>>31);
164 		denlo <<= 1;
165 		i++;
166 	}
167 
168 	quohi = 0;
169 	quolo = 0;
170 	for(; i >= 0; i--) {
171 		quohi = (quohi<<1) | (quolo>>31);
172 		quolo <<= 1;
173 		if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
174 			t = numlo;
175 			numlo -= denlo;
176 			if(numlo > t)
177 				numhi--;
178 			numhi -= denhi;
179 			quolo |= 1;
180 		}
181 		denlo = (denlo>>1) | (denhi<<31);
182 		denhi >>= 1;
183 	}
184 
185 	if(q) {
186 		q->lo = quolo;
187 		q->hi = quohi;
188 	}
189 	if(r) {
190 		r->lo = numlo;
191 		r->hi = numhi;
192 	}
193 }
194 
195 void
196 _divvu(Vlong *q, Vlong n, Vlong d)
197 {
198 
199 	if(n.hi == 0 && d.hi == 0) {
200 		q->hi = 0;
201 		q->lo = n.lo / d.lo;
202 		return;
203 	}
204 	dodiv(n, d, q, 0);
205 }
206 
207 void
208 _modvu(Vlong *r, Vlong n, Vlong d)
209 {
210 
211 	if(n.hi == 0 && d.hi == 0) {
212 		r->hi = 0;
213 		r->lo = n.lo % d.lo;
214 		return;
215 	}
216 	dodiv(n, d, 0, r);
217 }
218 
219 static void
220 vneg(Vlong *v)
221 {
222 
223 	if(v->lo == 0) {
224 		v->hi = -v->hi;
225 		return;
226 	}
227 	v->lo = -v->lo;
228 	v->hi = ~v->hi;
229 }
230 
231 void
232 _divv(Vlong *q, Vlong n, Vlong d)
233 {
234 	long nneg, dneg;
235 
236 	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
237 		q->lo = (long)n.lo / (long)d.lo;
238 		q->hi = ((long)q->lo) >> 31;
239 		return;
240 	}
241 	nneg = n.hi >> 31;
242 	if(nneg)
243 		vneg(&n);
244 	dneg = d.hi >> 31;
245 	if(dneg)
246 		vneg(&d);
247 	dodiv(n, d, q, 0);
248 	if(nneg != dneg)
249 		vneg(q);
250 }
251 
252 void
253 _modv(Vlong *r, Vlong n, Vlong d)
254 {
255 	long nneg, dneg;
256 
257 	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
258 		r->lo = (long)n.lo % (long)d.lo;
259 		r->hi = ((long)r->lo) >> 31;
260 		return;
261 	}
262 	nneg = n.hi >> 31;
263 	if(nneg)
264 		vneg(&n);
265 	dneg = d.hi >> 31;
266 	if(dneg)
267 		vneg(&d);
268 	dodiv(n, d, 0, r);
269 	if(nneg)
270 		vneg(r);
271 }
272 
273 void
274 _rshav(Vlong *r, Vlong a, int b)
275 {
276 	long t;
277 
278 	t = a.hi;
279 	if(b >= 32) {
280 		r->hi = t>>31;
281 		if(b >= 64) {
282 			/* this is illegal re C standard */
283 			r->lo = t>>31;
284 			return;
285 		}
286 		r->lo = t >> (b-32);
287 		return;
288 	}
289 	if(b <= 0) {
290 		r->hi = t;
291 		r->lo = a.lo;
292 		return;
293 	}
294 	r->hi = t >> b;
295 	r->lo = (t << (32-b)) | (a.lo >> b);
296 }
297 
298 void
299 _rshlv(Vlong *r, Vlong a, int b)
300 {
301 	ulong t;
302 
303 	t = a.hi;
304 	if(b >= 32) {
305 		r->hi = 0;
306 		if(b >= 64) {
307 			/* this is illegal re C standard */
308 			r->lo = 0;
309 			return;
310 		}
311 		r->lo = t >> (b-32);
312 		return;
313 	}
314 	if(b <= 0) {
315 		r->hi = t;
316 		r->lo = a.lo;
317 		return;
318 	}
319 	r->hi = t >> b;
320 	r->lo = (t << (32-b)) | (a.lo >> b);
321 }
322 
323 void
324 _lshv(Vlong *r, Vlong a, int b)
325 {
326 	ulong t;
327 
328 	t = a.lo;
329 	if(b >= 32) {
330 		r->lo = 0;
331 		if(b >= 64) {
332 			/* this is illegal re C standard */
333 			r->hi = 0;
334 			return;
335 		}
336 		r->hi = t << (b-32);
337 		return;
338 	}
339 	if(b <= 0) {
340 		r->lo = t;
341 		r->hi = a.hi;
342 		return;
343 	}
344 	r->lo = t << b;
345 	r->hi = (t >> (32-b)) | (a.hi << b);
346 }
347 
348 void
349 _andv(Vlong *r, Vlong a, Vlong b)
350 {
351 	r->hi = a.hi & b.hi;
352 	r->lo = a.lo & b.lo;
353 }
354 
355 void
356 _orv(Vlong *r, Vlong a, Vlong b)
357 {
358 	r->hi = a.hi | b.hi;
359 	r->lo = a.lo | b.lo;
360 }
361 
362 void
363 _xorv(Vlong *r, Vlong a, Vlong b)
364 {
365 	r->hi = a.hi ^ b.hi;
366 	r->lo = a.lo ^ b.lo;
367 }
368 
369 void
370 _vpp(Vlong *l, Vlong *r)
371 {
372 
373 	l->hi = r->hi;
374 	l->lo = r->lo;
375 	r->lo++;
376 	if(r->lo == 0)
377 		r->hi++;
378 }
379 
380 void
381 _vmm(Vlong *l, Vlong *r)
382 {
383 
384 	l->hi = r->hi;
385 	l->lo = r->lo;
386 	if(r->lo == 0)
387 		r->hi--;
388 	r->lo--;
389 }
390 
391 void
392 _ppv(Vlong *l, Vlong *r)
393 {
394 
395 	r->lo++;
396 	if(r->lo == 0)
397 		r->hi++;
398 	l->hi = r->hi;
399 	l->lo = r->lo;
400 }
401 
402 void
403 _mmv(Vlong *l, Vlong *r)
404 {
405 
406 	if(r->lo == 0)
407 		r->hi--;
408 	r->lo--;
409 	l->hi = r->hi;
410 	l->lo = r->lo;
411 }
412 
413 void
414 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
415 {
416 	Vlong t, u;
417 
418 	u = *ret;
419 	switch(type) {
420 	default:
421 		abort();
422 		break;
423 
424 	case 1:	/* schar */
425 		t.lo = *(schar*)lv;
426 		t.hi = t.lo >> 31;
427 		fn(&u, t, rv);
428 		*(schar*)lv = u.lo;
429 		break;
430 
431 	case 2:	/* uchar */
432 		t.lo = *(uchar*)lv;
433 		t.hi = 0;
434 		fn(&u, t, rv);
435 		*(uchar*)lv = u.lo;
436 		break;
437 
438 	case 3:	/* short */
439 		t.lo = *(short*)lv;
440 		t.hi = t.lo >> 31;
441 		fn(&u, t, rv);
442 		*(short*)lv = u.lo;
443 		break;
444 
445 	case 4:	/* ushort */
446 		t.lo = *(ushort*)lv;
447 		t.hi = 0;
448 		fn(&u, t, rv);
449 		*(ushort*)lv = u.lo;
450 		break;
451 
452 	case 9:	/* int */
453 		t.lo = *(int*)lv;
454 		t.hi = t.lo >> 31;
455 		fn(&u, t, rv);
456 		*(int*)lv = u.lo;
457 		break;
458 
459 	case 10:	/* uint */
460 		t.lo = *(uint*)lv;
461 		t.hi = 0;
462 		fn(&u, t, rv);
463 		*(uint*)lv = u.lo;
464 		break;
465 
466 	case 5:	/* long */
467 		t.lo = *(long*)lv;
468 		t.hi = t.lo >> 31;
469 		fn(&u, t, rv);
470 		*(long*)lv = u.lo;
471 		break;
472 
473 	case 6:	/* ulong */
474 		t.lo = *(ulong*)lv;
475 		t.hi = 0;
476 		fn(&u, t, rv);
477 		*(ulong*)lv = u.lo;
478 		break;
479 
480 	case 7:	/* vlong */
481 	case 8:	/* uvlong */
482 		fn(&u, *(Vlong*)lv, rv);
483 		*(Vlong*)lv = u;
484 		break;
485 	}
486 	*ret = u;
487 }
488 
489 void
490 _p2v(Vlong *ret, void *p)
491 {
492 	long t;
493 
494 	t = (ulong)p;
495 	ret->lo = t;
496 	ret->hi = 0;
497 }
498 
499 void
500 _sl2v(Vlong *ret, long sl)
501 {
502 	long t;
503 
504 	t = sl;
505 	ret->lo = t;
506 	ret->hi = t >> 31;
507 }
508 
509 void
510 _ul2v(Vlong *ret, ulong ul)
511 {
512 	long t;
513 
514 	t = ul;
515 	ret->lo = t;
516 	ret->hi = 0;
517 }
518 
519 void
520 _si2v(Vlong *ret, int si)
521 {
522 	long t;
523 
524 	t = si;
525 	ret->lo = t;
526 	ret->hi = t >> 31;
527 }
528 
529 void
530 _ui2v(Vlong *ret, uint ui)
531 {
532 	long t;
533 
534 	t = ui;
535 	ret->lo = t;
536 	ret->hi = 0;
537 }
538 
539 void
540 _sh2v(Vlong *ret, long sh)
541 {
542 	long t;
543 
544 	t = (sh << 16) >> 16;
545 	ret->lo = t;
546 	ret->hi = t >> 31;
547 }
548 
549 void
550 _uh2v(Vlong *ret, ulong ul)
551 {
552 	long t;
553 
554 	t = ul & 0xffff;
555 	ret->lo = t;
556 	ret->hi = 0;
557 }
558 
559 void
560 _sc2v(Vlong *ret, long uc)
561 {
562 	long t;
563 
564 	t = (uc << 24) >> 24;
565 	ret->lo = t;
566 	ret->hi = t >> 31;
567 }
568 
569 void
570 _uc2v(Vlong *ret, ulong ul)
571 {
572 	long t;
573 
574 	t = ul & 0xff;
575 	ret->lo = t;
576 	ret->hi = 0;
577 }
578 
579 long
580 _v2sc(Vlong rv)
581 {
582 	long t;
583 
584 	t = rv.lo & 0xff;
585 	return (t << 24) >> 24;
586 }
587 
588 long
589 _v2uc(Vlong rv)
590 {
591 
592 	return rv.lo & 0xff;
593 }
594 
595 long
596 _v2sh(Vlong rv)
597 {
598 	long t;
599 
600 	t = rv.lo & 0xffff;
601 	return (t << 16) >> 16;
602 }
603 
604 long
605 _v2uh(Vlong rv)
606 {
607 
608 	return rv.lo & 0xffff;
609 }
610 
611 long
612 _v2sl(Vlong rv)
613 {
614 
615 	return rv.lo;
616 }
617 
618 long
619 _v2ul(Vlong rv)
620 {
621 
622 	return rv.lo;
623 }
624 
625 long
626 _v2si(Vlong rv)
627 {
628 
629 	return rv.lo;
630 }
631 
632 long
633 _v2ui(Vlong rv)
634 {
635 
636 	return rv.lo;
637 }
638 
639 int
640 _testv(Vlong rv)
641 {
642 	return rv.lo || rv.hi;
643 }
644 
645 int
646 _eqv(Vlong lv, Vlong rv)
647 {
648 	return lv.lo == rv.lo && lv.hi == rv.hi;
649 }
650 
651 int
652 _nev(Vlong lv, Vlong rv)
653 {
654 	return lv.lo != rv.lo || lv.hi != rv.hi;
655 }
656 
657 int
658 _ltv(Vlong lv, Vlong rv)
659 {
660 	return (long)lv.hi < (long)rv.hi ||
661 		(lv.hi == rv.hi && lv.lo < rv.lo);
662 }
663 
664 int
665 _lev(Vlong lv, Vlong rv)
666 {
667 	return (long)lv.hi < (long)rv.hi ||
668 		(lv.hi == rv.hi && lv.lo <= rv.lo);
669 }
670 
671 int
672 _gtv(Vlong lv, Vlong rv)
673 {
674 	return (long)lv.hi > (long)rv.hi ||
675 		(lv.hi == rv.hi && lv.lo > rv.lo);
676 }
677 
678 int
679 _gev(Vlong lv, Vlong rv)
680 {
681 	return (long)lv.hi > (long)rv.hi ||
682 		(lv.hi == rv.hi && lv.lo >= rv.lo);
683 }
684 
685 int
686 _lov(Vlong lv, Vlong rv)
687 {
688 	return lv.hi < rv.hi ||
689 		(lv.hi == rv.hi && lv.lo < rv.lo);
690 }
691 
692 int
693 _lsv(Vlong lv, Vlong rv)
694 {
695 	return lv.hi < rv.hi ||
696 		(lv.hi == rv.hi && lv.lo <= rv.lo);
697 }
698 
699 int
700 _hiv(Vlong lv, Vlong rv)
701 {
702 	return lv.hi > rv.hi ||
703 		(lv.hi == rv.hi && lv.lo > rv.lo);
704 }
705 
706 int
707 _hsv(Vlong lv, Vlong rv)
708 {
709 	return lv.hi > rv.hi ||
710 		(lv.hi == rv.hi && lv.lo >= rv.lo);
711 }
712