summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndy Ross <andrew.j.ross@intel.com>2016-08-15 12:50:45 -0700
committerAnas Nashif <nashif@linux.intel.com>2016-09-10 00:49:01 +0000
commit5729235b57ba8f2cef6f4ae815c00455285ed3fb (patch)
tree63f752df7c844a458d01f7d23a1644ca6b544235 /lib
parentd06eea4eda04f0eb6761a8216a57902d8278a1fb (diff)
libc/printf: Use compiler-provided 64 bit math, phase 2
Remove the function wrappers around the 64 bit math and just use C syntax natively, combining ops where appropriate (e.g. there was a sequence implementing "(x<<2+x)<<2" to do "multiply by 10"). The _ldiv5 and _rlrshift routines are non-standard ops that provide useful abstraction, so they remain as separate functions. Change-Id: I4d83847348fdd7be09887b833c8ccbd2aa1e4182 Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/minimal/source/stdout/prf.c130
1 files changed, 48 insertions, 82 deletions
diff --git a/lib/libc/minimal/source/stdout/prf.c b/lib/libc/minimal/source/stdout/prf.c
index 0d21dd0d3..db351a410 100644
--- a/lib/libc/minimal/source/stdout/prf.c
+++ b/lib/libc/minimal/source/stdout/prf.c
@@ -137,21 +137,8 @@ static int _to_dec(char *buf, int32_t value, int fplus, int fspace, int precisio
return (buf + _to_udec(buf, (uint32_t) value, precision)) - start;
}
-static void _llshift(uint32_t value[])
+static void _rlrshift(uint64_t *v)
{
- *((uint64_t *)&value[0]) <<= 1;
-}
-
-static void __attribute__((noinline)) _ladd(uint32_t *result, uint32_t *value)
-{
- uint64_t *r = (uint64_t *)&result[0];
- uint64_t *v = (uint64_t *)&value[0];
- *r = *r + *v;
-}
-
-static void _rlrshift(uint32_t value[])
-{
- uint64_t *v = (uint64_t *)&value[0];
*v = (*v & 1) + (*v >> 1);
}
@@ -170,9 +157,8 @@ static void _rlrshift(uint32_t value[])
* the input space, and for ~2e12 (4 hours runtime) random inputs
* taken from the full 64 bit space.
*/
-static void _ldiv5(uint32_t value[])
+static void _ldiv5(uint64_t *v)
{
- uint64_t *v = (uint64_t *)&value[0];
uint32_t i, hi;
uint64_t rem = *v, quot = 0, q;
static const char shifts[] = { 32, 3, 0 };
@@ -192,10 +178,9 @@ static void _ldiv5(uint32_t value[])
*v = quot;
}
-static char _get_digit(uint32_t fract[], int *digit_count)
+static char _get_digit(uint64_t *fr, int *digit_count)
{
int rval;
- uint64_t *fr = (uint64_t *)&fract[0];
if (*digit_count > 0) {
*digit_count -= 1;
@@ -230,37 +215,31 @@ static char _get_digit(uint32_t fract[], int *digit_count)
*/
#define MAXFP1 0xFFFFFFFF /* Largest # if first fp format */
-#define MAXFP2 0x0FFFFFFF /* Largest # in second fp format */
+#define HIGHBIT64 (1ull<<63)
-static int _to_float(char *buf, uint32_t double_temp[], int c,
+static int _to_float(char *buf, uint64_t double_temp, int c,
int falt, int fplus, int fspace, int precision)
{
register int decexp;
register int exp;
+ int sign;
int digit_count;
- uint32_t fract[2];
- uint32_t ltemp[2];
+ uint64_t fract;
+ uint64_t ltemp;
int prune_zero;
char *start = buf;
- exp = (double_temp[1] >> 20) & 0x7FF;
- fract[1] = (double_temp[1] << 11) & 0x7FFFF800;
- fract[1] |= ((double_temp[0] >> 21) & 0x000007FF);
- fract[0] = double_temp[0] << 11;
-
- if (exp == 0x7FF) {
- if ((fract[1] | fract[0]) == 0) {
- if ((double_temp[1] & 0x80000000)) {
- *buf++ = '-';
- *buf++ = 'I';
- *buf++ = 'N';
- *buf++ = 'F';
- } else {
- *buf++ = '+';
- *buf++ = 'I';
- *buf++ = 'N';
- *buf++ = 'F';
- }
+ exp = double_temp >> 52 & 0x7ff;
+ fract = (double_temp << 11) & ~HIGHBIT64;
+ sign = !!(double_temp & HIGHBIT64);
+
+
+ if (exp == 0x7ff) {
+ if (!fract) {
+ *buf++ = sign ? '-' : '+';
+ *buf++ = 'I';
+ *buf++ = 'N';
+ *buf++ = 'F';
} else {
*buf++ = 'N';
*buf++ = 'a';
@@ -270,52 +249,49 @@ static int _to_float(char *buf, uint32_t double_temp[], int c,
return buf - start;
}
- if ((exp | fract[1] | fract[0]) != 0) {
+ if ((exp | fract) != 0) {
exp -= (1023 - 1); /* +1 since .1 vs 1. */
- fract[1] |= 0x80000000;
+ fract |= HIGHBIT64;
decexp = true; /* Wasn't zero */
} else
decexp = false; /* It was zero */
- if (decexp && (double_temp[1] & 0x80000000)) {
+ if (decexp && sign) {
*buf++ = '-';
- } else if (fplus)
+ } else if (fplus) {
*buf++ = '+';
- else if (fspace)
+ } else if (fspace) {
*buf++ = ' ';
+ }
decexp = 0;
while (exp <= -3) {
- while (fract[1] >= (MAXFP1 / 5)) {
- _rlrshift(fract);
+ while ((fract >> 32) >= (MAXFP1 / 5)) {
+ _rlrshift(&fract);
exp++;
}
- ltemp[0] = fract[0];
- ltemp[1] = fract[1];
- _llshift(fract);
- _llshift(fract);
- _ladd(fract, ltemp);
+ fract *= 5;
exp++;
decexp--;
- while (fract[1] <= (MAXFP1 / 2)) {
- _llshift(fract);
+ while ((fract >> 32) <= (MAXFP1 / 2)) {
+ fract <<= 1;
exp--;
}
}
while (exp > 0) {
- _ldiv5(fract);
+ _ldiv5(&fract);
exp--;
decexp++;
- while (fract[1] <= (MAXFP1 / 2)) {
- _llshift(fract);
+ while ((fract >> 32) <= (MAXFP1 / 2)) {
+ fract <<= 1;
exp--;
}
}
while (exp < (0 + 4)) {
- _rlrshift(fract);
+ _rlrshift(&fract);
exp++;
}
@@ -344,24 +320,23 @@ static int _to_float(char *buf, uint32_t double_temp[], int c,
if (exp > 16)
exp = 16;
- ltemp[0] = 0;
- ltemp[1] = 0x08000000;
+ ltemp = 0x0800000000000000;
while (exp--) {
- _ldiv5(ltemp);
- _rlrshift(ltemp);
+ _ldiv5(&ltemp);
+ _rlrshift(&ltemp);
}
- _ladd(fract, ltemp);
- if (fract[1] & 0xF0000000) {
- _ldiv5(fract);
- _rlrshift(fract);
+ fract += ltemp;
+ if ((fract >> 32) & 0xF0000000) {
+ _ldiv5(&fract);
+ _rlrshift(&fract);
decexp++;
}
if (c == 'f') {
if (decexp > 0) {
while (decexp > 0) {
- *buf++ = _get_digit(fract, &digit_count);
+ *buf++ = _get_digit(&fract, &digit_count);
decexp--;
}
} else
@@ -373,16 +348,16 @@ static int _to_float(char *buf, uint32_t double_temp[], int c,
*buf++ = '0';
decexp++;
} else
- *buf++ = _get_digit(fract, &digit_count);
+ *buf++ = _get_digit(&fract, &digit_count);
}
} else {
- *buf = _get_digit(fract, &digit_count);
+ *buf = _get_digit(&fract, &digit_count);
if (*buf++ != '0')
decexp--;
if (falt || (precision > 0))
*buf++ = '.';
while (precision-- > 0)
- *buf++ = _get_digit(fract, &digit_count);
+ *buf++ = _get_digit(&fract, &digit_count);
}
if (prune_zero) {
@@ -450,7 +425,7 @@ int _prf(int (*func)(), void *dest, char *format, va_list vargs)
int32_t *int32ptr_temp;
int32_t int32_temp;
uint32_t uint32_temp;
- uint32_t double_temp[2];
+ uint64_t double_temp;
count = 0;
@@ -599,20 +574,11 @@ int _prf(int (*func)(), void *dest, char *format, va_list vargs)
{
union {
double d;
- struct {
- uint32_t u1;
- uint32_t u2;
- } s;
+ uint64_t i;
} u;
u.d = (double) va_arg(vargs, double);
-#if defined(_BIG_ENDIAN)
- double_temp[0] = u.s.u2;
- double_temp[1] = u.s.u1;
-#else
- double_temp[0] = u.s.u1;
- double_temp[1] = u.s.u2;
-#endif
+ double_temp = u.i;
}
c = _to_float(buf, double_temp, c, falt, fplus,