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