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