linux/arch/mips/math-emu/dp_tint.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* IEEE754 floating point arithmetic
   3 * double precision: common utilities
   4 */
   5/*
   6 * MIPS floating point support
   7 * Copyright (C) 1994-2000 Algorithmics Ltd.
   8 */
   9
  10#include "ieee754dp.h"
  11
  12int ieee754dp_tint(union ieee754dp x)
  13{
  14        u64 residue;
  15        int round;
  16        int sticky;
  17        int odd;
  18
  19        COMPXDP;
  20
  21        ieee754_clearcx();
  22
  23        EXPLODEXDP;
  24        FLUSHXDP;
  25
  26        switch (xc) {
  27        case IEEE754_CLASS_SNAN:
  28        case IEEE754_CLASS_QNAN:
  29                ieee754_setcx(IEEE754_INVALID_OPERATION);
  30                return ieee754si_indef();
  31
  32        case IEEE754_CLASS_INF:
  33                ieee754_setcx(IEEE754_INVALID_OPERATION);
  34                return ieee754si_overflow(xs);
  35
  36        case IEEE754_CLASS_ZERO:
  37                return 0;
  38
  39        case IEEE754_CLASS_DNORM:
  40        case IEEE754_CLASS_NORM:
  41                break;
  42        }
  43        if (xe > 31) {
  44                /* Set invalid. We will only use overflow for floating
  45                   point overflow */
  46                ieee754_setcx(IEEE754_INVALID_OPERATION);
  47                return ieee754si_overflow(xs);
  48        }
  49        /* oh gawd */
  50        if (xe > DP_FBITS) {
  51                xm <<= xe - DP_FBITS;
  52        } else if (xe < DP_FBITS) {
  53                if (xe < -1) {
  54                        residue = xm;
  55                        round = 0;
  56                        sticky = residue != 0;
  57                        xm = 0;
  58                } else {
  59                        residue = xm << (64 - DP_FBITS + xe);
  60                        round = (residue >> 63) != 0;
  61                        sticky = (residue << 1) != 0;
  62                        xm >>= DP_FBITS - xe;
  63                }
  64                /* Note: At this point upper 32 bits of xm are guaranteed
  65                   to be zero */
  66                odd = (xm & 0x1) != 0x0;
  67                switch (ieee754_csr.rm) {
  68                case FPU_CSR_RN:
  69                        if (round && (sticky || odd))
  70                                xm++;
  71                        break;
  72                case FPU_CSR_RZ:
  73                        break;
  74                case FPU_CSR_RU:        /* toward +Infinity */
  75                        if ((round || sticky) && !xs)
  76                                xm++;
  77                        break;
  78                case FPU_CSR_RD:        /* toward -Infinity */
  79                        if ((round || sticky) && xs)
  80                                xm++;
  81                        break;
  82                }
  83                /* look for valid corner case 0x80000000 */
  84                if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
  85                        /* This can happen after rounding */
  86                        ieee754_setcx(IEEE754_INVALID_OPERATION);
  87                        return ieee754si_overflow(xs);
  88                }
  89                if (round || sticky)
  90                        ieee754_setcx(IEEE754_INEXACT);
  91        }
  92        if (xs)
  93                return -xm;
  94        else
  95                return xm;
  96}
  97