Skip to content

Commit 6622c49

Browse files
committed
Implement powi_f2
1 parent 954e3b7 commit 6622c49

File tree

6 files changed

+91
-28
lines changed

6 files changed

+91
-28
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ porting that particular intrinsic.
159159
- [x] mulodi4.c
160160
- [x] mulosi4.c
161161
- [ ] mulsf3.c
162-
- [ ] powidf2.c
163-
- [ ] powisf2.c
162+
- [x] powidf2.c
163+
- [x] powisf2.c
164164
- [ ] subdf3.c
165165
- [ ] subsf3.c
166166
- [ ] truncdfhf2.c

compiler-rt/compiler-rt-cdylib/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ fn main() {
5858
"udivmodsi4.c",
5959
"adddf3.c",
6060
"addsf3.c",
61+
"powidf2.c",
62+
"powisf2.c",
6163
]);
6264

6365
for src in sources.files.iter() {

compiler-rt/compiler-rt-cdylib/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ extern {
2222
fn __umodsi3();
2323
fn __addsf3();
2424
fn __adddf3();
25+
fn __powisf2();
26+
fn __powidf2();
2527
}
2628

2729
macro_rules! declare {
@@ -53,6 +55,8 @@ declare!(___umoddi3, __umoddi3);
5355
declare!(___umodsi3, __umodsi3);
5456
declare!(___addsf3, __addsf3);
5557
declare!(___adddf3, __adddf3);
58+
declare!(___powisf2, __powisf2);
59+
declare!(___powidf2, __powidf2);
5660

5761
#[lang = "eh_personality"]
5862
fn eh_personality() {}

src/float/add.rs

+1-26
Original file line numberDiff line numberDiff line change
@@ -186,35 +186,10 @@ add!(__adddf3: f64);
186186
#[cfg(test)]
187187
mod tests {
188188
use core::{f32, f64};
189-
use core::fmt;
190189

191-
use float::Float;
190+
use float::{Float, FRepr};
192191
use qc::{U32, U64};
193192

194-
// TODO: Move this to F32/F64 in qc.rs
195-
#[derive(Copy, Clone)]
196-
struct FRepr<F>(F);
197-
198-
impl<F: Float> PartialEq for FRepr<F> {
199-
fn eq(&self, other: &FRepr<F>) -> bool {
200-
// NOTE(cfg) for some reason, on hard float targets, our implementation doesn't
201-
// match the output of its gcc_s counterpart. Until we investigate further, we'll
202-
// just avoid testing against gcc_s on those targets. Do note that our
203-
// implementation matches the output of the FPU instruction on *hard* float targets
204-
// and matches its gcc_s counterpart on *soft* float targets.
205-
if cfg!(gnueabihf) {
206-
return true
207-
}
208-
self.0.eq_repr(other.0)
209-
}
210-
}
211-
212-
impl<F: fmt::Debug> fmt::Debug for FRepr<F> {
213-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214-
self.0.fmt(f)
215-
}
216-
}
217-
218193
// TODO: Add F32/F64 to qc so that they print the right values (at the very least)
219194
check! {
220195
fn __addsf3(f: extern fn(f32, f32) -> f32,

src/float/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use core::mem;
2+
use core::fmt;
23

34
pub mod add;
5+
pub mod pow;
46

57
/// Trait for some basic operations on floats
68
pub trait Float: Sized + Copy {
@@ -85,3 +87,30 @@ impl Float for f64 {
8587
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
8688
}
8789
}
90+
91+
// TODO: Move this to F32/F64 in qc.rs
92+
#[cfg(test)]
93+
#[derive(Copy, Clone)]
94+
pub struct FRepr<F>(F);
95+
96+
#[cfg(test)]
97+
impl<F: Float> PartialEq for FRepr<F> {
98+
fn eq(&self, other: &FRepr<F>) -> bool {
99+
// NOTE(cfg) for some reason, on hard float targets, our implementation doesn't
100+
// match the output of its gcc_s counterpart. Until we investigate further, we'll
101+
// just avoid testing against gcc_s on those targets. Do note that our
102+
// implementation matches the output of the FPU instruction on *hard* float targets
103+
// and matches its gcc_s counterpart on *soft* float targets.
104+
if cfg!(gnueabihf) {
105+
return true
106+
}
107+
self.0.eq_repr(other.0)
108+
}
109+
}
110+
111+
#[cfg(test)]
112+
impl<F: fmt::Debug> fmt::Debug for FRepr<F> {
113+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114+
self.0.fmt(f)
115+
}
116+
}

src/float/pow.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
macro_rules! pow {
3+
($intrinsic:ident: $fty:ty, $ity:ty) => {
4+
/// Returns `a` raised to the power `b`
5+
#[cfg_attr(not(test), no_mangle)]
6+
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
7+
let (mut a, mut b) = (a, b);
8+
let recip = b < 0;
9+
let mut r: $fty = 1.0;
10+
loop {
11+
if (b & 1) != 0 {
12+
r *= a;
13+
}
14+
b /= 2;
15+
if b == 0 {
16+
break;
17+
}
18+
a *= a;
19+
}
20+
21+
if recip {
22+
1.0 / r
23+
} else {
24+
r
25+
}
26+
}
27+
}
28+
}
29+
30+
pow!(__powisf2: f32, i32);
31+
pow!(__powidf2: f64, i32);
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use float::{Float, FRepr};
36+
use qc::{I32, U32, U64};
37+
38+
check! {
39+
fn __powisf2(f: extern fn(f32, i32) -> f32,
40+
a: U32,
41+
b: I32) -> Option<FRepr<f32> > {
42+
let (a, b) = (f32::from_repr(a.0), b.0);
43+
Some(FRepr(f(a, b)))
44+
}
45+
46+
fn __powidf2(f: extern fn(f64, i32) -> f64,
47+
a: U64,
48+
b: I32) -> Option<FRepr<f64> > {
49+
let (a, b) = (f64::from_repr(a.0), b.0);
50+
Some(FRepr(f(a, b)))
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)