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