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