| //===-- floatundidf.S - 64-bit unsigned int to double-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 __floatundidf function (64-bit unsigned integer to |
| // double 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(__floatundidf) |
| push {r4, lr} |
| bl __aeabi_ul2d |
| VMOV_TO_DOUBLE(d0, r0, r1) |
| pop {r4, pc} |
| #else |
| DEFINE_COMPILERRT_FUNCTION_ALIAS(__floatundidf, __aeabi_ul2d) |
| #endif |
| |
| DEFINE_COMPILERRT_FUNCTION(__aeabi_ul2d) |
| |
| // There are essentially three cases we need to separate. The leading bit of |
| // the integer is either in xh or xl; if it's in xh, it makes a difference |
| // whether it's above bit 20, because that's the case where we must shift |
| // right and potentially round. |
| // |
| // Start by assuming the high word is nonzero; if we're wrong, we'll find out |
| // in a few instructions' time and be able to try again. So we find the |
| // position of the leading bit in xh, and turn it into a left-shift count |
| // that will move the leading bit up to where it belongs in the output |
| // double. |
| clz r3, xh |
| subs r3, r3, #11 |
| |
| // If that left-shift count is negative, we're going to have to shift the |
| // mantissa right instead of left, and maybe round it. Branch out of line for |
| // the code that handles that case. |
| blo LOCAL_LABEL(shiftdown) |
| |
| // Shift xh left to bring the top word of the mantissa to the right place. By |
| // making this shift set the flags, we detect if xh was zero. |
| // |
| // We branch out of line if it _wasn't_ zero, on the theory that small input |
| // integers are likely to occur more often than large ones, so the small case |
| // should be the faster path. This is a bit of a compromise between large and |
| // small integer performance: if we wanted to prioritise small inputs above |
| // all else, we could have tested if xh=0 to begin with - but that would cost |
| // an extra instruction on the large-integer path, because it repeats work |
| // that this instruction can do in passing. |
| lsls xh, xh, r3 |
| bne LOCAL_LABEL(highword) |
| |
| // Now we've found out that xh=0, we need to repeat the CLZ instruction on |
| // xl. The simplest thing is to shift xl up by a variable distance to put its |
| // leading bit at the top; then we can do immediate shifts to move it up |
| // further to the top of the double-precision mantissa. (Otherwise you'd have |
| // to make a second shift count by subtracting from 32, using more registers |
| // and requiring more register-controlled shifts, especially awkward in |
| // Thumb.) |
| // |
| // There may not _be_ a leading bit in xl at all (just as there turned out |
| // not to have been one in xh, if we're on this path). In that case the input |
| // integer was 0, and so we should return double-precision 0, which |
| // conveniently has the same representation (xh=xl=0 already). |
| clz r3, xl // decide how far to shift up |
| lsls xh, xl, r3 // do the shift, also checking if xl = 0 |
| bxeq lr // if xl = 0, return zero immediately |
| |
| // Now xl contains the output mantissa, with the leading bit at the top. We |
| // must shift that up another 21 bits, and recombine it with an exponent |
| // derived from r3 (telling us how far we've already shifted up). |
| // |
| // If r3=0 then the input value was in the range [2^31,2^32), so its exponent |
| // in double precision should be 0x41e. We want to reduce that by 1 so that |
| // the leading bit of the mantissa will increment it when we add it in. So |
| // the exponent should be 0x41d minus r3. |
| rsb r3, r3, #0x1d // 0x1d minus shift count |
| add r3, r3, #0x400 // 0x41d minus shift count |
| lsr r2, xh, #11 // make top word of mantissa |
| lsl xl, xh, #21 // make bottom word of mantissa |
| add xh, r2, r3, lsl #20 // and combine it with exponent |
| bx lr |
| |
| LOCAL_LABEL(highword): |
| // This is the branch for numbers big enough that xh != 0, but not big enough |
| // to need to shift downwards and round. |
| // |
| // r3 is the distance that we've already shifted xh left by. We'll need to |
| // shift xl left by the same amount, and we'll also need to shift xl right by |
| // 32 minus that, to put some of its bits at the bottom of xh. |
| rsb r12, r3, #32 |
| #if __thumb__ |
| // In Thumb we have to do the register-controlled shift and the OR in |
| // separate instructions. |
| lsr r12, xl, r12 |
| orr xh, xh, r12 |
| #else |
| orr xh, xh, xl, lsr r12 |
| #endif |
| // Shift xl left as well, so that xh:xl are now the full output mantissa, |
| // with its leading bit in bit 20 of xh. |
| lsls xl, xl, r3 |
| |
| // Calculate the exponent, and recombine it with the mantissa. This is |
| // exactly the same method as above, except that the exponent is different, |
| // because this time r3 stores the offset between the original leading bit |
| // position and bit 20 of the mantissa, so that it's zero if the input is in |
| // the range [2^52,2^53), which would make the output exponent 0x433, or |
| // 0x432 after compensating for the leading mantissa bit. |
| rsb r3, r3, #0x32 // 0x32 minus shift count |
| add r3, r3, #0x400 // 0x432 minus shift count |
| add xh, xh, r3, lsl #20 // combine with the top word of the mantissa |
| bx lr |
| |
| LOCAL_LABEL(shiftdown): |
| // This is the branch for numbers so big that the mantissa has to be shifted |
| // _right_, so that some of the mantissa is shifted off the bottom and the |
| // number has to be rounded. |
| // |
| // r3 contains the shift count, but it's currently negative (it was |
| // calculated as a left shift). So it's in a good state to use for |
| // calculating the output exponent, and therefore we do that first, while |
| // it's convenient. |
| rsb r2, r3, #0x32 // 0x32 minus shift count |
| add r2, r2, #0x400 // 0x432 minus shift count |
| |
| // Shift the mantissa down to the right position, capturing the bits shifted |
| // off the bottom at the top of r3. We'll need to temporarily push a couple |
| // of extra registers for this part, because we need to calculate how far to |
| // shift xh and xl right, but also how far to shift them left to get the bits |
| // shifted out of each one. |
| push {r4,lr} |
| rsb r4, r3, #0 // r4 = right-shift count |
| rsb lr, r4, #32 // lr = left-shift count |
| lsl r12, xh, lr // r12 = bits shifted out of xh |
| lsr xh, xh, r4 // shift xh right to make its final value |
| lsl r3, xl, lr // r3 = bits shifted out of xl |
| #if __thumb__ |
| // In Thumb we have to do the register-controlled shift and the OR in |
| // separate instructions. |
| lsrs xl, xl, r4 |
| orr xl, xl, r12 |
| #else |
| orrs xl, r12, xl, lsr r4 // shift xl right and combine with r12 |
| #endif |
| pop {r4,lr} |
| |
| // Now xh:xl contains the unrounded output mantissa; r2 contains its |
| // exponent; and r3 contains the bits shifted off the bottom. Also, the |
| // single flag-setting shift in the sequence above was the one that shifted |
| // xl right, so the carry flag contains the bit just off the bottom, i.e. the |
| // bit that tells us whether we need to round up. |
| // |
| // Recombine the mantissa with the exponent, and then if C is clear, we don't |
| // need to round up, and can return. |
| add xh, xh, r2, lsl #20 // put back the exponent |
| bxcc lr // return if we don't have to round |
| |
| // We're rounding up, and we may also need to round to even. |
| adds xl, xl, #1 // increment the mantissa to round up |
| adc xh, xh, #0 // and propagate a carry if any |
| lsls r3, r3, #1 // set Z if we had an exact halfway case |
| biceq xl, xl, #1 // and round back to even if so |
| bx lr |
| |
| END_COMPILERRT_FUNCTION(__aeabi_ul2d) |
| |
| #if defined(__MINGW32__) |
| DEFINE_COMPILERRT_FUNCTION_ALIAS(__u64tod, __floatundidf) |
| #endif |
| |
| NO_EXEC_STACK_DIRECTIVE |