xref: /inferno-os/libkern/vlrt-mips.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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 	};
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 void
51 _d2v(Vlong *y, double d)
52 {
53 	union { double d; struct Vlong; } x;
54 	ulong xhi, xlo, ylo, yhi;
55 	int sh;
56 
57 	x.d = d;
58 
59 	xhi = (x.hi & 0xfffff) | 0x100000;
60 	xlo = x.lo;
61 	sh = 1075 - ((x.hi >> 20) & 0x7ff);
62 
63 	ylo = 0;
64 	yhi = 0;
65 	if(sh >= 0) {
66 		/* v = (hi||lo) >> sh */
67 		if(sh < 32) {
68 			if(sh == 0) {
69 				ylo = xlo;
70 				yhi = xhi;
71 			} else {
72 				ylo = (xlo >> sh) | (xhi << (32-sh));
73 				yhi = xhi >> sh;
74 			}
75 		} else {
76 			if(sh == 32) {
77 				ylo = xhi;
78 			} else
79 			if(sh < 64) {
80 				ylo = xhi >> (sh-32);
81 			}
82 		}
83 	} else {
84 		/* v = (hi||lo) << -sh */
85 		sh = -sh;
86 		if(sh <= 10) {
87 			ylo = xlo << sh;
88 			yhi = (xhi << sh) | (xlo >> (32-sh));
89 		} else {
90 			/* overflow */
91 			yhi = d;	/* causes something awful */
92 		}
93 	}
94 	if(x.hi & SIGN(32)) {
95 		if(ylo != 0) {
96 			ylo = -ylo;
97 			yhi = ~yhi;
98 		} else
99 			yhi = -yhi;
100 	}
101 
102 	y->hi = yhi;
103 	y->lo = ylo;
104 }
105 
106 void
107 _f2v(Vlong *y, float f)
108 {
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 *qp, Vlong *rp)
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(qp) {
186 		qp->lo = quolo;
187 		qp->hi = quohi;
188 	}
189 	if(rp) {
190 		rp->lo = numlo;
191 		rp->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.lo = 0;
419 	u.hi = 0;
420 	switch(type) {
421 	default:
422 		abort();
423 		break;
424 
425 	case 1:	/* schar */
426 		t.lo = *(schar*)lv;
427 		t.hi = t.lo >> 31;
428 		fn(&u, t, rv);
429 		*(schar*)lv = u.lo;
430 		break;
431 
432 	case 2:	/* uchar */
433 		t.lo = *(uchar*)lv;
434 		t.hi = 0;
435 		fn(&u, t, rv);
436 		*(uchar*)lv = u.lo;
437 		break;
438 
439 	case 3:	/* short */
440 		t.lo = *(short*)lv;
441 		t.hi = t.lo >> 31;
442 		fn(&u, t, rv);
443 		*(short*)lv = u.lo;
444 		break;
445 
446 	case 4:	/* ushort */
447 		t.lo = *(ushort*)lv;
448 		t.hi = 0;
449 		fn(&u, t, rv);
450 		*(ushort*)lv = u.lo;
451 		break;
452 
453 	case 9:	/* int */
454 		t.lo = *(int*)lv;
455 		t.hi = t.lo >> 31;
456 		fn(&u, t, rv);
457 		*(int*)lv = u.lo;
458 		break;
459 
460 	case 10:	/* uint */
461 		t.lo = *(uint*)lv;
462 		t.hi = 0;
463 		fn(&u, t, rv);
464 		*(uint*)lv = u.lo;
465 		break;
466 
467 	case 5:	/* long */
468 		t.lo = *(long*)lv;
469 		t.hi = t.lo >> 31;
470 		fn(&u, t, rv);
471 		*(long*)lv = u.lo;
472 		break;
473 
474 	case 6:	/* ulong */
475 		t.lo = *(ulong*)lv;
476 		t.hi = 0;
477 		fn(&u, t, rv);
478 		*(ulong*)lv = u.lo;
479 		break;
480 
481 	case 7:	/* vlong */
482 	case 8:	/* uvlong */
483 		fn(&u, *(Vlong*)lv, rv);
484 		*(Vlong*)lv = u;
485 		break;
486 	}
487 	*ret = u;
488 }
489 
490 void
491 _p2v(Vlong *ret, void *p)
492 {
493 	long t;
494 
495 	t = (ulong)p;
496 	ret->lo = t;
497 	ret->hi = 0;
498 }
499 
500 void
501 _sl2v(Vlong *ret, long sl)
502 {
503 	long t;
504 
505 	t = sl;
506 	ret->lo = t;
507 	ret->hi = t >> 31;
508 }
509 
510 void
511 _ul2v(Vlong *ret, ulong ul)
512 {
513 	long t;
514 
515 	t = ul;
516 	ret->lo = t;
517 	ret->hi = 0;
518 }
519 
520 void
521 _si2v(Vlong *ret, int si)
522 {
523 	long t;
524 
525 	t = si;
526 	ret->lo = t;
527 	ret->hi = t >> 31;
528 }
529 
530 void
531 _ui2v(Vlong *ret, uint ui)
532 {
533 	long t;
534 
535 	t = ui;
536 	ret->lo = t;
537 	ret->hi = 0;
538 }
539 
540 void
541 _sh2v(Vlong *ret, long sh)
542 {
543 	long t;
544 
545 	t = (sh << 16) >> 16;
546 	ret->lo = t;
547 	ret->hi = t >> 31;
548 }
549 
550 void
551 _uh2v(Vlong *ret, ulong ul)
552 {
553 	long t;
554 
555 	t = ul & 0xffff;
556 	ret->lo = t;
557 	ret->hi = 0;
558 }
559 
560 void
561 _sc2v(Vlong *ret, long uc)
562 {
563 	long t;
564 
565 	t = (uc << 24) >> 24;
566 	ret->lo = t;
567 	ret->hi = t >> 31;
568 }
569 
570 void
571 _uc2v(Vlong *ret, ulong ul)
572 {
573 	long t;
574 
575 	t = ul & 0xff;
576 	ret->lo = t;
577 	ret->hi = 0;
578 }
579 
580 long
581 _v2sc(Vlong rv)
582 {
583 	long t;
584 
585 	t = rv.lo & 0xff;
586 	return (t << 24) >> 24;
587 }
588 
589 long
590 _v2uc(Vlong rv)
591 {
592 
593 	return rv.lo & 0xff;
594 }
595 
596 long
597 _v2sh(Vlong rv)
598 {
599 	long t;
600 
601 	t = rv.lo & 0xffff;
602 	return (t << 16) >> 16;
603 }
604 
605 long
606 _v2uh(Vlong rv)
607 {
608 
609 	return rv.lo & 0xffff;
610 }
611 
612 long
613 _v2sl(Vlong rv)
614 {
615 
616 	return rv.lo;
617 }
618 
619 long
620 _v2ul(Vlong rv)
621 {
622 
623 	return rv.lo;
624 }
625 
626 long
627 _v2si(Vlong rv)
628 {
629 
630 	return rv.lo;
631 }
632 
633 long
634 _v2ui(Vlong rv)
635 {
636 
637 	return rv.lo;
638 }
639 
640 int
641 _testv(Vlong rv)
642 {
643 	return rv.lo || rv.hi;
644 }
645 
646 int
647 _eqv(Vlong lv, Vlong rv)
648 {
649 	return lv.lo == rv.lo && lv.hi == rv.hi;
650 }
651 
652 int
653 _nev(Vlong lv, Vlong rv)
654 {
655 	return lv.lo != rv.lo || lv.hi != rv.hi;
656 }
657 
658 int
659 _ltv(Vlong lv, Vlong rv)
660 {
661 	return (long)lv.hi < (long)rv.hi ||
662 		(lv.hi == rv.hi && lv.lo < rv.lo);
663 }
664 
665 int
666 _lev(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 _gtv(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 _gev(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 _lov(Vlong lv, Vlong rv)
688 {
689 	return lv.hi < rv.hi ||
690 		(lv.hi == rv.hi && lv.lo < rv.lo);
691 }
692 
693 int
694 _lsv(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 _hiv(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 _hsv(Vlong lv, Vlong rv)
709 {
710 	return lv.hi > rv.hi ||
711 		(lv.hi == rv.hi && lv.lo >= rv.lo);
712 }
713