github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/vlrt_arm.c (about)

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