(linenum→info "unix/slp.c:2238")

qemu/0.9.1/fpu/softfloat-native.c

    1: /* Native implementation of soft float functions. Only a single status
    2:    context is supported */
    3: #include "softfloat.h"
    4: #include <math.h>
    5: 
    6: void set_float_rounding_mode(int val STATUS_PARAM)
    7: {
    8:     STATUS(float_rounding_mode) = val;
    9: #if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
   10:     fpsetround(val);
   11: #elif defined(__arm__)
   12:     /* nothing to do */
   13: #else
   14:     fesetround(val);
   15: #endif
   16: }
   17: 
   18: #ifdef FLOATX80
   19: void set_floatx80_rounding_precision(int val STATUS_PARAM)
   20: {
   21:     STATUS(floatx80_rounding_precision) = val;
   22: }
   23: #endif
   24: 
   25: #if defined(_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
   26: #define lrint(d)                ((int32_t)rint(d))
   27: #define llrint(d)               ((int64_t)rint(d))
   28: #define lrintf(f)               ((int32_t)rint(f))
   29: #define llrintf(f)              ((int64_t)rint(f))
   30: #define sqrtf(f)                ((float)sqrt(f))
   31: #define remainderf(fa, fb)      ((float)remainder(fa, fb))
   32: #define rintf(f)                ((float)rint(f))
   33: #if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
   34: extern long double rintl(long double);
   35: extern long double scalbnl(long double, int);
   36: 
   37: long long
   38: llrintl(long double x) {
   39:         return ((long long) rintl(x));
   40: }
   41: 
   42: long
   43: lrintl(long double x) {
   44:         return ((long) rintl(x));
   45: }
   46: 
   47: long double
   48: ldexpl(long double x, int n) {
   49:         return (scalbnl(x, n));
   50: }
   51: #endif
   52: #endif
   53: 
   54: #if defined(__powerpc__)
   55: 
   56: /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
   57: double qemu_rint(double x)
   58: {
   59:     double y = 4503599627370496.0;
   60:     if (fabs(x) >= y)
   61:         return x;
   62:     if (x < 0)
   63:         y = -y;
   64:     y = (x + y) - y;
   65:     if (y == 0.0)
   66:         y = copysign(y, x);
   67:     return y;
   68: }
   69: 
   70: #define rint qemu_rint
   71: #endif
   72: 
   73: /*----------------------------------------------------------------------------
   74: | Software IEC/IEEE integer-to-floating-point conversion routines.
   75: *----------------------------------------------------------------------------*/
   76: float32 int32_to_float32(int v STATUS_PARAM)
   77: {
   78:     return (float32)v;
   79: }
   80: 
   81: float32 uint32_to_float32(unsigned int v STATUS_PARAM)
   82: {
   83:     return (float32)v;
   84: }
   85: 
   86: float64 int32_to_float64(int v STATUS_PARAM)
   87: {
   88:     return (float64)v;
   89: }
   90: 
   91: float64 uint32_to_float64(unsigned int v STATUS_PARAM)
   92: {
   93:     return (float64)v;
   94: }
   95: 
   96: #ifdef FLOATX80
   97: floatx80 int32_to_floatx80(int v STATUS_PARAM)
   98: {
   99:     return (floatx80)v;
  100: }
  101: #endif
  102: float32 int64_to_float32( int64_t v STATUS_PARAM)
  103: {
  104:     return (float32)v;
  105: }
  106: float32 uint64_to_float32( uint64_t v STATUS_PARAM)
  107: {
  108:     return (float32)v;
  109: }
  110: float64 int64_to_float64( int64_t v STATUS_PARAM)
  111: {
  112:     return (float64)v;
  113: }
  114: float64 uint64_to_float64( uint64_t v STATUS_PARAM)
  115: {
  116:     return (float64)v;
  117: }
  118: #ifdef FLOATX80
  119: floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
  120: {
  121:     return (floatx80)v;
  122: }
  123: #endif
  124: 
  125: /* XXX: this code implements the x86 behaviour, not the IEEE one.  */
  126: #if HOST_LONG_BITS == 32
  127: static inline int long_to_int32(long a)
  128: {
  129:     return a;
  130: }
  131: #else
  132: static inline int long_to_int32(long a)
  133: {
  134:     if (a != (int32_t)a)
  135:         a = 0x80000000;
  136:     return a;
  137: }
  138: #endif
  139: 
  140: /*----------------------------------------------------------------------------
  141: | Software IEC/IEEE single-precision conversion routines.
  142: *----------------------------------------------------------------------------*/
  143: int float32_to_int32( float32 a STATUS_PARAM)
  144: {
  145:     return long_to_int32(lrintf(a));
  146: }
  147: int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
  148: {
  149:     return (int)a;
  150: }
  151: int64_t float32_to_int64( float32 a STATUS_PARAM)
  152: {
  153:     return llrintf(a);
  154: }
  155: 
  156: int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
  157: {
  158:     return (int64_t)a;
  159: }
  160: 
  161: float64 float32_to_float64( float32 a STATUS_PARAM)
  162: {
  163:     return a;
  164: }
  165: #ifdef FLOATX80
  166: floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
  167: {
  168:     return a;
  169: }
  170: #endif
  171: 
  172: unsigned int float32_to_uint32( float32 a STATUS_PARAM)
  173: {
  174:     int64_t v;
  175:     unsigned int res;
  176: 
  177:     v = llrintf(a);
  178:     if (v < 0) {
  179:         res = 0;
  180:     } else if (v > 0xffffffff) {
  181:         res = 0xffffffff;
  182:     } else {
  183:         res = v;
  184:     }
  185:     return res;
  186: }
  187: unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
  188: {
  189:     int64_t v;
  190:     unsigned int res;
  191: 
  192:     v = (int64_t)a;
  193:     if (v < 0) {
  194:         res = 0;
  195:     } else if (v > 0xffffffff) {
  196:         res = 0xffffffff;
  197:     } else {
  198:         res = v;
  199:     }
  200:     return res;
  201: }
  202: 
  203: /*----------------------------------------------------------------------------
  204: | Software IEC/IEEE single-precision operations.
  205: *----------------------------------------------------------------------------*/
  206: float32 float32_round_to_int( float32 a STATUS_PARAM)
  207: {
  208:     return rintf(a);
  209: }
  210: 
  211: float32 float32_rem( float32 a, float32 b STATUS_PARAM)
  212: {
  213:     return remainderf(a, b);
  214: }
  215: 
  216: float32 float32_sqrt( float32 a STATUS_PARAM)
  217: {
  218:     return sqrtf(a);
  219: }
  220: int float32_compare( float32 a, float32 b STATUS_PARAM )
  221: {
  222:     if (a < b) {
  223:         return -1;
  224:     } else if (a == b) {
  225:         return 0;
  226:     } else if (a > b) {
  227:         return 1;
  228:     } else {
  229:         return 2;
  230:     }
  231: }
  232: int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
  233: {
  234:     if (isless(a, b)) {
  235:         return -1;
  236:     } else if (a == b) {
  237:         return 0;
  238:     } else if (isgreater(a, b)) {
  239:         return 1;
  240:     } else {
  241:         return 2;
  242:     }
  243: }
  244: int float32_is_signaling_nan( float32 a1)
  245: {
  246:     float32u u;
  247:     uint32_t a;
  248:     u.f = a1;
  249:     a = u.i;
  250:     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
  251: }
  252: 
  253: /*----------------------------------------------------------------------------
  254: | Software IEC/IEEE double-precision conversion routines.
  255: *----------------------------------------------------------------------------*/
  256: int float64_to_int32( float64 a STATUS_PARAM)
  257: {
  258:     return long_to_int32(lrint(a));
  259: }
  260: int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
  261: {
  262:     return (int)a;
  263: }
  264: int64_t float64_to_int64( float64 a STATUS_PARAM)
  265: {
  266:     return llrint(a);
  267: }
  268: int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
  269: {
  270:     return (int64_t)a;
  271: }
  272: float32 float64_to_float32( float64 a STATUS_PARAM)
  273: {
  274:     return a;
  275: }
  276: #ifdef FLOATX80
  277: floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
  278: {
  279:     return a;
  280: }
  281: #endif
  282: #ifdef FLOAT128
  283: float128 float64_to_float128( float64 a STATUS_PARAM)
  284: {
  285:     return a;
  286: }
  287: #endif
  288: 
  289: unsigned int float64_to_uint32( float64 a STATUS_PARAM)
  290: {
  291:     int64_t v;
  292:     unsigned int res;
  293: 
  294:     v = llrint(a);
  295:     if (v < 0) {
  296:         res = 0;
  297:     } else if (v > 0xffffffff) {
  298:         res = 0xffffffff;
  299:     } else {
  300:         res = v;
  301:     }
  302:     return res;
  303: }
  304: unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
  305: {
  306:     int64_t v;
  307:     unsigned int res;
  308: 
  309:     v = (int64_t)a;
  310:     if (v < 0) {
  311:         res = 0;
  312:     } else if (v > 0xffffffff) {
  313:         res = 0xffffffff;
  314:     } else {
  315:         res = v;
  316:     }
  317:     return res;
  318: }
  319: uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
  320: {
  321:     int64_t v;
  322: 
  323:     v = llrint(a + (float64)INT64_MIN);
  324: 
  325:     return v - INT64_MIN;
  326: }
  327: uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
  328: {
  329:     int64_t v;
  330: 
  331:     v = (int64_t)(a + (float64)INT64_MIN);
  332: 
  333:     return v - INT64_MIN;
  334: }
  335: 
  336: /*----------------------------------------------------------------------------
  337: | Software IEC/IEEE double-precision operations.
  338: *----------------------------------------------------------------------------*/
  339: #if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
  340: static inline float64 trunc(float64 x)
  341: {
  342:     return x < 0 ? -floor(-x) : floor(x);
  343: }
  344: #endif
  345: float64 float64_trunc_to_int( float64 a STATUS_PARAM )
  346: {
  347:     return trunc(a);
  348: }
  349: 
  350: float64 float64_round_to_int( float64 a STATUS_PARAM )
  351: {
  352: #if defined(__arm__)
  353:     switch(STATUS(float_rounding_mode)) {
  354:     default:
  355:     case float_round_nearest_even:
  356:         asm("rndd %0, %1" : "=f" (a) : "f"(a));
  357:         break;
  358:     case float_round_down:
  359:         asm("rnddm %0, %1" : "=f" (a) : "f"(a));
  360:         break;
  361:     case float_round_up:
  362:         asm("rnddp %0, %1" : "=f" (a) : "f"(a));
  363:         break;
  364:     case float_round_to_zero:
  365:         asm("rnddz %0, %1" : "=f" (a) : "f"(a));
  366:         break;
  367:     }
  368: #else
  369:     return rint(a);
  370: #endif
  371: }
  372: 
  373: float64 float64_rem( float64 a, float64 b STATUS_PARAM)
  374: {
  375:     return remainder(a, b);
  376: }
  377: 
  378: float64 float64_sqrt( float64 a STATUS_PARAM)
  379: {
  380:     return sqrt(a);
  381: }
  382: int float64_compare( float64 a, float64 b STATUS_PARAM )
  383: {
  384:     if (a < b) {
  385:         return -1;
  386:     } else if (a == b) {
  387:         return 0;
  388:     } else if (a > b) {
  389:         return 1;
  390:     } else {
  391:         return 2;
  392:     }
  393: }
  394: int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
  395: {
  396:     if (isless(a, b)) {
  397:         return -1;
  398:     } else if (a == b) {
  399:         return 0;
  400:     } else if (isgreater(a, b)) {
  401:         return 1;
  402:     } else {
  403:         return 2;
  404:     }
  405: }
  406: int float64_is_signaling_nan( float64 a1)
  407: {
  408:     float64u u;
  409:     uint64_t a;
  410:     u.f = a1;
  411:     a = u.i;
  412:     return
  413:            ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
  414:         && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
  415: 
  416: }
  417: 
  418: int float64_is_nan( float64 a1 )
  419: {
  420:     float64u u;
  421:     uint64_t a;
  422:     u.f = a1;
  423:     a = u.i;
  424: 
  425:     return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
  426: 
  427: }
  428: 
  429: #ifdef FLOATX80
  430: 
  431: /*----------------------------------------------------------------------------
  432: | Software IEC/IEEE extended double-precision conversion routines.
  433: *----------------------------------------------------------------------------*/
  434: int floatx80_to_int32( floatx80 a STATUS_PARAM)
  435: {
  436:     return long_to_int32(lrintl(a));
  437: }
  438: int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
  439: {
  440:     return (int)a;
  441: }
  442: int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
  443: {
  444:     return llrintl(a);
  445: }
  446: int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
  447: {
  448:     return (int64_t)a;
  449: }
  450: float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
  451: {
  452:     return a;
  453: }
  454: float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
  455: {
  456:     return a;
  457: }
  458: 
  459: /*----------------------------------------------------------------------------
  460: | Software IEC/IEEE extended double-precision operations.
  461: *----------------------------------------------------------------------------*/
  462: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
  463: {
  464:     return rintl(a);
  465: }
  466: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
  467: {
  468:     return remainderl(a, b);
  469: }
  470: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
  471: {
  472:     return sqrtl(a);
  473: }
  474: int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
  475: {
  476:     if (a < b) {
  477:         return -1;
  478:     } else if (a == b) {
  479:         return 0;
  480:     } else if (a > b) {
  481:         return 1;
  482:     } else {
  483:         return 2;
  484:     }
  485: }
  486: int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
  487: {
  488:     if (isless(a, b)) {
  489:         return -1;
  490:     } else if (a == b) {
  491:         return 0;
  492:     } else if (isgreater(a, b)) {
  493:         return 1;
  494:     } else {
  495:         return 2;
  496:     }
  497: }
  498: int floatx80_is_signaling_nan( floatx80 a1)
  499: {
  500:     floatx80u u;
  501:     u.f = a1;
  502:     return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
  503: }
  504: 
  505: #endif
1
Syntax (Markdown)