shithub: riscv

Download patch

ref: d2af6b40af268fafdbd04c0222e785167b9ae021
parent: 9124e491e5d172feec53dd662c2fe6d999cb2d3f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 4 15:49:02 EDT 2015

libc: add _uv2d()/uv2f() and _vas*d() functions to vlrt.c

on 32 bit archs, implement 64 bit vasop with floatingpoint right hand side.
also added is uvlong->double conversion function.

--- a/sys/src/ape/lib/ap/386/vlrt.c
+++ b/sys/src/ape/lib/ap/386/vlrt.c
@@ -28,19 +28,8 @@
 
 void	abort(void);
 
-void
-_subv(Vlong *r, Vlong a, Vlong b)
-{
-	ulong lo, hi;
+void _subv(Vlong*, Vlong, Vlong);
 
-	lo = a.lo - b.lo;
-	hi = a.hi - b.hi;
-	if(lo > a.lo)
-		hi--;
-	r->lo = lo;
-	r->hi = hi;
-}
-
 void
 _d2v(Vlong *y, double d)
 {
@@ -100,7 +89,6 @@
 void
 _f2v(Vlong *y, float f)
 {
-
 	_d2v(y, f);
 }
 
@@ -124,10 +112,109 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
 ulong	_div64by32(Vlong, ulong, ulong*);
 void	_mul64by32(Vlong*, Vlong, ulong);
 
 static void
+slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
+{
+	ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
+	int i;
+
+	numhi = num.hi;
+	numlo = num.lo;
+	denhi = den.hi;
+	denlo = den.lo;
+
+	/*
+	 * get a divide by zero
+	 */
+	if(denlo==0 && denhi==0) {
+		numlo = numlo / denlo;
+	}
+
+	/*
+	 * set up the divisor and find the number of iterations needed
+	 */
+	if(numhi >= SIGN(32)) {
+		quohi = SIGN(32);
+		quolo = 0;
+	} else {
+		quohi = numhi;
+		quolo = numlo;
+	}
+	i = 0;
+	while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
+		denhi = (denhi<<1) | (denlo>>31);
+		denlo <<= 1;
+		i++;
+	}
+
+	quohi = 0;
+	quolo = 0;
+	for(; i >= 0; i--) {
+		quohi = (quohi<<1) | (quolo>>31);
+		quolo <<= 1;
+		if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
+			t = numlo;
+			numlo -= denlo;
+			if(numlo > t)
+				numhi--;
+			numhi -= denhi;
+			quolo |= 1;
+		}
+		denlo = (denlo>>1) | (denhi<<31);
+		denhi >>= 1;
+	}
+
+	if(q) {
+		q->lo = quolo;
+		q->hi = quohi;
+	}
+	if(r) {
+		r->lo = numlo;
+		r->hi = numhi;
+	}
+}
+
+static void
 dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
 {
 	ulong n;
@@ -149,12 +236,12 @@
 		q.hi = 0;
 		n = num.hi/den.hi;
 		_mul64by32(&x, den, n);
-		if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)){
-			n--;
-			_mul64by32(&x, den, n);
+		if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
+			slowdodiv(num, den, &q, &r);
+		else {
+			q.lo = n;
+			_subv(&r, num, x);
 		}
-		q.lo = n;
-		_subv(&r, num, x);
 	} else {
 		if(num.hi >= den.lo){
 			q.hi = n = num.hi/den.lo;
--- a/sys/src/ape/lib/ap/arm/vlrt.c
+++ b/sys/src/ape/lib/ap/arm/vlrt.c
@@ -128,7 +128,46 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
 
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
+/* too many of these are also needed by profiler; leave them out */
+#pragma profile off
+
 static void
 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
 {
@@ -502,6 +541,7 @@
 	ret->lo = t;
 	ret->hi = t >> 31;
 }
+
 
 void
 _ul2v(Vlong *ret, ulong ul)
--- a/sys/src/ape/lib/ap/mips/vlrt.c
+++ b/sys/src/ape/lib/ap/mips/vlrt.c
@@ -28,6 +28,8 @@
 
 void	abort(void);
 
+/* needed by profiler; can't be profiled. */
+#pragma profile off
 void
 _addv(Vlong *r, Vlong a, Vlong b)
 {
@@ -54,6 +56,8 @@
 	r->hi = hi;
 }
 
+#pragma profile on
+
 void
 _d2v(Vlong *y, double d)
 {
@@ -113,7 +117,6 @@
 void
 _f2v(Vlong *y, float f)
 {
-
 	_d2v(y, f);
 }
 
@@ -135,6 +138,43 @@
 _v2f(Vlong x)
 {
 	return _v2d(x);
+}
+
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
 }
 
 static void
--- a/sys/src/ape/lib/ap/power/vlrt.c
+++ b/sys/src/ape/lib/ap/power/vlrt.c
@@ -99,6 +99,43 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
 void
 _divvu(Vlong *q, Vlong n, Vlong d)
 {
--- a/sys/src/ape/lib/ap/sparc/vlrt.c
+++ b/sys/src/ape/lib/ap/sparc/vlrt.c
@@ -28,6 +28,8 @@
 
 void	abort(void);
 
+/* needed by profiler; can't be profiled */
+#pragma profile off
 void
 _addv(Vlong *r, Vlong a, Vlong b)
 {
@@ -54,6 +56,8 @@
 	r->hi = hi;
 }
 
+#pragma profile on
+
 void
 _d2v(Vlong *y, double d)
 {
@@ -135,6 +139,43 @@
 _v2f(Vlong x)
 {
 	return _v2d(x);
+}
+
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
 }
 
 static void
--- a/sys/src/libc/386/vlrt.c
+++ b/sys/src/libc/386/vlrt.c
@@ -89,7 +89,6 @@
 void
 _f2v(Vlong *y, float f)
 {
-
 	_d2v(y, f);
 }
 
@@ -111,6 +110,43 @@
 _v2f(Vlong x)
 {
 	return _v2d(x);
+}
+
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
 }
 
 ulong	_div64by32(Vlong, ulong, ulong*);
--- a/sys/src/libc/arm/vlrt.c
+++ b/sys/src/libc/arm/vlrt.c
@@ -128,6 +128,43 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
 /* too many of these are also needed by profiler; leave them out */
 #pragma profile off
 
--- a/sys/src/libc/mips/vlrt.c
+++ b/sys/src/libc/mips/vlrt.c
@@ -117,7 +117,6 @@
 void
 _f2v(Vlong *y, float f)
 {
-
 	_d2v(y, f);
 }
 
@@ -139,6 +138,43 @@
 _v2f(Vlong x)
 {
 	return _v2d(x);
+}
+
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
 }
 
 static void
--- a/sys/src/libc/power/vlrt.c
+++ b/sys/src/libc/power/vlrt.c
@@ -99,6 +99,43 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
 void
 _divvu(Vlong *q, Vlong n, Vlong d)
 {
--- a/sys/src/libc/sparc/vlrt.c
+++ b/sys/src/libc/sparc/vlrt.c
@@ -141,6 +141,43 @@
 	return _v2d(x);
 }
 
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
+}
+
 static void
 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
 {
--- a/sys/src/libc/spim/vlrt.c
+++ b/sys/src/libc/spim/vlrt.c
@@ -117,7 +117,6 @@
 void
 _f2v(Vlong *y, float f)
 {
-
 	_d2v(y, f);
 }
 
@@ -139,6 +138,43 @@
 _v2f(Vlong x)
 {
 	return _v2d(x);
+}
+
+double
+_uv2d(Vlong x)
+{
+	return x.hi*4294967296. + x.lo;
+}
+
+float
+_uv2f(Vlong x)
+{
+	return _uv2d(x);
+}
+
+void
+_vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)+rv);
+	*ret = *lv;
+}
+void
+_vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)-rv);
+	*ret = *lv;
+}
+void
+_vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)*rv);
+	*ret = *lv;
+}
+void
+_vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
+{
+	_d2v(lv, v2d(*lv)/rv);
+	*ret = *lv;
 }
 
 static void