/*1* Linux/PA-RISC Project (http://www.parisc-linux.org/)2*3* Floating-point emulation code4* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]>5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; either version 2, or (at your option)9* any later version.10*11* This program is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19*/20/*21* BEGIN_DESC22*23* File:24* @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $25*26* Purpose:27* Single Fixed-point to Single Floating-point28* Single Fixed-point to Double Floating-point29* Double Fixed-point to Single Floating-point30* Double Fixed-point to Double Floating-point31*32* External Interfaces:33* dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)34* dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)35* sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)36* sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)37*38* Internal Interfaces:39*40* Theory:41* <<please update with a overview of the operation of this file>>42*43* END_DESC44*/454647#include "float.h"48#include "sgl_float.h"49#include "dbl_float.h"50#include "cnv_float.h"5152/*53* Convert single fixed-point to single floating-point format54*/5556int57sgl_to_sgl_fcnvxf(58int *srcptr,59unsigned int *nullptr,60sgl_floating_point *dstptr,61unsigned int *status)62{63register int src, dst_exponent;64register unsigned int result = 0;6566src = *srcptr;67/*68* set sign bit of result and get magnitude of source69*/70if (src < 0) {71Sgl_setone_sign(result);72Int_negate(src);73}74else {75Sgl_setzero_sign(result);76/* Check for zero */77if (src == 0) {78Sgl_setzero(result);79*dstptr = result;80return(NOEXCEPTION);81}82}83/*84* Generate exponent and normalized mantissa85*/86dst_exponent = 16; /* initialize for normalization */87/*88* Check word for most significant bit set. Returns89* a value in dst_exponent indicating the bit position,90* between -1 and 30.91*/92Find_ms_one_bit(src,dst_exponent);93/* left justify source, with msb at bit position 1 */94if (dst_exponent >= 0) src <<= dst_exponent;95else src = 1 << 30;96Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));97Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);9899/* check for inexact */100if (Int_isinexact_to_sgl(src)) {101switch (Rounding_mode()) {102case ROUNDPLUS:103if (Sgl_iszero_sign(result))104Sgl_increment(result);105break;106case ROUNDMINUS:107if (Sgl_isone_sign(result))108Sgl_increment(result);109break;110case ROUNDNEAREST:111Sgl_roundnearest_from_int(src,result);112}113if (Is_inexacttrap_enabled()) {114*dstptr = result;115return(INEXACTEXCEPTION);116}117else Set_inexactflag();118}119*dstptr = result;120return(NOEXCEPTION);121}122123/*124* Single Fixed-point to Double Floating-point125*/126127int128sgl_to_dbl_fcnvxf(129int *srcptr,130unsigned int *nullptr,131dbl_floating_point *dstptr,132unsigned int *status)133{134register int src, dst_exponent;135register unsigned int resultp1 = 0, resultp2 = 0;136137src = *srcptr;138/*139* set sign bit of result and get magnitude of source140*/141if (src < 0) {142Dbl_setone_sign(resultp1);143Int_negate(src);144}145else {146Dbl_setzero_sign(resultp1);147/* Check for zero */148if (src == 0) {149Dbl_setzero(resultp1,resultp2);150Dbl_copytoptr(resultp1,resultp2,dstptr);151return(NOEXCEPTION);152}153}154/*155* Generate exponent and normalized mantissa156*/157dst_exponent = 16; /* initialize for normalization */158/*159* Check word for most significant bit set. Returns160* a value in dst_exponent indicating the bit position,161* between -1 and 30.162*/163Find_ms_one_bit(src,dst_exponent);164/* left justify source, with msb at bit position 1 */165if (dst_exponent >= 0) src <<= dst_exponent;166else src = 1 << 30;167Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);168Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));169Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);170Dbl_copytoptr(resultp1,resultp2,dstptr);171return(NOEXCEPTION);172}173174/*175* Double Fixed-point to Single Floating-point176*/177178int179dbl_to_sgl_fcnvxf(180dbl_integer *srcptr,181unsigned int *nullptr,182sgl_floating_point *dstptr,183unsigned int *status)184{185int dst_exponent, srcp1;186unsigned int result = 0, srcp2;187188Dint_copyfromptr(srcptr,srcp1,srcp2);189/*190* set sign bit of result and get magnitude of source191*/192if (srcp1 < 0) {193Sgl_setone_sign(result);194Dint_negate(srcp1,srcp2);195}196else {197Sgl_setzero_sign(result);198/* Check for zero */199if (srcp1 == 0 && srcp2 == 0) {200Sgl_setzero(result);201*dstptr = result;202return(NOEXCEPTION);203}204}205/*206* Generate exponent and normalized mantissa207*/208dst_exponent = 16; /* initialize for normalization */209if (srcp1 == 0) {210/*211* Check word for most significant bit set. Returns212* a value in dst_exponent indicating the bit position,213* between -1 and 30.214*/215Find_ms_one_bit(srcp2,dst_exponent);216/* left justify source, with msb at bit position 1 */217if (dst_exponent >= 0) {218srcp1 = srcp2 << dst_exponent;219srcp2 = 0;220}221else {222srcp1 = srcp2 >> 1;223srcp2 <<= 31;224}225/*226* since msb set is in second word, need to227* adjust bit position count228*/229dst_exponent += 32;230}231else {232/*233* Check word for most significant bit set. Returns234* a value in dst_exponent indicating the bit position,235* between -1 and 30.236*237*/238Find_ms_one_bit(srcp1,dst_exponent);239/* left justify source, with msb at bit position 1 */240if (dst_exponent > 0) {241Variable_shift_double(srcp1,srcp2,(32-dst_exponent),242srcp1);243srcp2 <<= dst_exponent;244}245/*246* If dst_exponent = 0, we don't need to shift anything.247* If dst_exponent = -1, src = - 2**63 so we won't need to248* shift srcp2.249*/250else srcp1 >>= -(dst_exponent);251}252Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);253Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);254255/* check for inexact */256if (Dint_isinexact_to_sgl(srcp1,srcp2)) {257switch (Rounding_mode()) {258case ROUNDPLUS:259if (Sgl_iszero_sign(result))260Sgl_increment(result);261break;262case ROUNDMINUS:263if (Sgl_isone_sign(result))264Sgl_increment(result);265break;266case ROUNDNEAREST:267Sgl_roundnearest_from_dint(srcp1,srcp2,result);268}269if (Is_inexacttrap_enabled()) {270*dstptr = result;271return(INEXACTEXCEPTION);272}273else Set_inexactflag();274}275*dstptr = result;276return(NOEXCEPTION);277}278279/*280* Double Fixed-point to Double Floating-point281*/282283int284dbl_to_dbl_fcnvxf(285dbl_integer *srcptr,286unsigned int *nullptr,287dbl_floating_point *dstptr,288unsigned int *status)289{290register int srcp1, dst_exponent;291register unsigned int srcp2, resultp1 = 0, resultp2 = 0;292293Dint_copyfromptr(srcptr,srcp1,srcp2);294/*295* set sign bit of result and get magnitude of source296*/297if (srcp1 < 0) {298Dbl_setone_sign(resultp1);299Dint_negate(srcp1,srcp2);300}301else {302Dbl_setzero_sign(resultp1);303/* Check for zero */304if (srcp1 == 0 && srcp2 ==0) {305Dbl_setzero(resultp1,resultp2);306Dbl_copytoptr(resultp1,resultp2,dstptr);307return(NOEXCEPTION);308}309}310/*311* Generate exponent and normalized mantissa312*/313dst_exponent = 16; /* initialize for normalization */314if (srcp1 == 0) {315/*316* Check word for most significant bit set. Returns317* a value in dst_exponent indicating the bit position,318* between -1 and 30.319*/320Find_ms_one_bit(srcp2,dst_exponent);321/* left justify source, with msb at bit position 1 */322if (dst_exponent >= 0) {323srcp1 = srcp2 << dst_exponent;324srcp2 = 0;325}326else {327srcp1 = srcp2 >> 1;328srcp2 <<= 31;329}330/*331* since msb set is in second word, need to332* adjust bit position count333*/334dst_exponent += 32;335}336else {337/*338* Check word for most significant bit set. Returns339* a value in dst_exponent indicating the bit position,340* between -1 and 30.341*/342Find_ms_one_bit(srcp1,dst_exponent);343/* left justify source, with msb at bit position 1 */344if (dst_exponent > 0) {345Variable_shift_double(srcp1,srcp2,(32-dst_exponent),346srcp1);347srcp2 <<= dst_exponent;348}349/*350* If dst_exponent = 0, we don't need to shift anything.351* If dst_exponent = -1, src = - 2**63 so we won't need to352* shift srcp2.353*/354else srcp1 >>= -(dst_exponent);355}356Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));357Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);358Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);359360/* check for inexact */361if (Dint_isinexact_to_dbl(srcp2)) {362switch (Rounding_mode()) {363case ROUNDPLUS:364if (Dbl_iszero_sign(resultp1)) {365Dbl_increment(resultp1,resultp2);366}367break;368case ROUNDMINUS:369if (Dbl_isone_sign(resultp1)) {370Dbl_increment(resultp1,resultp2);371}372break;373case ROUNDNEAREST:374Dbl_roundnearest_from_dint(srcp2,resultp1,375resultp2);376}377if (Is_inexacttrap_enabled()) {378Dbl_copytoptr(resultp1,resultp2,dstptr);379return(INEXACTEXCEPTION);380}381else Set_inexactflag();382}383Dbl_copytoptr(resultp1,resultp2,dstptr);384return(NOEXCEPTION);385}386387388