...

Source file src/runtime/vlrt.go

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

View as plain text