aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/config/arc/ieee-754/truncdfsf2.S
blob: 87f40e4864ff929b4e122177fc8c4cb2b5ca612a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Copyright (C) 2006-2014 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)