1 // Inferno's libkern/vlrt-arm.c
2 // https://bitbucket.org/inferno-os/inferno-os/src/master/libkern/vlrt-arm.c
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.
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:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
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
26 //go:build arm || 386 || mips || mipsle
33 sign32 = 1 << (32 - 1)
34 sign64 = 1 << (64 - 1)
37 func float64toint64(d float64) (y uint64) {
42 func float64touint64(d float64) (y uint64) {
47 func int64tofloat64(y int64) float64 {
49 return -uint64tofloat64(-uint64(y))
51 return uint64tofloat64(uint64(y))
54 func uint64tofloat64(y uint64) float64 {
55 hi := float64(uint32(y >> 32))
56 lo := float64(uint32(y))
61 func int64tofloat32(y int64) float32 {
63 return -uint64tofloat32(-uint64(y))
65 return uint64tofloat32(uint64(y))
68 func uint64tofloat32(y uint64) float32 {
69 // divide into top 18, mid 23, and bottom 23 bits.
70 // (23-bit integers fit into a float32 without loss.)
71 top := uint32(y >> 46)
72 mid := uint32(y >> 23 & (1<<23 - 1))
73 bot := uint32(y & (1<<23 - 1))
75 return float32(mid)*(1<<23) + float32(bot)
78 // Top is not zero, so the bits in bot
79 // won't make it into the final mantissa.
80 // In fact, the bottom bit of mid won't
81 // make it into the mantissa either.
82 // We only need to make sure that if top+mid
83 // is about to round down in a round-to-even
84 // scenario, and bot is not zero, we make it
88 return float32(top)*(1<<46) + float32(mid)*(1<<23)
91 func _d2v(y *uint64, d float64) {
92 x := *(*uint64)(unsafe.Pointer(&d))
94 xhi := uint32(x>>32)&0xfffff | 0x100000
96 sh := 1075 - int32(uint32(x>>52)&0x7ff)
101 /* v = (hi||lo) >> sh */
107 ylo = xlo>>sh | xhi<<(32-sh)
114 ylo = xhi >> (sh - 32)
118 /* v = (hi||lo) << -sh */
122 yhi = xhi<<sh | xlo>>(32-sh)
125 yhi = uint32(d) /* causes something awful */
137 *y = uint64(yhi)<<32 | uint64(ylo)
139 func uint64div(n, d uint64) uint64 {
140 // Check for 32 bit operands
141 if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
145 return uint64(uint32(n) / uint32(d))
151 func uint64mod(n, d uint64) uint64 {
152 // Check for 32 bit operands
153 if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
157 return uint64(uint32(n) % uint32(d))
163 func int64div(n, d int64) int64 {
164 // Check for 32 bit operands
165 if int64(int32(n)) == n && int64(int32(d)) == d {
166 if int32(n) == -0x80000000 && int32(d) == -1 {
167 // special case: 32-bit -0x80000000 / -1 = -0x80000000,
168 // but 64-bit -0x80000000 / -1 = 0x80000000.
174 return int64(int32(n) / int32(d))
185 uq, _ := dodiv(uint64(n), uint64(d))
194 func int64mod(n, d int64) int64 {
195 // Check for 32 bit operands
196 if int64(int32(n)) == n && int64(int32(d)) == d {
200 return int64(int32(n) % int32(d))
210 _, ur := dodiv(uint64(n), uint64(d))
219 func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32)
222 func _div64by32(a uint64, b uint32, r *uint32) (q uint32)
225 func dodiv(n, d uint64) (q, r uint64) {
227 // arm doesn't have a division instruction, so
228 // slowdodiv is the best that we can do.
229 return slowdodiv(n, d)
232 if GOARCH == "mips" || GOARCH == "mipsle" {
233 // No _div64by32 on mips and using only _mul64by32 doesn't bring much benefit
234 return slowdodiv(n, d)
241 if uint32(d>>32) != 0 {
242 t := uint32(n>>32) / uint32(d>>32)
244 hi32 := _mul64by32(&lo64, d, t)
245 if hi32 != 0 || lo64 > n {
246 return slowdodiv(n, d)
248 return uint64(t), n - lo64
253 if uint32(n>>32) >= uint32(d) {
257 qhi = uint32(n>>32) / uint32(d)
258 n -= uint64(uint32(d)*qhi) << 32
264 qlo := _div64by32(n, uint32(d), &rlo)
265 return uint64(qhi)<<32 + uint64(qlo), uint64(rlo)
269 func slowdodiv(n, d uint64) (q, r uint64) {
274 // Set up the divisor and find the number of iterations needed.
296 // Floating point control word values.
297 // Bits 0-5 are bits to disable floating-point exceptions.
298 // Bits 8-9 are the precision control:
300 // 0 = single precision a.k.a. float32
301 // 2 = double precision a.k.a. float64
303 // Bits 10-11 are the rounding mode:
305 // 0 = round to nearest (even on a tie)
306 // 3 = round toward zero
308 controlWord64 uint16 = 0x3f + 2<<8 + 0<<10
309 controlWord64trunc uint16 = 0x3f + 2<<8 + 3<<10