github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/vlrt_386.c (about)

     1  // Inferno's libkern/vlrt-386.c
     2  // http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-386.c
     3  //
     4  //         Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //         Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
     6  //         Portions Copyright 2009 The Go Authors. All rights reserved.
     7  //
     8  // Permission is hereby granted, free of charge, to any person obtaining a copy
     9  // of this software and associated documentation files (the "Software"), to deal
    10  // in the Software without restriction, including without limitation the rights
    11  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    12  // copies of the Software, and to permit persons to whom the Software is
    13  // furnished to do so, subject to the following conditions:
    14  //
    15  // The above copyright notice and this permission notice shall be included in
    16  // all copies or substantial portions of the Software.
    17  //
    18  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    19  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    20  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    21  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    22  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    24  // THE SOFTWARE.
    25  
    26  #include "../../cmd/ld/textflag.h"
    27  
    28  /*
    29   * C runtime for 64-bit divide, others.
    30   *
    31   * TODO(rsc): The simple functions are dregs--8c knows how
    32   * to generate the code directly now.  Find and remove.
    33   */
    34  
    35  typedef	unsigned long	ulong;
    36  typedef	unsigned int	uint;
    37  typedef	unsigned short	ushort;
    38  typedef	unsigned char	uchar;
    39  typedef	signed char	schar;
    40  
    41  #define	SIGN(n)	(1UL<<(n-1))
    42  
    43  typedef	struct	Vlong	Vlong;
    44  struct	Vlong
    45  {
    46  	union
    47  	{
    48  		long long	v;
    49  		struct
    50  		{
    51  			ulong	lo;
    52  			ulong	hi;
    53  		};
    54  		struct
    55  		{
    56  			ushort	lols;
    57  			ushort	loms;
    58  			ushort	hils;
    59  			ushort	hims;
    60  		};
    61  	};
    62  };
    63  
    64  void	runtime·abort(void);
    65  
    66  void
    67  _d2v(Vlong *y, double d)
    68  {
    69  	union { double d; struct Vlong; } x;
    70  	ulong xhi, xlo, ylo, yhi;
    71  	int sh;
    72  
    73  	x.d = d;
    74  
    75  	xhi = (x.hi & 0xfffff) | 0x100000;
    76  	xlo = x.lo;
    77  	sh = 1075 - ((x.hi >> 20) & 0x7ff);
    78  
    79  	ylo = 0;
    80  	yhi = 0;
    81  	if(sh >= 0) {
    82  		/* v = (hi||lo) >> sh */
    83  		if(sh < 32) {
    84  			if(sh == 0) {
    85  				ylo = xlo;
    86  				yhi = xhi;
    87  			} else {
    88  				ylo = (xlo >> sh) | (xhi << (32-sh));
    89  				yhi = xhi >> sh;
    90  			}
    91  		} else {
    92  			if(sh == 32) {
    93  				ylo = xhi;
    94  			} else
    95  			if(sh < 64) {
    96  				ylo = xhi >> (sh-32);
    97  			}
    98  		}
    99  	} else {
   100  		/* v = (hi||lo) << -sh */
   101  		sh = -sh;
   102  		if(sh <= 10) {
   103  			ylo = xlo << sh;
   104  			yhi = (xhi << sh) | (xlo >> (32-sh));
   105  		} else {
   106  			/* overflow */
   107  			yhi = d;	/* causes something awful */
   108  		}
   109  	}
   110  	if(x.hi & SIGN(32)) {
   111  		if(ylo != 0) {
   112  			ylo = -ylo;
   113  			yhi = ~yhi;
   114  		} else
   115  			yhi = -yhi;
   116  	}
   117  
   118  	y->hi = yhi;
   119  	y->lo = ylo;
   120  }
   121  
   122  void
   123  _f2v(Vlong *y, float f)
   124  {
   125  
   126  	_d2v(y, f);
   127  }
   128  
   129  double
   130  _v2d(Vlong x)
   131  {
   132  	if(x.hi & SIGN(32)) {
   133  		if(x.lo) {
   134  			x.lo = -x.lo;
   135  			x.hi = ~x.hi;
   136  		} else
   137  			x.hi = -x.hi;
   138  		return -((long)x.hi*4294967296. + x.lo);
   139  	}
   140  	return (long)x.hi*4294967296. + x.lo;
   141  }
   142  
   143  float
   144  _v2f(Vlong x)
   145  {
   146  	return _v2d(x);
   147  }
   148  
   149  ulong	_div64by32(Vlong, ulong, ulong*);
   150  int	_mul64by32(Vlong*, Vlong, ulong);
   151  
   152  static void
   153  slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
   154  {
   155  	ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
   156  	int i;
   157  
   158  	numhi = num.hi;
   159  	numlo = num.lo;
   160  	denhi = den.hi;
   161  	denlo = den.lo;
   162  
   163  	/*
   164  	 * get a divide by zero
   165  	 */
   166  	if(denlo==0 && denhi==0) {
   167  		numlo = numlo / denlo;
   168  	}
   169  
   170  	/*
   171  	 * set up the divisor and find the number of iterations needed
   172  	 */
   173  	if(numhi >= SIGN(32)) {
   174  		quohi = SIGN(32);
   175  		quolo = 0;
   176  	} else {
   177  		quohi = numhi;
   178  		quolo = numlo;
   179  	}
   180  	i = 0;
   181  	while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
   182  		denhi = (denhi<<1) | (denlo>>31);
   183  		denlo <<= 1;
   184  		i++;
   185  	}
   186  
   187  	quohi = 0;
   188  	quolo = 0;
   189  	for(; i >= 0; i--) {
   190  		quohi = (quohi<<1) | (quolo>>31);
   191  		quolo <<= 1;
   192  		if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
   193  			t = numlo;
   194  			numlo -= denlo;
   195  			if(numlo > t)
   196  				numhi--;
   197  			numhi -= denhi;
   198  			quolo |= 1;
   199  		}
   200  		denlo = (denlo>>1) | (denhi<<31);
   201  		denhi >>= 1;
   202  	}
   203  
   204  	if(q) {
   205  		q->lo = quolo;
   206  		q->hi = quohi;
   207  	}
   208  	if(r) {
   209  		r->lo = numlo;
   210  		r->hi = numhi;
   211  	}
   212  }
   213  
   214  static void
   215  dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
   216  {
   217  	ulong n;
   218  	Vlong x, q, r;
   219  
   220  	if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){
   221  		if(qp) {
   222  			qp->hi = 0;
   223  			qp->lo = 0;
   224  		}
   225  		if(rp) {
   226  			rp->hi = num.hi;
   227  			rp->lo = num.lo;
   228  		}
   229  		return;
   230  	}
   231  
   232  	if(den.hi != 0){
   233  		q.hi = 0;
   234  		n = num.hi/den.hi;
   235  		if(_mul64by32(&x, den, n) || x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
   236  			slowdodiv(num, den, &q, &r);
   237  		else {
   238  			q.lo = n;
   239  			r.v = num.v - x.v;
   240  		}
   241  	} else {
   242  		if(num.hi >= den.lo){
   243  			q.hi = n = num.hi/den.lo;
   244  			num.hi -= den.lo*n;
   245  		} else {
   246  			q.hi = 0;
   247  		}
   248  		q.lo = _div64by32(num, den.lo, &r.lo);
   249  		r.hi = 0;
   250  	}
   251  	if(qp) {
   252  		qp->lo = q.lo;
   253  		qp->hi = q.hi;
   254  	}
   255  	if(rp) {
   256  		rp->lo = r.lo;
   257  		rp->hi = r.hi;
   258  	}
   259  }
   260  
   261  void
   262  _divvu(Vlong *q, Vlong n, Vlong d)
   263  {
   264  
   265  	if(n.hi == 0 && d.hi == 0) {
   266  		q->hi = 0;
   267  		q->lo = n.lo / d.lo;
   268  		return;
   269  	}
   270  	dodiv(n, d, q, 0);
   271  }
   272  
   273  void
   274  runtime·uint64div(Vlong n, Vlong d, Vlong q)
   275  {
   276  	_divvu(&q, n, d);
   277  }
   278  
   279  void
   280  _modvu(Vlong *r, Vlong n, Vlong d)
   281  {
   282  
   283  	if(n.hi == 0 && d.hi == 0) {
   284  		r->hi = 0;
   285  		r->lo = n.lo % d.lo;
   286  		return;
   287  	}
   288  	dodiv(n, d, 0, r);
   289  }
   290  
   291  void
   292  runtime·uint64mod(Vlong n, Vlong d, Vlong q)
   293  {
   294  	_modvu(&q, n, d);
   295  }
   296  
   297  static void
   298  vneg(Vlong *v)
   299  {
   300  
   301  	if(v->lo == 0) {
   302  		v->hi = -v->hi;
   303  		return;
   304  	}
   305  	v->lo = -v->lo;
   306  	v->hi = ~v->hi;
   307  }
   308  
   309  void
   310  _divv(Vlong *q, Vlong n, Vlong d)
   311  {
   312  	long nneg, dneg;
   313  
   314  	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
   315  		if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
   316  			// special case: 32-bit -0x80000000 / -1 causes divide error,
   317  			// but it's okay in this 64-bit context.
   318  			q->lo = 0x80000000;
   319  			q->hi = 0;
   320  			return;
   321  		}
   322  		q->lo = (long)n.lo / (long)d.lo;
   323  		q->hi = ((long)q->lo) >> 31;
   324  		return;
   325  	}
   326  	nneg = n.hi >> 31;
   327  	if(nneg)
   328  		vneg(&n);
   329  	dneg = d.hi >> 31;
   330  	if(dneg)
   331  		vneg(&d);
   332  	dodiv(n, d, q, 0);
   333  	if(nneg != dneg)
   334  		vneg(q);
   335  }
   336  
   337  void
   338  runtime·int64div(Vlong n, Vlong d, Vlong q)
   339  {
   340  	_divv(&q, n, d);
   341  }
   342  
   343  void
   344  _modv(Vlong *r, Vlong n, Vlong d)
   345  {
   346  	long nneg, dneg;
   347  
   348  	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
   349  		if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
   350  			// special case: 32-bit -0x80000000 % -1 causes divide error,
   351  			// but it's okay in this 64-bit context.
   352  			r->lo = 0;
   353  			r->hi = 0;
   354  			return;
   355  		}
   356  		r->lo = (long)n.lo % (long)d.lo;
   357  		r->hi = ((long)r->lo) >> 31;
   358  		return;
   359  	}
   360  	nneg = n.hi >> 31;
   361  	if(nneg)
   362  		vneg(&n);
   363  	dneg = d.hi >> 31;
   364  	if(dneg)
   365  		vneg(&d);
   366  	dodiv(n, d, 0, r);
   367  	if(nneg)
   368  		vneg(r);
   369  }
   370  
   371  void
   372  runtime·int64mod(Vlong n, Vlong d, Vlong q)
   373  {
   374  	_modv(&q, n, d);
   375  }
   376  
   377  void
   378  _rshav(Vlong *r, Vlong a, int b)
   379  {
   380  	long t;
   381  
   382  	t = a.hi;
   383  	if(b >= 32) {
   384  		r->hi = t>>31;
   385  		if(b >= 64) {
   386  			/* this is illegal re C standard */
   387  			r->lo = t>>31;
   388  			return;
   389  		}
   390  		r->lo = t >> (b-32);
   391  		return;
   392  	}
   393  	if(b <= 0) {
   394  		r->hi = t;
   395  		r->lo = a.lo;
   396  		return;
   397  	}
   398  	r->hi = t >> b;
   399  	r->lo = (t << (32-b)) | (a.lo >> b);
   400  }
   401  
   402  void
   403  _rshlv(Vlong *r, Vlong a, int b)
   404  {
   405  	ulong t;
   406  
   407  	t = a.hi;
   408  	if(b >= 32) {
   409  		r->hi = 0;
   410  		if(b >= 64) {
   411  			/* this is illegal re C standard */
   412  			r->lo = 0;
   413  			return;
   414  		}
   415  		r->lo = t >> (b-32);
   416  		return;
   417  	}
   418  	if(b <= 0) {
   419  		r->hi = t;
   420  		r->lo = a.lo;
   421  		return;
   422  	}
   423  	r->hi = t >> b;
   424  	r->lo = (t << (32-b)) | (a.lo >> b);
   425  }
   426  
   427  #pragma textflag NOSPLIT
   428  void
   429  _lshv(Vlong *r, Vlong a, int b)
   430  {
   431  	ulong t;
   432  
   433  	t = a.lo;
   434  	if(b >= 32) {
   435  		r->lo = 0;
   436  		if(b >= 64) {
   437  			/* this is illegal re C standard */
   438  			r->hi = 0;
   439  			return;
   440  		}
   441  		r->hi = t << (b-32);
   442  		return;
   443  	}
   444  	if(b <= 0) {
   445  		r->lo = t;
   446  		r->hi = a.hi;
   447  		return;
   448  	}
   449  	r->lo = t << b;
   450  	r->hi = (t >> (32-b)) | (a.hi << b);
   451  }
   452  
   453  void
   454  _andv(Vlong *r, Vlong a, Vlong b)
   455  {
   456  	r->hi = a.hi & b.hi;
   457  	r->lo = a.lo & b.lo;
   458  }
   459  
   460  void
   461  _orv(Vlong *r, Vlong a, Vlong b)
   462  {
   463  	r->hi = a.hi | b.hi;
   464  	r->lo = a.lo | b.lo;
   465  }
   466  
   467  void
   468  _xorv(Vlong *r, Vlong a, Vlong b)
   469  {
   470  	r->hi = a.hi ^ b.hi;
   471  	r->lo = a.lo ^ b.lo;
   472  }
   473  
   474  void
   475  _vpp(Vlong *l, Vlong *r)
   476  {
   477  
   478  	l->hi = r->hi;
   479  	l->lo = r->lo;
   480  	r->lo++;
   481  	if(r->lo == 0)
   482  		r->hi++;
   483  }
   484  
   485  void
   486  _vmm(Vlong *l, Vlong *r)
   487  {
   488  
   489  	l->hi = r->hi;
   490  	l->lo = r->lo;
   491  	if(r->lo == 0)
   492  		r->hi--;
   493  	r->lo--;
   494  }
   495  
   496  void
   497  _ppv(Vlong *l, Vlong *r)
   498  {
   499  
   500  	r->lo++;
   501  	if(r->lo == 0)
   502  		r->hi++;
   503  	l->hi = r->hi;
   504  	l->lo = r->lo;
   505  }
   506  
   507  void
   508  _mmv(Vlong *l, Vlong *r)
   509  {
   510  
   511  	if(r->lo == 0)
   512  		r->hi--;
   513  	r->lo--;
   514  	l->hi = r->hi;
   515  	l->lo = r->lo;
   516  }
   517  
   518  void
   519  _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
   520  {
   521  	Vlong t, u;
   522  
   523  	u.lo = 0;
   524  	u.hi = 0;
   525  	switch(type) {
   526  	default:
   527  		runtime·abort();
   528  		break;
   529  
   530  	case 1:	/* schar */
   531  		t.lo = *(schar*)lv;
   532  		t.hi = t.lo >> 31;
   533  		fn(&u, t, rv);
   534  		*(schar*)lv = u.lo;
   535  		break;
   536  
   537  	case 2:	/* uchar */
   538  		t.lo = *(uchar*)lv;
   539  		t.hi = 0;
   540  		fn(&u, t, rv);
   541  		*(uchar*)lv = u.lo;
   542  		break;
   543  
   544  	case 3:	/* short */
   545  		t.lo = *(short*)lv;
   546  		t.hi = t.lo >> 31;
   547  		fn(&u, t, rv);
   548  		*(short*)lv = u.lo;
   549  		break;
   550  
   551  	case 4:	/* ushort */
   552  		t.lo = *(ushort*)lv;
   553  		t.hi = 0;
   554  		fn(&u, t, rv);
   555  		*(ushort*)lv = u.lo;
   556  		break;
   557  
   558  	case 9:	/* int */
   559  		t.lo = *(int*)lv;
   560  		t.hi = t.lo >> 31;
   561  		fn(&u, t, rv);
   562  		*(int*)lv = u.lo;
   563  		break;
   564  
   565  	case 10:	/* uint */
   566  		t.lo = *(uint*)lv;
   567  		t.hi = 0;
   568  		fn(&u, t, rv);
   569  		*(uint*)lv = u.lo;
   570  		break;
   571  
   572  	case 5:	/* long */
   573  		t.lo = *(long*)lv;
   574  		t.hi = t.lo >> 31;
   575  		fn(&u, t, rv);
   576  		*(long*)lv = u.lo;
   577  		break;
   578  
   579  	case 6:	/* ulong */
   580  		t.lo = *(ulong*)lv;
   581  		t.hi = 0;
   582  		fn(&u, t, rv);
   583  		*(ulong*)lv = u.lo;
   584  		break;
   585  
   586  	case 7:	/* vlong */
   587  	case 8:	/* uvlong */
   588  		fn(&u, *(Vlong*)lv, rv);
   589  		*(Vlong*)lv = u;
   590  		break;
   591  	}
   592  	*ret = u;
   593  }
   594  
   595  void
   596  _p2v(Vlong *ret, void *p)
   597  {
   598  	long t;
   599  
   600  	t = (ulong)p;
   601  	ret->lo = t;
   602  	ret->hi = 0;
   603  }
   604  
   605  void
   606  _sl2v(Vlong *ret, long sl)
   607  {
   608  	long t;
   609  
   610  	t = sl;
   611  	ret->lo = t;
   612  	ret->hi = t >> 31;
   613  }
   614  
   615  void
   616  _ul2v(Vlong *ret, ulong ul)
   617  {
   618  	long t;
   619  
   620  	t = ul;
   621  	ret->lo = t;
   622  	ret->hi = 0;
   623  }
   624  
   625  void
   626  _si2v(Vlong *ret, int si)
   627  {
   628  	long t;
   629  
   630  	t = si;
   631  	ret->lo = t;
   632  	ret->hi = t >> 31;
   633  }
   634  
   635  void
   636  _ui2v(Vlong *ret, uint ui)
   637  {
   638  	long t;
   639  
   640  	t = ui;
   641  	ret->lo = t;
   642  	ret->hi = 0;
   643  }
   644  
   645  void
   646  _sh2v(Vlong *ret, long sh)
   647  {
   648  	long t;
   649  
   650  	t = (sh << 16) >> 16;
   651  	ret->lo = t;
   652  	ret->hi = t >> 31;
   653  }
   654  
   655  void
   656  _uh2v(Vlong *ret, ulong ul)
   657  {
   658  	long t;
   659  
   660  	t = ul & 0xffff;
   661  	ret->lo = t;
   662  	ret->hi = 0;
   663  }
   664  
   665  void
   666  _sc2v(Vlong *ret, long uc)
   667  {
   668  	long t;
   669  
   670  	t = (uc << 24) >> 24;
   671  	ret->lo = t;
   672  	ret->hi = t >> 31;
   673  }
   674  
   675  void
   676  _uc2v(Vlong *ret, ulong ul)
   677  {
   678  	long t;
   679  
   680  	t = ul & 0xff;
   681  	ret->lo = t;
   682  	ret->hi = 0;
   683  }
   684  
   685  long
   686  _v2sc(Vlong rv)
   687  {
   688  	long t;
   689  
   690  	t = rv.lo & 0xff;
   691  	return (t << 24) >> 24;
   692  }
   693  
   694  long
   695  _v2uc(Vlong rv)
   696  {
   697  
   698  	return rv.lo & 0xff;
   699  }
   700  
   701  long
   702  _v2sh(Vlong rv)
   703  {
   704  	long t;
   705  
   706  	t = rv.lo & 0xffff;
   707  	return (t << 16) >> 16;
   708  }
   709  
   710  long
   711  _v2uh(Vlong rv)
   712  {
   713  
   714  	return rv.lo & 0xffff;
   715  }
   716  
   717  long
   718  _v2sl(Vlong rv)
   719  {
   720  
   721  	return rv.lo;
   722  }
   723  
   724  long
   725  _v2ul(Vlong rv)
   726  {
   727  
   728  	return rv.lo;
   729  }
   730  
   731  long
   732  _v2si(Vlong rv)
   733  {
   734  
   735  	return rv.lo;
   736  }
   737  
   738  long
   739  _v2ui(Vlong rv)
   740  {
   741  
   742  	return rv.lo;
   743  }
   744  
   745  int
   746  _testv(Vlong rv)
   747  {
   748  	return rv.lo || rv.hi;
   749  }
   750  
   751  int
   752  _eqv(Vlong lv, Vlong rv)
   753  {
   754  	return lv.lo == rv.lo && lv.hi == rv.hi;
   755  }
   756  
   757  int
   758  _nev(Vlong lv, Vlong rv)
   759  {
   760  	return lv.lo != rv.lo || lv.hi != rv.hi;
   761  }
   762  
   763  int
   764  _ltv(Vlong lv, Vlong rv)
   765  {
   766  	return (long)lv.hi < (long)rv.hi ||
   767  		(lv.hi == rv.hi && lv.lo < rv.lo);
   768  }
   769  
   770  int
   771  _lev(Vlong lv, Vlong rv)
   772  {
   773  	return (long)lv.hi < (long)rv.hi ||
   774  		(lv.hi == rv.hi && lv.lo <= rv.lo);
   775  }
   776  
   777  int
   778  _gtv(Vlong lv, Vlong rv)
   779  {
   780  	return (long)lv.hi > (long)rv.hi ||
   781  		(lv.hi == rv.hi && lv.lo > rv.lo);
   782  }
   783  
   784  int
   785  _gev(Vlong lv, Vlong rv)
   786  {
   787  	return (long)lv.hi > (long)rv.hi ||
   788  		(lv.hi == rv.hi && lv.lo >= rv.lo);
   789  }
   790  
   791  int
   792  _lov(Vlong lv, Vlong rv)
   793  {
   794  	return lv.hi < rv.hi ||
   795  		(lv.hi == rv.hi && lv.lo < rv.lo);
   796  }
   797  
   798  int
   799  _lsv(Vlong lv, Vlong rv)
   800  {
   801  	return lv.hi < rv.hi ||
   802  		(lv.hi == rv.hi && lv.lo <= rv.lo);
   803  }
   804  
   805  int
   806  _hiv(Vlong lv, Vlong rv)
   807  {
   808  	return lv.hi > rv.hi ||
   809  		(lv.hi == rv.hi && lv.lo > rv.lo);
   810  }
   811  
   812  int
   813  _hsv(Vlong lv, Vlong rv)
   814  {
   815  	return lv.hi > rv.hi ||
   816  		(lv.hi == rv.hi && lv.lo >= rv.lo);
   817  }