github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/runtime/vlrt.go (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 // +build arm 386 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 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 func int64mod(n, d int64) int64 { 165 // Check for 32 bit operands 166 if int64(int32(n)) == n && int64(int32(d)) == d { 167 if int32(d) == 0 { 168 panicdivide() 169 } 170 return int64(int32(n) % int32(d)) 171 } 172 173 nneg := n < 0 174 if nneg { 175 n = -n 176 } 177 if d < 0 { 178 d = -d 179 } 180 _, ur := dodiv(uint64(n), uint64(d)) 181 r := int64(ur) 182 if nneg { 183 r = -r 184 } 185 return r 186 } 187 188 //go:noescape 189 func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32) 190 191 //go:noescape 192 func _div64by32(a uint64, b uint32, r *uint32) (q uint32) 193 194 func dodiv(n, d uint64) (q, r uint64) { 195 if GOARCH == "arm" { 196 // arm doesn't have a division instruction, so 197 // slowdodiv is the best that we can do. 198 // TODO: revisit for arm64. 199 return slowdodiv(n, d) 200 } 201 202 if d > n { 203 return 0, n 204 } 205 206 if uint32(d>>32) != 0 { 207 t := uint32(n>>32) / uint32(d>>32) 208 var lo64 uint64 209 hi32 := _mul64by32(&lo64, d, t) 210 if hi32 != 0 || lo64 > n { 211 return slowdodiv(n, d) 212 } 213 return uint64(t), n - lo64 214 } 215 216 // d is 32 bit 217 var qhi uint32 218 if uint32(n>>32) >= uint32(d) { 219 if uint32(d) == 0 { 220 panicdivide() 221 } 222 qhi = uint32(n>>32) / uint32(d) 223 n -= uint64(uint32(d)*qhi) << 32 224 } else { 225 qhi = 0 226 } 227 228 var rlo uint32 229 qlo := _div64by32(n, uint32(d), &rlo) 230 return uint64(qhi)<<32 + uint64(qlo), uint64(rlo) 231 } 232 233 func slowdodiv(n, d uint64) (q, r uint64) { 234 if d == 0 { 235 panicdivide() 236 } 237 238 // Set up the divisor and find the number of iterations needed. 239 capn := n 240 if n >= sign64 { 241 capn = sign64 242 } 243 i := 0 244 for d < capn { 245 d <<= 1 246 i++ 247 } 248 249 for ; i >= 0; i-- { 250 q <<= 1 251 if n >= d { 252 n -= d 253 q |= 1 254 } 255 d >>= 1 256 } 257 return q, n 258 }