From d2af6b40af268fafdbd04c0222e785167b9ae021 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 4 Oct 2015 19:49:02 +0200 Subject: 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. --- sys/src/ape/lib/ap/386/vlrt.c | 123 ++++++++++++++++++++++++++++++++++------ sys/src/ape/lib/ap/arm/vlrt.c | 40 +++++++++++++ sys/src/ape/lib/ap/mips/vlrt.c | 42 +++++++++++++- sys/src/ape/lib/ap/power/vlrt.c | 37 ++++++++++++ sys/src/ape/lib/ap/sparc/vlrt.c | 41 ++++++++++++++ sys/src/libc/386/vlrt.c | 38 ++++++++++++- sys/src/libc/arm/vlrt.c | 37 ++++++++++++ sys/src/libc/mips/vlrt.c | 38 ++++++++++++- sys/src/libc/power/vlrt.c | 37 ++++++++++++ sys/src/libc/sparc/vlrt.c | 37 ++++++++++++ sys/src/libc/spim/vlrt.c | 38 ++++++++++++- 11 files changed, 486 insertions(+), 22 deletions(-) diff --git a/sys/src/ape/lib/ap/386/vlrt.c b/sys/src/ape/lib/ap/386/vlrt.c index f0b100ef5..8e5633b05 100644 --- a/sys/src/ape/lib/ap/386/vlrt.c +++ b/sys/src/ape/lib/ap/386/vlrt.c @@ -28,18 +28,7 @@ struct Vlong void abort(void); -void -_subv(Vlong *r, Vlong a, Vlong b) -{ - ulong lo, hi; - - lo = a.lo - b.lo; - hi = a.hi - b.hi; - if(lo > a.lo) - hi--; - r->lo = lo; - r->hi = hi; -} +void _subv(Vlong*, Vlong, Vlong); void _d2v(Vlong *y, double d) @@ -100,7 +89,6 @@ _d2v(Vlong *y, double d) void _f2v(Vlong *y, float f) { - _d2v(y, f); } @@ -124,9 +112,108 @@ _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*); 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) { @@ -149,12 +236,12 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) 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; diff --git a/sys/src/ape/lib/ap/arm/vlrt.c b/sys/src/ape/lib/ap/arm/vlrt.c index 5e9524d34..cba8b27f1 100644 --- a/sys/src/ape/lib/ap/arm/vlrt.c +++ b/sys/src/ape/lib/ap/arm/vlrt.c @@ -128,6 +128,45 @@ _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; +} + +/* 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) @@ -503,6 +542,7 @@ _sl2v(Vlong *ret, long sl) ret->hi = t >> 31; } + void _ul2v(Vlong *ret, ulong ul) { diff --git a/sys/src/ape/lib/ap/mips/vlrt.c b/sys/src/ape/lib/ap/mips/vlrt.c index 964562775..2ca7288be 100644 --- a/sys/src/ape/lib/ap/mips/vlrt.c +++ b/sys/src/ape/lib/ap/mips/vlrt.c @@ -28,6 +28,8 @@ struct Vlong 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 @@ _subv(Vlong *r, Vlong a, Vlong b) r->hi = hi; } +#pragma profile on + void _d2v(Vlong *y, double d) { @@ -113,7 +117,6 @@ _d2v(Vlong *y, double d) void _f2v(Vlong *y, float f) { - _d2v(y, f); } @@ -137,6 +140,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 dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) { diff --git a/sys/src/ape/lib/ap/power/vlrt.c b/sys/src/ape/lib/ap/power/vlrt.c index 681a3b49b..e9fd3e8bf 100644 --- a/sys/src/ape/lib/ap/power/vlrt.c +++ b/sys/src/ape/lib/ap/power/vlrt.c @@ -99,6 +99,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; +} + void _divvu(Vlong *q, Vlong n, Vlong d) { diff --git a/sys/src/ape/lib/ap/sparc/vlrt.c b/sys/src/ape/lib/ap/sparc/vlrt.c index 6fbd83ca8..92c9b73c6 100644 --- a/sys/src/ape/lib/ap/sparc/vlrt.c +++ b/sys/src/ape/lib/ap/sparc/vlrt.c @@ -28,6 +28,8 @@ struct Vlong 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 @@ _subv(Vlong *r, Vlong a, Vlong b) r->hi = hi; } +#pragma profile on + void _d2v(Vlong *y, double d) { @@ -137,6 +141,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 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) { diff --git a/sys/src/libc/386/vlrt.c b/sys/src/libc/386/vlrt.c index 83fd09683..8e5633b05 100644 --- a/sys/src/libc/386/vlrt.c +++ b/sys/src/libc/386/vlrt.c @@ -89,7 +89,6 @@ _d2v(Vlong *y, double d) void _f2v(Vlong *y, float f) { - _d2v(y, f); } @@ -113,6 +112,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*); void _mul64by32(Vlong*, Vlong, ulong); diff --git a/sys/src/libc/arm/vlrt.c b/sys/src/libc/arm/vlrt.c index 6a0c5df6a..cba8b27f1 100644 --- a/sys/src/libc/arm/vlrt.c +++ b/sys/src/libc/arm/vlrt.c @@ -128,6 +128,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; +} + /* too many of these are also needed by profiler; leave them out */ #pragma profile off diff --git a/sys/src/libc/mips/vlrt.c b/sys/src/libc/mips/vlrt.c index 099c2c55d..2ca7288be 100644 --- a/sys/src/libc/mips/vlrt.c +++ b/sys/src/libc/mips/vlrt.c @@ -117,7 +117,6 @@ _d2v(Vlong *y, double d) void _f2v(Vlong *y, float f) { - _d2v(y, f); } @@ -141,6 +140,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 dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) { diff --git a/sys/src/libc/power/vlrt.c b/sys/src/libc/power/vlrt.c index 681a3b49b..e9fd3e8bf 100644 --- a/sys/src/libc/power/vlrt.c +++ b/sys/src/libc/power/vlrt.c @@ -99,6 +99,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; +} + void _divvu(Vlong *q, Vlong n, Vlong d) { diff --git a/sys/src/libc/sparc/vlrt.c b/sys/src/libc/sparc/vlrt.c index b71c92f73..92c9b73c6 100644 --- a/sys/src/libc/sparc/vlrt.c +++ b/sys/src/libc/sparc/vlrt.c @@ -141,6 +141,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 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) { diff --git a/sys/src/libc/spim/vlrt.c b/sys/src/libc/spim/vlrt.c index ef7902a28..f17cda42d 100644 --- a/sys/src/libc/spim/vlrt.c +++ b/sys/src/libc/spim/vlrt.c @@ -117,7 +117,6 @@ _d2v(Vlong *y, double d) void _f2v(Vlong *y, float f) { - _d2v(y, f); } @@ -141,6 +140,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 dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) { -- cgit v1.2.3