Skip to content

Commit 9e04723

Browse files
committed
Add test cases for Mul[s/d]f3vfp and Div[s/d]f3vfp
for ARM targets only
1 parent f42b9e0 commit 9e04723

File tree

5 files changed

+371
-0
lines changed

5 files changed

+371
-0
lines changed

build.rs

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,14 @@ mod tests {
130130
// float/mul.rs
131131
Mulsf3,
132132
Muldf3,
133+
Mulsf3vfp,
134+
Muldf3vfp,
133135

134136
// float/div.rs
135137
Divsf3,
136138
Divdf3,
139+
Divsf3vfp,
140+
Divdf3vfp,
137141

138142
// int/addsub.rs
139143
AddU128,
@@ -4203,6 +4207,171 @@ fn muldf3() {
42034207
}
42044208
}
42054209

4210+
#[derive(Eq, Hash, PartialEq)]
4211+
pub struct Mulsf3vfp {
4212+
a: u32, // f32
4213+
b: u32, // f32
4214+
c: u32, // f32
4215+
}
4216+
4217+
impl TestCase for Mulsf3vfp {
4218+
fn name() -> &'static str {
4219+
"mulsf3vfp"
4220+
}
4221+
4222+
fn generate<R>(rng: &mut R) -> Option<Self>
4223+
where
4224+
R: Rng,
4225+
Self: Sized,
4226+
{
4227+
let a = gen_large_f32(rng);
4228+
let b = gen_large_f32(rng);
4229+
let c = a * b;
4230+
// TODO accept NaNs. We don't do that right now because we can't check
4231+
// for NaN-ness on the thumb targets (due to missing intrinsics)
4232+
if a.is_nan() || b.is_nan() || c.is_nan() {
4233+
return None;
4234+
}
4235+
4236+
Some(
4237+
Mulsf3vfp {
4238+
a: to_u32(a),
4239+
b: to_u32(b),
4240+
c: to_u32(c),
4241+
},
4242+
)
4243+
}
4244+
4245+
fn to_string(&self, buffer: &mut String) {
4246+
writeln!(
4247+
buffer,
4248+
"(({a}, {b}), {c}),",
4249+
a = self.a,
4250+
b = self.b,
4251+
c = self.c
4252+
)
4253+
.unwrap();
4254+
}
4255+
4256+
fn prologue() -> &'static str {
4257+
r#"
4258+
#[cfg(all(target_arch = "arm",
4259+
not(any(target_env = "gnu", target_env = "musl")),
4260+
target_os = "linux",
4261+
test))]
4262+
use core::mem;
4263+
use compiler_builtins::float::mul::__mulsf3vfp;
4264+
4265+
fn mk_f32(x: u32) -> f32 {
4266+
unsafe { mem::transmute(x) }
4267+
}
4268+
4269+
fn to_u32(x: f32) -> u32 {
4270+
unsafe { mem::transmute(x) }
4271+
}
4272+
4273+
static TEST_CASES: &[((u32, u32), u32)] = &[
4274+
"#
4275+
}
4276+
4277+
fn epilogue() -> &'static str {
4278+
"
4279+
];
4280+
4281+
#[test]
4282+
fn mulsf3vfp() {
4283+
for &((a, b), c) in TEST_CASES {
4284+
let c_ = __mulsf3vfp(mk_f32(a), mk_f32(b));
4285+
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
4286+
}
4287+
}
4288+
"
4289+
}
4290+
}
4291+
4292+
#[derive(Eq, Hash, PartialEq)]
4293+
pub struct Muldf3vfp {
4294+
a: u64, // f64
4295+
b: u64, // f64
4296+
c: u64, // f64
4297+
}
4298+
4299+
impl TestCase for Muldf3vfp {
4300+
fn name() -> &'static str {
4301+
"muldf3vfp"
4302+
}
4303+
4304+
fn generate<R>(rng: &mut R) -> Option<Self>
4305+
where
4306+
R: Rng,
4307+
Self: Sized,
4308+
{
4309+
let a = gen_large_f64(rng);
4310+
let b = gen_large_f64(rng);
4311+
let c = a * b;
4312+
// TODO accept NaNs. We don't do that right now because we can't check
4313+
// for NaN-ness on the thumb targets (due to missing intrinsics)
4314+
if a.is_nan() || b.is_nan() || c.is_nan() {
4315+
return None;
4316+
}
4317+
4318+
Some(
4319+
Muldf3vfp {
4320+
a: to_u64(a),
4321+
b: to_u64(b),
4322+
c: to_u64(c),
4323+
},
4324+
)
4325+
}
4326+
4327+
fn to_string(&self, buffer: &mut String) {
4328+
writeln!(
4329+
buffer,
4330+
"(({a}, {b}), {c}),",
4331+
a = self.a,
4332+
b = self.b,
4333+
c = self.c
4334+
)
4335+
.unwrap();
4336+
}
4337+
4338+
fn prologue() -> &'static str {
4339+
r#"
4340+
#[cfg(all(target_arch = "arm",
4341+
not(any(target_env = "gnu", target_env = "musl")),
4342+
target_os = "linux",
4343+
test))]
4344+
use core::mem;
4345+
use compiler_builtins::float::mul::__muldf3vfp;
4346+
4347+
fn mk_f64(x: u64) -> f64 {
4348+
unsafe { mem::transmute(x) }
4349+
}
4350+
4351+
fn to_u64(x: f64) -> u64 {
4352+
unsafe { mem::transmute(x) }
4353+
}
4354+
4355+
static TEST_CASES: &[((u64, u64), u64)] = &[
4356+
"#
4357+
}
4358+
4359+
fn epilogue() -> &'static str {
4360+
"
4361+
];
4362+
4363+
#[test]
4364+
fn muldf3vfp() {
4365+
for &((a, b), c) in TEST_CASES {
4366+
let c_ = __muldf3vfp(mk_f64(a), mk_f64(b));
4367+
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
4368+
}
4369+
}
4370+
"
4371+
}
4372+
}
4373+
4374+
42064375
#[derive(Eq, Hash, PartialEq)]
42074376
pub struct Divsf3 {
42084377
a: u32, // f32
@@ -4384,6 +4553,176 @@ fn divdf3() {
43844553
}
43854554
}
43864555

4556+
#[derive(Eq, Hash, PartialEq)]
4557+
pub struct Divsf3vfp {
4558+
a: u32, // f32
4559+
b: u32, // f32
4560+
c: u32, // f32
4561+
}
4562+
4563+
impl TestCase for Divsf3vfp {
4564+
fn name() -> &'static str {
4565+
"divsf3vfp"
4566+
}
4567+
4568+
fn generate<R>(rng: &mut R) -> Option<Self>
4569+
where
4570+
R: Rng,
4571+
Self: Sized,
4572+
{
4573+
let a = gen_large_f32(rng);
4574+
let b = gen_large_f32(rng);
4575+
if b == 0.0 {
4576+
return None;
4577+
}
4578+
let c = a / b;
4579+
// TODO accept NaNs. We don't do that right now because we can't check
4580+
// for NaN-ness on the thumb targets (due to missing intrinsics)
4581+
if a.is_nan() || b.is_nan() || c.is_nan()|| c.abs() <= unsafe { mem::transmute(16777215u32) } {
4582+
return None;
4583+
}
4584+
4585+
Some(
4586+
Divsf3vfp {
4587+
a: to_u32(a),
4588+
b: to_u32(b),
4589+
c: to_u32(c),
4590+
},
4591+
)
4592+
}
4593+
4594+
fn to_string(&self, buffer: &mut String) {
4595+
writeln!(
4596+
buffer,
4597+
"(({a}, {b}), {c}),",
4598+
a = self.a,
4599+
b = self.b,
4600+
c = self.c
4601+
)
4602+
.unwrap();
4603+
}
4604+
4605+
fn prologue() -> &'static str {
4606+
r#"
4607+
#[cfg(all(target_arch = "arm",
4608+
not(any(target_env = "gnu", target_env = "musl")),
4609+
target_os = "linux",
4610+
test))]
4611+
use core::mem;
4612+
use compiler_builtins::float::div::__divsf3vfp;
4613+
4614+
fn mk_f32(x: u32) -> f32 {
4615+
unsafe { mem::transmute(x) }
4616+
}
4617+
4618+
fn to_u32(x: f32) -> u32 {
4619+
unsafe { mem::transmute(x) }
4620+
}
4621+
4622+
static TEST_CASES: &[((u32, u32), u32)] = &[
4623+
"#
4624+
}
4625+
4626+
fn epilogue() -> &'static str {
4627+
"
4628+
];
4629+
4630+
#[test]
4631+
fn divsf3vfp() {
4632+
for &((a, b), c) in TEST_CASES {
4633+
let c_ = __divsf3vfp(mk_f32(a), mk_f32(b));
4634+
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
4635+
}
4636+
}
4637+
"
4638+
}
4639+
}
4640+
4641+
#[derive(Eq, Hash, PartialEq)]
4642+
pub struct Divdf3vfp {
4643+
a: u64, // f64
4644+
b: u64, // f64
4645+
c: u64, // f64
4646+
}
4647+
4648+
impl TestCase for Divdf3vfp {
4649+
fn name() -> &'static str {
4650+
"divdf3vfp"
4651+
}
4652+
4653+
fn generate<R>(rng: &mut R) -> Option<Self>
4654+
where
4655+
R: Rng,
4656+
Self: Sized,
4657+
{
4658+
let a = gen_large_f64(rng);
4659+
let b = gen_large_f64(rng);
4660+
if b == 0.0 {
4661+
return None;
4662+
}
4663+
let c = a / b;
4664+
// TODO accept NaNs. We don't do that right now because we can't check
4665+
// for NaN-ness on the thumb targets (due to missing intrinsics)
4666+
if a.is_nan() || b.is_nan() || c.is_nan()
4667+
|| c.abs() <= unsafe { mem::transmute(4503599627370495u64) } {
4668+
return None;
4669+
}
4670+
4671+
Some(
4672+
Divdf3vfp {
4673+
a: to_u64(a),
4674+
b: to_u64(b),
4675+
c: to_u64(c),
4676+
},
4677+
)
4678+
}
4679+
4680+
fn to_string(&self, buffer: &mut String) {
4681+
writeln!(
4682+
buffer,
4683+
"(({a}, {b}), {c}),",
4684+
a = self.a,
4685+
b = self.b,
4686+
c = self.c
4687+
)
4688+
.unwrap();
4689+
}
4690+
4691+
fn prologue() -> &'static str {
4692+
r#"
4693+
#[cfg(all(target_arch = "arm",
4694+
not(any(target_env = "gnu", target_env = "musl")),
4695+
target_os = "linux",
4696+
test))]
4697+
use core::mem;
4698+
use compiler_builtins::float::div::__divdf3vfp;
4699+
4700+
fn mk_f64(x: u64) -> f64 {
4701+
unsafe { mem::transmute(x) }
4702+
}
4703+
4704+
fn to_u64(x: f64) -> u64 {
4705+
unsafe { mem::transmute(x) }
4706+
}
4707+
4708+
static TEST_CASES: &[((u64, u64), u64)] = &[
4709+
"#
4710+
}
4711+
4712+
fn epilogue() -> &'static str {
4713+
"
4714+
];
4715+
4716+
#[test]
4717+
fn divdf3vfp() {
4718+
for &((a, b), c) in TEST_CASES {
4719+
let c_ = __divdf3vfp(mk_f64(a), mk_f64(b));
4720+
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
4721+
}
4722+
}
4723+
"
4724+
}
4725+
}
43874726

43884727
#[derive(Eq, Hash, PartialEq)]
43894728
pub struct Udivdi3 {

tests/divdf3vfp.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
4+
target_os = "linux", test),
5+
no_std)]
6+
7+
#[cfg(target_arch = "arm")]
8+
include!(concat!(env!("OUT_DIR"), "/divdf3vfp.rs"));

tests/divsf3vfp.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
4+
target_os = "linux", test),
5+
no_std)]
6+
7+
#[cfg(target_arch = "arm")]
8+
include!(concat!(env!("OUT_DIR"), "/divsf3vfp.rs"));

tests/muldf3vfp.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
4+
target_os = "linux", test),
5+
no_std)]
6+
7+
#[cfg(target_arch = "arm")]
8+
include!(concat!(env!("OUT_DIR"), "/muldf3vfp.rs"));

tests/mulsf3vfp.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
4+
target_os = "linux", test),
5+
no_std)]
6+
7+
#[cfg(target_arch = "arm")]
8+
include!(concat!(env!("OUT_DIR"), "/mulsf3vfp.rs"));

0 commit comments

Comments
 (0)