This commit is contained in:
commit
b6b7d72717
96 changed files with 37739 additions and 0 deletions
171
softfp_template_icvt.h
Normal file
171
softfp_template_icvt.h
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* SoftFP Library
|
||||
*
|
||||
* Copyright (c) 2016 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#if ICVT_SIZE == 32
|
||||
#define ICVT_UINT uint32_t
|
||||
#define ICVT_INT int32_t
|
||||
#elif ICVT_SIZE == 64
|
||||
#define ICVT_UINT uint64_t
|
||||
#define ICVT_INT int64_t
|
||||
#elif ICVT_SIZE == 128
|
||||
#define ICVT_UINT uint128_t
|
||||
#define ICVT_INT int128_t
|
||||
#else
|
||||
#error unsupported icvt
|
||||
#endif
|
||||
|
||||
/* conversions between float and integers */
|
||||
static ICVT_INT glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,
|
||||
uint32_t *pfflags, BOOL is_unsigned)
|
||||
{
|
||||
uint32_t a_sign, addend, rnd_bits;
|
||||
int32_t a_exp;
|
||||
F_UINT a_mant;
|
||||
ICVT_UINT r, r_max;
|
||||
|
||||
a_sign = a >> (F_SIZE - 1);
|
||||
a_exp = (a >> MANT_SIZE) & EXP_MASK;
|
||||
a_mant = a & MANT_MASK;
|
||||
if (a_exp == EXP_MASK && a_mant != 0)
|
||||
a_sign = 0; /* NaN is like +infinity */
|
||||
if (a_exp == 0) {
|
||||
a_exp = 1;
|
||||
} else {
|
||||
a_mant |= (F_UINT)1 << MANT_SIZE;
|
||||
}
|
||||
a_mant <<= RND_SIZE;
|
||||
a_exp = a_exp - (EXP_MASK / 2) - MANT_SIZE;
|
||||
|
||||
if (is_unsigned)
|
||||
r_max = (ICVT_UINT)a_sign - 1;
|
||||
else
|
||||
r_max = ((ICVT_UINT)1 << (ICVT_SIZE - 1)) - (ICVT_UINT)(a_sign ^ 1);
|
||||
if (a_exp >= 0) {
|
||||
if (a_exp <= (ICVT_SIZE - 1 - MANT_SIZE)) {
|
||||
r = (ICVT_UINT)(a_mant >> RND_SIZE) << a_exp;
|
||||
if (r > r_max)
|
||||
goto overflow;
|
||||
} else {
|
||||
overflow:
|
||||
*pfflags |= FFLAG_INVALID_OP;
|
||||
return r_max;
|
||||
}
|
||||
} else {
|
||||
a_mant = rshift_rnd(a_mant, -a_exp);
|
||||
|
||||
switch(rm) {
|
||||
case RM_RNE:
|
||||
case RM_RMM:
|
||||
addend = (1 << (RND_SIZE - 1));
|
||||
break;
|
||||
case RM_RTZ:
|
||||
addend = 0;
|
||||
break;
|
||||
default:
|
||||
case RM_RDN:
|
||||
case RM_RUP:
|
||||
if (a_sign ^ (rm & 1))
|
||||
addend = (1 << RND_SIZE) - 1;
|
||||
else
|
||||
addend = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rnd_bits = a_mant & ((1 << RND_SIZE ) - 1);
|
||||
a_mant = (a_mant + addend) >> RND_SIZE;
|
||||
/* half way: select even result */
|
||||
if (rm == RM_RNE && rnd_bits == (1 << (RND_SIZE - 1)))
|
||||
a_mant &= ~1;
|
||||
if (a_mant > r_max)
|
||||
goto overflow;
|
||||
r = a_mant;
|
||||
if (rnd_bits != 0)
|
||||
*pfflags |= FFLAG_INEXACT;
|
||||
}
|
||||
if (a_sign)
|
||||
r = -r;
|
||||
return r;
|
||||
}
|
||||
|
||||
ICVT_INT glue(glue(glue(cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,
|
||||
uint32_t *pfflags)
|
||||
{
|
||||
return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(a, rm,
|
||||
pfflags, FALSE);
|
||||
}
|
||||
|
||||
ICVT_UINT glue(glue(glue(cvt_sf, F_SIZE), _u), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,
|
||||
uint32_t *pfflags)
|
||||
{
|
||||
return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE) (a, rm,
|
||||
pfflags, TRUE);
|
||||
}
|
||||
|
||||
/* conversions between float and integers */
|
||||
static F_UINT glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a,
|
||||
RoundingModeEnum rm,
|
||||
uint32_t *pfflags,
|
||||
BOOL is_unsigned)
|
||||
{
|
||||
uint32_t a_sign;
|
||||
int32_t a_exp;
|
||||
F_UINT a_mant;
|
||||
ICVT_UINT r, mask;
|
||||
int l;
|
||||
|
||||
if (!is_unsigned && a < 0) {
|
||||
a_sign = 1;
|
||||
r = -(ICVT_UINT)a;
|
||||
} else {
|
||||
a_sign = 0;
|
||||
r = a;
|
||||
}
|
||||
a_exp = (EXP_MASK / 2) + F_SIZE - 2;
|
||||
/* need to reduce range before generic float normalization */
|
||||
l = ICVT_SIZE - glue(clz, ICVT_SIZE)(r) - (F_SIZE - 1);
|
||||
if (l > 0) {
|
||||
mask = r & (((ICVT_UINT)1 << l) - 1);
|
||||
r = (r >> l) | ((r & mask) != 0);
|
||||
a_exp += l;
|
||||
}
|
||||
a_mant = r;
|
||||
return normalize_sf(a_sign, a_exp, a_mant, rm, pfflags);
|
||||
}
|
||||
|
||||
F_UINT glue(glue(glue(cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a,
|
||||
RoundingModeEnum rm,
|
||||
uint32_t *pfflags)
|
||||
{
|
||||
return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, FALSE);
|
||||
}
|
||||
|
||||
F_UINT glue(glue(glue(cvt_u, ICVT_SIZE), _sf), F_SIZE)(ICVT_UINT a,
|
||||
RoundingModeEnum rm,
|
||||
uint32_t *pfflags)
|
||||
{
|
||||
return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, TRUE);
|
||||
}
|
||||
|
||||
#undef ICVT_SIZE
|
||||
#undef ICVT_INT
|
||||
#undef ICVT_UINT
|
||||
Loading…
Add table
Add a link
Reference in a new issue