/* Copyright (C) 2006-2021 Free Software Foundation, Inc. Contributor: Joern Rennecke 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 . */ #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)