Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/vlrt.go

Documentation: runtime

     1  // Inferno's libkern/vlrt-arm.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/master/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  //go:build arm || 386 || mips || mipsle
    27  // +build arm 386 mips mipsle
    28  
    29  package runtime
    30  
    31  import "unsafe"
    32  
    33  const (
    34  	sign32 = 1 << (32 - 1)
    35  	sign64 = 1 << (64 - 1)
    36  )
    37  
    38  func float64toint64(d float64) (y uint64) {
    39  	_d2v(&y, d)
    40  	return
    41  }
    42  
    43  func float64touint64(d float64) (y uint64) {
    44  	_d2v(&y, d)
    45  	return
    46  }
    47  
    48  func int64tofloat64(y int64) float64 {
    49  	if y < 0 {
    50  		return -uint64tofloat64(-uint64(y))
    51  	}
    52  	return uint64tofloat64(uint64(y))
    53  }
    54  
    55  func uint64tofloat64(y uint64) float64 {
    56  	hi := float64(uint32(y >> 32))
    57  	lo := float64(uint32(y))
    58  	d := hi*(1<<32) + lo
    59  	return d
    60  }
    61  
    62  func _d2v(y *uint64, d float64) {
    63  	x := *(*uint64)(unsafe.Pointer(&d))
    64  
    65  	xhi := uint32(x>>32)&0xfffff | 0x100000
    66  	xlo := uint32(x)
    67  	sh := 1075 - int32(uint32(x>>52)&0x7ff)
    68  
    69  	var ylo, yhi uint32
    70  	if sh >= 0 {
    71  		sh := uint32(sh)
    72  		/* v = (hi||lo) >> sh */
    73  		if sh < 32 {
    74  			if sh == 0 {
    75  				ylo = xlo
    76  				yhi = xhi
    77  			} else {
    78  				ylo = xlo>>sh | xhi<<(32-sh)
    79  				yhi = xhi >> sh
    80  			}
    81  		} else {
    82  			if sh == 32 {
    83  				ylo = xhi
    84  			} else if sh < 64 {
    85  				ylo = xhi >> (sh - 32)
    86  			}
    87  		}
    88  	} else {
    89  		/* v = (hi||lo) << -sh */
    90  		sh := uint32(-sh)
    91  		if sh <= 11 {
    92  			ylo = xlo << sh
    93  			yhi = xhi<<sh | xlo>>(32-sh)
    94  		} else {
    95  			/* overflow */
    96  			yhi = uint32(d) /* causes something awful */
    97  		}
    98  	}
    99  	if x&sign64 != 0 {
   100  		if ylo != 0 {
   101  			ylo = -ylo
   102  			yhi = ^yhi
   103  		} else {
   104  			yhi = -yhi
   105  		}
   106  	}
   107  
   108  	*y = uint64(yhi)<<32 | uint64(ylo)
   109  }
   110  func uint64div(n, d uint64) uint64 {
   111  	// Check for 32 bit operands
   112  	if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
   113  		if uint32(d) == 0 {
   114  			panicdivide()
   115  		}
   116  		return uint64(uint32(n) / uint32(d))
   117  	}
   118  	q, _ := dodiv(n, d)
   119  	return q
   120  }
   121  
   122  func uint64mod(n, d uint64) uint64 {
   123  	// Check for 32 bit operands
   124  	if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
   125  		if uint32(d) == 0 {
   126  			panicdivide()
   127  		}
   128  		return uint64(uint32(n) % uint32(d))
   129  	}
   130  	_, r := dodiv(n, d)
   131  	return r
   132  }
   133  
   134  func int64div(n, d int64) int64 {
   135  	// Check for 32 bit operands
   136  	if int64(int32(n)) == n && int64(int32(d)) == d {
   137  		if int32(n) == -0x80000000 && int32(d) == -1 {
   138  			// special case: 32-bit -0x80000000 / -1 = -0x80000000,
   139  			// but 64-bit -0x80000000 / -1 = 0x80000000.
   140  			return 0x80000000
   141  		}
   142  		if int32(d) == 0 {
   143  			panicdivide()
   144  		}
   145  		return int64(int32(n) / int32(d))
   146  	}
   147  
   148  	nneg := n < 0
   149  	dneg := d < 0
   150  	if nneg {
   151  		n = -n
   152  	}
   153  	if dneg {
   154  		d = -d
   155  	}
   156  	uq, _ := dodiv(uint64(n), uint64(d))
   157  	q := int64(uq)
   158  	if nneg != dneg {
   159  		q = -q
   160  	}
   161  	return q
   162  }
   163  
   164  //go:nosplit
   165  func int64mod(n, d int64) int64 {
   166  	// Check for 32 bit operands
   167  	if int64(int32(n)) == n && int64(int32(d)) == d {
   168  		if int32(d) == 0 {
   169  			panicdivide()
   170  		}
   171  		return int64(int32(n) % int32(d))
   172  	}
   173  
   174  	nneg := n < 0
   175  	if nneg {
   176  		n = -n
   177  	}
   178  	if d < 0 {
   179  		d = -d
   180  	}
   181  	_, ur := dodiv(uint64(n), uint64(d))
   182  	r := int64(ur)
   183  	if nneg {
   184  		r = -r
   185  	}
   186  	return r
   187  }
   188  
   189  //go:noescape
   190  func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32)
   191  
   192  //go:noescape
   193  func _div64by32(a uint64, b uint32, r *uint32) (q uint32)
   194  
   195  //go:nosplit
   196  func dodiv(n, d uint64) (q, r uint64) {
   197  	if GOARCH == "arm" {
   198  		// arm doesn't have a division instruction, so
   199  		// slowdodiv is the best that we can do.
   200  		return slowdodiv(n, d)
   201  	}
   202  
   203  	if GOARCH == "mips" || GOARCH == "mipsle" {
   204  		// No _div64by32 on mips and using only _mul64by32 doesn't bring much benefit
   205  		return slowdodiv(n, d)
   206  	}
   207  
   208  	if d > n {
   209  		return 0, n
   210  	}
   211  
   212  	if uint32(d>>32) != 0 {
   213  		t := uint32(n>>32) / uint32(d>>32)
   214  		var lo64 uint64
   215  		hi32 := _mul64by32(&lo64, d, t)
   216  		if hi32 != 0 || lo64 > n {
   217  			return slowdodiv(n, d)
   218  		}
   219  		return uint64(t), n - lo64
   220  	}
   221  
   222  	// d is 32 bit
   223  	var qhi uint32
   224  	if uint32(n>>32) >= uint32(d) {
   225  		if uint32(d) == 0 {
   226  			panicdivide()
   227  		}
   228  		qhi = uint32(n>>32) / uint32(d)
   229  		n -= uint64(uint32(d)*qhi) << 32
   230  	} else {
   231  		qhi = 0
   232  	}
   233  
   234  	var rlo uint32
   235  	qlo := _div64by32(n, uint32(d), &rlo)
   236  	return uint64(qhi)<<32 + uint64(qlo), uint64(rlo)
   237  }
   238  
   239  //go:nosplit
   240  func slowdodiv(n, d uint64) (q, r uint64) {
   241  	if d == 0 {
   242  		panicdivide()
   243  	}
   244  
   245  	// Set up the divisor and find the number of iterations needed.
   246  	capn := n
   247  	if n >= sign64 {
   248  		capn = sign64
   249  	}
   250  	i := 0
   251  	for d < capn {
   252  		d <<= 1
   253  		i++
   254  	}
   255  
   256  	for ; i >= 0; i-- {
   257  		q <<= 1
   258  		if n >= d {
   259  			n -= d
   260  			q |= 1
   261  		}
   262  		d >>= 1
   263  	}
   264  	return q, n
   265  }
   266  
   267  // Floating point control word values.
   268  // Bits 0-5 are bits to disable floating-point exceptions.
   269  // Bits 8-9 are the precision control:
   270  //   0 = single precision a.k.a. float32
   271  //   2 = double precision a.k.a. float64
   272  // Bits 10-11 are the rounding mode:
   273  //   0 = round to nearest (even on a tie)
   274  //   3 = round toward zero
   275  var (
   276  	controlWord64      uint16 = 0x3f + 2<<8 + 0<<10
   277  	controlWord64trunc uint16 = 0x3f + 2<<8 + 3<<10
   278  )
   279  

View as plain text