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