blob: 1f08d51354b69977fb241879c800f95446bb845b [file] [edit]
//===-- floatdisf.S - 64-bit integer to single-precision FP conversion ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the __floatdisf and __floatundisf functions (64-bit
// signed and unsigned integer to single precision floating point conversion),
// with the IEEE-754 default rounding (to nearest, ties to even), for the Arm
// and Thumb2 ISAs.
//
//===----------------------------------------------------------------------===//
#include "../assembly.h"
#include "crt_endian.h"
.syntax unified
.text
.p2align 2
#if __ARM_PCS_VFP
DEFINE_COMPILERRT_FUNCTION(__floatdisf)
push {r4, lr}
bl __aeabi_l2f
vmov s0, r0
pop {r4, pc}
#else
DEFINE_COMPILERRT_FUNCTION_ALIAS(__floatdisf, __aeabi_l2f)
#endif
DEFINE_COMPILERRT_FUNCTION(__aeabi_l2f)
// Isolate the input integer's sign bit in r2, and if the input is negative,
// negate it.
ands r2, xh, #0x80000000
bpl 0f // if positive, skip the negation
rsbs xl, xl, #0
#if __thumb__
// Thumb has no RSC, so simulate it by bitwise inversion and then ADC
mvn xh, xh
adc xh, xh, #0
#else
rsc xh, xh, #0
#endif
0:
// Combine the sign in r2 with the FP exponent of 1. So r2 now holds the
// single-precision encoding of +1 or -1 as appropriate.
orr r2, r2, #0x3f800000
// Now we have a positive 64-bit integer in xh,xl, and a starting sign +
// exponent in r2.
//
// We also come here from the unsigned-integer conversion function below, so
// we must handle xh,xl having any possible values at all, even 2^63 or
// greater.
LOCAL_LABEL(normalise):
// Add 30 to the exponent in r2, so that it holds +2^30 or -2^30. The idea is
// that after we normalise the input integer into a FP mantissa with the
// topmost 1 in bit 23, adding that will increment by one more, so that this
// exponent will be correct if the input has its high bit in bit 31. We'll
// decrease the exponent if CLZ returns a positive value, and increment it by
// 32 if the high word is used.
//
// You might ask why we didn't set up r2 to have this value in the first
// place, by ORRing the sign bit with 0x4e800000 instead of 0x3f800000. The
// answer is because 0x4e800000 can't be represented in the immediate field
// of an AArch32 data-processing instruction, so we can't avoid using two
// instructions.
add r2, r2, #(30 << 23)
// Start setting up r3 to be the exponent adjustment, and set xh to be the
// highest _nonzero_ word of the input. If xh = 0, set r3 = 0 and copy xl
// (the only nonzero input word) into xh; if xh != 0, set r3 = 32.
movs r3, xh // sets r3=0 if xh=0, testing at the same time
movne r3, #32 // if that didn't happen, set r3=32
movseq xh, xl // and otherwise, copy xl into xh
// Using a MOVS for the final copy has the side effect that we've also just
// tested whether xh = xl = 0. If so, then the entire input value was zero,
// so we should return 0. Conveniently, that's the value in both xl and xh
// right now, so no matter which of those is r0 (which varies with
// endianness) we can just return.
bxeq lr
// Now we know xh contains the highest set bit of the input. Find that bit,
// shift it up to the top of the word, and adjust the shift count
// appropriately.
//
// After this, r3 contains the full exponent adjustment we'll need to add to
// the starting exponent in r2: it takes values from -31 (if the input was 1)
// to +32 (if the input was 2^63 or bigger).
clz r12, xh
mov xh, xh, lsl r12
sub r3, r3, r12
// If the input integer is < 2^32, then we've now set up xh to be the full
// output mantissa (with its leading bit at the top of the word). If not,
// then we still need to add some bits from xl.
//
// We don't need to spend an instruction on deciding which: it's enough to
// just shift xl right by whatever is in r3. In the case where we don't want
// it (because the bits in xl are already in the output mantissa), r3 <= 0.
// If r3 = 0 (the input was an exactly 32-bit integer) then the bits in xl
// will exactly overlay the ones already in xh and make no difference; if r3
// < 0 then the AArch32 shift instruction semantics will treat it as a shift
// of more than 32 bits, shifting xl right off the bottom of the word, and
// again not modify xh.
#if __thumb__
// Thumb can't fold a register-controlled shift into an ORR, so we must use
// two separate instructions.
lsr r12, xl, r3
orr xh, xh, r12
#else
orr xh, xh, xl, lsr r3 // if shift negative then xh unaltered
#endif
// Combine the exponent adjustment in r3 with the starting exponent and sign
// in r2. These parts of the output are now ready to combine with the
// mantissa, once we've shifted it down and rounded it.
add r2, r2, r3, lsl #23
// Now we must round. The mantissa in r12 contains the top 32 bits of the
// full result, including the bit we're going to shift just off the bottom
// (which controls the basic 'round up or down?' question). So we can start
// by checking those, which will handle most cases.
// This shift moves the round bit off the top of xh into the carry flag, so
// that C is set if we're rounding up. It also sets Z if all the bits below
// that are zero, which _might_ mean we need to round to even, but only if
// the further bits in xl are also zero. But if Z is _not_ set then we can
// return without checking xl.
lsls r12, xh, #25
#ifndef __BIG_ENDIAN__
// We're about to overwrite r0 with the preliminary output. This will be our
// last use of xh, but we still need xl later. So in little-endian mode,
// where xl _is_ r0, we must spend an extra instruction on saving it.
mov r12, xl
#endif
// Recombine the mantissa (shifted down to the right position) with the sign
// and exponent in r2. Using ADC also rounds up if C is set.
adc r0, r2, xh, lsr #8
// If C was clear, we didn't round up, so we don't need to undo that by
// rounding to even. And if Z was clear, we're not rounding to even anyway.
// So in either case, we're done.
bxcc lr
bxne lr
// The slow path: nothing in the top 32 bits of the mantissa ruled out having
// to round to even. Now we must check the rest of the mantissa bits in xl.
//
// This RSB instruction converts the previous exponent adjustment value (-31
// for smallest integer, +32 for largest) into a value from 0 (_largest_
// integer) to 63 (smallest). So if the integer occupied n bits of xh, then
// 32-n bits of xl ended up in the initial mantissa word, so shifting xl left
// by 32-n will catch precisely the bits of xl that didn't. And if the
// integer was entirely in xl, then this shift count will be >=32, so the
// left shift will throw away all of xl.
rsb r3, r3, #32
// Shift xl to include just the shifted-off bits, setting Z if they're all
// zero. Then we know whether to round to even by clearing bit 0 of the
// output.
#ifdef __BIG_ENDIAN__
lsls r12, xl, r3 // the low word is still in xl itself
#else
lsls r12, r12, r3 // we moved it into r12 earlier
#endif
biceq r0, r0, #1
// And whether we did that or not, we're finished.
bx lr
END_COMPILERRT_FUNCTION(__aeabi_l2f)
#if __ARM_PCS_VFP
DEFINE_COMPILERRT_FUNCTION(__floatundisf)
push {r4, lr}
bl __aeabi_ul2f
vmov s0, r0
pop {r4, pc}
#else
DEFINE_COMPILERRT_FUNCTION_ALIAS(__floatundisf, __aeabi_ul2f)
#endif
DEFINE_COMPILERRT_FUNCTION(__aeabi_ul2f)
// Jump to l2f_normalise above, without negating the input, and having set up
// r2 unconditionally to indicate that a positive output is wanted.
mov r2, #0x3f800000
b LOCAL_LABEL(normalise)
END_COMPILERRT_FUNCTION(__aeabi_ul2f)
#if defined(__MINGW32__)
DEFINE_COMPILERRT_FUNCTION_ALIAS(__i64tos, __floatdisf)
DEFINE_COMPILERRT_FUNCTION_ALIAS(__u64tos, __floatundisf)
#endif
NO_EXEC_STACK_DIRECTIVE