URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [runtime/] [softfloat64.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Software IEEE754 64-bit floating point.// Only referred to (and thus linked in) by arm port// and by gotest in this directory.package runtimeconst (mantbits64 uint = 52expbits64 uint = 11bias64 = -1<<(expbits64-1) + 1nan64 uint64 = (1<<expbits64-1)<<mantbits64 + 1inf64 uint64 = (1<<expbits64 - 1) << mantbits64neg64 uint64 = 1 << (expbits64 + mantbits64)mantbits32 uint = 23expbits32 uint = 8bias32 = -1<<(expbits32-1) + 1nan32 uint32 = (1<<expbits32-1)<<mantbits32 + 1inf32 uint32 = (1<<expbits32 - 1) << mantbits32neg32 uint32 = 1 << (expbits32 + mantbits32))func funpack64(f uint64) (sign, mant uint64, exp int, inf, nan bool) {sign = f & (1 << (mantbits64 + expbits64))mant = f & (1<<mantbits64 - 1)exp = int(f>>mantbits64) & (1<<expbits64 - 1)switch exp {case 1<<expbits64 - 1:if mant != 0 {nan = truereturn}inf = truereturncase 0:// denormalizedif mant != 0 {exp += bias64 + 1for mant < 1<<mantbits64 {mant <<= 1exp--}}default:// add implicit top bitmant |= 1 << mantbits64exp += bias64}return}func funpack32(f uint32) (sign, mant uint32, exp int, inf, nan bool) {sign = f & (1 << (mantbits32 + expbits32))mant = f & (1<<mantbits32 - 1)exp = int(f>>mantbits32) & (1<<expbits32 - 1)switch exp {case 1<<expbits32 - 1:if mant != 0 {nan = truereturn}inf = truereturncase 0:// denormalizedif mant != 0 {exp += bias32 + 1for mant < 1<<mantbits32 {mant <<= 1exp--}}default:// add implicit top bitmant |= 1 << mantbits32exp += bias32}return}func fpack64(sign, mant uint64, exp int, trunc uint64) uint64 {mant0, exp0, trunc0 := mant, exp, truncif mant == 0 {return sign}for mant < 1<<mantbits64 {mant <<= 1exp--}for mant >= 4<<mantbits64 {trunc |= mant & 1mant >>= 1exp++}if mant >= 2<<mantbits64 {if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {mant++if mant >= 4<<mantbits64 {mant >>= 1exp++}}mant >>= 1exp++}if exp >= 1<<expbits64-1+bias64 {return sign ^ inf64}if exp < bias64+1 {if exp < bias64-int(mantbits64) {return sign | 0}// repeat expecting denormalmant, exp, trunc = mant0, exp0, trunc0for exp < bias64 {trunc |= mant & 1mant >>= 1exp++}if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {mant++}mant >>= 1exp++if mant < 1<<mantbits64 {return sign | mant}}return sign | uint64(exp-bias64)<<mantbits64 | mant&(1<<mantbits64-1)}func fpack32(sign, mant uint32, exp int, trunc uint32) uint32 {mant0, exp0, trunc0 := mant, exp, truncif mant == 0 {return sign}for mant < 1<<mantbits32 {mant <<= 1exp--}for mant >= 4<<mantbits32 {trunc |= mant & 1mant >>= 1exp++}if mant >= 2<<mantbits32 {if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {mant++if mant >= 4<<mantbits32 {mant >>= 1exp++}}mant >>= 1exp++}if exp >= 1<<expbits32-1+bias32 {return sign ^ inf32}if exp < bias32+1 {if exp < bias32-int(mantbits32) {return sign | 0}// repeat expecting denormalmant, exp, trunc = mant0, exp0, trunc0for exp < bias32 {trunc |= mant & 1mant >>= 1exp++}if mant&1 != 0 && (trunc != 0 || mant&2 != 0) {mant++}mant >>= 1exp++if mant < 1<<mantbits32 {return sign | mant}}return sign | uint32(exp-bias32)<<mantbits32 | mant&(1<<mantbits32-1)}func fadd64(f, g uint64) uint64 {fs, fm, fe, fi, fn := funpack64(f)gs, gm, ge, gi, gn := funpack64(g)// Special cases.switch {case fn || gn: // NaN + x or x + NaN = NaNreturn nan64case fi && gi && fs != gs: // +Inf + -Inf or -Inf + +Inf = NaNreturn nan64case fi: // ±Inf + g = ±Infreturn fcase gi: // f + ±Inf = ±Infreturn gcase fm == 0 && gm == 0 && fs != 0 && gs != 0: // -0 + -0 = -0return fcase fm == 0: // 0 + g = g but 0 + -0 = +0if gm == 0 {g ^= gs}return gcase gm == 0: // f + 0 = freturn f}if fe < ge || fe == ge && fm < gm {f, g, fs, fm, fe, gs, gm, ge = g, f, gs, gm, ge, fs, fm, fe}shift := uint(fe - ge)fm <<= 2gm <<= 2trunc := gm & (1<<shift - 1)gm >>= shiftif fs == gs {fm += gm} else {fm -= gmif trunc != 0 {fm--}}if fm == 0 {fs = 0}return fpack64(fs, fm, fe-2, trunc)}func fsub64(f, g uint64) uint64 {return fadd64(f, fneg64(g))}func fneg64(f uint64) uint64 {return f ^ (1 << (mantbits64 + expbits64))}func fmul64(f, g uint64) uint64 {fs, fm, fe, fi, fn := funpack64(f)gs, gm, ge, gi, gn := funpack64(g)// Special cases.switch {case fn || gn: // NaN * g or f * NaN = NaNreturn nan64case fi && gi: // Inf * Inf = Inf (with sign adjusted)return f ^ gscase fi && gm == 0, fm == 0 && gi: // 0 * Inf = Inf * 0 = NaNreturn nan64case fm == 0: // 0 * x = 0 (with sign adjusted)return f ^ gscase gm == 0: // x * 0 = 0 (with sign adjusted)return g ^ fs}// 53-bit * 53-bit = 107- or 108-bitlo, hi := mullu(fm, gm)shift := mantbits64 - 1trunc := lo & (1<<shift - 1)mant := hi<<(64-shift) | lo>>shiftreturn fpack64(fs^gs, mant, fe+ge-1, trunc)}func fdiv64(f, g uint64) uint64 {fs, fm, fe, fi, fn := funpack64(f)gs, gm, ge, gi, gn := funpack64(g)// Special cases.switch {case fn || gn: // NaN / g = f / NaN = NaNreturn nan64case fi && gi: // ±Inf / ±Inf = NaNreturn nan64case !fi && !gi && fm == 0 && gm == 0: // 0 / 0 = NaNreturn nan64case fi, !gi && gm == 0: // Inf / g = f / 0 = Infreturn fs ^ gs ^ inf64case gi, fm == 0: // f / Inf = 0 / g = Infreturn fs ^ gs ^ 0}_, _, _, _ = fi, fn, gi, gn// 53-bit<<54 / 53-bit = 53- or 54-bit.shift := mantbits64 + 2q, r := divlu(fm>>(64-shift), fm<<shift, gm)return fpack64(fs^gs, q, fe-ge-2, r)}func f64to32(f uint64) uint32 {fs, fm, fe, fi, fn := funpack64(f)if fn {return nan32}fs32 := uint32(fs >> 32)if fi {return fs32 ^ inf32}const d = mantbits64 - mantbits32 - 1return fpack32(fs32, uint32(fm>>d), fe-1, uint32(fm&(1<<d-1)))}func f32to64(f uint32) uint64 {const d = mantbits64 - mantbits32fs, fm, fe, fi, fn := funpack32(f)if fn {return nan64}fs64 := uint64(fs) << 32if fi {return fs64 ^ inf64}return fpack64(fs64, uint64(fm)<<d, fe, 0)}func fcmp64(f, g uint64) (cmp int, isnan bool) {fs, fm, _, fi, fn := funpack64(f)gs, gm, _, gi, gn := funpack64(g)switch {case fn, gn: // flag NaNreturn 0, truecase !fi && !gi && fm == 0 && gm == 0: // ±0 == ±0return 0, falsecase fs > gs: // f < 0, g > 0return -1, falsecase fs < gs: // f > 0, g < 0return +1, false// Same sign, not NaN.// Can compare encodings directly now.// Reverse for sign.case fs == 0 && f < g, fs != 0 && f > g:return -1, falsecase fs == 0 && f > g, fs != 0 && f < g:return +1, false}// f == greturn 0, false}func f64toint(f uint64) (val int64, ok bool) {fs, fm, fe, fi, fn := funpack64(f)switch {case fi, fn: // NaNreturn 0, falsecase fe < -1: // f < 0.5return 0, falsecase fe > 63: // f >= 2^63if fs != 0 && fm == 0 { // f == -2^63return -1 << 63, true}if fs != 0 {return 0, false}return 0, false}for fe > int(mantbits64) {fe--fm <<= 1}for fe < int(mantbits64) {fe++fm >>= 1}val = int64(fm)if fs != 0 {val = -val}return val, true}func fintto64(val int64) (f uint64) {fs := uint64(val) & (1 << 63)mant := uint64(val)if fs != 0 {mant = -mant}return fpack64(fs, mant, int(mantbits64), 0)}// 64x64 -> 128 multiply.// adapted from hacker's delight.func mullu(u, v uint64) (lo, hi uint64) {const (s = 32mask = 1<<s - 1)u0 := u & masku1 := u >> sv0 := v & maskv1 := v >> sw0 := u0 * v0t := u1*v0 + w0>>sw1 := t & maskw2 := t >> sw1 += u0 * v1return u * v, u1*v1 + w2 + w1>>s}// 128/64 -> 64 quotient, 64 remainder.// adapted from hacker's delightfunc divlu(u1, u0, v uint64) (q, r uint64) {const b = 1 << 32if u1 >= v {return 1<<64 - 1, 1<<64 - 1}// s = nlz(v); v <<= ss := uint(0)for v&(1<<63) == 0 {s++v <<= 1}vn1 := v >> 32vn0 := v & (1<<32 - 1)un32 := u1<<s | u0>>(64-s)un10 := u0 << sun1 := un10 >> 32un0 := un10 & (1<<32 - 1)q1 := un32 / vn1rhat := un32 - q1*vn1again1:if q1 >= b || q1*vn0 > b*rhat+un1 {q1--rhat += vn1if rhat < b {goto again1}}un21 := un32*b + un1 - q1*vq0 := un21 / vn1rhat = un21 - q0*vn1again2:if q0 >= b || q0*vn0 > b*rhat+un0 {q0--rhat += vn1if rhat < b {goto again2}}return q1*b + q0, (un21*b + un0 - q0*v) >> s}// callable from Cfunc fadd64c(f, g uint64, ret *uint64) { *ret = fadd64(f, g) }func fsub64c(f, g uint64, ret *uint64) { *ret = fsub64(f, g) }func fmul64c(f, g uint64, ret *uint64) { *ret = fmul64(f, g) }func fdiv64c(f, g uint64, ret *uint64) { *ret = fdiv64(f, g) }func fneg64c(f uint64, ret *uint64) { *ret = fneg64(f) }func f32to64c(f uint32, ret *uint64) { *ret = f32to64(f) }func f64to32c(f uint64, ret *uint32) { *ret = f64to32(f) }func fcmp64c(f, g uint64, ret *int, retnan *bool) { *ret, *retnan = fcmp64(f, g) }func fintto64c(val int64, ret *uint64) { *ret = fintto64(val) }func f64tointc(f uint64, ret *int64, retok *bool) { *ret, *retok = f64toint(f) }
