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