Blame sysdeps/powerpc/powerpc64/fpu/s_llround.S

Packit Service 82fcde
/* llround function.  PowerPC64 version.
Packit Service 82fcde
   Copyright (C) 2004-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include <math_ldbl_opt.h>
Packit Service 82fcde
#include <libm-alias-double.h>
Packit Service 82fcde
Packit Service 82fcde
	.section	".toc","aw"
Packit Service 82fcde
.LC0:	/* 2^52 */
Packit Service 82fcde
	.tc FD_43300000_0[TC],0x4330000000000000
Packit Service 82fcde
.LC1:	/* 0.5 */
Packit Service 82fcde
	.tc FD_3fe00000_0[TC],0x3fe0000000000000
Packit Service 82fcde
	.section	".text"
Packit Service 82fcde
Packit Service 82fcde
/* long long [r3] llround (double x [fp1])
Packit Service 82fcde
   IEEE 1003.1 llround function.  IEEE specifies "round to the nearest
Packit Service 82fcde
   integer value, rounding halfway cases away from zero, regardless of
Packit Service 82fcde
   the current rounding mode."  However PowerPC Architecture defines
Packit Service 82fcde
   "round to Nearest" as "Choose the best approximation. In case of a
Packit Service 82fcde
   tie, choose the one that is even (least significant bit o).".
Packit Service 82fcde
   So we can't use the PowerPC "round to Nearest" mode. Instead we set
Packit Service 82fcde
   "round toward Zero" mode and round by adding +-0.5 before rounding
Packit Service 82fcde
   to the integer value.
Packit Service 82fcde
Packit Service 82fcde
   It is necessary to detect when x is (+-)0x1.fffffffffffffp-2
Packit Service 82fcde
   because adding +-0.5 in this case will cause an erroneous shift,
Packit Service 82fcde
   carry and round.  We simply return 0 if 0.5 > x > -0.5.  Likewise
Packit Service 82fcde
   if x is and odd number between +-(2^52 and 2^53-1) a shift and
Packit Service 82fcde
   carry will erroneously round if biased with +-0.5.  Therefore if x
Packit Service 82fcde
   is greater/less than +-2^52 we don't need to bias the number with
Packit Service 82fcde
   +-0.5.  */
Packit Service 82fcde
Packit Service 82fcde
ENTRY (__llround)
Packit Service 82fcde
	CALL_MCOUNT 0
Packit Service 82fcde
	lfd	fp9,.LC0@toc(2)	/* Load 2^52 into fpr9.  */
Packit Service 82fcde
	lfd	fp10,.LC1@toc(2)/* Load 0.5 into fpr10.  */
Packit Service 82fcde
	fabs	fp2,fp1		/* Get the absolute value of x.  */
Packit Service 82fcde
	fsub	fp12,fp10,fp10	/* Compute 0.0 into fp12.  */
Packit Service 82fcde
	fcmpu	cr6,fp2,fp10	/* if |x| < 0.5  */
Packit Service 82fcde
	fcmpu	cr7,fp2,fp9	/* if |x| >= 2^52  */
Packit Service 82fcde
	fcmpu	cr1,fp1,fp12	/* x is negative? x < 0.0  */
Packit Service 82fcde
	blt-	cr6,.Lretzero	/* 0.5 > x < -0.5 so just return 0.  */
Packit Service 82fcde
	bge-	cr7,.Lnobias	/* 2^52 > x < -2^52 just convert with no bias.  */
Packit Service 82fcde
	/* Test whether an integer to avoid spurious "inexact".  */
Packit Service 82fcde
	fadd	fp3,fp2,fp9
Packit Service 82fcde
	fsub	fp3,fp3,fp9
Packit Service 82fcde
	fcmpu	cr5,fp2,fp3
Packit Service 82fcde
	beq	cr5,.Lnobias
Packit Service 82fcde
	fadd	fp3,fp2,fp10	/* |x|+=0.5 bias to prepare to round.  */
Packit Service 82fcde
	bge	cr1,.Lconvert	/* x is positive so don't negate x.  */
Packit Service 82fcde
	fnabs	fp3,fp3		/* -(|x|+=0.5)  */
Packit Service 82fcde
.Lconvert:
Packit Service 82fcde
	fctidz	fp4,fp3		/* Convert to Integer double word round toward 0.  */
Packit Service 82fcde
	stfd	fp4,-16(r1)
Packit Service 82fcde
	nop
Packit Service 82fcde
	nop
Packit Service 82fcde
	nop
Packit Service 82fcde
	ld	r3,-16(r1)	/* Load return as integer.  */
Packit Service 82fcde
.Lout:
Packit Service 82fcde
	blr
Packit Service 82fcde
.Lretzero:			/* 0.5 > x > -0.5  */
Packit Service 82fcde
	li	r3,0		/* return 0.  */
Packit Service 82fcde
	b	.Lout
Packit Service 82fcde
.Lnobias:
Packit Service 82fcde
	fmr	fp3,fp1
Packit Service 82fcde
	b	.Lconvert
Packit Service 82fcde
	END (__llround)
Packit Service 82fcde
Packit Service 82fcde
strong_alias (__llround, __lround)
Packit Service 82fcde
libm_alias_double (__llround, llround)
Packit Service 82fcde
libm_alias_double (__lround, lround)