731 lines · 9.3 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ typedef	unsigned long	ulong;typedef	unsigned int	uint;typedef	unsigned short	ushort;typedef	unsigned char	uchar;typedef	signed char	schar; #define	SIGN(n)	(1UL<<(n-1)) typedef	struct	Vlong	Vlong;struct	Vlong{	union	{		struct		{			ulong	hi;			ulong	lo;		};		struct		{			ushort	hims;			ushort	hils;			ushort	loms;			ushort	lols;		};	};}; void	abort(void); /* needed by profiler; can't be profiled. */#pragma profile off void_addv(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 *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_d2v(Vlong *y, double d){	union { double d; struct Vlong; } x;	ulong xhi, xlo, ylo, yhi;	int sh; 	x.d = d; 	xhi = (x.hi & 0xfffff) | 0x100000;	xlo = x.lo;	sh = 1075 - ((x.hi >> 20) & 0x7ff); 	ylo = 0;	yhi = 0;	if(sh >= 0) {		/* v = (hi||lo) >> sh */		if(sh < 32) {			if(sh == 0) {				ylo = xlo;				yhi = xhi;			} else {				ylo = (xlo >> sh) | (xhi << (32-sh));				yhi = xhi >> sh;			}		} else {			if(sh == 32) {				ylo = xhi;			} else			if(sh < 64) {				ylo = xhi >> (sh-32);			}		}	} else {		/* v = (hi||lo) << -sh */		sh = -sh;		if(sh <= 10) {			ylo = xlo << sh;			yhi = (xhi << sh) | (xlo >> (32-sh));		} else {			/* overflow */			yhi = d;	/* causes something awful */		}	}	if(x.hi & SIGN(32)) {		if(ylo != 0) {			ylo = -ylo;			yhi = ~yhi;		} else			yhi = -yhi;	} 	y->hi = yhi;	y->lo = ylo;} void_f2v(Vlong *y, float f){ 	_d2v(y, f);} double_v2d(Vlong x){	if(x.hi & SIGN(32)) {		if(x.lo) {			x.lo = -x.lo;			x.hi = ~x.hi;		} else			x.hi = -x.hi;		return -((long)x.hi*4294967296. + x.lo);	}	return (long)x.hi*4294967296. + x.lo;} float_v2f(Vlong x){	return _v2d(x);} static voiddodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp){	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(qp) {		qp->lo = quolo;		qp->hi = quohi;	}	if(rp) {		rp->lo = numlo;		rp->hi = numhi;	}} void_divvu(Vlong *q, Vlong n, Vlong d){ 	if(n.hi == 0 && d.hi == 0) {		q->hi = 0;		q->lo = n.lo / d.lo;		return;	}	dodiv(n, d, q, 0);} void_modvu(Vlong *r, Vlong n, Vlong d){ 	if(n.hi == 0 && d.hi == 0) {		r->hi = 0;		r->lo = n.lo % d.lo;		return;	}	dodiv(n, d, 0, r);} static voidvneg(Vlong *v){ 	if(v->lo == 0) {		v->hi = -v->hi;		return;	}	v->lo = -v->lo;	v->hi = ~v->hi;} void_divv(Vlong *q, Vlong n, Vlong d){	long nneg, dneg; 	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {		q->lo = (long)n.lo / (long)d.lo;		q->hi = ((long)q->lo) >> 31;		return;	}	nneg = n.hi >> 31;	if(nneg)		vneg(&n);	dneg = d.hi >> 31;	if(dneg)		vneg(&d);	dodiv(n, d, q, 0);	if(nneg != dneg)		vneg(q);} void_modv(Vlong *r, Vlong n, Vlong d){	long nneg, dneg; 	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {		r->lo = (long)n.lo % (long)d.lo;		r->hi = ((long)r->lo) >> 31;		return;	}	nneg = n.hi >> 31;	if(nneg)		vneg(&n);	dneg = d.hi >> 31;	if(dneg)		vneg(&d);	dodiv(n, d, 0, r);	if(nneg)		vneg(r);} void_rshav(Vlong *r, Vlong a, int b){	long t; 	t = a.hi;	if(b >= 32) {		r->hi = t>>31;		if(b >= 64) {			/* this is illegal re C standard */			r->lo = t>>31;			return;		}		r->lo = t >> (b-32);		return;	}	if(b <= 0) {		r->hi = t;		r->lo = a.lo;		return;	}	r->hi = t >> b;	r->lo = (t << (32-b)) | (a.lo >> b);} void_rshlv(Vlong *r, Vlong a, int b){	ulong t; 	t = a.hi;	if(b >= 32) {		r->hi = 0;		if(b >= 64) {			/* this is illegal re C standard */			r->lo = 0;			return;		}		r->lo = t >> (b-32);		return;	}	if(b <= 0) {		r->hi = t;		r->lo = a.lo;		return;	}	r->hi = t >> b;	r->lo = (t << (32-b)) | (a.lo >> b);} void_lshv(Vlong *r, Vlong a, int b){	ulong t; 	t = a.lo;	if(b >= 32) {		r->lo = 0;		if(b >= 64) {			/* this is illegal re C standard */			r->hi = 0;			return;		}		r->hi = t << (b-32);		return;	}	if(b <= 0) {		r->lo = t;		r->hi = a.hi;		return;	}	r->lo = t << b;	r->hi = (t >> (32-b)) | (a.hi << b);} void_andv(Vlong *r, Vlong a, Vlong b){	r->hi = a.hi & b.hi;	r->lo = a.lo & b.lo;} void_orv(Vlong *r, Vlong a, Vlong b){	r->hi = a.hi | b.hi;	r->lo = a.lo | b.lo;} void_xorv(Vlong *r, Vlong a, Vlong b){	r->hi = a.hi ^ b.hi;	r->lo = a.lo ^ b.lo;} void_vpp(Vlong *l, Vlong *r){ 	l->hi = r->hi;	l->lo = r->lo;	r->lo++;	if(r->lo == 0)		r->hi++;} void_vmm(Vlong *l, Vlong *r){ 	l->hi = r->hi;	l->lo = r->lo;	if(r->lo == 0)		r->hi--;	r->lo--;} void_ppv(Vlong *l, Vlong *r){ 	r->lo++;	if(r->lo == 0)		r->hi++;	l->hi = r->hi;	l->lo = r->lo;} void_mmv(Vlong *l, Vlong *r){ 	if(r->lo == 0)		r->hi--;	r->lo--;	l->hi = r->hi;	l->lo = r->lo;} void_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv){	Vlong t, u; 	u.lo = 0;	u.hi = 0;	switch(type) {	default:		abort();		break; 	case 1:	/* schar */		t.lo = *(schar*)lv;		t.hi = t.lo >> 31;		fn(&u, t, rv);		*(schar*)lv = u.lo;		break; 	case 2:	/* uchar */		t.lo = *(uchar*)lv;		t.hi = 0;		fn(&u, t, rv);		*(uchar*)lv = u.lo;		break; 	case 3:	/* short */		t.lo = *(short*)lv;		t.hi = t.lo >> 31;		fn(&u, t, rv);		*(short*)lv = u.lo;		break; 	case 4:	/* ushort */		t.lo = *(ushort*)lv;		t.hi = 0;		fn(&u, t, rv);		*(ushort*)lv = u.lo;		break; 	case 9:	/* int */		t.lo = *(int*)lv;		t.hi = t.lo >> 31;		fn(&u, t, rv);		*(int*)lv = u.lo;		break; 	case 10:	/* uint */		t.lo = *(uint*)lv;		t.hi = 0;		fn(&u, t, rv);		*(uint*)lv = u.lo;		break; 	case 5:	/* long */		t.lo = *(long*)lv;		t.hi = t.lo >> 31;		fn(&u, t, rv);		*(long*)lv = u.lo;		break; 	case 6:	/* ulong */		t.lo = *(ulong*)lv;		t.hi = 0;		fn(&u, t, rv);		*(ulong*)lv = u.lo;		break; 	case 7:	/* vlong */

Lines 1–500 of 731.