-
Notifications
You must be signed in to change notification settings - Fork 140
/
Copy pathdint.S
144 lines (127 loc) · 2.91 KB
/
dint.S
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
135
136
137
138
139
140
141
142
143
144
/*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
*/
#if 0
#if defined(_WIN64)
typedef long long I64;
typedef unsigned long long UI64;
#else
typedef long I64;
typedef unsigned long UI64;
#endif
typedef union {
double f;
UI64 i;
} FPI;
#define EXPBIAS 1023
#define MANTBITS 52
#define GET_EXP(u) (I64)(((u) & 0x7ff0000000000000) >> MANTBITS)
double
__mth_i_dint (double xx)
{
I64 xexp;
UI64 ux, mask;
double x;
FPI fpi;
x = xx;
fpi.f = x;
ux = fpi.i;
xexp = GET_EXP(ux) - EXPBIAS;
if (xexp < 0 ) {
/* |x| < 0 => zero with the original sign */
fpi.i = ( ux & 0x8000000000000000 );
}
else if (xexp < MANTBITS) {
/* 1 <= |x| < 2^53:
* just mask out the trailing bits of the mantiassa beyond the
* range of the exponent; mask out the exponent field as well.
*/
mask = ((UI64)1 << ( MANTBITS - xexp )) - 1;
fpi.i = ux & ~mask;
}
/* else illegal input, nan, inf, overflow, ...; just return it */
return fpi.f;
}
#endif
#include "directives.h"
/* Use is_<PROC-FEATURE>() functions from libpgc */
#include "x86id.h"
.text
ALN_FUNC
.globl ENT(__mth_i_dint)
ENT(__mth_i_dint):
/*
* Assembly based on Clang's translation of:
* xexp = GET_EXP(ux) - EXPBIAS;
* mask = fpi.i;
* mask = xexp < MANTBITS ? (-1ULL) << (MANTBITS - xexp) : mask;
* mask = xexp < 0 ? 0x8000000000000000 : mask;
* fpi.i &= mask;
*
* Volatile registers common to both System V and Windows ABI:
* %rax, %rcx, %rdx, %r8, %r9
*/
#if defined(TARGET_WIN_X8664)
movl ENT(X86IDFN(hw_features))(%rip), %eax
#else
movq ENT(X86IDFN(hw_features))@GOTPCREL(%rip), %rax
movl (%rax), %eax
#endif
1:
testl $HW_AVX, %eax
jz 2f // Maybe SSE4.1?
/*
* AVX version.
*/
vroundsd $3, %xmm0, %xmm0, %xmm0
ret
/*
* SSE4.1 version.
*/
2:
testl $HW_SSE4, %eax
jz 3f // Maybe prior to SSE4.1
roundsd $3, %xmm0, %xmm0
ret
/*
* SSE version.
* Entry: (%eax) = X86IDFN(hw_features)
* (%xmm0) = xx (argument)
*/
3:
testl $HW_SSE, %eax
jz 4f // Possibly X86IDFN(hw_features) undefined
movq %xmm0, %rdx
movq %rdx, %rax
shrq $52, %rdx
andl $2047, %edx
movl $1075, %ecx
subl %edx, %ecx
movq $-1, %r8
shlq %cl, %r8
cmpq $1075, %rdx
cmovaeq %rax, %r8
cmpq $1023, %rdx
movabsq $-9223372036854775808, %rcx
cmovaeq %r8, %rcx
andq %rax, %rcx
movq %rcx, %xmm0
retq
/*
* X86IDFN(init_hw_features) is most likely uninitialized.
* (%eax) = current value of X86IDFN(init_hw_features).
*/
4:
subq $8, %rsp
movsd %xmm0, (%rsp) // Save %xmm0 - do not use vmovsd
movl %eax, I1W // Input to X86IDFN(init_hw_feature)()
CALL (ENT(X86IDFN(init_hw_features)))
// (%eax) = hw_features
movsd (%rsp), %xmm0 // restore %xmm0 - do not use vmovsd
addq $8, %rsp
jmp 1b
ELF_FUNC(__mth_i_dint)
ELF_SIZE(__mth_i_dint)