floatsisf.c revision 09009c50dd7118ed0bdf97e5c37e23c25e443682
109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//===-- lib/floatsisf.c - integer -> single-precision conversion --*- C -*-===//
209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//
309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//                     The LLVM Compiler Infrastructure
409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//
509009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon// This file is distributed under the University of Illinois Open Source
609009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon// License. See LICENSE.TXT for details.
709009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//
809009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//===----------------------------------------------------------------------===//
909009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//
1009009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon// This file implements integer to single-precision conversion for the
1109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even
1209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon// mode.
1309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//
1409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon//===----------------------------------------------------------------------===//
1509009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
1609009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon#define SINGLE_PRECISION
1709009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon#include "fp_lib.h"
1809009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
1909009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canonfp_t __floatsisf(int a) {
2009009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
2109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    const int aWidth = sizeof a * CHAR_BIT;
2209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
2309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // Handle zero as a special case to protect clz
2409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    if (a == 0)
2509009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        return fromRep(0);
2609009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
2709009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // All other cases begin by extracting the sign and absolute value of a
2809009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    rep_t sign = 0;
2909009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    if (a < 0) {
3009009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        sign = signBit;
3109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        a = -a;
3209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    }
3309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
3409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // Exponent of (fp_t)a is the width of abs(a).
3509009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    const int exponent = (aWidth - 1) - __builtin_clz(a);
3609009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    rep_t result;
3709009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
3809009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // Shift a into the significand field, rounding if it is a right-shift
3909009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    if (exponent <= significandBits) {
4009009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        const int shift = significandBits - exponent;
4109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        result = (rep_t)a << shift ^ implicitBit;
4209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    } else {
4309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        const int shift = exponent - significandBits;
4409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        result = (rep_t)a >> shift ^ implicitBit;
4509009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        rep_t round = (rep_t)a << (typeWidth - shift);
4609009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        if (round > signBit) result++;
4709009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon        if (round == signBit) result += result & 1;
4809009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    }
4909009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon
5009009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // Insert the exponent
5109009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    result += (rep_t)(exponent + exponentBias) << significandBits;
5209009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    // Insert the sign bit and return
5309009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon    return fromRep(result | sign);
5409009c50dd7118ed0bdf97e5c37e23c25e443682Stephen Canon}
55