| /* 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) |