mirror of
https://github.com/xemu-project/xemu.git
synced 2024-12-05 02:06:40 +00:00
5937fb63a9
The macros use the "flags" type and to be consistent if anyone just needs the macros we should bring in the header we need. There is an outstanding TODO to audit the use of "flags" and replace with bool at which point this include could be dropped. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Acked-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
806 lines
27 KiB
C
806 lines
27 KiB
C
/*
|
|
* QEMU float support macros
|
|
*
|
|
* The code in this source file is derived from release 2a of the SoftFloat
|
|
* IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
|
|
* some later contributions) are provided under that license, as detailed below.
|
|
* It has subsequently been modified by contributors to the QEMU Project,
|
|
* so some portions are provided under:
|
|
* the SoftFloat-2a license
|
|
* the BSD license
|
|
* GPL-v2-or-later
|
|
*
|
|
* Any future contributions to this file after December 1st 2014 will be
|
|
* taken to be licensed under the Softfloat-2a license unless specifically
|
|
* indicated otherwise.
|
|
*/
|
|
|
|
/*
|
|
===============================================================================
|
|
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
|
Arithmetic Package, Release 2a.
|
|
|
|
Written by John R. Hauser. This work was made possible in part by the
|
|
International Computer Science Institute, located at Suite 600, 1947 Center
|
|
Street, Berkeley, California 94704. Funding was partially provided by the
|
|
National Science Foundation under grant MIP-9311980. The original version
|
|
of this code was written as part of a project to build a fixed-point vector
|
|
processor in collaboration with the University of California at Berkeley,
|
|
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
|
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
|
|
arithmetic/SoftFloat.html'.
|
|
|
|
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
|
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
|
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
|
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
|
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
|
|
|
Derivative works are acceptable, even for commercial purposes, so long as
|
|
(1) they include prominent notice that the work is derivative, and (2) they
|
|
include prominent notice akin to these four paragraphs for those parts of
|
|
this code that are retained.
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/* BSD licensing:
|
|
* Copyright (c) 2006, Fabrice Bellard
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/* Portions of this work are licensed under the terms of the GNU GPL,
|
|
* version 2 or later. See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#ifndef FPU_SOFTFLOAT_MACROS_H
|
|
#define FPU_SOFTFLOAT_MACROS_H
|
|
|
|
#include "fpu/softfloat-types.h"
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts `a' right by the number of bits given in `count'. If any nonzero
|
|
| bits are shifted off, they are ``jammed'' into the least significant bit of
|
|
| the result by setting the least significant bit to 1. The value of `count'
|
|
| can be arbitrarily large; in particular, if `count' is greater than 32, the
|
|
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
|
|
| The result is stored in the location pointed to by `zPtr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void shift32RightJamming(uint32_t a, int count, uint32_t *zPtr)
|
|
{
|
|
uint32_t z;
|
|
|
|
if ( count == 0 ) {
|
|
z = a;
|
|
}
|
|
else if ( count < 32 ) {
|
|
z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
|
|
}
|
|
else {
|
|
z = ( a != 0 );
|
|
}
|
|
*zPtr = z;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts `a' right by the number of bits given in `count'. If any nonzero
|
|
| bits are shifted off, they are ``jammed'' into the least significant bit of
|
|
| the result by setting the least significant bit to 1. The value of `count'
|
|
| can be arbitrarily large; in particular, if `count' is greater than 64, the
|
|
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
|
|
| The result is stored in the location pointed to by `zPtr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void shift64RightJamming(uint64_t a, int count, uint64_t *zPtr)
|
|
{
|
|
uint64_t z;
|
|
|
|
if ( count == 0 ) {
|
|
z = a;
|
|
}
|
|
else if ( count < 64 ) {
|
|
z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
|
|
}
|
|
else {
|
|
z = ( a != 0 );
|
|
}
|
|
*zPtr = z;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
|
|
| _plus_ the number of bits given in `count'. The shifted result is at most
|
|
| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
|
|
| bits shifted off form a second 64-bit result as follows: The _last_ bit
|
|
| shifted off is the most-significant bit of the extra result, and the other
|
|
| 63 bits of the extra result are all zero if and only if _all_but_the_last_
|
|
| bits shifted off were all zero. This extra result is stored in the location
|
|
| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
|
|
| (This routine makes more sense if `a0' and `a1' are considered to form a
|
|
| fixed-point value with binary point between `a0' and `a1'. This fixed-point
|
|
| value is shifted right by the number of bits given in `count', and the
|
|
| integer part of the result is returned at the location pointed to by
|
|
| `z0Ptr'. The fractional part of the result may be slightly corrupted as
|
|
| described above, and is returned at the location pointed to by `z1Ptr'.)
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
shift64ExtraRightJamming(
|
|
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
|
{
|
|
uint64_t z0, z1;
|
|
int8_t negCount = ( - count ) & 63;
|
|
|
|
if ( count == 0 ) {
|
|
z1 = a1;
|
|
z0 = a0;
|
|
}
|
|
else if ( count < 64 ) {
|
|
z1 = ( a0<<negCount ) | ( a1 != 0 );
|
|
z0 = a0>>count;
|
|
}
|
|
else {
|
|
if ( count == 64 ) {
|
|
z1 = a0 | ( a1 != 0 );
|
|
}
|
|
else {
|
|
z1 = ( ( a0 | a1 ) != 0 );
|
|
}
|
|
z0 = 0;
|
|
}
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
|
|
| number of bits given in `count'. Any bits shifted off are lost. The value
|
|
| of `count' can be arbitrarily large; in particular, if `count' is greater
|
|
| than 128, the result will be 0. The result is broken into two 64-bit pieces
|
|
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
shift128Right(
|
|
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
|
{
|
|
uint64_t z0, z1;
|
|
int8_t negCount = ( - count ) & 63;
|
|
|
|
if ( count == 0 ) {
|
|
z1 = a1;
|
|
z0 = a0;
|
|
}
|
|
else if ( count < 64 ) {
|
|
z1 = ( a0<<negCount ) | ( a1>>count );
|
|
z0 = a0>>count;
|
|
}
|
|
else {
|
|
z1 = (count < 128) ? (a0 >> (count & 63)) : 0;
|
|
z0 = 0;
|
|
}
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
|
|
| number of bits given in `count'. If any nonzero bits are shifted off, they
|
|
| are ``jammed'' into the least significant bit of the result by setting the
|
|
| least significant bit to 1. The value of `count' can be arbitrarily large;
|
|
| in particular, if `count' is greater than 128, the result will be either
|
|
| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
|
|
| nonzero. The result is broken into two 64-bit pieces which are stored at
|
|
| the locations pointed to by `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
shift128RightJamming(
|
|
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
|
{
|
|
uint64_t z0, z1;
|
|
int8_t negCount = ( - count ) & 63;
|
|
|
|
if ( count == 0 ) {
|
|
z1 = a1;
|
|
z0 = a0;
|
|
}
|
|
else if ( count < 64 ) {
|
|
z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
|
|
z0 = a0>>count;
|
|
}
|
|
else {
|
|
if ( count == 64 ) {
|
|
z1 = a0 | ( a1 != 0 );
|
|
}
|
|
else if ( count < 128 ) {
|
|
z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
|
|
}
|
|
else {
|
|
z1 = ( ( a0 | a1 ) != 0 );
|
|
}
|
|
z0 = 0;
|
|
}
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
|
|
| by 64 _plus_ the number of bits given in `count'. The shifted result is
|
|
| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
|
|
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
|
|
| off form a third 64-bit result as follows: The _last_ bit shifted off is
|
|
| the most-significant bit of the extra result, and the other 63 bits of the
|
|
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
|
|
| were all zero. This extra result is stored in the location pointed to by
|
|
| `z2Ptr'. The value of `count' can be arbitrarily large.
|
|
| (This routine makes more sense if `a0', `a1', and `a2' are considered
|
|
| to form a fixed-point value with binary point between `a1' and `a2'. This
|
|
| fixed-point value is shifted right by the number of bits given in `count',
|
|
| and the integer part of the result is returned at the locations pointed to
|
|
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
|
|
| corrupted as described above, and is returned at the location pointed to by
|
|
| `z2Ptr'.)
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
shift128ExtraRightJamming(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t a2,
|
|
int count,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2;
|
|
int8_t negCount = ( - count ) & 63;
|
|
|
|
if ( count == 0 ) {
|
|
z2 = a2;
|
|
z1 = a1;
|
|
z0 = a0;
|
|
}
|
|
else {
|
|
if ( count < 64 ) {
|
|
z2 = a1<<negCount;
|
|
z1 = ( a0<<negCount ) | ( a1>>count );
|
|
z0 = a0>>count;
|
|
}
|
|
else {
|
|
if ( count == 64 ) {
|
|
z2 = a1;
|
|
z1 = a0;
|
|
}
|
|
else {
|
|
a2 |= a1;
|
|
if ( count < 128 ) {
|
|
z2 = a0<<negCount;
|
|
z1 = a0>>( count & 63 );
|
|
}
|
|
else {
|
|
z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
|
|
z1 = 0;
|
|
}
|
|
}
|
|
z0 = 0;
|
|
}
|
|
z2 |= ( a2 != 0 );
|
|
}
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
|
|
| number of bits given in `count'. Any bits shifted off are lost. The value
|
|
| of `count' must be less than 64. The result is broken into two 64-bit
|
|
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void shortShift128Left(uint64_t a0, uint64_t a1, int count,
|
|
uint64_t *z0Ptr, uint64_t *z1Ptr)
|
|
{
|
|
*z1Ptr = a1 << count;
|
|
*z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63));
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
|
|
| number of bits given in `count'. Any bits shifted off are lost. The value
|
|
| of `count' may be greater than 64. The result is broken into two 64-bit
|
|
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void shift128Left(uint64_t a0, uint64_t a1, int count,
|
|
uint64_t *z0Ptr, uint64_t *z1Ptr)
|
|
{
|
|
if (count < 64) {
|
|
*z1Ptr = a1 << count;
|
|
*z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63));
|
|
} else {
|
|
*z1Ptr = 0;
|
|
*z0Ptr = a1 << (count - 64);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
|
|
| by the number of bits given in `count'. Any bits shifted off are lost.
|
|
| The value of `count' must be less than 64. The result is broken into three
|
|
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
|
| `z1Ptr', and `z2Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
shortShift192Left(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t a2,
|
|
int count,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2;
|
|
int8_t negCount;
|
|
|
|
z2 = a2<<count;
|
|
z1 = a1<<count;
|
|
z0 = a0<<count;
|
|
if ( 0 < count ) {
|
|
negCount = ( ( - count ) & 63 );
|
|
z1 |= a2>>negCount;
|
|
z0 |= a1>>negCount;
|
|
}
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
|
|
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
|
|
| any carry out is lost. The result is broken into two 64-bit pieces which
|
|
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
add128(
|
|
uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
|
{
|
|
uint64_t z1;
|
|
|
|
z1 = a1 + b1;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = a0 + b0 + ( z1 < a1 );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
|
|
| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
|
|
| modulo 2^192, so any carry out is lost. The result is broken into three
|
|
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
|
| `z1Ptr', and `z2Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
add192(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t a2,
|
|
uint64_t b0,
|
|
uint64_t b1,
|
|
uint64_t b2,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2;
|
|
int8_t carry0, carry1;
|
|
|
|
z2 = a2 + b2;
|
|
carry1 = ( z2 < a2 );
|
|
z1 = a1 + b1;
|
|
carry0 = ( z1 < a1 );
|
|
z0 = a0 + b0;
|
|
z1 += carry1;
|
|
z0 += ( z1 < carry1 );
|
|
z0 += carry0;
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
|
|
| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
|
|
| 2^128, so any borrow out (carry out) is lost. The result is broken into two
|
|
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
|
|
| `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
sub128(
|
|
uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
|
{
|
|
|
|
*z1Ptr = a1 - b1;
|
|
*z0Ptr = a0 - b0 - ( a1 < b1 );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
|
|
| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
|
|
| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
|
|
| result is broken into three 64-bit pieces which are stored at the locations
|
|
| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
sub192(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t a2,
|
|
uint64_t b0,
|
|
uint64_t b1,
|
|
uint64_t b2,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2;
|
|
int8_t borrow0, borrow1;
|
|
|
|
z2 = a2 - b2;
|
|
borrow1 = ( a2 < b2 );
|
|
z1 = a1 - b1;
|
|
borrow0 = ( a1 < b1 );
|
|
z0 = a0 - b0;
|
|
z0 -= ( z1 < borrow1 );
|
|
z1 -= borrow1;
|
|
z0 -= borrow0;
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
|
|
| into two 64-bit pieces which are stored at the locations pointed to by
|
|
| `z0Ptr' and `z1Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
|
{
|
|
uint32_t aHigh, aLow, bHigh, bLow;
|
|
uint64_t z0, zMiddleA, zMiddleB, z1;
|
|
|
|
aLow = a;
|
|
aHigh = a>>32;
|
|
bLow = b;
|
|
bHigh = b>>32;
|
|
z1 = ( (uint64_t) aLow ) * bLow;
|
|
zMiddleA = ( (uint64_t) aLow ) * bHigh;
|
|
zMiddleB = ( (uint64_t) aHigh ) * bLow;
|
|
z0 = ( (uint64_t) aHigh ) * bHigh;
|
|
zMiddleA += zMiddleB;
|
|
z0 += ( ( (uint64_t) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
|
|
zMiddleA <<= 32;
|
|
z1 += zMiddleA;
|
|
z0 += ( z1 < zMiddleA );
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
|
|
| `b' to obtain a 192-bit product. The product is broken into three 64-bit
|
|
| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
|
|
| `z2Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
mul128By64To192(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t b,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2, more1;
|
|
|
|
mul64To128( a1, b, &z1, &z2 );
|
|
mul64To128( a0, b, &z0, &more1 );
|
|
add128( z0, more1, 0, z1, &z0, &z1 );
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
|
|
| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
|
|
| product. The product is broken into four 64-bit pieces which are stored at
|
|
| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline void
|
|
mul128To256(
|
|
uint64_t a0,
|
|
uint64_t a1,
|
|
uint64_t b0,
|
|
uint64_t b1,
|
|
uint64_t *z0Ptr,
|
|
uint64_t *z1Ptr,
|
|
uint64_t *z2Ptr,
|
|
uint64_t *z3Ptr
|
|
)
|
|
{
|
|
uint64_t z0, z1, z2, z3;
|
|
uint64_t more1, more2;
|
|
|
|
mul64To128( a1, b1, &z2, &z3 );
|
|
mul64To128( a1, b0, &z1, &more2 );
|
|
add128( z1, more2, 0, z2, &z1, &z2 );
|
|
mul64To128( a0, b0, &z0, &more1 );
|
|
add128( z0, more1, 0, z1, &z0, &z1 );
|
|
mul64To128( a0, b1, &more1, &more2 );
|
|
add128( more1, more2, 0, z2, &more1, &z2 );
|
|
add128( z0, z1, 0, more1, &z0, &z1 );
|
|
*z3Ptr = z3;
|
|
*z2Ptr = z2;
|
|
*z1Ptr = z1;
|
|
*z0Ptr = z0;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns an approximation to the 64-bit integer quotient obtained by dividing
|
|
| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
|
|
| divisor `b' must be at least 2^63. If q is the exact quotient truncated
|
|
| toward zero, the approximation returned lies between q and q + 2 inclusive.
|
|
| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
|
|
| unsigned integer is returned.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b)
|
|
{
|
|
uint64_t b0, b1;
|
|
uint64_t rem0, rem1, term0, term1;
|
|
uint64_t z;
|
|
|
|
if ( b <= a0 ) return UINT64_C(0xFFFFFFFFFFFFFFFF);
|
|
b0 = b>>32;
|
|
z = ( b0<<32 <= a0 ) ? UINT64_C(0xFFFFFFFF00000000) : ( a0 / b0 )<<32;
|
|
mul64To128( b, z, &term0, &term1 );
|
|
sub128( a0, a1, term0, term1, &rem0, &rem1 );
|
|
while ( ( (int64_t) rem0 ) < 0 ) {
|
|
z -= UINT64_C(0x100000000);
|
|
b1 = b<<32;
|
|
add128( rem0, rem1, b0, b1, &rem0, &rem1 );
|
|
}
|
|
rem0 = ( rem0<<32 ) | ( rem1>>32 );
|
|
z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
|
|
return z;
|
|
|
|
}
|
|
|
|
/* From the GNU Multi Precision Library - longlong.h __udiv_qrnnd
|
|
* (https://gmplib.org/repo/gmp/file/tip/longlong.h)
|
|
*
|
|
* Licensed under the GPLv2/LGPLv3
|
|
*/
|
|
static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,
|
|
uint64_t n0, uint64_t d)
|
|
{
|
|
#if defined(__x86_64__)
|
|
uint64_t q;
|
|
asm("divq %4" : "=a"(q), "=d"(*r) : "0"(n0), "1"(n1), "rm"(d));
|
|
return q;
|
|
#elif defined(__s390x__) && !defined(__clang__)
|
|
/* Need to use a TImode type to get an even register pair for DLGR. */
|
|
unsigned __int128 n = (unsigned __int128)n1 << 64 | n0;
|
|
asm("dlgr %0, %1" : "+r"(n) : "r"(d));
|
|
*r = n >> 64;
|
|
return n;
|
|
#elif defined(_ARCH_PPC64) && defined(_ARCH_PWR7)
|
|
/* From Power ISA 2.06, programming note for divdeu. */
|
|
uint64_t q1, q2, Q, r1, r2, R;
|
|
asm("divdeu %0,%2,%4; divdu %1,%3,%4"
|
|
: "=&r"(q1), "=r"(q2)
|
|
: "r"(n1), "r"(n0), "r"(d));
|
|
r1 = -(q1 * d); /* low part of (n1<<64) - (q1 * d) */
|
|
r2 = n0 - (q2 * d);
|
|
Q = q1 + q2;
|
|
R = r1 + r2;
|
|
if (R >= d || R < r2) { /* overflow implies R > d */
|
|
Q += 1;
|
|
R -= d;
|
|
}
|
|
*r = R;
|
|
return Q;
|
|
#else
|
|
uint64_t d0, d1, q0, q1, r1, r0, m;
|
|
|
|
d0 = (uint32_t)d;
|
|
d1 = d >> 32;
|
|
|
|
r1 = n1 % d1;
|
|
q1 = n1 / d1;
|
|
m = q1 * d0;
|
|
r1 = (r1 << 32) | (n0 >> 32);
|
|
if (r1 < m) {
|
|
q1 -= 1;
|
|
r1 += d;
|
|
if (r1 >= d) {
|
|
if (r1 < m) {
|
|
q1 -= 1;
|
|
r1 += d;
|
|
}
|
|
}
|
|
}
|
|
r1 -= m;
|
|
|
|
r0 = r1 % d1;
|
|
q0 = r1 / d1;
|
|
m = q0 * d0;
|
|
r0 = (r0 << 32) | (uint32_t)n0;
|
|
if (r0 < m) {
|
|
q0 -= 1;
|
|
r0 += d;
|
|
if (r0 >= d) {
|
|
if (r0 < m) {
|
|
q0 -= 1;
|
|
r0 += d;
|
|
}
|
|
}
|
|
}
|
|
r0 -= m;
|
|
|
|
*r = r0;
|
|
return (q1 << 32) | q0;
|
|
#endif
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns an approximation to the square root of the 32-bit significand given
|
|
| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
|
|
| `aExp' (the least significant bit) is 1, the integer returned approximates
|
|
| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
|
|
| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
|
|
| case, the approximation returned lies strictly within +/-2 of the exact
|
|
| value.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline uint32_t estimateSqrt32(int aExp, uint32_t a)
|
|
{
|
|
static const uint16_t sqrtOddAdjustments[] = {
|
|
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
|
|
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
|
|
};
|
|
static const uint16_t sqrtEvenAdjustments[] = {
|
|
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
|
|
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
|
|
};
|
|
int8_t index;
|
|
uint32_t z;
|
|
|
|
index = ( a>>27 ) & 15;
|
|
if ( aExp & 1 ) {
|
|
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ (int)index ];
|
|
z = ( ( a / z )<<14 ) + ( z<<15 );
|
|
a >>= 1;
|
|
}
|
|
else {
|
|
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ (int)index ];
|
|
z = a / z + z;
|
|
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
|
|
if ( z <= a ) return (uint32_t) ( ( (int32_t) a )>>1 );
|
|
}
|
|
return ( (uint32_t) ( ( ( (uint64_t) a )<<31 ) / z ) ) + ( z>>1 );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
|
|
| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
|
| Otherwise, returns 0.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
|
{
|
|
|
|
return ( a0 == b0 ) && ( a1 == b1 );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
|
|
| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
|
| Otherwise, returns 0.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
|
{
|
|
|
|
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
|
|
| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
|
|
| returns 0.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
|
{
|
|
|
|
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
|
|
| not equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
|
| Otherwise, returns 0.
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
static inline flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
|
{
|
|
|
|
return ( a0 != b0 ) || ( a1 != b1 );
|
|
|
|
}
|
|
|
|
#endif
|