162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Floating-point emulation code 662306a36Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * BEGIN_DESC 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * File: 1262306a36Sopenharmony_ci * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $ 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Purpose: 1562306a36Sopenharmony_ci * Single Fixed-point to Single Floating-point 1662306a36Sopenharmony_ci * Single Fixed-point to Double Floating-point 1762306a36Sopenharmony_ci * Double Fixed-point to Single Floating-point 1862306a36Sopenharmony_ci * Double Fixed-point to Double Floating-point 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * External Interfaces: 2162306a36Sopenharmony_ci * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) 2262306a36Sopenharmony_ci * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) 2362306a36Sopenharmony_ci * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) 2462306a36Sopenharmony_ci * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * Internal Interfaces: 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Theory: 2962306a36Sopenharmony_ci * <<please update with a overview of the operation of this file>> 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * END_DESC 3262306a36Sopenharmony_ci*/ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include "float.h" 3662306a36Sopenharmony_ci#include "sgl_float.h" 3762306a36Sopenharmony_ci#include "dbl_float.h" 3862306a36Sopenharmony_ci#include "cnv_float.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * Convert single fixed-point to single floating-point format 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciint 4562306a36Sopenharmony_cisgl_to_sgl_fcnvxf( 4662306a36Sopenharmony_ci int *srcptr, 4762306a36Sopenharmony_ci unsigned int *nullptr, 4862306a36Sopenharmony_ci sgl_floating_point *dstptr, 4962306a36Sopenharmony_ci unsigned int *status) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci register int src, dst_exponent; 5262306a36Sopenharmony_ci register unsigned int result = 0; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci src = *srcptr; 5562306a36Sopenharmony_ci /* 5662306a36Sopenharmony_ci * set sign bit of result and get magnitude of source 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci if (src < 0) { 5962306a36Sopenharmony_ci Sgl_setone_sign(result); 6062306a36Sopenharmony_ci Int_negate(src); 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci else { 6362306a36Sopenharmony_ci Sgl_setzero_sign(result); 6462306a36Sopenharmony_ci /* Check for zero */ 6562306a36Sopenharmony_ci if (src == 0) { 6662306a36Sopenharmony_ci Sgl_setzero(result); 6762306a36Sopenharmony_ci *dstptr = result; 6862306a36Sopenharmony_ci return(NOEXCEPTION); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci /* 7262306a36Sopenharmony_ci * Generate exponent and normalized mantissa 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 7562306a36Sopenharmony_ci /* 7662306a36Sopenharmony_ci * Check word for most significant bit set. Returns 7762306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 7862306a36Sopenharmony_ci * between -1 and 30. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_ci Find_ms_one_bit(src,dst_exponent); 8162306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 8262306a36Sopenharmony_ci if (dst_exponent >= 0) src <<= dst_exponent; 8362306a36Sopenharmony_ci else src = 1 << 30; 8462306a36Sopenharmony_ci Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); 8562306a36Sopenharmony_ci Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* check for inexact */ 8862306a36Sopenharmony_ci if (Int_isinexact_to_sgl(src)) { 8962306a36Sopenharmony_ci switch (Rounding_mode()) { 9062306a36Sopenharmony_ci case ROUNDPLUS: 9162306a36Sopenharmony_ci if (Sgl_iszero_sign(result)) 9262306a36Sopenharmony_ci Sgl_increment(result); 9362306a36Sopenharmony_ci break; 9462306a36Sopenharmony_ci case ROUNDMINUS: 9562306a36Sopenharmony_ci if (Sgl_isone_sign(result)) 9662306a36Sopenharmony_ci Sgl_increment(result); 9762306a36Sopenharmony_ci break; 9862306a36Sopenharmony_ci case ROUNDNEAREST: 9962306a36Sopenharmony_ci Sgl_roundnearest_from_int(src,result); 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci if (Is_inexacttrap_enabled()) { 10262306a36Sopenharmony_ci *dstptr = result; 10362306a36Sopenharmony_ci return(INEXACTEXCEPTION); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci else Set_inexactflag(); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci *dstptr = result; 10862306a36Sopenharmony_ci return(NOEXCEPTION); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* 11262306a36Sopenharmony_ci * Single Fixed-point to Double Floating-point 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint 11662306a36Sopenharmony_cisgl_to_dbl_fcnvxf( 11762306a36Sopenharmony_ci int *srcptr, 11862306a36Sopenharmony_ci unsigned int *nullptr, 11962306a36Sopenharmony_ci dbl_floating_point *dstptr, 12062306a36Sopenharmony_ci unsigned int *status) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci register int src, dst_exponent; 12362306a36Sopenharmony_ci register unsigned int resultp1 = 0, resultp2 = 0; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci src = *srcptr; 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * set sign bit of result and get magnitude of source 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci if (src < 0) { 13062306a36Sopenharmony_ci Dbl_setone_sign(resultp1); 13162306a36Sopenharmony_ci Int_negate(src); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci else { 13462306a36Sopenharmony_ci Dbl_setzero_sign(resultp1); 13562306a36Sopenharmony_ci /* Check for zero */ 13662306a36Sopenharmony_ci if (src == 0) { 13762306a36Sopenharmony_ci Dbl_setzero(resultp1,resultp2); 13862306a36Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 13962306a36Sopenharmony_ci return(NOEXCEPTION); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci /* 14362306a36Sopenharmony_ci * Generate exponent and normalized mantissa 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * Check word for most significant bit set. Returns 14862306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 14962306a36Sopenharmony_ci * between -1 and 30. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci Find_ms_one_bit(src,dst_exponent); 15262306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 15362306a36Sopenharmony_ci if (dst_exponent >= 0) src <<= dst_exponent; 15462306a36Sopenharmony_ci else src = 1 << 30; 15562306a36Sopenharmony_ci Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1); 15662306a36Sopenharmony_ci Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH)); 15762306a36Sopenharmony_ci Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 15862306a36Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 15962306a36Sopenharmony_ci return(NOEXCEPTION); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* 16362306a36Sopenharmony_ci * Double Fixed-point to Single Floating-point 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciint 16762306a36Sopenharmony_cidbl_to_sgl_fcnvxf( 16862306a36Sopenharmony_ci dbl_integer *srcptr, 16962306a36Sopenharmony_ci unsigned int *nullptr, 17062306a36Sopenharmony_ci sgl_floating_point *dstptr, 17162306a36Sopenharmony_ci unsigned int *status) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci int dst_exponent, srcp1; 17462306a36Sopenharmony_ci unsigned int result = 0, srcp2; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci Dint_copyfromptr(srcptr,srcp1,srcp2); 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * set sign bit of result and get magnitude of source 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci if (srcp1 < 0) { 18162306a36Sopenharmony_ci Sgl_setone_sign(result); 18262306a36Sopenharmony_ci Dint_negate(srcp1,srcp2); 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci else { 18562306a36Sopenharmony_ci Sgl_setzero_sign(result); 18662306a36Sopenharmony_ci /* Check for zero */ 18762306a36Sopenharmony_ci if (srcp1 == 0 && srcp2 == 0) { 18862306a36Sopenharmony_ci Sgl_setzero(result); 18962306a36Sopenharmony_ci *dstptr = result; 19062306a36Sopenharmony_ci return(NOEXCEPTION); 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci /* 19462306a36Sopenharmony_ci * Generate exponent and normalized mantissa 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 19762306a36Sopenharmony_ci if (srcp1 == 0) { 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * Check word for most significant bit set. Returns 20062306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 20162306a36Sopenharmony_ci * between -1 and 30. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci Find_ms_one_bit(srcp2,dst_exponent); 20462306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 20562306a36Sopenharmony_ci if (dst_exponent >= 0) { 20662306a36Sopenharmony_ci srcp1 = srcp2 << dst_exponent; 20762306a36Sopenharmony_ci srcp2 = 0; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci else { 21062306a36Sopenharmony_ci srcp1 = srcp2 >> 1; 21162306a36Sopenharmony_ci srcp2 <<= 31; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci /* 21462306a36Sopenharmony_ci * since msb set is in second word, need to 21562306a36Sopenharmony_ci * adjust bit position count 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ci dst_exponent += 32; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci else { 22062306a36Sopenharmony_ci /* 22162306a36Sopenharmony_ci * Check word for most significant bit set. Returns 22262306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 22362306a36Sopenharmony_ci * between -1 and 30. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci Find_ms_one_bit(srcp1,dst_exponent); 22762306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 22862306a36Sopenharmony_ci if (dst_exponent > 0) { 22962306a36Sopenharmony_ci Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 23062306a36Sopenharmony_ci srcp1); 23162306a36Sopenharmony_ci srcp2 <<= dst_exponent; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * If dst_exponent = 0, we don't need to shift anything. 23562306a36Sopenharmony_ci * If dst_exponent = -1, src = - 2**63 so we won't need to 23662306a36Sopenharmony_ci * shift srcp2. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci else srcp1 >>= -(dst_exponent); 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1); 24162306a36Sopenharmony_ci Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* check for inexact */ 24462306a36Sopenharmony_ci if (Dint_isinexact_to_sgl(srcp1,srcp2)) { 24562306a36Sopenharmony_ci switch (Rounding_mode()) { 24662306a36Sopenharmony_ci case ROUNDPLUS: 24762306a36Sopenharmony_ci if (Sgl_iszero_sign(result)) 24862306a36Sopenharmony_ci Sgl_increment(result); 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci case ROUNDMINUS: 25162306a36Sopenharmony_ci if (Sgl_isone_sign(result)) 25262306a36Sopenharmony_ci Sgl_increment(result); 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case ROUNDNEAREST: 25562306a36Sopenharmony_ci Sgl_roundnearest_from_dint(srcp1,srcp2,result); 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci if (Is_inexacttrap_enabled()) { 25862306a36Sopenharmony_ci *dstptr = result; 25962306a36Sopenharmony_ci return(INEXACTEXCEPTION); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci else Set_inexactflag(); 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci *dstptr = result; 26462306a36Sopenharmony_ci return(NOEXCEPTION); 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* 26862306a36Sopenharmony_ci * Double Fixed-point to Double Floating-point 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciint 27262306a36Sopenharmony_cidbl_to_dbl_fcnvxf( 27362306a36Sopenharmony_ci dbl_integer *srcptr, 27462306a36Sopenharmony_ci unsigned int *nullptr, 27562306a36Sopenharmony_ci dbl_floating_point *dstptr, 27662306a36Sopenharmony_ci unsigned int *status) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci register int srcp1, dst_exponent; 27962306a36Sopenharmony_ci register unsigned int srcp2, resultp1 = 0, resultp2 = 0; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci Dint_copyfromptr(srcptr,srcp1,srcp2); 28262306a36Sopenharmony_ci /* 28362306a36Sopenharmony_ci * set sign bit of result and get magnitude of source 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci if (srcp1 < 0) { 28662306a36Sopenharmony_ci Dbl_setone_sign(resultp1); 28762306a36Sopenharmony_ci Dint_negate(srcp1,srcp2); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci else { 29062306a36Sopenharmony_ci Dbl_setzero_sign(resultp1); 29162306a36Sopenharmony_ci /* Check for zero */ 29262306a36Sopenharmony_ci if (srcp1 == 0 && srcp2 ==0) { 29362306a36Sopenharmony_ci Dbl_setzero(resultp1,resultp2); 29462306a36Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 29562306a36Sopenharmony_ci return(NOEXCEPTION); 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci /* 29962306a36Sopenharmony_ci * Generate exponent and normalized mantissa 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 30262306a36Sopenharmony_ci if (srcp1 == 0) { 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * Check word for most significant bit set. Returns 30562306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 30662306a36Sopenharmony_ci * between -1 and 30. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci Find_ms_one_bit(srcp2,dst_exponent); 30962306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 31062306a36Sopenharmony_ci if (dst_exponent >= 0) { 31162306a36Sopenharmony_ci srcp1 = srcp2 << dst_exponent; 31262306a36Sopenharmony_ci srcp2 = 0; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci else { 31562306a36Sopenharmony_ci srcp1 = srcp2 >> 1; 31662306a36Sopenharmony_ci srcp2 <<= 31; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci /* 31962306a36Sopenharmony_ci * since msb set is in second word, need to 32062306a36Sopenharmony_ci * adjust bit position count 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ci dst_exponent += 32; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci else { 32562306a36Sopenharmony_ci /* 32662306a36Sopenharmony_ci * Check word for most significant bit set. Returns 32762306a36Sopenharmony_ci * a value in dst_exponent indicating the bit position, 32862306a36Sopenharmony_ci * between -1 and 30. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci Find_ms_one_bit(srcp1,dst_exponent); 33162306a36Sopenharmony_ci /* left justify source, with msb at bit position 1 */ 33262306a36Sopenharmony_ci if (dst_exponent > 0) { 33362306a36Sopenharmony_ci Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 33462306a36Sopenharmony_ci srcp1); 33562306a36Sopenharmony_ci srcp2 <<= dst_exponent; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci /* 33862306a36Sopenharmony_ci * If dst_exponent = 0, we don't need to shift anything. 33962306a36Sopenharmony_ci * If dst_exponent = -1, src = - 2**63 so we won't need to 34062306a36Sopenharmony_ci * shift srcp2. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ci else srcp1 >>= -(dst_exponent); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); 34562306a36Sopenharmony_ci Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); 34662306a36Sopenharmony_ci Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* check for inexact */ 34962306a36Sopenharmony_ci if (Dint_isinexact_to_dbl(srcp2)) { 35062306a36Sopenharmony_ci switch (Rounding_mode()) { 35162306a36Sopenharmony_ci case ROUNDPLUS: 35262306a36Sopenharmony_ci if (Dbl_iszero_sign(resultp1)) { 35362306a36Sopenharmony_ci Dbl_increment(resultp1,resultp2); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci break; 35662306a36Sopenharmony_ci case ROUNDMINUS: 35762306a36Sopenharmony_ci if (Dbl_isone_sign(resultp1)) { 35862306a36Sopenharmony_ci Dbl_increment(resultp1,resultp2); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci case ROUNDNEAREST: 36262306a36Sopenharmony_ci Dbl_roundnearest_from_dint(srcp2,resultp1, 36362306a36Sopenharmony_ci resultp2); 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci if (Is_inexacttrap_enabled()) { 36662306a36Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 36762306a36Sopenharmony_ci return(INEXACTEXCEPTION); 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci else Set_inexactflag(); 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 37262306a36Sopenharmony_ci return(NOEXCEPTION); 37362306a36Sopenharmony_ci} 374