/* tifloat.c */
 
/*****************************************************************************/
 
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
 
/*                                                                           */
 
/* AS                                                                        */
 
/*                                                                           */
 
/* IEEE -> TI DSP Floating Point Conversion on host                          */
 
/*                                                                           */
 
/*****************************************************************************/
 
 
 
#include <errno.h>
 
 
 
#include "as_float.h"
 
#include "errmsg.h"
 
#include "tifloat.h"
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     split_exp(as_float_t inp, LongInt *p_exponent, LongWord *p_mantissa)
 
 * \brief  common number dissection
 
 * \param  inp float input (host format)
 
 * \param  p_exponent exponent (without bias)
 
 * \param  p_mantissa mantissa (two's complement)
 
 * \return 0 or error code
 
 * ------------------------------------------------------------------------ */
 
 
 
static int split_exp(as_float_t inp, LongInt *p_exponent, LongWord *p_mantissa)
 
{
 
  as_float_dissect_t dissect;
 
 
 
  as_float_dissect(&dissect, inp);
 
  if ((dissect.fp_class != AS_FP_NORMAL)
 
   && (dissect.fp_class != AS_FP_SUBNORMAL))
 
    return -EINVAL;
 
 
 
  *p_exponent = dissect.exponent;
 
  if (dissect.mantissa_bits < 32)
 
    as_float_append_mantissa_bits(&dissect, 0, 32 - dissect.mantissa_bits);
 
  *p_mantissa = as_float_mantissa_extract(&dissect, 0, 32);
 
  if (dissect.negative)
 
    *p_mantissa = (0xffffffff - *p_mantissa) + 1;
 
  *p_mantissa = (*p_mantissa) ^ 0x80000000;
 
 
 
  return 0;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     as_float_2_ti2(as_float_t inp, Word *p_dest)
 
 * \brief  convert host float to C3x/4x short (16 bits)
 
 * \param  inp float input (host format)
 
 * \param  result buffer
 
 * \return 0 or error code
 
 * ------------------------------------------------------------------------ */
 
 
 
int as_float_2_ti2(as_float_t inp, Word *p_dest)
 
{
 
  int ret;
 
  LongInt exponent;
 
  LongWord mantissa;
 
 
 
  if (inp == 0)
 
  {
 
    *p_dest = 0x8000;
 
    return 0;
 
  }
 
 
 
  if ((ret = split_exp(inp, &exponent, &mantissa)) < 0)
 
    return ret;
 
  if (!ChkRange(exponent, -7, 7))
 
    return -E2BIG;
 
  *p_dest = ((exponent << 12) & 0xf000) | ((mantissa >> 20) & 0xfff);
 
  return 0;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     as_float_2_ti4(as_float_t inp, LongWord *p_dest)
 
 * \brief  convert host float to C3x/4x single (32 bits)
 
 * \param  inp float input (host format)
 
 * \param  result buffer
 
 * \return 0 or error code
 
 * ------------------------------------------------------------------------ */
 
 
 
int as_float_2_ti4(as_float_t inp, LongWord *p_dest)
 
{
 
  int ret;
 
  LongInt exponent;
 
  LongWord mantissa;
 
 
 
  if (inp == 0)
 
  {
 
    *p_dest = 0x80000000;
 
    return 0;
 
  }
 
 
 
  if ((ret = split_exp(inp, &exponent, &mantissa)) < 0)
 
    return ret;
 
  if (!ChkRange(exponent, -127, 127))
 
    return -E2BIG;
 
  *p_dest = ((exponent << 24) & 0xff000000) + (mantissa >> 8);
 
  return 0;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     as_float_2_ti5(as_float_t inp, LongWord *p_dest_l, LongWord *p_dest_h)
 
 * \brief  convert host float to C3x/4x extended (40 bits)
 
 * \param  inp float input (host format)
 
 * \param  p_dest_l result buffer (mantissa)
 
 * \param  p_dest_h result buffer (exponent)
 
 * \return 0 or error code
 
 * ------------------------------------------------------------------------ */
 
 
 
int as_float_2_ti5(as_float_t inp, LongWord *p_dest_l, LongWord *p_dest_h)
 
{
 
  int ret;
 
  LongInt exponent;
 
 
 
  if (inp == 0)
 
  {
 
    *p_dest_h = 0x80;
 
    *p_dest_l = 0x00000000;
 
    return 0;
 
  }
 
 
 
  if ((ret = split_exp(inp, &exponent, p_dest_l)) < 0)
 
    return ret;
 
  if (!ChkRange(exponent, -127, 127))
 
    return -E2BIG;
 
  *p_dest_h = exponent & 0xff;
 
 return 0;
 
}