gcc/libgcc/config/arc/ieee-754/truncdfsf2.S
2021-01-04 10:26:59 +01:00

135 lines
3.5 KiB
ArmAsm

/* Copyright (C) 2006-2021 Free Software Foundation, Inc.
Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
on behalf of Synopsys Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "arc-ieee-754.h"
#if 0 /* DEBUG */
FUNC(__truncdfsf2)
.global __truncdfsf2
.balign 4
__truncdfsf2:
push_s blink
push_s r0
bl.d __truncdfsf2_c
push_s r1
mov_s r2,r0
pop_s r1
ld r0,[sp]
bl.d __truncdfsf2_asm
st r2,[sp]
pop_s r1
pop_s blink
cmp r0,r1
jeq_s [blink]
and r12,r0,r1
bic.f 0,0x7f800000,r12
bne 0f
bmsk.f 0,r0,22
bmsk.ne.f r1,r1,22
jne_s [blink] ; both NaN -> OK
0: bl abort
ENDFUNC(__truncdfsf2)
#define __truncdfsf2 __truncdfsf2_asm
#endif /* DEBUG */
.global __truncdfsf2
.balign 4
FUNC(__truncdfsf2)
__truncdfsf2:
lsr r2,DBL0H,20
asl_s DBL0H,DBL0H,12
sub r12,r2,0x380
bclr.f r3,r12,11
brhs r3,0xff,.Lill_exp
beq_l .Ldenorm0
asl_s r12,r12,23
tst DBL0L, \
0x2fffffff /* Check if msb guard bit wants rounding up. */
lsr_s DBL0L,DBL0L,28
lsr_s DBL0H,DBL0H,8
add.ne DBL0L,DBL0L,1
add_s DBL0H,DBL0H,DBL0L
lsr_s DBL0H,DBL0H
btst_s r2,11
add_s r0,DBL0H,r12
j_s.d [blink]
bxor.ne r0,r0,31
.balign 4
.Lill_exp:
bbit1 r2,10,.Linf_nan
bmsk_s r12,r12,9
rsub.f r12,r12,8+0x400-32 ; Go from 9 to 1 guard bit in MSW. */
bhs_s .Lzero
lsr r3,DBL0L,21
rrc DBL0H,DBL0H ; insert leading 1
asl.f 0,DBL0L,8 ; check lower 24 guard bits
add_s r3,DBL0H,r3
add.pnz r3,r3,1 ; assemble fraction with compressed guard bits.
lsr r0,r3,r12
neg_s r12,r12
btst_s r0,1
asl.eq.f r3,r3,r12
add.ne r0,r0,1
btst_s r2,11
lsr_s r0,r0
j_s.d [blink]
bxor.ne r0,r0,31
.Lzero:
lsr_s r2,r2,11
j_s.d [blink]
asl r0,r2,31
.Ldenorm0:
asl_s r12,r12,20
tst DBL0L, \
0x5fffffff /* Check if msb guard bit wants rounding up. */
lsr_s DBL0L,DBL0L,29
lsr_s DBL0H,DBL0H,9
add.ne DBL0L,DBL0L,1
bset_s DBL0H,DBL0H,23
add_s DBL0H,DBL0H,DBL0L
lsr_s DBL0H,DBL0H
j_s.d [blink]
add_l r0,DBL0H,r12
/* We would generally say that NaNs must have a non-zero high fraction part,
but to allow hardware double precision floating point to interoperate
with single precision software floating point, we make an exception here.
The cost is to replace a tst_s DBL0H with an or.f DBL0L,DBL0L,DBL0H .
As we start out unaligned, and there is an odd number of other short insns,
we have a choice of letting this cost us a misalign penalty or
4 more bytes (if we align the code). We choose the former here because
infinity / NaN is not expected to be prevalent in time-critical code. */
.Linf_nan:
or.f DBL0L,DBL0L,DBL0H
mov_s r0,1
add.ne r2,r2,1
tst r2,0x7ff
asl.ne r0,r0,23
btst_s r12,11
neg r0,r0
j_s.d [blink]
bxor.eq r0,r0,31
ENDFUNC(__truncdfsf2)