1 #![allow(unreachable_code)]
2 
3 use float::Float;
4 use int::Int;
5 
6 #[derive(Clone, Copy)]
7 enum Result {
8     Less,
9     Equal,
10     Greater,
11     Unordered,
12 }
13 
14 impl Result {
to_le_abi(self) -> i3215     fn to_le_abi(self) -> i32 {
16         match self {
17             Result::Less => -1,
18             Result::Equal => 0,
19             Result::Greater => 1,
20             Result::Unordered => 1,
21         }
22     }
23 
to_ge_abi(self) -> i3224     fn to_ge_abi(self) -> i32 {
25         match self {
26             Result::Less => -1,
27             Result::Equal => 0,
28             Result::Greater => 1,
29             Result::Unordered => -1,
30         }
31     }
32 }
33 
cmp<F: Float>(a: F, b: F) -> Result34 fn cmp<F: Float>(a: F, b: F) -> Result {
35     let one = F::Int::ONE;
36     let zero = F::Int::ZERO;
37     let szero = F::SignedInt::ZERO;
38 
39     let sign_bit = F::SIGN_MASK as F::Int;
40     let abs_mask = sign_bit - one;
41     let exponent_mask = F::EXPONENT_MASK;
42     let inf_rep = exponent_mask;
43 
44     let a_rep = a.repr();
45     let b_rep = b.repr();
46     let a_abs = a_rep & abs_mask;
47     let b_abs = b_rep & abs_mask;
48 
49     // If either a or b is NaN, they are unordered.
50     if a_abs > inf_rep || b_abs > inf_rep {
51         return Result::Unordered;
52     }
53 
54     // If a and b are both zeros, they are equal.
55     if a_abs | b_abs == zero {
56         return Result::Equal;
57     }
58 
59     let a_srep = a.signed_repr();
60     let b_srep = b.signed_repr();
61 
62     // If at least one of a and b is positive, we get the same result comparing
63     // a and b as signed integers as we would with a fp_ting-point compare.
64     if a_srep & b_srep >= szero {
65         if a_srep < b_srep {
66             Result::Less
67         } else if a_srep == b_srep {
68             Result::Equal
69         } else {
70             Result::Greater
71         }
72     // Otherwise, both are negative, so we need to flip the sense of the
73     // comparison to get the correct result.  (This assumes a twos- or ones-
74     // complement integer representation; if integers are represented in a
75     // sign-magnitude representation, then this flip is incorrect).
76     } else if a_srep > b_srep {
77         Result::Less
78     } else if a_srep == b_srep {
79         Result::Equal
80     } else {
81         Result::Greater
82     }
83 }
84 
unord<F: Float>(a: F, b: F) -> bool85 fn unord<F: Float>(a: F, b: F) -> bool {
86     let one = F::Int::ONE;
87 
88     let sign_bit = F::SIGN_MASK as F::Int;
89     let abs_mask = sign_bit - one;
90     let exponent_mask = F::EXPONENT_MASK;
91     let inf_rep = exponent_mask;
92 
93     let a_rep = a.repr();
94     let b_rep = b.repr();
95     let a_abs = a_rep & abs_mask;
96     let b_abs = b_rep & abs_mask;
97 
98     a_abs > inf_rep || b_abs > inf_rep
99 }
100 
101 intrinsics! {
102     pub extern "C" fn __lesf2(a: f32, b: f32) -> i32 {
103         cmp(a, b).to_le_abi()
104     }
105 
106     pub extern "C" fn __gesf2(a: f32, b: f32) -> i32 {
107         cmp(a, b).to_ge_abi()
108     }
109 
110     #[arm_aeabi_alias = __aeabi_fcmpun]
111     pub extern "C" fn __unordsf2(a: f32, b: f32) -> i32 {
112         unord(a, b) as i32
113     }
114 
115     pub extern "C" fn __eqsf2(a: f32, b: f32) -> i32 {
116         cmp(a, b).to_le_abi()
117     }
118 
119     pub extern "C" fn __ltsf2(a: f32, b: f32) -> i32 {
120         cmp(a, b).to_le_abi()
121     }
122 
123     pub extern "C" fn __nesf2(a: f32, b: f32) -> i32 {
124         cmp(a, b).to_le_abi()
125     }
126 
127     pub extern "C" fn __gtsf2(a: f32, b: f32) -> i32 {
128         cmp(a, b).to_ge_abi()
129     }
130 
131     pub extern "C" fn __ledf2(a: f64, b: f64) -> i32 {
132         cmp(a, b).to_le_abi()
133     }
134 
135     pub extern "C" fn __gedf2(a: f64, b: f64) -> i32 {
136         cmp(a, b).to_ge_abi()
137     }
138 
139     #[arm_aeabi_alias = __aeabi_dcmpun]
140     pub extern "C" fn __unorddf2(a: f64, b: f64) -> i32 {
141         unord(a, b) as i32
142     }
143 
144     pub extern "C" fn __eqdf2(a: f64, b: f64) -> i32 {
145         cmp(a, b).to_le_abi()
146     }
147 
148     pub extern "C" fn __ltdf2(a: f64, b: f64) -> i32 {
149         cmp(a, b).to_le_abi()
150     }
151 
152     pub extern "C" fn __nedf2(a: f64, b: f64) -> i32 {
153         cmp(a, b).to_le_abi()
154     }
155 
156     pub extern "C" fn __gtdf2(a: f64, b: f64) -> i32 {
157         cmp(a, b).to_ge_abi()
158     }
159 }
160 
161 #[cfg(target_arch = "arm")]
162 intrinsics! {
163     pub extern "aapcs" fn __aeabi_fcmple(a: f32, b: f32) -> i32 {
164         (__lesf2(a, b) <= 0) as i32
165     }
166 
167     pub extern "aapcs" fn __aeabi_fcmpge(a: f32, b: f32) -> i32 {
168         (__gesf2(a, b) >= 0) as i32
169     }
170 
171     pub extern "aapcs" fn __aeabi_fcmpeq(a: f32, b: f32) -> i32 {
172         (__eqsf2(a, b) == 0) as i32
173     }
174 
175     pub extern "aapcs" fn __aeabi_fcmplt(a: f32, b: f32) -> i32 {
176         (__ltsf2(a, b) < 0) as i32
177     }
178 
179     pub extern "aapcs" fn __aeabi_fcmpgt(a: f32, b: f32) -> i32 {
180         (__gtsf2(a, b) > 0) as i32
181     }
182 
183     pub extern "aapcs" fn __aeabi_dcmple(a: f64, b: f64) -> i32 {
184         (__ledf2(a, b) <= 0) as i32
185     }
186 
187     pub extern "aapcs" fn __aeabi_dcmpge(a: f64, b: f64) -> i32 {
188         (__gedf2(a, b) >= 0) as i32
189     }
190 
191     pub extern "aapcs" fn __aeabi_dcmpeq(a: f64, b: f64) -> i32 {
192         (__eqdf2(a, b) == 0) as i32
193     }
194 
195     pub extern "aapcs" fn __aeabi_dcmplt(a: f64, b: f64) -> i32 {
196         (__ltdf2(a, b) < 0) as i32
197     }
198 
199     pub extern "aapcs" fn __aeabi_dcmpgt(a: f64, b: f64) -> i32 {
200         (__gtdf2(a, b) > 0) as i32
201     }
202 
203     // On hard-float targets LLVM will use native instructions
204     // for all VFP intrinsics below
205 
206     pub extern "C" fn __gesf2vfp(a: f32, b: f32) -> i32 {
207         (a >= b) as i32
208     }
209 
210     pub extern "C" fn __gedf2vfp(a: f64, b: f64) -> i32 {
211         (a >= b) as i32
212     }
213 
214     pub extern "C" fn __gtsf2vfp(a: f32, b: f32) -> i32 {
215         (a > b) as i32
216     }
217 
218     pub extern "C" fn __gtdf2vfp(a: f64, b: f64) -> i32 {
219         (a > b) as i32
220     }
221 
222     pub extern "C" fn __ltsf2vfp(a: f32, b: f32) -> i32 {
223         (a < b) as i32
224     }
225 
226     pub extern "C" fn __ltdf2vfp(a: f64, b: f64) -> i32 {
227         (a < b) as i32
228     }
229 
230     pub extern "C" fn __lesf2vfp(a: f32, b: f32) -> i32 {
231         (a <= b) as i32
232     }
233 
234     pub extern "C" fn __ledf2vfp(a: f64, b: f64) -> i32 {
235         (a <= b) as i32
236     }
237 
238     pub extern "C" fn __nesf2vfp(a: f32, b: f32) -> i32 {
239         (a != b) as i32
240     }
241 
242     pub extern "C" fn __nedf2vfp(a: f64, b: f64) -> i32 {
243         (a != b) as i32
244     }
245 
246     pub extern "C" fn __eqsf2vfp(a: f32, b: f32) -> i32 {
247         (a == b) as i32
248     }
249 
250     pub extern "C" fn __eqdf2vfp(a: f64, b: f64) -> i32 {
251         (a == b) as i32
252     }
253 }
254