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