17dd7cddfSDavid du Colombier typedef unsigned long ulong;
27dd7cddfSDavid du Colombier typedef unsigned int uint;
37dd7cddfSDavid du Colombier typedef unsigned short ushort;
47dd7cddfSDavid du Colombier typedef unsigned char uchar;
57dd7cddfSDavid du Colombier typedef signed char schar;
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier #define SIGN(n) (1UL<<(n-1))
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier typedef struct Vlong Vlong;
107dd7cddfSDavid du Colombier struct Vlong
117dd7cddfSDavid du Colombier {
127dd7cddfSDavid du Colombier ulong hi;
137dd7cddfSDavid du Colombier ulong lo;
147dd7cddfSDavid du Colombier };
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier void abort(void);
17*6891d857SDavid du Colombier void _divu64(Vlong, Vlong, Vlong*, Vlong*);
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier void
_d2v(Vlong * y,double d)207dd7cddfSDavid du Colombier _d2v(Vlong *y, double d)
217dd7cddfSDavid du Colombier {
22*6891d857SDavid du Colombier union { double d; Vlong; } x;
237dd7cddfSDavid du Colombier ulong xhi, xlo, ylo, yhi;
247dd7cddfSDavid du Colombier int sh;
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier x.d = d;
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier xhi = (x.hi & 0xfffff) | 0x100000;
297dd7cddfSDavid du Colombier xlo = x.lo;
307dd7cddfSDavid du Colombier sh = 1075 - ((x.hi >> 20) & 0x7ff);
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier ylo = 0;
337dd7cddfSDavid du Colombier yhi = 0;
347dd7cddfSDavid du Colombier if(sh >= 0) {
357dd7cddfSDavid du Colombier /* v = (hi||lo) >> sh */
367dd7cddfSDavid du Colombier if(sh < 32) {
377dd7cddfSDavid du Colombier if(sh == 0) {
387dd7cddfSDavid du Colombier ylo = xlo;
397dd7cddfSDavid du Colombier yhi = xhi;
407dd7cddfSDavid du Colombier } else {
417dd7cddfSDavid du Colombier ylo = (xlo >> sh) | (xhi << (32-sh));
427dd7cddfSDavid du Colombier yhi = xhi >> sh;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier } else {
457dd7cddfSDavid du Colombier if(sh == 32) {
467dd7cddfSDavid du Colombier ylo = xhi;
477dd7cddfSDavid du Colombier } else
487dd7cddfSDavid du Colombier if(sh < 64) {
497dd7cddfSDavid du Colombier ylo = xhi >> (sh-32);
507dd7cddfSDavid du Colombier }
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier } else {
537dd7cddfSDavid du Colombier /* v = (hi||lo) << -sh */
547dd7cddfSDavid du Colombier sh = -sh;
557dd7cddfSDavid du Colombier if(sh <= 10) {
567dd7cddfSDavid du Colombier ylo = xlo << sh;
577dd7cddfSDavid du Colombier yhi = (xhi << sh) | (xlo >> (32-sh));
587dd7cddfSDavid du Colombier } else {
597dd7cddfSDavid du Colombier /* overflow */
607dd7cddfSDavid du Colombier yhi = d; /* causes something awful */
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier if(x.hi & SIGN(32)) {
647dd7cddfSDavid du Colombier if(ylo != 0) {
657dd7cddfSDavid du Colombier ylo = -ylo;
667dd7cddfSDavid du Colombier yhi = ~yhi;
677dd7cddfSDavid du Colombier } else
687dd7cddfSDavid du Colombier yhi = -yhi;
697dd7cddfSDavid du Colombier }
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier y->hi = yhi;
727dd7cddfSDavid du Colombier y->lo = ylo;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier void
_f2v(Vlong * y,float f)767dd7cddfSDavid du Colombier _f2v(Vlong *y, float f)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier _d2v(y, f);
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier
827dd7cddfSDavid du Colombier double
_v2d(Vlong x)837dd7cddfSDavid du Colombier _v2d(Vlong x)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier if(x.hi & SIGN(32)) {
867dd7cddfSDavid du Colombier if(x.lo) {
877dd7cddfSDavid du Colombier x.lo = -x.lo;
887dd7cddfSDavid du Colombier x.hi = ~x.hi;
897dd7cddfSDavid du Colombier } else
907dd7cddfSDavid du Colombier x.hi = -x.hi;
917dd7cddfSDavid du Colombier return -((long)x.hi*4294967296. + x.lo);
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier return (long)x.hi*4294967296. + x.lo;
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier float
_v2f(Vlong x)977dd7cddfSDavid du Colombier _v2f(Vlong x)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier return _v2d(x);
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier void
_divvu(Vlong * q,Vlong n,Vlong d)1037dd7cddfSDavid du Colombier _divvu(Vlong *q, Vlong n, Vlong d)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier if(n.hi == 0 && d.hi == 0) {
1077dd7cddfSDavid du Colombier q->hi = 0;
1087dd7cddfSDavid du Colombier q->lo = n.lo / d.lo;
1097dd7cddfSDavid du Colombier return;
1107dd7cddfSDavid du Colombier }
111*6891d857SDavid du Colombier _divu64(n, d, q, 0);
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier void
_modvu(Vlong * r,Vlong n,Vlong d)1157dd7cddfSDavid du Colombier _modvu(Vlong *r, Vlong n, Vlong d)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier
1187dd7cddfSDavid du Colombier if(n.hi == 0 && d.hi == 0) {
1197dd7cddfSDavid du Colombier r->hi = 0;
1207dd7cddfSDavid du Colombier r->lo = n.lo % d.lo;
1217dd7cddfSDavid du Colombier return;
1227dd7cddfSDavid du Colombier }
123*6891d857SDavid du Colombier _divu64(n, d, 0, r);
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier static void
vneg(Vlong * v)1277dd7cddfSDavid du Colombier vneg(Vlong *v)
1287dd7cddfSDavid du Colombier {
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier if(v->lo == 0) {
1317dd7cddfSDavid du Colombier v->hi = -v->hi;
1327dd7cddfSDavid du Colombier return;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier v->lo = -v->lo;
1357dd7cddfSDavid du Colombier v->hi = ~v->hi;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier void
_divv(Vlong * q,Vlong n,Vlong d)1397dd7cddfSDavid du Colombier _divv(Vlong *q, Vlong n, Vlong d)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier long nneg, dneg;
1427dd7cddfSDavid du Colombier
1437dd7cddfSDavid du Colombier if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
1447dd7cddfSDavid du Colombier q->lo = (long)n.lo / (long)d.lo;
1457dd7cddfSDavid du Colombier q->hi = ((long)q->lo) >> 31;
1467dd7cddfSDavid du Colombier return;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier nneg = n.hi >> 31;
1497dd7cddfSDavid du Colombier if(nneg)
1507dd7cddfSDavid du Colombier vneg(&n);
1517dd7cddfSDavid du Colombier dneg = d.hi >> 31;
1527dd7cddfSDavid du Colombier if(dneg)
1537dd7cddfSDavid du Colombier vneg(&d);
154*6891d857SDavid du Colombier _divu64(n, d, q, 0);
1557dd7cddfSDavid du Colombier if(nneg != dneg)
1567dd7cddfSDavid du Colombier vneg(q);
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier void
_modv(Vlong * r,Vlong n,Vlong d)1607dd7cddfSDavid du Colombier _modv(Vlong *r, Vlong n, Vlong d)
1617dd7cddfSDavid du Colombier {
1627dd7cddfSDavid du Colombier long nneg, dneg;
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
1657dd7cddfSDavid du Colombier r->lo = (long)n.lo % (long)d.lo;
1667dd7cddfSDavid du Colombier r->hi = ((long)r->lo) >> 31;
1677dd7cddfSDavid du Colombier return;
1687dd7cddfSDavid du Colombier }
1697dd7cddfSDavid du Colombier nneg = n.hi >> 31;
1707dd7cddfSDavid du Colombier if(nneg)
1717dd7cddfSDavid du Colombier vneg(&n);
1727dd7cddfSDavid du Colombier dneg = d.hi >> 31;
1737dd7cddfSDavid du Colombier if(dneg)
1747dd7cddfSDavid du Colombier vneg(&d);
175*6891d857SDavid du Colombier _divu64(n, d, 0, r);
1767dd7cddfSDavid du Colombier if(nneg)
1777dd7cddfSDavid du Colombier vneg(r);
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier
1807dd7cddfSDavid du Colombier void
_vasop(Vlong * ret,void * lv,void fn (Vlong *,Vlong,Vlong),int type,Vlong rv)1817dd7cddfSDavid du Colombier _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
1827dd7cddfSDavid du Colombier {
1837dd7cddfSDavid du Colombier Vlong t, u;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier u = *ret;
1867dd7cddfSDavid du Colombier switch(type) {
1877dd7cddfSDavid du Colombier default:
1887dd7cddfSDavid du Colombier abort();
1897dd7cddfSDavid du Colombier break;
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier case 1: /* schar */
1927dd7cddfSDavid du Colombier t.lo = *(schar*)lv;
1937dd7cddfSDavid du Colombier t.hi = t.lo >> 31;
1947dd7cddfSDavid du Colombier fn(&u, t, rv);
1957dd7cddfSDavid du Colombier *(schar*)lv = u.lo;
1967dd7cddfSDavid du Colombier break;
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier case 2: /* uchar */
1997dd7cddfSDavid du Colombier t.lo = *(uchar*)lv;
2007dd7cddfSDavid du Colombier t.hi = 0;
2017dd7cddfSDavid du Colombier fn(&u, t, rv);
2027dd7cddfSDavid du Colombier *(uchar*)lv = u.lo;
2037dd7cddfSDavid du Colombier break;
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier case 3: /* short */
2067dd7cddfSDavid du Colombier t.lo = *(short*)lv;
2077dd7cddfSDavid du Colombier t.hi = t.lo >> 31;
2087dd7cddfSDavid du Colombier fn(&u, t, rv);
2097dd7cddfSDavid du Colombier *(short*)lv = u.lo;
2107dd7cddfSDavid du Colombier break;
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier case 4: /* ushort */
2137dd7cddfSDavid du Colombier t.lo = *(ushort*)lv;
2147dd7cddfSDavid du Colombier t.hi = 0;
2157dd7cddfSDavid du Colombier fn(&u, t, rv);
2167dd7cddfSDavid du Colombier *(ushort*)lv = u.lo;
2177dd7cddfSDavid du Colombier break;
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier case 9: /* int */
2207dd7cddfSDavid du Colombier t.lo = *(int*)lv;
2217dd7cddfSDavid du Colombier t.hi = t.lo >> 31;
2227dd7cddfSDavid du Colombier fn(&u, t, rv);
2237dd7cddfSDavid du Colombier *(int*)lv = u.lo;
2247dd7cddfSDavid du Colombier break;
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier case 10: /* uint */
2277dd7cddfSDavid du Colombier t.lo = *(uint*)lv;
2287dd7cddfSDavid du Colombier t.hi = 0;
2297dd7cddfSDavid du Colombier fn(&u, t, rv);
2307dd7cddfSDavid du Colombier *(uint*)lv = u.lo;
2317dd7cddfSDavid du Colombier break;
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier case 5: /* long */
2347dd7cddfSDavid du Colombier t.lo = *(long*)lv;
2357dd7cddfSDavid du Colombier t.hi = t.lo >> 31;
2367dd7cddfSDavid du Colombier fn(&u, t, rv);
2377dd7cddfSDavid du Colombier *(long*)lv = u.lo;
2387dd7cddfSDavid du Colombier break;
2397dd7cddfSDavid du Colombier
2407dd7cddfSDavid du Colombier case 6: /* ulong */
2417dd7cddfSDavid du Colombier t.lo = *(ulong*)lv;
2427dd7cddfSDavid du Colombier t.hi = 0;
2437dd7cddfSDavid du Colombier fn(&u, t, rv);
2447dd7cddfSDavid du Colombier *(ulong*)lv = u.lo;
2457dd7cddfSDavid du Colombier break;
2467dd7cddfSDavid du Colombier
2477dd7cddfSDavid du Colombier case 7: /* vlong */
2487dd7cddfSDavid du Colombier case 8: /* uvlong */
2497dd7cddfSDavid du Colombier fn(&u, *(Vlong*)lv, rv);
2507dd7cddfSDavid du Colombier *(Vlong*)lv = u;
2517dd7cddfSDavid du Colombier break;
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier *ret = u;
2547dd7cddfSDavid du Colombier }
255