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