[Kernelloader-cvs] linux/minimalistic floatingpoint.c, 1.4, 1.5 snprintf.c, 1.4, 1.5
Run Linux on the Playstation 2
Brought to you by:
kloader
From: Mega M. <kl...@us...> - 2013-07-06 21:29:54
|
Update of /cvsroot/kernelloader/linux/minimalistic In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv11199 Modified Files: floatingpoint.c snprintf.c Log Message: Test special floating point cases (inf, NaN). Add simple support for printing float values. Index: snprintf.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/snprintf.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** snprintf.c 1 Jul 2013 14:08:04 -0000 1.4 --- snprintf.c 6 Jul 2013 21:29:52 -0000 1.5 *************** *** 11,14 **** --- 11,15 ---- #include <stdarg.h> + #include <stdint.h> #include "stdio.h" *************** *** 18,25 **** }; int vsnprintf(char *b, int len, const char *fmt, va_list pvar) { int n, i; ! unsigned u; char *t, d[10]; int l = len; --- 19,39 ---- }; + typedef union { + float f; + uint32_t i; + struct { + uint32_t mantissa:23; + uint32_t bias:8; + uint32_t sign:1; + } u; + } float_u; + int vsnprintf(char *b, int len, const char *fmt, va_list pvar) { int n, i; ! unsigned int u; ! double dbl; ! int32_t e; ! float_u f; char *t, d[10]; int l = len; *************** *** 125,128 **** --- 139,143 ---- case 'd': /* signed integer */ n = va_arg(pvar, int); + n2: if (n < 0) { *************** *** 155,158 **** --- 170,267 ---- break; + case 'f': + fmt++; + dbl = va_arg(pvar, double); + f.f = dbl; + if (f.u.sign) { + *b++ = '-'; + l--; + if (l <= 0) + break; + } + + if (f.u.bias == 255) { + if (f.u.mantissa == 0) { + *b++ = 'i'; + l--; + if (l <= 0) + break; + *b++ = 'n'; + l--; + if (l <= 0) + break; + *b++ = 'f'; + l--; + break; + } else { + *b++ = 'N'; + l--; + if (l <= 0) + break; + *b++ = 'a'; + l--; + if (l <= 0) + break; + *b++ = 'N'; + l--; + break; + } + } else { + if (f.u.bias == 0) { + if (f.u.mantissa == 0) { + *b++ = '0'; + l--; + break; + } + if (f.u.mantissa == 0) { + *b++ = '0'; + l--; + break; + } + } + } + + e = ((int32_t)f.u.bias) - 127; + if ((e >= 0) && (e < 32)) { + uint32_t man; + uint32_t m; + + man = f.u.mantissa; + if (e < 23) { + man >>= 23 - e; + m = man << (23 - e); + } else { + man <<= e - 23; + m = man >> (e - 23); + } + if (man == m) { + /* Value is a simple integer. */ + u = 1 << e; + u |= man; + goto u2; + } + } + u = f.u.mantissa | (1 << 23); + i = 9; + do { + d[i] = (u % 10) + '0'; + u /= 10; + i--; + } while (u && i >= 0); + while (++i < 10) { + *b++ = d[i]; + l--; + if (l <= 0) + break; + } + + *b++ = 'e'; + l--; + if (l <= 0) + break; + + n = ((int32_t)f.u.bias) - 127; + goto n2; + case 0: /* End of string reached before type specifier. */ Index: floatingpoint.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/floatingpoint.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** floatingpoint.c 11 Jun 2013 12:54:55 -0000 1.4 --- floatingpoint.c 6 Jul 2013 21:29:52 -0000 1.5 *************** *** 60,64 **** __asm__("cfc1 %0, $0\n":"=r"(fcr0)); printf("fcr1: 0x%08x\n", fcr0); ! if (fcr0 == 0x00002e30) { printf("FPU is enabled\n"); } else { --- 60,64 ---- __asm__("cfc1 %0, $0\n":"=r"(fcr0)); printf("fcr1: 0x%08x\n", fcr0); ! if ((fcr0 & 0xFFFFFF00) == 0x00002e00) { printf("FPU is enabled\n"); } else { *************** *** 86,89 **** --- 86,145 ---- } + void devide(float a, float b) + { + float r; + unsigned int *pa = (void *) &a; + unsigned int *pb = (void *) &b; + unsigned int *pr = (void *) &r; + + r = a / b; + + printf("%f (0x%08x) / %f (0x%08x) = %f (0x%08x)\n", a, *pa, b, *pb, r, *pr); + } + + void add(float a, float b) + { + float r; + unsigned int *pa = (void *) &a; + unsigned int *pb = (void *) &b; + unsigned int *pr = (void *) &r; + + r = a + b; + + printf("%f (0x%08x) + %f (0x%08x) = %f (0x%08x)\n", a, *pa, b, *pb, r, *pr); + } + + typedef union { + float f; + uint32_t i; + } float_u; + + void nantest(void) + { + float_u nan; + float_u nnan; + float_u inf; + float_u ninf; + + if (sizeof(nan) != 4) { + printf("Error: Size of float is not 32 bits!\n"); + return; + } + + devide(1, 0); + devide(0, 0); + nan.i = 0x7fc00000; + nnan.i = 0xffc00000; + inf.i = 0x7f800000; + ninf.i = 0xff800000; + devide(0, nan.f); + add(1, 1); + add(1, inf.f); + add(inf.f, inf.f); + add(inf.f, ninf.f); + add(nan.f, nan.f); + add(nan.f, nnan.f); + } + void test_floating_point(void) { *************** *** 93,95 **** --- 149,152 ---- #endif test_fp2(); + nantest(); } |