c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * CDDL HEADER START
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri *
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * The contents of this file are subject to the terms of the
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * Common Development and Distribution License, Version 1.0 only
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * (the "License"). You may not use this file except in compliance
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * with the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * or http://www.opensolaris.org/os/licensing.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * See the License for the specific language governing permissions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and limitations under the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * When distributing Covered Code, include this CDDL HEADER in each
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If applicable, add the following below this CDDL HEADER, with the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fields enclosed by brackets "[]" replaced with your own identifying
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * information: Portions Copyright [yyyy] [name of copyright owner]
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 1994-1997, by Sun Microsystems, Inc.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#pragma ident "%Z%%M% %I% %E% SMI"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include "quad.h"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifdef __sparcv9
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define _Q_qtos _Qp_qtos
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * _Q_qtos(x) returns (float)*x.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otafloat
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota_Q_qtos(const union longdouble *x)
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota{
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota union {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota float f;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota unsigned int l;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota } u;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota unsigned int xm, round, sticky, fsr, rm;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int subnormal, e;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota xm = x->l.msw & 0x7fffffff;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* get the rounding mode, fudging directed rounding modes */
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota /* as though the result were positive */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_getfsrp(&fsr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rm = fsr >> 30;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (x->l.msw & 0x80000000)
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota rm ^= (rm >> 1);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* handle nan, inf, and out-of-range cases */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (xm >= 0x407f0000) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (xm >= 0x7fff0000) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if ((xm & 0xffff) | x->l.frac2 | x->l.frac3 |
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota x->l.frac4) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* x is nan */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l = (x->l.msw & 0x80000000) | 0x7fc00000;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l |= ((xm & 0x7fff) << 7) |
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota (x->l.frac2 >> 25);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (!(xm & 0x8000)) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* snan, signal invalid */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (fsr & FSR_NVM) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_fqtos(x, &u.f);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota fsr = (fsr & ~FSR_CEXC) |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FSR_NVA | FSR_NVC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __quad_setfsrp(&fsr);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota return (u.f);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* x is inf */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota u.l = (x->l.msw & 0x80000000) | 0x7f800000;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* x is too big, overflow */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (rm == FSR_RN || rm == FSR_RP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota u.l = 0x7f800000;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota else
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l = 0x7f7fffff;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l |= (x->l.msw & 0x80000000);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (fsr & (FSR_OFM | FSR_NXM)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __quad_fqtos(x, &u.f);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota fsr = (fsr & ~FSR_CEXC) | FSR_OFA | FSR_OFC |
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota FSR_NXA | FSR_NXC;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_setfsrp(&fsr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota subnormal = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (xm < 0x3f810000) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (xm < 0x3f690000) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (QUAD_ISZERO(*x)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota u.l = (x->l.msw & 0x80000000);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* x is too small, underflow */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota u.l = ((rm == FSR_RP)? 1 : 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota u.l |= (x->l.msw & 0x80000000);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (fsr & (FSR_UFM | FSR_NXM)) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_fqtos(x, &u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota } else {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr = (fsr & ~FSR_CEXC) | FSR_UFA | FSR_UFC |
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota FSR_NXA | FSR_NXC;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_setfsrp(&fsr);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota return (u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* x is in the subnormal range for single */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota subnormal = 1;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l = 0x800000 | ((xm & 0xffff) << 7) | (x->l.frac2 >> 25);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota e = 0x3f80 - (xm >> 16);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota round = u.l & (1 << e);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota sticky = (u.l & ((1 << e) - 1)) | (x->l.frac2 & 0x1ffffff) |
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota x->l.frac3 | x->l.frac4;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l >>= e + 1;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota } else {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* x is in the normal range for single */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota u.l = ((xm - 0x3f800000) << 7) | (x->l.frac2 >> 25);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota round = x->l.frac2 & 0x1000000;
b27516f55237249607f754e6e42e865f12456675agiri sticky = (x->l.frac2 & 0xffffff) | x->l.frac3 | x->l.frac4;
b27516f55237249607f754e6e42e865f12456675agiri }
b27516f55237249607f754e6e42e865f12456675agiri
b27516f55237249607f754e6e42e865f12456675agiri /* see if we need to round */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr &= ~FSR_CEXC;
b27516f55237249607f754e6e42e865f12456675agiri if (round | sticky) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota fsr |= FSR_NXC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (subnormal)
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr |= FSR_UFC;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* round up if necessary */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rm == FSR_RP || (rm == FSR_RN && round && (sticky ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (u.l & 1)))) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* round up and check for overflow */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if (++u.l >= 0x7f800000)
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr |= FSR_OFC;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* if result is exact and subnormal but underflow trapping is */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota /* enabled, signal underflow */
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota else if (subnormal && (fsr & FSR_UFM))
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr |= FSR_UFC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota /* attach the sign and raise exceptions as need be */
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota u.l |= (x->l.msw & 0x80000000);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((fsr & FSR_CEXC) & (fsr >> 23)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __quad_setfsrp(&fsr);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_fqtos(x, &u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota } else {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota fsr |= (fsr & 0x1f) << 5;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota __quad_setfsrp(&fsr);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota }
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota return (u.f);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota